poisson_tau.C

00001 /*
00002  *   Copyright (c) 2005 Philippe Grandclement
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 poisson_tau_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_tau.C,v 1.7 2008/08/27 08:51:15 jl_cornou Exp $" ;
00024 
00025 /*
00026  * $Id: poisson_tau.C,v 1.7 2008/08/27 08:51:15 jl_cornou Exp $
00027  * $Log: poisson_tau.C,v $
00028  * Revision 1.7  2008/08/27 08:51:15  jl_cornou
00029  * Added Jacobi(0,2) polynomials
00030  *
00031  * Revision 1.6  2007/12/14 10:19:34  jl_cornou
00032  * *** empty log message ***
00033  *
00034  * Revision 1.4  2005/11/24 14:07:54  j_novak
00035  * Use of Matrice::annule_hard()
00036  *
00037  * Revision 1.3  2005/08/26 14:02:41  p_grandclement
00038  * Modification of the elliptic solver that matches with an oscillatory exterior solution
00039  * small correction in Poisson tau also...
00040  *
00041  * Revision 1.2  2005/08/25 12:16:01  p_grandclement
00042  * *** empty log message ***
00043  *
00044  * 
00045  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_tau.C,v 1.7 2008/08/27 08:51:15 jl_cornou Exp $
00046  *
00047  */
00048 
00049 // Header C : 
00050 #include <stdlib.h>
00051 #include <math.h>
00052 
00053 // Headers Lorene :
00054 #include "matrice.h"
00055 #include "map.h"
00056 #include "proto.h"
00057 #include "type_parite.h"
00058 
00059 
00060 
00061         //----------------------------------------------
00062        //       Version Mtbl_cf
00063       //----------------------------------------------
00064 
00065 /*
00066  * 
00067  * Solution de l'equation de poisson with a multi-domain Tau method
00068  * 
00069  * Entree : mapping :   le mapping affine
00070  *      source : les coefficients de la source qui a ete multipliee par
00071  *          r^4 r^3 ou r^2 dans la ZEC.
00072  *          La base de decomposition doit etre Ylm
00073  *      dzpuis : exposant de r dans le factor multiplicatif dans la ZEC
00074  * Sortie : renvoie les coefficients de la solution dans la meme base de 
00075  *      decomposition (a savoir Ylm)
00076  *      
00077  */
00078 
00079 
00080 Mtbl_cf sol_poisson_tau(const Map_af& mapping, const Mtbl_cf& source, int dzpuis)
00081 {
00082     
00083     // Verifications d'usage sur les zones
00084     int nz = source.get_mg()->get_nzone() ;
00085     assert (nz>1) ;
00086     assert ((source.get_mg()->get_type_r(0) == RARE) || (source.get_mg()->get_type_r(0) == FINJAC)) ;
00087     assert (source.get_mg()->get_type_r(nz-1) == UNSURR) ;
00088     for (int l=1 ; l<nz-1 ; l++)
00089     assert(source.get_mg()->get_type_r(l) == FIN) ;
00090 
00091      assert ((dzpuis==4) || (dzpuis==2) || (dzpuis==3)) ;
00092        
00093     // Bases spectrales
00094     const Base_val& base = source.base ;
00095     
00096     // Resultat
00097     Mtbl_cf resultat(source.get_mg(), base) ;
00098     resultat.annule_hard() ;
00099      
00100     // donnees sur la zone
00101     int nr, nt, np ;
00102     int base_r ;
00103     double alpha, beta, echelle ;
00104     int l_quant, m_quant;
00105     
00106     // Determination of the size of the systeme :
00107     int size = 0 ;
00108     int max_nr = 0 ;
00109     for (int l=0 ; l<nz ; l++) { 
00110         nr = mapping.get_mg()->get_nr(l) ;
00111         size += nr ;
00112     if (nr > max_nr)
00113         max_nr = nr ;
00114     }
00115     
00116     Matrice systeme (size, size) ;
00117     systeme.set_etat_qcq() ;
00118     Tbl sec_membre (size) ;
00119    
00120     np = mapping.get_mg()->get_np(0) ;
00121     nt = mapping.get_mg()->get_nt(0) ;
00122     Matrice* work ;
00123     
00124     // On bosse pour chaque l, m :
00125     for (int k=0 ; k<np+1 ; k++)
00126       for (int j=0 ; j<nt ; j++) 
00127     if (nullite_plm(j, nt, k, np, base) == 1) {
00128     
00129 //  for (int lig=0 ; lig<size ; lig++)
00130 //             for (int col=0 ; col< size ; col++)
00131 //      systeme.set(lig,col) = 0 ;
00132     systeme.annule_hard() ;
00133     sec_membre.annule_hard() ;
00134          
00135     int column_courant = 0 ;
00136     int ligne_courant = 0 ;
00137     
00138             //--------------------------
00139         //       NUCLEUS
00140         //--------------------------
00141         
00142     nr = mapping.get_mg()->get_nr(0) ; 
00143     alpha = mapping.get_alpha()[0] ;
00144         base.give_quant_numbers (0, k, j, m_quant, l_quant, base_r) ;  
00145         work = new Matrice (laplacien_mat(nr, l_quant, 0., 0, base_r)) ;
00146 
00147     int nbr_cl = 0 ;
00148     // RARE case    
00149     if (source.get_mg()->get_type_r(0) == RARE) {
00150     // regularity conditions :
00151     if (l_quant > 1) {
00152          nbr_cl = 1 ;
00153          if (l_quant%2==0) {
00154             //Even case
00155         for (int col=0 ; col<nr ; col++)
00156             if (col%2==0)
00157                 systeme.set(ligne_courant, col+column_courant) = 1 ;
00158             else 
00159                 systeme.set(ligne_courant, col+column_courant) = -1 ;
00160         }
00161          else {
00162          //Odd case
00163              for (int col=0 ; col<nr ; col++)
00164             if (col%2==0)
00165                 systeme.set(ligne_courant, col+column_courant) = 2*col+1 ;
00166             else 
00167                 systeme.set(ligne_courant, col+column_courant) = -(2*col+1) ;
00168         }
00169       }
00170     }
00171 
00172     // FINJAC case
00173     else {
00174     // regularity conditions :
00175     if (l_quant == 0) {
00176         nbr_cl = 1 ;
00177         for (int col=0 ; col<nr ; col++) {
00178             systeme.set(ligne_courant, col+column_courant) =  col*(col+1)*(col+2)*(col+3)/double(12)*(2*(col%2)-1);
00179         }
00180         }
00181     else if (l_quant == 1) {
00182         nbr_cl = 1 ;
00183         for (int col=0 ; col<nr ; col++) {
00184             systeme.set(ligne_courant, col+column_courant) = (col+1)*(col+2)/double(2)*(1-2*(col%2)) ;
00185         }
00186         }
00187     else {
00188         nbr_cl = 2 ;
00189         for (int col=0 ; col<nr ; col++) {
00190             systeme.set(ligne_courant, col+column_courant) = (col+1)*(col+2)/double(2)*(1-2*(col%2)) ;
00191             systeme.set(ligne_courant+1, col+column_courant) = col*(col+1)*(col+2)*(col+3)/double(12)*(2*(col%2)-1) ;
00192         }
00193         }
00194     }   
00195     ligne_courant += nbr_cl ;
00196 
00197     // L'operateur :
00198     for (int lig=0 ; lig<nr-1-nbr_cl ; lig++) {
00199         for (int col=0 ; col<nr ; col++)
00200             systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
00201             sec_membre.set(lig+ligne_courant) = alpha*alpha*source(0, k, j, lig) ;
00202     }
00203     
00204     delete work ;
00205     ligne_courant += nr-1-nbr_cl ;
00206       
00207     // Le raccord :
00208     for (int col=0 ; col<nr ; col++) {
00209          if (source.get_mg()->get_type_r(0) == RARE) {
00210          // La fonction
00211          systeme.set(ligne_courant, col+column_courant) = 1 ;
00212          // Sa d�riv�e :
00213          if (l_quant%2==0) {
00214              systeme.set(ligne_courant+1, col+column_courant) = 4*col*col/alpha ;
00215          }
00216          else { 
00217              systeme.set(ligne_courant+1, col+column_courant) = (2*col+1)*(2*col+1)/alpha ;
00218         }
00219           }
00220          else {
00221          // La fonction
00222          systeme.set(ligne_courant, col+column_courant) = 1 ; 
00223          // Sa dérivée :
00224          systeme.set(ligne_courant+1, col+column_courant) = col*(col+3)/double(2)/alpha ;
00225           }
00226          }
00227       
00228     column_courant += nr ;
00229       
00230       
00231 
00232 
00233         //--------------------------
00234         //       SHELLS
00235         //--------------------------
00236     for (int l=1 ; l<nz-1 ; l++) {
00237     
00238         nr = mapping.get_mg()->get_nr(l) ; 
00239         alpha = mapping.get_alpha()[l] ;
00240         beta = mapping.get_beta()[l] ;
00241         echelle = beta/alpha ;
00242         
00243             base.give_quant_numbers (l, k, j, m_quant, l_quant, base_r) ;  
00244             work = new Matrice (laplacien_mat(nr, l_quant, echelle, 0, base_r)) ;
00245     
00246        // matching with previous domain :
00247        for (int col=0 ; col<nr ; col++) {
00248          // La fonction
00249          if (col%2==0)
00250               systeme.set(ligne_courant, col+column_courant) = -1 ;
00251          else 
00252               systeme.set(ligne_courant, col+column_courant) = 1 ;
00253          // Sa d�riv�e :
00254          if (col%2==0)
00255              systeme.set(ligne_courant+1, col+column_courant) = col*col/alpha ;
00256          else 
00257              systeme.set(ligne_courant+1, col+column_courant) = -col*col/alpha ;
00258       }
00259       ligne_courant += 2 ;
00260       
00261       // L'operateur :
00262       
00263       // source must be multiplied by (x+echelle)^2
00264       Tbl source_aux(nr) ;
00265       source_aux.set_etat_qcq() ;
00266       for (int i=0 ; i<nr ; i++)
00267           source_aux.set(i) = source(l,k,j,i)*alpha*alpha ;
00268         Tbl xso(source_aux) ;
00269         Tbl xxso(source_aux) ;
00270         multx_1d(nr, &xso.t, R_CHEB) ;
00271         multx_1d(nr, &xxso.t, R_CHEB) ;
00272         multx_1d(nr, &xxso.t, R_CHEB) ;
00273         source_aux = beta*beta/alpha/alpha*source_aux+2*beta/alpha*xso+xxso ;
00274       
00275     for (int lig=0 ; lig<nr-2 ; lig++) {
00276          for (int col=0 ; col<nr ; col++)
00277              systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
00278          sec_membre.set(lig+ligne_courant) = source_aux(lig) ;
00279       }
00280       
00281       delete work ;
00282       ligne_courant += nr-2 ;
00283       // Matching with the next domain :
00284       for (int col=0 ; col<nr ; col++) {
00285          // La fonction
00286          systeme.set(ligne_courant, col+column_courant) = 1 ;
00287          // Sa d�riv�e :
00288          systeme.set(ligne_courant+1, col+column_courant) = col*col/alpha ;
00289          }
00290          
00291       column_courant += nr ;   
00292       }
00293       
00294       
00295         //--------------------------
00296         //       ZEC
00297         //--------------------------
00298     nr = mapping.get_mg()->get_nr(nz-1) ; 
00299     alpha = mapping.get_alpha()[nz-1] ;
00300     beta = mapping.get_beta()[nz-1] ;
00301         
00302     base.give_quant_numbers (nz-1, k, j, m_quant, l_quant, base_r) ;  
00303     work = new Matrice(laplacien_mat(nr, l_quant, 0., dzpuis, base_r)) ;
00304     
00305     // Matching with the previous domain :
00306      for (int col=0 ; col<nr ; col++) {
00307          // La fonction
00308          if (col%2==0)
00309               systeme.set(ligne_courant, col+column_courant) = -1 ;
00310          else 
00311               systeme.set(ligne_courant, col+column_courant) = 1 ;
00312          // Sa d�riv�e :
00313          if (col%2==0)
00314              systeme.set(ligne_courant+1, col+column_courant) = -4*alpha*col*col ;
00315          else 
00316              systeme.set(ligne_courant+1, col+column_courant) = 4*alpha*col*col ;
00317       }
00318       ligne_courant += 2 ;  
00319       
00320       // Regularity and BC at infinity ?
00321       nbr_cl =0 ;
00322       switch (dzpuis) {
00323            case 4 : 
00324                if (l_quant==0) {
00325                nbr_cl = 1 ;
00326                // Only BC at infinity :
00327                for (int col=0 ; col<nr ; col++)
00328                    systeme.set(ligne_courant, col+column_courant) = 1 ;
00329                }
00330            else { 
00331                nbr_cl = 2 ;
00332                // BC at infinity :
00333                for (int col=0 ; col<nr ; col++)
00334                    systeme.set(ligne_courant, col+column_courant) = 1 ;
00335                // Regularity :
00336                for (int col=0 ; col<nr ; col++)
00337                    systeme.set(ligne_courant+1, col+column_courant) = -4*alpha*col*col ;   
00338             }
00339             break ;
00340            
00341             case 3 :
00342             nbr_cl = 1 ;
00343             // Only BC at infinity :
00344             for (int col=0 ; col<nr ; col++)
00345                systeme.set(ligne_courant, col+column_courant) = 1 ;
00346             break ;
00347         
00348         case 2 :
00349              if (l_quant==0) {
00350                  nbr_cl = 1 ;
00351                 // Only BC at infinity :
00352                 for (int col=0 ; col<nr ; col++)
00353                    systeme.set(ligne_courant, col+column_courant) = 1 ;
00354             }
00355              break ;
00356         default : 
00357             cout << "Unknown dzpuis in sol_poisson_tau ..." << endl ;
00358             abort() ;
00359     }
00360     
00361     ligne_courant += nbr_cl ;
00362     
00363     // Multiplication of the source :
00364     double indic = 1 ;
00365     switch (dzpuis) {
00366         case 4 : 
00367             indic = alpha*alpha ;
00368         break ;
00369         case 3 :
00370             indic = alpha ;
00371         break ;
00372     default : 
00373          break ;
00374     }
00375     
00376     // L'operateur :
00377     for (int lig=0 ; lig<nr-1-nbr_cl ; lig++) {
00378         for (int col=0 ; col<nr ; col++)
00379            systeme.set(lig+ligne_courant,col+column_courant) = (*work)(lig,col) ;
00380         sec_membre.set(lig+ligne_courant) = indic*source(nz-1, k, j, lig) ;
00381     }
00382     delete work ;
00383     
00384     // Solving the system:
00385     systeme.set_band (max_nr, max_nr) ;
00386     systeme.set_lu() ;
00387     Tbl soluce (systeme.inverse(sec_membre)) ;
00388     
00389     // On range :
00390     int conte = 0 ;
00391     for (int l=0 ; l<nz ; l++) {
00392          nr = mapping.get_mg()->get_nr(l) ;
00393          for (int i=0 ; i<nr ; i++) {
00394              resultat.set(l,k,j,i) = soluce(conte) ;
00395          conte ++ ;
00396         }
00397     }
00398     
00399     }
00400 
00401     return resultat ;
00402 }

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