tenseur.C

00001 /*
00002  *  Methods of class Tenseur
00003  *
00004  *   (see file tenseur.h for documentation)
00005  *
00006  */
00007 
00008 /*
00009  *   Copyright (c) 1999-2001 Philippe Grandclement
00010  *   Copyright (c) 2000-2001 Eric Gourgoulhon
00011  *   Copyright (c) 2002 Jerome Novak
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 tenseur_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tenseur/tenseur.C,v 1.13 2003/03/03 19:37:31 f_limousin Exp $" ;
00033 
00034 /*
00035  * $Id: tenseur.C,v 1.13 2003/03/03 19:37:31 f_limousin Exp $
00036  * $Log: tenseur.C,v $
00037  * Revision 1.13  2003/03/03 19:37:31  f_limousin
00038  * Suppression of many assert(verif()).
00039  *
00040  * Revision 1.12  2002/10/16 14:37:14  j_novak
00041  * Reorganization of #include instructions of standard C++, in order to
00042  * use experimental version 3 of gcc.
00043  *
00044  * Revision 1.11  2002/09/06 14:49:25  j_novak
00045  * Added method lie_derive for Tenseur and Tenseur_sym.
00046  * Corrected various errors for derive_cov and arithmetic.
00047  *
00048  * Revision 1.10  2002/08/30 13:21:38  j_novak
00049  * Corrected error in constructor
00050  *
00051  * Revision 1.9  2002/08/14 13:46:15  j_novak
00052  * Derived quantities of a Tenseur can now depend on several Metrique's
00053  *
00054  * Revision 1.8  2002/08/13 08:02:45  j_novak
00055  * Handling of spherical vector/tensor components added in the classes
00056  * Mg3d and Tenseur. Minor corrections for the class Metconf.
00057  *
00058  * Revision 1.7  2002/08/08 15:10:45  j_novak
00059  * The flag "plat" has been added to the class Metrique to show flat metrics.
00060  *
00061  * Revision 1.6  2002/08/07 16:14:11  j_novak
00062  * class Tenseur can now also handle tensor densities, this should be transparent to older codes
00063  *
00064  * Revision 1.5  2002/08/02 15:07:41  j_novak
00065  * Member function determinant has been added to the class Metrique.
00066  * A better handling of spectral bases is now implemented for the class Tenseur.
00067  *
00068  * Revision 1.4  2002/05/07 07:36:03  e_gourgoulhon
00069  * Compatibilty with xlC compiler on IBM SP2:
00070  *    suppressed the parentheses around argument of instruction new:
00071  *  e.g.   t = new (Tbl *[nzone])  -->   t = new Tbl*[nzone]
00072  *
00073  * Revision 1.3  2002/05/02 15:16:22  j_novak
00074  * Added functions for more general bi-fluid EOS
00075  *
00076  * Revision 1.2  2001/12/04 21:27:54  e_gourgoulhon
00077  *
00078  * All writing/reading to a binary file are now performed according to
00079  * the big endian convention, whatever the system is big endian or
00080  * small endian, thanks to the functions fwrite_be and fread_be
00081  *
00082  * Revision 1.1.1.1  2001/11/20 15:19:30  e_gourgoulhon
00083  * LORENE
00084  *
00085  * Revision 2.21  2001/10/10  13:54:40  eric
00086  * Modif Joachim: pow(3, *) --> pow(3., *)
00087  *
00088  * Revision 2.20  2000/12/20  09:50:08  eric
00089  * Correction erreur dans operator<< : la sortie doit etre flux et non cout !
00090  *
00091  * Revision 2.19  2000/10/12  13:11:23  eric
00092  * Methode set_std_base(): traitement du cas etat = ETATZERO (return).
00093  *
00094  * Revision 2.18  2000/09/13  12:11:40  eric
00095  * Ajout de la fonction allocate_all().
00096  *
00097  * Revision 2.17  2000/05/22  14:40:09  phil
00098  * ajout de inc_dzpuis et dec_dzpuis
00099  *
00100  * Revision 2.16  2000/03/22  09:18:57  eric
00101  * Traitement du cas ETATZERO dans dec2_dzpuis, inc2_dzpuis et mult_r_zec.
00102  *
00103  * Revision 2.15  2000/02/12  11:35:58  eric
00104  * Modif de la fonction set_std_base : appel de Valeur::set_base plutot
00105  * que l'affectation directe du membre Valeur::base.
00106  *
00107  * Revision 2.14  2000/02/10  18:30:47  eric
00108  * La fonction set_triad ne fait plus que l'affectation du membre triad.
00109  *
00110  * Revision 2.13  2000/02/10  16:11:07  eric
00111  * Ajout de la fonction change_triad.
00112  *
00113  * Revision 2.12  2000/02/09  19:32:39  eric
00114  * MODIF IMPORTANTE: la triade de decomposition est desormais passee en
00115  * argument des constructeurs.
00116  *
00117  * Revision 2.11  2000/01/24  13:02:39  eric
00118  * Traitement du cas triad = 0x0 dans la sauvegarde/lecture fichier
00119  * Constructeur par lecture de fichier: met_depend est desormais initialise
00120  *  a 0x0.
00121  *
00122  * Revision 2.10  2000/01/20  16:02:57  eric
00123  * Ajout des operator=(double ) et operator=(int ).
00124  *
00125  * Revision 2.9  2000/01/20  15:34:39  phil
00126  * changement traid dans fait_gradient()
00127  *
00128  * Revision 2.8  2000/01/14  14:07:26  eric
00129  * Ajout de la fonction annule.
00130  *
00131  * Revision 2.7  2000/01/13  14:10:53  eric
00132  * Ajout du constructeur par copie d'un Cmp (pour un scalaire)
00133  * ainsi que l'affectation a un Cmp.
00134  *
00135  * Revision 2.6  2000/01/13  13:46:38  eric
00136  * Ajout du membre p_gradient_spher et des fonctions fait_gradient_spher(),
00137  *  gradient_spher() pour le calcul du gradient d'un scalaire en
00138  *  coordonnees spheriques sur la triade spherique associee.
00139  *
00140  * Revision 2.5  2000/01/12  13:19:04  eric
00141  * Les operator::(...) renvoient desormais une reference const sur le c[...]
00142  * correspondant et non plus un Cmp copie de c[...].
00143  * (ceci grace a la nouvelle fonction Map::cmp_zero()).
00144  *
00145  * Revision 2.4  2000/01/11  11:13:59  eric
00146  * Changement de nom pour la base vectorielle : base --> triad
00147  *
00148  * Revision 2.3  2000/01/10  17:23:07  eric
00149  * Modif affichage.
00150  * Methode fait_derive_cov : ajout de
00151  *   assert( metre.gamma().get_base() == base )
00152  * Methode set_std_base : ajout de
00153  *    assert( *base == mp->get_bvect_cart() )
00154  *
00155  * Revision 2.2  2000/01/10  15:15:26  eric
00156  * Ajout du membre base (base vectorielle sur laquelle sont definies
00157  *   les composantes).
00158  *
00159  * Revision 2.1  1999/12/09  12:39:23  phil
00160  * changement prototypage des derivees
00161  *
00162  * Revision 2.0  1999/12/02  17:18:31  phil
00163  * *** empty log message ***
00164  *
00165  *
00166  * $Header: /cvsroot/Lorene/C++/Source/Tenseur/tenseur.C,v 1.13 2003/03/03 19:37:31 f_limousin Exp $
00167  *
00168  */
00169 
00170 // Headers C
00171 #include <stdlib.h>
00172 #include <assert.h>
00173 #include <math.h>
00174 
00175 // Headers Lorene
00176 #include "tenseur.h"
00177 #include "metrique.h"
00178 #include "utilitaires.h"
00179 
00180             //--------------//
00181             // Constructors //
00182             //--------------//
00183 // Consistency check for tensor densities
00184 //---------------------------------------
00185 bool Tenseur::verif() const {
00186   return ( (poids == 0.) || (metric != 0x0) ) ;
00187 }
00188 
00189 void Tenseur::new_der_met() {
00190     met_depend = new const Metrique*[N_MET_MAX] ;
00191     p_derive_cov = new Tenseur*[N_MET_MAX] ;
00192     p_derive_con = new Tenseur*[N_MET_MAX] ;
00193     p_carre_scal = new Tenseur*[N_MET_MAX] ;
00194     for (int i=0; i<N_MET_MAX; i++) {
00195       met_depend[i] = 0x0 ;
00196     }
00197     set_der_0x0() ;
00198 }
00199 
00200 // Constructor for a scalar field
00201 // ------------------------------
00202 Tenseur::Tenseur (const Map& map, const Metrique* met, double weight) : 
00203         mp(&map), valence(0), triad(0x0),
00204         type_indice(0), n_comp(1), etat(ETATNONDEF), poids(weight),
00205         metric(met) {
00206     
00207   //    assert(verif()) ;
00208     c = new Cmp*[n_comp] ;
00209     c[0] = 0x0 ;
00210     new_der_met() ;
00211 }
00212 
00213 
00214 
00215 // Constructor for a scalar field and from a {\tt Cmp} 
00216 // ---------------------------------------------------
00217 Tenseur::Tenseur (const Cmp& ci, const Metrique* met, double weight) : 
00218         mp(ci.get_mp()), valence(0), triad(0x0),
00219         type_indice(0), n_comp(1), etat(ci.get_etat()), poids(weight),
00220         metric(met){
00221     
00222     assert(ci.get_etat() != ETATNONDEF) ; 
00223     assert(verif()) ;
00224     
00225     c = new Cmp*[n_comp] ;
00226 
00227     if ( ci.get_etat() != ETATZERO ) {
00228       assert( ci.get_etat() == ETATQCQ ) ; 
00229       c[0] = new Cmp(ci) ;
00230     }
00231     else {
00232       c[0] = 0x0 ;
00233     }
00234     new_der_met() ;
00235 }
00236 
00237 // Standard constructor 
00238 // --------------------
00239 Tenseur::Tenseur(const Map& map, int val, const Itbl& tipe, 
00240          const Base_vect& triad_i, const Metrique* met, double weight) 
00241         : mp(&map), valence(val), triad(&triad_i), type_indice(tipe), 
00242            n_comp(int(pow(3., val))), etat(ETATNONDEF), poids(weight),
00243         metric(met){
00244         
00245     // Des verifs :
00246     assert (valence >= 0) ;
00247     assert (tipe.get_ndim() == 1) ;
00248     assert (valence == tipe.get_dim(0)) ;
00249     for (int i=0 ; i<valence ; i++)
00250     assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
00251     assert(verif()) ;
00252     
00253     c = new Cmp*[n_comp] ;
00254     for (int i=0 ; i<n_comp ; i++)
00255     c[i] = 0x0 ;
00256     new_der_met() ;
00257 }
00258 
00259 // Standard constructor with the triad passed as a pointer
00260 // -------------------------------------------------------
00261 Tenseur::Tenseur(const Map& map, int val, const Itbl& tipe, 
00262          const Base_vect* triad_i, const Metrique* met, double weight) 
00263         : mp(&map), valence(val), triad(triad_i), type_indice(tipe), 
00264            n_comp(int(pow(3., val))), etat(ETATNONDEF), poids(weight),
00265         metric(met){
00266         
00267     // Des verifs :
00268     assert (valence >= 0) ;
00269     assert (tipe.get_ndim() == 1) ;
00270     assert (valence == tipe.get_dim(0)) ;
00271     for (int i=0 ; i<valence ; i++)
00272     assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
00273     //   assert(verif()) ;
00274     
00275     if (valence == 0) {     // particular case of a scalar 
00276     triad = 0x0 ; 
00277     }   
00278     
00279     c = new Cmp*[n_comp] ;
00280     for (int i=0 ; i<n_comp ; i++)
00281     c[i] = 0x0 ;
00282     new_der_met() ;
00283 }
00284 
00285 
00286 
00287 
00288 // Standard constructor when all the indices are of the same type
00289 // --------------------------------------------------------------
00290 Tenseur::Tenseur(const Map& map, int val, int tipe, const Base_vect& triad_i,
00291          const Metrique* met, double weight) 
00292         : mp(&map), valence(val), triad(&triad_i), type_indice(val), 
00293                   n_comp(int(pow(3., val))), etat (ETATNONDEF), poids(weight), 
00294           metric(met){
00295     
00296     // Des verifs :
00297     assert (valence >= 0) ;
00298     assert ((tipe == COV) || (tipe == CON)) ;
00299     assert(verif()) ;
00300     type_indice.set_etat_qcq() ;
00301     type_indice = tipe ;
00302     
00303     c = new Cmp*[n_comp] ;
00304     for (int i=0 ; i<n_comp ; i++)
00305     c[i] = 0x0 ;
00306     new_der_met() ;
00307 }   
00308     
00309 // Copy constructor
00310 // ----------------
00311 Tenseur::Tenseur (const Tenseur& source) : 
00312     mp(source.mp), valence(source.valence), triad(source.triad), 
00313     type_indice(source.type_indice), etat (source.etat), poids(source.poids),
00314     metric(source.metric) {
00315   
00316   //   assert(verif()) ;
00317     
00318     n_comp = int(pow(3., valence)) ;
00319         
00320     c = new Cmp*[n_comp] ;
00321     for (int i=0 ; i<n_comp ; i++) {
00322     int place_source = source.donne_place(donne_indices(i)) ;
00323     if (source.c[place_source] == 0x0)
00324         c[i] = 0x0 ;
00325     else
00326         c[i] = new Cmp(*source.c[place_source]) ;
00327     }
00328 
00329     assert(source.met_depend != 0x0) ;
00330     assert(source.p_derive_cov != 0x0) ;
00331     assert(source.p_derive_con != 0x0) ;
00332     assert(source.p_carre_scal != 0x0) ;
00333     new_der_met() ;
00334     
00335     if (source.p_gradient != 0x0)
00336         p_gradient = new Tenseur (*source.p_gradient) ;
00337     
00338     if (source.p_gradient_spher != 0x0)
00339         p_gradient_spher = new Tenseur (*source.p_gradient_spher) ;
00340 
00341     for (int i=0; i<N_MET_MAX; i++) {
00342       met_depend[i] = source.met_depend[i] ;
00343       if (met_depend[i] != 0x0) {
00344     
00345     set_dependance (*met_depend[i]) ;
00346     
00347     if (source.p_derive_cov[i] != 0x0)
00348       p_derive_cov[i] = new Tenseur (*source.p_derive_cov[i]) ;
00349     if (source.p_derive_con[i] != 0x0)
00350       p_derive_con[i] = new Tenseur (*source.p_derive_con[i]) ;
00351     if (source.p_carre_scal[i] != 0x0)
00352         p_carre_scal[i] = new Tenseur (*source.p_carre_scal[i]) ;
00353       }
00354     }
00355 }   
00356 
00357 // Constructor from a symmetric tensor
00358 // -----------------------------------
00359 Tenseur::Tenseur (const Tenseur_sym& source) :
00360     mp(source.mp), valence(source.valence), triad(source.triad), 
00361     type_indice(source.type_indice), etat(source.etat), 
00362     poids(source.poids), metric(source.metric) {
00363     
00364     assert(verif()) ;
00365     n_comp = int(pow(3., valence)) ;
00366         
00367     c = new Cmp*[n_comp] ;
00368     for (int i=0 ; i<n_comp ; i++) {
00369     int place_source = source.donne_place(donne_indices(i)) ;
00370     if (source.c[place_source] == 0x0)
00371         c[i] = 0x0 ;
00372     else
00373         c[i] = new Cmp(*source.c[place_source]) ;
00374     }
00375 
00376     assert(source.met_depend != 0x0) ;
00377     assert(source.p_derive_cov != 0x0) ;
00378     assert(source.p_derive_con != 0x0) ;
00379     assert(source.p_carre_scal != 0x0) ;
00380     new_der_met() ;
00381     
00382     if (source.p_gradient != 0x0)
00383     p_gradient = new Tenseur_sym (*source.p_gradient) ;
00384 
00385     for (int i=0; i<N_MET_MAX; i++) {
00386       met_depend[i] = source.met_depend[i] ;
00387       if (met_depend[i] != 0x0) {
00388     
00389     set_dependance (*met_depend[i]) ;
00390     
00391     if (source.p_derive_cov[i] != 0x0)
00392       p_derive_cov[i] = new Tenseur (*source.p_derive_cov[i]) ;
00393     if (source.p_derive_con[i] != 0x0)
00394       p_derive_con[i] = new Tenseur (*source.p_derive_con[i]) ;
00395     if (source.p_carre_scal[i] != 0x0)
00396         p_carre_scal[i] = new Tenseur (*source.p_carre_scal[i]) ;
00397       }
00398     }
00399     
00400 }
00401 
00402 // Constructor from a file
00403 // -----------------------
00404 Tenseur::Tenseur(const Map& mapping, const Base_vect& triad_i, FILE* fd, 
00405          const Metrique* met)
00406          : mp(&mapping), triad(&triad_i), type_indice(fd), 
00407                    metric(met) {
00408    
00409     fread_be(&valence, sizeof(int), 1, fd) ;
00410 
00411     if (valence != 0) {
00412     Base_vect* triad_fich = Base_vect::bvect_from_file(fd) ; 
00413     assert( *triad_fich == *triad) ; 
00414     delete triad_fich ; 
00415     }
00416     else{
00417     triad = 0x0 ; 
00418     }
00419     
00420     fread_be(&n_comp, sizeof(int), 1, fd) ;
00421     fread_be(&etat, sizeof(int), 1, fd) ;
00422     
00423     c = new Cmp*[n_comp] ;
00424     for (int i=0 ; i<n_comp ; i++)
00425     c[i] = 0x0 ;
00426     if (etat == ETATQCQ)
00427     for (int i=0 ; i<n_comp ; i++)
00428         c[i] = new Cmp(*mp, *mp->get_mg(), fd) ;
00429 
00430     new_der_met() ;
00431     
00432     if (met == 0x0) 
00433       poids = 0. ;
00434     else
00435       fread_be(&poids, sizeof(double), 1, fd) ;
00436 }
00437 
00438 
00439 // Constructor from a file for a scalar field
00440 // ------------------------------------------
00441 Tenseur::Tenseur (const Map& mapping, FILE* fd, const Metrique* met) 
00442          : mp(&mapping), type_indice(fd), metric(met){
00443    
00444     fread_be(&valence, sizeof(int), 1, fd) ;
00445 
00446     assert(valence == 0) ; 
00447     
00448     triad = 0x0 ; 
00449     
00450     fread_be(&n_comp, sizeof(int), 1, fd) ;
00451     
00452     assert(n_comp == 1) ; 
00453 
00454     fread_be(&etat, sizeof(int), 1, fd) ;
00455     
00456     c = new Cmp*[n_comp] ;
00457 
00458     if (etat == ETATQCQ) {
00459     c[0] = new Cmp(*mp, *mp->get_mg(), fd) ;
00460     }
00461     else{
00462     c[0] = 0x0 ; 
00463     }
00464     
00465     new_der_met() ;
00466 
00467     if (met == 0x0) 
00468       poids = 0. ;
00469     else
00470       fread_be(&poids, sizeof(double), 1, fd) ;
00471 }
00472 
00473 
00474 
00475 
00476 // Constructor used by the derived classes
00477 // ---------------------------------------
00478 Tenseur::Tenseur (const Map& map, int val, const Itbl& tipe, int compo, 
00479         const Base_vect& triad_i, const Metrique* met, double weight) :
00480      mp(&map), valence(val), triad(&triad_i), type_indice(tipe), n_comp(compo), 
00481         etat (ETATNONDEF), poids(weight), metric(met) {
00482      
00483     // Des verifs :
00484     assert (valence >= 0) ;
00485     assert (tipe.get_ndim() == 1) ;
00486     assert (n_comp > 0) ;   
00487     assert (valence == tipe.get_dim(0)) ;
00488     for (int i=0 ; i<valence ; i++)
00489     assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
00490     //assert(verif()) ;
00491     
00492     c = new Cmp*[n_comp] ;
00493     for (int i=0 ; i<n_comp ; i++)
00494     c[i] = 0x0 ;
00495     
00496     new_der_met() ;
00497 }
00498 
00499 // Constructor used by the derived classes when all the indices are of 
00500 // the same type.
00501 // -------------------------------------------------------------------
00502 Tenseur::Tenseur (const Map& map, int val, int tipe, int compo, 
00503         const Base_vect& triad_i, const Metrique* met, double weight) :
00504      mp(&map), valence(val), triad(&triad_i), type_indice(val), n_comp(compo), 
00505         etat (ETATNONDEF), poids(weight), metric(met) {
00506     // Des verifs :
00507     assert (valence >= 0) ;
00508     assert (n_comp >= 0) ;
00509     assert ((tipe == COV) || (tipe == CON)) ;
00510     //assert(verif()) ;
00511     type_indice.set_etat_qcq() ;
00512     type_indice = tipe ;
00513     
00514     c = new Cmp*[n_comp] ;
00515     for (int i=0 ; i<n_comp ; i++)
00516     c[i] = 0x0 ;
00517 
00518     new_der_met() ;
00519 }
00520 
00521             //--------------//
00522             //  Destructor  //
00523             //--------------//
00524 
00525 
00526 Tenseur::~Tenseur () {
00527     
00528     del_t() ;
00529     delete [] met_depend ;
00530     delete [] p_derive_cov ;
00531     delete [] p_derive_con ;
00532     delete [] p_carre_scal ;
00533     delete [] c ;
00534 }
00535 
00536 
00537 
00538 void Tenseur::del_t() {
00539     del_derive() ;
00540     for (int i=0 ; i<n_comp ; i++)
00541     if (c[i] != 0x0) {
00542         delete c[i] ;
00543         c[i] = 0x0 ;
00544         }
00545 }
00546 
00547 void Tenseur::del_derive_met(int j) const {
00548 
00549   assert( (j>=0) && (j<N_MET_MAX) ) ;
00550   // On gere la metrique ...
00551   if (met_depend[j] != 0x0) {
00552     for (int i=0 ; i<N_DEPEND ; i++)
00553       if (met_depend[j]->dependances[i] == this)
00554     met_depend[j]->dependances[i] = 0x0 ;
00555     if (p_derive_cov[j] != 0x0)
00556       delete p_derive_cov[j] ;
00557     if (p_derive_con[j] != 0x0)
00558       delete p_derive_con[j] ;
00559     if (p_carre_scal[j] != 0x0)
00560       delete p_carre_scal[j] ;
00561     set_der_met_0x0(j) ;
00562   }
00563 }
00564 
00565 
00566 void Tenseur::del_derive () const {
00567   for (int i=0; i<N_MET_MAX; i++) 
00568     del_derive_met(i) ;
00569   if (p_gradient != 0x0)
00570     delete p_gradient ;
00571   if (p_gradient_spher != 0x0)
00572     delete p_gradient_spher ;
00573   set_der_0x0() ;
00574 }
00575 
00576 void Tenseur::set_der_met_0x0(int i) const {
00577   met_depend[i] = 0x0 ;
00578     p_derive_cov[i] = 0x0 ;
00579     p_derive_con[i] = 0x0 ;
00580     p_carre_scal[i] = 0x0 ;
00581 }
00582 
00583 
00584 void Tenseur::set_der_0x0() const {
00585   for (int i=0; i<N_MET_MAX; i++) 
00586     set_der_met_0x0(i) ;
00587   p_gradient = 0x0 ;   
00588   p_gradient_spher = 0x0 ;   
00589 }
00590 
00591 int Tenseur::get_place_met(const Metrique& metre) const {
00592   int resu = -1 ;
00593   for (int i=0; i<N_MET_MAX; i++) 
00594     if (met_depend[i] == &metre) {
00595       assert(resu == -1) ;
00596       resu = i ;
00597     }
00598   return resu ;
00599 }
00600 
00601 void Tenseur::set_dependance (const Metrique& met) const {
00602     
00603   int nmet = 0 ;
00604   bool deja = false ;
00605   for (int i=0; i<N_MET_MAX; i++) {
00606     if (met_depend[i] == &met) deja = true ;
00607     if ((!deja) && (met_depend[i] != 0x0)) nmet++ ;
00608   }
00609   if (nmet == N_MET_MAX) {
00610     cout << "Too many metrics in Tenseur::set_dependances" << endl ;
00611     abort() ;
00612   }
00613   if (!deja) { 
00614     int conte = 0 ;
00615     while ((conte < N_DEPEND) && (met.dependances[conte] != 0x0))
00616       conte ++ ;
00617     
00618     if (conte == N_DEPEND) {
00619       cout << "Too many dependancies in Tenseur::set_dependances " << endl ;
00620       abort() ;
00621     }
00622     else {
00623       met.dependances[conte] = this ;
00624       met_depend[nmet] = &met ;
00625     }
00626   }
00627 }
00628 
00629 void Tenseur::set_etat_qcq() { 
00630     
00631     del_derive() ;
00632     for (int i=0 ; i<n_comp ; i++)
00633     if (c[i] == 0x0)
00634         c[i] = new Cmp(mp) ;
00635     etat = ETATQCQ ;
00636 }
00637 
00638 void Tenseur::set_etat_zero() { 
00639     del_t() ;
00640     etat = ETATZERO ;
00641 }
00642 
00643 void Tenseur::set_etat_nondef() { 
00644     del_t() ;
00645     etat = ETATNONDEF ;
00646 }
00647 
00648 // Allocates everything
00649 // --------------------
00650 void Tenseur::allocate_all() {
00651     
00652     set_etat_qcq() ; 
00653     for (int i=0 ; i<n_comp ; i++) {
00654         c[i]->allocate_all() ; 
00655     }
00656     
00657 } 
00658 
00659 
00660 
00661 void Tenseur::change_triad(const Base_vect& bi) {
00662     
00663     bi.change_basis(*this) ; 
00664     
00665 }
00666 
00667 void Tenseur::set_triad(const Base_vect& bi) {
00668     
00669     triad = &bi ; 
00670     
00671 }
00672 
00673 void Tenseur::set_poids(double weight) {
00674 
00675     poids = weight ;
00676 }
00677 
00678 void Tenseur::set_metric(const Metrique& met) {
00679 
00680     metric = &met ;
00681 }
00682 
00683 int Tenseur::donne_place (const Itbl& idx) const {
00684     
00685     assert (idx.get_ndim() == 1) ;
00686     assert (idx.get_dim(0) == valence) ;
00687     
00688     for (int i=0 ; i<valence ; i++)
00689     assert ((idx(i)>=0) && (idx(i)<3)) ;
00690     int res = 0 ;
00691     for (int i=0 ; i<valence ; i++)
00692         res = 3*res+idx(i) ;
00693     
00694     return res;
00695 }
00696 
00697 Itbl Tenseur::donne_indices (int place) const {
00698     
00699     assert ((place >= 0) && (place < n_comp)) ;
00700 
00701     Itbl res(valence) ;
00702     res.set_etat_qcq() ;
00703             
00704     for (int i=valence-1 ; i>=0 ; i--) {
00705     res.set(i) = div(place, 3).rem ;
00706     place = int((place-res(i))/3) ;
00707     }
00708     return res ;
00709 }
00710 
00711 void Tenseur::operator=(const Tenseur& t) {
00712     
00713     assert (valence == t.valence) ;
00714 
00715     triad = t.triad ; 
00716     poids = t.poids ;
00717     metric = t.metric ;
00718 
00719     for (int i=0 ; i<valence ; i++)
00720     assert (t.type_indice(i) == type_indice(i)) ;
00721     
00722     switch (t.etat) {
00723     case ETATNONDEF: {
00724         set_etat_nondef() ;
00725         break ;
00726     }
00727     
00728     case ETATZERO: {
00729         set_etat_zero() ;
00730         break ;
00731     }
00732     
00733     case ETATQCQ: {
00734         set_etat_qcq() ;
00735         for (int i=0 ; i<n_comp ; i++) {
00736         int place_t = t.donne_place(donne_indices(i)) ;
00737         if (t.c[place_t] == 0x0)
00738             c[i] = 0x0 ;
00739         else 
00740             *c[i] = *t.c[place_t] ;
00741         }
00742         break ;
00743     }
00744     
00745     default: {
00746         cout << "Unknown state in Tenseur::operator= " << endl ;
00747         abort() ;
00748         break ;
00749         }
00750     }
00751 }
00752 
00753 
00754 void Tenseur::operator=(const Cmp& ci) {
00755     
00756     assert (valence == 0) ;
00757     poids = 0. ;
00758     metric = 0x0 ;
00759 
00760     switch (ci.get_etat()) {
00761     case ETATNONDEF: {
00762         set_etat_nondef() ;
00763         break ;
00764     }
00765     
00766     case ETATZERO: {
00767         set_etat_zero() ;
00768         break ;
00769     }
00770     
00771     case ETATQCQ: {
00772         set_etat_qcq() ;
00773         *(c[0]) = ci ; 
00774         break ;
00775     }
00776     
00777     default: {
00778         cout << "Unknown state in Tenseur::operator= " << endl ;
00779         abort() ;
00780         break ;
00781     }
00782     }
00783 }
00784 
00785 void Tenseur::operator=(double x) {
00786 
00787     poids = 0. ;
00788     metric = 0x0 ;
00789     if (x == double(0)) {
00790     set_etat_zero() ;
00791     }
00792     else {
00793     assert(valence == 0) ; 
00794     set_etat_qcq() ;
00795     *(c[0]) = x ; 
00796     }
00797 
00798 }
00799 
00800 void Tenseur::operator=(int x) {
00801 
00802     poids = 0. ;
00803     metric = 0x0 ;
00804     if (x == 0) {
00805     set_etat_zero() ;
00806     }
00807     else {
00808     assert(valence == 0) ; 
00809     set_etat_qcq() ;
00810     *(c[0]) = x ; 
00811     }
00812 
00813 }
00814 
00815 
00816 // Affectation d'un scalaire ...
00817 Cmp& Tenseur::set () {
00818     
00819     del_derive() ;
00820     assert(etat == ETATQCQ) ;
00821     assert (valence == 0) ;  
00822     return *c[0] ;
00823 }
00824 
00825 
00826 // Affectation d'un vecteur :
00827 Cmp& Tenseur::set (int ind) {
00828     
00829     del_derive() ;
00830     assert(valence == 1) ;
00831     assert (etat == ETATQCQ) ;
00832     assert ((ind >= 0) && (ind < 3)) ;
00833     
00834     return *c[ind] ;
00835 }
00836 
00837 // Affectation d'un tenseur d'ordre 2 :
00838 Cmp& Tenseur::set (int ind1, int ind2) {
00839     
00840     del_derive() ;
00841     assert (valence == 2) ;
00842     assert (etat == ETATQCQ) ;
00843     assert ((ind1 >= 0) && (ind1 < 3)) ;
00844     assert ((ind2 >= 0) && (ind2 < 3)) ;
00845     
00846     Itbl ind (valence) ;
00847     ind.set_etat_qcq() ;
00848     ind.set(0) = ind1 ;
00849     ind.set(1) = ind2 ;
00850     
00851     int place = donne_place(ind) ;
00852     
00853     return *c[place] ;
00854 }
00855 
00856 // Affectation d'un tenseur d'ordre 3 :
00857 Cmp& Tenseur::set (int ind1, int ind2, int ind3) {
00858     
00859     del_derive() ;
00860     assert (valence == 3) ;
00861     assert (etat == ETATQCQ) ;
00862     assert ((ind1 >= 0) && (ind1 < 3)) ;
00863     assert ((ind2 >= 0) && (ind2 < 3)) ;
00864     assert ((ind3 >= 0) && (ind3 < 3)) ;
00865     
00866     Itbl indices(valence) ;
00867     indices.set_etat_qcq() ;
00868     indices.set(0) = ind1 ;
00869     indices.set(1) = ind2 ;
00870     indices.set(2) = ind3 ;
00871     int place = donne_place(indices) ;
00872  
00873     return *c[place] ;
00874 }
00875 
00876 // Affectation cas general
00877 Cmp& Tenseur::set(const Itbl& indices) {
00878     
00879     assert (indices.get_ndim() == 1) ;
00880     assert (indices.get_dim(0) == valence) ;
00881     
00882     del_derive() ;
00883     assert (etat == ETATQCQ) ;
00884     for (int i=0 ; i<valence ; i++)
00885     assert ((indices(i)>=0) && (indices(i)<3)) ;
00886     
00887     int place = donne_place(indices) ;
00888     
00889     return *c[place] ;
00890 }
00891 
00892 // Annulation dans des domaines
00893 void Tenseur::annule(int l) {
00894     
00895     annule(l, l) ;     
00896 }
00897 
00898 void Tenseur::annule(int l_min, int l_max) {
00899     
00900     // Cas particulier: annulation globale : 
00901     if ( (l_min == 0) && (l_max == mp->get_mg()->get_nzone()-1) ) {
00902     set_etat_zero() ;
00903     return ; 
00904     }
00905     
00906     assert( etat != ETATNONDEF ) ; 
00907     
00908     if ( etat == ETATZERO ) {
00909     return ;        // rien n'a faire si c'est deja zero
00910     }
00911     else {
00912     assert( etat == ETATQCQ ) ; // sinon...
00913     
00914     // Annulation des composantes:
00915     for (int i=0 ; i<n_comp ; i++) {
00916         c[i]->annule(l_min, l_max) ; 
00917     }
00918     
00919     // Annulation des membres derives
00920     if (p_gradient != 0x0) p_gradient->annule(l_min, l_max) ;
00921     if (p_gradient_spher != 0x0) p_gradient_spher->annule(l_min, l_max) ;
00922     for (int j=0; j<N_MET_MAX; j++) {
00923       if (p_derive_cov[j] != 0x0) p_derive_cov[j]->annule(l_min, l_max) ;
00924       if (p_derive_con[j] != 0x0) p_derive_con[j]->annule(l_min, l_max) ;
00925       if (p_carre_scal[j] != 0x0) p_carre_scal[j]->annule(l_min, l_max) ;
00926     }
00927 
00928     }
00929     
00930 }
00931 
00932 
00933 
00934 
00935 // Exctraction :
00936 const Cmp& Tenseur::operator()() const {
00937     
00938     assert(valence == 0) ;
00939     
00940     if (etat == ETATQCQ) return *c[0] ;     // pour la performance,
00941                         // ce cas est traite en premier,
00942                         // en dehors du switch
00943     switch (etat) {
00944     
00945     case ETATNONDEF : {
00946         cout << "Undefined Tensor in Tenseur::operator() ..." << endl ;
00947         abort() ;
00948         return *c[0] ;  // bidon pour satisfaire le compilateur
00949         }
00950         
00951     case ETATZERO : {
00952         return mp->cmp_zero() ;
00953         }
00954         
00955         
00956     default : {
00957         cout <<"Unknown state in Tenseur::operator()" << endl ;
00958         abort() ;
00959         return *c[0] ;  // bidon pour satisfaire le compilateur
00960         }
00961     }
00962 }
00963 
00964 
00965 const Cmp& Tenseur::operator() (int indice) const {
00966     
00967     assert ((indice>=0) && (indice<3)) ;
00968     assert(valence == 1) ;
00969     
00970     if (etat == ETATQCQ) return *c[indice] ;     // pour la performance,
00971                         // ce cas est traite en premier,
00972                         // en dehors du switch
00973     switch (etat) {
00974     
00975     case ETATNONDEF : {
00976         cout << "Undefined Tensor in Tenseur::operator(int) ..." << endl ;
00977         abort() ;
00978         return *c[0] ;  // bidon pour satisfaire le compilateur
00979         }
00980         
00981     case ETATZERO : {
00982         return mp->cmp_zero() ;
00983         }
00984                 
00985     default : {
00986         cout <<"Unknown state in Tenseur::operator(int)" << endl ;
00987         abort() ;
00988         return *c[0] ;  // bidon pour satisfaire le compilateur
00989         }
00990     }
00991 }
00992 
00993 const Cmp& Tenseur::operator() (int indice1, int indice2) const {
00994     
00995     assert ((indice1>=0) && (indice1<3)) ;
00996     assert ((indice2>=0) && (indice2<3)) ;
00997     assert(valence == 2) ;
00998     
00999     if (etat == ETATQCQ) {      // pour la performance,
01000         Itbl idx(2) ;       // ce cas est traite en premier,
01001         idx.set_etat_qcq() ;    // en dehors du switch
01002         idx.set(0) = indice1 ;
01003         idx.set(1) = indice2 ;
01004         return *c[donne_place(idx)] ;   
01005     }
01006 
01007     switch (etat) {
01008     
01009     case ETATNONDEF : {
01010         cout << "Undefined Tensor in Tenseur::operator(int, int) ..." << endl ;
01011         abort() ;
01012         return *c[0] ;  // bidon pour satisfaire le compilateur
01013         }
01014         
01015     case ETATZERO : {
01016         return mp->cmp_zero() ;
01017         }
01018             
01019     default : {
01020         cout <<"Unknown state in Tenseur::operator(int, int)" << endl ;
01021         abort() ;
01022         return *c[0] ;  // bidon pour satisfaire le compilateur
01023         }
01024     } 
01025 }
01026 
01027 const Cmp& Tenseur::operator() (int indice1, int indice2, int indice3) const {
01028     
01029     assert ((indice1>=0) && (indice1<3)) ;
01030     assert ((indice2>=0) && (indice2<3)) ;
01031     assert ((indice3>=0) && (indice3<3)) ;
01032     assert(valence == 3) ;
01033     
01034     if (etat == ETATQCQ) {      // pour la performance,
01035         Itbl idx(3) ;       // ce cas est traite en premier,
01036         idx.set_etat_qcq() ;    // en dehors du switch
01037         idx.set(0) = indice1 ;
01038         idx.set(1) = indice2 ;
01039         idx.set(2) = indice3 ;
01040         return *c[donne_place(idx)] ;
01041     }
01042 
01043     switch (etat) {
01044     
01045     case ETATNONDEF : {
01046         cout << "Undefined Tensor in Tenseur::operator(int, int, int) ..." << endl ;
01047         abort() ;
01048         return *c[0] ;  // bidon pour satisfaire le compilateur
01049         }
01050         
01051     case ETATZERO : {
01052         return mp->cmp_zero() ;
01053         }
01054                 
01055     default : {
01056         cout <<"Unknown state in Tenseur::operator(int, int, int)" << endl ;
01057         abort() ;
01058         return *c[0] ;  // bidon pour satisfaire le compilateur
01059         }
01060     }
01061 }
01062 
01063 
01064 const Cmp& Tenseur::operator() (const Itbl& indices) const {
01065     
01066     assert (indices.get_ndim() == 1) ;
01067     assert (indices.get_dim(0) == valence) ;
01068     for (int i=0 ; i<valence ; i++)
01069     assert ((indices(i)>=0) && (indices(i)<3)) ;
01070     
01071     if (etat == ETATQCQ) {          // pour la performance,
01072     return *c[donne_place(indices)] ;   // ce cas est traite en premier,
01073     }                       // en dehors du switch
01074 
01075     switch (etat) {
01076     
01077     case ETATNONDEF : {
01078         cout << "Undefined Tensor in Tenseur::operator(const Itbl&) ..." << endl ;
01079         abort() ;
01080         return *c[0] ;  // bidon pour satisfaire le compilateur
01081         }
01082         
01083     case ETATZERO : {
01084         return mp->cmp_zero() ;
01085         }
01086         
01087     default : {
01088         cout <<"Unknown state in Tenseur::operator(const Itbl& )" << endl ;
01089         abort() ;
01090         return *c[0] ;  // bidon pour satisfaire le compilateur
01091         }
01092     }
01093     
01094 }
01095 
01096 // Gestion de la ZEC :
01097 void Tenseur::dec_dzpuis() {
01098     
01099     if (etat == ETATZERO) {
01100     return ; 
01101     }
01102     
01103     assert(etat == ETATQCQ) ;
01104    
01105     for (int i=0 ; i<n_comp ; i++)
01106     if (c[i] != 0x0)
01107         c[i]->dec_dzpuis() ;
01108 }
01109 
01110 void Tenseur::inc_dzpuis() {
01111     
01112     if (etat == ETATZERO) {
01113     return ; 
01114     }
01115 
01116     assert(etat == ETATQCQ) ;
01117     
01118     for (int i=0 ; i<n_comp ; i++)
01119     if (c[i] != 0x0)
01120         c[i]->inc_dzpuis() ;
01121 }
01122 
01123 void Tenseur::dec2_dzpuis() {
01124     
01125     if (etat == ETATZERO) {
01126     return ; 
01127     }
01128     
01129     assert(etat == ETATQCQ) ;
01130    
01131     for (int i=0 ; i<n_comp ; i++)
01132     if (c[i] != 0x0)
01133         c[i]->dec2_dzpuis() ;
01134 }
01135 
01136 void Tenseur::inc2_dzpuis() {
01137     
01138     if (etat == ETATZERO) {
01139     return ; 
01140     }
01141 
01142     assert(etat == ETATQCQ) ;
01143     
01144     for (int i=0 ; i<n_comp ; i++)
01145     if (c[i] != 0x0)
01146         c[i]->inc2_dzpuis() ;
01147 }
01148 
01149 void Tenseur::mult_r_zec() {
01150     
01151     if (etat == ETATZERO) {
01152     return ; 
01153     }
01154 
01155     assert(etat == ETATQCQ) ;
01156     
01157     for (int i=0 ; i<n_comp ; i++) 
01158         if (c[i] != 0x0)
01159         c[i]->mult_r_zec() ;
01160 }
01161 
01162 // Gestion des bases spectrales (valence <= 2)
01163 void Tenseur::set_std_base() {
01164     
01165     if (etat == ETATZERO) {
01166     return ; 
01167     }
01168     
01169     assert(etat == ETATQCQ) ;
01170     switch (valence) {
01171     
01172     case 0 : {
01173         c[0]->std_base_scal() ;
01174         break ;
01175     }
01176         
01177     case 1 : {
01178 
01179       if ( triad->identify() == (mp->get_bvect_cart()).identify() ) {
01180 
01181         Base_val** bases = mp->get_mg()->std_base_vect_cart() ;
01182 
01183         for (int i=0 ; i<3 ; i++)
01184         (c[i]->va).set_base( *bases[i] ) ;
01185         for (int i=0 ; i<3 ; i++)
01186         delete bases[i] ;
01187         delete [] bases ;
01188       }
01189       else {
01190         assert( triad->identify() == (mp->get_bvect_spher()).identify()) ;
01191         Base_val** bases = mp->get_mg()->std_base_vect_spher() ;
01192 
01193         for (int i=0 ; i<3 ; i++)
01194         (c[i]->va).set_base( *bases[i] ) ;
01195         for (int i=0 ; i<3 ; i++)
01196         delete bases[i] ;
01197         delete [] bases ;
01198       }
01199       break ;
01200         
01201     }
01202         
01203     case 2 : {
01204 
01205       if( triad->identify() == (mp->get_bvect_cart()).identify() ) {
01206 
01207         Base_val** bases = mp->get_mg()->std_base_vect_cart() ;
01208         
01209         Itbl indices (2) ;
01210         indices.set_etat_qcq() ;
01211         for (int i=0 ; i<n_comp ; i++) {   
01212         indices = donne_indices(i) ;
01213         (c[i]->va).set_base( (*bases[indices(0)]) * 
01214                      (*bases[indices(1)]) ) ;
01215         }
01216         for (int i=0 ; i<3 ; i++)
01217         delete bases[i] ;
01218         delete [] bases ;
01219       }
01220       else {
01221         assert( triad->identify() == (mp->get_bvect_spher()).identify()) ;
01222         Base_val** bases = mp->get_mg()->std_base_vect_spher() ;
01223         
01224         Itbl indices (2) ;
01225         indices.set_etat_qcq() ;
01226         for (int i=0 ; i<n_comp ; i++) {   
01227         indices = donne_indices(i) ;
01228         (c[i]->va).set_base( (*bases[indices(0)]) * 
01229                      (*bases[indices(1)]) ) ;
01230         }
01231         for (int i=0 ; i<3 ; i++)
01232         delete bases[i] ;
01233         delete [] bases ;
01234       }
01235       break ;
01236     }
01237        
01238         default : {
01239         cout << 
01240         "Tenseur::set_std_base() : the case valence = " << valence
01241          << " is not treated !" << endl ;
01242         abort() ;
01243         break ;
01244         }
01245     }
01246 }
01247 
01248  // Le cout :
01249 ostream& operator<<(ostream& flux, const Tenseur &source ) {
01250     
01251     flux << "Valence : " << source.valence << endl ;
01252     if (source.get_poids() != 0.) 
01253       flux << "Tensor density of weight " << source.poids << endl ;
01254 
01255     if (source.get_triad() != 0x0) {
01256     flux << "Vectorial basis (triad) on which the components are defined :" 
01257          << endl ; 
01258     flux << *(source.get_triad()) << endl ;
01259     }
01260     
01261     if (source.valence != 0)
01262     flux << "Type of the indices : " << endl ;
01263     for (int i=0 ; i<source.valence ; i++) {
01264     flux << "Index " << i << " : " ;
01265     if (source.type_indice(i) == CON)
01266         flux << " contravariant." << endl ;
01267     else
01268         flux << " covariant." << endl ;
01269     }
01270     
01271     switch (source.etat) {
01272     
01273     case ETATZERO : {
01274         flux << "Null Tenseur. " << endl ;
01275         break ;
01276         }
01277     
01278     case ETATNONDEF : {
01279         flux << "Undefined Tenseur. " << endl ;
01280         break ;
01281         }
01282     
01283     case ETATQCQ : {
01284         for (int i=0 ; i<source.n_comp ; i++) {
01285 
01286         Itbl num_indices (source.donne_indices(i)) ;
01287         flux << "Component " ;
01288         
01289         if (source.valence != 0) {
01290         for (int j=0 ; j<source.valence ; j++)
01291             flux << "  " << num_indices(j) ;
01292             }
01293         else
01294             flux << "  " << 0 ;
01295         flux << " : " << endl ;
01296         flux << "-------------" << endl ; 
01297 
01298 
01299         if (source.c[i] != 0x0)
01300             flux << *source.c[i] << endl ;
01301         else
01302             flux << "Unknown component ... " << endl ;
01303             
01304         }
01305         break ;
01306         }
01307     default : {
01308         cout << "Unknown case in operator<< (ostream&, const Tenseur&)" << endl ;
01309         abort() ;
01310         break ;
01311     }
01312     }
01313     
01314     flux << " -----------------------------------------------------" << endl ;
01315     return flux ;
01316 }
01317 
01318 void Tenseur::sauve(FILE* fd) const {
01319     
01320     type_indice.sauve(fd) ; // type des composantes
01321     fwrite_be(&valence, sizeof(int), 1, fd) ;    // la valence
01322     
01323     if (valence != 0) {
01324     triad->sauve(fd) ;      // Vectorial basis
01325     }
01326     
01327     fwrite_be(&n_comp, sizeof(int), 1, fd) ; // nbre composantes
01328     fwrite_be(&etat, sizeof(int), 1, fd) ; // etat
01329    
01330     if (etat == ETATQCQ)
01331     for (int i=0 ; i<n_comp ; i++)
01332         c[i]->sauve(fd) ;
01333     if (poids != 0.)
01334       fwrite_be(&poids, sizeof(double), 1, fd) ; //poids, si pertinent
01335 }
01336 
01337 
01338 void Tenseur::fait_gradient () const {
01339     
01340     assert (etat != ETATNONDEF) ;
01341     
01342     if (p_gradient != 0x0)
01343     return ;
01344     else {
01345  
01346     // Construction du resultat :
01347     Itbl tipe (valence+1) ;
01348     tipe.set_etat_qcq() ;
01349     tipe.set(0) = COV ;
01350     for (int i=0 ; i<valence ; i++)
01351         tipe.set(i+1) = type_indice(i) ;
01352     
01353     // Vectorial basis
01354     // ---------------
01355     if (valence != 0) {
01356       //        assert (*triad == mp->get_bvect_cart()) ;
01357     }
01358 
01359     p_gradient = new Tenseur(*mp, valence+1, tipe, mp->get_bvect_cart(), 
01360                  metric, poids) ;
01361     
01362     if (etat == ETATZERO)
01363         p_gradient->set_etat_zero() ;
01364     else {
01365         p_gradient->set_etat_qcq() ;
01366         // Boucle sur les indices :
01367     
01368         Itbl indices_source(valence) ;
01369         indices_source.set_etat_qcq() ;
01370     
01371         for (int j=0 ; j<p_gradient->n_comp ; j++) {    
01372         
01373         Itbl indices_res(p_gradient->donne_indices(j)) ;
01374 
01375         for (int m=0 ; m<valence ; m++)
01376             indices_source.set(m) = indices_res(m+1) ;
01377          
01378         p_gradient->set(indices_res) =  
01379             (*this)(indices_source).deriv(indices_res(0)) ;
01380         }
01381       }
01382     }
01383 }
01384 
01385 void Tenseur::fait_gradient_spher () const {
01386     
01387     assert (etat != ETATNONDEF) ;
01388     
01389     if (p_gradient_spher != 0x0)
01390     return ;
01391     else {
01392  
01393     // Construction du resultat :
01394     
01395     if (valence != 0) {
01396         cout << 
01397         "Tenseur::fait_gradient_spher : the valence must be zero !" 
01398         << endl ; 
01399         abort() ; 
01400     }
01401 
01402     p_gradient_spher = new Tenseur(*mp, 1, COV, mp->get_bvect_spher(),
01403                        metric, poids) ;
01404     
01405     if (etat == ETATZERO) {
01406         p_gradient_spher->set_etat_zero() ;
01407     }
01408     else {
01409         assert( etat == ETATQCQ ) ; 
01410         p_gradient_spher->set_etat_qcq() ;
01411 
01412         p_gradient_spher->set(0) = c[0]->dsdr() ;       // d/dr 
01413         p_gradient_spher->set(1) = c[0]->srdsdt() ;     // 1/r d/dtheta
01414         p_gradient_spher->set(2) = c[0]->srstdsdp() ;   // 1/(r sin(theta))
01415                                 //        d/dphi
01416 
01417     }
01418     }
01419 }
01420 
01421 
01422 void Tenseur::fait_derive_cov (const Metrique& metre, int ind) const {
01423     
01424   assert (etat != ETATNONDEF) ;
01425   assert (valence != 0) ;
01426   
01427   if (p_derive_cov[ind] != 0x0)
01428     return ;
01429   else {
01430     
01431     p_derive_cov[ind] = new Tenseur (gradient()) ;
01432     
01433     if ((valence != 0) && (etat != ETATZERO)) {
01434 
01435       
01436       //    assert( *(metre.gamma().get_triad()) == *triad ) ; 
01437       Tenseur* auxi ;
01438       for (int i=0 ; i<valence ; i++) {
01439     
01440     if (type_indice(i) == COV) {
01441       auxi = new Tenseur(contract(metre.gamma(), 0,(*this), i)) ;
01442       
01443       Itbl indices_gamma(p_derive_cov[ind]->valence) ;
01444       indices_gamma.set_etat_qcq() ;
01445       //On range comme il faut :
01446       for (int j=0 ; j<p_derive_cov[ind]->n_comp ; j++) {
01447         
01448         Itbl indices (p_derive_cov[ind]->donne_indices(j)) ;
01449         indices_gamma.set(0) = indices(0) ;
01450         indices_gamma.set(1) = indices(i+1) ;
01451         for (int idx=2 ; idx<p_derive_cov[ind]->valence ; idx++)
01452           if (idx<=i+1)
01453         indices_gamma.set(idx) = indices(idx-1) ;
01454           else
01455         indices_gamma.set(idx) = indices(idx) ;
01456         
01457           p_derive_cov[ind]->set(indices) -= (*auxi)(indices_gamma) ;
01458       }
01459     }   
01460     else {
01461       auxi = new Tenseur(contract(metre.gamma(), 1, (*this), i)) ;
01462       
01463       Itbl indices_gamma(p_derive_cov[ind]->valence) ;
01464       indices_gamma.set_etat_qcq() ;
01465       
01466       //On range comme il faut :
01467       for (int j=0 ; j<p_derive_cov[ind]->n_comp ; j++) {
01468         
01469         Itbl indices (p_derive_cov[ind]->donne_indices(j)) ;
01470         indices_gamma.set(0) = indices(i+1) ;
01471         indices_gamma.set(1) = indices(0) ;
01472         for (int idx=2 ; idx<p_derive_cov[ind]->valence ; idx++)
01473           if (idx<=i+1)
01474         indices_gamma.set(idx) = indices(idx-1) ;
01475           else
01476         indices_gamma.set(idx) = indices(idx) ;
01477         p_derive_cov[ind]->set(indices) += (*auxi)(indices_gamma) ;
01478       }
01479     }
01480     delete auxi ;
01481       }
01482     }
01483     if ((poids != 0.)&&(etat != ETATZERO)) 
01484       *p_derive_cov[ind] = *p_derive_cov[ind] - 
01485     poids*contract(metre.gamma(), 0, 2) * (*this) ;
01486     
01487   }
01488 }
01489 
01490 
01491 
01492 void Tenseur::fait_derive_con (const Metrique& metre, int ind) const {
01493     
01494   if (p_derive_con[ind] != 0x0)
01495     return ;
01496   else {
01497     // On calcul la derivee covariante :
01498     if (valence != 0)
01499       p_derive_con[ind] = new Tenseur
01500     (contract(metre.con(), 1, derive_cov(metre), 0)) ;
01501     
01502     else {
01503       Tenseur grad (gradient()) ;
01504       grad.change_triad( *(metre.con().get_triad()) ) ;
01505       p_derive_con[ind] = new Tenseur (contract(metre.con(), 1, grad, 0)) ;
01506     }
01507   }
01508 }
01509 
01510 void Tenseur::fait_carre_scal (const Metrique& met, int ind) const {
01511     
01512     if (p_carre_scal[ind] != 0x0)
01513     return ;
01514     else {
01515     assert (valence != 0) ;   // A ne pas appeler sur un scalaire ;
01516        
01517     // On bouge tous les indices :
01518     Tenseur op_t(manipule(*this, met)) ;
01519    
01520     Tenseur* auxi = new Tenseur(contract(*this, 0, op_t, 0)) ;
01521     Tenseur* auxi_old ;
01522     
01523     // On contracte tous les indices restant :
01524     for (int indice=1 ; indice<valence ; indice++) {
01525         auxi_old = new Tenseur(contract(*auxi, 0, valence-indice)) ;
01526         delete auxi ;
01527         auxi = new Tenseur(*auxi_old) ;
01528         delete auxi_old ;
01529     }
01530     p_carre_scal[ind] = new Tenseur (*auxi) ;
01531     delete auxi ;
01532     }
01533 }
01534     
01535 const Tenseur& Tenseur::gradient () const {
01536     if (p_gradient == 0x0)
01537     fait_gradient() ;
01538     return *p_gradient ;
01539 }
01540 
01541 const Tenseur& Tenseur::gradient_spher() const {
01542     if (p_gradient_spher == 0x0)
01543     fait_gradient_spher() ;
01544     return *p_gradient_spher ;
01545 }
01546 
01547 const Tenseur& Tenseur::derive_cov (const Metrique& metre) const {
01548     
01549     if (valence == 0)
01550     return gradient() ;
01551     else {
01552     set_dependance(metre) ;
01553     int j = get_place_met(metre) ;
01554     assert(j!=-1) ;
01555     if (p_derive_cov[j] == 0x0)
01556         fait_derive_cov (metre,j) ;
01557     return *p_derive_cov[j] ;
01558     }
01559 }
01560 
01561 const Tenseur& Tenseur::derive_con (const Metrique& metre) const {
01562     set_dependance(metre) ;
01563     int j = get_place_met(metre) ;
01564     assert(j!=-1) ;
01565     if (p_derive_con[j] == 0x0)
01566     fait_derive_con (metre, j) ;
01567     return *p_derive_con[j] ;
01568 }
01569 
01570 const Tenseur& Tenseur::carre_scal (const Metrique& metre) const {
01571     set_dependance(metre) ;
01572     int j = get_place_met(metre) ;
01573     assert(j!=-1) ;
01574     if (p_carre_scal[j] == 0x0)
01575     fait_carre_scal (metre, j) ;
01576     return *p_carre_scal[j] ;
01577 }

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