scalar_raccord_zec.C

00001 /*
00002  *   Copyright (c) 2003 Eric Gourgoulhon & Jerome Novak
00003  *
00004  *   Copyright (c) 2000-2001 Philippe Grandclement (for preceding Cmp version)
00005  *
00006  *
00007  *   This file is part of LORENE.
00008  *
00009  *   LORENE is free software; you can redistribute it and/or modify
00010  *   it under the terms of the GNU General Public License as published by
00011  *   the Free Software Foundation; either version 2 of the License, or
00012  *   (at your option) any later version.
00013  *
00014  *   LORENE is distributed in the hope that it will be useful,
00015  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *   GNU General Public License for more details.
00018  *
00019  *   You should have received a copy of the GNU General Public License
00020  *   along with LORENE; if not, write to the Free Software
00021  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 
00026 char scalar_raccord_zec_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tensor/Scalar/scalar_raccord_zec.C,v 1.6 2004/06/04 16:14:18 j_novak Exp $" ;
00027 
00028 /*
00029  * $Id: scalar_raccord_zec.C,v 1.6 2004/06/04 16:14:18 j_novak Exp $
00030  * $Log: scalar_raccord_zec.C,v $
00031  * Revision 1.6  2004/06/04 16:14:18  j_novak
00032  * In smooth_decay, the configuration space was not up-to-date.
00033  *
00034  * Revision 1.5  2004/03/05 15:09:59  e_gourgoulhon
00035  * Added method smooth_decay.
00036  *
00037  * Revision 1.4  2003/10/29 11:04:34  e_gourgoulhon
00038  * dec2_dpzuis() replaced by dec_dzpuis(2).
00039  * inc2_dpzuis() replaced by inc_dzpuis(2).
00040  *
00041  * Revision 1.3  2003/10/10 15:57:29  j_novak
00042  * Added the state one (ETATUN) to the class Scalar
00043  *
00044  * Revision 1.2  2003/09/25 09:22:33  j_novak
00045  * Added a #include<math.h>
00046  *
00047  * Revision 1.1  2003/09/25 08:58:10  e_gourgoulhon
00048  * First version.
00049  *
00050  *
00051  * $Header: /cvsroot/Lorene/C++/Source/Tensor/Scalar/scalar_raccord_zec.C,v 1.6 2004/06/04 16:14:18 j_novak Exp $
00052  *
00053  */
00054 
00055 //standard
00056 #include <stdlib.h>
00057 #include <math.h>
00058 
00059 // LORENE
00060 #include "matrice.h"
00061 #include "tensor.h"
00062 #include "proto.h"
00063 #include "nbr_spx.h"
00064 #include "utilitaires.h"
00065 
00066 // Fait le raccord C1 dans la zec ...
00067 // Suppose (pour le moment, le meme nbre de points sur les angles ...)
00068 // et que la zone precedente est une coquille
00069 
00070 void Scalar::raccord_c1_zec(int puis, int nbre, int lmax) {
00071     
00072     assert (nbre>0) ;
00073     assert (etat != ETATNONDEF) ;
00074     if ((etat == ETATZERO) || (etat == ETATUN))
00075     return ;
00076 
00077     // Le mapping doit etre affine :
00078     const Map_af* map  = dynamic_cast<const Map_af*>(mp) ;
00079     if (map == 0x0) {
00080     cout << "Le mapping doit etre affine" << endl ;
00081     abort() ;
00082     }
00083     
00084     int nz = map->get_mg()->get_nzone() ;
00085     int nr = map->get_mg()->get_nr (nz-1) ;
00086     int nt = map->get_mg()->get_nt (nz-1) ;
00087     int np = map->get_mg()->get_np (nz-1) ;
00088     
00089     double alpha = map->get_alpha()[nz-1] ;
00090     double r_cont = -1./2./alpha ;  //Rayon de debut de la zec.
00091   
00092     // On calcul les coefficients des puissances de 1./r
00093     Tbl coef (nbre+2*lmax, nr) ;
00094     coef.set_etat_qcq() ;
00095     
00096     int* deg = new int[3] ;
00097     deg[0] = 1 ; deg[1] = 1 ; deg[2] = nr ;
00098     double* auxi = new double[nr] ;
00099     
00100     for (int conte=0 ; conte<nbre+2*lmax ; conte++) {
00101     for (int i=0 ; i<nr ; i++)
00102         auxi[i] = pow(-1-cos(M_PI*i/(nr-1)), (conte+puis)) ;
00103         
00104     cfrcheb(deg, deg, auxi, deg, auxi) ;
00105     for (int i=0 ; i<nr ; i++)
00106         coef.set(conte, i) = auxi[i]*pow (alpha, conte+puis) ;
00107     }
00108      
00109     delete[] deg ;
00110     // Maintenant on va calculer les valeurs de la ieme derivee :
00111     Tbl valeurs (nbre, nt, np+1) ;
00112     valeurs.set_etat_qcq() ;
00113     
00114     Scalar courant (*this) ;
00115     double* res_val = new double[1] ;
00116     
00117     for (int conte=0 ; conte<nbre ; conte++) {
00118     
00119     courant.va.coef() ;
00120     courant.va.ylm() ;
00121     courant.va.c_cf->t[nz-1]->annule_hard() ;
00122     
00123     int base_r = courant.va.base.get_base_r(nz-2) ;
00124     for (int k=0 ; k<np+1 ; k++)
00125         for (int j=0 ; j<nt ; j++) 
00126         if (nullite_plm(j, nt, k, np, courant.va.base) == 1) {
00127         
00128             for (int i=0 ; i<nr ; i++)
00129             auxi[i] = (*courant.va.c_cf)(nz-2, k, j, i) ;
00130 
00131             switch (base_r) {
00132             case R_CHEB :
00133                 som_r_cheb (auxi, nr, 1, 1, 1, res_val) ;
00134                 break ;
00135             default :
00136                 cout << "Cas non prevu dans raccord_zec" << endl ;
00137                 abort() ;
00138                 break ;
00139             }
00140             valeurs.set(conte, k, j) = res_val[0] ;
00141         }
00142     Scalar copie (courant) ;
00143     copie.dec_dzpuis(2) ;
00144     courant = copie.dsdr() ;
00145     }
00146  
00147     delete [] auxi ;
00148     delete [] res_val ; 
00149    
00150     // On boucle sur les harmoniques : construction de la matrice 
00151     // et du second membre
00152     va.coef() ;
00153     va.ylm() ;
00154     va.c_cf->t[nz-1]->annule_hard() ;
00155     va.set_etat_cf_qcq() ;
00156     
00157     const Base_val& base = va.base ;
00158     int base_r, l_quant, m_quant ;
00159     for (int k=0 ; k<np+1 ; k++)
00160     for (int j=0 ; j<nt ; j++) 
00161         if (nullite_plm(j, nt, k, np, va.base) == 1) {
00162         
00163         donne_lm (nz, nz-1, j, k, base, m_quant, l_quant, base_r) ;
00164         
00165         if (l_quant<=lmax) {
00166         
00167         Matrice systeme (nbre, nbre) ;
00168         systeme.set_etat_qcq() ;
00169         
00170         for (int col=0 ; col<nbre ; col++)
00171             for (int lig=0 ; lig<nbre ; lig++) {
00172             
00173             int facteur = (lig%2==0) ? 1 : -1 ;
00174             for (int conte=0 ; conte<lig ; conte++)
00175                 facteur *= puis+col+conte+2*l_quant ;
00176             systeme.set(lig, col) = facteur/pow(r_cont, puis+col+lig+2*l_quant) ;
00177             }
00178         
00179         systeme.set_band(nbre, nbre) ;
00180         systeme.set_lu() ;
00181         
00182             Tbl sec_membre (nbre) ;
00183         sec_membre.set_etat_qcq() ;
00184         for (int conte=0 ; conte<nbre ; conte++)
00185             sec_membre.set(conte) = valeurs(conte, k, j) ;
00186         
00187         Tbl inv (systeme.inverse(sec_membre)) ;
00188         
00189         for (int conte=0 ; conte<nbre ; conte++)
00190             for (int i=0 ; i<nr ; i++)
00191             va.c_cf->set(nz-1, k, j, i)+= 
00192                 inv(conte)*coef(conte+2*l_quant, i) ;    
00193         }
00194     else for (int i=0 ; i<nr ; i++)
00195         va.c_cf->set(nz-1, k, j, i)
00196             = 0 ;
00197     }
00198     
00199     va.ylm_i() ;
00200     set_dzpuis (0) ;
00201 }
00202 
00203 
00204 //***************************************************************************
00205 
00206 void Scalar::smooth_decay(int kk, int nn) {
00207 
00208     assert(kk >= 0) ; 
00209 
00210     if (etat == ETATZERO) return ; 
00211     if (va.get_etat() == ETATZERO) return ; 
00212     
00213     const Mg3d& mgrid = *(mp->get_mg()) ; 
00214     
00215     int nz = mgrid.get_nzone() ; 
00216     int nzm1 = nz - 1 ; 
00217     int np = mgrid.get_np(nzm1) ; 
00218     int nt = mgrid.get_nt(nzm1) ; 
00219     int nr_ced = mgrid.get_nr(nzm1) ; 
00220     int nr_shell = mgrid.get_nr(nzm1-1) ; 
00221     
00222     assert(mgrid.get_np(nzm1-1) == np) ; 
00223     assert(mgrid.get_nt(nzm1-1) == nt) ; 
00224     
00225     assert(mgrid.get_type_r(nzm1) == UNSURR) ; 
00226 
00227     // In the present version, the mapping must be affine :
00228     const Map_af* mapaf  = dynamic_cast<const Map_af*>(mp) ;
00229     if (mapaf == 0x0) {
00230         cout << "Scalar::smooth_decay: present version supports only \n" 
00231          << "  affine mappings !" << endl ;
00232         abort() ;
00233     }
00234 
00235 
00236     assert(va.get_etat() == ETATQCQ) ; 
00237     
00238     
00239     // Spherical harmonics are required
00240     va.ylm() ; 
00241     
00242     // Array for the spectral coefficients in the CED:
00243     assert( va.c_cf->t[nzm1] != 0x0) ; 
00244     Tbl& coefresu = *( va.c_cf->t[nzm1] ) ; 
00245     coefresu.set_etat_qcq() ; 
00246     
00247     // 1-D grid 
00248     //----------
00249     int nbr1[] = {nr_shell, nr_ced} ; 
00250     int nbt1[] = {1, 1} ; 
00251     int nbp1[] = {1, 1} ; 
00252     int typr1[] = {mgrid.get_type_r(nzm1-1), UNSURR} ; 
00253     Mg3d grid1d(2, nbr1, typr1, nbt1, SYM, nbp1, SYM) ; 
00254     
00255     // 1-D mapping
00256     //------------
00257     double rbound = mapaf->get_alpha()[nzm1-1] 
00258                     + mapaf->get_beta()[nzm1-1] ; 
00259     double rmin = - mapaf->get_alpha()[nzm1-1] 
00260                     + mapaf->get_beta()[nzm1-1] ; 
00261     double bound1[] = {rmin, rbound, __infinity} ; 
00262 
00263     Map_af map1d(grid1d, bound1) ;     
00264     
00265     // 1-D scalars
00266     // -----------
00267     Scalar uu(map1d) ; 
00268     uu.std_spectral_base() ; 
00269     Scalar duu(map1d) ; 
00270     Scalar vv(map1d) ; 
00271     Scalar tmp(map1d) ; 
00272 
00273     const Base_val& base = va.get_base() ; 
00274     
00275     // Loop on the spherical harmonics
00276     // -------------------------------
00277     for (int k=0; k<=np; k++) {
00278         for (int j=0; j<nt; j++) {
00279             
00280             if (nullite_plm(j, nt, k, np, base) != 1) {
00281                 for (int i=0 ; i<nr_ced ; i++) {
00282                     coefresu.set(k, j, i) = 0 ;
00283                 }
00284             }
00285             else {
00286                 int base_r_ced, base_r_shell , l_quant, m_quant ;
00287                 donne_lm(nz, nzm1, j, k, base, m_quant, l_quant, base_r_ced) ;
00288                 donne_lm(nz, nzm1-1, j, k, base, m_quant, l_quant, base_r_shell) ;
00289                
00290                 int nn0 = l_quant + nn ;    // lowerst power of decay
00291                 
00292                 uu.set_etat_qcq() ; 
00293                 uu.va.set_etat_cf_qcq() ; 
00294                 uu.va.c_cf->set_etat_qcq() ; 
00295                 uu.va.c_cf->t[0]->set_etat_qcq() ;
00296                 uu.va.c_cf->t[1]->set_etat_qcq() ;
00297                 for (int i=0; i<nr_shell; i++) {
00298                     uu.va.c_cf->t[0]->set(0, 0, i) = 
00299                         va.c_cf->operator()(nzm1-1, k, j, i) ; 
00300                     uu.va.c_cf->t[0]->set(1, 0, i) = 0. ; 
00301                     uu.va.c_cf->t[0]->set(2, 0, i) = 0. ;
00302                 }
00303  
00304                 uu.va.c_cf->t[1]->set_etat_zero() ; 
00305 
00306                 uu.va.set_base_r(0, base_r_shell) ; 
00307                 uu.va.set_base_r(1, base_r_ced) ; 
00308  
00309                 // Computation of the derivatives up to order k at the outer
00310                 // of the last shell:
00311                 // ----------------------------------------------------------
00312                 Tbl derivb(kk+1) ;
00313                 derivb.set_etat_qcq() ; 
00314                 duu = uu ; 
00315                 derivb.set(0) = uu.val_grid_point(0, 0, 0, nr_shell-1) ; 
00316                 for (int p=1; p<=kk; p++) {
00317                     tmp = duu.dsdr() ; 
00318                     duu = tmp ; 
00319                     derivb.set(p) = duu.val_grid_point(0, 0, 0, nr_shell-1) ; 
00320                 }
00321                
00322                 // Matrix of the linear system to be solved
00323                 // ----------------------------------------
00324                 
00325                 Matrice mat(kk+1,kk+1) ; 
00326                 mat.set_etat_qcq() ; 
00327                 
00328                 for (int im=0; im<=kk; im++) {
00329                     
00330                     double fact = (im%2 == 0) ? 1. : -1. ; 
00331                     fact /= pow(rbound, nn0 + im) ; 
00332                 
00333                     for (int jm=0; jm<=kk; jm++) {
00334                         
00335                         double prod = 1 ; 
00336                         for (int ir=0; ir<im; ir++) {
00337                             prod *= nn0 + jm + ir ; 
00338                         } 
00339                         
00340                         mat.set(im, jm) = fact * prod / pow(rbound, jm) ; 
00341                         
00342                     }
00343                 }
00344            
00345                 // Resolution of the linear system to get the coefficients
00346                 // of the 1/r^i functions
00347                 //---------------------------------------------------------
00348                 mat.set_band(kk+1, kk+1) ;
00349                 mat.set_lu() ;
00350                 Tbl aa = mat.inverse( derivb ) ; 
00351 
00352                 // Decaying function 
00353                 // -----------------
00354                 vv = 0 ; 
00355                 const Coord& r = map1d.r ; 
00356                 for (int p=0; p<=kk; p++) {
00357                     tmp = aa(p) / pow(r, nn0 + p) ; 
00358                     vv += tmp ; 
00359                 }
00360                 vv.va.set_base( uu.va.get_base() ) ; 
00361 
00362                 // The coefficients of the decaying function 
00363                 // are set to the result
00364                 //-------------------------------------------
00365                 vv.va.coef() ; 
00366                 
00367                 if (vv.get_etat() == ETATZERO) {
00368                      for (int i=0; i<nr_ced; i++) {
00369                         coefresu.set(k,j,i) = 0 ; 
00370                     }
00371                 }
00372                 else {
00373                     assert( vv.va.c_cf != 0x0 ) ; 
00374                     for (int i=0; i<nr_ced; i++) {
00375                         coefresu.set(k,j,i) = vv.va.c_cf->operator()(1,0,0,i) ; 
00376                     }
00377                 }
00378                 
00379                
00380             }
00381          
00382             
00383         }
00384     } 
00385     
00386     if (va.c != 0x0) {
00387       delete va.c ;
00388       va.c = 0x0 ;
00389     }
00390     va.ylm_i() ;     
00391     
00392     // Test of the computation
00393     // -----------------------
00394         
00395     Scalar tmp1(*this) ; 
00396     Scalar tmp2(*mp) ; 
00397     for (int p=0; p<=kk; p++) {
00398         double rd = pow(rbound, tmp1.get_dzpuis()) ; 
00399         double err = 0 ; 
00400         for (int k=0; k<np; k++) {
00401             for (int j=0; j<nt; j++) {
00402                 double diff = fabs( tmp1.val_grid_point(nzm1, k, j, 0) / rd - 
00403                   tmp1.val_grid_point(nzm1-1, k, j, nr_shell-1) ) ;
00404                 if (diff > err) err = diff ;  
00405             }
00406         }
00407         cout << 
00408         "Scalar::smooth_decay: Max error matching of " << p 
00409             << "-th derivative: " << err << endl ; 
00410         tmp2 = tmp1.dsdr() ; 
00411         tmp1 = tmp2 ; 
00412     }
00413     
00414 
00415 }

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