tensor.C

00001 /*
00002  *  Methods of class Tensor
00003  *
00004  *   (see file tensor.h for documentation)
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 2003-2004 Eric Gourgoulhon & Jerome Novak
00010  *
00011  *   Copyright (c) 1999-2001 Philippe Grandclement (for preceding class Tenseur)
00012  *
00013  *   This file is part of LORENE.
00014  *
00015  *   LORENE is free software; you can redistribute it and/or modify
00016  *   it under the terms of the GNU General Public License as published by
00017  *   the Free Software Foundation; either version 2 of the License, or
00018  *   (at your option) any later version.
00019  *
00020  *   LORENE is distributed in the hope that it will be useful,
00021  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *   GNU General Public License for more details.
00024  *
00025  *   You should have received a copy of the GNU General Public License
00026  *   along with LORENE; if not, write to the Free Software
00027  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028  *
00029  */
00030 
00031 
00032 char tensor_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tensor/tensor.C,v 1.39 2007/12/21 16:07:08 j_novak Exp $" ;
00033 
00034 /*
00035  * $Id: tensor.C,v 1.39 2007/12/21 16:07:08 j_novak Exp $
00036  * $Log: tensor.C,v $
00037  * Revision 1.39  2007/12/21 16:07:08  j_novak
00038  * Methods to filter Tensor, Vector and Sym_tensor objects.
00039  *
00040  * Revision 1.38  2005/10/25 08:56:38  p_grandclement
00041  * addition of std_spectral_base in the case of odd functions near the origin
00042  *
00043  * Revision 1.37  2005/05/18 11:45:44  j_novak
00044  * Added del_deriv() calls at the end of inc/dec_dzpuis.
00045  *
00046  * Revision 1.36  2004/07/08 12:21:53  j_novak
00047  * Replaced tensor::annule_extern_c2 with tensor::annule_extern_cn for a
00048  * more general transition.
00049  *
00050  * Revision 1.35  2004/06/17 06:55:07  e_gourgoulhon
00051  * Added method annule_extern_c2.
00052  *
00053  * Revision 1.34  2004/03/04 09:47:51  e_gourgoulhon
00054  * Method annule_domain(int, int): added call to virtual function
00055  *  del_deriv() at the end !
00056  *
00057  * Revision 1.33  2004/02/27 21:14:27  e_gourgoulhon
00058  * Modif of method derive_con to create proper type of the result.
00059  *
00060  * Revision 1.32  2004/02/19 22:10:14  e_gourgoulhon
00061  * Added argument "comment" in method spectral_display.
00062  *
00063  * Revision 1.31  2004/02/05 15:03:47  e_gourgoulhon
00064  * Corrected bug in method derive_con().
00065  *
00066  * Revision 1.30  2004/01/27 13:05:11  j_novak
00067  * Removed the method Tensor::mult_r_ced()
00068  *
00069  * Revision 1.29  2004/01/19 16:32:13  e_gourgoulhon
00070  * Added operator()(int, int, int, int) and set(int, int, int, int)
00071  * for direct access to components of valence 4 tensors.
00072  *
00073  * Revision 1.28  2004/01/04 20:55:23  e_gourgoulhon
00074  * Method spectral_display(): added printing of type of class (through typeid).
00075  *
00076  * Revision 1.27  2003/12/30 23:09:47  e_gourgoulhon
00077  * Change in methods derive_cov() and divergence() to take into account
00078  *  the change of name: Metric::get_connect() --> Metric::connect().
00079  *
00080  * Revision 1.26  2003/12/27 15:01:50  e_gourgoulhon
00081  * Method derive_con(): the position of the derivation index has
00082  * been changed from the first one to the last one.
00083  *
00084  * Revision 1.25  2003/11/03 22:34:41  e_gourgoulhon
00085  * Method dec_dzpuis: changed the name of argument dec --> decrem
00086  * (in order not to shadow some globally defined dec).
00087  *
00088  * Revision 1.24  2003/10/29 11:02:54  e_gourgoulhon
00089  * Functions dec_dzpuis and inc_dzpuis have now an integer argument to
00090  * specify by which amount dzpuis is to be increased.
00091  * Accordingly methods dec2_dzpuis and inc2_dzpuis have been suppressed
00092  *
00093  * Revision 1.23  2003/10/27 10:49:48  e_gourgoulhon
00094  * Slightly modified operator<<.
00095  *
00096  * Revision 1.22  2003/10/19 19:57:00  e_gourgoulhon
00097  * -- Added new method spectral_display
00098  * -- slightly rearranged the operator<<
00099  *
00100  * Revision 1.21  2003/10/16 15:27:46  e_gourgoulhon
00101  * Name of method annule(int ) changed to annule_domain(int ).
00102  *
00103  * Revision 1.20  2003/10/16 14:21:36  j_novak
00104  * The calculation of the divergence of a Tensor is now possible.
00105  *
00106  * Revision 1.19  2003/10/13 13:52:40  j_novak
00107  * Better managment of derived quantities.
00108  *
00109  * Revision 1.18  2003/10/11 16:47:10  e_gourgoulhon
00110  * Suppressed the call to Ibtl::set_etat_qcq() after the construction
00111  * of the Itbl's, thanks to the new property of the Itbl class.
00112  *
00113  * Revision 1.17  2003/10/11 14:48:40  e_gourgoulhon
00114  * Line 344: suppressed assert(resu == -1)
00115  *           and added a break command to quit the loop.
00116  *
00117  * Revision 1.16  2003/10/08 14:24:09  j_novak
00118  * replaced mult_r_zec with mult_r_ced
00119  *
00120  * Revision 1.15  2003/10/07 15:25:38  e_gourgoulhon
00121  * Added call to del_derive_met in del_deriv().
00122  *
00123  * Revision 1.14  2003/10/07 09:10:00  j_novak
00124  * Use of ::contract instead of up()
00125  *
00126  * Revision 1.13  2003/10/06 20:51:43  e_gourgoulhon
00127  * In methods set: changed name "indices" to "idx" to avoid shadowing
00128  *  of class member.
00129  *
00130  * Revision 1.12  2003/10/06 16:17:31  j_novak
00131  * Calculation of contravariant derivative and Ricci scalar.
00132  *
00133  * Revision 1.11  2003/10/06 13:58:48  j_novak
00134  * The memory management has been improved.
00135  * Implementation of the covariant derivative with respect to the exact Tensor
00136  * type.
00137  *
00138  * Revision 1.10  2003/10/05 21:11:22  e_gourgoulhon
00139  * - Added method std_spectral_base().
00140  * - Removed method change_triad() from this file.
00141  *
00142  * Revision 1.9  2003/10/03 15:09:38  j_novak
00143  * Improved display
00144  *
00145  * Revision 1.8  2003/10/03 11:21:48  j_novak
00146  * More methods for the class Metric
00147  *
00148  * Revision 1.7  2003/10/01 11:56:31  e_gourgoulhon
00149  * Corrected error: '=' replaced by '==' in two assert tests.
00150  *
00151  * Revision 1.6  2003/09/30 08:38:23  j_novak
00152  * added a header typeinfo
00153  *
00154  * Revision 1.5  2003/09/29 12:52:57  j_novak
00155  * Methods for changing the triad are implemented.
00156  *
00157  * Revision 1.4  2003/09/26 14:33:53  j_novak
00158  * Arithmetic functions for the class Tensor
00159  *
00160  * Revision 1.3  2003/09/24 15:10:54  j_novak
00161  * Suppression of the etat flag in class Tensor (still present in Scalar)
00162  *
00163  * Revision 1.2  2003/09/23 08:52:17  e_gourgoulhon
00164  * new version
00165  *
00166  * Revision 1.1  2003/09/22 12:52:51  e_gourgoulhon
00167  * First version: not ready yet !
00168  *
00169  *
00170  * $Header: /cvsroot/Lorene/C++/Source/Tensor/tensor.C,v 1.39 2007/12/21 16:07:08 j_novak Exp $
00171  *
00172  */
00173 
00174 // Headers C
00175 #include <stdlib.h>
00176 #include <assert.h>
00177 #include <math.h>
00178 
00179 // Headers Lorene
00180 #include "metric.h"
00181 #include "utilitaires.h"
00182 
00183             //--------------//
00184             // Constructors //
00185             //--------------//
00186 
00187 // Standard constructor 
00188 // --------------------
00189 Tensor::Tensor(const Map& map, int val, const Itbl& tipe, 
00190          const Base_vect& triad_i) 
00191         : mp(&map), valence(val), triad(&triad_i), type_indice(tipe), 
00192            n_comp(int(pow(3., val))){
00193         
00194     // Des verifs :
00195     assert (valence >= 0) ;
00196     assert (tipe.get_ndim() == 1) ;
00197     assert (valence == tipe.get_dim(0)) ;
00198     for (int i=0 ; i<valence ; i++)
00199     assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
00200     
00201     cmp = new Scalar*[n_comp] ;
00202 
00203     for (int i=0 ; i<n_comp ; i++)
00204     cmp[i] = new Scalar(map) ;
00205 
00206     set_der_0x0() ;
00207     
00208 }
00209 
00210 // Standard constructor with the triad passed as a pointer
00211 // -------------------------------------------------------
00212 Tensor::Tensor(const Map& map, int val, const Itbl& tipe, 
00213          const Base_vect* triad_i) 
00214         : mp(&map), valence(val), triad(triad_i), type_indice(tipe), 
00215            n_comp(int(pow(3., val))){
00216         
00217     // Des verifs :
00218     assert (valence >= 0) ;
00219     assert (tipe.get_ndim() == 1) ;
00220     assert (valence == tipe.get_dim(0)) ;
00221     for (int i=0 ; i<valence ; i++)
00222     assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
00223     
00224     cmp = new Scalar*[n_comp] ;
00225 
00226     for (int i=0 ; i<n_comp ; i++)
00227     cmp[i] = new Scalar(map) ;
00228 
00229     set_der_0x0() ;
00230 
00231 }
00232 
00233 
00234 
00235 
00236 // Standard constructor when all the indices are of the same type
00237 // --------------------------------------------------------------
00238 Tensor::Tensor(const Map& map, int val, int tipe, const Base_vect& triad_i) 
00239         : mp(&map), valence(val), triad(&triad_i), type_indice(val), 
00240                   n_comp(int(pow(3., val))){
00241     
00242     // Des verifs :
00243     assert (valence >= 0) ;
00244     assert ((tipe == COV) || (tipe == CON)) ;
00245 
00246     type_indice = tipe ;
00247     
00248     cmp = new Scalar*[n_comp] ;
00249 
00250     for (int i=0 ; i<n_comp ; i++)
00251     cmp[i] = new Scalar(map) ;
00252 
00253     set_der_0x0() ;
00254 }   
00255     
00256 // Copy constructor
00257 // ----------------
00258 Tensor::Tensor (const Tensor& source) : 
00259     mp(source.mp), valence(source.valence), triad(source.triad), 
00260     type_indice(source.type_indice) {
00261   
00262     n_comp = int(pow(3., valence)) ;
00263         
00264     cmp = new Scalar*[n_comp] ;
00265     for (int i=0 ; i<n_comp ; i++) {
00266 
00267         // the following writing takes into account the case where
00268         // source belongs to a derived class of Tensor with a different
00269         // storage of components :
00270 
00271     int place_source = source.position(indices(i)) ;
00272     cmp[i] = new Scalar(*source.cmp[place_source]) ;
00273     }
00274 
00275     set_der_0x0() ;
00276 
00277 }   
00278 
00279 
00280 // Constructor from a file
00281 // -----------------------
00282 Tensor::Tensor(const Map& mapping, const Base_vect& triad_i, FILE* fd)
00283          : mp(&mapping), triad(&triad_i), type_indice(fd){
00284    
00285     fread_be(&valence, sizeof(int), 1, fd) ;
00286 
00287     if (valence != 0) {
00288         Base_vect* triad_fich = Base_vect::bvect_from_file(fd) ; 
00289         assert( *triad_fich == *triad) ; 
00290         delete triad_fich ; 
00291     }
00292     else{
00293         triad = 0x0 ; 
00294     }
00295     
00296     fread_be(&n_comp, sizeof(int), 1, fd) ;
00297     
00298     cmp = new Scalar*[n_comp] ;
00299     for (int i=0 ; i<n_comp ; i++)
00300       cmp[i] = new Scalar(*mp, *(mp->get_mg()), fd) ;
00301 
00302     set_der_0x0() ;
00303 }
00304 
00305 
00306 //  Constructor for a scalar field: to be used by the derived
00307 //  class {\tt Scalar}
00308 //-----------------------------------------------------------
00309 Tensor::Tensor(const Map& map) : mp(&map), valence(0), triad(0x0),
00310         type_indice(0), n_comp(1) {
00311         
00312   cmp = new Scalar*[n_comp] ; 
00313   cmp[0] = 0x0 ; 
00314   
00315   set_der_0x0() ;
00316 }
00317 
00318 
00319 // Constructor used by the derived classes
00320 // ---------------------------------------
00321 Tensor::Tensor (const Map& map, int val, const Itbl& tipe, int compo, 
00322         const Base_vect& triad_i) :
00323      mp(&map), valence(val), triad(&triad_i), type_indice(tipe), n_comp(compo)
00324 {
00325      
00326     // Des verifs :
00327     assert (valence >= 0) ;
00328     assert (tipe.get_ndim() == 1) ;
00329     assert (n_comp > 0) ;   
00330     assert (valence == tipe.get_dim(0)) ;
00331     for (int i=0 ; i<valence ; i++)
00332     assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
00333     
00334     cmp = new Scalar*[n_comp] ;
00335 
00336     for (int i=0 ; i<n_comp ; i++)
00337     cmp[i] = new Scalar(map) ;
00338 
00339     set_der_0x0() ;
00340   
00341 }
00342 
00343 // Constructor used by the derived classes when all the indices are of 
00344 // the same type.
00345 // -------------------------------------------------------------------
00346 Tensor::Tensor (const Map& map, int val, int tipe, int compo, 
00347         const Base_vect& triad_i) :
00348      mp(&map), valence(val), triad(&triad_i), type_indice(val), n_comp(compo)
00349 {
00350 
00351     // Des verifs :
00352     assert (valence >= 0) ;
00353     assert (n_comp >= 0) ;
00354     assert ((tipe == COV) || (tipe == CON)) ;
00355 
00356     type_indice = tipe ;
00357     
00358     cmp = new Scalar*[n_comp] ;
00359 
00360     for (int i=0 ; i<n_comp ; i++)
00361       cmp[i] = new Scalar(map) ;
00362 
00363     set_der_0x0() ;
00364 
00365 }
00366 
00367             //--------------//
00368             //  Destructor  //
00369             //--------------//
00370 
00371 
00372 Tensor::~Tensor () {
00373     
00374     Tensor::del_deriv() ;
00375 
00376     for (int i=0 ; i<n_comp ; i++) {
00377       if (cmp[i] != 0x0)
00378     delete cmp[i] ;
00379     }
00380     delete [] cmp ;
00381 }
00382 
00383 
00384 
00385 void Tensor::del_deriv() const {
00386 
00387   for (int i=0; i<N_MET_MAX; i++) 
00388     del_derive_met(i) ;
00389 
00390   set_der_0x0() ;
00391 
00392 }
00393 
00394 void Tensor::set_der_0x0() const {
00395 
00396   for (int i=0; i<N_MET_MAX; i++) 
00397     set_der_met_0x0(i) ;
00398 
00399 }
00400 
00401 void Tensor::del_derive_met(int j) const {
00402 
00403   assert( (j>=0) && (j<N_MET_MAX) ) ;
00404 
00405   if (met_depend[j] != 0x0) {
00406     for (int i=0 ; i<N_TENSOR_DEPEND ; i++)
00407       if (met_depend[j]->tensor_depend[i] == this)
00408         met_depend[j]->tensor_depend[i] = 0x0 ;
00409     if (p_derive_cov[j] != 0x0)
00410       delete p_derive_cov[j] ;
00411     if (p_derive_con[j] != 0x0)
00412       delete p_derive_con[j] ;
00413     if (p_divergence[j] != 0x0)
00414       delete p_divergence[j] ;
00415 
00416     set_der_met_0x0(j) ;
00417   }
00418 }
00419 
00420 void Tensor::set_der_met_0x0(int i) const {
00421 
00422   assert( (i>=0) && (i<N_MET_MAX) ) ;
00423   met_depend[i] = 0x0 ;
00424   p_derive_cov[i] = 0x0 ;
00425   p_derive_con[i] = 0x0 ;
00426   p_divergence[i] = 0x0 ;
00427 
00428 }
00429 
00430 int Tensor::get_place_met(const Metric& metre) const {
00431   int resu = -1 ;
00432   for (int i=0; i<N_MET_MAX; i++) 
00433     if (met_depend[i] == &metre) {
00434         resu = i ;
00435         break ; 
00436     }
00437   return resu ;
00438 }
00439 
00440 void Tensor::set_dependance (const Metric& met) const {
00441     
00442   int nmet = 0 ;
00443   bool deja = false ;
00444   for (int i=0; i<N_MET_MAX; i++) {
00445     if (met_depend[i] == &met) deja = true ;
00446     if ((!deja) && (met_depend[i] != 0x0)) nmet++ ;
00447   }
00448   if (nmet == N_MET_MAX) {
00449     cout << "Too many metrics in Tensor::set_dependances" << endl ;
00450     abort() ;
00451   }
00452   if (!deja) { 
00453     int conte = 0 ;
00454     while ((conte < N_TENSOR_DEPEND) && (met.tensor_depend[conte] != 0x0))
00455       conte ++ ;
00456     
00457     if (conte == N_TENSOR_DEPEND) {
00458       cout << "Too many dependancies in Tensor::set_dependances " << endl ;
00459       abort() ;
00460     }
00461     else {
00462       met.tensor_depend[conte] = this ;
00463       met_depend[nmet] = &met ;
00464     }
00465   }
00466 }
00467 
00468 void Tensor::set_etat_qcq() { 
00469     
00470     del_deriv() ;
00471     for (int i=0 ; i<n_comp ; i++) {
00472       cmp[i]->set_etat_qcq() ; 
00473     }
00474 }
00475 
00476 void Tensor::set_etat_nondef() { 
00477     
00478     del_deriv() ;
00479     for (int i=0 ; i<n_comp ; i++) {
00480       cmp[i]->set_etat_nondef() ; 
00481     }
00482 }
00483 
00484 void Tensor::set_etat_zero() { 
00485     
00486     del_deriv() ;
00487     for (int i=0 ; i<n_comp ; i++) {
00488       cmp[i]->set_etat_zero() ; 
00489     }
00490 }
00491 
00492 
00493 // Allocates everything
00494 // --------------------
00495 void Tensor::allocate_all() {
00496     
00497   del_deriv() ;
00498   for (int i=0 ; i<n_comp ; i++) {
00499     cmp[i]->allocate_all() ; 
00500   }
00501     
00502 } 
00503 
00504 
00505 
00506 void Tensor::set_triad(const Base_vect& bi) {
00507     
00508     triad = &bi ; 
00509     
00510 }
00511 
00512 int Tensor::position (const Itbl& idx) const {
00513     
00514     assert (idx.get_ndim() == 1) ;
00515     assert (idx.get_dim(0) == valence) ;
00516     
00517     for (int i=0 ; i<valence ; i++)
00518     assert ((idx(i)>=1) && (idx(i)<=3)) ;
00519     int res = 0 ;
00520     for (int i=0 ; i<valence ; i++)
00521         res = 3*res+(idx(i)-1) ;
00522     
00523     return res;
00524 }
00525 
00526 Itbl Tensor::indices (int place) const {
00527     
00528     assert ((place >= 0) && (place < n_comp)) ;
00529 
00530     Itbl res(valence) ;
00531             
00532     for (int i=valence-1 ; i>=0 ; i--) {
00533         res.set(i) = div(place, 3).rem ;
00534         place = int((place-res(i))/3) ;
00535         res.set(i)++ ; 
00536     }
00537     return res ;
00538 }
00539 
00540 void Tensor::operator=(const Tensor& t) {
00541     
00542     assert (valence == t.valence) ;
00543 
00544     triad = t.triad ; 
00545 
00546     for (int i=0 ; i<valence ; i++)
00547       assert(t.type_indice(i) == type_indice(i)) ;
00548     
00549     for (int i=0 ; i<n_comp ; i++) {
00550       int place_t = t.position(indices(i)) ;
00551       *cmp[i] = *t.cmp[place_t] ;
00552     }
00553 
00554     del_deriv() ;
00555 
00556 }
00557 
00558 void Tensor::operator+=(const Tensor& t) {
00559     
00560     assert (valence == t.valence) ;
00561     assert (triad == t.triad) ; 
00562     for (int i=0 ; i<valence ; i++)
00563       assert(t.type_indice(i) == type_indice(i)) ;
00564     
00565     for (int i=0 ; i<n_comp ; i++) {
00566       int place_t = t.position(indices(i)) ;
00567       *cmp[i] += *t.cmp[place_t] ;
00568     }
00569 
00570     del_deriv() ;
00571 
00572 }
00573 
00574 void Tensor::operator-=(const Tensor& t) {
00575     
00576     assert (valence == t.valence) ;
00577     assert (triad == t.triad) ; 
00578     for (int i=0 ; i<valence ; i++)
00579       assert(t.type_indice(i) == type_indice(i)) ;
00580     
00581     for (int i=0 ; i<n_comp ; i++) {
00582       int place_t = t.position(indices(i)) ;
00583       *cmp[i] -= *t.cmp[place_t] ;
00584     }
00585 
00586     del_deriv() ;
00587 
00588 }
00589 
00590 
00591 
00592 // Affectation d'un tenseur d'ordre 2 :
00593 Scalar& Tensor::set(int ind1, int ind2) {
00594     
00595     assert (valence == 2) ;
00596     
00597     Itbl ind (valence) ;
00598     ind.set(0) = ind1 ;
00599     ind.set(1) = ind2 ;
00600     
00601     int place = position(ind) ;
00602     
00603     del_deriv() ;
00604     return *cmp[place] ;
00605 }
00606 
00607 // Affectation d'un tenseur d'ordre 3 :
00608 Scalar& Tensor::set(int ind1, int ind2, int ind3) {
00609     
00610     assert (valence == 3) ;
00611     
00612     Itbl idx(valence) ;
00613     idx.set(0) = ind1 ;
00614     idx.set(1) = ind2 ;
00615     idx.set(2) = ind3 ;
00616     int place = position(idx) ;
00617     del_deriv() ;
00618  
00619     return *cmp[place] ;
00620 }
00621 
00622 
00623 // Affectation d'un tenseur d'ordre 4 :
00624 Scalar& Tensor::set(int ind1, int ind2, int ind3, int ind4) {
00625     
00626     assert (valence == 4) ;
00627     
00628     Itbl idx(valence) ;
00629     idx.set(0) = ind1 ;
00630     idx.set(1) = ind2 ;
00631     idx.set(2) = ind3 ;
00632     idx.set(3) = ind4 ;
00633     int place = position(idx) ;
00634     del_deriv() ;
00635  
00636     return *cmp[place] ;
00637 }
00638 
00639 
00640 // Affectation cas general
00641 Scalar& Tensor::set(const Itbl& idx) {
00642     
00643     assert (idx.get_ndim() == 1) ;
00644     assert (idx.get_dim(0) == valence) ;
00645         
00646     int place = position(idx) ;
00647     
00648     del_deriv() ;
00649     return *cmp[place] ;
00650 }
00651 
00652 // Annulation dans des domaines
00653 void Tensor::annule_domain(int l) {
00654     
00655     annule(l, l) ;     
00656 }
00657 
00658 void Tensor::annule(int l_min, int l_max) {
00659     
00660     // Cas particulier: annulation globale : 
00661     if ( (l_min == 0) && (l_max == mp->get_mg()->get_nzone()-1) ) {
00662       set_etat_zero() ;
00663       return ; 
00664     }
00665     
00666     // Annulation des composantes:
00667     for (int i=0 ; i<n_comp ; i++) {
00668       cmp[i]->annule(l_min, l_max) ; 
00669     }
00670     
00671     // The derived members are no longer up to date:
00672     del_deriv() ;
00673     
00674 }
00675 
00676 
00677 void Tensor::annule_extern_cn(int lrac, int deg) {
00678 
00679     // Not applicable in the nucleus nor the CED:
00680     assert( mp->get_mg()->get_type_r(lrac) == FIN ) ; 
00681 
00682     int nz = mp->get_mg()->get_nzone() ;
00683 #ifndef NDEBUG
00684     if ((2*deg+1) >= mp->get_mg()->get_nr(lrac)) 
00685       cout << "Tensor::annule_extern_cn : \n" 
00686        << "WARNING!! \n"
00687        << "The number of coefficients in r is too low \n"
00688        << "to do a clean matching..." << endl ;
00689 #endif
00690     // Boundary of domain lrac
00691     double r_min = mp->val_r(lrac, -1., 0., 0.)  ; 
00692     double r_max = mp->val_r(lrac, 1., 0., 0.)  ; 
00693 
00694     //Definition of binomial coefficients array
00695     Itbl binom(deg+1, deg+1) ;
00696     binom.annule_hard() ;
00697     binom.set(0,0) = 1 ;
00698     for (int n=1; n<=deg; n++) {
00699       binom.set(n,0) = 1 ;
00700       for (int k=1; k<=n; k++) 
00701     binom.set(n,k) = binom(n-1, k) + binom(n-1, k-1) ;
00702     }
00703     
00704     // Coefficient of the second polynomial factor
00705     Tbl coef(deg+1) ;
00706     coef.set_etat_qcq() ;
00707     coef.set(deg) = 1 ;
00708     int sg = -1 ;
00709     for (int i=deg-1; i>=0; i--) {
00710       
00711       coef.set(i) = double(r_max*(i+1)*coef(i+1) 
00712                + sg*binom(deg,i)*(2*deg+1)*pow(r_min,deg-i))
00713     / double(deg+i+1) ;
00714       sg *= -1 ;
00715     }
00716     
00717     // Normalization to have 1 at r_min
00718     double aa = coef(deg) ;
00719     for (int i = deg-1; i>=0; i--) 
00720       aa = r_min*aa + coef(i) ;
00721     aa *= pow(r_min - r_max, deg+1) ;
00722     aa = 1/aa ;
00723 
00724     Mtbl mr = mp->r ;
00725     Tbl rr = mr(lrac) ;
00726     
00727     Tbl poly(rr) ;
00728     poly = coef(deg) ;
00729     for (int i=deg-1; i>=0; i--)
00730       poly = rr*poly + coef(i) ;
00731     poly *= aa*pow((rr-r_max), deg+1) ;
00732     
00733     Scalar rac(*mp) ; 
00734     rac.allocate_all() ; 
00735     for (int l=0; l<lrac; l++) rac.set_domain(l) = 1 ; 
00736     rac.set_domain(lrac) = poly ; 
00737     rac.annule(lrac+1,nz-1) ; 
00738     rac.std_spectral_base() ;
00739     
00740     for (int ic=0; ic<n_comp; ic++) *(cmp[ic]) *= rac ; 
00741 
00742     del_deriv() ;    
00743 }
00744 
00745 
00746 
00747 const Scalar& Tensor::operator()(int indice1, int indice2) const {
00748     
00749     assert(valence == 2) ;
00750     
00751     Itbl idx(2) ;       
00752     idx.set(0) = indice1 ;
00753     idx.set(1) = indice2 ;
00754     return *cmp[position(idx)] ;
00755 
00756 }
00757 
00758 const Scalar& Tensor::operator()(int indice1, int indice2, int indice3) const {
00759     
00760     assert(valence == 3) ;
00761     
00762     Itbl idx(3) ;       
00763     idx.set(0) = indice1 ;
00764     idx.set(1) = indice2 ;
00765     idx.set(2) = indice3 ;
00766     return *cmp[position(idx)] ;
00767 }
00768 
00769 
00770 const Scalar& Tensor::operator()(int indice1, int indice2, int indice3,
00771                                  int indice4) const {
00772     
00773     assert(valence == 4) ;
00774     
00775     Itbl idx(4) ;       
00776     idx.set(0) = indice1 ;
00777     idx.set(1) = indice2 ;
00778     idx.set(2) = indice3 ;
00779     idx.set(3) = indice4 ;
00780     return *cmp[position(idx)] ;
00781 }
00782 
00783 
00784 
00785 const Scalar& Tensor::operator()(const Itbl& ind) const {
00786     
00787     assert (ind.get_ndim() == 1) ;
00788     assert (ind.get_dim(0) == valence) ;
00789     return *cmp[position(ind)] ;
00790     
00791 }
00792 
00793 
00794 // Gestion de la CED :
00795 void Tensor::dec_dzpuis(int decrem) {
00796     
00797   for (int i=0 ; i<n_comp ; i++)
00798     cmp[i]->dec_dzpuis(decrem) ;
00799 
00800   del_deriv() ;
00801 }
00802 
00803 void Tensor::inc_dzpuis(int inc) {
00804 
00805     for (int i=0 ; i<n_comp ; i++)
00806       cmp[i]->inc_dzpuis(inc) ;
00807 
00808     del_deriv() ;
00809 }
00810 
00811 
00812 // Le cout :
00813 ostream& operator<<(ostream& flux, const Tensor &source ) {
00814 
00815     flux << '\n' ;
00816     flux << "Lorene class : " << typeid(source).name() 
00817         << "           Valence : " << source.valence << '\n' ;
00818 
00819     if (source.get_triad() != 0x0) {
00820         flux << "Vectorial basis (triad) on which the components are defined :" 
00821          << '\n' ; 
00822         flux << *(source.get_triad()) << '\n' ;
00823     }
00824     
00825     if (source.valence != 0) {
00826         flux <<    "Type of the indices : " ;
00827         for (int i=0 ; i<source.valence ; i++) {
00828             flux << "index " << i << " : " ;
00829             if (source.type_indice(i) == CON)
00830                 flux << " contravariant." << '\n' ;
00831             else
00832                 flux << " covariant." << '\n' ;
00833             if ( i < source.valence-1 ) flux << "                      " ;
00834         }
00835         flux << '\n' ; 
00836     }
00837     
00838     for (int i=0 ; i<source.n_comp ; i++) {
00839 
00840         if (source.valence == 0) {
00841             flux << 
00842             "===================== Scalar field ========================= \n" ;
00843         }
00844         else { 
00845             flux << "================ Component " ;
00846             Itbl num_indices = source.indices(i) ;
00847             for (int j=0 ; j<source.valence ; j++) {
00848                 flux << " " << num_indices(j) ;
00849             }
00850             flux << " ================ \n" ; 
00851         }
00852         flux << '\n' ; 
00853       
00854         flux << *source.cmp[i] << '\n' ;
00855     }
00856     
00857     return flux ;
00858 }
00859 
00860 
00861 void Tensor::spectral_display(const char* comment,
00862                         double thres, int precis, ostream& ost) const {
00863 
00864     if (comment != 0x0) {
00865         ost << comment << " : " << endl ; 
00866     }
00867     
00868     ost << "Lorene class : " << typeid(*this).name() 
00869         << "           Valence : " << valence << '\n' ;
00870 
00871     for (int ic=0; ic<n_comp; ic++) {
00872     
00873         if (valence == 0) {
00874         ost << 
00875         "===================== Scalar field ========================= \n" ;
00876     }
00877     else { 
00878             ost << "================ Component " ;
00879         Itbl num_indices = indices(ic) ;
00880         for (int j=0 ; j<valence ; j++) {
00881             ost << " " << num_indices(j) ;
00882             }
00883             ost << " ================ \n" ; 
00884     }
00885     ost << '\n' ; 
00886         
00887     cmp[ic]->spectral_display(0x0, thres, precis, ost) ; 
00888     ost << '\n' ;           
00889     }
00890 }
00891 
00892 
00893 void Tensor::sauve(FILE* fd) const {
00894     
00895     type_indice.sauve(fd) ; // type des composantes
00896     fwrite_be(&valence, sizeof(int), 1, fd) ;    // la valence
00897     
00898     if (valence != 0) {
00899         triad->sauve(fd) ;      // Vectorial basis
00900     }
00901     
00902     fwrite_be(&n_comp, sizeof(int), 1, fd) ; // nbre composantes
00903     for (int i=0 ; i<n_comp ; i++)
00904       cmp[i]->sauve(fd) ;
00905 
00906 }
00907 
00908 
00909 
00910 
00911 
00912 // Sets the standard spectal bases of decomposition for each component
00913 
00914 void Tensor::std_spectral_base() {
00915 
00916     switch (valence) {
00917 
00918         case 0 : {
00919             cmp[0]->std_spectral_base() ; 
00920             break ; 
00921         }   
00922         
00923         case 1 : {
00924             cout << 
00925             "Tensor::std_spectral_base: should not be called on a Tensor"
00926             << " of valence 1 but on a Vector !" << endl ;  
00927             abort() ; 
00928             break ; 
00929         }
00930     
00931         case 2 : {
00932         
00933             Base_val** bases = 0x0 ; 
00934             if( triad->identify() == (mp->get_bvect_cart()).identify() ) {
00935                 bases = mp->get_mg()->std_base_vect_cart() ;
00936             }
00937             else {
00938                 assert( triad->identify() == (mp->get_bvect_spher()).identify()) ;
00939                 bases = mp->get_mg()->std_base_vect_spher() ;
00940             }
00941 
00942             Itbl ind(2) ;
00943             for (int i=0 ; i<n_comp ; i++) {   
00944                 ind = indices(i) ;
00945                 cmp[i]->set_spectral_base( (*bases[ind(0)-1]) * 
00946                      (*bases[ind(1)-1]) ) ;
00947             }
00948         
00949             for (int i=0 ; i<3 ; i++) {
00950                 delete bases[i] ;
00951             }
00952             delete [] bases ;
00953             break ; 
00954 
00955         }
00956         
00957        
00958         default : {
00959 
00960             cout << "Tensor::std_spectral_base: the case valence = " << valence
00961             << " is not treated yet !" << endl ;
00962             abort() ;
00963             break ;
00964         }
00965     }
00966 }
00967 
00968 // Sets the standard spectal bases of decomposition for each component (odd in the nucleus)
00969 
00970 void Tensor::std_spectral_base_odd() {
00971 
00972     switch (valence) {
00973 
00974         case 0 : {
00975             cmp[0]->std_spectral_base_odd() ; 
00976             break ; 
00977         }   
00978         
00979         default : {
00980 
00981             cout << "Tensor::std_spectral_base_odd: the case valence = " << valence
00982             << " is not treated yet !" << endl ;
00983             abort() ;
00984             break ;
00985         }
00986     }
00987 }
00988 
00989 
00990 const Tensor& Tensor::derive_cov(const Metric& metre) const {
00991   
00992   set_dependance(metre) ;
00993   int j = get_place_met(metre) ;
00994   assert ((j>=0) && (j<N_MET_MAX)) ;
00995   if (p_derive_cov[j] == 0x0) {
00996     p_derive_cov[j] = metre.connect().p_derive_cov(*this) ;
00997   }
00998   return *p_derive_cov[j] ;
00999 }
01000 
01001 
01002 const Tensor& Tensor::derive_con(const Metric& metre) const {
01003   
01004     set_dependance(metre) ;
01005     int j = get_place_met(metre) ;
01006     assert ((j>=0) && (j<N_MET_MAX)) ;
01007     if (p_derive_con[j] == 0x0) {
01008     
01009     if (valence == 0) {
01010         p_derive_con[j] = 
01011             new Vector( contract(derive_cov(metre), 0, metre.con(), 0) ) ;
01012     }
01013     else {
01014         const Tensor_sym* tsym = dynamic_cast<const Tensor_sym*>(this) ; 
01015 
01016         if (tsym != 0x0) { // symmetric case, preserved by derive_con
01017             const Tensor& dercov = derive_cov(metre) ; 
01018             Itbl type_ind = dercov.get_index_type() ;
01019             type_ind.set(valence) = CON ; 
01020             p_derive_con[j] = new Tensor_sym(*mp, valence+1, type_ind, *triad,
01021                                        tsym->sym_index1(), tsym->sym_index2()) ; 
01022  
01023             *(p_derive_con[j]) = contract(dercov, valence, metre.con(), 0) ;
01024                         // valence is the number of the last index of derive_cov 
01025                         //  (the "derivation" index)
01026         }
01027         else {  // general case, no symmetry
01028         
01029             p_derive_con[j] =  new Tensor( contract(derive_cov(metre), valence,
01030                                                     metre.con(), 0) ) ;
01031                     // valence is the number of the last index of derive_cov 
01032                     //  (the "derivation" index)
01033         }
01034         
01035     }
01036 
01037     }
01038   
01039     return *p_derive_con[j] ;
01040 
01041 }
01042 
01043 const Tensor& Tensor::divergence(const Metric& metre) const {
01044   
01045   set_dependance(metre) ;
01046   int j = get_place_met(metre) ;
01047   assert ((j>=0) && (j<N_MET_MAX)) ;
01048   if (p_divergence[j] == 0x0) {
01049     p_divergence[j] = metre.connect().p_divergence(*this) ;
01050   }
01051   return *p_divergence[j] ;
01052 }
01053 
01054 void Tensor::exponential_filter_r(int lzmin, int lzmax, int p, 
01055               double alpha) {
01056     if( triad->identify() == (mp->get_bvect_cart()).identify() ) 
01057     for (int i=0; i<n_comp; i++)
01058         cmp[i]->exponential_filter_r(lzmin, lzmax, p, alpha) ;
01059     else {
01060     cout << "Tensor::exponential_filter_r : " << endl ;
01061     cout << "Only Cartesian triad is implemented!" << endl ;
01062     cout << "Exiting..." << endl ;
01063     abort() ;
01064     }
01065 }
01066 
01067 void Tensor::exponential_filter_ylm(int lzmin, int lzmax, int p, 
01068               double alpha) {
01069     if( triad->identify() == (mp->get_bvect_cart()).identify() ) 
01070     for (int i=0; i<n_comp; i++)
01071         cmp[i]->exponential_filter_ylm(lzmin, lzmax, p, alpha) ;
01072     else {
01073     cout << "Tensor::exponential_filter_ylm : " << endl ;
01074     cout << "Only Cartesian triad is implemented!" << endl ;
01075     cout << "Exiting..." << endl ;
01076     abort() ;
01077     }
01078 }
01079 
01080 
01081 
01082 
01083 
01084 
01085 
01086 
01087 
01088 
01089 
01090 
01091 
01092 

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