#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "gbem_util.h"


void gbem_lap_fld_eval(int nip,double **ipts,double *fldvl)
{

/* ===purpose=== */

/**********************************************************************************************************************************/
/*********************************************  GALERKIN BEM for 3D LAPLACE EQUATION  *********************************************/
/************************************************  PIECEWISE LINEAR APPROXIMATION  ************************************************/
/***************************************  3-NODED TRIANGULAR ELEMENT: ANALYTIC INTEGRATION  ***************************************/
/********************************  Exact integration with Linear distribution on a flat triangle  *********************************/
/*********************************  Given an array of field points ipts[i][0:2], i=0,1,...,nip-1  *********************************/
/**********  Determine the potential at all field points ipts[i][0:2] due to boundary distribution of potential and flux  *********/
/**********************************************************************************************************************************/

/* Developer: Sylvain Nintcheu Fata */
/* Version:   V.1.1                 */
/* Released:  Jun 14, 2012          */

 
/* Typical triangular element with vertices {y1,y2,y3}

*           y3
*	    *
*	   / \
*	  /   \
*	 /     \
*       /       \
*      /	 \
*     /		  \
*    *-------------*
*  y1               y2

* Oriented edge L1 = [y1,y2] <== Edge1
* Oriented edge L2 = [y2,y3] <== Edge2
* Oriented edge L3 = [y3,y1] <== Edge3
*/

 
/******************************************************/
/* Parameter list:                                    */
/******************************************************/
/*
 * nip == (input) Number of interior points
 * ipts[nip][3] == (input): ipts[i][0:2] == Cartesian coordinates of the i-th interior (or field) point
 * fldvl[nip] == (output): fldvl[i] == Potential at the i-th interior point
 */

/* Global variables */
   extern const int mx_nd_elt; /* mx_nd_elt == Maximum number of nodes per element */
   extern int nbnd,nbelt;      /* nbnd == Total number of boundary nodes, nbelt == Total number of boundary elements */
   extern int **belt;          /* belt[i][0:2] == Global indices of boundary nodes on the i-th element */
   extern double **bnd;        /* bnd[i][0:2] = Cartesian coordinates of the i-th boundary node */
   extern double gm_eps,f_eps; /* gm_eps == Tolerance on the geometry, f_eps == Tolerance on the argument of a function */
   extern double pi,fac;       /* pi = 3.1415926535897932, fac == Factor of the Green's function: fac = 1/(4*pi) */
   extern double **LocCBasisElt; /* LocCBasisElt[k][0:8] == Local Companion Basis associated with the k-th boundary element */
   extern double **xvElt,*zvElt; /* xvElt[k][0] == Base of the k-th boundary element */
				 /* xvElt[k][1] == Geometric parameter associated with the k-th boundary element */
				 /* zvElt[k] == Height of the k-th boundary element */
   extern double **thetaElt;     /* thetaElt[k][i] == Angle at the i-th vertex of the k-th boundary element */
   extern double *phi, *flx;     /* phi == Vector containing boundary potentials, flx == Vector containing boundary fluxes */

/* Local variables */
   int i,ii,k,kk,j,th_id,elQ; /* elQ == Global index of the boundary element Q */
   int qq[mx_nd_elt];
   double e1[3],e2[3],e3[3]; /* Orthonormal local basis associated with element Q */
   double aQ,bQ,cQ; /* Geometric parameters of element Q: bQ = base, aQ = height,
 		       cQ = relative position of the 3rd node of element Q in the local basis {e1,e2,e3} */
   double r1[3],xi,zt,eth,et,ets,q[3],qs[3],d[3],rho[3],rhowv[3],chi[3],dchi[3],gamma[3],gam;
   double theta[3],alpha2,alpha3,Rh[3],Rhs[3],ch11,ch12,ch22,ch23,ch31,ch33;
   double kQ2,kQ3; /* kQ2 == Slope of Edge2 of element Q, kQ3 == Slope of Edge3 of element Q */
   double ah[9],bh[9]; /* ah and bh are viewed as Column-major ordered 3 by 3 matrices, i.e. ah[3][3], bh[3][3] */
   double vecA[3],vecB[3],sncf[2],cscf[2],qetx2[3],etchi[3],qrhowv[3];
   double p11,p12,p22,p23,p33,p31,x3,z3,rh1s,rh2s,rh3s,p11s,p12s,p33s,p11rh1,p31rh1,omega;
   double cr11,cr12,zn1,zd1,cr22,cr23,zn2,zd2,cr31,cr33,zn3,zd3,p12rh2,p22rh2,p23rh3,p33rh3,theta0,ThetGam;
   double shc[mx_nd_elt],int_p[mx_nd_elt],int_f[mx_nd_elt];
   double *int_G; /* int_G == Flux influence vector necessary to evaluate the potential at field points */
   double *int_H; /* int_H == Potential influence vector necessary to evaluate the potential at field points */
/*** Note: Below, the Projection of the collocation point ipts[i][0:2] means the Projection of the collocation point ipts[i][0:2] on
 *** Note: the plane of element Q in the direction e3. e3 is the unit normal to element Q */

/* pt_tria_tst, gammai, asym_chi are external functions (see gbem_util.c) */



   for (k=0; k<nip; k++) fldvl[k] = 0.0; /* Initialize the potential fldvl[k] at all interior points */

   if ( (int_G = (double *)calloc(nbnd,sizeof(double))) == NULL ) /* If int_G is not successfully allocated */
   {printf("gbem_lap_fld_eval: Allocate array \"int_G\" failed\n"); exit(1);}

   if ( (int_H = (double *)calloc(nbnd,sizeof(double))) == NULL ) /* If int_H is not successfully allocated */
   {printf("gbem_lap_fld_eval: Allocate array \"int_H\" failed\n"); exit(1);}

    for (j=0; j<nip; j++) /* Loop over all interior points */
    {
       for (k=0; k<nbnd; k++) /* Loop over all boundary nodes */
          {int_G[k] = 0.0; int_H[k] = 0.0;}

       for (elQ=0; elQ<nbelt; elQ++) /* Loop over all boundary elements */
       {
          for (k=0; k<mx_nd_elt; k++) /* Loop over the nodes of element Q */
	     qq[k] = belt[elQ][k]; /* qq[k] == Global index of the k-th node of the boundary element Q */
          
          e1[0] = LocCBasisElt[elQ][0]; e1[1] = LocCBasisElt[elQ][1]; e1[2] = LocCBasisElt[elQ][2];
          e2[0] = LocCBasisElt[elQ][3]; e2[1] = LocCBasisElt[elQ][4]; e2[2] = LocCBasisElt[elQ][5];
          e3[0] = LocCBasisElt[elQ][6]; e3[1] = LocCBasisElt[elQ][7]; e3[2] = LocCBasisElt[elQ][8];

          theta[0] = thetaElt[elQ][0]; theta[1] = thetaElt[elQ][1]; theta[2] = thetaElt[elQ][2];

           alpha2 = pi-theta[1]; alpha3 = pi+theta[0]; /* alpha1 = 0.0 */

           aQ = zvElt[elQ];    /* aQ>0.0 always */
           bQ = xvElt[elQ][0]; /* bQ>0.0 always */
           cQ = xvElt[elQ][1];

           kQ2 = (cQ-bQ)/aQ; kQ3 = cQ/aQ; /* kQ2 == Slope of Side 2 of element Q, kQ3 == Slope of Side 3 of element Q */

	   cscf[0] = cos(alpha2); sncf[0] = sin(alpha2); /* cscf(2) ; sncf(2) */
	   cscf[1] = cos(alpha3); sncf[1] = sin(alpha3); /* cscf(3) ; sncf(3) */
 
           vecA[0] = -1.0/bQ; vecA[1] =  1.0/bQ; vecA[2] = 0.0;
           vecB[0] =  kQ2/bQ; vecB[1] = -kQ3/bQ; vecB[2] = 1.0/aQ;
 
           ah[0] = vecA[0]; ah[1] = (kQ2*sncf[0] - cscf[0])/bQ; ah[2] = (kQ2*sncf[1] - cscf[1])/bQ; /* ah(1,1) ; ah(2,1) ; ah(3,1) */
           ah[3] = vecA[1]; ah[4] = (cscf[0] - kQ3*sncf[0])/bQ; ah[5] = (cscf[1] - kQ3*sncf[1])/bQ; /* ah(1,2) ; ah(2,2) ; ah(3,2) */
           ah[6] = 0.0;     ah[7] = sncf[0]/aQ;                 ah[8] = sncf[1]/aQ; /* ah(1,3) ; ah(2,3) ; ah(3,3) */
     
           bh[0] = -vecB[0]; bh[1] = -(sncf[0] + kQ2*cscf[0])/bQ; bh[2] = -(sncf[1] + kQ2*cscf[1])/bQ; /* bh(1,1) ; bh(2,1) ; bh(3,1) */
           bh[3] = -vecB[1]; bh[4] =  (sncf[0] + kQ3*cscf[0])/bQ; bh[5] =  (sncf[1] + kQ3*cscf[1])/bQ; /* bh(1,2) ; bh(2,2) ; bh(3,2) */
           bh[6] = -vecB[2]; bh[7] = -cscf[0]/aQ;                 bh[8] = -cscf[1]/aQ; /* bh(1,3) ; bh(2,3) ; bh(3,3) */

            for (k=0; k<3; k++) /* Loop over all components */
               r1[k] = ipts[j][k] - bnd[qq[0]][k]; /* r1 = ipts[i][0:2]-y1 */

	      xi = r1[0]*e1[0] + r1[1]*e1[1] + r1[2]*e1[2];
	      zt = r1[0]*e2[0] + r1[1]*e2[1] + r1[2]*e2[2];
	     eth = r1[0]*e3[0] + r1[1]*e3[1] + r1[2]*e3[2];

              p11 = -xi; p12 = bQ-xi; q[0] = -zt; et = -eth;

              if (fabs(et) < gm_eps) et = 0.0;

              x3 = cQ+p11; z3 = aQ+q[0];
              p22 = p12*cscf[0] + q[0]*sncf[0]; p23 = x3*cscf[0] + z3*sncf[0]; q[1] = q[0]*cscf[0] - p12*sncf[0];
              p31 = p11*cscf[1] + q[0]*sncf[1]; p33 = x3*cscf[1] + z3*sncf[1]; q[2] = q[0]*cscf[1] - p11*sncf[1];

              ets = et*et; p11s = p11*p11; p12s = p12*p12; p33s = p33*p33; qs[0] = q[0]*q[0]; qs[1] = q[1]*q[1]; qs[2] = q[2]*q[2];

              Rhs[0] = p11s + qs[0]; Rhs[1] = p12s + qs[0]; Rhs[2] = p33s + qs[2]; /* Rhs[2] = x3*x3 + z3*z3 */
              Rh[0] = sqrt(Rhs[0]); Rh[1] = sqrt(Rhs[1]); Rh[2] = sqrt(Rhs[2]);
              rh1s = Rhs[0] + ets; rh2s = Rhs[1] + ets; rh3s = Rhs[2] + ets;
              rho[0] = sqrt(rh1s); rho[1] = sqrt(rh2s); rho[2] = sqrt(rh3s);

              shc[2] = -q[0]/aQ; shc[1] = (kQ3*q[0] - p11)/bQ;
              shc[0] = 1.0 - (shc[1]+shc[2]); /* shc[0] = 1.0 + (p11 - kQ2*q[0])/bQ */

              if ( fabs(shc[0]) < gm_eps ) {shc[0] = 0.0; q[1] = 0.0;}
 
              if ( fabs(shc[1]) < gm_eps ) {shc[1] = 0.0; q[2] = 0.0;}
              else if ( fabs(shc[1]-1.0) < gm_eps ) shc[1] = 1.0;
 
              if ( fabs(shc[2]) < gm_eps ) {shc[2] = 0.0; q[0] = 0.0;}
              else if ( fabs(shc[2]-1.0) < gm_eps ) shc[2] = 1.0;

              theta0 = pt_tria_tst(shc[0],shc[1],shc[2],theta,&th_id); /* Point in triangle test */

              if ( th_id == 4 ) /* if the Projection of the collocation point ipts[i][0:2] is at vertex y1 */
	      {
        	 Rh[0] = 0.0;
        	 if (et == 0.0) rho[0] = 0.0; /* ipts[i][0:2] = y1 */
              }
	      else if ( th_id == 5 ) /* if the Projection of the collocation point ipts[i][0:2] is at vertex y2 */
	      {
        	 Rh[1] = 0.0;
        	 if (et == 0.0) rho[1] = 0.0; /* ipts[i][0:2] = y2 */
              }
	      else if ( th_id == 6 ) /* if the Projection of the collocation point ipts[i][0:2] is at vertex y3 */
	      {
        	 Rh[2] = 0.0;
        	 if (et == 0.0) rho[2] = 0.0; /* ipts[i][0:2] = y3 */
              }

              qetx2[0] = 2.0*q[0]*et; qetx2[1] = 2.0*q[1]*et; qetx2[2] = 2.0*q[2]*et;

              p11rh1 = p11*rho[0]; p12rh2 = p12*rho[1];
              p22rh2 = p22*rho[1]; p23rh3 = p23*rho[2];
              p33rh3 = p33*rho[2]; p31rh1 = p31*rho[0];

             if ( rho[0] == 0.0 ) /* if the collocation point ipts[i][0:2] is at vertex y1, i.e., ipts[i][0:2] = y1 */
	     {
               int_p[0] = theta0; int_p[1] = 0.0; int_p[2] = 0.0; /* gam = 0.0 */
               rhowv[1] = rho[1]-rho[2]; chi[1] = log( (p22+rho[1])/(p23+rho[2]) );
               qrhowv[1] = q[1]*rhowv[1]; dchi[1] = qs[1]*chi[1];
               int_f[0] = 0.5*(qrhowv[1]*ah[1] - dchi[1]*bh[1]) + q[1]*chi[1];
               int_f[1] = 0.5*(qrhowv[1]*ah[4] - dchi[1]*bh[4]);
               int_f[2] = 0.5*(qrhowv[1]*ah[7] - dchi[1]*bh[7]);
             }
	     else if ( rho[1] == 0.0 ) /* if the collocation point ipts[i][0:2] is at vertex y2, i.e., ipts[i][0:2] = y2 */
	     {
               int_p[0] = 0.0; int_p[1] = theta0; int_p[2] = 0.0; /* gam = 0.0 */
               rhowv[2] = rho[2]-rho[0]; chi[2] = log( (p33+rho[2])/(p31+rho[0]) );
               qrhowv[2] = q[2]*rhowv[2]; dchi[2] = qs[2]*chi[2];
               int_f[0] = 0.5*(qrhowv[2]*ah[2] - dchi[2]*bh[2]);
               int_f[1] = 0.5*(qrhowv[2]*ah[5] - dchi[2]*bh[5]) + q[2]*chi[2];
               int_f[2] = 0.5*(qrhowv[2]*ah[8] - dchi[2]*bh[8]);
             }
	     else if ( rho[2] == 0.0 ) /* if the collocation point ipts[i][0:2] is at vertex y3, i.e., ipts[i][0:2] = y3 */
	     {
               int_p[0] = 0.0; int_p[1] = 0.0; int_p[2] = theta0; /* gam = 0.0 */
               rhowv[0] = rho[0]-rho[1]; chi[0] = log( (p11+rho[0])/(p12+rho[1]) );
               qrhowv[0] = q[0]*rhowv[0]; dchi[0] = qs[0]*chi[0];
               int_f[0] = 0.5*(qrhowv[0]*ah[0] - dchi[0]*bh[0]);
               int_f[1] = 0.5*(qrhowv[0]*ah[3] - dchi[0]*bh[3]);
               int_f[2] = 0.5*(qrhowv[0]*ah[6] - dchi[0]*bh[6]) + q[0]*chi[0];
             }
	     else
	     {
 		    if ( Rh[0] == 0.0 ) /* if the Projection of the collocation point ipts[i][0:2] is at vertex y1 */
		    {
 		    	  cr22 = qs[1]*rh2s-p22*p22*ets; cr23 = qs[1]*rh3s-p23*p23*ets;
 		    	  zn2 = qetx2[1]*(p23rh3*cr22 - p22rh2*cr23); zd2 = cr22*cr23 + qetx2[1]*qetx2[1]*p22rh2*p23rh3;
 		    	  gam = gammai(p22,p23,qetx2[1],cr22,cr23,zn2,zd2); /* gam = gamma[1]; gamma[0] = -gamma[2] = +pi or -pi */
 		    }
		    else if ( Rh[1] == 0.0 ) /* if the Projection of the collocation point ipts[i][0:2] is at vertex y2 */
		    {
 		    	  cr33 = qs[2]*rh3s - p33s*ets; cr31 = qs[2]*rh1s - p31*p31*ets;
 		    	  zn3 = qetx2[2]*(p31rh1*cr33 - p33rh3*cr31); zd3 = cr31*cr33 + qetx2[2]*qetx2[2]*p31rh1*p33rh3;
 		    	  gam = gammai(p33,p31,qetx2[2],cr33,cr31,zn3,zd3); /* gam = gamma[2]; gamma[0] = -gamma[1] = +pi or -pi */
 		    }
		    else if ( Rh[2] == 0.0 ) /* if the Projection of the collocation point ipts[i][0:2] is at vertex y3 */
		    {
 		    	  cr11 = qs[0]*rh1s - p11s*ets; cr12 = qs[0]*rh2s - p12s*ets;
 		    	  zn1 = qetx2[0]*(p12rh2*cr11 - p11rh1*cr12); zd1 = cr11*cr12 + qetx2[0]*qetx2[0]*p11rh1*p12rh2;
 		    	  gam = gammai(p11,p12,qetx2[0],cr11,cr12,zn1,zd1); /* gam = gamma[0]; gamma[1] = -gamma[2] = +pi or -pi */
 		    }
		    else if ( q[0] == 0.0 ) /* if the Projection of the collocation point ipts[i][0:2] is on the line parallel to edge [y1,y2] */
		    {
 		    	  cr22 = qs[1]*rh2s-p22*p22*ets; cr23 = qs[1]*rh3s-p23*p23*ets;
 		    	  zn2 = qetx2[1]*(p23rh3*cr22 - p22rh2*cr23); zd2 = cr22*cr23 + qetx2[1]*qetx2[1]*p22rh2*p23rh3;

 		    	  cr33 = qs[2]*rh3s - p33s*ets; cr31 = qs[2]*rh1s - p31*p31*ets;
 		    	  zn3 = qetx2[2]*(p31rh1*cr33 - p33rh3*cr31); zd3 = cr31*cr33 + qetx2[2]*qetx2[2]*p31rh1*p33rh3;
 
 		    	  gamma[1] = gammai(p22,p23,qetx2[1],cr22,cr23,zn2,zd2);
 		    	  gamma[2] = gammai(p33,p31,qetx2[2],cr33,cr31,zn3,zd3);
 		    	  gam = gamma[1]+gamma[2];
 		    }
		    else if ( q[1] == 0.0 ) /* if the Projection of the collocation point ipts[i][0:2] is on the line parallel to edge [y2,y3] */
		    {
 		    	  cr11 = qs[0]*rh1s - p11s*ets; cr12 = qs[0]*rh2s - p12s*ets;
 		    	  zn1 = qetx2[0]*(p12rh2*cr11 - p11rh1*cr12); zd1 = cr11*cr12 + qetx2[0]*qetx2[0]*p11rh1*p12rh2;

 		    	  cr33 = qs[2]*rh3s - p33s*ets; cr31 = qs[2]*rh1s - p31*p31*ets;
 		    	  zn3 = qetx2[2]*(p31rh1*cr33 - p33rh3*cr31); zd3 = cr31*cr33 + qetx2[2]*qetx2[2]*p31rh1*p33rh3;
 
 		    	  gamma[0] = gammai(p11,p12,qetx2[0],cr11,cr12,zn1,zd1);
 		    	  gamma[2] = gammai(p33,p31,qetx2[2],cr33,cr31,zn3,zd3);
 		    	  gam = gamma[0]+gamma[2];
 		    }
		    else if ( q[2] == 0.0 ) /* if the Projection of the collocation point ipts[i][0:2] is on the line parallel to edge [y3,y1] */
		    {
 		    	  cr11 = qs[0]*rh1s - p11s*ets; cr12 = qs[0]*rh2s - p12s*ets;
 		    	  zn1 = qetx2[0]*(p12rh2*cr11 - p11rh1*cr12); zd1 = cr11*cr12 + qetx2[0]*qetx2[0]*p11rh1*p12rh2;

 		    	  cr22 = qs[1]*rh2s-p22*p22*ets; cr23 = qs[1]*rh3s-p23*p23*ets;
 		    	  zn2 = qetx2[1]*(p23rh3*cr22 - p22rh2*cr23); zd2 = cr22*cr23 + qetx2[1]*qetx2[1]*p22rh2*p23rh3;
 
 		    	  gamma[0] = gammai(p11,p12,qetx2[0],cr11,cr12,zn1,zd1);
 		    	  gamma[1] = gammai(p22,p23,qetx2[1],cr22,cr23,zn2,zd2);
 		    	  gam = gamma[0]+gamma[1];
 		    }
		    else
		    {
 		    	  cr11 = qs[0]*rh1s - p11s*ets; cr12 = qs[0]*rh2s - p12s*ets;
 		    	  zn1 = qetx2[0]*(p12rh2*cr11 - p11rh1*cr12); zd1 = cr11*cr12 + qetx2[0]*qetx2[0]*p11rh1*p12rh2;

 		    	  cr22 = qs[1]*rh2s-p22*p22*ets; cr23 = qs[1]*rh3s-p23*p23*ets;
 		    	  zn2 = qetx2[1]*(p23rh3*cr22 - p22rh2*cr23); zd2 = cr22*cr23 + qetx2[1]*qetx2[1]*p22rh2*p23rh3;

 		    	  cr33 = qs[2]*rh3s - p33s*ets; cr31 = qs[2]*rh1s - p31*p31*ets;
 		    	  zn3 = qetx2[2]*(p31rh1*cr33 - p33rh3*cr31); zd3 = cr31*cr33 + qetx2[2]*qetx2[2]*p31rh1*p33rh3;
 
 		    	  gamma[0] = gammai(p11,p12,qetx2[0],cr11,cr12,zn1,zd1);
 		    	  gamma[1] = gammai(p22,p23,qetx2[1],cr22,cr23,zn2,zd2);
 		    	  gamma[2] = gammai(p33,p31,qetx2[2],cr33,cr31,zn3,zd3);
 		    	  gam = gamma[0]+gamma[1]+gamma[2];
 		    }

        	    rhowv[0] = rho[0]-rho[1]; rhowv[1] = rho[1]-rho[2]; rhowv[2] = rho[2]-rho[0];

        	    d[0] = qs[0] + ets; d[1] = qs[1] + ets; d[2] = qs[2] + ets;

        	    ch11 = p11+rho[0]; ch12 = p12+rho[1];
        	    ch22 = p22+rho[1]; ch23 = p23+rho[2];
        	    ch31 = p31+rho[0]; ch33 = p33+rho[2];

 		    if ( (ch11 >= f_eps) && (ch12 >= f_eps) )
		       chi[0] = log(ch11/ch12);
 		    else
		       chi[0] = asym_chi(p11,p12,d[0]);

 		    if ( (ch22 >= f_eps) && (ch23 >= f_eps) )
 		       chi[1] = log(ch22/ch23);
 		    else
 		       chi[1] = asym_chi(p22,p23,d[1]);

 		    if ( (ch33 >= f_eps) && (ch31 >= f_eps) )
 		       chi[2] = log(ch33/ch31);
 		    else
 		       chi[2] = asym_chi(p33,p31,d[2]);

 		    omega = q[0]*chi[0] + q[1]*chi[1] + q[2]*chi[2];

 		    for (k=0; k<mx_nd_elt; k++) {dchi[k] = d[k]*chi[k]; qrhowv[k] = q[k]*rhowv[k]; etchi[k] = et*chi[k];}
 
 		     if ( et >= 0.0 )
 		    	ThetGam = 0.5*gam + theta0;
 		     else
 		    	ThetGam = 0.5*gam - theta0;

 		    for (k=0; k<mx_nd_elt; k++) /* Loop over all nodes on element Q */
		    {
 		       int_f[k] = 0.0; int_p[k] = 0.0;
		       kk = mx_nd_elt*k; /* kk == Column stride */
 		       for (i=0; i<3; i++) /* Loop over all components */
		       {
 		    	  ii = i + kk; /* ii == Linear index in Column-major ordered ah[3][3] and bh[3][3] matrices defined as 1D arrays */
			  int_f[k] = int_f[k] + qrhowv[i]*ah[ii] - dchi[i]*bh[ii];
 		    	  int_p[k] = int_p[k] - etchi[i]*bh[ii];
 		       }
 		       int_f[k] = 0.5*int_f[k] + (omega - et*ThetGam)*shc[k];
 		       int_p[k] = int_p[k] - ThetGam*shc[k];
 		    }
 
             } /* if The collocation point ipts[i][0:2] is at vertex y1, i.e., ipts[i][0:2] = y1 */

           for (k=0; k<mx_nd_elt; k++) {int_G[qq[k]] += int_f[k]; int_H[qq[k]] += int_p[k];}
 
       } /* Loop over all boundary elements */

       for (k=0; k<nbnd; k++) /* Loop over all boundary nodes */
          fldvl[j] += int_G[k]*flx[k] - int_H[k]*phi[k]; /* fldvl[j] = dot_product(int_G,flx) - dot_product(int_H,phi) */

    } /* Loop over all interior points */

    for (k=0; k<nip; k++) fldvl[k] *= fac; /* Correct the potential at all interior points by the factor fac */
    
    free(int_G); free(int_H);

}
