poisson_compact.C

00001 /*
00002  *   Copyright (c) 2000-2006 Philippe Grandclement
00003  *   Copyright (c) 2007 Michal Bejger
00004  *   Copyright (c) 2007 Eric Gourgoulhon
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 as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  *   LORENE is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with LORENE; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 
00025 char poisson_compact_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_compact.C,v 1.4 2007/10/16 21:54:23 e_gourgoulhon Exp $" ;
00026 
00027 /*
00028  * $Id: poisson_compact.C,v 1.4 2007/10/16 21:54:23 e_gourgoulhon Exp $
00029  * $Log: poisson_compact.C,v $
00030  * Revision 1.4  2007/10/16 21:54:23  e_gourgoulhon
00031  * Added new function sol_poisson_compact (multi-domain version).
00032  *
00033  * Revision 1.3  2006/09/05 13:39:46  p_grandclement
00034  * update of the bin_ns_bh project
00035  *
00036  * Revision 1.2  2002/10/16 14:37:12  j_novak
00037  * Reorganization of #include instructions of standard C++, in order to
00038  * use experimental version 3 of gcc.
00039  *
00040  * Revision 1.1.1.1  2001/11/20 15:19:28  e_gourgoulhon
00041  * LORENE
00042  *
00043  * Revision 2.2  2000/03/16  16:28:06  phil
00044  * Version entirement revue et corrigee
00045  *
00046  * Revision 2.1  2000/03/09  13:51:55  phil
00047  * *** empty log message ***
00048  *
00049  * Revision 2.0  2000/03/09  13:44:56  phil
00050  * *** empty log message ***
00051  *
00052  *
00053  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_compact.C,v 1.4 2007/10/16 21:54:23 e_gourgoulhon Exp $
00054  *
00055  */
00056 
00057 // Headers C
00058 #include <stdlib.h>
00059 #include <math.h>
00060 #include <assert.h>
00061 
00062 // Headers Lorene
00063 #include "map.h"
00064 #include "diff.h"
00065 #include "matrice.h"
00066 #include "type_parite.h"
00067 #include "proto.h"
00068 #include "base_val.h"
00069 #include "utilitaires.h"
00070 
00072     //  Single domain version  //
00074 
00075 /*
00076  * Cette fonction resout, dans le noyau :
00077  *  a*(1-xi^2)*lap(uu)+b*xi*duu/dxi = source
00078  * avec a>0 et b<0 ;
00079  * Pour le stokage des operateurs, il faut faire reamorce = true au
00080  * debut d'un nouveau calcul.
00081  */
00082 
00083 Mtbl_cf sol_poisson_compact(const Mtbl_cf& source, double a, double b, 
00084                 bool reamorce)  {
00085                     
00086     // Verifications :
00087     assert (source.get_etat() != ETATNONDEF) ;
00088     
00089     assert (a>0) ;
00090     assert (b<0) ;
00091     
00092     // Les tableaux de stockage :
00093     const int nmax = 200 ;
00094     static Matrice* tab_op[nmax] ;
00095     static int nb_deja_fait = 0 ;
00096     static int l_deja_fait[nmax] ;
00097     static int n_deja_fait[nmax] ;
00098     
00099     if (reamorce) {
00100     for (int i=0 ; i<nb_deja_fait ; i++)
00101         delete tab_op[i] ;
00102     nb_deja_fait = 0 ;
00103     }
00104     
00105     int nz = source.get_mg()->get_nzone() ;
00106 
00107     // Pour le confort (on ne travaille que dans le noyau) :
00108     int nr = source.get_mg()->get_nr(0) ;
00109     int nt = source.get_mg()->get_nt(0) ;
00110     int np = source.get_mg()->get_np(0) ;
00111      
00112     int l_quant ;
00113     int m_quant ;
00114     int base_r ;
00115     
00116     // La solution ...    
00117     Mtbl_cf solution(source.get_mg(), source.base) ;
00118     solution.set_etat_qcq() ;
00119     solution.t[0]->set_etat_qcq() ;
00120     
00121     for (int k=0 ; k<np+1 ; k++)
00122     for (int j=0 ; j<nt ; j++)
00123         if (nullite_plm(j, nt, k, np, source.base) == 1) 
00124         {
00125          // calcul des nombres quantiques :
00126         donne_lm(nz, 0, j, k, source.base, m_quant, l_quant, base_r) ;
00127         
00128         
00129         //On gere le cas l_quant == 0 (c'est bien simple y'en a pas !)
00130         if (l_quant == 0) {
00131         for (int i=0 ; i<nr ; i++)
00132             solution.set(0, k, j, i) = 0 ;
00133         }
00134         
00135         // cas l_quant != 0
00136         else {
00137         // On determine si la matrice a deja ete calculee :
00138         int indice = -1 ;
00139         
00140         // Le cas l==1 est non singulier : pas de base de Gelerkin
00141         int taille = (l_quant == 1) ? nr : nr-1 ;
00142         
00143         Matrice operateur (taille, taille) ;
00144         for (int conte=0 ; conte<nb_deja_fait ; conte++)
00145         if ((l_deja_fait[conte]== l_quant) && (n_deja_fait[conte] == nr))
00146             indice = conte ;
00147         
00148         if (indice == -1) {
00149         if (nb_deja_fait >= nmax) {
00150             cout << "sol_poisson_compact : trop de matrices ..." << endl;
00151             abort() ;
00152             } 
00153         // Calcul a faire :
00154         operateur = a*lap_cpt_mat (nr, l_quant, base_r) 
00155                 + b*xdsdx_mat(nr, l_quant, base_r) ;
00156         operateur = combinaison_cpt (operateur, l_quant, base_r) ;
00157         
00158         l_deja_fait[nb_deja_fait] = l_quant ;
00159         n_deja_fait[nb_deja_fait] = nr ;
00160         tab_op[nb_deja_fait] = new Matrice(operateur) ;
00161 
00162         nb_deja_fait++ ;
00163         }
00164         else {
00165         // rien a faire :
00166         operateur = *tab_op[indice] ;
00167         }
00168         
00169        // La source :
00170         Tbl so(taille) ;
00171         so.set_etat_qcq() ;
00172         for (int i=0 ; i<taille ; i++)
00173         so.set(i) = source(0, k, j, i) ;
00174         so = combinaison_cpt (so, base_r) ;
00175         
00176         Tbl part (operateur.inverse(so)) ;
00177         
00178         if (taille == nr)
00179         for (int i=0 ; i<nr ; i++)
00180              solution.set(0, k, j, i) = part(i) ; // cas l==1
00181         else {
00182         solution.set(0, k, j, nr-1) = 0 ;
00183         for (int i=nr-2 ; i>=0 ; i--)
00184             if (base_r == R_CHEBP) { //Gelerkin pair
00185             solution.set(0, k, j, i) = part(i) ;
00186             solution.set(0, k, j, i+1) += part(i) ;
00187             }
00188             else { //Gelerkin impaire
00189                 solution.set(0, k, j, i) = part(i)*(2*i+3) ;
00190             solution.set(0, k, j, i+1) += part(i)*(2*i+1) ;
00191             }
00192             }
00193         }
00194         }
00195         else   // cas ou nullite_plm = 0 :
00196         for (int i=0 ; i<nr ; i++)
00197             solution.set(0, k, j, i) = 0 ; 
00198         
00199     // Mise a zero du coefficient (inusite) k=np+1
00200     for (int j=0; j<nt; j++)
00201     for(int i=0 ; i<nr ; i++)
00202         solution.set(0, np+1, j, i) = 0 ; 
00203     
00204     for (int zone=1 ; zone<nz ; zone++)
00205         solution.t[zone]->set_etat_zero() ;
00206 
00207     return solution ;
00208 }
00209 
00210 
00211 
00213     //  Multi domain version  //
00215 
00216 
00217 Mtbl_cf sol_poisson_compact(const Map_af& mapping, const Mtbl_cf& source, 
00218         const Tbl& ac, const Tbl& bc, bool )  {
00219 
00220     // Number of domains inside the star :
00221     int nzet = ac.get_dim(1) ; 
00222     assert(nzet<=source.get_mg()->get_nzone()) ; 
00223     
00224     // Some checks
00225     assert (source.get_mg()->get_type_r(0) == RARE) ;
00226     for (int l=1 ; l<nzet ; l++)
00227         assert(source.get_mg()->get_type_r(l) == FIN) ;
00228 
00229     // Spectral bases
00230     const Base_val& base = source.base ;
00231     
00232     // Result
00233     Mtbl_cf resultat(source.get_mg(), base) ;
00234     resultat.annule_hard() ;
00235 
00236     // donnees sur la zone
00237     int nr, nt, np ;
00238     int base_r ;
00239     double alpha, beta, echelle ;
00240     int l_quant, m_quant;
00241 
00242     // Determination of the size of the systeme :
00243     int size = 0 ;
00244     int max_nr = 0 ;
00245     for (int l=0 ; l<nzet ; l++) { 
00246         nr = mapping.get_mg()->get_nr(l) ;
00247         size += nr ;
00248         if (nr > max_nr) max_nr = nr ;
00249     }
00250     
00251     Matrice systeme (size, size) ;
00252     systeme.set_etat_qcq() ;
00253     Tbl sec_membre (size) ;
00254     Tbl soluce (size) ;
00255     soluce.set_etat_qcq() ;
00256 
00257     np = mapping.get_mg()->get_np(0) ;
00258     nt = mapping.get_mg()->get_nt(0) ;
00259     Matrice* work ;
00260     
00261     // On bosse pour chaque l, m :
00262     for (int k=0 ; k<np+1 ; k++)
00263       for (int j=0 ; j<nt ; j++)
00264         if (nullite_plm(j, nt, k, np, base) == 1) {
00265     
00266     systeme.annule_hard() ;
00267     sec_membre.annule_hard() ;
00268          
00269     int column_courant = 0 ;
00270     int ligne_courant = 0 ;
00271     
00272     //--------------------------
00273     //       NUCLEUS
00274     //--------------------------
00275         
00276     nr = mapping.get_mg()->get_nr(0) ; 
00277     alpha = mapping.get_alpha()[0] ;
00278     base.give_quant_numbers (0, k, j, m_quant, l_quant, base_r) ;  
00279 
00280     if (l_quant == 0) {
00281         for (int i=0 ; i<size ; i++)
00282             soluce.set(i) = 0 ;
00283     }  
00284     else {
00285 
00286     Diff_dsdx2      d2_n(base_r, nr) ;      // suffix _n stands for "nucleus"
00287     Diff_sxdsdx     sxd_n(base_r, nr) ;
00288     Diff_sx2        sx2_n(base_r, nr) ;
00289     Diff_x2dsdx2    x2d2_n(base_r,nr) ;
00290     Diff_xdsdx      xd_n(base_r,nr) ;
00291     Diff_id         id_n(base_r,nr) ;  
00292     
00293     work = new Matrice( ac(0,0) * ( d2_n + 2.*sxd_n -l_quant*(l_quant+1)*sx2_n )
00294         + ac(0,2) * ( x2d2_n + 2.*xd_n -l_quant*(l_quant+1)*id_n ) 
00295         + alpha * bc(0,1) * xd_n ) ;
00296 
00297     // cout << *work << endl ; 
00298     // arrete() ; 
00299 
00300     // regularity conditions :
00301     int nbr_cl = 0 ;
00302     if (l_quant > 1) {
00303          nbr_cl = 1 ;
00304          if (l_quant%2==0) {
00305             //Even case
00306         for (int col=0 ; col<nr ; col++)
00307             if (col%2==0)
00308                 systeme.set(ligne_courant, col+column_courant) = 1 ;
00309             else 
00310                 systeme.set(ligne_courant, col+column_courant) = -1 ;
00311         }
00312          else {
00313          //Odd case
00314              for (int col=0 ; col<nr ; col++)
00315             if (col%2==0)
00316                 systeme.set(ligne_courant, col+column_courant) = 2*col+1 ;
00317             else 
00318                 systeme.set(ligne_courant, col+column_courant) = -(2*col+1) ;
00319         }
00320       ligne_courant ++ ;
00321     }
00322     
00323     // L'operateur :
00324     for (int lig=0 ; lig<nr-1-nbr_cl ; lig++) {
00325         for (int col=0 ; col<nr ; col++)
00326             systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
00327             sec_membre.set(lig+ligne_courant) = alpha*alpha*source(0, k, j, lig) ;
00328     }
00329     
00330     delete work ;
00331     ligne_courant += nr-1-nbr_cl ;
00332       
00333     // Le raccord :
00334     for (int col=0 ; col<nr ; col++) {
00335          // La fonction
00336          systeme.set(ligne_courant, col+column_courant) = 1 ;
00337          // Sa dérivée :
00338          if (l_quant%2==0)
00339              systeme.set(ligne_courant+1, col+column_courant) = 4*col*col/alpha ;
00340          else 
00341              systeme.set(ligne_courant+1, col+column_courant) = (2*col+1)*(2*col+1)/alpha ;
00342     }
00343     column_courant += nr ;
00344     
00345         //--------------------------
00346         //       SHELLS
00347         //--------------------------
00348 
00349     for (int l=1 ; l<nzet ; l++) {
00350     
00351         nr = mapping.get_mg()->get_nr(l) ; 
00352         alpha = mapping.get_alpha()[l] ;
00353         beta = mapping.get_beta()[l] ;
00354         echelle = beta/alpha ;
00355         double bsa = echelle ; 
00356         double bsa2 = bsa*bsa ; 
00357         
00358         base.give_quant_numbers (l, k, j, m_quant, l_quant, base_r) ;  
00359 
00360         Diff_dsdx       dx(base_r, nr) ; 
00361         Diff_xdsdx      xdx(base_r, nr) ; 
00362         Diff_x2dsdx     x2dx(base_r, nr) ; 
00363         Diff_x3dsdx     x3dx(base_r, nr) ; 
00364         Diff_dsdx2      dx2(base_r, nr) ; 
00365         Diff_xdsdx2     xdx2(base_r, nr) ; 
00366         Diff_x2dsdx2    x2dx2(base_r, nr) ; 
00367         Diff_x3dsdx2    x3dx2(base_r, nr) ; 
00368         Diff_id         id(base_r,nr) ;  
00369         Diff_mx         mx(base_r,nr) ;  
00370     
00371         work = new Matrice ( ac(l,0) * ( x2dx2 + 2.*bsa*xdx2 + bsa2*dx2 + 2.*xdx 
00372             + 2.*bsa*dx - l_quant*(l_quant+1)*id )
00373             + ac(l,1) * ( x3dx2 + 2.*bsa*x2dx2 + bsa2*xdx2 + 2.*x2dx 
00374             + 2.*bsa*xdx - l_quant*(l_quant+1) *mx )
00375             + alpha * ( bc(l,0) * ( x2dx + 2.*bsa*xdx + bsa2*dx ) 
00376                       + bc(l,1) * ( x3dx + 2.*bsa*x2dx + bsa2*xdx ) ) ) ;
00377     
00378        // matching with previous domain :
00379        for (int col=0 ; col<nr ; col++) {
00380          // La fonction
00381          if (col%2==0)
00382               systeme.set(ligne_courant, col+column_courant) = -1 ;
00383          else 
00384               systeme.set(ligne_courant, col+column_courant) = 1 ;
00385          // Sa dérivée :
00386          if (col%2==0)
00387              systeme.set(ligne_courant+1, col+column_courant) = col*col/alpha ;
00388          else 
00389              systeme.set(ligne_courant+1, col+column_courant) = -col*col/alpha ;
00390         }
00391       ligne_courant += 2 ;
00392       
00393       // source must be multiplied by (x+echelle)^2
00394       Tbl source_aux(nr) ;
00395       source_aux.set_etat_qcq() ;
00396       for (int i=0 ; i<nr ; i++)
00397         source_aux.set(i) = source(l,k,j,i)*alpha*alpha ;
00398         Tbl xso(source_aux) ;
00399         Tbl xxso(source_aux) ;
00400         multx_1d(nr, &xso.t, R_CHEB) ;
00401         multx_1d(nr, &xxso.t, R_CHEB) ;
00402         multx_1d(nr, &xxso.t, R_CHEB) ;
00403         source_aux = beta*beta/alpha/alpha*source_aux+2*beta/alpha*xso+xxso ;
00404       
00405       // L'operateur :
00406       
00407         for (int lig=0 ; lig<nr-1 ; lig++) {
00408             for (int col=0 ; col<nr ; col++)
00409             systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
00410             sec_membre.set(lig+ligne_courant) = source_aux(lig) ;
00411         }
00412       
00413         // cout << *work << endl ; 
00414         // arrete() ; 
00415 
00416       delete work ;
00417       ligne_courant += nr-2 ;
00418 
00419         if (l<nzet-1) {  // if this not the last shell
00420             //  matching with the next domain 
00421             for (int col=0 ; col<nr ; col++) {
00422             // La fonction
00423             systeme.set(ligne_courant, col+column_courant) = 1 ;
00424             // Sa dérivée :
00425             systeme.set(ligne_courant+1, col+column_courant) = col*col/alpha ;
00426             }
00427         }
00428          
00429       column_courant += nr ;   
00430 
00431       } // end loop on the shells (index l)
00432       
00433     // cout << "systeme : " << systeme << endl ; 
00434     // arrete() ;       
00435     
00436     // Solving the system:
00437  
00438     systeme.set_band (size, size) ;   
00439     systeme.set_lu() ;
00440 
00441     // cout << "Determinant: " << systeme.determinant() << endl ; 
00442     // cout << "Eigenvalues: " << systeme.val_propre() << endl ;
00443 
00444     soluce = systeme.inverse(sec_membre) ;
00445     
00446     } // end case l_quant != 0 
00447 
00448     // cout << "soluce: " << soluce << endl ; 
00449     // arrete() ; 
00450 
00451     // On range :
00452     int conte = 0 ;
00453     for (int l=0 ; l<nzet ; l++) {
00454          nr = mapping.get_mg()->get_nr(l) ;
00455          for (int i=0 ; i<nr ; i++) {
00456             resultat.set(l,k,j,i) = soluce(conte) ;
00457             conte++ ;
00458         }
00459     }
00460 
00461     } // end case nullite_plm == 1
00462 
00463     return resultat ;
00464 
00465 }
00466 
00467 
00468 
00469 
00470 
00471 
00472 
00473 
00474 
00475 
00476 
00477 
00478 
00479 
00480 

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