sol_elliptic_boundary.C

00001 /*
00002  *   Copyright (c) 2003 Philippe Grandclement
00003  *                      Jose Luis Jaramillo
00004  *                      Francois Limousin
00005  *
00006  *   This file is part of LORENE.
00007  *
00008  *   LORENE is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License version 2
00010  *   as published by the Free Software Foundation.
00011  *
00012  *   LORENE is distributed in the hope that it will be useful,
00013  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  *   GNU General Public License for more details.
00016  *
00017  *   You should have received a copy of the GNU General Public License
00018  *   along with LORENE; if not, write to the Free Software
00019  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  */
00022 
00023 char sol_elliptic_boundary_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/sol_elliptic_boundary.C,v 1.2 2008/08/20 15:03:55 n_vasset Exp $" ;
00024 
00025 /*
00026  * $Id: sol_elliptic_boundary.C,v 1.2 2008/08/20 15:03:55 n_vasset Exp $
00027  * $Log: sol_elliptic_boundary.C,v $
00028  * Revision 1.2  2008/08/20 15:03:55  n_vasset
00029  * Correction on how the boundary condition is imposed
00030  *
00031  * Revision 1.1  2005/06/09 08:01:05  f_limousin
00032  * Implement a new function sol_elliptic_boundary() and
00033  * Vector::poisson_boundary(...) which solve the vectorial poisson
00034  * equation (method 6) with an inner boundary condition.
00035  *
00036  * 
00037  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/sol_elliptic_boundary.C,v 1.2 2008/08/20 15:03:55 n_vasset Exp $
00038  *
00039  */
00040 
00041 // Header C : 
00042 #include <stdlib.h>
00043 #include <math.h>
00044 
00045 // Headers Lorene :
00046 #include "param_elliptic.h"
00047 #include "tbl.h"
00048 #include "mtbl_cf.h"
00049 #include "map.h"
00050           
00051  
00052         //----------------------------------------------
00053        //       Version Mtbl_cf
00054       //----------------------------------------------
00055 
00056 
00057 
00058 Mtbl_cf elliptic_solver_boundary  (const Param_elliptic& ope_var, const Mtbl_cf& source, 
00059                    const Mtbl_cf& bound, double fact_dir, double fact_neu )  {
00060    // Verifications d'usage sur les zones
00061   int nz = source.get_mg()->get_nzone() ;
00062   assert (nz>1) ;
00063   assert (source.get_mg()->get_type_r(0) == RARE) ;
00064   assert (source.get_mg()->get_type_r(nz-1) == UNSURR) ;
00065   for (int l=1 ; l<nz-1 ; l++)
00066     assert(source.get_mg()->get_type_r(l) == FIN) ;
00067    
00068   // donnees sur la zone
00069   int nr, nt, np ;
00070   
00071   //Rangement des valeurs intermediaires 
00072   Tbl *so ;
00073   Tbl *sol_hom ;
00074   Tbl *sol_part ;
00075    
00076   
00077   // Rangement des solutions, avant raccordement
00078   Mtbl_cf solution_part(source.get_mg(), source.base) ;
00079   Mtbl_cf solution_hom_un(source.get_mg(), source.base) ;
00080   Mtbl_cf solution_hom_deux(source.get_mg(), source.base) ;
00081   Mtbl_cf resultat(source.get_mg(), source.base) ;
00082 
00083   solution_part.annule_hard() ;
00084   solution_hom_un.annule_hard() ;
00085   solution_hom_deux.annule_hard() ;
00086   resultat.annule_hard() ;
00087 
00088   // Computation of the SP and SH's in every domain ...
00089   int conte = 0 ;
00090   for (int zone=0 ; zone<nz ; zone++) {
00091 
00092     nr = source.get_mg()->get_nr(zone) ;
00093     nt = source.get_mg()->get_nt(zone) ;
00094     np = source.get_mg()->get_np(zone) ;
00095 
00096     for (int k=0 ; k<np+1 ; k++)
00097       for (int j=0 ; j<nt ; j++) {
00098 
00099     if (ope_var.operateurs[conte] != 0x0) {
00100 
00101       // Calcul de la SH
00102       sol_hom = new Tbl(ope_var.operateurs[conte]->get_solh()) ;
00103       
00104       //Calcul de la SP
00105       so = new Tbl(nr) ;
00106       so->set_etat_qcq() ;
00107       for (int i=0 ; i<nr ; i++)
00108         so->set(i) = source(zone, k, j, i) ;
00109       
00110       sol_part = new Tbl(ope_var.operateurs[conte]->get_solp(*so)) ;
00111       
00112       // Rangement dans les tableaux globaux ;
00113       for (int i=0 ; i<nr ; i++) {
00114         solution_part.set(zone, k, j, i) = (*sol_part)(i) ;
00115         if (sol_hom->get_ndim()==1)
00116           solution_hom_un.set(zone, k, j, i) = (*sol_hom)(i) ;
00117         else
00118           {
00119         solution_hom_un.set(zone, k, j, i) = (*sol_hom)(0,i) ;
00120         solution_hom_deux.set(zone, k, j, i) = (*sol_hom)(1,i) ;
00121           }
00122       }
00123       
00124       delete so ;
00125       delete sol_hom ;
00126       delete sol_part ;
00127       
00128     }
00129     conte ++ ;
00130       }
00131   }
00132 
00133 
00134   //-------------------------------------------------
00135   // ON EST PARTI POUR LE RACCORD (Be careful  ....)
00136   //-------------------------------------------------
00137   
00138   // C'est pas simple toute cette sombre affaire...
00139   // Que de cas meme nombre de points dans chaque domaines...
00140 
00141   int start = 0 ;
00142   for (int k=0 ; k<source.get_mg()->get_np(0)+1 ; k++)
00143     for (int j=0 ; j<source.get_mg()->get_nt(0) ; j++) {
00144       if (ope_var.operateurs[start] != 0x0) {
00145     
00146     int taille = 2*nz - 3 ;
00147     Matrice systeme (taille, taille) ;
00148     systeme.set_etat_qcq() ;
00149     for (int i=0 ; i<taille ; i++)
00150       for (int j2=0 ; j2<taille ; j2++)
00151         systeme.set(i,j2) = 0 ;
00152     Tbl sec_membre (taille) ;
00153     sec_membre.set_etat_qcq() ;
00154     for (int i=0 ; i<taille ; i++)
00155       sec_membre.set(i) = 0 ;
00156     
00157     //----------
00158     //  BOUNDARY :
00159     //----------
00160     conte = start ;
00161 
00162     // Boundary value at an angular point
00163     
00164     // Setting the right hand side term
00165 
00166     sec_membre.set(0) -= bound.val_in_bound_jk(1, j, k)/sqrt(2.) ; //Relevant value is in the first shell and only in the first coefficient
00167 
00168 
00169     //--------------
00170     // FIRST SHELL :
00171     //--------------
00172     
00173     int l_1=1 ;
00174     
00175     // On se met au bon endroit :
00176     int np_prec_1 = source.get_mg()->get_np(l_1-1) ;
00177     int nt_prec_1 = source.get_mg()->get_nt(l_1-1) ;
00178     conte += (np_prec_1+1)*nt_prec_1 ;
00179 
00180     systeme.set(0, 0) = fact_dir * (-ope_var.G_minus(l_1) * 
00181                     ope_var.operateurs[conte]->val_sh_one_minus() ) 
00182         + fact_neu * 
00183      ( -ope_var.dG_minus(l_1)*ope_var.operateurs[conte]->val_sh_one_minus()-  
00184       ope_var.G_minus(l_1)*ope_var.operateurs[conte]->der_sh_one_minus() );
00185       
00186     systeme.set(0, 1) = fact_dir * (- ope_var.G_minus(l_1) * 
00187       ope_var.operateurs[conte]->val_sh_two_minus() ) + fact_neu *
00188       (-ope_var.dG_minus(l_1)*ope_var.operateurs[conte]->val_sh_two_minus()-  
00189       ope_var.G_minus(l_1)*ope_var.operateurs[conte]->der_sh_two_minus() ) ;
00190 
00191     //Completing the right hand side term
00192     sec_membre.set(0) += fact_dir * (ope_var.F_minus(l_1,k,j) + 
00193       ope_var.G_minus(l_1) * ope_var.operateurs[conte]->val_sp_minus() ) +
00194       fact_neu * ( ope_var.dF_minus(l_1,k,j) + 
00195       ope_var.dG_minus(l_1) * ope_var.operateurs[conte]->val_sp_minus() + 
00196       ope_var.G_minus(l_1) * ope_var.operateurs[conte]->der_sp_minus() )   ;
00197 
00198     
00199     // Valeurs en +1 :
00200     systeme.set(2*l_1-1, 2*l_1-2) = ope_var.G_plus(l_1) * 
00201       ope_var.operateurs[conte]->val_sh_one_plus() ;
00202     systeme.set(2*l_1-1, 2*l_1-1) = ope_var.G_plus(l_1) * 
00203       ope_var.operateurs[conte]->val_sh_two_plus() ;
00204     systeme.set(2*l_1, 2*l_1-2) = 
00205       ope_var.dG_plus(l_1)*ope_var.operateurs[conte]->val_sh_one_plus()+  
00206       ope_var.G_plus(l_1)*ope_var.operateurs[conte]->der_sh_one_plus() ;
00207     systeme.set(2*l_1, 2*l_1-1) =
00208         ope_var.dG_plus(l_1)*ope_var.operateurs[conte]->val_sh_two_plus()+
00209       ope_var.G_plus(l_1)*ope_var.operateurs[conte]->der_sh_two_plus() ;
00210     
00211       sec_membre.set(2*l_1-1) -=  ope_var.F_plus(l_1,k,j) + 
00212         ope_var.G_plus(l_1) * ope_var.operateurs[conte]->val_sp_plus();
00213       sec_membre.set(2*l_1) -=  ope_var.dF_plus(l_1,k,j) + 
00214         ope_var.dG_plus(l_1) * ope_var.operateurs[conte]->val_sp_plus() + 
00215         ope_var.G_plus(l_1) * ope_var.operateurs[conte]->der_sp_plus() ;
00216     
00217 
00218     
00219     //----------
00220     // SHELLS :
00221     //----------
00222 //  assert (nz-1 > 2) ;    // At least two shells
00223     for (int l=2 ; l<nz-1 ; l++) {
00224       
00225       // On se met au bon endroit :
00226       int np_prec = source.get_mg()->get_np(l-1) ;
00227       int nt_prec = source.get_mg()->get_nt(l-1) ;
00228       conte += (np_prec+1)*nt_prec ;
00229          
00230       systeme.set(2*l-3, 2*l-2) = -ope_var.G_minus(l) * 
00231         ope_var.operateurs[conte]->val_sh_one_minus() ;
00232       systeme.set(2*l-3, 2*l-1) = - ope_var.G_minus(l) * 
00233         ope_var.operateurs[conte]->val_sh_two_minus() ;
00234       systeme.set(2*l-2, 2*l-2) = 
00235         -ope_var.dG_minus(l)*ope_var.operateurs[conte]->val_sh_one_minus()-  
00236         ope_var.G_minus(l)*ope_var.operateurs[conte]->der_sh_one_minus() ;
00237       systeme.set(2*l-2, 2*l-1) =
00238         -ope_var.dG_minus(l)*ope_var.operateurs[conte]->val_sh_two_minus()-  
00239         ope_var.G_minus(l)*ope_var.operateurs[conte]->der_sh_two_minus() ;
00240       
00241       sec_membre.set(2*l-3) += ope_var.F_minus(l,k,j) + 
00242         ope_var.G_minus(l) * ope_var.operateurs[conte]->val_sp_minus() ;
00243       sec_membre.set(2*l-2) += ope_var.dF_minus(l,k,j) + 
00244         ope_var.dG_minus(l) * ope_var.operateurs[conte]->val_sp_minus() + 
00245         ope_var.G_minus(l) * ope_var.operateurs[conte]->der_sp_minus() ;
00246       
00247       // Valeurs en +1 :
00248       systeme.set(2*l-1, 2*l-2) = ope_var.G_plus(l) * 
00249         ope_var.operateurs[conte]->val_sh_one_plus() ;
00250       systeme.set(2*l-1, 2*l-1) = ope_var.G_plus(l) * 
00251         ope_var.operateurs[conte]->val_sh_two_plus() ;
00252       systeme.set(2*l, 2*l-2) = 
00253         ope_var.dG_plus(l)*ope_var.operateurs[conte]->val_sh_one_plus()+  
00254         ope_var.G_plus(l)*ope_var.operateurs[conte]->der_sh_one_plus() ;
00255       systeme.set(2*l, 2*l-1) =
00256         ope_var.dG_plus(l)*ope_var.operateurs[conte]->val_sh_two_plus()+
00257         ope_var.G_plus(l)*ope_var.operateurs[conte]->der_sh_two_plus() ;
00258       
00259       sec_membre.set(2*l-1) -=  ope_var.F_plus(l,k,j) + 
00260         ope_var.G_plus(l) * ope_var.operateurs[conte]->val_sp_plus();
00261       sec_membre.set(2*l) -=  ope_var.dF_plus(l,k,j) + 
00262         ope_var.dG_plus(l) * ope_var.operateurs[conte]->val_sp_plus() + 
00263         ope_var.G_plus(l) * ope_var.operateurs[conte]->der_sp_plus() ;
00264     }
00265     
00266     //-------
00267     // ZEC :
00268     //-------
00269     int np_prec = source.get_mg()->get_np(nz-2) ;
00270     int nt_prec = source.get_mg()->get_nt(nz-2) ;
00271     conte += (np_prec+1)*nt_prec ;
00272     
00273     systeme.set(taille-2, taille-1) = -ope_var.G_minus(nz-1) * 
00274       ope_var.operateurs[conte]->val_sh_one_minus() ;
00275     systeme.set(taille-1, taille-1) = 
00276       -ope_var.dG_minus(nz-1)*ope_var.operateurs[conte]->val_sh_one_minus()-  
00277       ope_var.G_minus(nz-1)*ope_var.operateurs[conte]->der_sh_one_minus()  ;
00278     
00279     sec_membre.set(taille-2) += ope_var.F_minus(nz-1,k,j) + 
00280       ope_var.G_minus(nz-1)*ope_var.operateurs[conte]->val_sp_minus() ;
00281     sec_membre.set(taille-1) += ope_var.dF_minus(nz-1,k,j) + 
00282       ope_var.dG_minus(nz-1) * ope_var.operateurs[conte]->val_sp_minus() + 
00283       ope_var.G_minus(nz-1) * ope_var.operateurs[conte]->der_sp_minus() ;
00284     
00285     // On resout le systeme ...
00286     if (taille > 2)
00287       systeme.set_band(2,2) ;
00288     else
00289       systeme.set_band(1,1) ;
00290     
00291     systeme.set_lu() ;
00292     Tbl facteur (systeme.inverse(sec_membre)) ;
00293 
00294     // On range tout ca :
00295   
00296     // Shells
00297     for (int l=1 ; l<nz-1 ; l++) {
00298       nr = source.get_mg()->get_nr(l) ;
00299       for (int i=0 ; i<nr ; i++)
00300         resultat.set(l,k,j,i) = solution_part(l,k,j,i) + 
00301           facteur(2*l-2)*solution_hom_un(l,k,j,i) +
00302           facteur(2*l-1)*solution_hom_deux(l,k,j,i) ;
00303     }
00304     
00305     // Zec
00306     nr = source.get_mg()->get_nr(nz-1) ;
00307     for (int i=0 ; i<nr ; i++)
00308       resultat.set(nz-1,k,j,i) = solution_part(nz-1,k,j,i) + 
00309         facteur(taille-1)*solution_hom_un(nz-1,k,j,i) ;
00310       }
00311     start ++ ;
00312     }
00313     
00314   return resultat;
00315 }
00316 

Generated on Tue Feb 7 01:35:19 2012 for LORENE by  doxygen 1.4.6