tensor_calculus.C

00001 /*
00002  *  Methods of class Tensor for tensor calculus
00003  *
00004  *
00005  */
00006 
00007 /*
00008  *   Copyright (c) 2003 Eric Gourgoulhon & Jerome Novak
00009  *
00010  *   Copyright (c) 1999-2001 Philippe Grandclement (for preceding class Tenseur)
00011  *
00012  *   This file is part of LORENE.
00013  *
00014  *   LORENE is free software; you can redistribute it and/or modify
00015  *   it under the terms of the GNU General Public License as published by
00016  *   the Free Software Foundation; either version 2 of the License, or
00017  *   (at your option) any later version.
00018  *
00019  *   LORENE is distributed in the hope that it will be useful,
00020  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022  *   GNU General Public License for more details.
00023  *
00024  *   You should have received a copy of the GNU General Public License
00025  *   along with LORENE; if not, write to the Free Software
00026  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00027  *
00028  */
00029 
00030 
00031 char tensor_calculus_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tensor/tensor_calculus.C,v 1.8 2004/02/26 22:49:45 e_gourgoulhon Exp $" ;
00032 
00033 /*
00034  * $Id: tensor_calculus.C,v 1.8 2004/02/26 22:49:45 e_gourgoulhon Exp $
00035  * $Log: tensor_calculus.C,v $
00036  * Revision 1.8  2004/02/26 22:49:45  e_gourgoulhon
00037  * Added methods compute_derive_lie and derive_lie.
00038  *
00039  * Revision 1.7  2004/02/18 18:50:07  e_gourgoulhon
00040  * -- Added new methods trace(...).
00041  * -- Tensorial product moved to file tensor_calculus_ext.C, since it is not
00042  *    a method of class Tensor.
00043  *
00044  * Revision 1.6  2004/02/18 15:54:23  e_gourgoulhon
00045  * Efficiency improved in method scontract: better handling of work (it is
00046  * now considered as a reference on the relevant component of the result).
00047  *
00048  * Revision 1.5  2003/12/05 16:38:50  f_limousin
00049  * Added method operator*
00050  *
00051  * Revision 1.4  2003/10/28 21:25:34  e_gourgoulhon
00052  * Method contract renamed scontract.
00053  *
00054  * Revision 1.3  2003/10/11 16:47:10  e_gourgoulhon
00055  * Suppressed the call to Ibtl::set_etat_qcq() after the construction
00056  * of the Itbl's, thanks to the new property of the Itbl class.
00057  *
00058  * Revision 1.2  2003/10/06 20:52:22  e_gourgoulhon
00059  * Added methods up, down and up_down.
00060  *
00061  * Revision 1.1  2003/10/06 15:13:38  e_gourgoulhon
00062  * Tensor contraction.
00063  *
00064  *
00065  * $Header: /cvsroot/Lorene/C++/Source/Tensor/tensor_calculus.C,v 1.8 2004/02/26 22:49:45 e_gourgoulhon Exp $
00066  *
00067  */
00068 
00069 // Headers C++
00070 #include "headcpp.h"
00071 
00072 // Headers C
00073 #include <stdlib.h>
00074 #include <assert.h>
00075 #include <math.h>
00076 
00077 // Headers Lorene
00078 #include "tensor.h"
00079 #include "metric.h"
00080 
00081 
00082                 //------------------//
00083                 //       Trace      //
00084                 //------------------//
00085 
00086 
00087 Tensor Tensor::trace(int ind_1, int ind_2) const {
00088     
00089     // Les verifications :
00090     assert( (ind_1 >= 0) && (ind_1 < valence) ) ;
00091     assert( (ind_2 >= 0) && (ind_2 < valence) ) ;
00092     assert( ind_1 != ind_2 )  ;
00093     assert( type_indice(ind_1) != type_indice(ind_2) )  ;
00094  
00095     // On veut ind_1 < ind_2 :
00096     if (ind_1 > ind_2) {
00097         int auxi = ind_2 ;
00098         ind_2 = ind_1 ;
00099         ind_1 = auxi ;
00100     }
00101     
00102     // On construit le resultat :
00103     int val_res = valence - 2 ;
00104    
00105     Itbl tipe(val_res) ;
00106     
00107     for (int i=0 ; i<ind_1 ; i++)
00108         tipe.set(i) = type_indice(i) ;
00109     for (int i=ind_1 ; i<ind_2-1 ; i++)
00110         tipe.set(i) = type_indice(i+1) ;
00111     for (int i = ind_2-1 ; i<val_res ; i++)
00112         tipe.set(i) = type_indice(i+2) ;
00113     
00114     Tensor res(*mp, val_res, tipe, triad) ; 
00115     
00116     // Boucle sur les composantes de res :
00117     
00118     Itbl jeux_indice_source(valence) ;
00119     
00120     for (int i=0 ; i<res.get_n_comp() ; i++) {
00121 
00122         Itbl jeux_indice_res(res.indices(i)) ;
00123         
00124         for (int j=0 ; j<ind_1 ; j++)
00125             jeux_indice_source.set(j) = jeux_indice_res(j) ;
00126         for (int j=ind_1+1 ; j<ind_2 ; j++)
00127             jeux_indice_source.set(j) = jeux_indice_res(j-1) ;
00128         for (int j=ind_2+1 ; j<valence ; j++)
00129             jeux_indice_source.set(j) = jeux_indice_res(j-2) ;
00130         
00131         Scalar& work = res.set(jeux_indice_res) ; 
00132         work.set_etat_zero() ;
00133 
00134         for (int j=1 ; j<=3 ; j++) {
00135             jeux_indice_source.set(ind_1) = j ;
00136             jeux_indice_source.set(ind_2) = j ;
00137             work += (*cmp[position(jeux_indice_source)]) ;
00138         }
00139         
00140     }
00141     
00142     return res ;
00143 }
00144 
00145 
00146 Tensor Tensor::trace(int ind1, int ind2, const Metric& gam) const {
00147 
00148     // Les verifications :
00149     assert( (ind1 >= 0) && (ind1 < valence) ) ;
00150     assert( (ind2 >= 0) && (ind2 < valence) ) ;
00151     assert( ind1 != ind2 )  ;
00152  
00153     if ( type_indice(ind1) != type_indice(ind2) ) {
00154         cout << "Tensor::trace(int, int, const Metric&) : Warning : \n"
00155             << "  the two indices for the trace have opposite types,\n"
00156             << "  hence the metric is useless !\n" ; 
00157 
00158         return trace(ind1, ind2) ;               
00159     }
00160     else {
00161         if ( type_indice(ind1) == COV  ) {
00162             return contract(gam.con(), 0, 1, *this, ind1, ind2) ; 
00163         }
00164         else{
00165             return contract(gam.cov(), 0, 1, *this, ind1, ind2) ; 
00166         }
00167     }
00168           
00169 }
00170 
00171 
00172 
00173 Scalar Tensor::trace() const {
00174     
00175     // Les verifications :
00176     assert( valence == 2 )  ;
00177     assert( type_indice(0) != type_indice(1) )  ;
00178     
00179     Scalar res(*mp) ; 
00180     res.set_etat_zero() ; 
00181     
00182     for (int i=1; i<=3; i++) {
00183         res += operator()(i,i) ;    
00184     }
00185     
00186     return res ;
00187 }
00188 
00189 
00190 Scalar Tensor::trace(const Metric& gam) const {
00191     
00192     assert( valence == 2 )  ;
00193     
00194     if ( type_indice(0) != type_indice(1) ) {
00195         cout << "Tensor::trace(const Metric&) : Warning : \n"
00196             << "  the two indices have opposite types,\n"
00197             << "  hence the metric is useless to get the trace !\n" ; 
00198 
00199         return trace() ;               
00200     }
00201     else {
00202         if ( type_indice(0) == COV  ) {
00203             return contract(gam.con(), 0, 1, *this, 0, 1) ; 
00204         }
00205         else{
00206             return contract(gam.cov(), 0, 1, *this, 0, 1) ; 
00207         }
00208     }
00209           
00210 }
00211 
00212 
00213                 //----------------------//
00214                 //  Index manipulation  //
00215                 //----------------------//
00216 
00217 
00218 Tensor Tensor::up(int place, const Metric& met) const {
00219     
00220     assert (valence != 0) ;     // Aucun interet pour un scalaire...
00221     assert ((place >=0) && (place < valence)) ;
00222     
00223     
00224     Tensor auxi = ::contract(met.con(), 1, *this, place) ;
00225     
00226     // On doit remettre les indices a la bonne place ...
00227     
00228     Itbl tipe(valence) ;
00229 
00230     for (int i=0 ; i<valence ; i++)
00231         tipe.set(i) = type_indice(i) ;
00232     tipe.set(place) = CON ;
00233     
00234     Tensor res(*mp, valence, tipe, triad) ;
00235     
00236     Itbl place_auxi(valence) ;
00237     
00238     for (int i=0 ; i<res.n_comp ; i++) {
00239     
00240         Itbl place_res(res.indices(i)) ;
00241     
00242         place_auxi.set(0) = place_res(place) ;
00243         for (int j=1 ; j<place+1 ; j++)
00244             place_auxi.set(j) = place_res(j-1)  ;
00245         place_res.set(place) = place_auxi(0) ;
00246     
00247         for (int j=place+1 ; j<valence ; j++)
00248             place_auxi.set(j) = place_res(j);   
00249     
00250         res.set(place_res) = auxi(place_auxi) ;
00251     }
00252     
00253     return res ;
00254 
00255 } 
00256 
00257 
00258 Tensor Tensor::down(int place, const Metric& met) const {
00259     
00260     assert (valence != 0) ;     // Aucun interet pour un scalaire...
00261     assert ((place >=0) && (place < valence)) ;
00262     
00263     Tensor auxi = ::contract(met.cov(), 1, *this, place) ;
00264     
00265     // On doit remettre les indices a la bonne place ...
00266     
00267     Itbl tipe(valence) ;
00268 
00269     for (int i=0 ; i<valence ; i++)
00270         tipe.set(i) = type_indice(i) ;
00271     tipe.set(place) = COV ;
00272     
00273     Tensor res(*mp, valence, tipe, triad) ;
00274     
00275     Itbl place_auxi(valence) ;
00276     
00277     for (int i=0 ; i<res.n_comp ; i++) {
00278     
00279         Itbl place_res(res.indices(i)) ;
00280     
00281         place_auxi.set(0) = place_res(place) ;
00282         for (int j=1 ; j<place+1 ; j++)
00283             place_auxi.set(j) = place_res(j-1)  ;
00284         place_res.set(place) = place_auxi(0) ;
00285     
00286         for (int j=place+1 ; j<valence ; j++)
00287             place_auxi.set(j) = place_res(j);   
00288     
00289         res.set(place_res) = auxi(place_auxi) ;
00290     }
00291     
00292     return res ;
00293 
00294 } 
00295 
00296 
00297 
00298 Tensor Tensor::up_down(const Metric& met) const  {
00299     
00300     Tensor* auxi ;
00301     Tensor* auxi_old = new Tensor(*this) ;
00302     
00303     for (int i=0 ; i<valence ; i++) {
00304 
00305         if (type_indice(i) == COV) {
00306             auxi = new Tensor( auxi_old->up(i, met) ) ;
00307         }
00308         else{
00309             auxi = new Tensor( auxi_old->down(i, met) ) ;
00310         }
00311         
00312         delete auxi_old ;
00313         auxi_old = new Tensor(*auxi) ;
00314         delete auxi ;
00315 
00316     }
00317     
00318     Tensor result(*auxi_old) ;
00319     delete auxi_old ;
00320 
00321     return result ;
00322 }
00323 
00324 
00325                 //-----------------------//
00326                 //     Lie derivative    //
00327                 //-----------------------//
00328 
00329 // Protected method
00330 //-----------------
00331 
00332 void Tensor::compute_derive_lie(const Vector& vv, Tensor& resu) const {
00333 
00334 
00335     // Protections
00336     // -----------
00337     if (valence > 0) {
00338         assert(vv.get_triad() == triad) ; 
00339         assert(resu.get_triad() == triad) ; 
00340     }
00341 
00342 
00343     // Flat metric
00344     // -----------
00345         
00346     const Metric_flat* fmet ;
00347     
00348     if (valence == 0) {
00349         fmet = &(mp->flat_met_spher()) ; 
00350     }
00351     else {
00352         assert( triad != 0x0 ) ; 
00353 
00354         const Base_vect_spher* bvs = 
00355             dynamic_cast<const Base_vect_spher*>(triad) ; 
00356         if (bvs != 0x0) {
00357             fmet = &(mp->flat_met_spher()) ; 
00358         }
00359         else {
00360             const Base_vect_cart* bvc = 
00361                 dynamic_cast<const Base_vect_cart*>(triad) ; 
00362             if (bvc != 0x0) {
00363                 fmet = &(mp->flat_met_cart()) ; 
00364             }
00365             else {
00366                 cerr << "Tensor::compute_derive_lie : unknown triad type !\n" ; 
00367                 abort() ; 
00368             }
00369         }
00370     }
00371 
00372     // Determination of the dzpuis parameter of the input  --> dz_in
00373     // ---------------------------------------------------
00374     int dz_in = 0 ;
00375     for (int ic=0; ic<n_comp; ic++) {
00376         int dzp = cmp[ic]->get_dzpuis() ; 
00377         assert(dzp >= 0) ; 
00378         if (dzp > dz_in) dz_in = dzp ; 
00379     }
00380 
00381 #ifndef NDEBUG
00382     // Check : do all components have the same dzpuis ?
00383     for (int ic=0; ic<n_comp; ic++) {
00384         if ( !(cmp[ic]->check_dzpuis(dz_in)) ) {
00385             cout << "######## WARNING #######\n" ; 
00386             cout << " Tensor::compute_derive_lie: the tensor components \n"
00387             << "    do not have all the same dzpuis ! : \n" 
00388             << "    ic, dzpuis(ic), dz_in : " << ic << "  " 
00389             <<  cmp[ic]->get_dzpuis() << "  " << dz_in << endl ; 
00390         } 
00391     }
00392 #endif
00393         
00394     
00395     // Initialisation to nabla_V T 
00396     // ---------------------------
00397     
00398     resu = contract(vv, 0, derive_cov(*fmet), valence) ;
00399     
00400 
00401     // Addition of the terms with derivatives of V  (only if valence > 0)
00402     // -------------------------------------------
00403     
00404     if (valence > 0) {
00405     
00406         const Tensor& dv = vv.derive_cov(*fmet) ;  // gradient of V
00407     
00408         Itbl ind1(valence) ; // working Itbl to store the indices of resu
00409         Itbl ind0(valence) ; // working Itbl to store the indices of this
00410         Scalar tmp(*mp) ;   // working scalar
00411     
00412         // loop on all the components of the output tensor:
00413 
00414         int ncomp_resu = resu.get_n_comp() ; 
00415         
00416         for (int ic=0; ic<ncomp_resu; ic++) {
00417     
00418             // indices corresponding to the component no. ic in the output tensor
00419             ind1 = resu.indices(ic) ; 
00420     
00421             tmp = 0 ; 
00422         
00423             // Loop on the number of indices of this 
00424             for (int id=0; id<valence; id++) {
00425             
00426                 ind0 = ind1 ;
00427                 
00428                 switch( type_indice(id) ) {
00429                 
00430                     case CON : {
00431                         for (int k=1; k<=3; k++) {
00432                             ind0.set(id) = k ; 
00433                             tmp -= operator()(ind0) * dv(ind1(id), k) ;
00434                         }
00435                         break ; 
00436                     }
00437                 
00438                     case COV : {
00439                         for (int k=1; k<=3; k++) {
00440                             ind0.set(id) = k ; 
00441                             tmp += operator()(ind0) * dv(k, ind1(id)) ;
00442                         }
00443                         break ; 
00444                     }
00445                 
00446                     default : {
00447                         cerr << 
00448                         "Tensor::compute_derive_lie: unexpected type of index !\n" ;
00449                         abort() ; 
00450                         break ; 
00451                     }
00452                 
00453                 }   // end of switch on index type 
00454                 
00455             }   // end of loop on the number of indices of uu               
00456 
00457 
00458             if (dz_in > 0) tmp.dec_dzpuis() ; // to get the same dzpuis as
00459                                               // nabla_V T
00460 
00461             resu.set(ind1) += tmp ;    // Addition to the nabla_V T term
00462         
00463         
00464         }   // end of loop on all the components of the output tensor
00465         
00466     }   // end of case valence > 0 
00467     
00468 }
00469  
00470 
00471 // Public interface
00472 //-----------------
00473 
00474 Tensor Tensor::derive_lie(const Vector& vv) const {
00475 
00476     Tensor resu(*mp, valence, type_indice, triad) ; 
00477     
00478     compute_derive_lie(vv, resu) ;
00479     
00480     return resu ; 
00481     
00482 }
00483 
00484 
00485 
00486 
00487 
00488 
00489 
00490 
00491 
00492 
00493  

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