00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 char tenseur_sym_C[] = "$Header: /cvsroot/Lorene/C++/Source/Tenseur/tenseur_sym.C,v 1.6 2003/03/03 19:39:58 f_limousin Exp $" ;
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 #include <stdlib.h>
00076 #include <assert.h>
00077 #include <math.h>
00078
00079
00080 #include "tenseur.h"
00081 #include "metrique.h"
00082
00083
00084
00085
00086
00087
00088
00089 Tenseur_sym::Tenseur_sym(const Map& map, int val, const Itbl& tipe,
00090 const Base_vect& triad_i, const Metrique* met,
00091 double weight)
00092 : Tenseur(map, val, tipe, int(pow(3., val-2)) * 6, triad_i,
00093 met, weight) {
00094
00095 assert (val >= 2) ;
00096 }
00097
00098
00099
00100 Tenseur_sym::Tenseur_sym(const Map& map, int val, int tipe,
00101 const Base_vect& triad_i, const Metrique* met,
00102 double weight)
00103 : Tenseur(map, val, tipe, int(pow(3., val-2)) * 6, triad_i,
00104 met, weight) {
00105
00106 assert (val >= 2) ;
00107 }
00108
00109
00110
00111 Tenseur_sym::Tenseur_sym (const Tenseur_sym& source) :
00112 Tenseur (*source.mp, source.valence, source.type_indice,
00113 int(pow(3., source.valence-2)*6), *(source.triad), source.metric,
00114 source.poids) {
00115
00116 assert (valence >= 2) ;
00117 for (int i=0 ; i<n_comp ; i++) {
00118 int place_source = source.donne_place(donne_indices(i)) ;
00119 if (source.c[place_source] == 0x0)
00120 c[i] = 0x0 ;
00121 else
00122 c[i] = new Cmp (*source.c[place_source]) ;
00123 }
00124 etat = source.etat ;
00125 assert(source.met_depend != 0x0) ;
00126 assert(source.p_derive_cov != 0x0) ;
00127 assert(source.p_derive_con != 0x0) ;
00128 assert(source.p_carre_scal != 0x0) ;
00129
00130 if (source.p_gradient != 0x0)
00131 p_gradient = new Tenseur_sym (*source.p_gradient) ;
00132
00133 for (int i=0; i<N_MET_MAX; i++) {
00134 met_depend[i] = source.met_depend[i] ;
00135 if (met_depend[i] != 0x0) {
00136
00137 set_dependance (*met_depend[i]) ;
00138
00139 if (source.p_derive_cov[i] != 0x0)
00140 p_derive_cov[i] = new Tenseur (*source.p_derive_cov[i]) ;
00141 if (source.p_derive_con[i] != 0x0)
00142 p_derive_con[i] = new Tenseur (*source.p_derive_con[i]) ;
00143 if (source.p_carre_scal[i] != 0x0)
00144 p_carre_scal[i] = new Tenseur (*source.p_carre_scal[i]) ;
00145 }
00146 }
00147 }
00148
00149
00150
00151
00152 Tenseur_sym::Tenseur_sym (const Tenseur& source) :
00153 Tenseur (*source.mp, source.valence, source.type_indice,
00154 int(pow(3., source.valence-2)*6), *(source.triad), source.metric,
00155 source.poids) {
00156
00157 assert (valence >= 2) ;
00158
00159 for (int i=0 ; i<n_comp ; i++) {
00160 int place_source = source.donne_place(donne_indices(i)) ;
00161 if (source.c[place_source] == 0x0)
00162 c[i] = 0x0 ;
00163 else
00164 c[i] = new Cmp (*source.c[place_source]) ;
00165 }
00166
00167 etat = source.etat ;
00168
00169 assert(source.met_depend != 0x0) ;
00170 assert(source.p_derive_cov != 0x0) ;
00171 assert(source.p_derive_con != 0x0) ;
00172 assert(source.p_carre_scal != 0x0) ;
00173
00174 if (source.p_gradient != 0x0)
00175 p_gradient = new Tenseur (*source.p_gradient) ;
00176
00177 }
00178
00179
00180
00181
00182 Tenseur_sym::Tenseur_sym(const Map& map, const Base_vect& triad_i, FILE* fd,
00183 const Metrique* met)
00184 : Tenseur(map, triad_i, fd, met) {
00185
00186 assert (valence >= 2) ;
00187 assert (n_comp == int(pow(3., valence-2))*6) ;
00188 }
00189
00190
00191
00192
00193
00194 Tenseur_sym::~Tenseur_sym() {}
00195
00196
00197
00198
00199
00200 int Tenseur_sym::donne_place (const Itbl& idx) const {
00201
00202 assert (idx.get_ndim() == 1) ;
00203 assert (idx.get_dim(0) == valence) ;
00204 for (int i=0 ; i<valence ; i++)
00205 assert ((idx(i) >= 0) && (idx(i) < 3)) ;
00206
00207
00208
00209 int last = idx(valence-1) ;
00210 int lastm1 = idx(valence-2) ;
00211 if (last < lastm1) {
00212 int auxi = last ;
00213 last = lastm1 ;
00214 lastm1 = auxi ;
00215 }
00216
00217 int place_fin ;
00218 switch (lastm1) {
00219 case 0 : {
00220 place_fin = last ;
00221 break ;
00222 }
00223 case 1 : {
00224 place_fin = 2+last ;
00225 break ;
00226 }
00227 case 2 : {
00228 place_fin = 5 ;
00229 break ;
00230 }
00231 default : {
00232 abort() ;
00233 }
00234 }
00235
00236 int res = 0 ;
00237 for (int i=0 ; i<valence-2 ; i++)
00238 res = 3*res+idx(i) ;
00239
00240 res = 6*res + place_fin ;
00241
00242 return res ;
00243 }
00244
00245 Itbl Tenseur_sym::donne_indices (int place) const {
00246 Itbl res(valence) ;
00247 res.set_etat_qcq() ;
00248 assert ((place>=0) && (place<n_comp)) ;
00249
00250 int reste = div(place, 6).rem ;
00251 place = int((place-reste)/6) ;
00252
00253 for (int i=valence-3 ; i>=0 ; i--) {
00254 res.set(i) = div(place, 3).rem ;
00255 place = int((place-res(i))/3) ;
00256 }
00257
00258 if (reste<3) {
00259 res.set(valence-2) = 0 ;
00260 res.set(valence-1) = reste ;
00261 }
00262
00263 if ((reste>2) && (reste<5)) {
00264 res.set(valence-2) = 1 ;
00265 res.set(valence-1) = reste - 2 ;
00266 }
00267
00268 if (reste == 5) {
00269 res.set(valence-2) = 2 ;
00270 res.set(valence-1) = 2 ;
00271 }
00272
00273 return res ;
00274 }
00275
00276 void Tenseur_sym::operator= (const Tenseur& t) {
00277
00278 assert (valence == t.get_valence()) ;
00279
00280 triad = t.triad ;
00281 poids = t.poids ;
00282 metric = t.metric ;
00283
00284 for (int i=0 ; i<valence ; i++)
00285 assert (type_indice(i) == t.type_indice(i)) ;
00286
00287 switch (t.get_etat()) {
00288 case ETATNONDEF: {
00289 set_etat_nondef() ;
00290 break ;
00291 }
00292
00293 case ETATZERO: {
00294 set_etat_zero() ;
00295 break ;
00296 }
00297
00298 case ETATQCQ: {
00299 set_etat_qcq() ;
00300 for (int i=0 ; i<n_comp ; i++) {
00301 int place_t = t.donne_place(donne_indices(i)) ;
00302 if (t.c[place_t] == 0x0)
00303 c[i] = 0x0 ;
00304 else
00305 *c[i] = *t.c[place_t] ;
00306 }
00307 break ;
00308 }
00309
00310 default: {
00311 cout << "Unknown state in Tenseur_sym::operator= " << endl ;
00312 abort() ;
00313 break ;
00314 }
00315 }
00316 }
00317
00318 void Tenseur_sym::fait_gradient () const {
00319
00320 assert (etat != ETATNONDEF) ;
00321
00322 if (p_gradient != 0x0)
00323 return ;
00324 else {
00325
00326
00327 Itbl tipe (valence+1) ;
00328 tipe.set_etat_qcq() ;
00329 tipe.set(0) = COV ;
00330 for (int i=0 ; i<valence ; i++)
00331 tipe.set(i+1) = type_indice(i) ;
00332
00333
00334
00335 assert(*triad == mp->get_bvect_cart()) ;
00336
00337 p_gradient = new Tenseur_sym(*mp, valence+1, tipe,
00338 mp->get_bvect_cart(), metric, poids) ;
00339
00340
00341 if (etat == ETATZERO)
00342 p_gradient->set_etat_zero() ;
00343 else {
00344 p_gradient->set_etat_qcq() ;
00345
00346
00347 Itbl indices_source(valence) ;
00348 indices_source.set_etat_qcq() ;
00349
00350 for (int j=0 ; j<p_gradient->n_comp ; j++) {
00351
00352 Itbl indices_res(p_gradient->donne_indices(j)) ;
00353
00354 for (int m=0 ; m<valence ; m++)
00355 indices_source.set(m) = indices_res(m+1) ;
00356
00357 p_gradient->set(indices_res) =
00358 (*this)(indices_source).deriv(indices_res(0)) ;
00359 }
00360 }
00361 }
00362 }
00363
00364
00365 void Tenseur_sym::fait_derive_cov (const Metrique& metre, int ind) const {
00366
00367 assert (etat != ETATNONDEF) ;
00368 assert (valence != 0) ;
00369
00370 if (p_derive_cov[ind] != 0x0)
00371 return ;
00372 else {
00373 p_derive_cov[ind] = new Tenseur_sym (gradient()) ;
00374
00375 if ((valence != 0) && (etat != ETATZERO)) {
00376
00377 assert( *(metre.gamma().get_triad()) == *triad ) ;
00378
00379 Tenseur* auxi ;
00380 for (int i=0 ; i<valence ; i++) {
00381
00382 if (type_indice(i) == COV) {
00383 auxi = new Tenseur(contract(metre.gamma(), 0,(*this), i)) ;
00384
00385 Itbl indices_gamma(p_derive_cov[ind]->valence) ;
00386 indices_gamma.set_etat_qcq() ;
00387
00388 for (int j=0 ; j<p_derive_cov[ind]->n_comp ; j++) {
00389
00390 Itbl indices (p_derive_cov[ind]->donne_indices(j)) ;
00391 indices_gamma.set(0) = indices(0) ;
00392 indices_gamma.set(1) = indices(i+1) ;
00393 for (int idx=2 ; idx<p_derive_cov[ind]->valence ; idx++)
00394 if (idx<=i+1)
00395 indices_gamma.set(idx) = indices(idx-1) ;
00396 else
00397 indices_gamma.set(idx) = indices(idx) ;
00398
00399 p_derive_cov[ind]->set(indices) -= (*auxi)(indices_gamma) ;
00400 }
00401 }
00402 else {
00403 auxi = new Tenseur(contract(metre.gamma(), 1, (*this), i)) ;
00404
00405 Itbl indices_gamma(p_derive_cov[ind]->valence) ;
00406 indices_gamma.set_etat_qcq() ;
00407
00408
00409 for (int j=0 ; j<p_derive_cov[ind]->n_comp ; j++) {
00410
00411 Itbl indices (p_derive_cov[ind]->donne_indices(j)) ;
00412 indices_gamma.set(0) = indices(i+1) ;
00413 indices_gamma.set(1) = indices(0) ;
00414 for (int idx=2 ; idx<p_derive_cov[ind]->valence ; idx++)
00415 if (idx<=i+1)
00416 indices_gamma.set(idx) = indices(idx-1) ;
00417 else
00418 indices_gamma.set(idx) = indices(idx) ;
00419 p_derive_cov[ind]->set(indices) += (*auxi)(indices_gamma) ;
00420 }
00421 }
00422 delete auxi ;
00423 }
00424 }
00425 if ((poids != 0.)&&(etat != ETATZERO))
00426 *p_derive_cov[ind] = *p_derive_cov[ind] -
00427 poids*contract(metre.gamma(), 0, 2) * (*this) ;
00428
00429 }
00430 }
00431
00432
00433
00434 void Tenseur_sym::fait_derive_con (const Metrique& metre, int ind) const {
00435
00436 if (p_derive_con[ind] != 0x0)
00437 return ;
00438 else {
00439
00440 if (valence != 0)
00441 p_derive_con[ind] = new Tenseur_sym
00442 (contract(metre.con(), 1, derive_cov(metre), 0)) ;
00443
00444 else
00445 p_derive_con[ind] = new Tenseur_sym
00446 (contract(metre.con(), 1, gradient(), 0)) ;
00447 }
00448 }