scalar_import_asymy.C

00001 /*
00002  * Member function of the Scalar class for initiating a Scalar from 
00003  * a Scalar defined on another mapping.
00004  * Case where both Scalar's are antisymmetric with respect to their y=0 plane.
00005  */
00006 
00007 /*
00008  *   Copyright (c) 2003 Eric Gourgoulhon & Jerome Novak
00009  *   Copyright (c) 1999-2001 Eric Gourgoulhon (Cmp version)
00010  *
00011  *   This file is part of LORENE.
00012  *
00013  *   LORENE is free software; you can redistribute it and/or modify
00014  *   it under the terms of the GNU General Public License as published by
00015  *   the Free Software Foundation; either version 2 of the License, or
00016  *   (at your option) any later version.
00017  *
00018  *   LORENE is distributed in the hope that it will be useful,
00019  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  *   GNU General Public License for more details.
00022  *
00023  *   You should have received a copy of the GNU General Public License
00024  *   along with LORENE; if not, write to the Free Software
00025  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00026  *
00027  */
00028 
00029 
00030 char scalar_import_asymy_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tensor/Scalar/scalar_import_asymy.C,v 1.3 2003/10/10 15:57:29 j_novak Exp $" ;
00031 
00032 
00033 /*
00034  * $Id: scalar_import_asymy.C,v 1.3 2003/10/10 15:57:29 j_novak Exp $
00035  * $Log: scalar_import_asymy.C,v $
00036  * Revision 1.3  2003/10/10 15:57:29  j_novak
00037  * Added the state one (ETATUN) to the class Scalar
00038  *
00039  * Revision 1.2  2003/10/01 13:04:44  e_gourgoulhon
00040  * The method Tensor::get_mp() returns now a reference (and not
00041  * a pointer) onto a mapping.
00042  *
00043  * Revision 1.1  2003/09/25 09:07:05  j_novak
00044  * Added the functions for importing from another mapping (to be tested).
00045  *
00046  *
00047  * $Header: /cvsroot/Lorene/C++/Source/Tensor/Scalar/scalar_import_asymy.C,v 1.3 2003/10/10 15:57:29 j_novak Exp $
00048  *
00049  */
00050 
00051 
00052 
00053 // Headers C
00054 #include <math.h>
00055 
00056 // Headers Lorene
00057 #include "tensor.h"
00058 #include "param.h"
00059 #include "nbr_spx.h"
00060 
00061             //-------------------------------//
00062             //  Importation in all domains   //
00063             //-------------------------------//
00064 
00065 void Scalar::import_asymy(const Scalar& ci) {
00066     
00067     int nz = mp->get_mg()->get_nzone() ; 
00068     
00069     import_asymy(nz, ci) ; 
00070         
00071 }
00072 
00073             //--------------------------------------//
00074             //  Importation in inner domains only   //
00075             //--------------------------------------//
00076 
00077 void Scalar::import_asymy(int nzet, const Scalar& cm_d) {
00078     
00079     const Map* mp_d = &(cm_d.get_mp()) ; // Departure mapping
00080 
00081     // Trivial case : mappings identical !
00082     // -----------------------------------
00083     
00084     if (mp_d == mp) {
00085     *this = cm_d ; 
00086     return ; 
00087     }
00088     
00089     // Relative orientation of the two mappings
00090     // ----------------------------------------
00091  
00092     int align_rel = (mp->get_bvect_cart()).get_align()  
00093             * (mp_d->get_bvect_cart()).get_align() ;
00094             
00095     switch (align_rel) {
00096 
00097     case 1 : {  // the two mappings have aligned Cartesian axis
00098         import_align_asymy(nzet, cm_d) ; 
00099         break ; 
00100     }
00101 
00102     case -1 : {  // the two mappings have anti-aligned Cartesian axis
00103         import_anti_asymy(nzet, cm_d) ; 
00104         break ; 
00105     }
00106 
00107     default : {  
00108         cout << "Scalar::import_asymy : unexpected value of align_rel : " 
00109          << align_rel << endl ; 
00110         abort() ; 
00111         break ; 
00112     }
00113 
00114     }
00115     
00116 }    
00117 
00118 
00119         //-----------------------------------------//
00120         //   Case of Cartesian axis anti-aligned   //
00121         //-----------------------------------------//
00122 
00123 
00124 void Scalar::import_anti_asymy(int nzet, const Scalar& cm_d) {
00125     
00126     // Trivial case : null Scalar
00127     // ------------------------
00128     
00129     if (cm_d.get_etat() == ETATZERO) {
00130     set_etat_zero() ; 
00131     return ; 
00132     }
00133     if (cm_d.get_etat() == ETATUN) {
00134     set_etat_one() ; 
00135     return ; 
00136     }
00137 
00138     const Map* mp_d = &(cm_d.get_mp()) ; // Departure mapping
00139 
00140     // Protections
00141     // -----------
00142     int align = (mp->get_bvect_cart()).get_align() ;
00143 
00144     assert( align  * (mp_d->get_bvect_cart()).get_align() == -1 ) ; 
00145     
00146     assert(cm_d.get_etat() == ETATQCQ) ;
00147 
00148     if (cm_d.get_dzpuis() != 0) {
00149     cout << 
00150     "Scalar::import_anti_asymy : the dzpuis of the Scalar to be imported"
00151       << " must be zero !" << endl ; 
00152     abort() ; 
00153     }
00154 
00155 
00156     const Mg3d* mg_a = mp->get_mg() ; 
00157     assert(mg_a->get_type_p() == NONSYM) ; 
00158     
00159     
00160     int nz_a = mg_a->get_nzone() ; 
00161     assert(nzet <= nz_a) ;     
00162 
00163     const Valeur& va_d = cm_d.get_spectral_va() ; 
00164     va_d.coef() ;       // The coefficients are required
00165     
00166 
00167     // Preparations for storing the result in *this 
00168     // --------------------------------------------
00169     del_t() ;   // delete all previously computed derived quantities
00170     
00171     set_etat_qcq() ;        // Set the state to ETATQCQ
00172     
00173     va.set_etat_c_qcq() ;   // Allocates the memory for the Mtbl va.c
00174                 //  if it does not exist already
00175     va.c->set_etat_qcq() ;  // Allocates the memory for the Tbl's in each
00176                 //  domain if they do not exist already
00177 
00178 
00179     // Departure (x,y,z) coordinates of the origin of the Arrival mapping :
00180 
00181     double xx_a, yy_a, zz_a ; 
00182     if (align == 1) {
00183     xx_a = mp_d->get_ori_x() - mp->get_ori_x() ; 
00184     yy_a = mp_d->get_ori_y() - mp->get_ori_y() ; 
00185     }
00186     else {
00187     xx_a = mp->get_ori_x() - mp_d->get_ori_x() ; 
00188     yy_a = mp->get_ori_y() - mp_d->get_ori_y() ; 
00189     }
00190     zz_a = mp->get_ori_z() - mp_d->get_ori_z() ; 
00191 
00192     
00193     // r, theta, phi, x, y and z on the Arrival mapping 
00194     //  update of the corresponding Coord's if necessary
00195     
00196     if ( (mp->r).c == 0x0 ) (mp->r).fait() ; 
00197     if ( (mp->tet).c == 0x0 ) (mp->tet).fait() ; 
00198     if ( (mp->phi).c == 0x0 ) (mp->phi).fait() ; 
00199     if ( (mp->x).c == 0x0 ) (mp->x).fait() ; 
00200     if ( (mp->y).c == 0x0 ) (mp->y).fait() ; 
00201     if ( (mp->z).c == 0x0 ) (mp->z).fait() ; 
00202 
00203     const Mtbl* mr_a = (mp->r).c ; 
00204     const Mtbl* mtet_a = (mp->tet).c ; 
00205     const Mtbl* mphi_a = (mp->phi).c ; 
00206     const Mtbl* mx_a = (mp->x).c ;
00207     const Mtbl* my_a = (mp->y).c ;
00208     const Mtbl* mz_a = (mp->z).c ;
00209 
00210     Param par_precis ;      // Required precision in the method Map::val_lx
00211     int nitermax = 100 ;    // Maximum number of iteration in the secant method
00212     int niter ; 
00213     double precis = 1e-15 ; // Absolute precision in the secant method
00214     par_precis.add_int(nitermax) ;  
00215     par_precis.add_int_mod(niter) ; 
00216     par_precis.add_double(precis) ; 
00217 
00218 
00219     // Loop of the Arrival domains where the computation is to be performed
00220     // --------------------------------------------------------------------
00221     
00222     for (int l=0; l < nzet; l++) {
00223     
00224     int nr = mg_a->get_nr(l) ;
00225     int nt = mg_a->get_nt(l) ;
00226     int np = mg_a->get_np(l) ;
00227     int ntnr = nt*nr ;  
00228     
00229     const double* pr_a = mr_a->t[l]->t ;      // Pointer on the values of r
00230     const double* ptet_a = mtet_a->t[l]->t ;  // Pointer on the values of theta
00231     const double* pphi_a = mphi_a->t[l]->t ;  // Pointer on the values of phi
00232     const double* px_a = mx_a->t[l]->t ;      // Pointer on the values of X
00233     const double* py_a = my_a->t[l]->t ;      // Pointer on the values of Y
00234     const double* pz_a = mz_a->t[l]->t ;      // Pointer on the values of Z
00235     
00236     (va.c->t[l])->set_etat_qcq() ;       // Allocates the array of double to
00237                          //  store the result 
00238     double* ptx = (va.c->t[l])->t ;      // Pointer on the allocated array
00239     
00240     
00241     // Loop on half the grid points in the considered arrival domain
00242     // (the other half will be obtained by antisymmetry with respect to
00243     //  the y=0 plane). 
00244         
00245     // Case k=0 (phi=0) : the function is zero (by antisymmetry)
00246     for (int i=0; i<ntnr; i++) {
00247         *ptx = 0 ;   
00248         ptx++ ;   // next point
00249     }
00250     
00251     // Go to k=1 :
00252     pr_a += ntnr ;  
00253     ptet_a += ntnr ;  
00254     pphi_a += ntnr ; 
00255     px_a += ntnr ;  
00256     py_a += ntnr ;  
00257     pz_a += ntnr ;  
00258 
00259     for (int k=1 ; k<np/2 ; k++) {    // np/2 : ~ half the grid
00260         for (int j=0 ; j<nt ; j++) {
00261         for (int i=0 ; i<nr ; i++) {
00262 
00263             double r = *pr_a ; 
00264             double rd, tetd, phid ;
00265             if (r == __infinity) {
00266             rd = r ;
00267             tetd = *ptet_a ;
00268             phid = *pphi_a + M_PI ;
00269             if (phid < 0) phid += 2*M_PI ;
00270             }
00271             else {
00272 
00273             // Cartesian coordinates on the Departure mapping
00274             double xd = - *px_a + xx_a ; 
00275             double yd = - *py_a + yy_a ; 
00276             double zd = *pz_a + zz_a ; 
00277 
00278             // Spherical coordinates on the Departure mapping
00279             double rhod2 = xd*xd + yd*yd ; 
00280             double rhod = sqrt( rhod2 ) ;
00281             rd = sqrt(rhod2 + zd*zd) ;
00282             tetd = atan2(rhod, zd) ;
00283             phid = atan2(yd, xd) ; 
00284             if (phid < 0) phid += 2*M_PI ;
00285             }           
00286 
00287 
00288             // NB: to increase the efficiency, the method Scalar::val_point
00289             //  is not invoked; the method Mtbl_cf::val_point is 
00290             //  called directly instead. 
00291 
00292             // Value of the grid coordinates (l,xi) corresponding to
00293             //  (rd,tetd,phid) :
00294             
00295             int ld ;        // domain index
00296             double xxd ;    // radial coordinate xi in [0,1] or [-1,1]
00297             mp_d->val_lx(rd, tetd, phid, par_precis, ld, xxd) ;
00298 
00299             // Value of the Departure Scalar at the obtained point:
00300             *ptx = va_d.c_cf->val_point_asymy(ld, xxd, tetd, phid) ;
00301 
00302             // Next point : 
00303             ptx++ ;   
00304             pr_a++ ;  
00305             ptet_a++ ;  
00306             pphi_a++ ; 
00307             px_a++ ;  
00308             py_a++ ;  
00309             pz_a++ ;  
00310 
00311         }
00312         }
00313     }
00314     
00315     // Case k=np/2 (phi=pi) : the function is zero (by antisymmetry)
00316     for (int i=0; i<ntnr; i++) {
00317         *ptx = 0 ;   
00318         ptx++ ;   // next point
00319     }
00320     
00321     // Go to k=np/2+1 :
00322     pr_a += ntnr ;  
00323     ptet_a += ntnr ;  
00324     pphi_a += ntnr ; 
00325     px_a += ntnr ;  
00326     py_a += ntnr ;  
00327     pz_a += ntnr ;  
00328 
00329     // The remaining points are obtained by antisymmetry with rspect to the
00330     //  y=0 plane
00331         
00332     for (int k=np/2+1 ; k<np ; k++) {
00333 
00334         // pointer on the value (already computed) at the point symmetric 
00335         // with respect to the plane y=0
00336         double* ptx_symy = (va.c->t[l])->t + (np-k)*nt*nr ;  
00337 
00338         // copy : 
00339         for (int j=0 ; j<nt ; j++) {
00340         for (int i=0 ; i<nr ; i++) {
00341             *ptx = - (*ptx_symy) ; 
00342             ptx++ ;
00343             ptx_symy++ ; 
00344         }
00345         }
00346     } 
00347     
00348         
00349     }   // End of the loop on the Arrival domains
00350     
00351     // In the remaining domains, *this is set to zero:
00352     // ----------------------------------------------
00353     
00354     if (nzet < nz_a) {
00355     annule(nzet, nz_a - 1) ; 
00356     }
00357     
00358     // Treatment of dzpuis
00359     // -------------------
00360     
00361     set_dzpuis(0) ; 
00362 
00363 }
00364 
00365 
00366         //-------------------------------------//
00367         //   Case of aligned Cartesian axis    //
00368         //-------------------------------------//
00369 
00370 
00371 void Scalar::import_align_asymy(int nzet, const Scalar& cm_d) {
00372     
00373     // Trivial case : null Scalar
00374     // ------------------------
00375     
00376     if (cm_d.get_etat() == ETATZERO) {
00377     set_etat_zero() ; 
00378     return ; 
00379     }
00380     if (cm_d.get_etat() == ETATUN) {
00381     set_etat_one() ; 
00382     return ; 
00383     }
00384 
00385     const Map* mp_d = &(cm_d.get_mp()) ; // Departure mapping
00386 
00387     // Protections
00388     // -----------
00389     int align = (mp->get_bvect_cart()).get_align() ;
00390 
00391     assert( align  * (mp_d->get_bvect_cart()).get_align() == 1 ) ; 
00392     
00393     assert(cm_d.get_etat() == ETATQCQ) ;
00394 
00395     if (cm_d.get_dzpuis() != 0) {
00396     cout << 
00397     "Scalar::import_align_asymy : the dzpuis of the Scalar to be imported"
00398     << " must be zero !" << endl ; 
00399     abort() ; 
00400     }
00401 
00402 
00403     const Mg3d* mg_a = mp->get_mg() ; 
00404     assert(mg_a->get_type_p() == NONSYM) ; 
00405 
00406     int nz_a = mg_a->get_nzone() ; 
00407     assert(nzet <= nz_a) ;     
00408 
00409     const Valeur& va_d = cm_d.get_spectral_va() ; 
00410     va_d.coef() ;       // The coefficients are required
00411     
00412 
00413     // Preparations for storing the result in *this 
00414     // --------------------------------------------
00415     del_t() ;   // delete all previously computed derived quantities
00416     
00417     set_etat_qcq() ;        // Set the state to ETATQCQ
00418     
00419     va.set_etat_c_qcq() ;   // Allocates the memory for the Mtbl va.c
00420                 //  if it does not exist already
00421     va.c->set_etat_qcq() ;  // Allocates the memory for the Tbl's in each
00422                 //  domain if they do not exist already
00423 
00424 
00425     // Departure (x,y,z) coordinates of the origin of the Arrival mapping :
00426 
00427     double xx_a, yy_a, zz_a ; 
00428     if (align == 1) {
00429     xx_a = mp->get_ori_x() - mp_d->get_ori_x() ; 
00430     yy_a = mp->get_ori_y() - mp_d->get_ori_y() ; 
00431     }
00432     else {
00433     xx_a = mp_d->get_ori_x() - mp->get_ori_x() ; 
00434     yy_a = mp_d->get_ori_y() - mp->get_ori_y() ; 
00435     }
00436     zz_a = mp->get_ori_z() - mp_d->get_ori_z() ; 
00437 
00438     
00439     // r, theta, phi, x, y and z on the Arrival mapping 
00440     //  update of the corresponding Coord's if necessary
00441     
00442     if ( (mp->r).c == 0x0 ) (mp->r).fait() ; 
00443     if ( (mp->tet).c == 0x0 ) (mp->tet).fait() ; 
00444     if ( (mp->phi).c == 0x0 ) (mp->phi).fait() ; 
00445     if ( (mp->x).c == 0x0 ) (mp->x).fait() ; 
00446     if ( (mp->y).c == 0x0 ) (mp->y).fait() ; 
00447     if ( (mp->z).c == 0x0 ) (mp->z).fait() ; 
00448 
00449     const Mtbl* mr_a = (mp->r).c ; 
00450     const Mtbl* mtet_a = (mp->tet).c ; 
00451     const Mtbl* mphi_a = (mp->phi).c ; 
00452     const Mtbl* mx_a = (mp->x).c ;
00453     const Mtbl* my_a = (mp->y).c ;
00454     const Mtbl* mz_a = (mp->z).c ;
00455 
00456     Param par_precis ;      // Required precision in the method Map::val_lx
00457     int nitermax = 100 ;    // Maximum number of iteration in the secant method
00458     int niter ; 
00459     double precis = 1e-15 ; // Absolute precision in the secant method
00460     par_precis.add_int(nitermax) ;  
00461     par_precis.add_int_mod(niter) ; 
00462     par_precis.add_double(precis) ; 
00463 
00464 
00465     // Loop of the Arrival domains where the computation is to be performed
00466     // --------------------------------------------------------------------
00467     
00468     for (int l=0; l < nzet; l++) {
00469     
00470     int nr = mg_a->get_nr(l) ;
00471     int nt = mg_a->get_nt(l) ;
00472     int np = mg_a->get_np(l) ;
00473     int ntnr = nt*nr ;      
00474     
00475     const double* pr_a = mr_a->t[l]->t ;      // Pointer on the values of r
00476     const double* ptet_a = mtet_a->t[l]->t ;  // Pointer on the values of theta
00477     const double* pphi_a = mphi_a->t[l]->t ;  // Pointer on the values of phi
00478     const double* px_a = mx_a->t[l]->t ;      // Pointer on the values of X
00479     const double* py_a = my_a->t[l]->t ;      // Pointer on the values of Y
00480     const double* pz_a = mz_a->t[l]->t ;      // Pointer on the values of Z
00481     
00482     (va.c->t[l])->set_etat_qcq() ;       // Allocates the array of double to
00483                          //  store the result 
00484     double* ptx = (va.c->t[l])->t ;      // Pointer on the allocated array
00485     
00486     
00487     
00488     // Loop on half the grid points in the considered arrival domain
00489     // (the other half will be obtained by antisymmetry with respect to
00490     //  the y=0 plane). 
00491         
00492     // Case k=0 (phi=0) : the function is zero (by antisymmetry)
00493     for (int i=0; i<ntnr; i++) {
00494         *ptx = 0 ;   
00495         ptx++ ;   // next point
00496     }
00497     
00498     // Go to k=1 :
00499     pr_a += ntnr ;  
00500     ptet_a += ntnr ;  
00501     pphi_a += ntnr ; 
00502     px_a += ntnr ;  
00503     py_a += ntnr ;  
00504     pz_a += ntnr ;  
00505 
00506     for (int k=1 ; k<np/2 ; k++) {    // np/2 : ~ half the grid
00507         for (int j=0 ; j<nt ; j++) {
00508         for (int i=0 ; i<nr ; i++) {
00509 
00510             double r = *pr_a ; 
00511             double rd, tetd, phid ;
00512             if (r == __infinity) {
00513             rd = r ;
00514             tetd = *ptet_a ;
00515             phid = *pphi_a ;
00516             }
00517             else {
00518 
00519             // Cartesian coordinates on the Departure mapping
00520             double xd = *px_a + xx_a ; 
00521             double yd = *py_a + yy_a ; 
00522             double zd = *pz_a + zz_a ; 
00523 
00524             // Spherical coordinates on the Departure mapping
00525             double rhod2 = xd*xd + yd*yd ; 
00526             double rhod = sqrt( rhod2 ) ;
00527             rd = sqrt(rhod2 + zd*zd) ;
00528             tetd = atan2(rhod, zd) ;
00529             phid = atan2(yd, xd) ; 
00530             if (phid < 0) phid += 2*M_PI ;
00531             }           
00532 
00533 
00534             // NB: to increase the efficiency, the method Scalar::val_point
00535             //  is not invoked; the method Mtbl_cf::val_point is 
00536             //  called directly instead. 
00537 
00538             // Value of the grid coordinates (l,xi) corresponding to
00539             //  (rd,tetd,phid) :
00540             
00541             int ld ;        // domain index
00542             double xxd ;    // radial coordinate xi in [0,1] or [-1,1]
00543             mp_d->val_lx(rd, tetd, phid, par_precis, ld, xxd) ;
00544 
00545             // Value of the Departure Scalar at the obtained point:
00546             *ptx = va_d.c_cf->val_point_asymy(ld, xxd, tetd, phid) ;
00547 
00548             // Next point : 
00549             ptx++ ;   
00550             pr_a++ ;  
00551             ptet_a++ ;  
00552             pphi_a++ ; 
00553             px_a++ ;  
00554             py_a++ ;  
00555             pz_a++ ;  
00556 
00557         }
00558         }
00559     }   
00560     
00561         
00562     // Case k=np/2 (phi=pi) : the function is zero (by antisymmetry)
00563     for (int i=0; i<ntnr; i++) {
00564         *ptx = 0 ;   
00565         ptx++ ;   // next point
00566     }
00567     
00568     // Go to k=np/2+1 :
00569     pr_a += ntnr ;  
00570     ptet_a += ntnr ;  
00571     pphi_a += ntnr ; 
00572     px_a += ntnr ;  
00573     py_a += ntnr ;  
00574     pz_a += ntnr ;  
00575 
00576     // The remaining points are obtained by antisymmetry with respect to the
00577     //  y=0 plane
00578         
00579     for (int k=np/2+1 ; k<np ; k++) {
00580 
00581         // pointer on the value (already computed) at the point symmetric 
00582         // with respect to the plane y=0
00583         double* ptx_symy = (va.c->t[l])->t + (np-k)*nt*nr ;  
00584 
00585         // copy : 
00586         for (int j=0 ; j<nt ; j++) {
00587         for (int i=0 ; i<nr ; i++) {
00588             *ptx = - (*ptx_symy) ; 
00589             ptx++ ;
00590             ptx_symy++ ; 
00591         }
00592         }
00593     } 
00594 
00595     }   // End of the loop on the Arrival domains
00596     
00597     // In the remaining domains, *this is set to zero:
00598     // ----------------------------------------------
00599     
00600     if (nzet < nz_a) {
00601     annule(nzet, nz_a - 1) ; 
00602     }
00603     
00604     // Treatment of dzpuis
00605     // -------------------
00606     
00607     set_dzpuis(0) ; 
00608 
00609 }

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