KADATH
metric.cpp
1 /*
2  Copyright 2017 Philippe Grandclement
3 
4  This file is part of Kadath.
5 
6  Kadath is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  Kadath is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with Kadath. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "space.hpp"
21 #include "tensor.hpp"
22 #include "metric.hpp"
23 #include "term_eq.hpp"
24 #include "scalar.hpp"
25 #include "tensor_impl.hpp"
26 #include "system_of_eqs.hpp"
27 namespace Kadath {
28 
29  Metric::Metric (const Space& sp) :
30  espace {sp}, syst{nullptr},
31  p_met_cov{espace.get_nbr_domains()}, p_met_con{espace.get_nbr_domains()},
32  p_christo{espace.get_nbr_domains()}, p_riemann{espace.get_nbr_domains()},
33  p_ricci_tensor{espace.get_nbr_domains()}, p_ricci_scalar{espace.get_nbr_domains()},
34  p_dirac{espace.get_nbr_domains()}, p_det_cov{espace.get_nbr_domains()},
35  type_tensor{0}
36  {
37  for (int i=0 ; i<espace.get_nbr_domains() ; i++) {
38  p_met_con[i] = nullptr ;
39  p_met_cov[i] = nullptr ;
40  p_christo[i] = nullptr ;
41  p_riemann[i] = nullptr ;
42  p_ricci_tensor[i] = nullptr ;
43  p_ricci_scalar[i] = nullptr ;
44  p_dirac[i] = nullptr ;
45  p_det_cov[i] = nullptr ;
46  }
47  }
48 
49  Metric::Metric (const Metric& so) :
50  espace {so.espace}, syst{so.syst},
51  p_met_cov{espace.get_nbr_domains()}, p_met_con{espace.get_nbr_domains()},
52  p_christo{espace.get_nbr_domains()}, p_riemann{espace.get_nbr_domains()},
53  p_ricci_tensor{espace.get_nbr_domains()}, p_ricci_scalar{espace.get_nbr_domains()},
54  p_dirac{espace.get_nbr_domains()}, p_det_cov{espace.get_nbr_domains()},
55  type_tensor{so.type_tensor}
56  {
57  for (int i=0 ; i<espace.get_nbr_domains() ; i++) {
58  p_met_cov[i] = (so.p_met_cov[i]==nullptr) ? nullptr : new Term_eq{*so.p_met_cov[i]} ;
59  p_met_con[i] = (so.p_met_con[i]==nullptr) ? nullptr : new Term_eq{*so.p_met_con[i]} ;
60  p_christo[i] = (so.p_christo[i]==nullptr) ? nullptr : new Term_eq{*so.p_christo[i]} ;
61  p_riemann[i] = (so.p_riemann[i]==nullptr) ? nullptr : new Term_eq{*so.p_riemann[i]} ;
62  p_ricci_tensor[i] = (so.p_ricci_tensor[i]==nullptr) ? nullptr : new Term_eq{*so.p_ricci_tensor[i]} ;
63  p_ricci_scalar[i] = (so.p_ricci_scalar[i]==nullptr) ? nullptr : new Term_eq{*so.p_ricci_scalar[i]} ;
64  p_dirac[i] = (so.p_dirac[i]==nullptr) ? nullptr : new Term_eq{*so.p_dirac[i]} ;
65  p_det_cov[i] = (so.p_det_cov[i]==nullptr) ? nullptr : new Term_eq{*so.p_det_cov[i]} ;
66  }
67  }
68 
70  for (int i=0 ; i<espace.get_nbr_domains() ; i++) {
71  safe_delete(p_met_cov[i]);
72  safe_delete(p_met_con[i]);
73  safe_delete(p_christo[i]);
74  safe_delete(p_riemann[i]);
75  safe_delete(p_ricci_tensor[i]);
76  safe_delete(p_ricci_scalar[i]);
77  safe_delete(p_dirac[i]);
78  safe_delete(p_det_cov[i]);
79  }
80  }
81 
82  void Metric::update(int i) {
83  if (type_tensor == CON) {
84  if (p_met_con[i]!=nullptr) compute_con(i) ;
85  if (p_met_cov[i]!=nullptr) compute_cov(i) ;
86  }
87  else {
88  if (p_met_cov[i]!=nullptr) compute_cov(i) ;
89  if (p_met_con[i]!=nullptr) compute_con(i) ;
90  }
91  if (p_det_cov[i]!=nullptr) compute_det_cov(i) ;
92  if (p_christo[i]!=nullptr) compute_christo(i) ;
93  if (p_riemann[i]!=nullptr) compute_riemann(i) ;
94  if (p_dirac[i]!=nullptr) compute_dirac(i) ;
95  if (p_ricci_tensor[i]!=nullptr) compute_ricci_tensor(i) ;
96  if (p_ricci_scalar[i]!=nullptr) compute_ricci_scalar(i) ;
97  }
98 
99  void Metric::update() {
100  for (int i=0 ; i<espace.get_nbr_domains() ; i++) update(i) ;
101  }
102 
103  const Term_eq* Metric::give_term (int dd, int type) const {
104  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
105  switch (type) {
106  case COV :
107  if (p_met_cov[dd]==nullptr) compute_cov (dd) ;
108  return p_met_cov[dd] ;
109  case CON :
110  if (p_met_con[dd]==nullptr) compute_con (dd) ;
111  return p_met_con[dd] ;
112  default :
113  cerr << "Unknown type of indice in Metric::give_term" << endl ;
114  abort() ;
115  }
116  }
117 
118  int Metric::give_type (int dd) const {
119  if (p_met_cov[dd]==nullptr)
120  compute_cov(dd) ;
121  return (p_met_cov[dd]->val_t->get_basis().get_basis(dd)) ;
122  }
123 
124  const Term_eq* Metric::give_christo (int dd) const {
125  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
126  if (p_christo[dd]==nullptr)
127  compute_christo(dd) ;
128  return p_christo[dd] ;
129  }
130 
131  const Term_eq* Metric::give_riemann (int dd) const {
132  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
133  if (p_riemann[dd]==nullptr)
134  compute_riemann(dd) ;
135  return p_riemann[dd] ;
136  }
137 
138  const Term_eq* Metric::give_ricci_tensor (int dd) const {
139  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
140  if (p_ricci_tensor[dd]==nullptr)
142  return p_ricci_tensor[dd] ;
143  }
144 
145  const Term_eq* Metric::give_ricci_scalar (int dd) const {
146  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
147  if (p_ricci_scalar[dd]==nullptr)
149  return p_ricci_scalar[dd] ;
150  }
151 
152  const Term_eq* Metric::give_dirac (int dd) const {
153  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
154  if (p_dirac[dd]==nullptr)
155  compute_dirac(dd) ;
156  return p_dirac[dd] ;
157  }
158 
159  const Term_eq* Metric::give_det_cov (int dd) const {
160  assert ((dd>=0) && (dd<espace.get_nbr_domains())) ;
161  if (p_det_cov[dd]==nullptr)
162  compute_det_cov(dd) ;
163  return p_det_cov[dd] ;
164  }
165 
166 
168  cerr << "No background metric defined" << endl ;
169  abort() ;
170  }
171 
172  Term_eq Metric::derive_partial (int type_der, char ind_der, const Term_eq& so) const {
173 
174  int dom = so.get_dom() ;
175 
176  if (type_tensor == CON) {
177  if (p_met_con[dom]==nullptr)
178  compute_con(dom) ;
179  if (p_met_cov[dom]==nullptr)
180  compute_cov(dom) ;
181  }
182  else {
183  if (p_met_cov[dom]==nullptr)
184  compute_cov(dom) ;
185  if (p_met_con[dom]==nullptr)
186  compute_con(dom) ;
187  }
188 
189  // so must be tensor :
190  if (so.get_type_data()!=TERM_T) {
191  cerr << "Metric::derive partial only defined for tensor data" << endl ;
192  abort() ;
193  }
194 
195  // Check that the triad is good :
196  if ((so.val_t->get_valence()>0) && (so.val_t->get_basis().get_basis(dom) != CARTESIAN_BASIS)) {
197  cerr << "Metric::derive_partial only defined for tensor on cartesian triad" << endl ;
198  abort() ;
199  }
200 
201 
202  bool doder = ((so.der_t==nullptr) || (p_met_cov[dom]->der_t==nullptr) || (p_met_cov[dom]->der_t==nullptr)) ? false : true ;
203 
204  assert ((type_der==COV) || (type_der==CON)) ;
205  int val_res = so.val_t->get_valence() + 1 ;
206 
207  bool doname = true ;
208  if (so.val_t->get_valence()>0)
209  if (!so.val_t->is_name_affected())
210  doname = false;
211 
212  Array<int> type_ind (val_res) ;
213  type_ind.set(0) = COV ;
214  for (int i=1 ; i<val_res ; i++)
215  type_ind.set(i) = so.val_t->get_index_type(i-1) ;
216 
217  // Need for summation ?
218  bool need_sum = false ;
219  if (doname)
220  for (int i=1 ; i<val_res ; i++)
221  if (ind_der== so.val_t->get_name_ind()[i-1])
222  need_sum = true ;
223 
224  // Tensor for val
225  Tensor auxi_val (espace, val_res, type_ind, so.val_t->get_basis()) ;
226  // Set the names of the indices :
227  if (doname) {
228  auxi_val.set_name_affected() ;
229  auxi_val.set_name_ind(0, ind_der) ;
230  for (int i=1 ; i<val_res ; i++)
231  auxi_val.set_name_ind(i, so.val_t->get_name_ind()[i-1]) ;
232  }
233 
234  //Loop on the components :
235  Index pos_auxi(auxi_val) ;
236  Index pos_so (*so.val_t) ;
237  do {
238  for (int i=0 ; i<val_res-1 ; i++)
239  pos_so.set(i) = pos_auxi(i+1) ;
240  auxi_val.set(pos_auxi).set_domain(dom) = (*so.val_t)(pos_so)(dom).der_abs(pos_auxi(0)+1) ;
241  }
242  while (pos_auxi.inc()) ;
243 
244  if (!doder) {
245  // No need for derivative :
246  Term_eq auxi (dom, auxi_val) ;
247  // If derive contravariant : manipulate first indice :
248  if (type_der==CON)
249  manipulate_ind (auxi, 0) ;
250 
251  if (!need_sum)
252  return auxi ;
253  else
254  return Term_eq (dom, auxi.val_t->do_summation_one_dom(dom)) ;
255  }
256  else {
257  // Need to compute the derivative :
258  // Tensor for der
259  Tensor auxi_der (espace, val_res, type_ind, so.der_t->get_basis()) ;
260  // Set the names of the indices :
261  auxi_der.set_name_affected() ;
262  auxi_der.set_name_ind(0, ind_der) ;
263  for (int i=1 ; i<val_res ; i++)
264  auxi_der.set_name_ind(i, so.der_t->get_name_ind()[i-1]) ;
265 
266  //Loop on the components :
267  Index pos_auxi_der(auxi_der) ;
268  do {
269  for (int i=0 ; i<val_res-1 ; i++)
270  pos_so.set(i) = pos_auxi_der(i+1) ;
271  auxi_der.set(pos_auxi_der).set_domain(dom) = (*so.der_t)(pos_so)(dom).der_abs(pos_auxi_der(0)+1) ;
272  }
273  while (pos_auxi_der.inc()) ;
274 
275  // Need for derivative :
276  Term_eq auxi (dom, auxi_val, auxi_der) ;
277  // If derive contravariant : manipulate first indice :
278  if (type_der==CON)
279  manipulate_ind (auxi, 0) ;
280 
281  if (!need_sum)
282  return auxi ;
283  else
284  return Term_eq (dom, auxi.val_t->do_summation_one_dom(dom),
285  auxi.der_t->do_summation_one_dom(dom)) ;
286  }
287 
288  }
289 
290  Term_eq Metric::derive (int type_der, char ind_der, const Term_eq& so) const {
291 
292  // The partial derivative part
293  Term_eq res (derive_partial (type_der, ind_der, so)) ;
294 
295  // Add the part containing the Christoffel :
296  //Must find a name for summation on Christofel :
297  bool found = false ;
298  int start = 97 ;
299  do {
300  bool same = false ;
301  if (ind_der==char(start))
302  same = true ;
303  for (int i=0 ; i<so.val_t->get_valence() ; i++)
304  if (so.val_t->get_name_ind()[i]==char(start))
305  same = true ;
306  if (!same)
307  found = true ;
308  else
309  start ++ ;
310  }
311  while ((!found) && (start<123)) ;
312  if (!found) {
313  cerr << "Trouble with indices in derive (you are not using tensors of order > 24, are you ?)" << endl ;
314  abort() ;
315  }
316  char name_sum = char(start) ;
317 
318  int dd = so.get_dom() ;
319  if (p_christo[dd]==nullptr)
320  compute_christo(dd) ;
321  bool doder = ((so.der_t==nullptr) || (p_christo[dd]->der_t==nullptr)) ? false : true ;
322 
323  //loop on the components of so :
324  for (int cmp=0 ; cmp<so.val_t->get_valence() ; cmp ++) {
325 
326  int genre_indice = so.val_t->get_index_type(cmp) ;
327 
328  //Affecte names on the Christoffels :
329  p_christo[dd]->val_t->set_name_affected() ;
330  p_christo[dd]->val_t->set_name_ind(0, ind_der) ;
331  if (genre_indice==COV) {
332  p_christo[dd]->val_t->set_name_ind(1, so.val_t->get_name_ind()[cmp]) ;
333  p_christo[dd]->val_t->set_name_ind(2, name_sum) ;
334  }
335  else {
336  p_christo[dd]->val_t->set_name_ind(2, so.val_t->get_name_ind()[cmp]) ;
337  p_christo[dd]->val_t->set_name_ind(1, name_sum) ;
338  }
339 
340  if (doder) {
341  p_christo[dd]->der_t->set_name_affected() ;
342  p_christo[dd]->der_t->set_name_ind(0, ind_der) ;
343  if (genre_indice==COV) {
344  p_christo[dd]->der_t->set_name_ind(1, so.der_t->get_name_ind()[cmp]) ;
345  p_christo[dd]->der_t->set_name_ind(2, name_sum) ;
346  }
347  else {
348  p_christo[dd]->der_t->set_name_ind(2, so.der_t->get_name_ind()[cmp]) ;
349  p_christo[dd]->der_t->set_name_ind(1, name_sum) ;
350  }
351  }
352 
353  Term_eq auxi_christ (*p_christo[dd]) ;
354 
355  if (type_der==CON)
356  manipulate_ind(auxi_christ, 0) ;
357 
358  // Check if one inner summation is needed :
359  bool need_sum = false ;
360  char const * ind = p_christo[dd]->val_t->get_name_ind() ;
361  if ((ind[0]==ind[2]) || (ind[1]==ind[2]) || (ind[0]==ind[1]))
362  need_sum = true ;
363 
364  Term_eq* christ ;
365  if (need_sum)
366  if (!doder)
367  christ = new Term_eq (dd, auxi_christ.val_t->do_summation_one_dom(dd)) ;
368  else
369  christ = new Term_eq (dd, auxi_christ.val_t->do_summation_one_dom(dd),
370  auxi_christ.der_t->do_summation_one_dom(dd)) ;
371  else
372  christ = new Term_eq (auxi_christ) ;
373 
374  // Affecte names on the field :
375  Term_eq copie (so) ;
376  copie.val_t->set_name_affected() ;
377  for (int i=0 ; i<so.val_t->get_valence() ; i++)
378  if (i!=cmp)
379  copie.val_t->set_name_ind(i, so.val_t->get_name_ind()[i]) ;
380  else
381  copie.val_t->set_name_ind(i, name_sum) ;
382  if (doder) {
383  copie.der_t->set_name_affected() ;
384  for (int i=0 ; i<so.der_t->get_valence() ; i++)
385  if (i!=cmp)
386  copie.der_t->set_name_ind(i, so.der_t->get_name_ind()[i]) ;
387  else
388  copie.der_t->set_name_ind(i, name_sum) ;
389  }
390 
391  Term_eq part_christo ((*christ)*copie) ;
392  delete christ ;
393 
394  if (genre_indice==CON)
395  res = res + part_christo ;
396  else
397  res = res - part_christo ;
398  }
399  return res ;
400  }
401 
402  Term_eq Metric::derive_flat (int, char, const Term_eq&) const {
403  cerr << "derive_flat not implemented for this type of metric (yet)" << endl ;
404  abort() ;
405  }
406 
407  void Metric::compute_christo (int dd) const {
408 
409  if (type_tensor == CON) {
410  if (p_met_con[dd]==nullptr)
411  compute_con(dd) ;
412  if (p_met_cov[dd]==nullptr)
413  compute_cov(dd) ;
414  }
415  else {
416  if (p_met_cov[dd]==nullptr)
417  compute_cov(dd) ;
418  if (p_met_con[dd]==nullptr)
419  compute_con(dd) ;
420  }
421 
422  // Get the conformal factor
423  bool doder = ((p_met_con[dd]->der_t==nullptr) || (p_met_cov[dd]->der_t==nullptr)) ? false : true ;
424 
425  Array<int> type_ind (3) ;
426  type_ind.set(0) = COV ; type_ind.set(1) = COV ; type_ind.set(2) = CON ;
427  Tensor res_val (espace, 3, type_ind, p_met_con[dd]->val_t->get_basis()) ;
428  Tensor res_der (espace, 3, type_ind, p_met_con[dd]->val_t->get_basis()) ;
429 
430  res_val = 0 ;
431  res_der = 0 ;
432 
433  Index pos (res_val) ;
434  do {
435  Val_domain cmpval(espace.get_domain(dd)) ;
436  cmpval = 0 ;
437 
438  for (int l=1 ; l<=espace.get_ndim() ; l++)
439  cmpval += 0.5*(
440  (*p_met_con[dd]->val_t)(pos(2)+1,l)(dd)*((*p_met_cov[dd]->val_t)(pos(1)+1,l)(dd).der_abs(pos(0)+1) +
441  (*p_met_cov[dd]->val_t)(pos(0)+1,l)(dd).der_abs(pos(1)+1) - (*p_met_cov[dd]->val_t)(pos(1)+1,pos(0)+1)(dd).der_abs(l))) ;
442 
443  res_val.set(pos).set_domain(dd) = cmpval ;
444 
445  if (doder) {
446  Val_domain cmpder(espace.get_domain(dd)) ;
447  cmpder = 0 ;
448 
449  for (int l=1 ; l<=espace.get_ndim() ; l++)
450  cmpder += 0.5*(
451  (*p_met_con[dd]->der_t)(pos(2)+1,l)(dd)*((*p_met_cov[dd]->val_t)(pos(1)+1,l)(dd).der_abs(pos(0)+1) +
452  (*p_met_cov[dd]->val_t)(pos(0)+1,l)(dd).der_abs(pos(1)+1) - (*p_met_cov[dd]->val_t)(pos(1)+1,pos(0)+1)(dd).der_abs(l)))
453  + 0.5*(
454  (*p_met_con[dd]->val_t)(pos(2)+1,l)(dd)*((*p_met_cov[dd]->der_t)(pos(1)+1,l)(dd).der_abs(pos(0)+1) +
455  (*p_met_cov[dd]->der_t)(pos(0)+1,l)(dd).der_abs(pos(1)+1) - (*p_met_cov[dd]->der_t)(pos(1)+1,pos(0)+1)(dd).der_abs(l))) ;
456 
457  res_der.set(pos).set_domain(dd) = cmpder ;
458  }
459  }
460  while (pos.inc()) ;
461 
462  if (!doder) {
463  if (p_christo[dd]==nullptr)
464  p_christo[dd] = new Term_eq(dd, res_val) ;
465  else
466  *p_christo[dd] = Term_eq (dd, res_val) ;
467  }
468  else {
469  if (p_christo[dd]==nullptr)
470  p_christo[dd] = new Term_eq(dd, res_val, res_der) ;
471  else
472  *p_christo[dd] = Term_eq(dd, res_val, res_der) ;
473  }
474  }
475 
476  void Metric::compute_riemann (int dd) const {
477  // Need christoffels
478  if (p_christo[dd]==nullptr)
479  compute_christo(dd) ;
480 
481  // Get the conformal factor
482  bool doder = ((p_met_con[dd]->der_t==nullptr) || (p_met_cov[dd]->der_t==nullptr)) ? false : true ;
483  Array<int> indices (4) ;
484  indices.set(0) = CON ; indices.set(1) = COV ; indices.set(2) = COV ; indices.set(3) = COV ;
485  Tensor res_val (espace, 4, indices, p_met_con[dd]->val_t->get_basis()) ;
486  Tensor res_der (espace, 4, indices, p_met_con[dd]->val_t->get_basis()) ;
487 
488  Index pos (res_val) ;
489  do {
490  Val_domain cmpval (espace.get_domain(dd)) ;
491 
492  cmpval = (*p_christo[dd]->val_t)(pos(1)+1,pos(3)+1,pos(0)+1)(dd).der_abs(pos(2)+1) -
493  (*p_christo[dd]->val_t)(pos(1)+1, pos(2)+1, pos(0)+1)(dd).der_abs(pos(3)+1) ;
494 
495  for (int m=1 ; m<=espace.get_ndim() ; m++)
496  cmpval += (*p_christo[dd]->val_t)(pos(2)+1,m, pos(0)+1)(dd)*(*p_christo[dd]->val_t)(pos(1)+1,pos(3)+1,m)(dd)
497  - (*p_christo[dd]->val_t)(pos(3)+1,m,pos(0)+1)(dd)*(*p_christo[dd]->val_t)(pos(1)+1,pos(2)+1,m)(dd) ;
498  res_val.set(pos).set_domain(dd) = cmpval ;
499 
500  if (doder) {
501  Val_domain cmpder(espace.get_domain(dd)) ;
502 
503  cmpder = (*p_christo[dd]->der_t)(pos(1)+1,pos(3)+1,pos(0)+1)(dd).der_abs(pos(2)+1) -
504  (*p_christo[dd]->der_t)(pos(1)+1, pos(2)+1, pos(0)+1)(dd).der_abs(pos(3)+1) ;
505 
506  for (int m=1 ; m<=espace.get_ndim() ; m++)
507  cmpder += (*p_christo[dd]->der_t)(pos(2)+1,m, pos(0)+1)(dd)*(*p_christo[dd]->val_t)(pos(1)+1,pos(3)+1,m)(dd)
508  + (*p_christo[dd]->val_t)(pos(2)+1,m, pos(0)+1)(dd)*(*p_christo[dd]->der_t)(pos(1)+1,pos(3)+1,m)(dd)
509  - (*p_christo[dd]->der_t)(pos(3)+1,m,pos(0)+1)(dd)*(*p_christo[dd]->val_t)(pos(1)+1,pos(2)+1,m)(dd)
510  - (*p_christo[dd]->val_t)(pos(3)+1,m,pos(0)+1)(dd)*(*p_christo[dd]->der_t)(pos(1)+1,pos(2)+1,m)(dd) ;
511 
512  res_der.set(pos).set_domain(dd) = cmpder ;
513  }
514  }
515  while (pos.inc()) ;
516 
517  if (!doder) {
518  if (p_riemann[dd]==nullptr)
519  p_riemann[dd] = new Term_eq(dd, res_val) ;
520  else
521  *p_riemann[dd] = Term_eq (dd, res_val) ;
522  }
523  else {
524  if (p_riemann[dd]==nullptr)
525  p_riemann[dd] = new Term_eq(dd, res_val, res_der) ;
526  else
527  *p_riemann[dd] = Term_eq(dd, res_val, res_der) ;
528  }
529  }
530 
531 
532  void Metric::compute_ricci_tensor (int dd) const {
533  // Need christoffels
534  if (p_christo[dd]==nullptr)
535  compute_christo(dd) ;
536 
537  // Get the conformal factor
538  bool doder = ((p_met_con[dd]->der_t==nullptr) || (p_met_cov[dd]->der_t==nullptr)) ? false : true ;
539  Tensor res_val (espace, 2, COV, p_met_con[dd]->val_t->get_basis()) ;
540  Tensor res_der (espace, 2, COV, p_met_con[dd]->val_t->get_basis()) ;
541 
542  Index pos (res_val) ;
543  do {
544  Val_domain cmpval (espace.get_domain(dd)) ;
545  cmpval = 0 ;
546 
547  for (int k=1 ; k<=espace.get_ndim() ; k++) {
548  cmpval += (*p_christo[dd]->val_t)(pos(0)+1,pos(1)+1,k)(dd).der_abs(k) - (*p_christo[dd]->val_t)(pos(1)+1, k, k)(dd).der_abs(pos(0)+1) ;
549  for (int l=1 ; l<=espace.get_ndim() ; l++)
550  cmpval += (*p_christo[dd]->val_t)(k,l,l)(dd)*(*p_christo[dd]->val_t)(pos(0)+1,pos(1)+1,k)(dd)
551  - (*p_christo[dd]->val_t)(pos(0)+1,k,l)(dd)*(*p_christo[dd]->val_t)(pos(1)+1,l,k)(dd) ;
552  }
553 
554  res_val.set(pos).set_domain(dd) = cmpval ;
555 
556  if (doder) {
557  Val_domain cmpder (espace.get_domain(dd)) ;
558  cmpder = 0 ;
559 
560  for (int k=1 ; k<=espace.get_ndim() ; k++) {
561  cmpder += (*p_christo[dd]->der_t)(pos(0)+1,pos(1)+1,k)(dd).der_abs(k) - (*p_christo[dd]->der_t)(pos(1)+1, k, k)(dd).der_abs(pos(0)+1) ;
562  for (int l=1 ; l<=espace.get_ndim() ; l++)
563  cmpder += (*p_christo[dd]->der_t)(k,l,l)(dd)*(*p_christo[dd]->val_t)(pos(0)+1,pos(1)+1,k)(dd)
564  + (*p_christo[dd]->val_t)(k,l,l)(dd)*(*p_christo[dd]->der_t)(pos(0)+1,pos(1)+1,k)(dd)
565  - (*p_christo[dd]->der_t)(pos(0)+1,k,l)(dd)*(*p_christo[dd]->val_t)(pos(1)+1,l,k)(dd)
566  - (*p_christo[dd]->val_t)(pos(0)+1,k,l)(dd)*(*p_christo[dd]->der_t)(pos(1)+1,l,k)(dd) ;
567  }
568  res_der.set(pos).set_domain(dd) = cmpder ;
569  }
570  }
571  while (pos.inc()) ;
572 
573  if (!doder) {
574  if (p_ricci_tensor[dd]==nullptr)
575  p_ricci_tensor[dd] = new Term_eq(dd, res_val) ;
576  else
577  *p_ricci_tensor[dd] = Term_eq (dd, res_val) ;
578  }
579  else {
580  if (p_ricci_tensor[dd]==nullptr)
581  p_ricci_tensor[dd] = new Term_eq(dd, res_val, res_der) ;
582  else
583  *p_ricci_tensor[dd] = Term_eq(dd, res_val, res_der) ;
584  }
585 
586 
587 
588  }
589 
590  void Metric::compute_ricci_scalar (int dd) const {
591 
592  // Need that
593  if (type_tensor == CON) {
594  if (p_met_con[dd]==nullptr)
595  compute_con(dd) ;
596  if (p_met_cov[dd]==nullptr)
597  compute_cov(dd) ;
598  }
599  else {
600  if (p_met_cov[dd]==nullptr)
601  compute_cov(dd) ;
602  if (p_met_con[dd]==nullptr)
603  compute_con(dd) ;
604  }
605  if (p_ricci_tensor[dd]==nullptr)
607 
608  bool doder = ((p_met_con[dd]->der_t==nullptr) || (p_ricci_tensor[dd]->der_t==nullptr)) ? false : true ;
609  Scalar res_val (espace) ;
610  Scalar res_der (espace) ;
611 
612  Val_domain cmpval (espace.get_domain(dd)) ;
613  cmpval = 0 ;
614 
615  for (int i=1 ; i<=espace.get_ndim() ; i++)
616  for (int j=1 ; j<=espace.get_ndim() ; j++)
617  cmpval += (*p_met_con[dd]->val_t)(i,j)(dd)*(*p_ricci_tensor[dd]->val_t)(i,j)(dd) ;
618  res_val.set_domain(dd) = cmpval ;
619 
620  if (doder) {
621  Val_domain cmpder (espace.get_domain(dd)) ;
622  cmpder = 0 ;
623 
624  for (int i=1 ; i<=espace.get_ndim() ; i++)
625  for (int j=1 ; j<=espace.get_ndim() ; j++)
626  cmpder += (*p_met_con[dd]->val_t)(i,j)(dd)*(*p_ricci_tensor[dd]->der_t)(i,j)(dd)
627  + (*p_met_con[dd]->der_t)(i,j)(dd)*(*p_ricci_tensor[dd]->val_t)(i,j)(dd) ;
628  res_der.set_domain(dd) = cmpder ;
629  }
630 
631  if (!doder) {
632  if (p_ricci_scalar[dd]==nullptr)
633  p_ricci_scalar[dd] = new Term_eq(dd, res_val) ;
634  else
635  *p_ricci_scalar[dd] = Term_eq (dd, res_val) ;
636  }
637  else {
638  if (p_ricci_scalar[dd]==nullptr)
639  p_ricci_scalar[dd] = new Term_eq(dd, res_val, res_der) ;
640  else
641  *p_ricci_scalar[dd] = Term_eq(dd, res_val, res_der) ;
642  }
643  }
644 
645  void Metric::manipulate_ind(Term_eq& so, int ind) const {
646 
647  int dd = so.get_dom() ;
648  int valence = so.get_val_t().get_valence() ;
649  int type_start = so.get_val_t().get_index_type (ind) ;
650 
651  if (type_tensor == CON) {
652  if (p_met_con[dd]==nullptr)
653  compute_con(dd) ;
654  if (p_met_cov[dd]==nullptr)
655  compute_cov(dd) ;
656  }
657  else {
658  if (p_met_cov[dd]==nullptr)
659  compute_cov(dd) ;
660  if (p_met_con[dd]==nullptr)
661  compute_con(dd) ;
662  }
663 
664  bool doder = false ;
665  if ((type_start==COV) && (p_met_con[dd]->der_t!=nullptr) && (so.der_t!=nullptr))
666  doder = true ;
667  if ((type_start==CON) && (p_met_cov[dd]->der_t!=nullptr) && (so.der_t!=nullptr))
668  doder = true ;
669 
670  Array<int> type_res (valence) ;
671  for (int i=0 ; i<valence ; i++)
672  type_res.set(i) = (i==ind) ? - so.get_val_t().get_index_type(i) : so.get_val_t().get_index_type(i) ;
673 
674  Tensor val_res (espace, valence, type_res, p_met_con[dd]->val_t->get_basis()) ;
675  Tensor val_der (espace, valence, type_res, p_met_con[dd]->val_t->get_basis()) ;
676 
677  Index pos (val_res) ;
678  do {
679  Val_domain cmpval (espace.get_domain(dd)) ;
680  cmpval = 0 ;
681 
682  for (int k=0 ; k<espace.get_ndim() ; k++) {
683  Index copie(pos) ;
684  copie.set(ind) = k ;
685  if (type_start==COV)
686  cmpval += (*p_met_con[dd]->val_t)(pos(ind)+1, k+1)(dd) * (*so.val_t)(copie)(dd);
687  else
688  cmpval += (*p_met_cov[dd]->val_t)(pos(ind)+1, k+1)(dd) * (*so.val_t)(copie)(dd) ;
689  }
690 
691  val_res.set(pos).set_domain(dd) = cmpval ;
692 
693  if (doder) {
694  Val_domain cmpder(espace.get_domain(dd)) ;
695  cmpder = 0 ;
696  for (int k=0 ; k<espace.get_ndim() ; k++) {
697  Index copie(pos) ;
698  copie.set(ind) = k ;
699  if (type_start==COV)
700  cmpder += (*p_met_con[dd]->der_t)(pos(ind)+1, k+1)(dd) * (*so.val_t)(copie)(dd)
701  +(*p_met_con[dd]->val_t)(pos(ind)+1, k+1)(dd) * (*so.der_t)(copie)(dd);
702  else
703  cmpder += (*p_met_cov[dd]->der_t)(pos(ind)+1, k+1)(dd) * (*so.val_t)(copie)(dd)
704  + (*p_met_cov[dd]->val_t)(pos(ind)+1, k+1)(dd) * (*so.der_t)(copie)(dd) ;
705 
706  }
707  val_der.set(pos).set_domain(dd) = cmpder ;
708  }
709  }
710  while (pos.inc()) ;
711 
712  // Put the names :
713  if (so.get_val_t().is_name_affected()) {
714  val_res.set_name_affected() ;
715  for (int i=0 ; i<valence ; i++)
716  val_res.set_name_ind(i, so.val_t->get_name_ind()[i]) ;
717  }
718 
719  if ((doder) && (so.get_der_t().is_name_affected())) {
720  val_der.set_name_affected() ;
721  for (int i=0 ; i<valence ; i++)
722  val_der.set_name_ind(i, so.der_t->get_name_ind()[i]) ;
723  }
724 
725  so.set_val_t()->set_index_type (ind) *= -1 ;
726  if (so.set_der_t() !=nullptr)
727  so.set_der_t()->set_index_type (ind) *= -1 ;
728 
729  delete so.val_t ;
730  so.val_t = new Tensor (val_res) ;
731  delete so.der_t ;
732  so.der_t = (doder) ? new Tensor (val_der) : nullptr ;
733  }
734 
735  void Metric::compute_cov (int) const {
736  cerr << "compute_cov not implemented for this type of metric" << endl ;
737  abort() ;
738  }
739 
740  void Metric::compute_con (int) const {
741  cerr << "compute_con not implemented for this type of metric" << endl ;
742  abort() ;
743  }
744 
745  void Metric::compute_dirac (int) const {
746  cerr << "Compute Dirac not implemented for this type of metric" << endl ;
747  abort() ;
748  }
749 
750  void Metric::compute_det_cov (int) const {
751  cerr << "Compute determinant of covariant not implemented for this type of metric" << endl ;
752  abort() ;
753  }
754 }
reference set(const Index &pos)
Read/write of an element.
Definition: array.hpp:186
int get_basis(int nd) const
Read only the basis in a given domain.
Definition: base_tensor.hpp:93
Class that gives the position inside a multi-dimensional Array.
Definition: index.hpp:38
int & set(int i)
Read/write of the position in a given dimension.
Definition: index.hpp:72
bool inc(int increm, int var=0)
Increments the position of the Index.
Definition: index.hpp:99
Purely abstract class for metric handling.
Definition: metric.hpp:39
virtual void compute_det_cov(int) const
Computes the determinant of the covariant representation, in a given Domain.
Definition: metric.cpp:750
const Term_eq * give_riemann(int dd) const
Gives the Riemann tensor, in a Domain.
Definition: metric.cpp:131
int type_tensor
States if one works in the CON or COV representation.
Definition: metric.hpp:86
const Term_eq * give_christo(int dd) const
Gives the Christoffel symbols, in a Domain.
Definition: metric.cpp:124
const Term_eq * give_det_cov(int dd) const
Gives the determinant of the covariant metric, in a Domain.
Definition: metric.cpp:159
MMPtr_array< Term_eq > p_ricci_tensor
Array of pointers on various Term_eq.
Definition: metric.hpp:70
const Term_eq * give_term(int typemet, int dd) const
Gives one representation of the metric, in a Domain.
Definition: metric.cpp:103
virtual Term_eq derive_partial(int typeder, char nameder, const Term_eq &so) const
Computes the partial derivative of a Term_eq (assumes Cartesian basis of decomposition).
Definition: metric.cpp:172
const Term_eq * give_dirac(int dd) const
Gives the potential of the Dirac gauge, in a Domain.
Definition: metric.cpp:152
virtual Term_eq derive(int typeder, char nameder, const Term_eq &so) const
Computes the covariant derivative of a Term_eq (assumes Cartesian basis of decomposition).
Definition: metric.cpp:290
virtual void compute_dirac(int) const
Computes the Dirac gauge term, in a given Domain.
Definition: metric.cpp:745
const Term_eq * give_ricci_scalar(int dd) const
Gives the Ricci scalar, in a Domain.
Definition: metric.cpp:145
const Term_eq * give_ricci_tensor(int dd) const
Gives the Ricci tensor, in a Domain.
Definition: metric.cpp:138
virtual void compute_con(int) const
Computes the contravariant representation, in a given Domain.
Definition: metric.cpp:740
virtual void compute_ricci_tensor(int) const
Computes the Ricci tensor, in a given Domain.
Definition: metric.cpp:532
virtual void update()
Updates the derived quantities (Christoffels etc..) This is done only for the ones that are needed,...
Definition: metric.cpp:99
virtual const Metric * get_background() const
Returns a pointer on the background metric, if it exists.
Definition: metric.cpp:167
const Space & espace
The associated Space.
Definition: metric.hpp:42
MMPtr_array< Term_eq > p_met_cov
Array of pointers on various Term_eq.
Definition: metric.hpp:50
MMPtr_array< Term_eq > p_met_con
Array of pointers on various Term_eq.
Definition: metric.hpp:55
virtual void manipulate_ind(Term_eq &so, int ind) const
Uses the Metric to manipulate one of the index of a Term_eq (i.e.
Definition: metric.cpp:645
virtual void compute_ricci_scalar(int) const
Computes the Ricci scalar, in a given Domain.
Definition: metric.cpp:590
MMPtr_array< Term_eq > p_dirac
Array of pointers on various Term_eq.
Definition: metric.hpp:80
MMPtr_array< Term_eq > p_riemann
Array of pointers on various Term_eq.
Definition: metric.hpp:65
MMPtr_array< Term_eq > p_christo
Array of pointers on various Term_eq.
Definition: metric.hpp:60
virtual void compute_christo(int) const
Computes the Christoffel symbols, in a given Domain.
Definition: metric.cpp:407
MMPtr_array< Term_eq > p_ricci_scalar
Array of pointers on various Term_eq.
Definition: metric.hpp:75
MMPtr_array< Term_eq > p_det_cov
Array of pointers on various Term_eq.
Definition: metric.hpp:85
virtual ~Metric()
Destructor.
Definition: metric.cpp:69
Metric(const Space &)
Constructor from a Space only (internal use only).
Definition: metric.cpp:29
virtual void compute_riemann(int) const
Computes the Riemann tensor, in a given Domain.
Definition: metric.cpp:476
virtual int give_type(int) const
Returns the type of tensorial basis of the covariant representation, in a given Domain.
Definition: metric.cpp:118
virtual void compute_cov(int) const
Computes the covariant representation, in a given Domain.
Definition: metric.cpp:735
virtual Term_eq derive_flat(int typeder, char nameder, const Term_eq &so) const
Computes the covariant flat derivative of a Term_eq.
Definition: metric.cpp:402
The class Scalar does not really implements scalars in the mathematical sense but rather tensorial co...
Definition: scalar.hpp:67
Val_domain & set_domain(int)
Read/write of a particular Val_domain.
Definition: scalar.hpp:555
The Space class is an ensemble of domains describing the whole space of the computation.
Definition: space.hpp:1362
const Domain * get_domain(int i) const
returns a pointer on the domain.
Definition: space.hpp:1385
int get_ndim() const
Returns the number of dimensions.
Definition: space.hpp:1373
int get_nbr_domains() const
Returns the number of Domains.
Definition: space.hpp:1375
Tensor handling.
Definition: tensor.hpp:149
void set_name_ind(int dd, char name)
Sets the name of one index ; the names must have been affected first.
void set_name_affected()
Affects the name of the indices.
Definition: tensor.hpp:435
Scalar & set(const Array< int > &ind)
Returns the value of a component (read/write version).
Definition: tensor_impl.hpp:91
char const * get_name_ind() const
Definition: tensor.hpp:424
int get_index_type(int i) const
Gives the type (covariant or contravariant) of a given index.
Definition: tensor.hpp:526
const Base_tensor & get_basis() const
Returns the vectorial basis (triad) on which the components are defined.
Definition: tensor.hpp:504
int get_valence() const
Returns the valence.
Definition: tensor.hpp:509
bool is_name_affected() const
Check whether the names of the indices have been affected.
Definition: tensor.hpp:429
Tensor do_summation_one_dom(int dd) const
Does the inner contraction of the Tensor in a given domain.
This class is intended to describe the manage objects appearing in the equations.
Definition: term_eq.hpp:62
Tensor * der_t
Pointer on the variation, if the Term_eq is a Tensor.
Definition: term_eq.hpp:69
void set_der_t(Tensor)
Sets the tensorial variation (only the values in the pertinent Domain are copied).
Definition: term_eq.cpp:171
int get_dom() const
Definition: term_eq.hpp:135
int get_type_data() const
Definition: term_eq.hpp:131
Tensor const & get_val_t() const
Definition: term_eq.hpp:355
Tensor const & get_der_t() const
Definition: term_eq.hpp:369
void set_val_t(Tensor)
Sets the tensorial value (only the values in the pertinent Domain are copied).
Definition: term_eq.cpp:155
Tensor * val_t
Pointer on the value, if the Term_eq is a Tensor.
Definition: term_eq.hpp:68
Class for storing the basis of decompositions of a field and its values on both the configuration and...
Definition: val_domain.hpp:69
Val_domain der_abs(int i) const
Computes the derivative with respect to an absolute coordinate (typically Cartesian).
Definition: val_domain.cpp:681