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

void dgemm_(char *transa,char *transb,const int *m,const int *n,const int *k,
            double *alpha,double *a,const int *lda,double *b,const int *ldb,double *beta,double *c,const int *ldc);
void sing_edg(double a, double c, double aQ, double b, double cQ,
              double *theta, double QPTM[][2], double *int_p, double *int_f, double *int_r);
void seesp(double a, double c, double aQ, double b, double cQ,
              double *theta, double c22, double *int_p, double *int_f, double *int_r);


void gbem_lap_iex_int_e(int elP, int elQ)
{

/* ===purpose=== */

/**********************************************************************************************************************************/
/**********************************  GALERKIN BEM for 3D LAPLACE EQUATION: SINGULAR FORMULATION  **********************************/
/************************************  3-NODED TRIANGULAR ELEMENT: SEMI-ANALYTIC INTEGRATION  *************************************/
/************************************************  PIECEWISE LINEAR APPROXIMATION  ************************************************/
/*******************************  EXact Inner integral with linear distribution on a flat triangle  *******************************/
/**************************************************  Edge-adjacent integration  ***************************************************/
/**********************************************************************************************************************************/

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

 
/******************************************************/
/* Parameter list:                                    */
/******************************************************/
/*
 * elP == (input) Global index of the outer boundary element P
 * elQ == (input) Global index of the inner boundary element Q
 */

/* Global variables */
   extern const int mx_nd_elt;   /* mx_nd_elt == Maximum number of nodes per element */
   extern int nbnd;              /* nbnd == Total number of boundary nodes */
   extern int **belt;            /* belt[i][0:2] == Global indices of boundary nodes on the i-th element */
   extern int *pp, *qq;          /* pp[k] == Global index of the k-th node of the boundary element P */
                                 /* qq[k] == Global index of the k-th node of the boundary element Q */
   extern double pi;             /* pi = 3.1415926535897932 */
   extern double **bnd;          /* bnd[i][0:2] = Cartesian coordinates of the i-th boundary node */
   extern double **xeP, **xeQ;   /* xeP[k][0:2] == Cartesian coordinates of the k-th node of element P */
			         /* xeQ[k][0:2] == Cartesian coordinates of the k-th node of element Q */
   extern int PQmLocId[2];       /* PQmLocId[0] == Local index of the edge of element P that is adjacent to element Q */
			         /* PQmLocId[1] == Local index of the edge of element Q that is adjacent to element P */
   extern double **LocCBasisElt; /* LocCBasisElt[k][0:8] == Local Companion Basis associated with 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 *int_p, *int_f; /* int_p == Local contribution for potential influence matrix */
				 /* int_f == Local contribution for flux influence matrix */
   extern double *int_r;         /* int_r == Local contribution for potential/flux influence matrix */
   extern double *h, *g;         /* h == Potential influence matrix, g == Flux influence matrix */

/* Local variables */
   int k,i,row,col,j,cl_i,cl_i_loc;
   int PcoincidentSide,QcoincidentSide;
   double e1P[3],e2P[3],e3P[3]; /* Orthonormal companion basis associated with element P */
   double e1Q[3],e2Q[3],e3Q[3]; /* Orthonormal companion basis associated with element Q */
   double e1[3],e2[3]; /* Orthonormal local basis */
   double aP,cP; /* Geometric parameters of element P: bP = base, aP = height, 
 		    cP = relative position of the 3rd vertex of element P in the local basis {e1P,e2P,e3P} */
   double aQ,bQ,cQ; /* Geometric parameters of element Q: bQ = bP = length of the coincident edge, aQ = height,
 		       cQ = relative position of the 3rd vertex of element Q in the local basis {e1Q,e2Q,e3Q} */
   double QPTransitionMtrx[2][2];
   double vij[2][3],theta[3],alpha[3],alphaEltP[3],calpk,salpk,x;



    PcoincidentSide = PQmLocId[0]; QcoincidentSide = PQmLocId[1]; /* Side "PcoincidentSide" of element P coincides */
    								  /* with Side "QcoincidentSide" of element Q      */
    

/*** Geometry of the inner element Q */
    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 inner boundary element Q */
       for (i=0; i<3; i++) /* Loop over all components */
          xeQ[k][i] = bnd[qq[k]][i]; /* xeQ[k][0:2] == Cartesian coordinates of the k-th node of 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];
    e3Q[0] = LocCBasisElt[elQ][6]; e3Q[1] = LocCBasisElt[elQ][7]; e3Q[2] = LocCBasisElt[elQ][8];
    
    theta[0] = thetaElt[elQ][0]; theta[1] = thetaElt[elQ][1]; theta[2] = thetaElt[elQ][2];

    alpha[0] = 0.0; alpha[1] = pi-theta[1]; alpha[2] = pi+theta[0];

/*** Reorder the node numbers of element Q so that the edge of element Q specified by the nodes with local  */
/*** indices 0 and 1 respectively coincides with the edge of element Q that is adjacent to element P, i.e., */
/*** consider the permutation of node numbers of the inner element Q                                        */
     if (QcoincidentSide == 0) /* {0,1,2} ==> {0,1,2} */
     {
	  for (k=0; k<3; k++) /* Loop over all components */
	  {e1Q[k] = e1[k]; e2Q[k] = e2[k];}
     }
     else if(QcoincidentSide == 1) /* {0,1,2} ==> {1,2,0} */
     {
	  for (k=0; k<3; k++) /* Loop over all components */
	  {
	     x = xeQ[0][k];
	     xeQ[0][k] = xeQ[1][k];
	     xeQ[1][k] = xeQ[2][k];
	     xeQ[2][k] = x;
	  }
	  k = qq[0];     x = theta[0];
	  qq[0] = qq[1]; theta[0] = theta[1];
	  qq[1] = qq[2]; theta[1] = theta[2];
	  qq[2] = k;     theta[2] = x;

	calpk = cos(alpha[1]); salpk = sin(alpha[1]);

        for (k=0; k<3; k++) /* loop over all components */
	{
           e1Q[k] = calpk*e1[k] + salpk*e2[k];
           e2Q[k] = calpk*e2[k] - salpk*e1[k];
        }
     }
     else /* QcoincidentSide == 2: {0,1,2} ==> {2,0,1} */
     {
	  for (k=0; k<3; k++) /* Loop over all components */
	  {
	     x = xeQ[0][k];
	     xeQ[0][k] = xeQ[2][k];
	     xeQ[2][k] = xeQ[1][k];
	     xeQ[1][k] = x;
	  }
	  k = qq[0];     x = theta[0];
	  qq[0] = qq[2]; theta[0] = theta[2];
	  qq[2] = qq[1]; theta[2] = theta[1];
	  qq[1] = k;     theta[1] = x;

	calpk = cos(alpha[2]); salpk = sin(alpha[2]);

        for (k=0; k<3; k++) /* loop over all components */
	{
           e1Q[k] = calpk*e1[k] + salpk*e2[k];
           e2Q[k] = calpk*e2[k] - salpk*e1[k];
        }
     }

    for (k=0; k<3; k++) /* Loop over all components */
    {
       vij[0][k] = xeQ[1][k] - xeQ[0][k]; /* y2-y1 <== Side 1 of element Q */
       vij[1][k] = xeQ[2][k] - xeQ[0][k]; /* y3-y1 <== Side 3 of element Q */
    }

    bQ = vij[0][0]*e1Q[0] + vij[0][1]*e1Q[1] + vij[0][2]*e1Q[2]; /* bQ>0.0 always */
    aQ = vij[1][0]*e2Q[0] + vij[1][1]*e2Q[1] + vij[1][2]*e2Q[2]; /* aQ>0.0 always */
    cQ = vij[1][0]*e1Q[0] + vij[1][1]*e1Q[1] + vij[1][2]*e1Q[2];


/*** Geometry of the outer element P */
    for (k=0; k<mx_nd_elt; k++) /* Loop over the nodes of element P */
    {
       pp[k] = belt[elP][k]; /* pp[k] == Global index of the k-th node of the outer boundary element P */
       for (i=0; i<3; i++) /* Loop over all components */
	  xeP[k][i] = bnd[pp[k]][i]; /* xeP[k][0:2] == Cartesian coordinates of the k-th node of element P */
    }

     e1[0] = LocCBasisElt[elP][0];  e1[1] = LocCBasisElt[elP][1];  e1[2] = LocCBasisElt[elP][2];
     e2[0] = LocCBasisElt[elP][3];  e2[1] = LocCBasisElt[elP][4];  e2[2] = LocCBasisElt[elP][5];
    e3P[0] = LocCBasisElt[elP][6]; e3P[1] = LocCBasisElt[elP][7]; e3P[2] = LocCBasisElt[elP][8];

    alphaEltP[0] = 0.0; alphaEltP[1] = pi-thetaElt[elP][1]; alphaEltP[2] = pi+thetaElt[elP][0];

/*** Reorder the node numbers of element P so that the edge of element P specified by the nodes with local  */
/*** indices 1 and 2 respectively coincides with the edge of element P that is adjacent to element Q, i.e., */
/*** consider the permutation of node numbers of the outer element P                                        */
     if (PcoincidentSide == 0) /* {0,1,2} ==> {0,1,2} */
     {
	  for (k=0; k<3; k++) /* Loop over all components */
	  {e1P[k] = e1[k]; e2P[k] = e2[k];}
     }
     else if(PcoincidentSide == 1) /* {0,1,2} ==> {1,2,0} */
     {
	  for (k=0; k<3; k++) /* Loop over all components */
	  {
	     x = xeP[0][k];
	     xeP[0][k] = xeP[1][k];
	     xeP[1][k] = xeP[2][k];
	     xeP[2][k] = x;
	  }
	  k = pp[0];
	  pp[0] = pp[1];
	  pp[1] = pp[2];
	  pp[2] = k;

        calpk = cos(alphaEltP[1]); salpk = sin(alphaEltP[1]);

        for (k=0; k<3; k++) /* loop over all components */
	{
           e1P[k] = calpk*e1[k] + salpk*e2[k];
           e2P[k] = calpk*e2[k] - salpk*e1[k];
        }
     }
     else /* PcoincidentSide == 2: {0,1,2} ==> {2,0,1} */
     {
	  for (k=0; k<3; k++) /* Loop over all components */
	  {
	     x = xeP[0][k];
	     xeP[0][k] = xeP[2][k];
	     xeP[2][k] = xeP[1][k];
	     xeP[1][k] = x;
	  }
	  k = pp[0];
	  pp[0] = pp[2];
	  pp[2] = pp[1];
	  pp[1] = k;

        calpk = cos(alphaEltP[2]); salpk = sin(alphaEltP[2]);

        for (k=0; k<3; k++) /* loop over all components */
	{
           e1P[k] = calpk*e1[k] + salpk*e2[k];
           e2P[k] = calpk*e2[k] - salpk*e1[k];
        }
     }

    for (k=0; k<3; k++) /* Loop over all components */
       vij[1][k] = xeP[2][k] - xeP[1][k]; /* x3-x2 <== Side 2 of element P */
    
    cP = vij[1][0]*e1P[0] + vij[1][1]*e1P[1] + vij[1][2]*e1P[2];
    aP = vij[1][0]*e2P[0] + vij[1][1]*e2P[1] + vij[1][2]*e2P[2];


/*** C_ij == Transition matrix from {e1Q,e2Q,e3Q} to {e1P,e2P,e3P} */
/*** Projection (Transformation) of e2P to coordinate system {e1Q,e2Q,e3Q} local to element Q */
          QPTransitionMtrx[0][0] = e2P[0]*e2Q[0] + e2P[1]*e2Q[1] + e2P[2]*e2Q[2]; /* C_22 */
	  QPTransitionMtrx[0][1] = e2P[0]*e3Q[0] + e2P[1]*e3Q[1] + e2P[2]*e3Q[2]; /* C_32 */

/*** Projection (Transformation) of e3P to coordinate system {e1Q,e2Q,e3Q} local to element Q */
          QPTransitionMtrx[1][0] = e3P[0]*e2Q[0] + e3P[1]*e2Q[1] + e3P[2]*e2Q[2]; /* C_23 */
	  QPTransitionMtrx[1][1] = e3P[0]*e3Q[0] + e3P[1]*e3Q[1] + e3P[2]*e3Q[2]; /* C_33 */

     sing_edg(aP,cP,aQ,bQ,cQ,theta,QPTransitionMtrx,int_p,int_f,int_r); /* Integration for edge-adjacent elements */

     for (col=0; col<mx_nd_elt; col++) /* Loop over the nodes of element Q */
     {
        cl_i_loc = mx_nd_elt*col; /* cl_i_loc == Local Column stride */
        cl_i = nbnd*qq[col]; /* cl_i == Column stride */

        for (row=0; row<mx_nd_elt; row++) /* Loop over the nodes of element P */
	{
           k = pp[row] + cl_i; /* Column-major order in h[nbnd][nbnd] and g[nbnd][nbnd] matrices */
	   i = row + cl_i_loc; /* Column-major order in int_p, int_f and int_r matrices */
	   h[k] += int_p[i];
	   g[k] += int_f[i];

/*** Reverse Kernel */
	   j = qq[col] + nbnd*pp[row]; /* nbnd*pp[row] == Column stride for Reverse kernel */
	   h[j] += int_r[i];
	   g[j] += int_f[i];
        }
     }
		 
}


void sing_edg(double a, double c, double aQ, double b, double cQ,
              double *theta, double QPTM[][2], double *int_p, double *int_f, double *int_r)
{

/* ===purpose=== */

/**********************************************************************************************************************************/
/**********************************  GALERKIN BEM for 3D LAPLACE EQUATION: SINGULAR FORMULATION  **********************************/
/************************************  3-NODED TRIANGULAR ELEMENT: SEMI-ANALYTIC INTEGRATION  *************************************/
/************************************************  PIECEWISE LINEAR APPROXIMATION  ************************************************/
/*******************************  EXact Inner integral with linear distribution on a flat triangle  *******************************/
/***************************************  Singular integration for edge-adjacent elements  ****************************************/
/**********************************************************************************************************************************/

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


/******************************************************/
/* Parameter list:                                    */
/******************************************************/
/*
 * a,b,c == (input) Geometric parameters of element P: b = length of the coincident edge for elements P and Q,
 *                  a = height, c = relative position of the 3rd vertex of element P
 * aQ,cQ == (input) Geometric parameters of element Q: b = length of the coincident edge for elements P and Q,
 *                  aQ = height, cQ = relative position of the 3rd vertex of element Q
 * theta[3] == (input): theta[i] == Angle at the i-th vertex of element Q
 * QPTM[2][2] == (input) Transition matrix from element Q to element P
 * int_p == (output) Singular contribution to potential influence matrix H
 * int_f == (output) Singular contribution to flux influence matrix G
 * int_r == (output) Singular contribution to potential influence matrix H: Reverse kernel
 */

/* Global variables */
   extern const int mx_nd_elt; /* mx_nd_elt == Maximum number of nodes per element */
   extern int smx_nd_elt;      /* smx_nd_elt == mx_nd_elt*mx_nd_elt */
   extern double pi, gm_eps;   /* pi = 3.1415926535897932, gm_eps == Tolerance on the geometry */
   extern double ***shfe1;     /* shfe1[i][k][l] == l-th shape function evaluated at Gauss point (k,i) for edge-adjacent case: E' */
   extern double ***shfe2;     /* shfe2[i][k][l] == l-th shape function evaluated at Gauss point (k,i) for edge-adjacent case: E" */
   extern int ng1;       /* ng1 == Number of Gauss-Legendre points over a segment [0,1] for Singular integrations */
   extern double *xi1;   /* xi1 == Gauss-Legendre points over a segment [0,1] for Singular integrations */
   extern double **wwg1; /* wwg1[i][k] = wg1[i]*wg1[k], where wg1[k] is the k-th Gauss-Legendre weight factor corresponding to xi1[k] */

/* Local variables */
   char tr;
   int k,i,ii,kk,j,jj,cl_i,l_k,th_id,dabh;
   double dlt,a_rh2p2,a_rh3p2,a_rh2p2x3,a_rh3p2x3,c_rh2p2,bpc_rh3p2,alp,bet;
   double ap2,ap3,ap4,bp2,bp3,bp4,cp2,cp3,cp4,rh2,rh3,rh2p2,rh2p3,rh2p4,rh2p6,rh3p2,rh3p3,rh3p4,rh3p6,cQmb;
   double ln1,ln2,ln3,bc,bpc,bmc,bpcp2,bc_rh2,bc_rh2s,bbpc_rh3,bbpc_rh3s,bmrh2,bmrh3,ln2_rh2,ln3_rh3;
   double kP2,kP3; /* kP2 == Slope of Edge2 of element P, kP3 == Slope of Edge3 of element P */
   double kQ2,kQ3; /* kQ2 == Slope of Edge2 of element Q, kQ3 == Slope of Edge3 of element Q */
   double c22,c32,c23,c33,c22p2,c32p2,c22c32x2,c22c32s,c22kQ2,c22kQ3,c22_aQ,p12rh2,p11rh1,dltHlf;
   double Ichixx,Ichizz,Ichixz,Ichix,Ichiz,Ichi,Irhoz,Irhoxz,Irhozz,Ichixxz,Ichixzz,Ichizzz,chicR;
   double x,y,xi,zt,p11,p12,p11s,p12s,et,xh,zh,eth,q1h,xhs,rho1h,rho1hs,rh1s,rho2h,rho2hs,q3hethx2,omega;
   double ThetGam,etThetGam,cpbhlf,bhlf,cr11,cr12,xhrh1h,xhrh2h,xww,wpc,theta0,hh1,hh2,hh3,etx2,p31rh1,p33rh3;
   double alpha2,alpha3,p22,p23,p31,p33,x3,z3,rh2s,rh3s,p31h,p31hs,q3h,q3hs,p22h,p22hs,q2h,q2hs,p22hrho2h,q2hethx2;
   double d2h,d3h,zhs,eths,ets,zts,cr22,cr23,cr31,cr33,p33s,p31hrh1h,p22rh2,p23rh3,zn1,zd1,zn2,zd2,zn3,zd3;
   double q[3],qs[2],d[2],rho[3],rhowv[2],chi[2],gamma[3],dchi[2],qchi[2],etchi[2],qrhowv[2],GN2cf[2];
   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],intAh[mx_nd_elt*2]; /* Column-major order in intAh[mx_nd_elt][2] */
   double psi[mx_nd_elt],shc[mx_nd_elt],xwp[mx_nd_elt],intGamwv[mx_nd_elt],intGamwvh[mx_nd_elt];
   double intclNh[mx_nd_elt*2],intclNbh[mx_nd_elt*2],intclMh[mx_nd_elt*2]; /* intclNh,intclNbh,intclMh,intR,intRhoh,intclA are       */
   double intR[mx_nd_elt*2],intRhoh[mx_nd_elt*2],intclA[mx_nd_elt*2];      /* viewed as Column-major ordered mx_nd_elt by 2 matrices */
   double intclN[mx_nd_elt*3],intclM[mx_nd_elt*3]; /* Column-major order in intclN[mx_nd_elt][3], intclM[mx_nd_elt][3] */
   double intGam[smx_nd_elt],intGamh[smx_nd_elt],intKh[smx_nd_elt],intGN3tmp[smx_nd_elt];
   double intOme[smx_nd_elt],intOmeh[smx_nd_elt],intGK2Rchk[smx_nd_elt]; /* intGam,intGamh,intKh,intGN3tmp,intOme,intOmeh,intGK2Rchk, */
   double intGK2[smx_nd_elt],intGN2[smx_nd_elt],intGK2Rh[smx_nd_elt];    /* intGK2,intGN2,intGK2Rh,intGK3,intGN3,intGK3h are viewed   */
   double intGK3[smx_nd_elt],intGN3[smx_nd_elt],intGK3h[smx_nd_elt];     /* as Column-major ordered mx_nd_elt by mx_nd_elt matrices   */



     c22 = QPTM[0][0]; c32 = QPTM[0][1];
     c23 = QPTM[1][0]; c33 = QPTM[1][1];
     
     if ( (fabs(c23) < gm_eps) || (fabs(c32) < gm_eps))
     {
          seesp(a,c,aQ,b,cQ,theta,c22,int_p,int_f,int_r); /* Integration for edge-adjacent elements on the same plane */
	  return;
     }


    dlt = a*b;

    ap2 = a*a;   bp2 = b*b;   cp2 = c*c;
    ap3 = ap2*a; bp3 = bp2*b; cp3 = cp2*c;
    ap4 = ap3*a; bp4 = bp3*b; cp4 = cp3*c;
    
    bc = b*c; bpc = b+c; bmc = b-c;
    bpcp2 = bpc*bpc;

    rh2 = sqrt(ap2+cp2); rh3 = sqrt(ap2+bpcp2);
    rh2p2 = rh2*rh2;   rh3p2 = rh3*rh3;
    rh2p3 = rh2p2*rh2; rh3p3 = rh3p2*rh3;
    rh2p4 = rh2p3*rh2; rh3p4 = rh3p3*rh3;
    rh2p6 = rh2p4*rh2p2; rh3p6 = rh3p4*rh3p2;

    bc_rh2 = bc/rh2; bbpc_rh3 = (bp2+bc)/rh3;
    bc_rh2s = bc_rh2/rh2; bbpc_rh3s = bbpc_rh3/rh3;
    
    ln1 = log( (rh2+c)/(rh3+bpc) );
    ln2 = log( (b + bc_rh2)/(rh2 + rh3 + bc_rh2) );
    ln3 = log( (b - bbpc_rh3)/(rh2 + rh3 - bbpc_rh3) );
    
    a_rh2p2 = ap2/rh2p2; a_rh3p2 = ap2/rh3p2;
    a_rh2p2x3 = 3.0*a_rh2p2; a_rh3p2x3 = 3.0*a_rh3p2;
    bmrh2 = b-rh2; bmrh3 = b-rh3;
    ln2_rh2 = ln2/rh2; ln3_rh3 = ln3/rh3;
    c_rh2p2 = cp2/rh2p2; bpc_rh3p2 = bpcp2/rh3p2;



     Irhoz = ap2*b*( bp3*( (bpcp2*bpcp2-ap2*(ap2+rh3p2))/rh3p6 + (ap2*(ap2+rh2p2)-cp4)/rh2p6 ) +
             rh2*(2.0+b*(b*(a_rh3p2x3-2.0)-c)/rh3p2) - rh3*(2.0+b*(b*a_rh2p2x3-bmc)/rh2p2) -
             bp2*( a_rh2p2x3*bc_rh2s*ln2_rh2 + a_rh3p2x3*bbpc_rh3s*ln3_rh3 ) )/24.0;

     Irhoxz = ap2*b*( bp4*((5.0*a_rh2p2*(a_rh2p2x3-4.0)+3.0)/rh2p2 +(5.0*a_rh3p2*(a_rh3p2x3-1.0)-2.0)/rh3p2)-
              rh2*(4.0*b-6.0*c+b*( 5.0*ap2*b*( b*(a_rh3p2x3-2.0)-c )/rh3p2-2.0*(ap2+bc+bp2+bp2) )/rh3p2)-
              rh3*(6.0*c+b*( 5.0*ap2*b*( c+b*(a_rh2p2x3-4.0) )/rh2p2-ap2-ap2+3.0*b*bmc )/rh2p2) +
              15.0*ap2*bp4*(cp3*ln2_rh2/rh2p6 + ap2*bpc*ln3_rh3/rh3p6) )/120.0;

     Irhozz = ap3*b*( bp4*bpc*(bpcp2+bpcp2-13.0*ap2)/rh3p6 + bp4*c*(cp2+cp2-13.0*ap2)/rh2p6 +
              rh2*(6.0+b*( b*( ap2*(15.0*bbpc_rh3s+5.0)-2.0*(bp2+bc) )/rh3p2 -2.0*(b+b+c))/rh3p2) -
              rh3*(6.0-b*( b*( ap2*(15.0*bc_rh2s-5.0)-bc-bc )/rh2p2 +bmc+bmc )/rh2p2) -
              bp4*(a_rh2p2x3*(5.0*a_rh2p2-4.0)*ln2_rh2/rh2p2 - a_rh3p2x3*(5.0*a_rh3p2-4.0)*ln3_rh3/rh3p2) )/120.0;

     Ichixxz = ap2*b*( bp4*((a_rh2p2*(15.0*a_rh2p2-32.0)+19.0)/rh2p2+(a_rh3p2*(15.0*a_rh3p2-2.0)-1.0)/rh3p2)-
               b*rh2*(2.0+( a_rh3p2*(bp2*(15.0*a_rh3p2-7.0)-5.0*bc)-ap2-ap2-4.0*bp2-3.0*bc )/rh3p2) -
               b*rh3*(2.0+( a_rh2p2*(bp2*(15.0*a_rh2p2-32.0)+5.0*bc)-ap2-ap2+19.0*bp2-7.0*bc )/rh2p2) +
               2.0*(bmc*bmc+cp2+cp2)*ln1 + bp4*( 3.0*cp3*(5.0*a_rh2p2-4.0)*ln2_rh2/rh2p4 +
               bpc*(a_rh3p2*(15.0*a_rh3p2+3.0)+2.0)*ln3_rh3/rh3p2 ) )/120.0;

     Ichixzz = ap3*b*( bp4*( c*(14.0-15.0*a_rh2p2)/rh2p4 - bpc*(1.0+15.0*a_rh3p2)/rh3p4 ) +
               b*rh2*( b*(b*bpc*(15.0*a_rh3p2+1.0)+5.0*ap2)/rh3p2-3.0*b-c-c)/rh3p2 +
               b*rh3*( b*( bc*(15.0*a_rh2p2-14.0)-5.0*ap2)/rh2p2+6.0*b-c-c )/rh2p2 - (2.0*b-6.0*c)*ln1 -
               bp4*( (a_rh2p2*(15.0*a_rh2p2-24.0)+8.0)*ln2_rh2/rh2p2 -
               (a_rh3p2*(15.0*a_rh3p2-9.0)-2.0)*ln3_rh3/rh3p2) )/120.0;

     Ichizzz = ap4*b*( bp4*( (11.0-15.0*a_rh3p2 - bpc*(15.0*a_rh3p2-6.0)*ln3_rh3)/rh3p4 +
               (11.0-15.0*a_rh2p2 + c*(15.0*a_rh2p2-6.0)*ln2_rh2)/rh2p4  ) + 6.0*ln1 +
               b*rh2*( ( bp2*(15.0*a_rh3p2-16.0)-5.0*bc )/rh3p2 - 2.0 )/rh3p2 +
               b*rh3*( ( bp2*(15.0*a_rh2p2-11.0)+5.0*bc )/rh2p2 - 2.0 )/rh2p2 )/120.0;

/* Ichizz/b */
     Ichizz = a*( bp2*( a_rh3p2x3*bbpc_rh3s - a_rh2p2x3*bc_rh2s ) - b*( a_rh3p2*(rh2+3.0*rh2*bbpc_rh3s) +
              a_rh2p2*(rh3-3.0*rh3*bc_rh2s) ) + 2.0*ap2*ln1 - bp3*( a_rh2p2*(a_rh2p2-2.0*c_rh2p2)*ln2_rh2 +
              a_rh3p2*(a_rh3p2-2.0*bpc_rh3p2)*ln3_rh3 ) )/24.0;

/* Ichixz/b */
     Ichixz = ( b*(rh3*a_rh2p2*(4.0*b-c-b*a_rh2p2x3)-rh2*a_rh3p2*(bpc-b*a_rh3p2x3)) -
               bp3*(a_rh2p2*(1.0+3.0*c_rh2p2) + a_rh3p2x3*a_rh3p2) - ap2*(b-c-c)*ln1 +
               bp2*(bc_rh2*a_rh2p2x3*ln2*c_rh2p2 - bbpc_rh3*a_rh3p2*(1.0+a_rh3p2x3)*ln3) )/24.0;

/* Ichixx/(b*b) */
     Ichixx = a*( -b*( bc_rh2*(2.0+3.0*c_rh2p2)/rh2 + bbpc_rh3*(3.0+a_rh3p2x3)/rh3 ) +
             rh2*(a_rh3p2x3*bbpc_rh3 + bpc*(b+b-c)/rh3)/rh3 - rh3*(a_rh2p2x3*bc_rh2 - (5.0*bc-cp2)/rh2)/rh2 +
             2.0*(b-c+cp2/b)*ln1 + bp2*( (6.0+a_rh2p2*(a_rh2p2x3-7.0))*ln2_rh2 +
             (2.0+a_rh3p2*(a_rh3p2x3+1.0))*ln3_rh3 ) )/24.0;

/* Ichiz/b */
     Ichiz = ( b*( a_rh2p2*( bmrh3 - bc_rh2*ln2 ) + a_rh3p2*( bmrh2 + bbpc_rh3*ln3 ) ) + ap2*ln1 )/6.0;

/* Ichix/b */
     Ichix = a*(bc_rh2*bmrh3/rh2 + bbpc_rh3*bmrh2/rh3-(b-c)*ln1-bp2*((1.0+c_rh2p2)*ln2_rh2+(1.0+a_rh3p2)*ln3_rh3))/6.0;

     Ichi = 0.5*dlt*( ln1 + b*(ln2_rh2 + ln3_rh3) );


     cQmb = cQ-b;
     kQ2 = cQmb/aQ; kQ3 = cQ/aQ;
     kP2 = c/a; kP3 = bpc/a;

     c22p2 = c22*c22; c32p2 = c32*c32; c22c32x2 = 2.0*c22*c32;
     c22c32s = c22p2*c32p2; c22kQ2 = c22*kQ2; c22kQ3 = c22*kQ3; c22_aQ = c22/aQ;
    
     intKh[0] = (kP2*c22kQ2*Ichizzz - Ichixxz + (kP2-c22kQ2)*Ichixzz)/bp2 - Ichixz + kP2*Ichizz; /* intKh(1,1) */
     intKh[1] = (Ichixxz - kP3*c22kQ2*Ichizzz - (kP3-c22kQ2)*Ichixzz)/bp2 + 2.0*Ichixz - (kP3-c22kQ2)*Ichizz + b*Ichiz; /* intKh(2,1) */
     intKh[2] = (c22kQ2*Ichizzz + Ichixzz)/dlt + b*Ichizz/a; /* intKh(3,1) */
     intKh[3] = (Ichixxz - (kP2-c22kQ3)*Ichixzz - kP2*c22kQ3*Ichizzz)/bp2; /* intKh(1,2) */
     intKh[4] = (kP3*c22kQ3*Ichizzz - Ichixxz  + (kP3-c22kQ3)*Ichixzz)/bp2 - Ichixz - c22kQ3*Ichizz; /* intKh(2,2) */
     intKh[5] = -(c22kQ3*Ichizzz + Ichixzz)/dlt; /* intKh(3,2) */
     intKh[6] = c22_aQ*(kP2*Ichizzz - Ichixzz)/b; /* intKh(1,3) */
     intKh[7] = c22_aQ*( b*Ichizz + (Ichixzz - kP3*Ichizzz)/b ); /* intKh(2,3) */
     intKh[8] = c22_aQ*Ichizzz/a; /* intKh(3,3) */

     intclN[0] = -c22*(kP2*Irhozz - Irhoxz)/b; /* intclN(1,1) */
     intclN[1] = -c22*((Irhoxz - kP3*Irhozz)/b + Irhoz); /* intclN(2,1) */
     intclN[2] = -c22*Irhozz/a; /* intclN(3,1) */

     intclM[0] = (kP2*Ichizzz - Ichixzz)/b; /* intclM(1,1) */
     intclM[1] = (Ichixzz - kP3*Ichizzz)/b + b*Ichizz; /* intclM(2,1) */
     intclM[2] = Ichizzz/a; /* intclM(3,1) */

    intGK2[0] =  Ichixx - c22kQ2*kP2*Ichizz/b - (kP2-c22kQ2)*Ichixz/b + Ichix - kP2*Ichiz; /* intGK2(1,1) */
    intGK2[1] = -Ichixx + c22kQ2*kP3*Ichizz/b + (kP3-c22kQ2)*Ichixz/b - 2.0*Ichix + (kP3-c22kQ2)*Ichiz - Ichi; /* intGK2(2,1) */
    intGK2[2] = -( c22kQ2*Ichizz + Ichixz + b*Ichiz )/a; /* intGK2(3,1) */
    intGK2[3] = -Ichixx + c22kQ3*kP2*Ichizz/b + (kP2-c22kQ3)*Ichixz/b; /* intGK2(1,2) */
    intGK2[4] =  Ichixx - c22kQ3*kP3*Ichizz/b - (kP3-c22kQ3)*Ichixz/b + Ichix + c22kQ3*Ichiz; /* intGK2(2,2) */
    intGK2[5] =  ( c22kQ3*Ichizz + Ichixz )/a; /* intGK2(3,2) */
    intGK2[6] =  c22_aQ*(Ichixz - kP2*Ichizz); /* intGK2(1,3) */
    intGK2[7] =  c22_aQ*(kP3*Ichizz - Ichixz - b*Ichiz); /* intGK2(2,3) */
    intGK2[8] = -c22_aQ*b*Ichizz/a; /* intGK2(3,3) */

    intGN3tmp[0] = -c32*(kP2*Ichizz-Ichixz); /* intGN3tmp(1,1) */
    intGN3tmp[1] = -c32*(Ichixz-kP3*Ichizz+b*Ichiz); /* intGN3tmp(2,1) */
    intGN3tmp[2] = -c32*b*Ichizz/a; /* intGN3tmp(3,1) */

      if (fabs(c22) < gm_eps ) c22 = 0.0;
      if (fabs(c32) < gm_eps ) c32 = 0.0;

     for (i=0; i<mx_nd_elt; i++)
     {intGN2[i] = 0.0; intGamwv[i] = 0.0; intGamwvh[i] = 0.0;}
     
     for (i=0; i<smx_nd_elt; i++)
     {
              intGamh[i] = 0.0;   intGam[i] = 0.0; intGK3[i] = 0.0; intGK3h[i] = 0.0;
	       intOme[i] = 0.0;  intOmeh[i] = 0.0;
	   intGK2Rchk[i] = 0.0; intGK2Rh[i] = 0.0;
     }

     for (i=0; i<2; i++)
     {
        ii = mx_nd_elt*(i+1); /* ii == Local Column stride */
	for (k=0; k<mx_nd_elt; k++)
	{ 
	   kk = k + ii; /* Column-major order in intclN, intclM and intGN3tmp matrices */
	   intclN[kk] = 0.0; intclM[kk] = 0.0; intGN3tmp[kk] = 0.0; 
	}
     }
     
     for (i=0; i<2*mx_nd_elt; i++)
     {intclNh[i] = 0.0; intclMh[i] = 0.0; intclNbh[i] = 0.0; intR[i] = 0.0; intRhoh[i] = 0.0; intclA[i] = 0.0; intAh[i] = 0.0;}

     bhlf = 0.5*b;
     cpbhlf = c+bhlf; alpha2 = pi-theta[1]; alpha3 = pi+theta[0]; /* alpha1 = 0.0 */
     
     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/b; vecA[1] =  1.0/b; vecA[2] = 0.0;
     vecB[0] =  kQ2/b; vecB[1] = -kQ3/b; vecB[2] = 1.0/aQ;
     
     ah[0] = vecA[0]; ah[1] = (kQ2*sncf[0] - cscf[0])/b; ah[2] = (kQ2*sncf[1] - cscf[1])/b; /* ah(1,1) ; ah(2,1) ; ah(3,1) */
     ah[3] = vecA[1]; ah[4] = (cscf[0] - kQ3*sncf[0])/b; ah[5] = (cscf[1] - kQ3*sncf[1])/b; /* 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])/b; bh[2] = -(sncf[1] + kQ2*cscf[1])/b; /* bh(1,1) ; bh(2,1) ; bh(3,1) */
     bh[3] = -vecB[1]; bh[4] =  (sncf[0] + kQ3*cscf[0])/b; bh[5] =  (sncf[1] + kQ3*cscf[1])/b; /* 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 (i=0; i<ng1; i++) /* Loop over y  :: E' */
     {
        y = xi1[i];
	xh = c-cpbhlf*y; zh = a*(1.0-y);
        eth = -c32*zh; q1h = -c22*zh;
	p31h = xh*cscf[1] + q1h*sncf[1]; q3h = q1h*cscf[1] - xh*sncf[1]; /* cscf[1] = cos(alpha3); sncf[1] = sin(alpha3) */
	xhs = xh*xh; zhs = zh*zh;

        rho1hs = xhs + zhs;
        rho1h = sqrt(rho1hs);

	if (fabs(q3h) < gm_eps) q3h = 0.0;
	
	eths = eth*eth; p31hs = p31h*p31h; q3hs = q3h*q3h;
	d3h = q3hs + eths;
        
	xhrh1h = xh*rho1h; p31hrh1h = p31h*rho1h; q3hethx2 = 2.0*q3h*eth;
	cr11 = c22p2*rho1hs - c32p2*xhs; hh1 = 4.0*c22c32s*xhrh1h;
	cr31 = q3hs*rho1hs - p31hs*eths; hh3 = 4.0*p31hrh1h*q3hs*eths;
	
        for (k=0; k<ng1; k++) /* Loop over x  :: E' */
	{
           x = xi1[k];
           xww = x*wwg1[i][k]; /* xww = x*wg1[i]*wg1[k] */
           xi = x*xh; zt = x*zh; q[0] = x*q1h; et = x*eth; p31 = x*p31h; q[2] = x*q3h; /* p11 = xi */
	   p12 = b+xi; x3 = cQ+xi; z3 = aQ+q[0];
	   p22 = p12*cscf[0] + q[0]*sncf[0]; q[1] = q[0]*cscf[0] - p12*sncf[0]; /* cscf[0] = cos(alpha2); sncf[0] = sin(alpha2) */
	   p23 = x3*cscf[0] + z3*sncf[0]; p33 = x3*cscf[1] + z3*sncf[1];        /* cscf[1] = cos(alpha3); sncf[1] = sin(alpha3) */
	   ets = et*et; p12s = p12*p12; zts = zt*zt; p33s = p33*p33; qs[0] = q[1]*q[1]; /* qs[0] = qs(2) */

	   rh1s = xi*xi + zts; rh2s = p12s + zts; rh3s = p33s + q[2]*q[2] + ets;
	   rho[0] = sqrt(rh1s); rho[1] = sqrt(rh2s); rho[2] = sqrt(rh3s);

	   psi[0] = shfe1[i][k][0]; psi[1] = shfe1[i][k][1]; psi[2] = shfe1[i][k][2]; /* psi[0] = 0.5*x*y; psi[2] = x*(1.0-y) */
									              /* psi[1] = 1.0 + x*(0.5*y-1.0) */

           shc[1] = -(xi+c22kQ3*zt)/b; shc[2] = c22_aQ*zt;
	   shc[0] = 1.0 - (shc[1]+shc[2]); /* shc[0] = 1.0 + (xi+c22kQ2*zt)/b */

	   if ( fabs(shc[0]) < gm_eps ) {shc[0] = 0.0; q[1] = 0.0;}
	   
	   if ( fabs(shc[1]) < gm_eps ) shc[1] = 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;
	   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 */

	   rhowv[0] = rho[1]-rho[2]; rhowv[1] = rho[2]-rho[0]; /* rhowv[0] = rhowv(2); rhowv[1] = rhowv(3)*/
	   chi[0] = log( (p22+rho[1])/(p23+rho[2]) ); chi[1] = -log( (p31+rho[0])/(p33+rho[2]) ); /* chi[0] = chi(2); chi[1] = chi(3) */

	   d[0] = qs[0] + ets; d[1] = x*x*d3h; etx2 = 2.0*et; /* d[0] = d(2); d[1] = d(3) */
	   
	   qetx2[0] = q[0]*etx2; qetx2[1] = q[1]*etx2;
	   
	   cr12 = c22p2*rh2s - c32p2*p12s; p12rh2 = p12*rho[1];
	   zn1 = c22c32x2*(p12rh2*cr11 - xhrh1h*cr12); zd1 = cr11*cr12 + p12rh2*hh1;

	   cr22 = qs[0]*rh2s - p22*p22*ets; cr23 = qs[0]*rh3s - p23*p23*ets; p22rh2 = p22*rho[1]; p23rh3 = p23*rho[2];
	   zn2 = qetx2[1]*(p23rh3*cr22 - p22rh2*cr23); zd2 = cr22*cr23 + qetx2[1]*qetx2[1]*p22rh2*p23rh3;
	   
	   cr33 = q3hs*rh3s - p33s*eths; p33rh3 = p33*rho[2];
	   zn3 = q3hethx2*(p31hrh1h*cr33 - p33rh3*cr31); zd3 = cr31*cr33 + p33rh3*hh3;

	   gamma[0] = gammai(xi ,p12,qetx2[0],cr11,cr12,zn1,zd1);
	   gamma[1] = gammai(p22,p23,qetx2[1],cr22,cr23,zn2,zd2);
	   gamma[2] = gammai(p33,p31,q3hethx2,cr33,cr31,zn3,zd3);

	   if ( et > 0.0)
	      ThetGam = 0.5*(gamma[0]+gamma[1]+gamma[2]) + theta0;
	   else
	      ThetGam = 0.5*(gamma[0]+gamma[1]+gamma[2]) - theta0;

	   etThetGam = et*ThetGam;

           xwp[0] = xww*psi[0]; xwp[1] = xww*psi[1]; xwp[2] = xww*psi[2];
	   for (ii=0; ii<2; ii++)
	   {dchi[ii] = d[ii]*chi[ii]; qrhowv[ii] = q[ii+1]*rhowv[ii]; qchi[ii] = q[ii+1]*chi[ii]; etchi[ii] = et*chi[ii];}

	   omega = qchi[0] + qchi[1]; /* qchi[0] = qchi(2); qchi[1] = qchi(3) */
	   chicR = cscf[0]*chi[0] + cscf[1]*chi[1]; /* cscf[0] = cos(alpha2); cscf[1] = cos(alpha3) */
           
           for (ii=0; ii<mx_nd_elt; ii++)
	   {
	      intGamwvh[ii] = intGamwvh[ii] + xwp[ii]*etThetGam;
	      cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
                 wpc = xwp[kk]*shc[ii];
		 l_k = kk + cl_i; /* Column-major order in intGamh, intGK3h, intOmeh and intGK2Rh matrices */
                  intGamh[l_k] += wpc*etThetGam;
		  intGK3h[l_k] += wpc*ThetGam;
		  intOmeh[l_k] += wpc*omega;
		 intGK2Rh[l_k] += wpc*chicR;
              }
           }

           for (ii=0; ii<2; ii++)
	   {
              cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
                  l_k = kk + cl_i; /* Column-major order in intclNh, intclMh, intclNbh, intRhoh and intAh matrices */
		  intclNh[l_k] += xwp[kk]*qrhowv[ii];
		  intclMh[l_k] += xwp[kk]*dchi[ii];
		 intclNbh[l_k] += xwp[kk]*etchi[ii];
		  intRhoh[l_k] += xwp[kk]*rhowv[ii];
		    intAh[l_k] += xwp[kk]*qchi[ii];
              }
           }

        } /* End Loop over x  :: E' */
     } /* End Loop over y  :: E' */


     for (i=0; i<ng1; i++) /* Loop over y  :: E" */
     {
        y = xi1[i];
        xh = bhlf+cpbhlf*y; zh = a*y;
	eth = -c32*zh; q1h = -c22*zh;
	p22h = xh*cscf[0] + q1h*sncf[0]; q2h = q1h*cscf[0] - xh*sncf[0]; /* cscf[0] = cos(alpha2); sncf[0] = sin(alpha2) */
	xhs = xh*xh; zhs = zh*zh;

        rho2hs = xhs + zhs;
        rho2h = sqrt(rho2hs);

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

	eths = eth*eth; p22hs = p22h*p22h; q2hs = q2h*q2h;
	d2h = q2hs + eths;

	xhrh2h = xh*rho2h; p22hrho2h = p22h*rho2h; q2hethx2 = 2.0*q2h*eth;
	cr12 = c22p2*rho2hs - c32p2*xhs; hh1 = 4.0*c22c32s*xhrh2h;
	cr22 = q2hs*rho2hs - p22hs*eths; hh2 = 4.0*p22hrho2h*q2hs*eths;
	
        for (k=0; k<ng1; k++) /* Loop over x  :: E" */
	{
           x = xi1[k];
           xww = x*wwg1[i][k]; /* xww = x*wg1[i]*wg1[k] */
           xi = x*xh; zt = x*zh; q[0] = x*q1h; et = x*eth; p22 = x*p22h; q[1] = x*q2h; /* p12 = xi */
	   p11 = xi-b; x3 = cQmb+xi; z3 = aQ+q[0];
	   p23 = x3*cscf[0] + z3*sncf[0]; p33 = x3*cscf[1] + z3*sncf[1];
	   p31 = p11*cscf[1] + q[0]*sncf[1]; q[2] = q[0]*cscf[1] - p11*sncf[1]; /* cscf[1] = cos(alpha3); sncf[1] = sin(alpha3) */
	   ets = et*et; p11s = p11*p11; zts = zt*zt; p33s = p33*p33; qs[1] = q[2]*q[2]; /* qs[1] = qs(3) */

	   rh1s = p11s + zts; rh2s = xi*xi + zts; rh3s = p33s + qs[1] + ets;
	   rho[0] = sqrt(rh1s); rho[1] = sqrt(rh2s); rho[2] = sqrt(rh3s);

	   psi[0] = shfe2[i][k][0]; psi[1] = shfe2[i][k][1]; psi[2] = shfe2[i][k][2]; /* psi[0] = 1.0-0.5*x*(1.0+y); psi[2] = x*y */
									              /* psi[1] = 0.5*x*(1.0-y) */

           shc[0] = (xi+c22kQ2*zt)/b; shc[2] = c22_aQ*zt;
	   shc[1] = 1.0 -(shc[0]+shc[2]); /* shc[1] = 1.0 - (xi+c22kQ3*zt)/b */

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

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

	   rhowv[0] = rho[1]-rho[2]; rhowv[1] = rho[2]-rho[0]; /* rhowv[0] = rhowv(2); rhowv[1] = rhowv(3)*/
	   chi[0] = log( (p22+rho[1])/(p23+rho[2]) ); chi[1] = -log( (p31+rho[0])/(p33+rho[2]) ); /* chi[0] = chi(2); chi[1] = chi(3) */

	   d[0] = x*x*d2h; d[1] = qs[1] + ets; etx2 = 2.0*et; /* d[0] = d(2); d[1] = d(3) */

	   qetx2[0] = q[0]*etx2; qetx2[2] = q[2]*etx2;
	   
	   cr11 = c22p2*rh1s - c32p2*p11s; p11rh1 = p11*rho[0];
	   zn1 = c22c32x2*(xhrh2h*cr11 - p11rh1*cr12); zd1 = cr11*cr12 + p11rh1*hh1;
	   
	   cr23 = q2hs*rh3s - p23*p23*eths; p23rh3 = p23*rho[2];
	   zn2 = q2hethx2*(p23rh3*cr22 - p22hrho2h*cr23); zd2 = cr22*cr23 + p23rh3*hh2;
	   
	   cr33 = qs[1]*rh3s - p33s*ets; cr31 = qs[1]*rh1s - p31*p31*ets; p31rh1 = p31*rho[0]; p33rh3 = p33*rho[2];
	   zn3 = qetx2[2]*(p31rh1*cr33 - p33rh3*cr31); zd3 = cr31*cr33 + qetx2[2]*qetx2[2]*p31rh1*p33rh3;

	   gamma[0] = gammai(p11,xi ,qetx2[0],cr11,cr12,zn1,zd1);
	   gamma[1] = gammai(p22,p23,q2hethx2,cr22,cr23,zn2,zd2);
	   gamma[2] = gammai(p33,p31,qetx2[2],cr33,cr31,zn3,zd3);

	   if ( et > 0.0 ) 
	      ThetGam = 0.5*(gamma[0]+gamma[1]+gamma[2]) + theta0;
	   else
	      ThetGam = 0.5*(gamma[0]+gamma[1]+gamma[2]) - theta0;

	   etThetGam = et*ThetGam;

           xwp[0] = xww*psi[0]; xwp[1] = xww*psi[1]; xwp[2] = xww*psi[2];

	   for (ii=0; ii<2; ii++)
	   {dchi[ii] = d[ii]*chi[ii]; qrhowv[ii] = q[ii+1]*rhowv[ii]; qchi[ii] = q[ii+1]*chi[ii]; etchi[ii] = et*chi[ii];}
	   
	   omega = qchi[0] + qchi[1]; /* qchi[0] = qchi(2); qchi[1] = qchi(3) */
	   chicR = cscf[0]*chi[0] + cscf[1]*chi[1]; /* cscf[0] = cos(alpha2); cscf[1] = cos(alpha3) */
	   
           for (ii=0; ii<mx_nd_elt; ii++)
	   {
	      intGamwv[ii] = intGamwv[ii] + xwp[ii]*etThetGam;
	      cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
                 wpc = xwp[kk]*shc[ii];
		 l_k = kk + cl_i; /* Column-major order in intGam, intGK3, intOme and intGK2Rchk matrices */
                     intGam[l_k] += wpc*etThetGam;
		     intGK3[l_k] += wpc*ThetGam;
		     intOme[l_k] += wpc*omega;
		 intGK2Rchk[l_k] += wpc*chicR;
              }
           }
           
           for (ii=0; ii<2; ii++)
	   {
              cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      jj = mx_nd_elt + cl_i; /* jj == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
		    j = kk + jj; /* Column-major order in intclN, intclM, intGN3tmp */
                    l_k = kk + cl_i; /* Column-major order in intR and intclA matrices */
		    intclN[j] += xwp[kk]*qrhowv[ii];
		    intclM[j] += xwp[kk]*dchi[ii];
		 intGN3tmp[j] += xwp[kk]*etchi[ii];

		    intR[l_k] += xwp[kk]*rhowv[ii];
		  intclA[l_k] += xwp[kk]*qchi[ii];
              }
           }
           
        } /* End Loop over x :: E" */
     } /*  End Loop over y  :: E" */


     dltHlf = 0.5*dlt;
     GN2cf[0] = sncf[0]*dltHlf; GN2cf[1] = sncf[1]*dltHlf; /* sncf[0] = sin(alpha2); sncf[1] = sin(alpha3) */

    intGamwv[0] = dltHlf*(intGamwv[0] + intGamwvh[0]);
    intGamwv[1] = dltHlf*(intGamwv[1] + intGamwvh[1]);
    intGamwv[2] = dltHlf*(intGamwv[2] + intGamwvh[2]);
    
    for (k=0; k<2; k++)
    {
       kk = mx_nd_elt*k; /* kk == Local Column stride */
       l_k = mx_nd_elt + kk; /* l_k == Local Column stride */
       for (i=0; i<mx_nd_elt; i++)
       {
             ii = i + kk; /* Column-major order in intclNh, intclMh, intclNbh, intRhoh and intAh matrices */
	     cl_i = i + l_k; /* Column-major order in intclN, intclM, intGN3tmp, intR and intclA matrices */
	     intclN[cl_i] = dltHlf*(   intclN[cl_i] +  intclNh[ii]);
	     intclM[cl_i] = dltHlf*(   intclM[cl_i] +  intclMh[ii]);
	  intGN3tmp[cl_i] = dltHlf*(intGN3tmp[cl_i] + intclNbh[ii]);
	  
	    intR[ii] = GN2cf[k]*(  intR[ii] + intRhoh[ii]);
	  intclA[ii] = GN2cf[k]*(intclA[ii] +   intAh[ii]);
       }
    }

     tr = 'n'; dabh = 3; alp = 1.0; bet = 0.0;
     dgemm_(&tr,&tr,&mx_nd_elt,&dabh,&mx_nd_elt,&alp,intGN3tmp,&mx_nd_elt,bh,&dabh,&bet,intGN3,&mx_nd_elt); /* intGN3 = matmul(intGN3tmp,bh) */

/*** int_f = matmul(intclN,ah) - matmul(intclM,bh) */
     dgemm_(&tr,&tr,&mx_nd_elt,&dabh,&dabh,&alp,intclM,&mx_nd_elt,bh,&dabh,&bet,int_f,&mx_nd_elt); /* int_f = matmul(intclM,bh) */
     bet = -1.0;
     dgemm_(&tr,&tr,&mx_nd_elt,&dabh,&dabh,&alp,intclN,&mx_nd_elt,ah,&dabh,&bet,int_f,&mx_nd_elt); /* int_f = matmul(intclN,ah) - int_f */

    intGN2[0] = intR[0]*bh[1] + intR[3]*bh[2] + intclA[0]*ah[1] + intclA[3]*ah[2];
    intGN2[1] = intR[1]*bh[1] + intR[4]*bh[2] + intclA[1]*ah[1] + intclA[4]*ah[2];
    intGN2[2] = intR[2]*bh[1] + intR[5]*bh[2] + intclA[2]*ah[1] + intclA[5]*ah[2];
    
    intGN2[3] = intR[0]*bh[4] + intR[3]*bh[5] + intclA[0]*ah[4] + intclA[3]*ah[5];
    intGN2[4] = intR[1]*bh[4] + intR[4]*bh[5] + intclA[1]*ah[4] + intclA[4]*ah[5];
    intGN2[5] = intR[2]*bh[4] + intR[5]*bh[5] + intclA[2]*ah[4] + intclA[5]*ah[5];
    
    intGN2[6] = intR[0]*bh[7] + intR[3]*bh[8] + intclA[0]*ah[7] + intclA[3]*ah[8];
    intGN2[7] = intR[1]*bh[7] + intR[4]*bh[8] + intclA[1]*ah[7] + intclA[4]*ah[8];
    intGN2[8] = intR[2]*bh[7] + intR[5]*bh[8] + intclA[2]*ah[7] + intclA[5]*ah[8];

    for (k=0; k<mx_nd_elt; k++)
    {
       kk = mx_nd_elt*k; /* kk == Local Column stride */
       for (i=0; i<mx_nd_elt; i++)
       {
	  ii = i + kk; /* Column-major order in intGam, intGK3, intOme, intGK2 and intGN2 matrices */
	  intGam[ii] = dltHlf*(intGam[ii] + intGamh[ii]);
	  intGK3[ii] = dltHlf*(intGK3[ii] + intGK3h[ii]);
	  intOme[ii] = dltHlf*(intOme[ii] + intOmeh[ii]) - c22*intKh[ii];
	  
	  intGK2[ii] = intGK2[ii] - dltHlf*(intGK2Rh[ii] + intGK2Rchk[ii]);
	  intGN2[ii] = intGN2[ii] - intGamwv[i]*vecB[k];
       }
    }

    for (k=0; k<mx_nd_elt; k++)
    {
       kk = mx_nd_elt*k; /* kk == Local Column stride */ 
       for (i=0; i<mx_nd_elt; i++)
       {
	  ii = i + kk; /* Column-major order in int_f, int_p and int_r matrices viewed as mx_nd_elt by mx_nd_elt matrices */
	  int_f[ii] = 0.5*int_f[ii] + intOme[ii] - intGam[ii];       /* Weakly-singular kernel ==> G */
	  int_p[ii] = -(intGN3[ii] + intGK3[ii]);                    /* Singular kernel ==> H */
	  int_r[ii] = c23*(intGN2[ii] + intGK2[ii]) - c33*int_p[ii]; /* Reverse kernel ==> H */
       }
    }

}


void seesp(double a, double c, double aQ, double b, double cQ,
              double *theta, double c22, double *int_p, double *int_f, double *int_r)
{

/* ===purpose=== */

/**********************************************************************************************************************************/
/**********************************  GALERKIN BEM for 3D LAPLACE EQUATION: SINGULAR FORMULATION  **********************************/
/************************************  3-NODED TRIANGULAR ELEMENT: SEMI-ANALYTIC INTEGRATION  *************************************/
/************************************************  PIECEWISE LINEAR APPROXIMATION  ************************************************/
/*******************************  EXact Inner integral with linear distribution on a flat triangle  *******************************/
/******************************  Singular integration for edge-adjacent elements on the same plane  *******************************/
/**********************************************************************************************************************************/

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


/******************************************************/
/* Parameter list:                                    */
/******************************************************/
/*
 * a,b,c == (input) Geometric parameters of element P: b = length of the coincident edge for elements P and Q,
 *                  a = height, c = relative position of the 3rd vertex of element P
 * aQ,cQ == (input) Geometric parameters of element Q: b = length of the coincident edge for elements P and Q,
 *                  aQ = height, cQ = relative position of the 3rd vertex of element Q
 * theta[3] == (input): theta[i] == Angle at the i-th vertex of element Q
 * c22 == (input) Diagonal component of the Transition matrix from element Q to element P
 * int_p == (output) Singular contribution to potential influence matrix H
 * int_f == (output) Singular contribution to flux influence matrix G
 * int_r == (output) Singular contribution to potential influence matrix H: Reverse kernel
 */

/* Global variables */
   extern const int mx_nd_elt; /* mx_nd_elt == Maximum number of nodes per element */
   extern int smx_nd_elt;      /* smx_nd_elt == mx_nd_elt*mx_nd_elt */
   extern double pi, f_eps;    /* pi = 3.1415926535897932, f_eps == Tolerance on the argument of a function */
   extern double ***shfe1;     /* shfe1[i][k][l] == l-th shape function evaluated at Gauss point (k,i) for edge-adjacent case: E' */
   extern double ***shfe2;     /* shfe2[i][k][l] == l-th shape function evaluated at Gauss point (k,i) for edge-adjacent case: E" */
   extern int ng1;       /* ng1 == Number of Gauss-Legendre points over a segment [0,1] for Singular integrations */
   extern double *xi1;   /* xi1 == Gauss-Legendre points over a segment [0,1] for Singular integrations */
   extern double **wwg1; /* wwg1[i][k] = wg1[i]*wg1[k], where wg1[k] is the k-th Gauss-Legendre weight factor corresponding to xi1[k] */

/* Local variables */
   char tr;
   int k,i,ii,kk,j,jj,cl_i,l_k,dabh;
   double dlt,a_rh2p2,a_rh3p2,a_rh2p2x3,a_rh3p2x3,c_rh2p2,bpc_rh3p2,alp,bet;
   double ap2,ap3,ap4,bp2,bp3,bp4,cp2,cp3,cp4,rh2,rh3,rh2p2,rh2p3,rh2p4,rh2p6,rh3p2,rh3p3,rh3p4,rh3p6,cQmb;
   double ln1,ln2,ln3,bc,bpc,bmc,bpcp2,bc_rh2,bc_rh2s,bbpc_rh3,bbpc_rh3s,bmrh2,bmrh3,ln2_rh2,ln3_rh3;
   double kP2,kP3; /* kP2 == Slope of Edge2 of element P, kP3 == Slope of Edge3 of element P */
   double kQ2,kQ3; /* kQ2 == Slope of Edge2 of element Q, kQ3 == Slope of Edge3 of element Q */
   double c22kQ2,c22kQ3,c22_aQ,dltHlf,x,y,xi,zt,xh,zh,q1h,cpbhlf,bhlf;
   double Ichizz,Ichixz,Ichiz,Irhoz,Irhoxz,Irhozz,Ichixxz,Ichixzz,Ichizzz,xww,d2h,d3h,zts,omega;
   double alpha2,alpha3,p11,p12,p22,p23,p31,p33,x3,z3,p31h,q3h,p22h,q2h,ch33,ch31,z1,z1s,z2,z2s;
   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],q[3],qs[2],rho[3],rhowv[2],chi[2],dchi[2],qrhowv[2];
   double psi[mx_nd_elt],shc[mx_nd_elt],xwp[mx_nd_elt];
   double intclNh[mx_nd_elt*2],intclMh[mx_nd_elt*2]; /* Column-major order in intclNh[mx_nd_elt][2], intclMh[mx_nd_elt][2] */
   double intclN[mx_nd_elt*3],intclM[mx_nd_elt*3]; /* Column-major order in intclN[mx_nd_elt][3], intclM[mx_nd_elt][3] */
   double intKh[smx_nd_elt],intOme[smx_nd_elt]; /* Column-major order in intKh[mx_nd_elt][mx_nd_elt],intOme[mx_nd_elt][mx_nd_elt] */
   double intOmeh[smx_nd_elt]; /* Column-major order in intOmeh[mx_nd_elt][mx_nd_elt] */



    dlt = a*b;

    ap2 = a*a;   bp2 = b*b;   cp2 = c*c;
    ap3 = ap2*a; bp3 = bp2*b; cp3 = cp2*c;
    ap4 = ap3*a; bp4 = bp3*b; cp4 = cp3*c;
    
    bc = b*c; bpc = b+c; bmc = b-c;
    bpcp2 = bpc*bpc;

    rh2 = sqrt(ap2+cp2); rh3 = sqrt(ap2+bpcp2);
    rh2p2 = rh2*rh2;   rh3p2 = rh3*rh3;
    rh2p3 = rh2p2*rh2; rh3p3 = rh3p2*rh3;
    rh2p4 = rh2p3*rh2; rh3p4 = rh3p3*rh3;
    rh2p6 = rh2p4*rh2p2; rh3p6 = rh3p4*rh3p2;

    bc_rh2 = bc/rh2; bbpc_rh3 = (bp2+bc)/rh3;
    bc_rh2s = bc_rh2/rh2; bbpc_rh3s = bbpc_rh3/rh3;
    
    ln1 = log( (rh2+c)/(rh3+bpc) );
    ln2 = log( (b + bc_rh2)/(rh2 + rh3 + bc_rh2) );
    ln3 = log( (b - bbpc_rh3)/(rh2 + rh3 - bbpc_rh3) );
    
    a_rh2p2 = ap2/rh2p2; a_rh3p2 = ap2/rh3p2;
    a_rh2p2x3 = 3.0*a_rh2p2; a_rh3p2x3 = 3.0*a_rh3p2;
    bmrh2 = b-rh2; bmrh3 = b-rh3;
    ln2_rh2 = ln2/rh2; ln3_rh3 = ln3/rh3;
    c_rh2p2 = cp2/rh2p2; bpc_rh3p2 = bpcp2/rh3p2;



     Irhoz = ap2*b*( bp3*( (bpcp2*bpcp2-ap2*(ap2+rh3p2))/rh3p6 + (ap2*(ap2+rh2p2)-cp4)/rh2p6 ) +
             rh2*(2.0+b*(b*(a_rh3p2x3-2.0)-c)/rh3p2) - rh3*(2.0+b*(b*a_rh2p2x3-bmc)/rh2p2) -
             bp2*( a_rh2p2x3*bc_rh2s*ln2_rh2 + a_rh3p2x3*bbpc_rh3s*ln3_rh3 ) )/24.0;

     Irhoxz = ap2*b*( bp4*((5.0*a_rh2p2*(a_rh2p2x3-4.0)+3.0)/rh2p2 +(5.0*a_rh3p2*(a_rh3p2x3-1.0)-2.0)/rh3p2)-
              rh2*(4.0*b-6.0*c+b*( 5.0*ap2*b*( b*(a_rh3p2x3-2.0)-c )/rh3p2-2.0*(ap2+bc+bp2+bp2) )/rh3p2)-
              rh3*(6.0*c+b*( 5.0*ap2*b*( c+b*(a_rh2p2x3-4.0) )/rh2p2-ap2-ap2+3.0*b*bmc )/rh2p2) +
              15.0*ap2*bp4*(cp3*ln2_rh2/rh2p6 + ap2*bpc*ln3_rh3/rh3p6) )/120.0;

     Irhozz = ap3*b*( bp4*bpc*(bpcp2+bpcp2-13.0*ap2)/rh3p6 + bp4*c*(cp2+cp2-13.0*ap2)/rh2p6 +
              rh2*(6.0+b*( b*( ap2*(15.0*bbpc_rh3s+5.0)-2.0*(bp2+bc) )/rh3p2 -2.0*(b+b+c))/rh3p2) -
              rh3*(6.0-b*( b*( ap2*(15.0*bc_rh2s-5.0)-bc-bc )/rh2p2 +bmc+bmc )/rh2p2) -
              bp4*(a_rh2p2x3*(5.0*a_rh2p2-4.0)*ln2_rh2/rh2p2 - a_rh3p2x3*(5.0*a_rh3p2-4.0)*ln3_rh3/rh3p2) )/120.0;

     Ichixxz = ap2*b*( bp4*((a_rh2p2*(15.0*a_rh2p2-32.0)+19.0)/rh2p2+(a_rh3p2*(15.0*a_rh3p2-2.0)-1.0)/rh3p2)-
               b*rh2*(2.0+( a_rh3p2*(bp2*(15.0*a_rh3p2-7.0)-5.0*bc)-ap2-ap2-4.0*bp2-3.0*bc )/rh3p2) -
               b*rh3*(2.0+( a_rh2p2*(bp2*(15.0*a_rh2p2-32.0)+5.0*bc)-ap2-ap2+19.0*bp2-7.0*bc )/rh2p2) +
               2.0*(bmc*bmc+cp2+cp2)*ln1 + bp4*( 3.0*cp3*(5.0*a_rh2p2-4.0)*ln2_rh2/rh2p4 +
               bpc*(a_rh3p2*(15.0*a_rh3p2+3.0)+2.0)*ln3_rh3/rh3p2 ) )/120.0;

     Ichixzz = ap3*b*( bp4*( c*(14.0-15.0*a_rh2p2)/rh2p4 - bpc*(1.0+15.0*a_rh3p2)/rh3p4 ) +
               b*rh2*( b*(b*bpc*(15.0*a_rh3p2+1.0)+5.0*ap2)/rh3p2-3.0*b-c-c)/rh3p2 +
               b*rh3*( b*( bc*(15.0*a_rh2p2-14.0)-5.0*ap2)/rh2p2+6.0*b-c-c )/rh2p2 - (2.0*b-6.0*c)*ln1 -
               bp4*( (a_rh2p2*(15.0*a_rh2p2-24.0)+8.0)*ln2_rh2/rh2p2 -
               (a_rh3p2*(15.0*a_rh3p2-9.0)-2.0)*ln3_rh3/rh3p2) )/120.0;

     Ichizzz = ap4*b*( bp4*( (11.0-15.0*a_rh3p2 - bpc*(15.0*a_rh3p2-6.0)*ln3_rh3)/rh3p4 +
               (11.0-15.0*a_rh2p2 + c*(15.0*a_rh2p2-6.0)*ln2_rh2)/rh2p4  ) + 6.0*ln1 +
               b*rh2*( ( bp2*(15.0*a_rh3p2-16.0)-5.0*bc )/rh3p2 - 2.0 )/rh3p2 +
               b*rh3*( ( bp2*(15.0*a_rh2p2-11.0)+5.0*bc )/rh2p2 - 2.0 )/rh2p2 )/120.0;

/* Ichizz/b */
     Ichizz = a*( bp2*( a_rh3p2x3*bbpc_rh3s - a_rh2p2x3*bc_rh2s ) - b*( a_rh3p2*(rh2+3.0*rh2*bbpc_rh3s) +
              a_rh2p2*(rh3-3.0*rh3*bc_rh2s) ) + 2.0*ap2*ln1 - bp3*( a_rh2p2*(a_rh2p2-2.0*c_rh2p2)*ln2_rh2 +
              a_rh3p2*(a_rh3p2-2.0*bpc_rh3p2)*ln3_rh3 ) )/24.0;

/* Ichixz/b */
     Ichixz = ( b*(rh3*a_rh2p2*(4.0*b-c-b*a_rh2p2x3)-rh2*a_rh3p2*(bpc-b*a_rh3p2x3)) -
               bp3*(a_rh2p2*(1.0+3.0*c_rh2p2) + a_rh3p2x3*a_rh3p2) - ap2*(b-c-c)*ln1 +
               bp2*(bc_rh2*a_rh2p2x3*ln2*c_rh2p2 - bbpc_rh3*a_rh3p2*(1.0+a_rh3p2x3)*ln3) )/24.0;

/* Ichiz/b */
     Ichiz = ( b*( a_rh2p2*( bmrh3 - bc_rh2*ln2 ) + a_rh3p2*( bmrh2 + bbpc_rh3*ln3 ) ) + ap2*ln1 )/6.0;

     cQmb = cQ-b;
     kQ2 = cQmb/aQ; kQ3 = cQ/aQ;
     kP2 = c/a; kP3 = bpc/a;

     c22kQ2 = c22*kQ2; c22kQ3 = c22*kQ3; c22_aQ = c22/aQ;
    
     intKh[0] = (kP2*c22kQ2*Ichizzz - Ichixxz + (kP2-c22kQ2)*Ichixzz)/bp2 - Ichixz + kP2*Ichizz; /* intKh(1,1) */
     intKh[1] = (Ichixxz - kP3*c22kQ2*Ichizzz - (kP3-c22kQ2)*Ichixzz)/bp2 + 2.0*Ichixz - (kP3-c22kQ2)*Ichizz + b*Ichiz; /* intKh(2,1) */
     intKh[2] = (c22kQ2*Ichizzz + Ichixzz)/dlt + b*Ichizz/a; /* intKh(3,1) */
     intKh[3] = (Ichixxz - (kP2-c22kQ3)*Ichixzz - kP2*c22kQ3*Ichizzz)/bp2; /* intKh(1,2) */
     intKh[4] = (kP3*c22kQ3*Ichizzz - Ichixxz  + (kP3-c22kQ3)*Ichixzz)/bp2 - Ichixz - c22kQ3*Ichizz; /* intKh(2,2) */
     intKh[5] = -(c22kQ3*Ichizzz + Ichixzz)/dlt; /* intKh(3,2) */
     intKh[6] = c22_aQ*(kP2*Ichizzz - Ichixzz)/b; /* intKh(1,3) */
     intKh[7] = c22_aQ*( b*Ichizz + (Ichixzz - kP3*Ichizzz)/b ); /* intKh(2,3) */
     intKh[8] = c22_aQ*Ichizzz/a; /* intKh(3,3) */

     intclN[0] = -c22*(kP2*Irhozz - Irhoxz)/b; /* intclN(1,1) */
     intclN[1] = -c22*((Irhoxz - kP3*Irhozz)/b + Irhoz); /* intclN(2,1) */
     intclN[2] = -c22*Irhozz/a; /* intclN(3,1) */

     intclM[0] = (kP2*Ichizzz - Ichixzz)/b; /* intclM(1,1) */
     intclM[1] = (Ichixzz - kP3*Ichizzz)/b + b*Ichizz; /* intclM(2,1) */
     intclM[2] = Ichizzz/a; /* intclM(3,1) */

     for (i=0; i<smx_nd_elt; i++) {intOme[i] = 0.0;  intOmeh[i] = 0.0;}

     for (i=0; i<2; i++)
     {
        ii = mx_nd_elt*(i+1); /* ii == Local Column stride */
	for (k=0; k<mx_nd_elt; k++)
	{ 
	   kk = k + ii; /* Column-major order in intclN and intclM matrices */
	   intclN[kk] = 0.0; intclM[kk] = 0.0;
	}
     }
     
     for (i=0; i<2*mx_nd_elt; i++) {intclNh[i] = 0.0; intclMh[i] = 0.0;}

     bhlf = 0.5*b;
     cpbhlf = c+bhlf; alpha2 = pi-theta[1]; alpha3 = pi+theta[0]; /* alpha1 = 0.0 */
     
     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/b; vecA[1] =  1.0/b; vecA[2] = 0.0;
     vecB[0] =  kQ2/b; vecB[1] = -kQ3/b; vecB[2] = 1.0/aQ;
     
     ah[0] = vecA[0]; ah[1] = (kQ2*sncf[0] - cscf[0])/b; ah[2] = (kQ2*sncf[1] - cscf[1])/b; /* ah(1,1) ; ah(2,1) ; ah(3,1) */
     ah[3] = vecA[1]; ah[4] = (cscf[0] - kQ3*sncf[0])/b; ah[5] = (cscf[1] - kQ3*sncf[1])/b; /* 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])/b; bh[2] = -(sncf[1] + kQ2*cscf[1])/b; /* bh(1,1) ; bh(2,1) ; bh(3,1) */
     bh[3] = -vecB[1]; bh[4] =  (sncf[0] + kQ3*cscf[0])/b; bh[5] =  (sncf[1] + kQ3*cscf[1])/b; /* 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 (i=0; i<ng1; i++) /* Loop over y  :: E' */
     {
        y = xi1[i];
	xh = c-cpbhlf*y; zh = a*(1.0-y);
        q1h = -c22*zh;
	p31h = xh*cscf[1] + q1h*sncf[1]; q3h = q1h*cscf[1] - xh*sncf[1]; /* cscf[1] = cos(alpha3); sncf[1] = sin(alpha3) */
        d3h = q3h*q3h;
	
        for (k=0; k<ng1; k++) /* Loop over x  :: E' */
	{
           x = xi1[k];
           xww = x*wwg1[i][k]; /* xww = x*wg1[i]*wg1[k] */
           xi = x*xh; zt = x*zh; q[0] = x*q1h; p31 = x*p31h; q[2] = x*q3h; /* p11 = xi */
	   p12 = b+xi; x3 = cQ+xi; z3 = aQ+q[0];
	   p22 = p12*cscf[0] + q[0]*sncf[0]; q[1] = q[0]*cscf[0] - p12*sncf[0]; /* cscf[0] = cos(alpha2); sncf[0] = sin(alpha2) */
	   p23 = x3*cscf[0] + z3*sncf[0]; p33 = x3*cscf[1] + z3*sncf[1];        /* cscf[1] = cos(alpha3); sncf[1] = sin(alpha3) */
	   zts = zt*zt; qs[0] = q[1]*q[1]; qs[1] = x*x*d3h; /* qs[0] = qs(2); qs[1] = qs(3) */

	   rho[0] = sqrt(xi*xi + zts); rho[1] = sqrt(p12*p12 + zts); rho[2] = sqrt(p33*p33 + q[2]*q[2]);

	   psi[0] = shfe1[i][k][0]; psi[1] = shfe1[i][k][1]; psi[2] = shfe1[i][k][2]; /* psi[0] = 0.5*x*y; psi[2] = x*(1.0-y) */
									              /* psi[1] = 1.0 + x*(0.5*y-1.0) */

           shc[1] = -(xi+c22kQ3*zt)/b; shc[2] = c22_aQ*zt;
	   shc[0] = 1.0 - (shc[1]+shc[2]); /* shc[0] = 1.0 + (xi+c22kQ2*zt)/b */

	   rhowv[0] = rho[1]-rho[2]; rhowv[1] = rho[2]-rho[0]; /* rhowv[0] = rhowv(2); rhowv[1] = rhowv(3)*/

	   chi[0] = log( (p22+rho[1])/(p23+rho[2]) ); /* chi[0] = chi(2) */
	   ch31 = p31+rho[0]; ch33 = p33+rho[2];
	   if ( (ch31 >= f_eps) && (ch33 >= f_eps) ) 
	        chi[1] = -log(ch31/ch33); /* chi[1] = chi(3) */
	   else
	   {
		z1 = q3h/p31h; z2 = q[2]/p33;
		z1s = z1*z1; z2s = z2*z2;
		chi[1] = -log( (p33/p31)*( (1.0 - 0.25*z1s*(1.0 - 0.5*z1s))/(1.0 - 0.25*z2s*(1.0 - 0.5*z2s)) ) );
	   }

           xwp[0] = xww*psi[0]; xwp[1] = xww*psi[1]; xwp[2] = xww*psi[2];
	   for (ii=0; ii<2; ii++)
	   {dchi[ii] = qs[ii]*chi[ii]; qrhowv[ii] = q[ii+1]*rhowv[ii];}

	   omega = q[1]*chi[0] + q[2]*chi[1]; /* chi[0] = chi(2); chi[1] = chi(3) */
           
           for (ii=0; ii<mx_nd_elt; ii++)
	   {
	      cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
		 l_k = kk + cl_i; /* Column-major order in intOmeh matrix */
		  intOmeh[l_k] += xwp[kk]*shc[ii]*omega;
              }
           }

           for (ii=0; ii<2; ii++)
	   {
              cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
                  l_k = kk + cl_i; /* Column-major order in intclNh and intclMh matrices */
		  intclNh[l_k] += xwp[kk]*qrhowv[ii];
		  intclMh[l_k] += xwp[kk]*dchi[ii];
              }
           }

        } /* End Loop over x  :: E' */
     } /* End Loop over y  :: E' */


     for (i=0; i<ng1; i++) /* Loop over y  :: E" */
     {
        y = xi1[i];
        xh = bhlf+cpbhlf*y; zh = a*y;
	q1h = -c22*zh;
	p22h = xh*cscf[0] + q1h*sncf[0]; q2h = q1h*cscf[0] - xh*sncf[0]; /* cscf[0] = cos(alpha2); sncf[0] = sin(alpha2) */
        d2h = q2h*q2h;

        for (k=0; k<ng1; k++) /* Loop over x  :: E" */
	{
           x = xi1[k];
           xww = x*wwg1[i][k]; /* xww = x*wg1[i]*wg1[k] */
           xi = x*xh; zt = x*zh; q[0] = x*q1h; p22 = x*p22h; q[1] = x*q2h; /* p12 = xi */
	   p11 = xi-b; x3 = cQmb+xi; z3 = aQ+q[0];
	   p23 = x3*cscf[0] + z3*sncf[0]; p33 = x3*cscf[1] + z3*sncf[1];
	   p31 = p11*cscf[1] + q[0]*sncf[1]; q[2] = q[0]*cscf[1] - p11*sncf[1]; /* cscf[1] = cos(alpha3); sncf[1] = sin(alpha3) */
	   zts = zt*zt; qs[0] = x*x*d2h; qs[1] = q[2]*q[2]; /* qs[0] = qs(2); qs[1] = qs(3) */

	   rho[0] = sqrt(p11*p11 + zts); rho[1] = sqrt(xi*xi + zts); rho[2] = sqrt(p33*p33 + qs[1]);

	   psi[0] = shfe2[i][k][0]; psi[1] = shfe2[i][k][1]; psi[2] = shfe2[i][k][2]; /* psi[0] = 1.0-0.5*x*(1.0+y); psi[2] = x*y */
									              /* psi[1] = 0.5*x*(1.0-y) */

           shc[0] = (xi+c22kQ2*zt)/b; shc[2] = c22_aQ*zt;
	   shc[1] = 1.0 -(shc[0]+shc[2]); /* shc[1] = 1.0 - (xi+c22kQ3*zt)/b */

	   rhowv[0] = rho[1]-rho[2]; rhowv[1] = rho[2]-rho[0]; /* rhowv[0] = rhowv(2); rhowv[1] = rhowv(3)*/

	   chi[0] = log( (p22+rho[1])/(p23+rho[2]) ); /* chi[0] = chi(2) */
	   ch31 = p31+rho[0]; ch33 = p33+rho[2];
	   if ( (ch31 >= f_eps) && (ch33 >= f_eps) )
		chi[1] = -log(ch31/ch33); /* chi[1] = chi(3) */
	   else
	   {
		z1 = q[2]/p31; z2 = q[2]/p33;
		z1s = z1*z1; z2s = z2*z2;
		chi[1] = -log( (p33/p31)*( (1.0 - 0.25*z1s*(1.0 - 0.5*z1s))/(1.0 - 0.25*z2s*(1.0 - 0.5*z2s)) ) );
	   }

           xwp[0] = xww*psi[0]; xwp[1] = xww*psi[1]; xwp[2] = xww*psi[2];

	   for (ii=0; ii<2; ii++)
	   {dchi[ii] = qs[ii]*chi[ii]; qrhowv[ii] = q[ii+1]*rhowv[ii];}
	   
	   omega = q[1]*chi[0] + q[2]*chi[1]; /* chi[0] = chi(2); chi[1] = chi(3) */
	   
           for (ii=0; ii<mx_nd_elt; ii++)
	   {
	      cl_i = mx_nd_elt*ii; /* cl_i == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
		 l_k = kk + cl_i; /* Column-major order in intOme matrix */
		 intOme[l_k] += xwp[kk]*shc[ii]*omega;
              }
           }
           
           for (ii=0; ii<2; ii++)
	   {
	      jj = mx_nd_elt*(ii+1); /* jj == Local Column stride */
	      for (kk=0; kk<mx_nd_elt; kk++)
	      {
		    j = kk + jj; /* Column-major order in intclN, intclM, intGN3tmp */
		    intclN[j] += xwp[kk]*qrhowv[ii];
		    intclM[j] += xwp[kk]*dchi[ii];
              }
           }
           
        } /* End Loop over x :: E" */
     } /*  End Loop over y  :: E" */


     dltHlf = 0.5*dlt;
    
    for (k=0; k<2; k++)
    {
       kk = mx_nd_elt*k; /* kk == Local Column stride */
       l_k = mx_nd_elt + kk; /* l_k == Local Column stride */
       for (i=0; i<mx_nd_elt; i++)
       {
             ii = i + kk; /* Column-major order in intclNh and intclMh matrices */
	     cl_i = i + l_k; /* Column-major order in intclN and intclM matrices */
	     intclN[cl_i] = dltHlf*(intclN[cl_i] +  intclNh[ii]);
	     intclM[cl_i] = dltHlf*(intclM[cl_i] +  intclMh[ii]);
       }
    }

/*** int_f = matmul(intclN,ah) - matmul(intclM,bh) */
     tr = 'n'; dabh = 3; alp = 1.0; bet = 0.0;
     dgemm_(&tr,&tr,&mx_nd_elt,&dabh,&dabh,&alp,intclM,&mx_nd_elt,bh,&dabh,&bet,int_f,&mx_nd_elt); /* int_f = matmul(intclM,bh) */
     bet = -1.0;
     dgemm_(&tr,&tr,&mx_nd_elt,&dabh,&dabh,&alp,intclN,&mx_nd_elt,ah,&dabh,&bet,int_f,&mx_nd_elt); /* int_f = matmul(intclN,ah) - int_f */

    for (k=0; k<mx_nd_elt; k++)
    {
       kk = mx_nd_elt*k; /* kk == Local Column stride */ 
       for (i=0; i<mx_nd_elt; i++)
       {
	  ii = i + kk; /* Column-major order in intOme, intOmeh and intKh matrices */
	  intOme[ii] = dltHlf*(intOme[ii] + intOmeh[ii]) - c22*intKh[ii];
       }
    }

    for (k=0; k<mx_nd_elt; k++)
    {
       kk = mx_nd_elt*k; /* kk == Local Column stride */ 
       for (i=0; i<mx_nd_elt; i++)
       {
	  ii = i + kk; /* Column-major order in int_f, int_p, int_r and intOme matrices viewed as mx_nd_elt by mx_nd_elt matrices */
	  int_f[ii] = 0.5*int_f[ii] + intOme[ii]; /* Weakly-singular kernel ==> G */
	  int_p[ii] = 0.0;                        /* Singular kernel ==> H */
	  int_r[ii] = 0.0;                        /* Reverse kernel ==> H */
       }
    }

}
