
/* ===purpose=== */

/**********************************************************************************************************************************/
/********************************  COLLOCATION BEM for 3D LAPLACE EQUATION: SINGULAR FORMULATION  *********************************/
/***************************************  3-NODED TRIANGULAR ELEMENT: ANALYTIC INTEGRATION  ***************************************/
/***********************************************  PIECEWISE CONSTANT APPROXIMATION  ***********************************************/
/*******************************************************  Example routine  ********************************************************/
/**********************************************************************************************************************************/

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


#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include "cbem_lap.h"
#include "cbem_util.h"


int main (void)
{
   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][k] == Global index of the k-th node on the boundary element i */
   extern double **bnd;        /* bnd[k][0:2] = Cartesian coordinates of the k-th boundary node */
   extern double **repnd;      /* repnd[i][0:2] == Cartesian coordinate of the centroid of the i-th boundary element */
   extern double *phi,*flx;    /* phi == Vector containing boundary potentials */
                               /* flx == Vector containing boundary fluxes */

   char *InputFileData = "bndata.dat", *InputFileParams = "cbem_lap_par.dat";
   int i,k,j,nintpts; /* nintpts == Number of interior points */
   clock_t tm0, tm1;  /* time variables */
   double *extsol;    /* Exact solution */
   double **intpts;   /* intpts[i][0:2] == Cartesian coordinates of the i-th interior (or field) point */
   double *pot_ip;    /* pot_ip[i] == Potential at the i-th interior point */
   double r12[3],r13[3];
   double xeQ[mx_nd_elt][3]; /* xeQ[k][0:2] == Cartesian coordinates of the k-th vertex on the current surface triangle */
   double e1[3],e2[3],e3[3]; /* Orthonormal local basis associated with the current surface triangle */
   double Perr,Ferr,ax,nrm_Exs;
   FILE *fp;



       tm0 = clock();    /* Initial time */
       cbem_lap_srf_eval(InputFileParams,InputFileData,tm0);    /* Solve the Singular BIE for the Laplace equation */
       tm1 = clock();
       printf("Time == %#.14G\n",((double)(tm1-tm0))/CLOCKS_PER_SEC);  /* cpu time used */
       
       printf(" >>>  Write the boundary potential and flux at Discrete boundary nodes  <<<\n");
       
       if ( (extsol = (double *)malloc(nbelt*sizeof(double))) == NULL )   /* If extsol is not successfully allocated */
       {printf("lap_ex.c: Allocate array \"extsol\" failed\n"); exit(1);}

       if ((fp = fopen("potl.dat","w")) != NULL)
       {
          fprintf(fp,"  phi\n");
          fprintf(fp," %s %9s %15s %15s %17s %16s %13s\n","Nodes","x" ,"y","z","CBEM","Exact","Error");
	  
	  for (i=0; i<nbelt; i++)    /* Loop over all boundary elements */
	  {
	     extsol[i] = exp(repnd[i][0])*sin(repnd[i][2]) + exp(repnd[i][2])*cos(repnd[i][1]);   /* Exact solution */
	     fprintf(fp,"%5d %15.8lf %15.8lf %15.8lf %15.8lf %15.8lf %15.8E\n",
	             i, repnd[i][0], repnd[i][1], repnd[i][2], phi[i], extsol[i], fabs(extsol[i]-phi[i]));
	  }
	  
	  fclose(fp);

          Perr = 0.0; nrm_Exs = 0.0;
	  for (i=0; i<nbelt; i++)    /* Loop over all boundary elements */
	  {
	     ax = phi[i]-extsol[i];
	     Perr += ax*ax; nrm_Exs += extsol[i]*extsol[i];
          }
	  Perr = sqrt(Perr/nrm_Exs);  /* Perr = sqrt(dot_product(phi-extsol,phi-extsol)/dot_product(extsol,extsol)) */
	  printf("Relative Error on Potential == %.17E\n",Perr);
       }
       else
       {fprintf(stderr, "\nError opening file \"%s\".\n","potl.dat"); exit(1);}


       if ((fp = fopen("flux.dat","w")) != NULL)
       {
          fprintf(fp,"  flux\n");
          fprintf(fp," %s %9s %15s %15s %17s %16s %13s\n","Nodes","x" ,"y","z","CBEM","Exact","Error");
	  
	  for (i=0; i<nbelt; i++)    /* Loop over all boundary elements */
	  {
	     for (k=0; k<mx_nd_elt; k++)    /* Loop over the vertices of the i-th element */
	        for (j=0; j<3; j++)    /* Loop over all components */
                   xeQ[k][j] = bnd[belt[i][k]][j];  /* xeQ[k][0:2] == Cartesian coordinates of the k-th vertex of element i  */
	                                            /* belt[i][k] == Global index of the k-th node on the boundary element i */
	     
	     for (j=0; j<3; j++)    /* Loop over all components */
	     {
	        r12[j] = xeQ[1][j] - xeQ[0][j];    /* y2-y1 <== Side 1 of element i */
		r13[j] = xeQ[2][j] - xeQ[0][j];    /* y3-y1 <== Side 3 of element i */
	     }
	     
	     ortho_comp_basis(r12,r13,e1,e2,e3); /* Deternime the orthonormal local basis associated with element i */

	     extsol[i] = exp(repnd[i][0])*sin(repnd[i][2])*e3[0] - exp(repnd[i][2])*sin(repnd[i][1])*e3[1] +
	                (exp(repnd[i][0])*cos(repnd[i][2]) + exp(repnd[i][2])*cos(repnd[i][1]))*e3[2];   /* Exact solution */
	     fprintf(fp,"%5d %15.8lf %15.8lf %15.8lf %15.8lf %15.8lf %15.8E\n",
	             i, repnd[i][0], repnd[i][1], repnd[i][2], flx[i], extsol[i], fabs(extsol[i]-flx[i]));
	  }
	  
	  fclose(fp);

          Ferr = 0.0; nrm_Exs = 0.0;
	  for (i=0; i<nbelt; i++)
	  {
	     ax = flx[i]-extsol[i];
	     Ferr += ax*ax; nrm_Exs += extsol[i]*extsol[i];
          }
	  Ferr = sqrt(Ferr/nrm_Exs);  /* Ferr = sqrt(dot_product(flx-extsol,flx-extsol)/dot_product(extsol,extsol)) */
	  printf("Relative Error on Flux ==  %.17E\n",Ferr);
       }
       else
       {fprintf(stderr, "\nError opening file \"%s\".\n","flux.dat"); exit(1);}

       printf("Relative Error on Potential & Flux == %.17E\n",0.5*(Perr+Ferr));
       free(extsol);

/*** Evaluation at interior point */
       nintpts = 3;
       if ( (intpts = (double **)malloc(nintpts*sizeof(double *))) != NULL )  /* If intpts is successfully allocated */
       {
           for (i=0; i<nintpts; i++)    /* Loop over all interior points */
	       if ( (intpts[i] = (double *)malloc(3*sizeof(double))) == NULL )   /* If intpts[i] is not successfully allocated */
	       {printf("lap_ex.c: Allocate array \"intpts[%d]\" failed\n",i); exit(1);}
       }
       else
       {printf("lap_ex.c: Allocate array \"intpts\" failed\n"); exit(1);}

       if ( (pot_ip = (double *)malloc(nintpts*sizeof(double))) == NULL )   /* If pot_ip is not successfully allocated */
       {printf("lap_ex.c: Allocate array \"pot_ip\" failed\n"); exit(1);}

       intpts[0][0] = 0.000001; intpts[0][1] = 0.0001; intpts[0][2] = 0.999;
       intpts[1][0] = 0.100;    intpts[1][1] = 0.300;  intpts[1][2] = 0.700;
       intpts[2][0] = 0.500;    intpts[2][1] = 0.500;  intpts[2][2] = 0.500;
    
       cbem_lap_fld_eval(nintpts,intpts,pot_ip);  /* Compute the potential at interior points */

       printf("****Evaluation at interior points****\n");
       printf("        CBEM                   Exact\n");
       for (i=0; i<nintpts; i++)
       printf(" %.16lf        %.16lf\n",pot_ip[i],exp(intpts[i][0])*sin(intpts[i][2]) + exp(intpts[i][2])*cos(intpts[i][1]));

       for (i=0; i<nintpts; i++) free(intpts[i]);
       free(intpts); free(pot_ip);

/*** Deallocate remaining Global arrays */
       free(phi); free(flx); /* Deallocate potential and flux vectors */
       
       for (i=0; i<nbnd; i++) free(bnd[i]);  /* Deallocate memory block for all boundary nodes */
       free(bnd);
       
       for (i=0; i<nbelt; i++) /* Loop over all boundary elements */
       {
          free(belt[i]); free(repnd[i]);
       }
       free(repnd); free(belt);
/*** End Deallocate remaining Global arrays */

       tm1 = clock();
       printf("Time == %#.14G\n",((double)(tm1-tm0))/CLOCKS_PER_SEC);   /* cpu time used */
       
       return 0;

}
