scalar_sol_div.C

00001 /*
00002  *  Resolution of the divergence ODE: df/df + n*f/r = source (source must have dzpuis =2)
00003  *
00004  *    (see file scalar.h for documentation).
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2005  Jerome Novak
00010  *
00011  *   This file is part of LORENE.
00012  *
00013  *   LORENE is free software; you can redistribute it and/or modify
00014  *   it under the terms of the GNU General Public License version 2
00015  *   as published by the Free Software Foundation.
00016  *
00017  *   LORENE is distributed in the hope that it will be useful,
00018  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *   GNU General Public License for more details.
00021  *
00022  *   You should have received a copy of the GNU General Public License
00023  *   along with LORENE; if not, write to the Free Software
00024  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00025  *
00026  */
00027 
00028 char scalar_sol_div_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tensor/Scalar/scalar_sol_div.C,v 1.3 2005/09/16 14:33:00 j_novak Exp $" ;
00029 
00030 /*
00031  * $Id: scalar_sol_div.C,v 1.3 2005/09/16 14:33:00 j_novak Exp $
00032  * $Log: scalar_sol_div.C,v $
00033  * Revision 1.3  2005/09/16 14:33:00  j_novak
00034  * Added #include <math.h>.
00035  *
00036  * Revision 1.2  2005/09/16 12:49:52  j_novak
00037  * The case with dzpuis=1 is added.
00038  *
00039  * Revision 1.1  2005/06/08 12:35:22  j_novak
00040  * New method for solving divergence-like ODEs.
00041  *
00042  *
00043  * $Header: /cvsroot/Lorene/C++/Source/Tensor/Scalar/scalar_sol_div.C,v 1.3 2005/09/16 14:33:00 j_novak Exp $
00044  *
00045  */
00046 
00047 // C headers
00048 #include<assert.h>
00049 #include<math.h>
00050 
00051 //Lorene headers
00052 #include "tensor.h"
00053 #include "diff.h"
00054 #include "proto.h"
00055 
00056 // Local prototypes 
00057 void _sx_r_chebp(Tbl* , int& ) ;
00058 void _sx_r_chebi(Tbl* , int& ) ;
00059 
00060 
00061 Scalar Scalar::sol_divergence(int n_factor) const {
00062 
00063     assert(etat != ETATNONDEF) ;
00064     const Map_af* mpaff = dynamic_cast<const Map_af*>(mp) ;
00065     assert( mpaff != 0x0) ;
00066 
00067     Scalar result(*mp) ;
00068 
00069     if ( etat == ETATZERO )
00070     result.set_etat_zero() ;
00071     else {                                             //source not zero
00072     Base_val base_resu = get_spectral_base() ;
00073     base_resu.mult_x() ;
00074     const Mg3d* mg = mp->get_mg() ;
00075     result.set_etat_qcq() ; result.set_spectral_base(base_resu) ;
00076     result.set_spectral_va().set_etat_cf_qcq() ;
00077     Valeur sigma(va) ;
00078     sigma.ylm_i() ;                               // work on Fourier basis
00079     const Mtbl_cf& source = *sigma.c_cf ;
00080 
00081     // Checks on the type of domains
00082     int nz = mg->get_nzone() ;
00083     bool ced = (mg->get_type_r(nz-1) == UNSURR ) ;
00084     assert ( (!ced) || (check_dzpuis(2)) || (check_dzpuis(1)) ) ;
00085     assert (mg->get_type_r(0) == RARE) ;
00086     int nt = mg->get_nt(0) ;
00087     int np = mg->get_np(0) ;
00088 #ifndef NDEBUG
00089     for (int lz = 0; lz<nz; lz++)
00090         assert( (mg->get_nt(lz) == nt) && (mg->get_np(lz) == np) ) ;
00091 #endif
00092     int nr, base_r,l_quant, m_quant;
00093     Tbl *so ;
00094     Tbl *s_hom ;
00095     Tbl *s_part ;
00096   
00097     // Working objects and initialization
00098     Mtbl_cf sol_part(mg, base_resu) ;
00099     Mtbl_cf sol_hom(mg, base_resu) ;
00100     Mtbl_cf& resu = *result.set_spectral_va().c_cf ;
00101     sol_part.annule_hard();
00102     sol_hom.annule_hard() ;
00103     resu.annule_hard() ;
00104 
00105     //---------------
00106     //--  NUCLEUS ---
00107     //---------------
00108     int lz = 0 ;  
00109     nr = mg->get_nr(lz) ;
00110 
00111         int dege = 1 ; // the operator is degenerate
00112     int nr0 = nr - dege ;
00113     Tbl vect1(3, 1, nr) ; 
00114     Tbl vect2(3, 1, nr) ;
00115     int base_pipo = 0 ;
00116     double alpha = mpaff->get_alpha()[lz] ;
00117     double beta =  0. ;
00118     Matrice ope_even(nr0, nr0) ; //when the *result* is decomposed on R_CHEBP
00119     ope_even.set_etat_qcq() ;
00120     for (int i=dege; i<nr; i++) {
00121         vect1.annule_hard() ;
00122         vect2.annule_hard() ;
00123         vect1.set(0,0,i) = 1. ; vect2.set(0,0,i) = 1. ;
00124         _dsdx_r_chebp(&vect1, base_pipo) ;
00125         _sx_r_chebp(&vect2, base_pipo) ;
00126         for (int j=0; j<nr0; j++)
00127         ope_even.set(j,i-dege) = (vect1(0,0,j) + n_factor*vect2(0,0,j)) / alpha ;
00128     }
00129     ope_even.set_lu() ;
00130     Matrice ope_odd(nr0, nr0) ; //when the *result* is decomposed on R_CHEBI
00131     ope_odd.set_etat_qcq() ;
00132     for (int i=0; i<nr0; i++) {
00133         vect1.annule_hard() ;
00134         vect2.annule_hard() ;
00135         vect1.set(0,0,i) = 1. ; vect2.set(0,0,i) = 1. ;
00136         _dsdx_r_chebi(&vect1, base_pipo) ;
00137         _sx_r_chebi(&vect2, base_pipo) ;
00138         for (int j=0; j<nr0; j++)
00139         ope_odd.set(j,i) = (vect1(0,0,j) + n_factor*vect2(0,0,j)) / alpha ;
00140     }
00141     ope_odd.set_lu() ;
00142   
00143     for (int k=0 ; k<np+1 ; k++) 
00144         for (int j=0 ; j<nt ; j++) {
00145         // to get the spectral base
00146         base_resu.give_quant_numbers(lz, k, j, m_quant, l_quant, base_r) ;
00147         assert ( (base_r == R_CHEBP) || (base_r == R_CHEBI) ) ;
00148         const Matrice& operateur = (( base_r == R_CHEBP ) ? 
00149                         ope_even : ope_odd ) ;
00150         // particular solution 
00151         so = new Tbl(nr0) ;
00152         so->set_etat_qcq() ;
00153         for (int i=0 ; i<nr0 ; i++)
00154             so->set(i) = source(lz, k, j, i) ;
00155 
00156         s_part = new Tbl(operateur.inverse(*so)) ;
00157         
00158         // Putting to Mtbl_cf     
00159         double somme = 0 ;
00160         for (int i=0 ; i<nr0 ; i++) {
00161             if (base_r == R_CHEBP) {
00162             resu.set(lz, k, j, i+dege) = (*s_part)(i) ;
00163             somme += ((i+dege)%2 == 0 ? 1 : -1)*(*s_part)(i) ;
00164             }
00165             else 
00166             resu.set(lz,k,j,i) = (*s_part)(i) ;
00167         }
00168         if (base_r == R_CHEBI) 
00169             for (int i=nr0; i<nr; i++) 
00170             resu.set(lz,k,j,i) = 0 ; 
00171         if (base_r == R_CHEBP) //result must vanish at r=0
00172             resu.set(lz, k, j, 0) -= somme ;
00173 
00174         delete so ;
00175         delete s_part ;
00176         
00177         }
00178     
00179     //---------------------
00180     //--      SHELLS     --
00181     //---------------------
00182     int nz0 = (ced ? nz - 1 : nz) ;
00183     for (lz=1 ; lz<nz0 ; lz++) {
00184         nr = mg->get_nr(lz) ;    
00185         alpha = mpaff->get_alpha()[lz] ;
00186         beta =  mpaff->get_beta()[lz];
00187         double ech = beta / alpha ;
00188         Diff_id id(R_CHEB, nr) ; const Matrice& mid = id.get_matrice() ; 
00189         Diff_xdsdx xd(R_CHEB, nr) ; const Matrice& mxd = xd.get_matrice() ;
00190         Diff_dsdx dx(R_CHEB, nr) ; const Matrice& mdx = dx.get_matrice() ;
00191         Matrice operateur = mxd + ech*mdx + n_factor*mid ;
00192         operateur.set_lu() ;
00193         // homogeneous solution
00194         s_hom = new Tbl(solh(nr, n_factor-1, ech, R_CHEB)) ;
00195         
00196         for (int k=0 ; k<np+1 ; k++)
00197         for (int j=0 ; j<nt ; j++) {
00198             // to get the spectral base
00199             base_resu.give_quant_numbers(lz, k, j, m_quant, l_quant, base_r) ;
00200             assert (base_r == R_CHEB) ;
00201             
00202             so = new Tbl(nr) ;
00203             so->set_etat_qcq() ;
00204             // particular solution
00205             Tbl tmp(nr) ;
00206             tmp.set_etat_qcq() ;
00207             for (int i=0 ; i<nr ; i++)
00208             tmp.set(i) = source(lz, k, j, i) ;
00209             for (int i=0; i<nr; i++) so->set(i) = beta*tmp(i) ;
00210             multx_1d(nr, &tmp.t, R_CHEB) ;
00211             for (int i=0; i<nr; i++) so->set(i) += alpha*tmp(i)  ;
00212             
00213             s_part = new Tbl (operateur.inverse(*so)) ;
00214             
00215             // cleaning things...
00216             for (int i=0 ; i<nr ; i++) {
00217             sol_part.set(lz, k, j, i) = (*s_part)(i) ;
00218             sol_hom.set(lz, k, j, i) = (*s_hom)(1,i) ;
00219             }
00220             
00221             delete so ;
00222             delete s_part ;
00223         }
00224         delete s_hom ;
00225     }
00226     if (ced) {
00227     //---------------
00228     //--  CED   -----
00229     //---------------
00230         int dzp = ( check_dzpuis(2) ? 2 : 1) ;
00231         nr = source.get_mg()->get_nr(nz-1) ;
00232         alpha = mpaff->get_alpha()[nz-1] ;
00233         beta = mpaff->get_beta()[nz-1] ;
00234         dege = dzp  ;
00235         nr0 = nr - dege ;
00236         Diff_dsdx dx(R_CHEBU, nr) ; const Matrice& mdx = dx.get_matrice() ;
00237         Diff_sx sx(R_CHEBU, nr) ; const Matrice& msx = sx.get_matrice() ;
00238         Diff_xdsdx xdx(R_CHEBU, nr) ; const Matrice& mxdx = xdx.get_matrice() ;
00239         Diff_id id(R_CHEBU, nr) ; const Matrice& mid = id.get_matrice() ;
00240         Matrice operateur(nr0, nr0) ;
00241         operateur.set_etat_qcq() ;
00242         if (dzp == 2)
00243         for (int lin=0; lin<nr0; lin++) 
00244             for (int col=dege; col<nr; col++)
00245             operateur.set(lin,col-dege) = (-mdx(lin,col) 
00246                     + n_factor*msx(lin, col)) / alpha ;
00247         else {
00248         for (int lin=0; lin<nr0; lin++) {
00249             for (int col=dege; col<nr; col++)
00250             operateur.set(lin,col-dege) = (-mxdx(lin,col) 
00251                     + n_factor*mid(lin, col)) ;
00252         }
00253         }
00254         operateur.set_lu() ;
00255         // homogeneous solution
00256         s_hom = new Tbl(solh(nr, n_factor-1, 0., R_CHEBU)) ;
00257         for (int k=0 ; k<np+1 ; k++)
00258         for (int j=0 ; j<nt ; j++) {
00259             base_resu.give_quant_numbers(lz, k, j, m_quant, l_quant, base_r) ;
00260             assert(base_r == R_CHEBU) ;     
00261             
00262             // particular solution
00263             so = new Tbl(nr0) ;
00264             so->set_etat_qcq() ;
00265             for (int i=0 ; i<nr0 ; i++)
00266             so->set(i) = source(nz-1, k, j, i) ;
00267             s_part = new Tbl(operateur.inverse(*so)) ;
00268 
00269             // cleaning
00270             double somme = 0 ;
00271             for (int i=0 ; i<nr0 ; i++) {
00272             sol_part.set(nz-1, k, j, i+dege) = (*s_part)(i) ;
00273             somme += (*s_part)(i) ;
00274             sol_hom.set(nz-1, k, j, i) = (*s_hom)(i) ;
00275             }
00276             for (int i=nr0; i<nr; i++)
00277             sol_hom.set(nz-1, k, j, i) = (*s_hom)(i) ;
00278             //result must vanish at infinity
00279             sol_part.set(nz-1, k, j, 0) = -somme ; 
00280             delete so ;
00281             delete s_part ;
00282         }
00283         delete s_hom ;
00284     }
00285     
00286     //-------------------------
00287     //-- matching solutions ---
00288     //-------------------------
00289     if (nz > 1) { 
00290         Tbl echelles(nz-1) ;
00291         echelles.set_etat_qcq() ;
00292         for (lz=1; lz<nz; lz++) 
00293         echelles.set(lz-1) 
00294             = pow ( (mpaff->get_beta()[lz]/mpaff->get_alpha()[lz] -1), 
00295                 n_factor) ;
00296         if (ced) echelles.set(nz-2) = 1./pow(-2., n_factor) ;
00297         
00298         for (int k=0 ; k<np+1 ; k++)
00299         for (int j=0 ; j<nt ; j++) {
00300             for (lz=1; lz<nz; lz++) {
00301             double val1 = 0 ;
00302             double valm1 = 0 ;
00303             double valhom1 = 0 ;
00304             int nr_prec = mg->get_nr(lz-1) ;
00305             nr = mg->get_nr(lz) ;
00306             for (int i=0; i<nr_prec; i++)
00307                 val1 += resu(lz-1, k, j, i) ;
00308             for (int i=0; i<nr; i++) {
00309                 valm1 += ( i%2 == 0 ? 1 : -1)*sol_part(lz, k, j, i) ;
00310                 valhom1 += ( i%2 == 0 ? 1 : -1)*sol_hom(lz, k, j, i) ;
00311             }
00312             double lambda = (val1 - valm1) * echelles(lz-1) ;
00313             for (int i=0; i<nr; i++)
00314                 resu.set(lz, k, j, i) = sol_part(lz, k, j, i) 
00315                 + lambda*sol_hom(lz, k, j, i) ;
00316 
00317             }
00318         }
00319     }
00320     }
00321     return result ;
00322 }
00323 

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