KADATH
metric_AADS.cpp
1 /*
2  Copyright 2017 GrĂ©goire Martinon
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 "metric_AADS.hpp"
21 namespace Kadath {
22 Metric_AADS::Metric_AADS(const Space& space, Metric_tensor& hmet) : Metric(space), m_doder(false), m_ads(space), p_hmet(&hmet)
23 {
24  int dim(space.get_ndim());
25  assert(dim == 3);
26 
27  p_basis = new Base_tensor(space, CARTESIAN_BASIS);
28  p_der_eps = new Vector(space, COV, *p_basis);
29 
30  type_tensor = COV; // assume covariance
31  assert(hmet.get_type() == COV);
32  m_nd = espace.get_nbr_domains(); // discard infinity (last domain)
33  m_L = espace.get_domain(m_nd - 1)->get_rmax(); // AdS length
34 
35  p_h = new Term_eq*[m_nd];
36  p_k = new Term_eq*[m_nd];
37  for (int d(0) ; d < m_nd ; ++d)
38  {
39  p_h[d] = nullptr;
40  p_k[d] = nullptr;
41  }
42 
43  for (int d(0) ; d < m_nd ; ++d)
44  for (int i(1) ; i <= dim ; ++i)
45  p_der_eps->set(i).set_domain(d) = -4.0*espace.get_domain(d)->get_cart(i)/m_L/m_L/pow(1.0 + m_ads.m_rho2(d) , 2); // derivative of eps
46 }
47 
48 Metric_AADS::Metric_AADS(const Metric_AADS& so) : Metric(so), m_nd(so.m_nd), m_L(so.m_L), m_doder(so.m_doder), m_ads(so.m_ads)
49 {
50  p_h = new Term_eq*[m_nd];
51  p_k = new Term_eq*[m_nd];
52  for (int d(0) ; d < espace.get_nbr_domains() ; ++d)
53  {
54  p_h[d] = (so.p_h[d] == nullptr) ? nullptr : new Term_eq(*so.p_h[d]);
55  p_k[d] = (so.p_k[d] == nullptr) ? nullptr : new Term_eq(*so.p_k[d]);
56  }
57  p_basis = new Base_tensor(*so.p_basis);
58  p_der_eps = new Vector(*so.p_der_eps);
59  p_hmet = new Metric_tensor(*so.p_hmet);
60 }
61 
62 Metric_AADS::~Metric_AADS()
63 {
64  for (int d(0) ; d < m_nd ; ++d)
65  {
66  if (p_h[d] != nullptr) delete p_h[d];
67  p_h[d] = nullptr;
68  if (p_k[d] != nullptr) delete p_k[d];
69  p_k[d] = nullptr;
70  }
71  delete[] p_h;
72  delete[] p_k;
73  delete p_basis;
74  delete p_der_eps;
75 }
76 
78 {
79  assert(type_tensor == COV);
80  if (p_met_cov[d] != nullptr) compute_cov(d);
81  if (p_met_con[d] != nullptr) compute_con(d);
82  if (p_christo[d] != nullptr) compute_christo(d);
83  if (p_ricci_tensor[d] != nullptr) compute_ricci_tensor(d);
84  if (p_ricci_scalar[d] != nullptr) compute_ricci_scalar(d);
85 }
86 
88 {
89  for (int d(0) ; d < m_nd ; ++d) update(d);
90 }
91 
92 void Metric_AADS::compute_cov(int d) const // compute covariant metric in domain d
93 { // eps^2*gama_ij is stored
94  if(m_ads.p_met_cov[d] == nullptr) m_ads.compute_cov(d);
95  if (syst != nullptr)
96  {
97  int place(m_place_syst + (d - syst->dom_min)); // where is the unknown eps^2*h Term_eq in the d-th domain in system of equations
98  if (p_h[d] == nullptr) p_h[d] = new Term_eq(*syst->term[place]);
99  else *p_h[d] = *syst->term[place];
100 
101  if (p_met_cov[d] == nullptr) p_met_cov[d] = new Term_eq(*m_ads.p_met_cov[d] + *p_h[d]);
102  else *p_met_cov[d] = *m_ads.p_met_cov[d] + *p_h[d];
103  }
104  else
105  {
106  if (p_met_cov[d] == nullptr) p_met_cov[d] = new Term_eq(d, *m_ads.give_term(d, COV)->val_t + *p_hmet);
107  else *p_met_cov[d] = Term_eq(d, *m_ads.give_term(d, COV)->val_t + *p_hmet);
108  }
109  // at this point, metric is multiplied by epsilon^2
110  m_doder = (p_met_cov[d]->der_t != nullptr);
111 }
112 
113 void Metric_AADS::compute_con(int d) const // compute contravariant metric in domain d
114 {
115  if (p_met_cov[d] == nullptr) compute_cov(d); // need the covariant metric
116  if (m_ads.p_met_con[d] == nullptr) m_ads.compute_con(d); // need the background contravariant metric
117  int dim(espace.get_ndim()); // dimension
118  assert(dim == 3); // what follows only valid for 3D but is easily generalisable
119 
120  Term_eq** res(new Term_eq* [dim*(dim + 1)/2]); // 6 components to compute...
121  Scalar val(espace); // val and cmpval are more or less the same intermediate, but with different types
122  Scalar der(espace);
123  Val_domain cmpval(espace.get_domain(d));
124  Val_domain cmpder(espace.get_domain(d));
125 
126  Val_domain detval(espace.get_domain(d)); // let's compute the determinant...
127  Val_domain detder(espace.get_domain(d)); // ... and its automatic derivative
128  detval = 0.0;
129  detder = 0.0;
130 
131  // compute determinant as a sum over permutations
132  double signature; // signature of the permutation
133  gsl_permutation* p(gsl_permutation_calloc(dim)); // initialise to identity 0, 1, 2
134  do
135  {
136  signature = sign(p);
137  int p1(static_cast<int>(gsl_permutation_get(p, 0)) + 1); // for tensor indices, you need to add one to get a permutation of 1, 2, 3
138  int p2(static_cast<int>(gsl_permutation_get(p, 1)) + 1);
139  int p3(static_cast<int>(gsl_permutation_get(p, 2)) + 1);
140  detval += signature * (*p_met_cov[d]->val_t)(p1, 1)(d) * (*p_met_cov[d]->val_t)(p2, 2)(d) * (*p_met_cov[d]->val_t)(p3, 3)(d); // sum on permutations
141  if (m_doder)
142  {
143  detder += signature *((*p_met_cov[d]->der_t)(p1, 1)(d) * (*p_met_cov[d]->val_t)(p2, 2)(d) * (*p_met_cov[d]->val_t)(p3, 3)(d)
144  + (*p_met_cov[d]->val_t)(p1, 1)(d) * (*p_met_cov[d]->der_t)(p2, 2)(d) * (*p_met_cov[d]->val_t)(p3, 3)(d)
145  + (*p_met_cov[d]->val_t)(p1, 1)(d) * (*p_met_cov[d]->val_t)(p2, 2)(d) * (*p_met_cov[d]->der_t)(p3, 3)(d));
146  }
147  }while(gsl_permutation_next(p) == GSL_SUCCESS);
148  gsl_permutation_free(p);
149 
150  // compute the transposed comatrix
151  for (int i(1) ; i <= dim ; ++i) // sum over components, only the upper triangular part
152  {
153  for (int j(i) ; j <= dim ; ++j)
154  {
155  cmpval = 0.0; // initialise to 0 before each computation
156  cmpder = 0.0; // initialise to 0 before each computation
157  p = gsl_permutation_calloc(dim - 1); // reinitialise to identity 0, 1, ready to be used for next component
158  do
159  {
160  signature = sign(p);
161  int p1(static_cast<int>(gsl_permutation_get(p, 0)) + 1); // always add one for tensor indices, now we have a permutation of 1, 2
162  int p2(static_cast<int>(gsl_permutation_get(p, 1)) + 1);
163  vector<int> index1, index2; // manage the indices of the transposed comatrix
164  index1 = ind_com(i, j, p1, 1); // we need to play a bit with indices to get transpose(COM(metric))
165  index2 = ind_com(i, j, p2, 2);
166  cmpval += pow(-1.0, i + j)*signature*(*p_met_cov[d]->val_t)(index1[0], index1[1])(d)*(*p_met_cov[d]->val_t)(index2[0],index2[1])(d); // sum on permutations
167  if (m_doder)
168  cmpder += pow(-1.0, i + j)*signature*(*p_met_cov[d]->der_t)(index1[0], index1[1])(d)*(*p_met_cov[d]->val_t)(index2[0], index2[1])(d)
169  + pow(-1.0, i + j)*signature*(*p_met_cov[d]->val_t)(index1[0], index1[1])(d)*(*p_met_cov[d]->der_t)(index2[0], index2[1])(d);
170  }while(gsl_permutation_next(p) == GSL_SUCCESS);
171  gsl_permutation_free(p);
172  val.set_domain(d) = cmpval / detval; // now we have the component of the inverse matrix
173  if (m_doder)
174  {
175  der.set_domain(d) = cmpder / detval - cmpval * detder / (detval*detval);
176  res[j - 1 + dim*(i - 1) - i*(i - 1)/2] = new Term_eq (d, val, der); // just save upper triangular components in a 1D array of Term_eq (the indice will run throug 0, 1, 2, 3, 4, 5 with i, j)
177  }
178  else res[j - 1 + dim*(i - 1) - i*(i - 1)/2] = new Term_eq (d, val);
179  }
180  }
181 
182  // Value field :
183  Metric_tensor resval(espace, CON, *p_basis);
184  Metric_tensor resder(espace, CON, *p_basis);
185  for (int i(1) ; i <= dim ; ++i)
186  for (int j(i) ; j <= dim ; ++j)
187  resval.set(i, j) = res[j - 1 + dim*(i - 1) - i*(i - 1)/2]->get_val_t();
188 
189  // Der field
190  if (!m_doder)
191  {
192  if (p_met_con[d] == nullptr) p_met_con[d] = new Term_eq(d, resval);
193  else *p_met_con[d] = Term_eq(d, resval);
194  }
195  else
196  {
197  for (int i(1) ; i <= dim ; ++i)
198  for (int j(i) ; j <= dim ; ++j)
199  resder.set(i, j) = res[j - 1 + dim*(i - 1) - i*(i - 1)/2]->get_der_t();
200 
201  if (p_met_con[d] == nullptr) p_met_con[d] = new Term_eq(d, resval, resder);
202  else *p_met_con[d] = Term_eq(d, resval, resder);
203  }
204 
205  for (int i(0) ; i < dim*(dim + 1)/2 ; ++i) delete res[i];
206  delete[] res;
207 
208  // k^ij/eps^2
209  resval = *p_met_con[d]->val_t - *m_ads.give_term(d, CON)->val_t;
210  if (m_doder) resder = *p_met_con[d]->der_t - *m_ads.give_term(d, CON)->der_t;
211  if (!m_doder)
212  {
213  if (p_k[d] == nullptr) p_k[d] = new Term_eq(d, resval);
214  else *p_k[d] = Term_eq(d, resval);
215  }
216  else
217  {
218  if (p_k[d] == nullptr) p_k[d] = new Term_eq(d, resval, resder);
219  else *p_k[d] = Term_eq(d, resval, resder);
220  }
221 }
222 
223 void Metric_AADS::manipulate_ind(Term_eq& so, int ind) const // rise or lower indice ind on term_eq via the metric (in place)
224 {
225  int d(so.get_dom()); // domain
226  int dim(espace.get_ndim());
227  int valence(so.get_val_t().get_valence()); // number of indices
228  int type_start(so.get_val_t().get_index_type (ind)); // contravariant or covariant
229 
230  if (p_met_con[d] == nullptr and type_start == COV) compute_con(d); // make sure that metric is computed
231  if (p_met_cov[d] == nullptr and type_start == CON) compute_cov(d);
232  bool doder(so.der_t != nullptr and m_doder); // compute variations only if tensor need to
233  Array<int> type_res (valence); // CON or COV
234  for (int i(0) ; i < valence ; ++i) type_res.set(i) = (i == ind) ? - so.get_val_t().get_index_type(i) : so.get_val_t().get_index_type(i); // change the COV/CON of ind
235  Tensor val_res(espace, valence, type_res, *p_basis); // tensor
236  Tensor val_der(espace, valence, type_res, *p_basis); // its variation
237  Val_domain cmpval(espace.get_domain(d)); // component value
238  Val_domain cmpder(espace.get_domain(d));
239  Index pos(val_res);
240  do // for all components
241  {
242  cmpval = 0.0;
243  cmpder = 0.0;
244  Index copie(pos);
245  for (int k(0) ; k < dim ; ++k) // loop on mute indice
246  {
247  copie.set(ind) = k; // loop on the indice to rise/lower
248  if (type_start == COV) cmpval += (*p_met_con[d]->val_t)(pos(ind) + 1, k + 1)(d) * (*so.val_t)(copie)(d); // g^ik T_jk
249  else cmpval += (*p_met_cov[d]->val_t)(pos(ind) + 1, k + 1)(d) * (*so.val_t)(copie)(d); // g_ik T^k_j
250  }
251  val_res.set(pos).set_domain(d) = cmpval; // assign cmpval to right component
252 
253  if (doder) // if variation of tensor needs to be computed
254  {
255  for (int k(0) ; k < dim ; ++k)
256  {
257  copie.set(ind) = k;
258  if (type_start == COV) cmpder += (*p_met_con[d]->val_t)(pos(ind) + 1, k + 1)(d) * (*so.der_t)(copie)(d)
259  + (*p_met_con[d]->der_t)(pos(ind) + 1, k + 1)(d) * (*so.val_t)(copie)(d); // recall that variations of background metric are not zero
260 
261  else cmpder += (*p_met_cov[d]->val_t)(pos(ind) + 1, k + 1)(d) * (*so.der_t)(copie)(d)
262  + (*p_met_cov[d]->der_t)(pos(ind) + 1, k + 1)(d) * (*so.val_t)(copie)(d);
263  }
264  val_der.set(pos).set_domain(d) = cmpder; // assign cmpder to the component of the variation
265  }
266  }while (pos.inc());
267 
268  // Put the names :
269  if (so.get_val_t().is_name_affected())
270  {
271  val_res.set_name_affected();
272  for (int i(0) ; i < valence ; ++i) val_res.set_name_ind(i, so.val_t->get_name_ind()[i]); // result have same indice names as source
273  if (doder)
274  {
275  val_der.set_name_affected();
276  for (int i(0) ; i < valence ; ++i) val_der.set_name_ind(i, so.val_t->get_name_ind()[i]);
277  }
278  }
279 
280  delete so.val_t;
281  so.val_t = new Tensor(val_res); // in place substitution
282  delete so.der_t;
283  so.der_t = doder ? new Tensor(val_der) : nullptr;
284 
285  // multiplication/division by eps^2
286  if (type_start == CON) so = m_ads.div_eps(so, 2);
287  else if (type_start == COV) so = m_ads.mul_eps(so, 2);
288 }
289 
290 void Metric_AADS::compute_christo(int d) const // WARNING : christo will store the DIFFERENCE between background Christoffel and actual one
291 {
292  if (p_met_cov[d] == nullptr) compute_cov(d);
293  if (p_met_con[d] == nullptr) compute_con(d);
294  if (m_ads.p_christo[d] == nullptr) m_ads.compute_christo(d);
295 
296  int dim(espace.get_ndim());
297  Array<int> type_ind(3);
298  type_ind.set(0) = COV ; type_ind.set(1) = COV ; type_ind.set(2) = CON; // position of indices
299  Tensor res_val(espace, 3, type_ind, *p_basis); // tensor to affect to the value of *p_christo
300  Tensor res_der(espace, 3, type_ind, *p_basis); // tensor to affect to the variation of *p_christo
301  res_val = 0.0;
302  res_der = 0.0;
303  Index pos(res_val);
304  Val_domain cmpval(espace.get_domain(d)); // components of the tensor
305  Val_domain cmpder(espace.get_domain(d));
306  do
307  {
308  cmpval = 0.0;
309  for (int l(1) ; l <= dim ; ++l)
310  {
311  cmpval += 0.5 * m_ads.m_eps(d) * (*p_met_con[d]->val_t)(pos(2) + 1, l)(d) // formule (7.30) 3+1 Eric Gourgoulhon
312  * ( (*p_h[d]->val_t)(pos(1) + 1, l)(d).der_abs(pos(0) + 1)
313  + (*p_h[d]->val_t)(pos(0) + 1, l)(d).der_abs(pos(1) + 1)
314  - (*p_h[d]->val_t)(pos(0) + 1, pos(1) + 1)(d).der_abs(l) )
315  - (*p_met_con[d]->val_t)(pos(2) + 1, l)(d)
316  * ( (*p_h[d]->val_t)(pos(1) + 1, l)(d)*(*p_der_eps)(pos(0) + 1)(d)
317  + (*p_h[d]->val_t)(pos(0) + 1, l)(d)*(*p_der_eps)(pos(1) + 1)(d)
318  - (*p_h[d]->val_t)(pos(0) + 1, pos(1) + 1)(d)*(*p_der_eps)(l)(d));
319  for (int m(1) ; m <= dim ; ++m) cmpval -= (*p_met_con[d]->val_t)(pos(2) + 1, l)(d)*(*m_ads.p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, m)(d)*(*p_h[d]->val_t)(l,m)(d);
320  }
321  res_val.set(pos).set_domain(d) = cmpval;
322 
323  if (m_doder)
324  {
325  cmpder = 0.0;
326  for (int l(1) ; l <= dim ; ++l)
327  {
328  cmpder += 0.5 * m_ads.m_eps(d) * (*p_met_con[d]->der_t)(pos(2) + 1, l)(d) // formule (7.30) 3+1 Eric Gourgoulhon
329  * ( (*p_h[d]->val_t)(pos(1) + 1, l)(d).der_abs(pos(0) + 1)
330  + (*p_h[d]->val_t)(pos(0) + 1, l)(d).der_abs(pos(1) + 1)
331  - (*p_h[d]->val_t)(pos(0) + 1, pos(1) + 1)(d).der_abs(l) )
332  + 0.5 * m_ads.m_eps(d) * (*p_met_con[d]->val_t)(pos(2) + 1, l)(d) // formule (7.30) 3+1 Eric Gourgoulhon
333  * ( (*p_h[d]->der_t)(pos(1) + 1, l)(d).der_abs(pos(0) + 1)
334  + (*p_h[d]->der_t)(pos(0) + 1, l)(d).der_abs(pos(1) + 1)
335  - (*p_h[d]->der_t)(pos(0) + 1, pos(1) + 1)(d).der_abs(l) )
336  - (*p_met_con[d]->der_t)(pos(2) + 1, l)(d)
337  * ( (*p_h[d]->val_t)(pos(0) + 1, l)(d)*(*p_der_eps)(pos(1) + 1)(d)
338  + (*p_h[d]->val_t)(pos(1) + 1, l)(d)*(*p_der_eps)(pos(0) + 1)(d)
339  - (*p_h[d]->val_t)(pos(0) + 1, pos(1) + 1)(d)*(*p_der_eps)(l)(d))
340  - (*p_met_con[d]->val_t)(pos(2) + 1, l)(d)
341  * ( (*p_h[d]->der_t)(pos(0) + 1, l)(d)*(*p_der_eps)(pos(1) + 1)(d)
342  + (*p_h[d]->der_t)(pos(1) + 1, l)(d)*(*p_der_eps)(pos(0) + 1)(d)
343  - (*p_h[d]->der_t)(pos(0) + 1, pos(1) + 1)(d)*(*p_der_eps)(l)(d));
344  for (int m(1) ; m <= dim ; ++m) cmpder -= (*p_met_con[d]->der_t)(pos(2) + 1, l)(d)*(*m_ads.p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, m)(d)*(*p_h[d]->val_t)(l,m)(d)
345  + (*p_met_con[d]->val_t)(pos(2) + 1, l)(d)*(*m_ads.p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, m)(d)*(*p_h[d]->der_t)(l,m)(d);
346  }
347  res_der.set(pos).set_domain(d) = cmpder;
348  }
349  }while(pos.inc());
350 
351  if (!m_doder)
352  {
353  if (p_christo[d] == nullptr) p_christo[d] = new Term_eq(d, res_val);
354  else *p_christo[d] = Term_eq (d, res_val);
355  }
356  else
357  {
358  if (p_christo[d] == nullptr) p_christo[d] = new Term_eq(d, res_val, res_der);
359  else *p_christo[d] = Term_eq(d, res_val, res_der);
360  }
361 }
362 
363 Term_eq Metric_AADS::derive_simple(const Term_eq& so) const // covariant derivative which does not affect indices and assume derivative indice is covariant
364 {
365  assert(espace.get_ndim() == 3);
366  bool doder(so.der_t != nullptr and m_doder);
367  int d(so.get_dom()); // domain
368  int so_val(so.val_t->get_valence());
369  Term_eq res(m_ads.derive_simple(so)); // The background covariant derivative part
370  Tensor gam_res_arg(espace, res.val_t->get_valence(), res.val_t->get_index_type(), *p_basis); // just to initialise a term_eq gam
371  gam_res_arg = 0.0;
372  Term_eq gam_res(d, gam_res_arg);
373  if (doder) gam_res.set_der_zero();
374  if (p_christo[d] == nullptr) compute_christo(d); // of course you need Christoffel
375  Index posgamres(*gam_res.val_t);
376  Index poschristo(*p_christo[d]->val_t);
377  Index posso(*so.val_t);
378  int genre_indice; // COV or CON
379  for (int cmp(0) ; cmp < so_val ; ++cmp) // loop on the components of so, compute one Christoffel term on each cycle
380  {
381  posgamres.set_start(); // reinitialize the gam_res indice position
382  genre_indice = so.val_t->get_index_type(cmp); // COV or CON
383  do // loop on the components of gam_res, compute all components of the Chritoffel term under consideration
384  {
385  if (genre_indice == CON)
386  {
387  poschristo.set(0) = posgamres(0); // indice of D
388  poschristo.set(2) = posgamres(cmp + 1); // e.g. first indice of so is the second one of gam_res... poschristo.set(1) sumation, see below
389  for (int i(0) ; i < so_val ; ++i) if (i != cmp) posso.set(i) = posgamres(i + 1);// e.g. first indice of so is the second one of gam_res...
390  for (int mute(0) ; mute < 3 ; ++mute) // case sumation
391  {
392  poschristo.set(1) = mute;
393  posso.set(cmp) = mute;
394  gam_res.val_t->set(posgamres).set_domain(d) += (*p_christo[d]->val_t)(poschristo)(d) * (*so.val_t)(posso)(d);
395  if (doder) gam_res.der_t->set(posgamres).set_domain(d) += (*p_christo[d]->val_t)(poschristo)(d) * (*so.der_t)(posso)(d)
396  + (*p_christo[d]->der_t)(poschristo)(d) * (*so.val_t)(posso)(d);
397  }
398  }
399  if (genre_indice == COV)
400  {
401  poschristo.set(0) = posgamres(0); // indice of D
402  poschristo.set(1) = posgamres(cmp + 1); //poschristo.set(2) summation, see below
403  for (int i(0) ; i < so_val ; ++i) if (i != cmp) posso.set(i) = posgamres(i + 1); // e.g. first indice of so is the second one of gam_res...
404  for (int mute(0) ; mute < 3 ; ++mute) // case sumation
405  {
406  poschristo.set(2) = mute;
407  posso.set(cmp) = mute;
408  gam_res.val_t->set(posgamres).set_domain(d) -= (*p_christo[d]->val_t)(poschristo)(d) * (*so.val_t)(posso)(d);
409  if (doder) gam_res.der_t->set(posgamres).set_domain(d) -= (*p_christo[d]->val_t)(poschristo)(d) * (*so.der_t)(posso)(d)
410  - (*p_christo[d]->der_t)(poschristo)(d) * (*so.val_t)(posso)(d);
411  }
412  }
413  }while(posgamres.inc());
414  }
415  return res + m_ads.div_eps(gam_res, 1);
416 }
417 
418 Term_eq Metric_AADS::derive(int type_der, char ind_der, const Term_eq& so) const // covariant derivative
419 {
420  int d(so.get_dom()); // domain
421  int so_val(so.val_t->get_valence());
422  bool doder(so.der_t != nullptr and m_doder);
423  if (p_christo[d] == nullptr) compute_christo(d); // of course you need Christoffel
424  Term_eq res(derive_simple(so)); // The background simple derivative part (no indice names affected, no inner summation)
425  if (type_der == CON) manipulate_ind(res, 0); // manipulate indice if you want D^i
426 
427  // Set names and check inner summ
428  bool inner_sum(false);
429  if (so.val_t->is_name_affected())
430  {
431  res.val_t->set_name_affected();
432  res.val_t->set_name_ind(0, ind_der);
433  for (int i(0) ; i < so_val ; ++i)
434  {
435  res.val_t->set_name_ind(i + 1, so.val_t->get_name_ind()[i]); // put the names of ressult with name of D and names of tensor indices
436  if (so.val_t->get_name_ind()[i] == ind_der) inner_sum = true;
437  }
438  if (doder)
439  {
440  res.der_t->set_name_affected();
441  res.der_t->set_name_ind(0, ind_der);
442  for (int i(0) ; i < so_val ; ++i) res.der_t->set_name_ind(i + 1, so.val_t->get_name_ind()[i]);
443  }
444  }
445  else if (so_val == 0) // manage the scalar case
446  {
447  res.val_t->set_name_affected();
448  res.val_t->set_name_ind(0, ind_der);
449  if (doder)
450  {
451  res.der_t->set_name_affected();
452  res.der_t->set_name_ind(0, ind_der);
453  }
454  }
455  if (inner_sum)
456  {
457  if (!doder) return Term_eq(d, res.val_t->do_summation_one_dom(d));
458  else return Term_eq(d, res.val_t->do_summation_one_dom(d), res.der_t->do_summation_one_dom(d));
459  }
460  else return res;
461 }
462 
463 void Metric_AADS::compute_ricci_tensor(int d) const // epsilon^2 *(Ricci - RicciB)
464 {
465  if (p_christo[d] == nullptr) compute_christo(d);
466  if (m_ads.p_christo[d] == nullptr) m_ads.compute_christo(d);
467  int dim(espace.get_ndim());
468  Tensor res_val(espace, 2, COV, *p_basis); // the result to put into Ricci
469  Tensor res_der(espace, 2, COV, *p_basis);
470  Index pos(res_val);
471  Val_domain cmpval(espace.get_domain(d)); // each component
472  Val_domain cmpder(espace.get_domain(d));
473  do
474  {
475  cmpval = 0.0;
476  for (int k(1) ; k <= dim ; ++k) // formula (7.40) 3+1 Eric Gourgoulhon
477  {
478  cmpval += m_ads.m_eps(d)*( (*p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, k)(d).der_abs(k)
479  - (*p_christo[d]->val_t)(pos(1) + 1, k, k)(d).der_abs(pos(0) + 1) )
480  - (*p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, k)(d)*(*p_der_eps)(k)(d)
481  + (*p_christo[d]->val_t)(pos(1) + 1, k, k)(d)*(*p_der_eps)(pos(0) + 1)(d);
482  for (int l(1) ; l <= dim ; ++l) cmpval += (*p_christo[d]->val_t)(k, l, l)(d) * (*p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, k)(d)
483  - (*p_christo[d]->val_t)(pos(0) + 1, l, k)(d) * (*p_christo[d]->val_t)(pos(1) + 1, k, l)(d)
484  + (*m_ads.p_christo[d]->val_t)(k,l,k)(d) * (*p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1,l)(d)
485  - (*m_ads.p_christo[d]->val_t)(k,pos(1) + 1,l)(d) * (*p_christo[d]->val_t)(pos(0) + 1, l,k)(d)
486  - (*m_ads.p_christo[d]->val_t)(pos(0) + 1,l,k)(d) * (*p_christo[d]->val_t)(pos(1) + 1, k,l)(d)
487  + (*m_ads.p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1,l)(d) * (*p_christo[d]->val_t)(l,k,k)(d);
488  }
489  res_val.set(pos).set_domain(d) = cmpval;
490 
491  if (m_doder)
492  { // variation
493  cmpder = 0.0;
494  for (int k(1) ; k <= dim ; ++k)
495  {
496  cmpder += m_ads.m_eps(d)*( (*p_christo[d]->der_t)(pos(0) + 1, pos(1) + 1, k)(d).der_abs(k)
497  - (*p_christo[d]->der_t)(pos(1) + 1, k, k)(d).der_abs(pos(0) + 1) )
498  - (*p_christo[d]->der_t)(pos(0) + 1, pos(1) + 1, k)(d)*(*p_der_eps)(k)(d)
499  + (*p_christo[d]->der_t)(pos(1) + 1, k, k)(d)*(*p_der_eps)(pos(0) + 1)(d);
500  for (int l(1) ; l <= dim ; ++l) cmpder += (*p_christo[d]->der_t)(k, l, l)(d) * (*p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1, k)(d)
501  + (*p_christo[d]->val_t)(k, l, l)(d) * (*p_christo[d]->der_t)(pos(0) + 1, pos(1) + 1, k)(d)
502  - (*p_christo[d]->der_t)(pos(0) + 1, l, k)(d) * (*p_christo[d]->val_t)(pos(1) + 1, k, l)(d)
503  - (*p_christo[d]->val_t)(pos(0) + 1, l, k)(d) * (*p_christo[d]->der_t)(pos(1) + 1, k, l)(d)
504  + (*m_ads.p_christo[d]->val_t)(k,l,k)(d) * (*p_christo[d]->der_t)(pos(0) + 1, pos(1) + 1,l)(d)
505  - (*m_ads.p_christo[d]->val_t)(k,pos(1) + 1,l)(d) * (*p_christo[d]->der_t)(pos(0) + 1, l,k)(d)
506  - (*m_ads.p_christo[d]->val_t)(pos(0) + 1,l,k)(d) * (*p_christo[d]->der_t)(pos(1) + 1, k,l)(d)
507  + (*m_ads.p_christo[d]->val_t)(pos(0) + 1, pos(1) + 1,l)(d) * (*p_christo[d]->der_t)(l,k,k)(d);
508  }
509  res_der.set(pos).set_domain(d) = cmpder;
510  }
511  }while (pos.inc());
512 
513  if (!m_doder)
514  if (p_ricci_tensor[d] == nullptr) p_ricci_tensor[d] = new Term_eq(d, res_val);
515  else *p_ricci_tensor[d] = Term_eq(d, res_val);
516  else
517  if (p_ricci_tensor[d] == nullptr) p_ricci_tensor[d] = new Term_eq(d, res_val, res_der);
518  else *p_ricci_tensor[d] = Term_eq(d, res_val, res_der);
519 }
520 
521 void Metric_AADS::compute_ricci_scalar(int d) const // O(1) in last domain
522 {
523  int dim(espace.get_ndim());
524  if (p_met_cov[d] == nullptr) compute_cov(d);
525  if (p_met_con[d] == nullptr) compute_con(d);
526  if (p_ricci_tensor[d] == nullptr) compute_ricci_tensor(d);
527  if (m_ads.p_ricci_tensor[d] == nullptr) m_ads.compute_ricci_tensor(d);
528  Scalar res_val(espace);
529  Scalar res_der(espace);
530  Val_domain cmpval(espace.get_domain(d));
531  Val_domain cmpder(espace.get_domain(d));
532  cmpval = 0.0;
533  cmpder = 0.0;
534  for (int i(1) ; i <= dim ; ++i)
535  for (int j(1) ; j <= dim ; ++j)
536  cmpval += (*p_met_con[d]->val_t)(i, j)(d) * (*p_ricci_tensor[d]->val_t)(i, j)(d)
537  + (*p_k[d]->val_t)(i, j)(d) * (*m_ads.p_ricci_tensor[d]->val_t)(i, j)(d);
538  res_val.set_domain(d) = cmpval;
539 
540  if (m_doder)
541  {
542  for (int i(1) ; i <= dim ; ++i)
543  for (int j(1) ; j <= dim ; ++j)
544  cmpder += (*p_met_con[d]->val_t)(i, j)(d) * ( (*p_ricci_tensor[d]->der_t)(i, j)(d) )
545  + (*p_met_con[d]->der_t)(i, j)(d) * (*p_ricci_tensor[d]->val_t)(i, j)(d)
546  + (*p_k[d]->der_t)(i, j)(d) * (*m_ads.p_ricci_tensor[d]->val_t)(i, j)(d);
547  res_der.set_domain(d) = cmpder;
548  }
549 
550  if (!m_doder)
551  {
552  if (p_ricci_scalar[d] == nullptr) p_ricci_scalar[d] = new Term_eq(d, res_val);
553  else *p_ricci_scalar[d] = Term_eq (d, res_val);
554  }
555  else
556  {
557  if (p_ricci_scalar[d] == nullptr) p_ricci_scalar[d] = new Term_eq(d, res_val, res_der);
558  else *p_ricci_scalar[d] = Term_eq(d, res_val, res_der);
559  }
560 }
561 
562 void Metric_AADS::set_system(System_of_eqs& ss, const char* name_met, const char* name_hmet)
563 {
564  syst = &ss;
565  m_place_syst = ss.ndom*ss.nvar; // position in the system
566  ss.add_var(name_hmet, *p_hmet); // unknown for the system (no name, the name is in the metric already)
567  if (ss.met != nullptr)
568  {
569  cerr << "Metric already set for the system" << endl;
570  abort() ;
571  }
572  ss.met = this;
573  ss.name_met = new char[LMAX];
574  trim_spaces(ss.name_met, name_met);
575 }
576 
577 void Metric_AADS::set_system(System_of_eqs& ss, const char* name_met, const char* name_hmet, const char* name_back_cov, const char* name_back_con, const char* name_back_ricci)
578 {
579  syst = &ss;
580  m_ads.init_system(ss, name_back_cov, name_back_con, name_back_ricci); // put background metric as a cst in the system
581  m_place_syst = ss.ndom*ss.nvar; // position in the system
582  ss.add_var(name_hmet, *p_hmet); // unknown for the system (no name, the name is in the metric already)
583  if (ss.met != nullptr)
584  {
585  cerr << "Metric already set for the system" << endl;
586  abort() ;
587  }
588  ss.met = this;
589  ss.name_met = new char[LMAX];
590  trim_spaces(ss.name_met, name_met);
591 }
592 
593 void Metric_AADS::set_system(System_of_eqs& ss, const char* name_met, const char* name_hmet, const char* name_back_cov, const char* name_back_con, const char* name_back_gam, const char* name_back_ricci)
594 {
595  syst = &ss;
596  m_ads.init_system(ss, name_back_cov, name_back_con, name_back_gam, name_back_ricci); // put background metric as a cst in the system
597  m_place_syst = ss.ndom*ss.nvar; // position in the system
598  ss.add_var(name_hmet, *p_hmet); // unknown for the system (no name, the name is in the metric already)
599  if (ss.met != nullptr)
600  {
601  cerr << "Metric already set for the system" << endl;
602  abort() ;
603  }
604  ss.met = this;
605  ss.name_met = new char[LMAX];
606  trim_spaces(ss.name_met, name_met);
607 }
608 
610 {
611  return &m_ads;
612 }}
reference set(const Index &pos)
Read/write of an element.
Definition: array.hpp:186
Describes the tensorial basis used by the various tensors.
Definition: base_tensor.hpp:49
virtual double get_rmax() const
Returns the maximum radius.
Definition: domain.cpp:1369
Val_domain const & get_cart(int i) const
Returns a Cartesian coordinates.
Definition: space.hpp:1471
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
void set_start()
Sets the position to zero in all dimensions.
Definition: index.hpp:88
bool inc(int increm, int var=0)
Increments the position of the Index.
Definition: index.hpp:99
Class to manage asymptotically anti de Sitter metrics.
Term_eq derive_simple(const Term_eq &so) const
Computes the covariant derivative.
Vector * p_der_eps
Pointer on the vector containing the derivative of the conformal factor .
Metric_ADS m_ads
Background metric(i.e. ADS metric).
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.
double m_L
AdS length.
virtual void compute_christo(int d) const
Computes the Christoffel symbols, in a given Domain.
virtual void update()
Updates the derived quantities (Christoffels etc..) This is done only for the ones that are needed,...
Definition: metric_AADS.cpp:87
Metric_AADS(const Space &space, Metric_tensor &hmet)
Standard constructor.
Definition: metric_AADS.cpp:22
void set_system(System_of_eqs &syst, const char *name_met, const char *name_hmet)
Associates the metric to a given system of equations.
virtual void compute_ricci_scalar(int d) const
Computes the Ricci scalar, in a given Domain.
virtual void compute_ricci_tensor(int d) const
Computes the Ricci tensor, in a given Domain.
virtual void compute_cov(int d) const
Computes the covariant representation, in a given Domain.
Definition: metric_AADS.cpp:92
int m_nd
number of physical domains (usually the last compaxtified domain is discarded).
Term_eq ** p_h
Pointers on the differences between the covariant metric and the covariant background.
virtual void compute_con(int d) const
Computes the contravariant representation, in a given Domain.
Base_tensor * p_basis
Pointer on the tensorial basis (Cartesian basis only).
virtual const Metric * get_background() const
virtual Term_eq derive(int type_der, char ind_der, const Term_eq &so) const
Computes the covariant derivative of a Term_eq (assumes Cartesian basis of decomposition).
Term_eq ** p_k
Pointers on the differences between the contravariant metric and the contravariant background.
int m_place_syst
Where is the unknown h in the system of equations.
Metric_tensor * p_hmet
: the discrepancy between covariant metric and contravariant background.
void init_system(System_of_eqs &syst, const char *name_back_cov, const char *name_back_con, const char *name_back_ricci)
Put the covariant and contravariant metric, dans the Ricci background into the System_of_eqs,...
Definition: metric_ADS.cpp:370
Scalar m_rho2
Scalar containing
Definition: metric_AADS.hpp:49
Particular type of Tensor, dedicated to the desription of metrics.
Purely abstract class for metric handling.
Definition: metric.hpp:39
int type_tensor
States if one works in the CON or COV representation.
Definition: metric.hpp:86
MMPtr_array< Term_eq > p_ricci_tensor
Array of pointers on various Term_eq.
Definition: metric.hpp:70
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
MMPtr_array< Term_eq > p_christo
Array of pointers on various Term_eq.
Definition: metric.hpp:60
MMPtr_array< Term_eq > p_ricci_scalar
Array of pointers on various Term_eq.
Definition: metric.hpp:75
const System_of_eqs * syst
Pointer of the system of equations where the metric is used (only one for now).
Definition: metric.hpp:44
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
Class used to describe and solve a system of equations.
virtual void add_var(const char *name, double &var)
Addition of a variable (number case)
int ndom
Number of domains used.
char * name_met
Name by which the metric is recognized.
Metric * met
Pointer on the associated Metric, if defined.
int nvar
Number of unknown fields.
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
int get_index_type(int i) const
Gives the type (covariant or contravariant) of a given index.
Definition: tensor.hpp:526
int get_valence() const
Returns the valence.
Definition: tensor.hpp:509
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_zero()
Sets the variation of the approriate type to zero.
Definition: term_eq.cpp:187
Tensor const & get_val_t() const
Definition: term_eq.hpp:355
Tensor const & get_der_t() const
Definition: term_eq.hpp:369
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
A class derived from Tensor to deal specificaly with objects of valence 1 (and so also 1-forms).
Definition: vector.hpp:41
Scalar & set(int)
Read/write access to a component.