tenseur_operateur.C

00001 /*
00002  *   Copyright (c) 1999-2001 Philippe Grandclement
00003  *   Copyright (c) 2000-2001 Eric Gourgoulhon
00004  *   Copyright (c) 2002 Jerome Novak
00005  *
00006  *   This file is part of LORENE.
00007  *
00008  *   LORENE is free software; you can redistribute it and/or modify
00009  *   it under the terms of the GNU General Public License as published by
00010  *   the Free Software Foundation; either version 2 of the License, or
00011  *   (at your option) any later version.
00012  *
00013  *   LORENE is distributed in the hope that it will be useful,
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  *   GNU General Public License for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with LORENE; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  */
00023 
00024 
00025 char tenseur_operateur_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tenseur/tenseur_operateur.C,v 1.8 2004/05/27 07:17:19 p_grandclement Exp $" ;
00026 
00027 /*
00028  * $Id: tenseur_operateur.C,v 1.8 2004/05/27 07:17:19 p_grandclement Exp $
00029  * $Log: tenseur_operateur.C,v $
00030  * Revision 1.8  2004/05/27 07:17:19  p_grandclement
00031  * Correction of some shadowed variables
00032  *
00033  * Revision 1.7  2003/06/20 14:53:38  f_limousin
00034  * Add the function contract_desal()
00035  *
00036  * Revision 1.6  2003/03/03 19:38:41  f_limousin
00037  * Suppression of an assert on a metric associated with a tensor.
00038  *
00039  * Revision 1.5  2002/10/16 14:37:14  j_novak
00040  * Reorganization of #include instructions of standard C++, in order to
00041  * use experimental version 3 of gcc.
00042  *
00043  * Revision 1.4  2002/09/10 13:44:17  j_novak
00044  * The method "manipule" of one indice has been removed for Tenseur_sym objects
00045  * (the result cannot be a Tenseur_sym).
00046  * The method "sans_trace" now computes the traceless part of a Tenseur (or
00047  * Tenseur_sym) of valence 2.
00048  *
00049  * Revision 1.3  2002/09/06 14:49:25  j_novak
00050  * Added method lie_derive for Tenseur and Tenseur_sym.
00051  * Corrected various errors for derive_cov and arithmetic.
00052  *
00053  * Revision 1.2  2002/08/07 16:14:11  j_novak
00054  * class Tenseur can now also handle tensor densities, this should be transparent to older codes
00055  *
00056  * Revision 1.1.1.1  2001/11/20 15:19:30  e_gourgoulhon
00057  * LORENE
00058  *
00059  * Revision 2.11  2001/08/27  10:04:21  eric
00060  * Ajout de l'operator% (produit tensoriel avec desaliasing)
00061  *
00062  * Revision 2.10  2001/05/26  15:43:17  eric
00063  * Ajout de la fonction flat_scalar_prod_desal (desaliasage)
00064  *
00065  * Revision 2.9  2000/10/06  15:08:40  eric
00066  * Traitement des cas ETATZERO dans contract et flat_scal_prod
00067  *
00068  * Revision 2.8  2000/09/13  09:43:29  eric
00069  * Modif skxk : appel des nouvelles fonctions Valeur::mult_cp() et
00070  *  Valeur::mult_sp() pour la multiplication par cos(phi) et sin(phi).
00071  *
00072  * Revision 2.7  2000/02/09  19:32:11  eric
00073  * MODIF IMPORTANTE: la triade de decomposition est desormais passee en
00074  * argument des constructeurs.
00075  *
00076  * Revision 2.6  2000/02/01  14:14:25  eric
00077  * Ajout de la fonction amie flat_scalar_prod.
00078  *
00079  * Revision 2.5  2000/01/21  12:59:18  phil
00080  * ajout de skxk
00081  *
00082  * Revision 2.4  2000/01/14  09:29:43  eric
00083  * *** empty log message ***
00084  *
00085  * Revision 2.3  2000/01/13  17:22:37  phil
00086  * la fonction contraction de deux tenseurs ne passe plus par produit tensoriel
00087  *
00088  * Revision 2.2  2000/01/11  11:14:29  eric
00089  * Changement de nom pour la base vectorielle : base --> triad
00090  *
00091  * Revision 2.1  2000/01/10  17:25:15  eric
00092  * Gestion des bases vectorielles (triades de decomposition).
00093  *
00094  * Revision 2.0  1999/12/02  17:19:06  phil
00095  * *** empty log message ***
00096  *
00097  *
00098  * $Header: /cvsroot/Lorene/C++/Source/Tenseur/tenseur_operateur.C,v 1.8 2004/05/27 07:17:19 p_grandclement Exp $
00099  *
00100  */
00101 
00102 // Headers C
00103 #include <stdlib.h>
00104 #include <assert.h>
00105 #include <math.h>
00106 
00107 // Headers Lorene
00108 #include "tenseur.h"
00109 #include "metrique.h"
00110 
00111 
00112 Tenseur operator*(const Tenseur& t1, const Tenseur& t2) {
00113    
00114     assert ((t1.etat != ETATNONDEF) && (t2.etat != ETATNONDEF)) ;
00115     assert (t1.mp == t2.mp) ;
00116     
00117     int val_res = t1.valence + t2.valence ;
00118     double poids_res = t1.poids + t2.poids ;
00119     poids_res = (fabs(poids_res) < 1.e-10 ? 0. : poids_res) ;
00120     const Metrique* met_res = 0x0 ;
00121     if (poids_res != 0.) {
00122       //      assert((t1.metric != 0x0) || (t2.metric != 0x0)) ;
00123       if (t1.metric != 0x0) met_res = t1.metric ;
00124       else met_res = t2.metric ;
00125     }
00126     
00127    // cas scalaire :
00128     if (val_res == 0) {
00129     Tenseur scal(*t1.mp, met_res, poids_res) ;
00130     // cas ou un des deux est nul :
00131     if ((t1.etat == ETATZERO) || (t2.etat == ETATZERO))
00132         scal.set_etat_zero() ;
00133     else {
00134         scal.set_etat_qcq() ;
00135         scal.set() = t1() * t2() ;
00136     }
00137     return scal ;
00138    }
00139     
00140     else {
00141     
00142     Itbl tipe (val_res) ;
00143     tipe.set_etat_qcq() ;
00144     for (int i=0 ; i<t1.valence ; i++)
00145         tipe.set(i) = t1.type_indice(i) ;
00146     for (int i=0 ; i<t2.valence ; i++)
00147         tipe.set(i+t1.valence) = t2.type_indice(i) ;
00148     
00149 
00150     if ( (t1.valence != 0) && (t2.valence != 0) ) {
00151         assert ( *(t1.get_triad()) == *(t2.get_triad()) ) ;
00152     }
00153 
00154     const Base_vect* triad_res ; 
00155     if (t1.valence != 0) {
00156         triad_res = t1.get_triad() ; 
00157     }
00158     else{
00159         triad_res = t2.get_triad() ; 
00160     }
00161 
00162     Tenseur res(*t1.mp, val_res, tipe, triad_res, met_res, poids_res) ;
00163     
00164     if ((t1.etat == ETATZERO) || (t2.etat == ETATZERO))
00165         res.set_etat_zero() ;
00166     else {
00167         res.set_etat_qcq() ;
00168         Itbl jeux_indice_t1 (t1.valence) ;
00169         jeux_indice_t1.set_etat_qcq() ;
00170         Itbl jeux_indice_t2 (t2.valence) ;
00171         jeux_indice_t2.set_etat_qcq() ;
00172         
00173         for (int i=0 ; i<res.n_comp ; i++) {
00174         Itbl jeux_indice_res(res.donne_indices(i)) ;
00175         for (int j=0 ; j<t1.valence ; j++)
00176             jeux_indice_t1.set(j) = jeux_indice_res(j) ;
00177         for (int j=0 ; j<t2.valence ; j++)
00178             jeux_indice_t2.set(j) = jeux_indice_res(j+t1.valence) ;
00179         
00180         res.set(jeux_indice_res) = t1(jeux_indice_t1)*t2(jeux_indice_t2) ;
00181         }
00182     }
00183     return res ;
00184     }
00185 }
00186 
00187     //------------------------------------//
00188     // Tensorial product wiht desaliasing //
00189     //------------------------------------//
00190     
00191 
00192 Tenseur operator%(const Tenseur& t1, const Tenseur& t2) {
00193    
00194     assert ((t1.etat != ETATNONDEF) && (t2.etat != ETATNONDEF)) ;
00195     assert (t1.mp == t2.mp) ;
00196     
00197     int val_res = t1.valence + t2.valence ;
00198     double poids_res = t1.poids + t2.poids ;
00199     poids_res = (fabs(poids_res) < 1.e-10 ? 0. : poids_res) ;
00200     const Metrique* met_res = 0x0 ;
00201     if (poids_res != 0.) {
00202       // assert((t1.metric != 0x0) || (t2.metric != 0x0)) ;
00203       if (t1.metric != 0x0) met_res = t1.metric ;
00204       else met_res = t2.metric ;
00205     }
00206     
00207    // cas scalaire :
00208     if (val_res == 0) {
00209     Tenseur scal(*t1.mp, met_res, poids_res) ;
00210     // cas ou un des deux est nul :
00211     if ((t1.etat == ETATZERO) || (t2.etat == ETATZERO))
00212         scal.set_etat_zero() ;
00213     else {
00214         scal.set_etat_qcq() ;
00215         scal.set() = t1() % t2() ;
00216     }
00217     return scal ;
00218    }
00219     
00220     else {
00221     
00222     Itbl tipe (val_res) ;
00223     tipe.set_etat_qcq() ;
00224     for (int i=0 ; i<t1.valence ; i++)
00225         tipe.set(i) = t1.type_indice(i) ;
00226     for (int i=0 ; i<t2.valence ; i++)
00227         tipe.set(i+t1.valence) = t2.type_indice(i) ;
00228     
00229 
00230     if ( (t1.valence != 0) && (t2.valence != 0) ) {
00231         assert ( *(t1.get_triad()) == *(t2.get_triad()) ) ;
00232     }
00233 
00234     const Base_vect* triad_res ; 
00235     if (t1.valence != 0) {
00236         triad_res = t1.get_triad() ; 
00237     }
00238     else{
00239         triad_res = t2.get_triad() ; 
00240     }
00241 
00242     Tenseur res(*t1.mp, val_res, tipe, triad_res, met_res, poids_res) ;
00243 
00244 
00245     
00246     if ((t1.etat == ETATZERO) || (t2.etat == ETATZERO))
00247         res.set_etat_zero() ;
00248     else {
00249         res.set_etat_qcq() ;
00250         Itbl jeux_indice_t1 (t1.valence) ;
00251         jeux_indice_t1.set_etat_qcq() ;
00252         Itbl jeux_indice_t2 (t2.valence) ;
00253         jeux_indice_t2.set_etat_qcq() ;
00254         
00255         for (int i=0 ; i<res.n_comp ; i++) {
00256         Itbl jeux_indice_res(res.donne_indices(i)) ;
00257         for (int j=0 ; j<t1.valence ; j++)
00258             jeux_indice_t1.set(j) = jeux_indice_res(j) ;
00259         for (int j=0 ; j<t2.valence ; j++)
00260             jeux_indice_t2.set(j) = jeux_indice_res(j+t1.valence) ;
00261         
00262         res.set(jeux_indice_res) = t1(jeux_indice_t1) % 
00263                             t2(jeux_indice_t2) ;
00264         }
00265     }
00266     return res ;
00267     }
00268 }
00269 
00270 
00271 
00272 Tenseur contract(const Tenseur& source, int ind_1, int ind_2)  {
00273     
00274     
00275     // Les verifications :
00276     assert (source.etat != ETATNONDEF) ;
00277     assert ((ind_1 >= 0) && (ind_1 < source.valence)) ;
00278     assert ((ind_2 >= 0) && (ind_2 < source.valence)) ;
00279     assert (source.type_indice(ind_1) != source.type_indice(ind_2))  ;
00280  
00281     // On veut ind_1 < ind_2 :
00282     if (ind_1 > ind_2) {
00283     int auxi = ind_2 ;
00284     ind_2 = ind_1 ;
00285     ind_1 = auxi ;
00286     }
00287     
00288     // On construit le resultat :
00289     int val_res = source.valence - 2 ;
00290    
00291     Itbl tipe (val_res) ;
00292     tipe.set_etat_qcq() ;
00293     for (int i=0 ; i<ind_1 ; i++)
00294     tipe.set(i) = source.type_indice(i) ;
00295     for (int i=ind_1 ; i<ind_2-1 ; i++)
00296     tipe.set(i) = source.type_indice(i+1) ;
00297     for (int i = ind_2-1 ; i<val_res ; i++)
00298     tipe.set(i) = source.type_indice(i+2) ;
00299     
00300     Tenseur res(*source.mp, val_res, tipe, source.triad, source.metric, 
00301         source.poids) ;
00302 
00303     // Cas particulier d'une source nulle
00304     if (source.etat == ETATZERO) {
00305     res.set_etat_zero() ; 
00306     return res ; 
00307     }
00308 
00309     res.set_etat_qcq() ;
00310     
00311     Cmp work(source.mp) ;
00312     
00313     // Boucle sur les composantes de res :
00314     
00315     Itbl jeux_indice_source(source.valence) ;
00316     jeux_indice_source.set_etat_qcq() ;
00317     
00318     for (int i=0 ; i<res.n_comp ; i++) {
00319     Itbl jeux_indice_res (res.donne_indices(i)) ;
00320     for (int j=0 ; j<ind_1 ; j++)
00321         jeux_indice_source.set(j) = jeux_indice_res(j) ;
00322     for (int j=ind_1+1 ; j<ind_2 ; j++)
00323         jeux_indice_source.set(j) = jeux_indice_res(j-1) ;
00324     for (int j=ind_2+1 ; j<source.valence ; j++)
00325         jeux_indice_source.set(j) = jeux_indice_res(j-2) ;
00326         
00327         
00328     work.set_etat_zero() ;
00329     for (int j=0 ; j<3 ; j++) {
00330         jeux_indice_source.set(ind_1) = j ;
00331         jeux_indice_source.set(ind_2) = j ;
00332         work = work + source(jeux_indice_source) ;
00333         }
00334         
00335     res.set(jeux_indice_res) = work ;
00336     }
00337     return res ;
00338 }
00339 
00340 
00341 Tenseur contract (const Tenseur& t1, int ind1, const Tenseur& t2, int ind2) {
00342     
00343     assert ((t1.etat != ETATNONDEF) && (t2.etat != ETATNONDEF)) ;
00344     // Verifs :
00345     assert ((ind1>=0) && (ind1<t1.valence)) ;
00346     assert ((ind2>=0) && (ind2<t2.valence)) ;
00347     assert (*(t1.mp) == *(t2.mp)) ;
00348     
00349     // Contraction possible ?
00350     if ( (t1.valence != 0) && (t2.valence != 0) ) {
00351         assert ( *(t1.get_triad()) == *(t2.get_triad()) ) ;
00352     }
00353     assert (t1.type_indice(ind1) != t2.type_indice(ind2)) ;
00354     
00355     int val_res = t1.valence + t2.valence - 2;
00356     double poids_res = t1.poids + t2.poids ;
00357     poids_res = (fabs(poids_res) < 1.e-10 ? 0. : poids_res) ;
00358     const Metrique* met_res = 0x0 ;
00359     if (poids_res != 0.) {
00360       //  assert((t1.metric != 0x0) || (t2.metric != 0x0)) ;
00361       if (t1.metric != 0x0) met_res = t1.metric ;
00362       else met_res = t2.metric ;
00363     }
00364     Itbl tipe(val_res) ;
00365     tipe.set_etat_qcq() ;
00366     for (int i=0 ; i<ind1 ; i++)
00367     tipe.set(i) = t1.type_indice(i) ;
00368     for (int i=ind1 ; i<t1.valence-1 ; i++)
00369     tipe.set(i) = t1.type_indice(i+1) ;
00370     for (int i=t1.valence-1 ; i<t1.valence+ind2-1 ; i++)
00371     tipe.set(i) = t2.type_indice(i-t1.valence+1) ;
00372     for (int i = t1.valence+ind2-1 ; i<val_res ; i++)
00373     tipe.set(i) = t2.type_indice(i-t1.valence+2) ;
00374     
00375     const Base_vect* triad_res = (val_res == 0) ? 0x0 : t1.get_triad() ; 
00376 
00377     Tenseur res(*t1.mp, val_res, tipe, triad_res, met_res, poids_res) ;
00378 
00379     // Cas particulier ou l'un des deux tenseurs est nul
00380     if ( (t1.etat == ETATZERO) || (t2.etat == ETATZERO) ) {
00381     res.set_etat_zero() ; 
00382     return res ; 
00383     }
00384 
00385     res.set_etat_qcq() ;
00386     
00387     Cmp work(t1.mp) ;
00388     
00389     // Boucle sur les composantes de res :
00390     
00391     Itbl jeux_indice_t1(t1.valence) ;
00392     Itbl jeux_indice_t2(t2.valence) ;
00393     jeux_indice_t1.set_etat_qcq() ;
00394     jeux_indice_t2.set_etat_qcq() ;
00395     
00396     for (int comp=0 ; comp<res.n_comp ; comp++) {
00397     Itbl jeux_indice_res (res.donne_indices(comp)) ;
00398     for (int i=0 ; i<ind1 ; i++)
00399         jeux_indice_t1.set(i) = jeux_indice_res(i) ;
00400     for (int i=ind1+1 ; i<t1.valence ; i++)
00401         jeux_indice_t1.set(i) = jeux_indice_res(i-1) ;
00402     for (int i=0 ; i<ind2 ; i++)
00403         jeux_indice_t2.set(i) = jeux_indice_res(t1.valence+i-1) ;
00404     for (int i=ind2+1 ; i<t2.valence ; i++)
00405         jeux_indice_t2.set(i) = jeux_indice_res(t1.valence+i-2) ;
00406     
00407         
00408         
00409     work.set_etat_zero() ;
00410     for (int j=0 ; j<3 ; j++) {
00411         jeux_indice_t1.set(ind1) = j ;
00412         jeux_indice_t2.set(ind2) = j ;
00413         work = work + t1(jeux_indice_t1)*t2(jeux_indice_t2) ;
00414         }
00415         
00416     res.set(jeux_indice_res) = work ;
00417     }
00418     return res ;
00419 }
00420 
00421 Tenseur contract_desal (const Tenseur& t1, int ind1, const Tenseur& t2, int ind2) {
00422     
00423     assert ((t1.etat != ETATNONDEF) && (t2.etat != ETATNONDEF)) ;
00424     // Verifs :
00425     assert ((ind1>=0) && (ind1<t1.valence)) ;
00426     assert ((ind2>=0) && (ind2<t2.valence)) ;
00427     assert (t1.mp == t2.mp) ;
00428     
00429     // Contraction possible ?
00430     if ( (t1.valence != 0) && (t2.valence != 0) ) {
00431         assert ( *(t1.get_triad()) == *(t2.get_triad()) ) ;
00432     }
00433     assert (t1.type_indice(ind1) != t2.type_indice(ind2)) ;
00434     
00435     int val_res = t1.valence + t2.valence - 2;
00436     double poids_res = t1.poids + t2.poids ;
00437     poids_res = (fabs(poids_res) < 1.e-10 ? 0. : poids_res) ;
00438     const Metrique* met_res = 0x0 ;
00439     if (poids_res != 0.) {
00440       //  assert((t1.metric != 0x0) || (t2.metric != 0x0)) ;
00441       if (t1.metric != 0x0) met_res = t1.metric ;
00442       else met_res = t2.metric ;
00443     }
00444     Itbl tipe(val_res) ;
00445     tipe.set_etat_qcq() ;
00446     for (int i=0 ; i<ind1 ; i++)
00447     tipe.set(i) = t1.type_indice(i) ;
00448     for (int i=ind1 ; i<t1.valence-1 ; i++)
00449     tipe.set(i) = t1.type_indice(i+1) ;
00450     for (int i=t1.valence-1 ; i<t1.valence+ind2-1 ; i++)
00451     tipe.set(i) = t2.type_indice(i-t1.valence+1) ;
00452     for (int i = t1.valence+ind2-1 ; i<val_res ; i++)
00453     tipe.set(i) = t2.type_indice(i-t1.valence+2) ;
00454     
00455     const Base_vect* triad_res = (val_res == 0) ? 0x0 : t1.get_triad() ; 
00456 
00457     Tenseur res(*t1.mp, val_res, tipe, triad_res, met_res, poids_res) ;
00458 
00459     // Cas particulier ou l'un des deux tenseurs est nul
00460     if ( (t1.etat == ETATZERO) || (t2.etat == ETATZERO) ) {
00461     res.set_etat_zero() ; 
00462     return res ; 
00463     }
00464 
00465     res.set_etat_qcq() ;
00466     
00467     Cmp work(t1.mp) ;
00468     
00469     // Boucle sur les composantes de res :
00470     
00471     Itbl jeux_indice_t1(t1.valence) ;
00472     Itbl jeux_indice_t2(t2.valence) ;
00473     jeux_indice_t1.set_etat_qcq() ;
00474     jeux_indice_t2.set_etat_qcq() ;
00475     
00476     for (int comp=0 ; comp<res.n_comp ; comp++) {
00477     Itbl jeux_indice_res (res.donne_indices(comp)) ;
00478     for (int i=0 ; i<ind1 ; i++)
00479         jeux_indice_t1.set(i) = jeux_indice_res(i) ;
00480     for (int i=ind1+1 ; i<t1.valence ; i++)
00481         jeux_indice_t1.set(i) = jeux_indice_res(i-1) ;
00482     for (int i=0 ; i<ind2 ; i++)
00483         jeux_indice_t2.set(i) = jeux_indice_res(t1.valence+i-1) ;
00484     for (int i=ind2+1 ; i<t2.valence ; i++)
00485         jeux_indice_t2.set(i) = jeux_indice_res(t1.valence+i-2) ;
00486     
00487         
00488         
00489     work.set_etat_zero() ;
00490     for (int j=0 ; j<3 ; j++) {
00491         jeux_indice_t1.set(ind1) = j ;
00492         jeux_indice_t2.set(ind2) = j ;
00493         work = work + t1(jeux_indice_t1)%t2(jeux_indice_t2) ;
00494         }
00495         
00496     res.set(jeux_indice_res) = work ;
00497     }
00498     return res ;
00499 }
00500 
00501 
00502 Tenseur manipule(const Tenseur& t1, const Metrique& met, int place) {
00503     
00504     assert (t1.etat != ETATNONDEF) ;
00505     assert (met.get_etat() != ETATNONDEF) ;
00506     
00507     int valen = t1.valence ;
00508     assert (valen != 0) ;       // Aucun interet pour un scalaire...
00509     assert ((place >=0) && (place < valen)) ;
00510     
00511     Itbl tipe (valen) ;
00512     tipe.set_etat_qcq() ;
00513     tipe.set(0) = -t1.type_indice(place) ;
00514     for (int i=1 ; i<place+1 ; i++)
00515     tipe.set(i) = t1.type_indice(i-1) ;
00516     for (int i=place+1 ; i<valen ; i++)
00517     tipe.set(i) = t1.type_indice(i) ;
00518     
00519     Tenseur auxi(*t1.mp, valen, tipe, t1.triad) ;
00520     
00521     if (t1.type_indice(place) == COV)
00522     auxi = contract (met.con(), 1, t1, place) ;
00523     else
00524     auxi = contract (met.cov(), 1, t1, place) ;
00525     
00526     // On doit remettre les indices a la bonne place ...
00527     
00528     for (int i=0 ; i<valen ; i++)
00529     tipe.set(i) = t1.type_indice(i) ;
00530     tipe.set(place) *= -1 ;
00531     
00532     Tenseur res(*t1.mp, valen, tipe, t1.triad, auxi.metric, auxi.poids) ;
00533     res.set_etat_qcq() ;
00534     
00535     Itbl place_auxi(valen) ;
00536     place_auxi.set_etat_qcq() ;
00537     
00538     for (int i=0 ; i<res.n_comp ; i++) {
00539     
00540     Itbl place_res (res.donne_indices(i)) ;
00541     
00542     place_auxi.set(0) = place_res(place) ;
00543     for (int j=1 ; j<place+1 ; j++)
00544         place_auxi.set(j) = place_res(j-1)  ;
00545     place_res.set(place) = place_auxi(0) ;
00546     for (int j=place+1 ; j<valen ; j++)
00547          place_auxi.set(j) = place_res(j);
00548     
00549     
00550     res.set(place_res) = auxi(place_auxi) ;
00551     }
00552     return res ;
00553 }
00554 
00555 Tenseur manipule (const Tenseur& t1, const Metrique& met) {
00556     
00557     Tenseur* auxi ;
00558     Tenseur* auxi_old = new Tenseur(t1) ;
00559     
00560     for (int i=0 ; i<t1.valence ; i++) {
00561     auxi = new Tenseur(manipule(*auxi_old, met, i)) ;
00562     delete auxi_old ;
00563     auxi_old = new Tenseur(*auxi) ;
00564     delete auxi ;
00565     }
00566     
00567     Tenseur result(*auxi_old) ;
00568     delete auxi_old ;
00569     return result ;
00570 }
00571 
00572 
00573 Tenseur skxk(const Tenseur& source) {
00574     
00575     // Verification
00576     assert (source.valence > 0) ;
00577     assert (source.etat != ETATNONDEF) ;
00578     assert (*source.triad == source.mp->get_bvect_cart()) ;
00579     
00580     // Le resultat :
00581     int val_res = source.valence-1 ;
00582     Itbl tipe (val_res) ;
00583     tipe.set_etat_qcq() ;
00584     for (int i=0 ; i<val_res ; i++)
00585     tipe.set(i) = source.type_indice(i) ;
00586     
00587     
00588     Tenseur res (*source.mp, val_res, tipe, source.triad, source.metric,
00589          source.poids) ;
00590     
00591     if (source.etat == ETATZERO)
00592     res.set_etat_zero() ;
00593     else {
00594     res.set_etat_qcq() ;
00595     
00596     for (int i=0 ; i<res.n_comp ; i++) {
00597         Itbl indices_res (res.donne_indices(i)) ;
00598         Itbl indices_so (val_res+1) ;
00599         indices_so.set_etat_qcq() ;
00600         for (int j=0 ; j<val_res ; j++)
00601         indices_so.set(j) = indices_res(j) ;
00602         // x S_x
00603         // -----
00604         indices_so.set(val_res) = 0 ;
00605         Cmp resu(source(indices_so)) ;
00606         
00607         resu.mult_r() ;             // Multipl. by r
00608 
00609         // What follows is valid only for a mapping of class Map_radial : 
00610         assert( dynamic_cast<const Map_radial*>(source.get_mp()) != 0x0) ; 
00611 
00612         resu.va = (resu.va).mult_st() ;     // Multipl. by sin(theta)
00613         resu.va = (resu.va).mult_cp() ;     // Multipl. by cos(phi)
00614 
00615     // y S_y
00616     // -----
00617         indices_so.set(val_res) = 1 ;
00618         Cmp auxiliaire (source(indices_so)) ;
00619         
00620         auxiliaire.mult_r() ;               // Multipl. by r
00621 
00622         auxiliaire.va = (auxiliaire.va).mult_st() ;  // Multipl. by sin(theta)
00623         auxiliaire.va = (auxiliaire.va).mult_sp() ;  // Multipl. by sin(phi)
00624     
00625         resu = resu + auxiliaire ; 
00626     
00627         // z S_z
00628         // -----
00629         indices_so.set(val_res) = 2 ;
00630         auxiliaire = source(indices_so) ;
00631         
00632         auxiliaire.mult_r() ;               // Multipl. by r
00633 
00634         auxiliaire.va = (auxiliaire.va).mult_ct() ;     // Multipl. by cos(theta)
00635    
00636         resu = resu + auxiliaire ; 
00637     
00638         res.set(indices_res) = resu ;
00639         // The End 
00640         // -------
00641         }
00642     }
00643     return res ;
00644 }
00645 
00646 Tenseur flat_scalar_prod(const Tenseur& t1, const Tenseur& t2) {
00647     
00648     assert ((t1.etat != ETATNONDEF) && (t2.etat != ETATNONDEF)) ;
00649     // Verifs :
00650     assert (t1.mp == t2.mp) ;
00651     
00652     // Contraction possible ?
00653     if ( (t1.valence != 0) && (t2.valence != 0) ) {
00654         assert ( *(t1.get_triad()) == *(t2.get_triad()) ) ;
00655     }
00656     
00657     int val_res = t1.valence + t2.valence - 2;
00658     double poids_res = t1.poids + t2.poids ;
00659     poids_res = (fabs(poids_res) < 1.e-10 ? 0. : poids_res) ;
00660     const Metrique* met_res = 0x0 ;
00661     if (poids_res != 0.) {
00662       assert((t1.metric != 0x0) || (t2.metric != 0x0)) ;
00663       if (t1.metric != 0x0) met_res = t1.metric ;
00664       else met_res = t2.metric ;
00665     }
00666     Itbl tipe(val_res) ;
00667     tipe.set_etat_qcq() ;
00668 
00669     for (int i=0 ; i<t1.valence - 1 ; i++)
00670     tipe.set(i) = t1.type_indice(i) ;
00671     for (int i = t1.valence-1 ; i<val_res ; i++)
00672     tipe.set(i) = t2.type_indice(i-t1.valence+2) ;
00673     
00674     Tenseur res(*t1.mp, val_res, tipe, t1.triad, met_res, poids_res) ;
00675 
00676     // Cas particulier ou l'un des deux tenseurs est nul
00677     if ( (t1.etat == ETATZERO) || (t2.etat == ETATZERO) ) {
00678     res.set_etat_zero() ; 
00679     return res ; 
00680     }
00681 
00682     res.set_etat_qcq() ;
00683     
00684     Cmp work(t1.mp) ;
00685     
00686     // Boucle sur les composantes de res :
00687     
00688     Itbl jeux_indice_t1(t1.valence) ;
00689     Itbl jeux_indice_t2(t2.valence) ;
00690     jeux_indice_t1.set_etat_qcq() ;
00691     jeux_indice_t2.set_etat_qcq() ;
00692     
00693     for (int ir=0 ; ir<res.n_comp ; ir++) {    // Boucle sur les composantes
00694                            // du resultat 
00695 
00696     // Indices du resultat correspondant a la position ir : 
00697     Itbl jeux_indice_res = res.donne_indices(ir) ;
00698 
00699     // Premiers indices correspondant dans t1 : 
00700     for (int i=0 ; i<t1.valence - 1 ; i++) {
00701         jeux_indice_t1.set(i) = jeux_indice_res(i) ;
00702     }
00703     
00704     // Derniers indices correspondant dans t2 : 
00705     for (int i=1 ; i<t2.valence ; i++) {
00706         jeux_indice_t2.set(i) = jeux_indice_res(t1.valence+i-2) ;
00707     }
00708     
00709     work.set_etat_zero() ;
00710 
00711     // Sommation sur le dernier indice de t1 et le premier de t2 : 
00712     
00713     for (int j=0 ; j<3 ; j++) {
00714         jeux_indice_t1.set(t1.valence - 1) = j ;
00715         jeux_indice_t2.set(0) = j ;
00716         work = work + t1(jeux_indice_t1)*t2(jeux_indice_t2) ;
00717         }
00718         
00719     res.set(jeux_indice_res) = work ;
00720     
00721     }   // fin de la boucle sur les composantes du resultat
00722     
00723     return res ;
00724 }
00725 
00726 
00727 
00728 Tenseur flat_scalar_prod_desal(const Tenseur& t1, const Tenseur& t2) {
00729     
00730     assert ((t1.etat != ETATNONDEF) && (t2.etat != ETATNONDEF)) ;
00731     // Verifs :
00732     assert (t1.mp == t2.mp) ;
00733     
00734     // Contraction possible ?
00735     if ( (t1.valence != 0) && (t2.valence != 0) ) {
00736         assert ( *(t1.get_triad()) == *(t2.get_triad()) ) ;
00737     }
00738     
00739     int val_res = t1.valence + t2.valence - 2;
00740     double poids_res = t1.poids + t2.poids ;
00741     poids_res = (fabs(poids_res) < 1.e-10 ? 0. : poids_res) ;
00742     const Metrique* met_res = 0x0 ;
00743     if (poids_res != 0.) {
00744       assert((t1.metric != 0x0) || (t2.metric != 0x0)) ;
00745       if (t1.metric != 0x0) met_res = t1.metric ;
00746       else met_res = t2.metric ;
00747     }
00748     Itbl tipe(val_res) ;
00749     tipe.set_etat_qcq() ;
00750 
00751     for (int i=0 ; i<t1.valence - 1 ; i++)
00752     tipe.set(i) = t1.type_indice(i) ;
00753     for (int i = t1.valence-1 ; i<val_res ; i++)
00754     tipe.set(i) = t2.type_indice(i-t1.valence+2) ;
00755     
00756     Tenseur res(*t1.mp, val_res, tipe, t1.triad, met_res, poids_res) ;
00757 
00758     // Cas particulier ou l'un des deux tenseurs est nul
00759     if ( (t1.etat == ETATZERO) || (t2.etat == ETATZERO) ) {
00760     res.set_etat_zero() ; 
00761     return res ; 
00762     }
00763 
00764     res.set_etat_qcq() ;
00765     
00766     Cmp work(t1.mp) ;
00767     
00768     // Boucle sur les composantes de res :
00769     
00770     Itbl jeux_indice_t1(t1.valence) ;
00771     Itbl jeux_indice_t2(t2.valence) ;
00772     jeux_indice_t1.set_etat_qcq() ;
00773     jeux_indice_t2.set_etat_qcq() ;
00774     
00775     for (int ir=0 ; ir<res.n_comp ; ir++) {    // Boucle sur les composantes
00776                            // du resultat 
00777 
00778     // Indices du resultat correspondant a la position ir : 
00779     Itbl jeux_indice_res = res.donne_indices(ir) ;
00780 
00781     // Premiers indices correspondant dans t1 : 
00782     for (int i=0 ; i<t1.valence - 1 ; i++) {
00783         jeux_indice_t1.set(i) = jeux_indice_res(i) ;
00784     }
00785     
00786     // Derniers indices correspondant dans t2 : 
00787     for (int i=1 ; i<t2.valence ; i++) {
00788         jeux_indice_t2.set(i) = jeux_indice_res(t1.valence+i-2) ;
00789     }
00790     
00791     work.set_etat_zero() ;
00792 
00793     // Sommation sur le dernier indice de t1 et le premier de t2 : 
00794     
00795     for (int j=0 ; j<3 ; j++) {
00796         jeux_indice_t1.set(t1.valence - 1) = j ;
00797         jeux_indice_t2.set(0) = j ;
00798         work = work + t1(jeux_indice_t1) % t2(jeux_indice_t2) ;
00799         }
00800         
00801     res.set(jeux_indice_res) = work ;
00802     
00803     }   // fin de la boucle sur les composantes du resultat
00804     
00805     return res ;
00806 }
00807 
00808 
00809 Tenseur lie_derive (const Tenseur& t, const Tenseur& x, const Metrique* met)
00810 {
00811   assert ( (t.get_etat() != ETATNONDEF) && (x.get_etat() != ETATNONDEF) ) ;
00812   assert(x.get_valence() == 1) ;
00813   assert(x.get_type_indice(0) == CON) ;
00814   assert(x.get_poids() == 0.) ;
00815   assert(t.get_mp() == x.get_mp()) ;
00816  
00817   int val = t.get_valence() ;
00818   double poids = t.get_poids() ;
00819   Itbl tipe (val+1) ;
00820   tipe.set_etat_qcq() ;
00821   tipe.set(0) = COV ;
00822   Itbl tipx(2) ;
00823   tipx.set_etat_qcq() ;
00824   tipx.set(0) = COV ;
00825   tipx.set(1) = CON ;
00826   for (int i=0 ; i<val ; i++)
00827     tipe.set(i+1) = t.get_type_indice(i) ;
00828   Tenseur dt(*t.get_mp(), val+1, tipe, t.get_triad(), t.get_metric(), poids) ;
00829   Tenseur dx(*x.get_mp(), 2, tipx, x.get_triad()) ; 
00830   if (met == 0x0) {
00831     dx = x.gradient() ;
00832     dt = t.gradient() ;
00833   }
00834   else {
00835     dx = x.derive_cov(*met) ;
00836     dt = t.derive_cov(*met) ;
00837   }
00838   Tenseur resu(contract(x,0,dt,0)) ;
00839   Tenseur* auxi ;
00840   if ((val!=0)&&(t.get_etat()!=ETATZERO)&&(x.get_etat()!=ETATZERO)) {
00841     assert(t.get_triad()->identify() == x.get_triad()->identify()) ;
00842 
00843     for (int i=0 ; i<val ; i++) {
00844       if (t.get_type_indice(i) == COV) {
00845     auxi = new Tenseur(contract(t,i,dx,1)) ;
00846     
00847     Itbl indices_aux(val) ;
00848     indices_aux.set_etat_qcq() ;
00849     for (int j=0 ; j<resu.get_n_comp() ; j++) {
00850       
00851       Itbl indices (resu.donne_indices(j)) ;
00852       indices_aux.set(val-1) = indices(i) ;
00853       for (int idx=0 ; idx<val-1 ; idx++)
00854         if (idx<i)
00855           indices_aux.set(idx) = indices(idx) ;
00856         else
00857           indices_aux.set(idx) = indices(idx+1) ;
00858       
00859       resu.set(indices) += (*auxi)(indices_aux) ;
00860     }
00861       }   
00862       else {
00863     auxi = new Tenseur(contract(t,i,dx,0)) ;
00864     
00865     Itbl indices_aux(val) ;
00866     indices_aux.set_etat_qcq() ;
00867     
00868     //On range comme il faut :
00869     for (int j=0 ; j<resu.get_n_comp() ; j++) {
00870       
00871       Itbl indices (resu.donne_indices(j)) ;
00872       indices_aux.set(val-1) = indices(i) ;
00873       for (int idx=0 ; idx<val-1 ; idx++)
00874         if (idx<i)
00875           indices_aux.set(idx) = indices(idx) ;
00876         else
00877           indices_aux.set(idx) = indices(idx+1) ;
00878       resu.set(indices) -= (*auxi)(indices_aux) ;
00879     }
00880       }
00881       delete auxi ;
00882     }
00883   }
00884   if ((poids != 0.)&&(t.get_etat()!=ETATZERO)&&(x.get_etat()!=ETATZERO)) 
00885     resu = resu + poids*contract(dx,0,1)*t ;
00886 
00887   return resu ;
00888 }
00889 
00890 Tenseur sans_trace(const Tenseur& t, const Metrique& metre) 
00891 {
00892   assert(t.get_etat() != ETATNONDEF) ;
00893   assert(metre.get_etat() != ETATNONDEF) ;
00894   assert(t.get_valence() == 2) ;
00895 
00896   Tenseur resu(t) ;
00897   if (resu.get_etat() == ETATZERO) return resu ;
00898   assert(resu.get_etat() == ETATQCQ) ;
00899 
00900   int t0 = t.get_type_indice(0) ;
00901   int t1 = t.get_type_indice(1) ;
00902   Itbl mix(2) ;
00903   mix.set_etat_qcq() ;
00904   mix.set(0) = (t0 == t1 ? -t0 : t0) ;
00905   mix.set(1) = t1 ;
00906 
00907   Tenseur tmp(*t.get_mp(), 2, mix, *t.get_triad(), t.get_metric(), 
00908           t.get_poids()) ;
00909   if (t0 == t1)
00910     tmp = manipule(t, metre, 0) ;
00911   else
00912     tmp = t ;
00913 
00914   Tenseur trace(contract(tmp, 0, 1)) ;
00915 
00916   if (t0 == t1) {
00917     switch (t0) {
00918     case COV : {
00919       resu = resu - 1./3.*trace * metre.cov() ;
00920       break ;
00921     }
00922     case CON : {
00923       resu = resu - 1./3.*trace * metre.con() ; 
00924       break ;
00925     }
00926     default :
00927       cout << "Erreur bizarre dans sans_trace!" << endl ;
00928       abort() ;
00929       break ;
00930     }
00931   }
00932   else {
00933     Tenseur_sym delta(*t.get_mp(), 2, mix, *t.get_triad(), 
00934               t.get_metric(), t.get_poids()) ;
00935     delta.set_etat_qcq() ;
00936     for (int i=0; i<3; i++) 
00937       for (int j=i; j<3; j++)
00938     delta.set(i,j) = (i==j ? 1 : 0) ;
00939     resu = resu - trace/3. * delta ;
00940   }
00941   resu.set_std_base() ;
00942   return resu ;
00943 }
00944     
00945 
00946   

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