poisson_ylm.C

00001 /*
00002  *  Method of Non_class_members for solving Poisson equations
00003  *   with a multipole 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_ylm_C[] = "$Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_ylm.C,v 1.1 2004/12/29 16:32:02 k_taniguchi Exp $" ;
00028 
00029 /*
00030  * $Id: poisson_ylm.C,v 1.1 2004/12/29 16:32:02 k_taniguchi Exp $
00031  * $Log: poisson_ylm.C,v $
00032  * Revision 1.1  2004/12/29 16:32:02  k_taniguchi
00033  * *** empty log message ***
00034  *
00035  *
00036  * $Header: /cvsroot/Lorene/C++/Source/Non_class_members/PDE/poisson_ylm.C,v 1.1 2004/12/29 16:32:02 k_taniguchi Exp $
00037  *
00038  */
00039 
00040 // C headers
00041 #include <stdlib.h>
00042 #include <math.h>
00043 
00044 // Lorene headers
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_ylm: 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_ylm(const Map_af& mapping, const Mtbl_cf& source, const int nylm, const double* intvec)
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     // donnees sur la zone
00093     int nr, nt, np ;
00094     int base_r ;
00095     double alpha, beta, echelle ;
00096     int l_quant, m_quant;
00097     
00098     //Rangement des valeurs intermediaires 
00099     Tbl *so ;
00100     Tbl *sol_hom ;
00101     Tbl *sol_part ;
00102     Matrice *operateur ;
00103     Matrice *nondege ;
00104     
00105     
00106     // Rangement des solutions, avant raccordement
00107     Mtbl_cf solution_part(source.get_mg(), base) ;
00108     Mtbl_cf solution_hom_un(source.get_mg(), base) ;
00109     Mtbl_cf solution_hom_deux(source.get_mg(), base) ;
00110     Mtbl_cf resultat(source.get_mg(), base) ;
00111     
00112     solution_part.set_etat_qcq() ;
00113     solution_hom_un.set_etat_qcq() ;
00114     solution_hom_deux.set_etat_qcq() ;
00115     resultat.set_etat_qcq() ;
00116     
00117     for (int l=0 ; l<nz ; l++) {
00118     solution_part.t[l]->set_etat_qcq() ;
00119     solution_hom_un.t[l]->set_etat_qcq() ;
00120     solution_hom_deux.t[l]->set_etat_qcq() ;
00121     resultat.t[l]->set_etat_qcq() ;
00122     for (int k=0 ; k<source.get_mg()->get_np(l)+2 ; k++)
00123         for (int j=0 ; j<source.get_mg()->get_nt(l) ; j++)
00124         for (int i=0 ; i<source.get_mg()->get_nr(l) ; i++)
00125             resultat.set(l, k, j, i) = 0 ;
00126     }
00127     
00128     // nbre maximum de point en theta et en phi :
00129     int np_max, nt_max ;
00130     
00131            //---------------
00132           //--  NOYAU -----
00133          //---------------
00134          
00135     nr = source.get_mg()->get_nr(0) ;
00136     nt = source.get_mg()->get_nt(0) ;
00137     np = source.get_mg()->get_np(0) ;
00138     
00139     nt_max = nt ;
00140     np_max = np ;
00141     
00142     alpha = mapping.get_alpha()[0] ;
00143     beta = mapping.get_beta()[0] ;
00144     
00145     for (int k=0 ; k<np+1 ; k++)
00146     for (int j=0 ; j<nt ; j++) 
00147         if (nullite_plm(j, nt, k, np, base) == 1) 
00148         {
00149         // calcul des nombres quantiques :
00150         donne_lm(nz, 0, j, k, base, m_quant, l_quant, base_r) ;
00151         
00152         // Construction operateur
00153         operateur = new Matrice(laplacien_mat(nr, l_quant, 0., 0, base_r)) ;
00154         (*operateur) = combinaison(*operateur, l_quant, 0., 0, base_r) ;
00155         
00156         //Operateur inversible
00157         nondege = new Matrice(prepa_nondege(*operateur, l_quant, 0., 0, base_r)) ;
00158         
00159         // Calcul de la SH
00160         sol_hom = new Tbl(solh(nr, l_quant, 0., base_r)) ;
00161      
00162         //Calcul de la SP
00163         so = new Tbl(nr) ;
00164         so->set_etat_qcq() ;
00165         for (int i=0 ; i<nr ; i++)
00166           so->set(i) = source(0, k, j, i) ;
00167         
00168         sol_part = new Tbl(solp(*operateur, *nondege, alpha, beta, 
00169                     *so, 0, base_r)) ;
00170         
00171         // Rangement dans les tableaux globaux ;
00172         
00173         for (int i=0 ; i<nr ; i++) {
00174         solution_part.set(0, k, j, i) = (*sol_part)(i) ;
00175         solution_hom_un.set(0, k, j, i) = (*sol_hom)(i) ;
00176         solution_hom_deux.set(0, k, j, i) = 0. ; 
00177         }       
00178         
00179         
00180         
00181         delete operateur ;
00182         delete nondege ;
00183         delete so ;
00184         delete sol_hom ;
00185         delete sol_part ;
00186     }
00187 
00188 
00189     
00190            //---------------
00191           //- COQUILLES ---
00192          //---------------
00193 
00194     for (int zone=1 ; zone<nz ; zone++) {
00195     nr = source.get_mg()->get_nr(zone) ;
00196     nt = source.get_mg()->get_nt(zone) ;
00197     np = source.get_mg()->get_np(zone) ;
00198     
00199     if (np > np_max) np_max = np ;
00200     if (nt > nt_max) nt_max = nt ;
00201     
00202     alpha = mapping.get_alpha()[zone] ;
00203     beta = mapping.get_beta()[zone] ;
00204 
00205     for (int k=0 ; k<np+1 ; k++)
00206         for (int j=0 ; j<nt ; j++) 
00207         if (nullite_plm(j, nt, k, np, base) == 1)
00208         {
00209         // calcul des nombres quantiques :
00210         donne_lm(nz, zone, j, k, base, m_quant, l_quant, base_r) ;
00211         
00212         // Construction de l'operateur
00213         operateur = new Matrice(laplacien_mat
00214                     (nr, l_quant, beta/alpha, 0, base_r)) ;
00215         
00216         (*operateur) = combinaison(*operateur, l_quant, beta/alpha, 0, 
00217                                      base_r) ;
00218         
00219          // Operateur inversible
00220         nondege = new Matrice(prepa_nondege(*operateur, l_quant, 
00221                             beta/alpha, 0, base_r)) ;       
00222         
00223         // Calcul DES DEUX SH
00224         sol_hom = new Tbl(solh(nr, l_quant, beta/alpha, base_r)) ;
00225         
00226         // Calcul de la SP
00227         so = new Tbl(nr) ;
00228         so->set_etat_qcq() ;
00229         for (int i=0 ; i<nr ; i++)
00230           so->set(i) = source(zone, k, j, i) ;
00231         
00232         sol_part = new Tbl (solp(*operateur, *nondege, alpha,
00233                      beta, *so, 0, base_r)) ;
00234         
00235         
00236         // Rangement
00237         for (int i=0 ; i<nr ; i++) {
00238             solution_part.set(zone, k, j, i) = (*sol_part)(i) ;
00239             solution_hom_un.set(zone, k, j, i) = (*sol_hom)(0, i) ;
00240             solution_hom_deux.set(zone, k, j, i) = (*sol_hom)(1, i) ;
00241         }
00242             
00243         
00244         delete operateur ;
00245         delete nondege ;
00246         delete so ;
00247         delete sol_hom ;
00248         delete sol_part ;
00249         }
00250     }
00251 
00252          //-------------------------------------------
00253         // On est parti pour le raccord des solutions
00254        //-------------------------------------------
00255     // Tableau de 0 et 1 sur les zones, indiquant si le Plm considere
00256     // intervient dans le developpement de cette zone.
00257     int * indic = new int [nz] ;
00258     int taille ;
00259     Tbl *sec_membre ; // termes constants du systeme
00260     Matrice *systeme ; //le systeme a resoudre
00261 
00262     // des compteurs pour le remplissage du systeme
00263     int ligne ;
00264     int colonne ;
00265 
00266     // compteurs pour les diagonales du systeme :
00267     int sup ;
00268     int inf ;
00269     int sup_new, inf_new ;
00270 
00271     // on boucle sur le plus grand nombre possible de Plm intervenant...
00272     for (int k=0 ; k<np_max+1 ; k++)
00273     for (int j=0 ; j<nt_max ; j++)
00274         if (nullite_plm(j, nt_max, k, np_max, base) == 1) {
00275         
00276         ligne = 0 ;
00277         colonne = 0 ;
00278         sup = 0 ;
00279         inf = 0 ;
00280         
00281         for (int zone=0 ; zone<nz ; zone++)
00282             indic[zone] = nullite_plm(j, source.get_mg()->get_nt(zone), 
00283                      k,  source.get_mg()->get_np(zone), base);
00284         
00285         // taille du systeme a resoudre pour ce Plm 
00286         taille = indic[0] ;
00287         for (int zone=1 ; zone<nz ; zone++)
00288             taille+=2*indic[zone] ;
00289         
00290         // on verifie que la taille est non-nulle.
00291         // cas pouvant a priori se produire...
00292         
00293         if (taille != 0) {
00294             
00295             sec_membre = new Tbl(taille) ;
00296             sec_membre->set_etat_qcq() ;
00297             for (int l=0 ; l<taille ; l++)
00298             sec_membre->set(l) = 0 ;
00299             
00300             systeme = new Matrice(taille, taille) ;
00301             systeme->set_etat_qcq() ;
00302             for (int l=0 ; l<taille ; l++)
00303             for (int c=0 ; c<taille ; c++)
00304                 systeme->set(l, c) = 0 ;
00305             
00306             //Calcul des nombres quantiques
00307             //base_r est donne dans le noyau, sa valeur dans les autres
00308             //zones etant inutile.
00309             
00310             donne_lm (nz, 0, j, k, base, m_quant, l_quant, base_r) ;
00311             
00312             
00313              //--------------------------
00314             //      NOYAU 
00315            //---------------------------
00316             
00317             if (indic[0] == 1) {
00318             nr = source.get_mg()->get_nr(0) ;
00319             
00320             alpha = mapping.get_alpha()[0] ;
00321             // valeur de x^l en 1 :
00322             systeme->set(ligne, colonne) = 1. ; /* ligne=0, colonne=0 */
00323             // coefficient du Plm dans la solp
00324             for (int i=0 ; i<nr ; i++)
00325                 sec_membre->set(ligne) -= solution_part(0, k, j, i) ; /* ligne=0 */
00326                 
00327             ligne++ ;  /* ligne=1, colonne=0 */
00328             // on prend les derivees que si Plm existe 
00329             //dans la zone suivante
00330             
00331             if (indic[1] == 1) {
00332                 // derivee de x^l en 1 :
00333                 systeme->set(ligne, colonne) = 1./alpha*l_quant ; /* ligne=1, colonne=0 */
00334             
00335                 // coefficient de la derivee du Plm dans la solp
00336                 if (base_r == R_CHEBP)
00337                 // cas en R_CHEBP 
00338                 for (int i=0 ; i<nr ; i++)
00339                     sec_membre->set(ligne) -= 
00340                         4*i*i/alpha
00341                         *solution_part(0, k, j, i) ; /* ligne=1 */
00342                 else
00343                 // cas en R_CHEBI
00344                 for (int i=0 ; i<nr ; i++)
00345                     sec_membre->set(ligne) -=
00346                     (2*i+1)*(2*i+1)/alpha
00347                         *solution_part(0, k, j, i) ; /* ligne=1 */
00348                             
00349                 // on a au moins un diag inferieure dans ce cas ...
00350                 inf = 1 ;
00351             }
00352             colonne++ ; /* ligne=1, colonne=1 */
00353             }
00354             
00355             //-----------------------------
00356            //        COQUILLES
00357           //------------------------------
00358           
00359           for (int zone=1 ; zone<nz ; zone++)
00360             if (indic[zone] == 1) {
00361             
00362             nr = source.get_mg()->get_nr(zone) ;
00363             alpha = mapping.get_alpha()[zone] ;
00364             echelle = mapping.get_beta()[zone]/alpha ;
00365             
00366             //Frontiere avec la zone precedente :
00367             if (indic[zone-1] == 1) ligne -- ; /* ligne=0, colonne=1 */
00368             
00369             //valeur de (x+echelle)^l en -1 :
00370             systeme->set(ligne, colonne) = 
00371                 -pow(echelle-1, double(l_quant)) ; /* ligne=0, colonne=1 */
00372             
00373             // valeur de 1/(x+echelle) ^(l+1) en -1 :
00374             systeme->set(ligne, colonne+1) = 
00375                 -1/pow(echelle-1, double(l_quant+1)) ; /* ligne=0, colonne=1, colonne+1=2 */
00376             
00377             // la solution particuliere :
00378             for (int i=0 ; i<nr ; i++)
00379                 if (i%2 == 0)
00380                 sec_membre->set(ligne) += solution_part(zone, k, j, i) ;
00381                 else sec_membre->set(ligne) -= solution_part(zone, k, j, i) ; /* ligne=0 */
00382             
00383             // les diagonales :
00384             sup_new = colonne+1-ligne ; /* ligne=0, colonne=1, colonne+1-ligne=2 */
00385             if (sup_new > sup) sup = sup_new ;
00386             
00387             ligne++ ; /* ligne=1 */
00388             
00389             // on prend les derivees si Plm existe dans la zone 
00390             // precedente :
00391             
00392             if (indic[zone-1] == 1) {
00393             // derivee de (x+echelle)^l en -1 :
00394                 systeme->set(ligne, colonne) = 
00395                   -l_quant*pow(echelle-1, double(l_quant-1))/alpha ; /* ligne=1, colonne=1 */
00396             // derivee de 1/(x+echelle)^(l+1) en -1 :
00397                 systeme->set(ligne, colonne+1) = 
00398                 (l_quant+1)/pow(echelle-1, double(l_quant+2))/alpha ; /* ligne=1, colonne=1, colonne+1=2 */
00399             
00400             
00401             
00402             // la solution particuliere :
00403                 for (int i=0 ; i<nr ; i++)
00404                 if (i%2 == 0)
00405                     sec_membre->set(ligne) -= 
00406                       i*i/alpha*solution_part(zone, k, j, i) ; /* ligne=1 */
00407                 else
00408                     sec_membre->set(ligne) +=
00409                     i*i/alpha*solution_part(zone, k, j, i) ; /* ligne=1 */
00410             
00411             // les diagonales :
00412             sup_new = colonne+1-ligne ; /* ligne=1, colonne=1, colonne+1-ligne=1 */
00413             if (sup_new > sup) sup = sup_new ;
00414             
00415             ligne++ ; /* ligne=2 */
00416             }
00417             
00418 
00419             if(zone < nz-1) {
00420 
00421             // Frontiere avec la zone suivante :
00422             //valeur de (x+echelle)^l en 1 :
00423             systeme->set(ligne, colonne) = 
00424               pow(echelle+1, double(l_quant)) ; /* ligne=2, colonne=1 */ 
00425             
00426             // valeur de 1/(x+echelle)^(l+1) en 1 :
00427             systeme->set(ligne, colonne+1) =
00428                 1/pow(echelle+1, double(l_quant+1)) ; /* ligne=2, colonne=1, colonne+1=2 */
00429                 
00430             // la solution particuliere :
00431             for (int i=0 ; i<nr ; i++)
00432               sec_membre->set(ligne) -= solution_part(zone, k, j, i) ; /* ligne=2 */
00433             
00434             // les diagonales inf :
00435             inf_new = ligne-colonne ; /* ligne=2, colonne=1, ligne-colonne=1 */
00436             if (inf_new > inf) inf = inf_new ;  
00437             
00438             ligne ++ ; /* ligne=3 */
00439                 
00440             // Utilisation des derivees ssi Plm existe dans la
00441             //zone suivante :
00442             if (indic[zone+1] == 1) {
00443                 
00444                 //derivee de (x+echelle)^l en 1 :
00445                 systeme->set(ligne, colonne) = 
00446                   l_quant*pow(echelle+1, double(l_quant-1))/alpha ; /* ligne=3, colonne=1 */
00447                 
00448                 //derivee de 1/(echelle+x)^(l+1) en 1 :
00449                 systeme->set(ligne, colonne+1) =
00450                 -(l_quant+1)/pow(echelle+1, double(l_quant+2))/alpha ; /* ligne=3, colonne=1, colonne+1=2 */
00451                 
00452                 // La solution particuliere :
00453                 for (int i=0 ; i<nr ; i++)
00454                 sec_membre->set(ligne) -= 
00455                   i*i/alpha*solution_part(zone, k, j, i) ; /* ligne=3 */
00456                     
00457             // les diagonales inf :
00458             inf_new = ligne-colonne ; /* ligne=3, colonne=1, ligne-colonne=2 */
00459             if (inf_new > inf) inf = inf_new ;  
00460                 
00461                  }
00462             colonne += 2 ; /* ligne=colonne=3 -> ligne=colonne=1 next block of two */
00463             } else {
00464 
00465 
00466 
00467             //-------------------------
00468            //  Ylm outer boundary           
00469           //---------------------------
00470 
00471               /* ligne=2, colonne=1 */
00472               
00473               // The coefficient for A_n is (k+l)(echelle+1)^l
00474              systeme->set(ligne, colonne) = 
00475                pow(echelle+1, double(l_quant)) ;  /* ligne=2, colonne=1 */
00476 
00477              // The coefficient for B_n is (k-(l+1))(echelle+1)^{-(l+1)}
00478             systeme->set(ligne, colonne+1) =
00479                 pow(echelle+1, double(-1-l_quant)) ; /* ligne=2, colonne=1, colonne+1=2 */
00480 
00481             // Here we have -f - multipole integral 
00482             //(pos source->neg field!!)
00483 
00484             int indylm;
00485             double intterm=0.;
00486             if(l_quant*l_quant < nylm && m_quant<=l_quant) {
00487               indylm=l_quant*l_quant+2*m_quant;
00488               if(k%2==0 && k>=2)indylm-=1;
00489               intterm=intvec[indylm];
00490               cout <<"l,m:"<<l_quant<<" "<<m_quant<<" "<<j<<" "<<k<<" "<<indylm<<" "<<intterm<<endl;
00491             }
00492             // This is just for testing!!!
00493             //if(l_quant==1 && m_quant==1&& k%2==0) {
00494             //  intterm=1.0 ;
00495             //} else {
00496             //  intterm=0.;
00497             //}
00498             
00499             sec_membre->set(ligne) -= intterm;
00500             
00501             // La solution particuliere :
00502             for (int i=0 ; i<nr ; i++)
00503               sec_membre->set(ligne) -= 
00504                 solution_part(zone, k, j, i) ; /* ligne=2 */
00505 
00506             // les diagonales inf :
00507             inf_new = ligne-colonne ; /* ligne=2, colonne=1, ligne-colonne=1 */
00508             if (inf_new > inf) inf = inf_new ;  
00509                 
00510             }
00511             }
00512             
00513 
00514             //-------------------------
00515            //  resolution du systeme 
00516           //--------------------------
00517             
00518             systeme->set_band(sup, inf) ;
00519             systeme->set_lu() ;
00520 
00521             Tbl facteurs(systeme->inverse(*sec_membre)) ;
00522             int conte = 0 ;
00523             
00524          
00525         // rangement dans le noyau :
00526             
00527             if (indic[0] == 1) {
00528             nr = source.get_mg()->get_nr(0) ;
00529             for (int i=0 ; i<nr ; i++)
00530                 resultat.set(0, k, j, i) = solution_part(0, k, j, i)
00531                 +facteurs(conte)*solution_hom_un(0, k, j, i) ;
00532             conte++ ;
00533             }
00534             
00535             // rangement dans les coquilles :
00536             for (int zone=1 ; zone<nz ; zone++)
00537             if (indic[zone] == 1) {
00538                 nr = source.get_mg()->get_nr(zone) ;
00539                 for (int i=0 ; i<nr ; i++)
00540                 resultat.set(zone, k, j, i) = 
00541                 solution_part(zone, k, j, i)
00542                 +facteurs(conte)*solution_hom_un(zone, k, j, i) 
00543                 +facteurs(conte+1)*solution_hom_deux(zone, k, j, i) ;
00544                 conte+=2 ;
00545             }
00546             
00547             delete sec_membre ;
00548             delete systeme ;
00549         }
00550         
00551         }
00552     
00553     delete [] indic ;
00554     
00555     return resultat;
00556 }

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