#define RCSID "$Id: Cal_FMMAnalyticalIntegral.c,v 1.10 2006/02/26 00:42:53 geuzaine Exp $"
/*
 * Copyright (C) 1997-2006 P. Dular, C. Geuzaine
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 *
 * Please report all bugs and problems to <getdp@geuz.org>.
 *
 * Contributor(s):
 *   Ruth Sabariego
 */

#include "GetDP.h"
#include "CurrentData.h"
#include "Numeric.h"
#include "Tools.h"
#include "Cal_FMMAnalyticalIntegral.h"


void GF_FMMLaplacexForm( struct Element           * Element, 
			 struct QuantityStorage   * QuantityStorage_P,
			 int                        Nbr_Dof, 
			 void                       (*xFunctionBF) (), List_T *NumDof_L,
			 struct Value                Val,
			 double                   ** M ){

  int      i, j, id, NbrDir ;
  double   xs[MAX_NODES], ys[MAX_NODES] ;
  double   r0, phi0=0., r1, phi1=0., p0, p1, d, phi=0., cphi, sphi, Re, Im, cte=0., R=0. ;
  double   ValRe = 1., ValIm = 0., Re2, Im2 ;

  GetDP_Begin("GF_FMMLaplacexForm");

  NbrDir = Current.FMM.N ;
  /* Watch out: Only SCALAR ctes are considered */
  
  if (Val.Type == SCALAR){
    ValRe = Val.Val[0];
    ValIm = Val.Val[MAX_DIM];
  }

  switch ( _2D ) {
  case _2D : 
    switch (Element->ElementSource->Type) {
    case LINE:
      xs[0] = Element->ElementSource->x[0] ; ys[0] = Element->ElementSource->y[0] ;
      xs[1] = Element->ElementSource->x[1] ; ys[1] = Element->ElementSource->y[1] ;
      
      d = sqrt(SQU(xs[0]-xs[1]) + SQU(ys[0]-ys[1])) ;

      r0 = sqrt(SQU(xs[0]-Current.FMM.Xgc) + SQU(ys[0]-Current.FMM.Ygc)) ;
      r1 = sqrt(SQU(xs[1]-Current.FMM.Xgc) + SQU(ys[1] -Current.FMM.Ygc)) ;

      switch (Current.FMM.Flag_GF) {
      case FMM_AGGREGATION :
	if(!Current.FMM.Flag_Normal){
	  phi = atan2(ys[1]-ys[0], xs[1]-xs[0]) ;
	  phi0 = atan2(ys[0] - Current.FMM.Ygc, xs[0] - Current.FMM.Xgc) ;    
	  phi1 = atan2(ys[1] - Current.FMM.Ygc, xs[1] - Current.FMM.Xgc) ; 
	}
	else{
	  /* Watch out: the analytical integration with NPxGradLaplace 
	     is solo posible for Aggregation */
	  phi = atan2(-ys[1]+ys[0], -xs[1]+xs[0]) ;
	  phi0 = atan2(-ys[0] + Current.FMM.Ygc, -xs[0] + Current.FMM.Xgc) ;    
	  phi1 = atan2(-ys[1] + Current.FMM.Ygc, -xs[1] + Current.FMM.Xgc) ; 
	}
	cte = -ONE_OVER_TWO_PI ;
	R = Current.FMM.Rsrc ;
	break;
      case FMM_DISAGGREGATION :
	phi = atan2(-ys[1]+ys[0], -xs[1]+xs[0]) ;
	phi0 = atan2(-ys[0] + Current.FMM.Ygc, -xs[0] + Current.FMM.Xgc) ;    
	phi1 = atan2(-ys[1] + Current.FMM.Ygc, -xs[1] + Current.FMM.Xgc) ; 
	cte = 1. ;
	R = Current.FMM.Robs ;
	break;
      }

      cphi = cos(phi) ;
      sphi = sin(phi) ;
      
      for (j = 0 ; j < Nbr_Dof ; j++) {
	if(QuantityStorage_P->BasisFunction[j].Dof->Type == DOF_UNKNOWN){
	  i = List_ISearch(NumDof_L, 
			   &QuantityStorage_P->BasisFunction[j].Dof->Case.Unknown.NumDof,
			   fcmp_int) ;
	  if (i != -1){
	    p0 = p1 = cte*R/d ;
	    for (id = 0 ; id < NbrDir ; id++){
	      p0 *= r0/R ;
	      p1 *= r1/R ;
	      Re = (p1 * cos((id+1)*phi1) - p0 * cos((id+1)*phi0))/(id+1);
	      Im = (p1 * sin((id+1)*phi1) - p0 * sin((id+1)*phi0))/(id+1);
	      Re2 = Re * ValRe - Im * ValIm ;
	      Im2 = Re * ValIm + Im * ValRe ;
  	      M[i][2*id  ] =  Re2*cphi + Im2*sphi ;
	      M[i][2*id+1] = -Re2*sphi + Im2*cphi ;
	    }
	  }
	  else  Msg(GERROR, "Wrong NumDof %d for Analytical Aggreg", 
		    QuantityStorage_P->BasisFunction[j].Dof->Case.Unknown.NumDof) ;
	}
      } 
      break;
    default:
      Msg(GERROR, "Element not implemented for Analytical Aggreg") ;
    }/* Element type */
    break;
  default:
    Msg(GERROR, "Wrong dimension for Analytical Aggreg") ;
  }
  
  GetDP_End;
  
}






syntax highlighted by Code2HTML, v. 0.9.1