dalembert.C

00001 /*
00002  *   Copyright (c) 2000-2001 Jerome Novak
00003  *
00004  *   This file is part of LORENE.
00005  *
00006  *   LORENE is free software; you can redistribute it and/or modify
00007  *   it under the terms of the GNU General Public License as published by
00008  *   the Free Software Foundation; either version 2 of the License, or
00009  *   (at your option) any later version.
00010  *
00011  *   LORENE is distributed in the hope that it will be useful,
00012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *   GNU General Public License for more details.
00015  *
00016  *   You should have received a copy of the GNU General Public License
00017  *   along with LORENE; if not, write to the Free Software
00018  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019  *
00020  */
00021 
00022 
00023 char dalembert_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/dalembert.C,v 1.10 2008/08/27 08:51:15 jl_cornou Exp $" ;
00024 
00025 /*
00026  * $Id: dalembert.C,v 1.10 2008/08/27 08:51:15 jl_cornou Exp $
00027  * $Log: dalembert.C,v $
00028  * Revision 1.10  2008/08/27 08:51:15  jl_cornou
00029  * Added Jacobi(0,2) polynomials
00030  *
00031  * Revision 1.9  2006/08/31 08:56:40  j_novak
00032  * Added the possibility to have a shift in the quantum number l in the operator.
00033  *
00034  * Revision 1.8  2004/10/05 15:44:21  j_novak
00035  * Minor speed enhancements.
00036  *
00037  * Revision 1.7  2004/03/01 09:57:03  j_novak
00038  * the wave equation is solved with Scalars. It now accepts a grid with a
00039  * compactified external domain, which the solver ignores and where it copies
00040  * the values of the field from one time-step to the next.
00041  *
00042  * Revision 1.6  2003/12/19 16:21:49  j_novak
00043  * Shadow hunt
00044  *
00045  * Revision 1.5  2003/07/25 08:31:20  j_novak
00046  * Error corrected in the case of only nucleus
00047  *
00048  * Revision 1.4  2003/06/18 08:45:27  j_novak
00049  * In class Mg3d: added the member get_radial, returning only a radial grid
00050  * For dAlembert solver: the way the coefficients of the operator are defined has been changed.
00051  *
00052  * Revision 1.3  2002/01/03 13:18:41  j_novak
00053  * Optimization: the members set(i,j) and operator(i,j) of class Matrice are
00054  * now defined inline. Matrice is a friend class of Tbl.
00055  *
00056  * Revision 1.2  2002/01/02 14:07:57  j_novak
00057  * Dalembert equation is now solved in the shells. However, the number of
00058  * points in theta and phi must be the same in each domain. The solver is not
00059  * completely tested (beta version!).
00060  *
00061  * Revision 1.1.1.1  2001/11/20 15:19:28  e_gourgoulhon
00062  * LORENE
00063  *
00064  * Revision 1.1  2000/12/04  14:24:15  novak
00065  * Initial revision
00066  *
00067  *
00068  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/dalembert.C,v 1.10 2008/08/27 08:51:15 jl_cornou Exp $
00069  *
00070  */
00071 
00072 
00073 // Header C : 
00074 #include <math.h>
00075 
00076 // Headers Lorene :
00077 #include "param.h"
00078 #include "matrice.h"
00079 #include "map.h"
00080 #include "base_val.h"
00081 #include "proto.h"
00082 
00083 
00084         //----------------------------------------------
00085        //       Version Mtbl_cf
00086       //----------------------------------------------
00087 
00088 /*
00089  * 
00090  * Solution de l'equation de d'Alembert
00091  * 
00092  * Entree : mapping :   le mapping affine
00093  *      source : les coefficients de la source 
00094  *          La base de decomposition doit etre Ylm
00095  * Sortie : renvoie les coefficients de la solution dans la meme base de 
00096  *      decomposition (a savoir Ylm)
00097  *      
00098  */
00099 
00100 
00101 
00102 Mtbl_cf sol_dalembert(Param& par, const Map_af& mapping, const Mtbl_cf& source) 
00103 {
00104     
00105   // Verifications d'usage sur les zones
00106   int nz = source.get_mg()->get_nzone() ;
00107   bool ced = (source.get_mg()->get_type_r(nz-1) == UNSURR ) ;
00108   int nz0 = (ced ? nz - 1 : nz ) ;
00109   assert ((source.get_mg()->get_type_r(0) == RARE)||(source.get_mg()->get_type_r(0) == FINJAC)) ;
00110   for (int l=1 ; l<nz0 ; l++) {
00111     assert(source.get_mg()->get_type_r(l) == FIN) ;
00112     assert(source.get_mg()->get_nt(l) == source.get_mg()->get_nt(0)) ;
00113     assert(source.get_mg()->get_np(l) == source.get_mg()->get_np(0)) ;
00114   } // Same number of points in theta and phi in all domains...
00115   assert (par.get_n_double() > 0) ;
00116   assert (par.get_n_tbl_mod() > 1) ;
00117   
00118   //Is there a shift in the quantum number l?
00119   int dl = 0 ;  //value of the shift
00120   int l_min = 0 ; //the wave equation is solved only for l+dl >= l_min
00121   if (par.get_n_int() > 1) {
00122       dl = -1 ;
00123       l_min = par.get_int(1) ;
00124   }
00125 
00126   // Bases spectrales
00127   const Base_val& base = source.base ;
00128   
00129   // donnees sur la zone
00130   int nr, nt, np ;
00131   int base_r, type_dal ;
00132   double alpha, beta ;
00133   int l_quant, m_quant;
00134   nt = source.get_mg()->get_nt(0) ;
00135   np = source.get_mg()->get_np(0) ;
00136   
00137   //Rangement des valeurs intermediaires 
00138   Tbl *so ;
00139   Tbl *sol_hom ;
00140   Tbl *sol_hom2 ;
00141   Tbl *sol_part ;
00142   
00143   // Rangement des solutions, avant raccordement
00144   Mtbl_cf solution_part(source.get_mg(), base) ;
00145   Mtbl_cf solution_hom_un(source.get_mg(), base) ;
00146   Mtbl_cf solution_hom_deux(source.get_mg(), base) ;
00147   Mtbl_cf resultat(source.get_mg(), base) ;
00148   
00149   solution_part.set_etat_qcq() ;
00150   solution_hom_un.set_etat_qcq() ;
00151   solution_hom_deux.set_etat_qcq() ;
00152   resultat.annule_hard() ;
00153 
00154   // Tbls for the boundary condition
00155   double* bc1 = &par.get_double_mod(1) ;
00156   double* bc2 = &par.get_double_mod(2) ;
00157   Tbl* tbc3 = &par.get_tbl_mod(1) ;
00158   
00159   for (int l=0 ; l<nz ; l++) {
00160     solution_part.t[l]->annule_hard() ;
00161     solution_hom_un.t[l]->annule_hard() ;
00162     solution_hom_deux.t[l]->annule_hard() ;
00163   }  
00164   
00165   //---------------
00166   //--  NUCLEUS ---
00167   //---------------
00168   int lz = 0 ;
00169   nr = source.get_mg()->get_nr(lz) ;
00170   so = new Tbl(nr) ;
00171   
00172   alpha = mapping.get_alpha()[lz] ;
00173   
00174   for (int k=0 ; k<np+1 ; k++) {
00175       for (int j=0 ; j<nt ; j++) {
00176       // quantic numbers and spectral bases
00177       base.give_quant_numbers(lz, k, j, m_quant, l_quant, base_r) ;
00178       l_quant += dl ;
00179       if ( (nullite_plm(j, nt, k, np, base) == 1) && (l_quant >=l_min) )
00180       {
00181           //Calculation of the coefficients of the operator
00182           par.get_tbl_mod().set(4,lz) = 2*par.get_tbl_mod()(2,lz) ;
00183           par.get_tbl_mod().set(5,lz) = 2*par.get_tbl_mod()(3,lz) ;
00184           par.get_tbl_mod().set(6,lz) = 2*par.get_tbl_mod()(1,lz) ;
00185           par.get_tbl_mod().set(7,lz) = 
00186           -l_quant*(l_quant+1)*par.get_tbl_mod()(3,lz) ;
00187           par.get_tbl_mod().set(8,lz) = 
00188           -l_quant*(l_quant+1)*par.get_tbl_mod()(2,lz) ;
00189           par.get_tbl_mod().set(9,lz) = 
00190           -l_quant*(l_quant+1)*par.get_tbl_mod()(1,lz) ;
00191       
00192           Matrice operateur(nr,nr) ;
00193           
00194           get_operateur_dal(par, lz, base_r, type_dal, operateur) ;
00195           
00196           // Getting the particular solution
00197           so->set_etat_qcq() ;
00198           for (int i=0 ; i<nr ; i++)
00199           so->set(i) = source(lz, k, j, i) ;
00200           if ((type_dal == ORDRE1_LARGE) || (type_dal == O2DEGE_LARGE)
00201           || (type_dal == O2NOND_LARGE))
00202           so->set(nr-1) = 0 ;
00203           sol_part = new Tbl(dal_inverse(base_r, type_dal, operateur, 
00204                          *so, true)) ;
00205           
00206           // Getting the homogeneous solution
00207           sol_hom = new Tbl(dal_inverse(base_r, type_dal, operateur, 
00208                         *so, false)) ;
00209           
00210           // Putting to Mtbl_cf
00211           for (int i=0 ; i<nr ; i++) {
00212           solution_part.set(lz, k, j, i) = (*sol_part)(i) ;
00213           solution_hom_un.set(lz, k, j, i) = (*sol_hom)(i) ;
00214           solution_hom_deux.set(lz, k, j, i) = 0. ; 
00215           }
00216       
00217           // If only one zone, the BC is set
00218           if (nz0 == 1) {
00219           
00220           int base_pipo = 0 ;
00221           double part, dpart, hom, dhom;
00222           Tbl der_part(3,1,nr) ;
00223           der_part.set_etat_qcq() ;
00224           for (int i=0; i<nr; i++) 
00225               der_part.set(0,0,i) = (*sol_part)(i) ;
00226           Tbl der_hom(3,1,nr) ;
00227           der_hom.set_etat_qcq() ;
00228           for (int i=0; i<nr; i++) 
00229               der_hom.set(0,0,i) = (*sol_hom)(i) ;
00230           
00231           if (base_r == R_CHEBP) {
00232               som_r_chebp(sol_part->t, nr, 1, 1, 1., &part) ;
00233               _dsdx_r_chebp(&der_part, base_pipo) ;
00234               som_r_chebi(der_part.t, nr, 1, 1, 1., &dpart) ;
00235               som_r_chebp(sol_hom->t, nr, 1, 1, 1., &hom) ;
00236               _dsdx_r_chebp(&der_hom, base_pipo) ;
00237               som_r_chebi(der_hom.t, nr, 1, 1, 1., &dhom) ;
00238           }
00239           else {
00240               som_r_chebi(sol_part->t, nr, 1, 1, 1., &part) ;
00241               _dsdx_r_chebi(&der_part, base_pipo) ;
00242               som_r_chebp(der_part.t, nr, 1, 1, 1., &dpart) ;
00243               som_r_chebi(sol_hom->t, nr, 1, 1, 1., &hom) ;
00244               _dsdx_r_chebi(&der_hom, base_pipo) ;
00245               som_r_chebp(der_hom.t, nr, 1, 1, 1., &dhom) ;
00246           }
00247         
00248           part = part*(*bc1) + dpart*(*bc2)/alpha ;
00249           hom = hom*(*bc1) + dhom*(*bc2)/alpha ;
00250           double lambda = ((*tbc3)(k,j) - part) / hom ;
00251           for (int i=0 ; i<nr ; i++)
00252               resultat.set(lz, k, j, i) = 
00253               solution_part(lz, k, j, i)
00254               +lambda*solution_hom_un(lz, k, j, i) ; 
00255           }
00256           
00257           delete sol_hom ;
00258           delete sol_part ;
00259       } // nullite_plm
00260       } // theta loop
00261   } // phi loop  
00262   delete so ;
00263 
00264   //---------------------
00265   //--      SHELLS     --
00266   //---------------------
00267   for (lz=1 ; lz<nz0 ; lz++) {
00268     nr = source.get_mg()->get_nr(lz) ;
00269     so = new Tbl(nr) ;
00270     alpha = mapping.get_alpha()[lz] ;
00271     beta = mapping.get_beta()[lz] ;
00272     
00273     for (int k=0 ; k<np+1 ; k++)
00274     for (int j=0 ; j<nt ; j++) {
00275         // quantic numbers and spectral bases
00276         base.give_quant_numbers(lz, k, j, m_quant, l_quant, base_r) ;
00277         l_quant += dl ;
00278         if ( (nullite_plm(j, nt, k, np, base) == 1) && (l_quant >=l_min) )
00279         {
00280         //Calculation of the coefficients of the operator
00281         par.get_tbl_mod().set(4,lz) = 2*par.get_tbl_mod()(2,lz) ;
00282         par.get_tbl_mod().set(5,lz) = 2*par.get_tbl_mod()(3,lz) ;
00283         par.get_tbl_mod().set(6,lz) = 2*par.get_tbl_mod()(1,lz) ;
00284         par.get_tbl_mod().set(7,lz) = 
00285             -l_quant*(l_quant+1)*par.get_tbl_mod()(3,lz) ;
00286         par.get_tbl_mod().set(8,lz) = 
00287             -l_quant*(l_quant+1)*par.get_tbl_mod()(2,lz) ;
00288         par.get_tbl_mod().set(9,lz) = 
00289             -l_quant*(l_quant+1)*par.get_tbl_mod()(1,lz) ;
00290         
00291         Matrice operateur(nr,nr) ;
00292         
00293         get_operateur_dal(par, lz, base_r, type_dal, operateur) ;
00294         
00295         // Calcul DES DEUX SH
00296         so->set_etat_qcq() ;
00297         for (int i=0; i<nr; i++) so->set(i) = 0. ;
00298         so->set(nr-2) = 1. ;
00299         sol_hom = new Tbl(dal_inverse(base_r, type_dal, operateur, *so,
00300                           false)) ;
00301         so->set(nr-2) = 0. ;
00302         so->set(nr-1) = 1. ;
00303         sol_hom2 = new Tbl(dal_inverse(base_r, type_dal, operateur, *so,
00304                            false)) ;
00305         
00306         // Calcul de la SP
00307         double *tmp = new double[nr] ;
00308         for (int i=0 ; i<nr ; i++)
00309             tmp[i] = source(lz, k, j, i) ;
00310         if ((type_dal == O2DEGE_SMALL) || (type_dal == O2DEGE_LARGE)) {
00311             for (int i=0; i<nr; i++) so->set(i) = beta*tmp[i] ;
00312             multx_1d(nr, &tmp, R_CHEB) ;
00313             for (int i=0; i<nr; i++) so->set(i) += alpha*tmp[i] ;
00314         }
00315         else {
00316             for (int i=0; i<nr; i++) so->set(i) = beta*beta*tmp[i] ;
00317             multx_1d(nr, &tmp, R_CHEB) ;
00318             for (int i=0; i<nr; i++) so->set(i) += 2*alpha*beta*tmp[i] ;
00319             multx_1d(nr, &tmp, R_CHEB) ;
00320             for (int i=0; i<nr; i++) so->set(i) += alpha*alpha*tmp[i] ;
00321         }
00322         so->set(nr-2) = 0. ;
00323         so->set(nr-1) = 0. ;
00324         
00325         sol_part = new Tbl (dal_inverse(base_r, type_dal, operateur, 
00326                         *so, true)) ;       
00327         // Rangement
00328         for (int i=0 ; i<nr ; i++) {
00329             solution_part.set(lz, k, j, i) = (*sol_part)(i) ;
00330             solution_hom_un.set(lz, k, j, i) = (*sol_hom)(i) ;
00331             solution_hom_deux.set(lz, k, j, i) = (*sol_hom2)(i) ;
00332         }
00333         
00334         delete [] tmp ;
00335         delete sol_hom ;
00336         delete sol_hom2 ;
00337         delete sol_part ;
00338         }
00339     } // theta loop
00340     delete so ;
00341   } // domain loop
00342   if (nz0 > 1) {
00343     //--------------------------------------------------------------------
00344     //
00345     //     Combinations of particular and homogeneous solutions
00346     //         to verify continuity and boundary conditions
00347     //
00348     //--------------------------------------------------------------------
00349     int taille = 2*nz0 - 1 ; 
00350     Tbl deuz(taille) ;
00351     deuz.set_etat_qcq() ;
00352     Matrice systeme(taille,taille) ;
00353     systeme.set_etat_qcq() ;
00354     int sup = 2;
00355     int inf = (nz0>2) ? 2 : 1 ;
00356     for (int k=0; k<np+1; k++) {
00357       for (int j=0; j<nt; j++) {
00358       // To get the r basis in the nucleus
00359       base.give_quant_numbers(0, k, j, m_quant, l_quant, base_r) ;
00360       if ( (nullite_plm(j, nt, k, np, base)) && (l_quant + dl >= l_min) ) {
00361           assert ((base_r == R_CHEBP)||(base_r == R_CHEBI)) ;
00362           int parite = (base_r == R_CHEBP) ? 0 : 1 ;
00363           int l, c ; 
00364           double xx = 0.;
00365           for (l=0; l<taille; l++) 
00366           for (c=0; c<taille; c++) systeme.set(l,c) = xx ;
00367           for (l=0; l<taille; l++) deuz.set(l) = xx ;
00368       
00369           //---------
00370           // Nucleus
00371           //---------
00372           nr = source.get_mg()->get_nr(0) ;
00373           alpha = mapping.get_alpha()[0] ;
00374           l=0 ; c=0 ;
00375           for (int i=0; i<nr; i++) 
00376           systeme.set(l,c) += solution_hom_un(0, k, j, i) ;
00377           for (int i=0; i<nr; i++) deuz.set(l) -= solution_part(0, k, j, i) ;
00378           
00379           l++ ;
00380           xx = 0. ;
00381           for (int i=0; i<nr; i++)
00382           xx +=(2*i+parite)*(2*i+parite)
00383               *solution_hom_un(0, k, j, i) ;
00384           systeme.set(l,c) += xx/alpha ;
00385           xx = 0. ; 
00386           for (int i=0; i<nr; i++) xx -= (2*i+parite)*
00387                        (2*i+parite)*solution_part(0, k, j, i) ;
00388           deuz.set(l) += xx/alpha ;
00389       
00390           //----------
00391           //  Shells
00392           //----------
00393           for (lz=1; lz<nz0; lz++) {
00394           nr = source.get_mg()->get_nr(lz) ;
00395           alpha = mapping.get_alpha()[lz] ;
00396           l-- ; 
00397           c = l+1 ;
00398           for (int i=0; i<nr; i++) 
00399               if (i%2 == 0)
00400               systeme.set(l,c) -= solution_hom_un(lz, k, j, i) ;
00401               else
00402               systeme.set(l,c) += solution_hom_un(lz, k, j, i) ;
00403           c++ ;
00404           for (int i=0; i<nr; i++) 
00405               if (i%2 == 0)
00406               systeme.set(l,c) -= solution_hom_deux(lz, k, j, i) ;
00407               else
00408               systeme.set(l,c) += solution_hom_deux(lz, k, j, i) ;
00409           for (int i=0; i<nr; i++) 
00410               if (i%2 == 0) deuz.set(l) += solution_part(lz, k, j, i) ;
00411               else deuz.set(l) -= solution_part(lz, k, j, i) ;
00412           
00413           l++ ; c-- ;
00414           xx = 0. ;
00415           for (int i=0; i<nr; i++) 
00416               if (i%2 == 0)
00417               xx += i*i*solution_hom_un(lz, k, j, i) ;
00418               else
00419               xx -= i*i*solution_hom_un(lz, k, j, i) ;
00420           systeme.set(l,c) += xx/alpha ;
00421           c++ ;
00422           xx = 0. ;
00423           for (int i=0; i<nr; i++) 
00424               if (i%2 == 0)
00425               xx += i*i*solution_hom_deux(lz, k, j, i) ;
00426               else
00427               xx -= i*i*solution_hom_deux(lz, k, j, i) ;
00428           systeme.set(l,c) += xx/alpha ;
00429           xx = 0. ;
00430           for (int i=0; i<nr; i++) 
00431               if (i%2 == 0) xx -= i*i*solution_part(lz, k, j, i) ;
00432               else xx += i*i*solution_part(lz, k, j, i) ;
00433           deuz.set(l) += xx/alpha ;
00434           
00435           l++ ; c--;
00436           if (lz == nz0-1) { // Last domain, the outer BC is set
00437               for (int i=0; i<nr; i++) 
00438               systeme.set(l,c) +=
00439                   ((*bc1)+(*bc2)*i*i/alpha)*solution_hom_un(lz, k, j, i) ;
00440               c++ ;
00441               for (int i=0; i<nr; i++) 
00442               systeme.set(l,c) +=
00443                   ((*bc1)+(*bc2)*i*i/alpha)*solution_hom_deux(lz, k, j, i) ;
00444               for (int i=0; i<nr; i++) 
00445               deuz.set(l) -=
00446                   ((*bc1)+(*bc2)*i*i/alpha)*solution_part(lz, k, j, i) ;
00447               deuz.set(l) += (*tbc3)(k,j) ;
00448           }
00449           else { // At least one more shell
00450               for (int i=0; i<nr; i++) 
00451               systeme.set(l,c) += solution_hom_un(lz, k, j, i) ;
00452               c++ ;
00453               for (int i=0; i<nr; i++) 
00454               systeme.set(l,c) += solution_hom_deux(lz, k, j, i) ;
00455               for (int i=0; i<nr; i++) 
00456               deuz.set(l) -= solution_part(lz, k, j, i) ;
00457               l++ ; c-- ;
00458               xx = 0. ;
00459               for (int i=0; i<nr; i++) xx += i*i*solution_hom_un(lz, k, j, i) ;
00460               systeme.set(l,c) += xx/alpha ;
00461               c++ ;
00462               xx = 0. ;
00463               for (int i=0; i<nr; i++) 
00464               xx += i*i*solution_hom_deux(lz, k, j, i) ;
00465               systeme.set(l,c) += xx/alpha ;
00466               xx = 0. ;
00467               for (int i=0; i<nr; i++) 
00468               xx -= i*i*solution_part(lz, k, j, i) ;     
00469               deuz.set(l) += xx/alpha ;
00470           }
00471           }
00472 
00473           //--------------------------------------
00474           //   Solution of the linear system
00475           //--------------------------------------
00476       
00477           systeme.set_band(sup, inf) ;
00478           systeme.set_lu() ;
00479           Tbl facteur(systeme.inverse(deuz)) ;
00480           
00481           //Linear Combination in the nucleus
00482           nr = source.get_mg()->get_nr(0) ;
00483           for (int i=0; i<nr; i++) 
00484           resultat.set(0, k, j, i) = solution_part(0, k, j, i) 
00485               + facteur(0)*solution_hom_un(0, k, j, i) ;
00486           
00487           //Linear combination in the shells
00488           for (lz=1; lz<nz0; lz++) {
00489           nr = source.get_mg()->get_nr(lz) ;
00490           for (int i=0; i<nr; i++) 
00491               resultat.set(lz, k, j, i) = solution_part(lz, k, j, i) 
00492               + facteur(2*lz-1)*solution_hom_un(lz, k, j, i) 
00493               + facteur(2*lz)*solution_hom_deux(lz, k, j, i) ;
00494           }
00495       }        
00496       } //End of j/theta loop   
00497     } //End of k/phi loop 
00498   } //End of case nz0>1
00499   
00500   return resultat ;
00501 
00502 }

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