
/* ===purpose=== */

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

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


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


int main (void)
{

/* Global variables */
   extern int nbnd;          /* nbnd == Total number of boundary nodes */
   extern double **bnd;      /* bnd[k][0:2] = Cartesian coordinates of the k-th boundary node */
   extern double *phi, *flx; /* phi == Vector containing boundary potentials, flx == Vector containing boundary fluxes */

/* Local variables */
   char *InputFileData = "bndata.dat", *InputFileParams = "gbem_lap_par.dat";
   int i,k,l,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 Perr,Ferr,ax,nrm_Exs;
   FILE *fp;



       tm0 = clock(); /* Initial time */
       gbem_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(nbnd*sizeof(double))) == NULL ) /* If extsol is not successfully allocated */
       {printf("lap_ex: 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","GBEM","Exact","Error");
	  
	  for (i=0; i<nbnd; i++) /* Loop over all boundary nodes */
	  {
	     extsol[i] = exp(bnd[i][0])*sin(bnd[i][2]) + exp(bnd[i][2])*cos(bnd[i][1]); /* Exact solution */
	     fprintf(fp,"%5d %15.8lf %15.8lf %15.8lf %15.8lf %15.8lf %15.8E\n",
	             i, bnd[i][0], bnd[i][1], bnd[i][2], phi[i], extsol[i], fabs(extsol[i]-phi[i]));
	  }
	  
	  fclose(fp);

          Perr = 0.0; nrm_Exs = 0.0;
	  for (i=0; i<nbnd; i++) /* Loop over all boundary nodes */
	  {
	     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","GBEM","Exact","Error");
	  
	  l=nbnd/6; /* l==Number of boundary nodes per face of the cube */
	  for (i=1; i<=6; i++) /* loop over all faces */
	  {
	     for (k=(i-1)*l; k<i*l; k++) /* Loop over all boundary nodes on the i-th face */
	     {
		if (i==1) /* face: x=0 */
		   extsol[k] = -exp(bnd[k][0])*sin(bnd[k][2]);
		else if(i==2) /* face: x=1 */
		   extsol[k] =  exp(bnd[k][0])*sin(bnd[k][2]);
		else if(i==3) /* face: y=0 */
		   extsol[k] =  exp(bnd[k][2])*sin(bnd[k][1]);
		else if(i==4) /* face: y=1 */
		   extsol[k] = -exp(bnd[k][2])*sin(bnd[k][1]);
		else if(i==5) /* face: z=0 */
		   extsol[k] = -exp(bnd[k][0])*cos(bnd[k][2]) - exp(bnd[k][2])*cos(bnd[k][1]);
		else if(i==6) /* face: z=1 */
		   extsol[k] =  exp(bnd[k][0])*cos(bnd[k][2]) + exp(bnd[k][2])*cos(bnd[k][1]);

	        fprintf(fp,"%5d %15.8lf %15.8lf %15.8lf %15.8lf %15.8lf %15.8E\n",
	                k, bnd[k][0], bnd[k][1], bnd[k][2], flx[k], extsol[k], fabs(extsol[k]-flx[k]));
	     }
	  }
	  
	  fclose(fp);

          Ferr = 0.0; nrm_Exs = 0.0;
	  for (i=0; i<nbnd; 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: Allocate array \"intpts[%d]\" failed\n",i); exit(1);}
       }
       else
       {printf("lap_ex: 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: 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;
    
       gbem_lap_fld_eval(nintpts,intpts,pot_ip); /* Compute the potential at interior points */

       printf("****Evaluation at interior points****\n");
       printf("        GBEM                   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 */
       gbem_lap_del(); /* Deallocate remaining global arrays associated with the GALERKIN BEM */
/*** End Deallocate remaining Global arrays */

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

}
