map_radial_poisson_cpt.C

00001 /*
00002  * Method of the class Map_radial for resolution of the equation
00003  *
00004  *  a \Delta\psi + {\bf b} \cdot \nabla \psi = \sigma
00005  *
00006  * Computes the unique solution such that psi(0) = 0.
00007  * bb must be given in spherical coordinates.
00008  *
00009  * (see file map.h for documentation)
00010  *
00011  */
00012 
00013 /*
00014  *   Copyright (c) 2000-2007 Eric Gourgoulhon
00015  *   Copyright (c) 2007 Michal Bejger
00016  *   Copyright (c) 2000-2001 Philippe Grandclement
00017  *   Copyright (c) 2001 Keisuke Taniguchi
00018  *
00019  *   This file is part of LORENE.
00020  *
00021  *   LORENE is free software; you can redistribute it and/or modify
00022  *   it under the terms of the GNU General Public License as published by
00023  *   the Free Software Foundation; either version 2 of the License, or
00024  *   (at your option) any later version.
00025  *
00026  *   LORENE is distributed in the hope that it will be useful,
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00029  *   GNU General Public License for more details.
00030  *
00031  *   You should have received a copy of the GNU General Public License
00032  *   along with LORENE; if not, write to the Free Software
00033  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00034  *
00035  */
00036 
00037 
00038 char map_radial_poisson_cpt_C[] = "$Header: /cvsroot/Lorene/C++/Source/Map/map_radial_poisson_cpt.C,v 1.5 2007/10/18 08:19:32 e_gourgoulhon Exp $" ;
00039 
00040 /*
00041  * $Id: map_radial_poisson_cpt.C,v 1.5 2007/10/18 08:19:32 e_gourgoulhon Exp $
00042  * $Log: map_radial_poisson_cpt.C,v $
00043  * Revision 1.5  2007/10/18 08:19:32  e_gourgoulhon
00044  * Suppression of the abort for nzet > 2 : the function should be able
00045  * to treat an arbitrary number of domains inside the star.
00046  * NB: tested only for nzet = 2.
00047  *
00048  * Revision 1.4  2007/10/16 21:53:13  e_gourgoulhon
00049  * Added new function poisson_compact (multi-domain version)
00050  *
00051  * Revision 1.3  2003/10/03 15:58:48  j_novak
00052  * Cleaning of some headers
00053  *
00054  * Revision 1.2  2002/12/11 13:17:07  k_taniguchi
00055  * Change the multiplication "*" to "%".
00056  *
00057  * Revision 1.1.1.1  2001/11/20 15:19:27  e_gourgoulhon
00058  * LORENE
00059  *
00060  * Revision 2.17  2001/08/28  15:08:06  keisuke
00061  *  Uncomment "sour_j.std_base_scal()" and "sour_j.ylm()".
00062  *
00063  * Revision 2.16  2001/08/28  14:45:06  keisuke
00064  * Uncomment "sour_j.coef()".
00065  *
00066  * Revision 2.15  2001/08/28  14:10:42  keisuke
00067  * Comment out "sour_j.std_base_scal()", "sour_j.coef()", and "sour_j.ylm()".
00068  *
00069  * Revision 2.14  2000/03/30  09:18:53  eric
00070  * Modifs affichage.
00071  *
00072  * Revision 2.13  2000/03/17  15:24:01  phil
00073  * suppression du nettoyage brutal
00074  *
00075  * Revision 2.12  2000/03/16  16:26:07  phil
00076  * Ajout du nettoyage des hautes frequences
00077  *
00078  * Revision 2.11  2000/03/10  09:18:36  eric
00079  * Annulation du terme l=0 de la source effective.
00080  *
00081  * Revision 2.10  2000/03/09  13:52:19  phil
00082  * *** empty log message ***
00083  *
00084  * Revision 2.9  2000/02/28  14:34:31  eric
00085  * *** empty log message ***
00086  *
00087  * Revision 2.8  2000/02/28  14:31:32  eric
00088  * Suppression de mpaff: remplacement de pre_lap = (1-r^2/R^2) par
00089  *  Id - .mult_x().mult_x().
00090  * Introduction de dpsi.
00091  * Modif affichages.
00092  *
00093  * Revision 2.7  2000/02/25  13:48:00  eric
00094  * Suppression des appels a Mtbl_cf::nettoie().
00095  *
00096  * Revision 2.6  2000/02/22  11:43:10  eric
00097  * Appel de ylm() sur d2psi.
00098  * Modif affichage.
00099  *
00100  * Revision 2.5  2000/02/21  12:58:12  eric
00101  * Modif affichage.
00102  *
00103  * Revision 2.4  2000/01/27  15:58:36  eric
00104  * Utilisation du nouveau constructeur Map_af::Map_af(const Map&)
00105  * pour la construction du mapping auxiliaire mpaff.
00106  * Suppression des affichages intermediaires.
00107  *
00108  * Revision 2.3  2000/01/14  17:33:44  eric
00109  * Amelioration du calcul (le Cmp intermediaire psi0 est supprime).
00110  *
00111  * Revision 2.2  2000/01/13  16:43:59  eric
00112  * Premiere version testee : OK !
00113  *
00114  * Revision 2.1  2000/01/12  16:03:23  eric
00115  * Premiere version complete.
00116  *
00117  * Revision 2.0  2000/01/10  09:14:52  eric
00118  * *** empty log message ***
00119  *
00120  *
00121  * $Header: /cvsroot/Lorene/C++/Source/Map/map_radial_poisson_cpt.C,v 1.5 2007/10/18 08:19:32 e_gourgoulhon Exp $
00122  *
00123  */
00124 
00125 // Headers C++
00126 
00127 // Headers C
00128 #include <stdlib.h>
00129 #include <math.h>
00130 
00131 // Headers Lorene
00132 #include "tenseur.h"
00133 #include "param.h"
00134 #include "proto.h"
00135 #include "graphique.h"
00136 #include "utilitaires.h"
00137 
00138 // Local prototypes
00139 Mtbl_cf sol_poisson_compact(const Mtbl_cf&, double, double, bool) ;
00140 Mtbl_cf sol_poisson_compact(const Map_af&, const Mtbl_cf&, const Tbl&, 
00141     const Tbl&, bool) ;  
00142 
00143 
00145     //  Single domain version  //
00147 
00148 void Map_radial::poisson_compact(const Cmp& source, const Cmp& aa, 
00149                  const Tenseur& bb, const Param& par, 
00150                  Cmp& psi) const {
00151 
00152 
00153     // Protections
00154     // -----------
00155     
00156     assert(source.get_etat() != ETATNONDEF) ; 
00157     assert(aa.get_etat() != ETATNONDEF) ; 
00158     assert(bb.get_etat() != ETATNONDEF) ; 
00159     assert(aa.get_mp() == source.get_mp()) ; 
00160     assert(bb.get_mp() == source.get_mp()) ; 
00161     assert(psi.get_mp() == source.get_mp()) ; 
00162     
00163     
00164     // The components of vector b must be given in the spherical basis
00165     //  associated with the mapping : 
00166     assert(*(bb.get_triad()) == bvect_spher) ; 
00167 
00168     // Computation parameters
00169     // ----------------------
00170     int nitermax = par.get_int() ; 
00171     int& niter = par.get_int_mod() ; 
00172     double precis = par.get_double(0) ; 
00173     double relax = par.get_double(1) ; 
00174     double unmrelax = 1. - relax ; 
00175         
00176     // Maybe nothing to do ?
00177     // ---------------------
00178     
00179     if ( source.get_etat() == ETATZERO ) {  
00180     psi.set_etat_zero() ; 
00181     return ; 
00182     }   
00183     
00184     // Factors alpha ( in front of (1-xi^2) Lap_xi(psi) )
00185     //  and    beta  ( in front of xi dpsi/dxi )
00186     // --------------------------------------------------
00187     
00188     Mtbl tmp = dxdr ; 
00189     double dxdr_c = tmp(0, 0, 0, 0) ;  // central value of 1/(dR/dxi)
00190     
00191     double alph = dxdr_c * dxdr_c * aa(0, 0, 0, 0) ; 
00192 
00193     const Valeur& b_r = bb(0).va ;  // radial component b^r of vector b
00194     
00195     Valeur vatmp = dxdr*dxdr*b_r ;
00196     
00197     double bet = min(vatmp)(0) ;  // Minimal value in domain no. 0
00198     
00199     cout << "Map_radial::poisson_compact : alph, bet : " << alph << "  "
00200      << bet << endl ; 
00201 
00202 
00203     // Everything is set to zero except in the innermost domain (nucleus) :
00204     // ------------------------------------------------------------------
00205 
00206     int nz = mg->get_nzone() ;
00207 
00208     psi.annule(1, nz-1) ; 
00209 
00210     // Auxilary quantities
00211     // -------------------
00212     Cmp psi_jm1 = psi ; 
00213     Cmp b_grad_psi(this) ; 
00214     Valeur sour_j(*mg) ; 
00215     Valeur aux_psi(*mg) ;       
00216     Valeur lap_xi_psi(*mg) ; 
00217     Valeur oper_psi(*mg) ; 
00218     Valeur dpsi(*mg) ; 
00219     Valeur d2psi(*mg) ; 
00220 
00221     Valeur& vpsi = psi.va ; 
00222 
00223 //==========================================================================
00224 //              Start of iteration 
00225 //==========================================================================
00226 
00227     Tbl tdiff(nz) ; 
00228     double diff ; 
00229     niter = 0 ; 
00230  
00231     
00232     do {
00233     
00234     // Computation of the source for sol_poisson_compact
00235     // -------------------------------------------------
00236 
00237     b_grad_psi = bb(0) % psi.dsdr() + 
00238              bb(1) % psi.srdsdt() +
00239              bb(2) % psi.srstdsdp() ; 
00240     
00241 
00242     vpsi.ylm() ;    // Expansion of psi onto spherical harmonics
00243 
00244     // Lap_xi(psi) :
00245 
00246     dpsi = vpsi.dsdx() ; 
00247     dpsi.ylm() ;            // necessary because vpsi.p_dsdx
00248                     // has been already computed (in 
00249                     // non-spherical harmonics bases) by
00250                     // the call psi.dsdr() above
00251 
00252     aux_psi = 2.*dpsi + (vpsi.lapang()).sx() ;
00253 
00254     d2psi = vpsi.d2sdx2() ; 
00255     d2psi.ylm() ; 
00256     
00257     lap_xi_psi = d2psi + aux_psi.sx() ; 
00258 
00259     // Effective source : 
00260 
00261     sour_j = source.va 
00262             + alph * ( lap_xi_psi - (lap_xi_psi.mult_x()).mult_x() )
00263             - aa.va   * (psi.laplacien()).va
00264             + bet * dpsi.mult_x() 
00265             - b_grad_psi.va ; 
00266                
00267     sour_j.std_base_scal() ; 
00268     sour_j.coef() ; 
00269     sour_j.ylm() ;      // Spherical harmonics expansion 
00270 
00271     // The term l=0 of the effective source is set to zero : 
00272     // ---------------------------------------------------
00273     double somlzero = 0 ; 
00274         for (int i=0; i<mg->get_nr(0); i++) {
00275         somlzero += fabs( (*(sour_j.c_cf))(0, 0, 0, i) ) ; 
00276         (sour_j.c_cf)->set(0, 0, 0, i) = 0 ;  
00277     }
00278     
00279     if (somlzero > 1.e-10) {
00280         cout << "### WARNING : Map_radial::poisson_compact : " << endl
00281          << " the l=0 part of the effective source is > 1.e-10  : "
00282          << somlzero << endl ; 
00283     }
00284 
00285     
00286     // Resolution of the equation 
00287     //   a (1-xi^2) Lap_xi(psi) + b xi dpsi/dxi = sour_j 
00288     //---------------------------------------------------
00289     
00290     bool reamorce = (niter == 0) ;
00291     
00292     assert(sour_j.c_cf != 0x0) ; 
00293     
00294     psi.set_etat_zero() ;  // to call Cmp::del_deriv().
00295     psi.set_etat_qcq() ;
00296     vpsi = sol_poisson_compact( *(sour_j.c_cf), alph, bet, reamorce ) ;
00297 
00298 
00299     // Test: multiplication by the operator matrix 
00300     // -------------------------------------------
00301     
00302 //  Mtbl_cf cvpsi = *(vpsi.c_cf) ; 
00303 //  Mtbl_cf csour = *(sour_j.c_cf) ; 
00304 //  
00305 //  int np = mg->get_np(0) ; 
00306 //  int nt = mg->get_nt(0) ; 
00307 //  int nr = mg->get_nr(0) ;
00308 //  
00309 //  for (int k=0 ; k<np+1 ; k++) {
00310 //      for (int j=0 ; j<nt ; j++) {
00311 //      if (nullite_plm(j, nt, k, np, cvpsi.base) == 1) {
00312 //      int l_quant, m_quant, base_r ; 
00313 //      donne_lm(nz, 0, j, k, cvpsi.base, m_quant, l_quant, base_r) ;
00314 //      
00315 //      cout << "### k, j, l, m : " << k << "  " << j << "    "
00316 //          <<  l_quant << "  " << m_quant << endl ; 
00317 //      Matrice operateur = alph * laplacien_nul_mat(nr, l_quant, base_r)
00318 //                   + bet * xdsdx_mat(nr, l_quant, base_r) ;
00319 //      Tbl coef(nr) ;  
00320 //      operateur = combinaison_nul(operateur, l_quant, coef, base_r) ;
00321 //      
00322 //          Tbl so(nr) ;
00323 //          so.set_etat_qcq() ;
00324 //          for (int i=0 ; i<nr ; i++)
00325 //          so.set(i) = csour(0, k, j, i) ;
00326 //          so = combinaison_nul(so, l_quant, coef, base_r) ;
00327 //
00328 //          Tbl psi1(nr) ;
00329 //          Tbl opi1(nr) ;
00330 //          psi1.set_etat_qcq() ; 
00331 //          opi1.set_etat_qcq() ; 
00332 //          
00333 //      bool discrep = false ; 
00334 //
00335 //      for (int i=0; i<nr; i++) {
00336 //      
00337 //      double op = 0 ; 
00338 //      for (int i1=0; i1<nr; i1++) {
00339 //          op += operateur(i, i1) * cvpsi(0, k, j, i1) ; 
00340 //      }
00341 //      
00342 //      psi1.set(i) = cvpsi(0, k, j, i) ; 
00343 //      opi1.set(i) = op ; 
00344 //      
00345 //      double x1 = so(i) ; 
00346 //      double x2 = op - so(i) ; 
00347 //      double seuil = 1e-11 ; 
00348 //      if ( fabs(x2) > seuil )
00349 //          {
00350 //          discrep = true ; 
00351 //          cout << "i : op , sou,  diff : " << i << " : " << op << "  " 
00352 //           << x1 << "  " << x2 << endl ; 
00353 //           } 
00354 //      
00355 //      }
00356 //
00357 //      if ( discrep ) {
00358 //      cout << "Matrice pour k,  j = " << k << "  " << j << endl ; 
00359 //      cout << operateur << endl ; 
00360 //      cout << "psi : " << psi1 << endl ; 
00361 //      cout << "op(psi) : " << opi1 << endl ; 
00362 //      cout << "so : " << so << endl ; 
00363 //      }
00364 //
00365 //      }   // fin du cas ou m<=l 
00366 //      }   // fin de boucle sur j  
00367 //  }   // fin de boucle sur k 
00368 
00369 
00370     // Test: has the equation been correctly solved ?
00371     // ---------------------------------------------
00372     
00373     // Lap_xi(psi) :
00374     aux_psi = vpsi.dsdx() ; 
00375     
00376     aux_psi = 2.*aux_psi + (vpsi.lapang()).sx() ;
00377         
00378     lap_xi_psi = vpsi.d2sdx2() + aux_psi.sx() ; 
00379             
00380     oper_psi = alph * ( lap_xi_psi - (lap_xi_psi.mult_x()).mult_x() )
00381            + bet * (vpsi.dsdx()).mult_x() ; 
00382             
00383 
00384     double maxc = fabs( max(*(vpsi.c_cf))(0) ) ; 
00385     double minc = fabs( min(*(vpsi.c_cf))(0) ) ; 
00386     double max_abs_psi = ( maxc > minc ) ? maxc : minc ;    
00387 
00388     maxc = fabs( max(*(sour_j.c_cf))(0) ) ; 
00389     minc = fabs( min(*(sour_j.c_cf))(0) ) ; 
00390     double max_abs_sou = ( maxc > minc ) ? maxc : minc ;    
00391 
00392     Mtbl_cf diff_opsou = *oper_psi.c_cf - *sour_j.c_cf ; 
00393     maxc = fabs( max(diff_opsou)(0) ) ; 
00394     minc = fabs( min(diff_opsou)(0) ) ; 
00395     double max_abs_diff = ( maxc > minc ) ? maxc : minc ;   
00396 
00397 
00398 //  cout << " Coef of oper_psi - sour_j : " << endl ; 
00399 //  diff_opsou.affiche_seuil(cout, 4, 1.e-11) ; 
00400 
00401     cout << "  Step " << niter 
00402          << "  : test (1-xi^2) Lap_xi(psi) + b xi dpsi/dxi : "  << endl ; 
00403     cout << "   max |psi| |sou| |oper(psi)-sou|: " 
00404          << max_abs_psi << "  " << max_abs_sou << "  "  
00405          << max_abs_diff << endl ; 
00406     
00407     // Relaxation : 
00408     // -----------
00409     
00410     vpsi.ylm_i() ;    // Inverse spherical harmonics transform
00411 
00412     psi = relax * psi + unmrelax * psi_jm1 ; 
00413 
00414     tdiff = diffrel(psi, psi_jm1) ; 
00415 
00416     diff = max(tdiff) ;
00417 
00418     cout << 
00419     "   Relative difference psi^J <-> psi^{J-1} :                       " 
00420          << tdiff(0) << endl ; 
00421 
00422 //  arrete() ; 
00423 
00424     // Updates for the next iteration
00425     // -------------------------------    
00426 
00427     psi_jm1 = psi ;
00428     niter++ ; 
00429 
00430     }   // End of iteration 
00431     while ( (diff > precis) && (niter < nitermax) ) ;
00432     
00433 //==========================================================================
00434 //              End of iteration 
00435 //==========================================================================        
00436                      
00437 }
00438 
00439 
00440 
00442     //  Multi domain version  //
00444 
00445 
00446 void Map_radial::poisson_compact(int nzet, const Cmp& source, const Cmp& aa, 
00447                  const Tenseur& bb, const Param& par, 
00448                  Cmp& psi) const {
00449     
00450     if (nzet == 1) {
00451         poisson_compact(source, aa, bb, par, psi) ;
00452         return ; 
00453     }
00454 
00455 
00456     // Protections
00457     // -----------
00458     
00459     assert(source.get_etat() != ETATNONDEF) ; 
00460     assert(aa.get_etat() != ETATNONDEF) ; 
00461     assert(bb.get_etat() != ETATNONDEF) ; 
00462     assert(aa.get_mp() == source.get_mp()) ; 
00463     assert(bb.get_mp() == source.get_mp()) ; 
00464     assert(psi.get_mp() == source.get_mp()) ; 
00465     
00466     
00467     // The components of vector b must be given in the spherical basis
00468     //  associated with the mapping : 
00469     assert(*(bb.get_triad()) == bvect_spher) ; 
00470 
00471     // Maybe nothing to do ?
00472     // ---------------------
00473     
00474     if ( source.get_etat() == ETATZERO ) {  
00475         psi.set_etat_zero() ; 
00476         return ; 
00477     }   
00478     
00479     // Computation parameters
00480     // ----------------------
00481     int nitermax = par.get_int() ; 
00482     int& niter = par.get_int_mod() ; 
00483     double precis = par.get_double(0) ; 
00484     double relax = par.get_double(1) ; 
00485     double unmrelax = 1. - relax ; 
00486 
00487     // Auxiliary affine mapping
00488     Map_af mpaff(*this) ; 
00489 
00490     // Coefficients to fit the profiles of aa and bb in each domain
00491     // ------------------------------------------------------------
00492     Tbl ac(nzet,3) ; 
00493     ac.annule_hard() ;  // initialization to zero 
00494     Tbl bc(nzet,3) ; 
00495     bc.annule_hard() ; // initialization to zero 
00496 
00497     Valeur ap = aa.va ;
00498     Valeur bp = bb(0).va ;
00499 
00500     // Coefficients in the nucleus
00501     int nrm1 = mg->get_nr(0) - 1 ; 
00502     ac.set(0,0) = ap(0,0,0,0) ;
00503     ac.set(0,2) = ap(0,0,0,nrm1) - ac(0,0) ; 
00504     
00505     bc.set(0,1) = bp(0,0,0,nrm1) ; 
00506 
00507     // Coefficients in the intermediate shells
00508     for (int lz=1; lz<nzet-1; lz++) {
00509         nrm1 = mg->get_nr(lz) - 1 ; 
00510         ac.set(lz,0) = 0.5 * ( ap(lz,0,0,nrm1) + ap(lz,0,0,0) ) ; 
00511         ac.set(lz,1) = 0.5 * ( ap(lz,0,0,nrm1) - ap(lz,0,0,0) ) ; 
00512 
00513         bc.set(lz,0) = 0.5 * ( bp(lz,0,0,nrm1) + bp(lz,0,0,0) ) ; 
00514         bc.set(lz,1) = 0.5 * ( bp(lz,0,0,nrm1) - bp(lz,0,0,0) ) ; 
00515     }
00516 
00517     // Coefficients in the external shell
00518     int lext = nzet - 1 ; 
00519     nrm1 = mg->get_nr(lext) - 1 ; 
00520     ac.set(lext,0) = 0.5 * ap(lext,0,0,0) ; 
00521     ac.set(lext,1) = - ac(lext,0) ; 
00522 
00523     bc.set(lext,0) = 0.5 * ( bp(lext,0,0,nrm1) + bp(lext,0,0,0) ) ; 
00524     bc.set(lext,1) = 0.5 * ( bp(lext,0,0,nrm1) - bp(lext,0,0,0) ) ;   
00525 
00526     cout << "ac : " << ac << endl ; 
00527     cout << "bc : " << bc << endl ; 
00528 
00529     // Prefactor of Lap_xi(Psi) and dPsi/dxi
00530     // -------------------------------------
00531 
00532     Mtbl ta(mg) ;
00533     Mtbl tb(mg) ;
00534     ta.annule_hard() ; 
00535     tb.annule_hard() ; 
00536     for (int lz=0; lz<nzet; lz++) {
00537         const double* xi = mg->get_grille3d(lz)->x ;
00538         double* tta = ta.set(lz).t ; 
00539         double* ttb = tb.set(lz).t ; 
00540         int np = mg->get_np(lz) ; 
00541         int nt = mg->get_nt(lz) ; 
00542         int nr = mg->get_nr(lz) ; 
00543         int pt = 0 ; 
00544         for (int k=0; k<np; k++) {
00545             for (int j=0; j<nt; j++) {
00546                 for (int i=0; i<nr; i++) {
00547                     tta[pt] = ac(lz,0) + xi[i] * (ac(lz,1) + ac(lz,2) * xi[i]) ;
00548                     ttb[pt] = bc(lz,0) + xi[i] * (bc(lz,1) + bc(lz,2) * xi[i]) ;
00549                     pt++ ;  
00550                 }
00551             }
00552         }
00553     }
00554 
00555 // Verification
00556 //  cout << "Map :" << *(aa.get_mp()) << endl ; 
00557 //  Cmp tverif(*this) ; 
00558 //  tverif = ap ;
00559 //  tverif.std_base_scal() ;  
00560 //  des_profile(tverif,0., 4., 0., 0.) ; 
00561 //  tverif = ta ; 
00562 //  tverif.std_base_scal() ;  
00563 //  des_profile(tverif,0., 4., 0., 0.) ; 
00564 // 
00565 //  tverif = bp ;
00566 //  tverif.std_base_scal() ;  
00567 //  des_profile(tverif,0., 4., 0., 0.) ; 
00568 //  tverif = tb ; 
00569 //  tverif.std_base_scal() ;  
00570 //  des_profile(tverif,0., 4., 0., 0.) ; 
00571 
00572 
00573     // Everything is set to zero except inside the star
00574     // -------------------------------------------------
00575 
00576     int nz = mg->get_nzone() ;
00577 
00578     psi.annule(nzet, nz-1) ; 
00579 
00580     // Auxilary quantities
00581     // -------------------
00582     Cmp psi_jm1 = psi ; 
00583     Cmp b_grad_psi(this) ; 
00584     Valeur sour_j(*mg) ; 
00585     Valeur aux_psi(*mg) ;       
00586     Valeur lap_xi_psi(*mg) ; 
00587     Valeur oper_psi(*mg) ; 
00588     Valeur dpsi(*mg) ; 
00589     Valeur d2psi(*mg) ; 
00590 
00591     Valeur& vpsi = psi.va ; 
00592 
00593 //==========================================================================
00594 //              Start of iteration 
00595 //==========================================================================
00596 
00597     Tbl tdiff(nz) ; 
00598     double diff ; 
00599     niter = 0 ; 
00600  
00601     
00602     do {
00603     
00604     // Computation of the source for sol_poisson_compact
00605     // -------------------------------------------------
00606 
00607     b_grad_psi = bb(0) % psi.dsdr() + bb(1) % psi.srdsdt() + bb(2) % psi.srstdsdp() ; 
00608 
00609 //?? 
00610     vpsi.ylm() ;    // Expansion of psi onto spherical harmonics
00611 
00612     // Effective source : 
00613 
00614     Cmp lap_zeta(mpaff) ; 
00615     mpaff.laplacien(psi, 0, lap_zeta) ; 
00616 
00617     Cmp grad_zeta(mpaff) ;
00618     mpaff.dsdr(psi, grad_zeta) ; 
00619 
00620     sour_j = source.va 
00621             + ta * lap_zeta.va - aa.va * (psi.laplacien()).va
00622             + tb * grad_zeta.va - b_grad_psi.va ; 
00623                
00624     sour_j.std_base_scal() ; 
00625     sour_j.coef() ; 
00626     sour_j.ylm() ;      // Spherical harmonics expansion 
00627 
00628 
00629     // The term l=0 of the effective source is set to zero : 
00630     // ---------------------------------------------------
00631 
00632     for (int lz=0; lz<nzet; lz++) {
00633         double somlzero = 0 ; 
00634         for (int i=0; i<mg->get_nr(lz); i++) {
00635             somlzero += fabs( (*(sour_j.c_cf))(lz, 0, 0, i) ) ; 
00636             (sour_j.c_cf)->set(lz, 0, 0, i) = 0 ;  
00637         }
00638         if (somlzero > 1.e-10) {
00639             cout << "### WARNING : Map_radial::poisson_compact : " << endl
00640             << " domain no. " << lz << " : the l=0 part of the effective source is > 1.e-10  : "
00641             << somlzero << endl ; 
00642         }
00643     }
00644 
00645     // Resolution of the equation 
00646     //----------------------------
00647     
00648     bool reamorce = (niter == 0) ;
00649     
00650     assert(sour_j.c_cf != 0x0) ; 
00651     
00652     psi.set_etat_zero() ;  // to call Cmp::del_deriv().
00653     psi.set_etat_qcq() ;
00654     
00655     vpsi = sol_poisson_compact(mpaff, *(sour_j.c_cf), ac, bc, reamorce) ;
00656 
00657     // Test: has the equation been correctly solved ?
00658     // ---------------------------------------------
00659     
00660     mpaff.laplacien(psi, 0, lap_zeta) ; 
00661     mpaff.dsdr(psi, grad_zeta) ; 
00662 
00663     oper_psi = ta * lap_zeta.va + tb * grad_zeta.va ; 
00664     oper_psi.std_base_scal() ; 
00665     oper_psi.coef() ; 
00666     oper_psi.ylm() ;            
00667 
00668     Mtbl_cf diff_opsou = *oper_psi.c_cf - *sour_j.c_cf ; 
00669         //cout << " Coef of oper_psi - sour_j : " << endl ; 
00670         // diff_opsou.affiche_seuil(cout, 4, 1.e-11) ; 
00671     
00672     cout << "poisson_compact:  step " << niter << " : " << endl ;  
00673     for (int lz=0; lz<nzet; lz++) {
00674         double maxc = fabs( max(*(vpsi.c_cf))(lz) ) ; 
00675         double minc = fabs( min(*(vpsi.c_cf))(lz) ) ; 
00676         double max_abs_psi = ( maxc > minc ) ? maxc : minc ;    
00677 
00678         maxc = fabs( max(*(sour_j.c_cf))(lz) ) ; 
00679         minc = fabs( min(*(sour_j.c_cf))(lz) ) ; 
00680         double max_abs_sou = ( maxc > minc ) ? maxc : minc ;    
00681 
00682         maxc = fabs( max(diff_opsou)(lz) ) ; 
00683         minc = fabs( min(diff_opsou)(lz) ) ; 
00684         double max_abs_diff = ( maxc > minc ) ? maxc : minc ;   
00685 
00686         cout << "  lz = " << lz << " : max |psi| |sou| |oper(psi)-sou|: " 
00687          << max_abs_psi << "  " << max_abs_sou << "  "  
00688          << max_abs_diff << endl ; 
00689     }
00690 
00691     // Relaxation : 
00692     // -----------
00693     
00694     vpsi.ylm_i() ;    // Inverse spherical harmonics transform
00695 
00696     psi = relax * psi + unmrelax * psi_jm1 ; 
00697 
00698     tdiff = diffrel(psi, psi_jm1) ; 
00699 
00700     diff = max(tdiff) ;
00701 
00702     cout << "   Relative difference psi^J <-> psi^{J-1} :    " 
00703          << tdiff << endl ;
00704 
00705     // Updates for the next iteration
00706     // -------------------------------    
00707 
00708     psi_jm1 = psi ;
00709     niter++ ; 
00710 
00711     }   // End of iteration 
00712     while ( (diff > precis) && (niter < nitermax) ) ;
00713     
00714 //==========================================================================
00715 //              End of iteration 
00716 //==========================================================================        
00717 
00718     psi.annule(nzet, nz-1) ; 
00719 
00720 }
00721 
00722 
00723 
00724 
00725 
00726 
00727 
00728 
00729 
00730 
00731 
00732 
00733 
00734 
00735 
00736 
00737 
00738 

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