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

void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
void dgetrs_(char *trans, int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);


void gbem_lap_solv(void)
{

/* ===purpose=== */

/**********************************************************************************************************************************/
/**********************************  GALERKIN BEM for 3D LAPLACE EQUATION: SINGULAR FORMULATION  **********************************/
/************************************  3-NODED TRIANGULAR ELEMENT: SEMI-ANALYTIC INTEGRATION  *************************************/
/************************************************  PIECEWISE LINEAR APPROXIMATION  ************************************************/
/***************************************************  Solve the Discretized BIE  **************************************************/
/**********************************************************************************************************************************/

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


/* Global variables */
   extern int nbnd;             /* nbnd == Total number of boundary nodes */
   extern int *ndbc;            /* ndbc[i] = {0,1} ==> {Dirichlet,Neunamm} boundary condition is prescribed at the i-th boundary node */
   extern int nmltplnd;         /* nmltplnd == Number of Multiple nodes (or Number of class of Multiple Nodes) on the boundary mesh */
   extern mltndinfo_t *mltplnd; /* mltplnd[k] == Structure containing information about the k-th class of multiple nodes */
   extern double *g;            /* g == Discretized BIE matrix or Left-hand side of the BEM equation */
   extern double *rhs;          /* rhs == Right-hand side of the Discretized BIE */
   extern double *phi, *flx;    /* phi == Vector containing boundary potentials, flx == Vector containing boundary fluxes */

/* Local variables */
   char tr;
   int k,j,info,nrhs;
   int *ipiv;



    printf("           >>>  LU Decomposition of the BIE matrix <<<\n");
    
    if ( (ipiv = (int *)malloc(nbnd*sizeof(int))) != NULL ) /* If ipiv is successfully allocated */
       dgetrf_(&nbnd,&nbnd,g,&nbnd,ipiv,&info); /* LU Decomposition */
    else
    {printf("gbem_lap_solv: Allocate array \"ipiv\" failed\n"); exit(1);}

    printf("           >>>  Back-substitution  <<<\n");

    tr = 'n'; nrhs = 1;
    dgetrs_(&tr,&nbnd,&nrhs,g,&nbnd,ipiv,rhs,&nbnd,&info); /* Back-substitution */
    free(ipiv); free(g);
    
    printf("err == %d\n",info);

    for (k=0; k<nbnd; k++)
       if ( ndbc[k] == 0 ) /* ndbc[k] = 0 ==> Dirichlet data is prescribed at the k-th boundary node */
          flx[k] = rhs[k];
       else /* ndbc[k] = 1 ==> Neumann data is prescribed at the k-th boundary node */
          phi[k] = rhs[k];  

    free(rhs); free(ndbc);

    if (nmltplnd != 0)
    {
         for (k=0; k<nmltplnd; k++) /* Loop over all class of multiple nodes */
	 {
	    if (mltplnd[k].pnd != -1) /* if there exist in the k-th class a boundary node with Global */
	                              /* index mltplnd[k].pnd at which the potential is prescribed    */
	       for (j=0; j<mltplnd[k].nn; j++) /* Loop over all multiple nodes in the k-th class */
		  phi[mltplnd[k].id[j]] = phi[mltplnd[k].pnd]; /* Retrieve prescribed potential from the boundary node mltplnd[k].pnd */
	    else /* there is no potential node in the k-th class of equivalence: ONLY flux nodes in the k-th class */
	       for (j=1; j<mltplnd[k].nn; j++) /* Loop over the remaining nodes in the k-th class of multiple nodes */
		  phi[mltplnd[k].id[j]] = phi[mltplnd[k].id[0]]; /* Assign potential by continuity */
	    free(mltplnd[k].id);
         }
        free(mltplnd);
    }

}
