poisson_falloff.C

00001 /*
00002  *  Method of Non_class_members for solving Poisson equations
00003  *   with a falloff condition at the outer boundary
00004  *
00005  */
00006 
00007 /*
00008  *   Copyright (c) 2004 Joshua A. Faber
00009  *
00010  *   This file is part of LORENE.
00011  *
00012  *   LORENE is free software; you can redistribute it and/or modify
00013  *   it under the terms of the GNU General Public License version 2
00014  *   as published by the Free Software Foundation.
00015  *
00016  *   LORENE is distributed in the hope that it will be useful,
00017  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *   GNU General Public License for more details.
00020  *
00021  *   You should have received a copy of the GNU General Public License
00022  *   along with LORENE; if not, write to the Free Software
00023  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00024  *
00025  */
00026 
00027 char poisson_falloff_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_falloff.C,v 1.1 2004/11/30 20:55:03 k_taniguchi Exp $" ;
00028 
00029 /*
00030  * $Id: poisson_falloff.C,v 1.1 2004/11/30 20:55:03 k_taniguchi Exp $
00031  * $Log: poisson_falloff.C,v $
00032  * Revision 1.1  2004/11/30 20:55:03  k_taniguchi
00033  * *** empty log message ***
00034  *
00035  *
00036  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_falloff.C,v 1.1 2004/11/30 20:55:03 k_taniguchi Exp $
00037  *
00038  */
00039 
00040 // Header C : 
00041 #include <stdlib.h>
00042 #include <math.h>
00043 
00044 // Headers Lorene :
00045 #include "matrice.h"
00046 #include "tbl.h"
00047 #include "mtbl_cf.h"
00048 #include "map.h"
00049 #include "base_val.h"
00050 #include "proto.h"
00051 #include "type_parite.h"
00052 
00053 
00054 
00055         //----------------------------------------------
00056        //       Version Mtbl_cf
00057       //----------------------------------------------
00058 
00059 /*
00060  * 
00061  * Solution de l'equation de poisson
00062  * 
00063  * Entree : mapping :   le mapping affine
00064  *      source : les coefficients de la source qui a ete multipliee par
00065  *          r^4 ou r^2 dans la ZEC.
00066  *          La base de decomposition doit etre Ylm
00067  *      k_falloff: exponent in radial dependence of field: phi \propto r^{-k}
00068  * Sortie : renvoie les coefficients de la solution dans la meme base de 
00069  *      decomposition (a savoir Ylm)
00070  *      
00071  */
00072 
00073 
00074 
00075 Mtbl_cf sol_poisson_falloff(const Map_af& mapping, const Mtbl_cf& source, const int k_falloff)
00076 {
00077     
00078     // Verifications d'usage sur les zones
00079     int nz = source.get_mg()->get_nzone() ;
00080     assert (nz>1) ;
00081     assert (source.get_mg()->get_type_r(0) == RARE) ;
00082     //    assert (source.get_mg()->get_type_r(nz-1) == UNSURR) ;
00083     for (int l=1 ; l<nz ; l++)
00084     assert(source.get_mg()->get_type_r(l) == FIN) ;
00085 
00086     //     assert ((dzpuis==4) || (dzpuis==2) || (dzpuis==3)) ;
00087     
00088     
00089     // Bases spectrales
00090     const Base_val& base = source.base ;
00091     
00092     
00093     // donnees sur la zone
00094     int nr, nt, np ;
00095     int base_r ;
00096     double alpha, beta, echelle ;
00097     int l_quant, m_quant;
00098     
00099     //Rangement des valeurs intermediaires 
00100     Tbl *so ;
00101     Tbl *sol_hom ;
00102     Tbl *sol_part ;
00103     Matrice *operateur ;
00104     Matrice *nondege ;
00105     
00106     
00107     // Rangement des solutions, avant raccordement
00108     Mtbl_cf solution_part(source.get_mg(), base) ;
00109     Mtbl_cf solution_hom_un(source.get_mg(), base) ;
00110     Mtbl_cf solution_hom_deux(source.get_mg(), base) ;
00111     Mtbl_cf resultat(source.get_mg(), base) ;
00112     
00113     solution_part.set_etat_qcq() ;
00114     solution_hom_un.set_etat_qcq() ;
00115     solution_hom_deux.set_etat_qcq() ;
00116     resultat.set_etat_qcq() ;
00117     
00118     for (int l=0 ; l<nz ; l++) {
00119     solution_part.t[l]->set_etat_qcq() ;
00120     solution_hom_un.t[l]->set_etat_qcq() ;
00121     solution_hom_deux.t[l]->set_etat_qcq() ;
00122     resultat.t[l]->set_etat_qcq() ;
00123     for (int k=0 ; k<source.get_mg()->get_np(l)+2 ; k++)
00124         for (int j=0 ; j<source.get_mg()->get_nt(l) ; j++)
00125         for (int i=0 ; i<source.get_mg()->get_nr(l) ; i++)
00126             resultat.set(l, k, j, i) = 0 ;
00127     }
00128     
00129     // nbre maximum de point en theta et en phi :
00130     int np_max, nt_max ;
00131     
00132            //---------------
00133           //--  NOYAU -----
00134          //---------------
00135          
00136     nr = source.get_mg()->get_nr(0) ;
00137     nt = source.get_mg()->get_nt(0) ;
00138     np = source.get_mg()->get_np(0) ;
00139     
00140     nt_max = nt ;
00141     np_max = np ;
00142     
00143     alpha = mapping.get_alpha()[0] ;
00144     beta = mapping.get_beta()[0] ;
00145     
00146     for (int k=0 ; k<np+1 ; k++)
00147     for (int j=0 ; j<nt ; j++) 
00148         if (nullite_plm(j, nt, k, np, base) == 1) 
00149         {
00150         // calcul des nombres quantiques :
00151         donne_lm(nz, 0, j, k, base, m_quant, l_quant, base_r) ;
00152         
00153         // Construction operateur
00154         operateur = new Matrice(laplacien_mat(nr, l_quant, 0., 0, base_r)) ;
00155         (*operateur) = combinaison(*operateur, l_quant, 0., 0, base_r) ;
00156         
00157         //Operateur inversible
00158         nondege = new Matrice(prepa_nondege(*operateur, l_quant, 0., 0, base_r)) ;
00159         
00160         // Calcul de la SH
00161         sol_hom = new Tbl(solh(nr, l_quant, 0., base_r)) ;
00162      
00163         //Calcul de la SP
00164         so = new Tbl(nr) ;
00165         so->set_etat_qcq() ;
00166         for (int i=0 ; i<nr ; i++)
00167         so->set(i) = source(0, k, j, i) ;
00168         
00169         sol_part = new Tbl(solp(*operateur, *nondege, alpha, beta, 
00170                     *so, 0, base_r)) ;
00171         
00172         // Rangement dans les tableaux globaux ;
00173         
00174         for (int i=0 ; i<nr ; i++) {
00175         solution_part.set(0, k, j, i) = (*sol_part)(i) ;
00176         solution_hom_un.set(0, k, j, i) = (*sol_hom)(i) ;
00177         solution_hom_deux.set(0, k, j, i) = 0. ; 
00178         }       
00179         
00180         
00181         
00182         delete operateur ;
00183         delete nondege ;
00184         delete so ;
00185         delete sol_hom ;
00186         delete sol_part ;
00187     }
00188 
00189 
00190     
00191            //---------------
00192           //- COQUILLES ---
00193          //---------------
00194 
00195     for (int zone=1 ; zone<nz ; zone++) {
00196     nr = source.get_mg()->get_nr(zone) ;
00197     nt = source.get_mg()->get_nt(zone) ;
00198     np = source.get_mg()->get_np(zone) ;
00199     
00200     if (np > np_max) np_max = np ;
00201     if (nt > nt_max) nt_max = nt ;
00202     
00203     alpha = mapping.get_alpha()[zone] ;
00204     beta = mapping.get_beta()[zone] ;
00205 
00206     for (int k=0 ; k<np+1 ; k++)
00207         for (int j=0 ; j<nt ; j++) 
00208         if (nullite_plm(j, nt, k, np, base) == 1)
00209         {
00210         // calcul des nombres quantiques :
00211         donne_lm(nz, zone, j, k, base, m_quant, l_quant, base_r) ;
00212         
00213         // Construction de l'operateur
00214         operateur = new Matrice(laplacien_mat
00215                     (nr, l_quant, beta/alpha, 0, base_r)) ;
00216         
00217         (*operateur) = combinaison(*operateur, l_quant, beta/alpha, 0, 
00218                                      base_r) ;
00219         
00220          // Operateur inversible
00221         nondege = new Matrice(prepa_nondege(*operateur, l_quant, 
00222                             beta/alpha, 0, base_r)) ;       
00223         
00224         // Calcul DES DEUX SH
00225         sol_hom = new Tbl(solh(nr, l_quant, beta/alpha, base_r)) ;
00226         
00227         // Calcul de la SP
00228         so = new Tbl(nr) ;
00229         so->set_etat_qcq() ;
00230         for (int i=0 ; i<nr ; i++)
00231             so->set(i) = source(zone, k, j, i) ;
00232         
00233         sol_part = new Tbl (solp(*operateur, *nondege, alpha,
00234                      beta, *so, 0, base_r)) ;
00235         
00236         
00237         // Rangement
00238         for (int i=0 ; i<nr ; i++) {
00239             solution_part.set(zone, k, j, i) = (*sol_part)(i) ;
00240             solution_hom_un.set(zone, k, j, i) = (*sol_hom)(0, i) ;
00241             solution_hom_deux.set(zone, k, j, i) = (*sol_hom)(1, i) ;
00242         }
00243             
00244         
00245         delete operateur ;
00246         delete nondege ;
00247         delete so ;
00248         delete sol_hom ;
00249         delete sol_part ;
00250         }
00251     }
00252 
00253          //-------------------------------------------
00254         // On est parti pour le raccord des solutions
00255        //-------------------------------------------
00256     // Tableau de 0 et 1 sur les zones, indiquant si le Plm considere
00257     // intervient dans le developpement de cette zone.
00258     int * indic = new int [nz] ;
00259     int taille ;
00260     Tbl *sec_membre ; // termes constants du systeme
00261     Matrice *systeme ; //le systeme a resoudre
00262 
00263     // des compteurs pour le remplissage du systeme
00264     int ligne ;
00265     int colonne ;
00266 
00267     // compteurs pour les diagonales du systeme :
00268     int sup ;
00269     int inf ;
00270     int sup_new, inf_new ;
00271 
00272     // on boucle sur le plus grand nombre possible de Plm intervenant...
00273     for (int k=0 ; k<np_max+1 ; k++)
00274     for (int j=0 ; j<nt_max ; j++)
00275         if (nullite_plm(j, nt_max, k, np_max, base) == 1) {
00276         
00277         ligne = 0 ;
00278         colonne = 0 ;
00279         sup = 0 ;
00280         inf = 0 ;
00281         
00282         for (int zone=0 ; zone<nz ; zone++)
00283             indic[zone] = nullite_plm(j, source.get_mg()->get_nt(zone), 
00284                      k,  source.get_mg()->get_np(zone), base);
00285         
00286         // taille du systeme a resoudre pour ce Plm 
00287         taille = indic[0] ;
00288         for (int zone=1 ; zone<nz ; zone++)
00289             taille+=2*indic[zone] ;
00290         
00291         // on verifie que la taille est non-nulle.
00292         // cas pouvant a priori se produire...
00293         
00294         if (taille != 0) {
00295             
00296             sec_membre = new Tbl(taille) ;
00297             sec_membre->set_etat_qcq() ;
00298             for (int l=0 ; l<taille ; l++)
00299             sec_membre->set(l) = 0 ;
00300             
00301             systeme = new Matrice(taille, taille) ;
00302             systeme->set_etat_qcq() ;
00303             for (int l=0 ; l<taille ; l++)
00304             for (int c=0 ; c<taille ; c++)
00305                 systeme->set(l, c) = 0 ;
00306             
00307             //Calcul des nombres quantiques
00308             //base_r est donne dans le noyau, sa valeur dans les autres
00309             //zones etant inutile.
00310             
00311             donne_lm (nz, 0, j, k, base, m_quant, l_quant, base_r) ;
00312             
00313             
00314              //--------------------------
00315             //      NOYAU 
00316            //---------------------------
00317             
00318             if (indic[0] == 1) {
00319             nr = source.get_mg()->get_nr(0) ;
00320             
00321             alpha = mapping.get_alpha()[0] ;
00322             // valeur de x^l en 1 :
00323             systeme->set(ligne, colonne) = 1. ; /* ligne=0, colonne=0 */
00324             // coefficient du Plm dans la solp
00325             for (int i=0 ; i<nr ; i++)
00326                 sec_membre->set(ligne) -= solution_part(0, k, j, i) ; /* ligne=0 */
00327                 
00328             ligne++ ;  /* ligne=1, colonne=0 */
00329             // on prend les derivees que si Plm existe 
00330             //dans la zone suivante
00331             
00332             if (indic[1] == 1) {
00333                 // derivee de x^l en 1 :
00334                 systeme->set(ligne, colonne) = 1./alpha*l_quant ; /* ligne=1, colonne=0 */
00335             
00336                 // coefficient de la derivee du Plm dans la solp
00337                 if (base_r == R_CHEBP)
00338                 // cas en R_CHEBP 
00339                 for (int i=0 ; i<nr ; i++)
00340                     sec_membre->set(ligne) -= 
00341                         4*i*i/alpha
00342                         *solution_part(0, k, j, i) ; /* ligne=1 */
00343                 else
00344                 // cas en R_CHEBI
00345                 for (int i=0 ; i<nr ; i++)
00346                     sec_membre->set(ligne) -=
00347                     (2*i+1)*(2*i+1)/alpha
00348                         *solution_part(0, k, j, i) ; /* ligne=1 */
00349                             
00350                 // on a au moins un diag inferieure dans ce cas ...
00351                 inf = 1 ;
00352             }
00353             colonne++ ; /* ligne=1, colonne=1 */
00354             }
00355             
00356             //-----------------------------
00357            //        COQUILLES
00358           //------------------------------
00359           
00360           for (int zone=1 ; zone<nz ; zone++)
00361             if (indic[zone] == 1) {
00362             
00363             nr = source.get_mg()->get_nr(zone) ;
00364             alpha = mapping.get_alpha()[zone] ;
00365             echelle = mapping.get_beta()[zone]/alpha ;
00366             
00367             //Frontiere avec la zone precedente :
00368             if (indic[zone-1] == 1) ligne -- ; /* ligne=0, colonne=1 */
00369             
00370             //valeur de (x+echelle)^l en -1 :
00371             systeme->set(ligne, colonne) = 
00372                 -pow(echelle-1, double(l_quant)) ; /* ligne=0, colonne=1 */
00373             
00374             // valeur de 1/(x+echelle) ^(l+1) en -1 :
00375             systeme->set(ligne, colonne+1) = 
00376                 -1/pow(echelle-1, double(l_quant+1)) ; /* ligne=0, colonne=1, colonne+1=2 */
00377             
00378             // la solution particuliere :
00379             for (int i=0 ; i<nr ; i++)
00380                 if (i%2 == 0)
00381                 sec_membre->set(ligne) += solution_part(zone, k, j, i) ;
00382                 else sec_membre->set(ligne) -= solution_part(zone, k, j, i) ; /* ligne=0 */
00383             
00384             // les diagonales :
00385             sup_new = colonne+1-ligne ; /* ligne=0, colonne=1, colonne+1-ligne=2 */
00386             if (sup_new > sup) sup = sup_new ;
00387             
00388             ligne++ ; /* ligne=1 */
00389             
00390             // on prend les derivees si Plm existe dans la zone 
00391             // precedente :
00392             
00393             if (indic[zone-1] == 1) {
00394             // derivee de (x+echelle)^l en -1 :
00395                 systeme->set(ligne, colonne) = 
00396                   -l_quant*pow(echelle-1, double(l_quant-1))/alpha ; /* ligne=1, colonne=1 */
00397             // derivee de 1/(x+echelle)^(l+1) en -1 :
00398                 systeme->set(ligne, colonne+1) = 
00399                 (l_quant+1)/pow(echelle-1, double(l_quant+2))/alpha ; /* ligne=1, colonne=1, colonne+1=2 */
00400             
00401             
00402             
00403             // la solution particuliere :
00404                 for (int i=0 ; i<nr ; i++)
00405                 if (i%2 == 0)
00406                     sec_membre->set(ligne) -= 
00407                       i*i/alpha*solution_part(zone, k, j, i) ; /* ligne=1 */
00408                 else
00409                     sec_membre->set(ligne) +=
00410                     i*i/alpha*solution_part(zone, k, j, i) ; /* ligne=1 */
00411             
00412             // les diagonales :
00413             sup_new = colonne+1-ligne ; /* ligne=1, colonne=1, colonne+1-ligne=1 */
00414             if (sup_new > sup) sup = sup_new ;
00415             
00416             ligne++ ; /* ligne=2 */
00417             }
00418             
00419 
00420             if(zone < nz-1) {
00421 
00422             // Frontiere avec la zone suivante :
00423             //valeur de (x+echelle)^l en 1 :
00424             systeme->set(ligne, colonne) = 
00425               pow(echelle+1, double(l_quant)) ; /* ligne=2, colonne=1 */ 
00426             
00427             // valeur de 1/(x+echelle)^(l+1) en 1 :
00428             systeme->set(ligne, colonne+1) =
00429                 1/pow(echelle+1, double(l_quant+1)) ; /* ligne=2, colonne=1, colonne+1=2 */
00430                 
00431             // la solution particuliere :
00432             for (int i=0 ; i<nr ; i++)
00433               sec_membre->set(ligne) -= solution_part(zone, k, j, i) ; /* ligne=2 */
00434             
00435             // les diagonales inf :
00436             inf_new = ligne-colonne ; /* ligne=2, colonne=1, ligne-colonne=1 */
00437             if (inf_new > inf) inf = inf_new ;  
00438             
00439             ligne ++ ; /* ligne=3 */
00440                 
00441             // Utilisation des derivees ssi Plm existe dans la
00442             //zone suivante :
00443             if (indic[zone+1] == 1) {
00444                 
00445                 //derivee de (x+echelle)^l en 1 :
00446                 systeme->set(ligne, colonne) = 
00447                   l_quant*pow(echelle+1, double(l_quant-1))/alpha ; /* ligne=3, colonne=1 */
00448                 
00449                 //derivee de 1/(echelle+x)^(l+1) en 1 :
00450                 systeme->set(ligne, colonne+1) =
00451                 -(l_quant+1)/pow(echelle+1, double(l_quant+2))/alpha ; /* ligne=3, colonne=1, colonne+1=2 */
00452                 
00453                 // La solution particuliere :
00454                 for (int i=0 ; i<nr ; i++)
00455                 sec_membre->set(ligne) -= 
00456                   i*i/alpha*solution_part(zone, k, j, i) ; /* ligne=3 */
00457                     
00458             // les diagonales inf :
00459             inf_new = ligne-colonne ; /* ligne=3, colonne=1, ligne-colonne=2 */
00460             if (inf_new > inf) inf = inf_new ;  
00461                 
00462                  }
00463             colonne += 2 ; /* ligne=colonne=3 -> ligne=colonne=1 next block of two */
00464             } else {
00465 
00466 
00467 
00468             //-------------------------
00469            //  Falloff outer boundary           
00470           //---------------------------
00471 
00472               /* ligne=2, colonne=1 */
00473               
00474               // The coefficient for A_n is (k+l)(echelle+1)^l
00475              systeme->set(ligne, colonne) = 
00476                double(k_falloff+l_quant)*pow(echelle+1, double(l_quant)) ;  /* ligne=2, colonne=1 */
00477 
00478              // The coefficient for B_n is (k-(l+1))(echelle+1)^{-(l+1)}
00479             systeme->set(ligne, colonne+1) =
00480                 double(k_falloff-l_quant-1)/pow(echelle+1, double(l_quant+1)) ; /* ligne=2, colonne=1, colonne+1=2 */
00481 
00482             // Here we have -(1+echelle)*F'(x=1)-k*F(x=1)
00483             // La solution particuliere :
00484             for (int i=0 ; i<nr ; i++)
00485               sec_membre->set(ligne) -= 
00486                 (k_falloff+(echelle+1)*i*i)*solution_part(zone, k, j, i) ; /* ligne=2 */
00487 
00488             // les diagonales inf :
00489             inf_new = ligne-colonne ; /* ligne=2, colonne=1, ligne-colonne=1 */
00490             if (inf_new > inf) inf = inf_new ;  
00491                 
00492             }
00493             }
00494             
00495 
00496             //-------------------------
00497            //  resolution du systeme 
00498           //--------------------------
00499             
00500             systeme->set_band(sup, inf) ;
00501             systeme->set_lu() ;
00502 
00503             Tbl facteurs(systeme->inverse(*sec_membre)) ;
00504             int conte = 0 ;
00505             
00506          
00507         // rangement dans le noyau :
00508             
00509             if (indic[0] == 1) {
00510             nr = source.get_mg()->get_nr(0) ;
00511             for (int i=0 ; i<nr ; i++)
00512                 resultat.set(0, k, j, i) = solution_part(0, k, j, i)
00513                 +facteurs(conte)*solution_hom_un(0, k, j, i) ;
00514             conte++ ;
00515             }
00516             
00517             // rangement dans les coquilles :
00518             for (int zone=1 ; zone<nz ; zone++)
00519             if (indic[zone] == 1) {
00520                 nr = source.get_mg()->get_nr(zone) ;
00521                 for (int i=0 ; i<nr ; i++)
00522                 resultat.set(zone, k, j, i) = 
00523                 solution_part(zone, k, j, i)
00524                 +facteurs(conte)*solution_hom_un(zone, k, j, i) 
00525                 +facteurs(conte+1)*solution_hom_deux(zone, k, j, i) ;
00526                 conte+=2 ;
00527             }
00528             
00529             delete sec_membre ;
00530             delete systeme ;
00531         }
00532         
00533         }
00534     
00535     delete [] indic ;
00536     
00537     return resultat;
00538 }

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