KADATH
domain_polar_periodic_shell_for_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 "headcpp.hpp"
21 
22 #include "utilities.hpp"
23 #include "polar_periodic.hpp"
24 #include "term_eq.hpp"
25 #include "metric.hpp"
26 #include "scalar.hpp"
27 #include "tensor_impl.hpp"
28 namespace Kadath {
29 
31 
32 
33 
34  int dom = so.get_dom() ;
35  int val_res = so.val_t->get_valence() + 1 ;
36  Array<int> type_ind (val_res) ;
37  type_ind.set(0) = COV ;
38  for (int i=1 ; i<val_res ; i++)
39  type_ind.set(i) = so.val_t->get_index_type(i-1) ;
40 
41  Base_tensor basis (so.get_val_t().get_space()) ;
42  basis.set_basis(dom) = SPHERICAL_BASIS ;
43 
44  // Tensor for val
45  Tensor auxi_val (so.get_val_t().get_space(), val_res, type_ind, basis, 3) ;
46 
47  //Loop on the components :
48  Index pos_auxi(auxi_val) ;
49  Index pos_so (*so.val_t) ;
50  do {
51  for (int i=0 ; i<val_res-1 ; i++)
52  pos_so.set(i) = pos_auxi(i+1) ;
53  switch (pos_auxi(0)) {
54  case 0 :
55  // d/dr :
56  auxi_val.set(pos_auxi).set_domain(dom) = (*so.val_t)(pos_so)(dom).der_r() ;
57  break ;
58  case 1 :
59  // 1/r dtheta
60  auxi_val.set(pos_auxi).set_domain(dom) = (*so.val_t)(pos_so)(dom).der_var(2).div_r() ;
61  break ;
62  case 2 :
63  // 1/r sint d/dphi
64  auxi_val.set(pos_auxi).set_domain(dom) = 0. ;
65  break ;
66  default :
67  cerr << "Bad indice in Domain_polar_periodic_shell::derive_partial_spher" << endl ;
68  abort() ;
69  }
70  }
71  while (pos_auxi.inc()) ;
72 
73  if (so.der_t==0x0) {
74  return Term_eq (dom, auxi_val) ;
75  }
76  else {
77  // Need to compute the derivative :
78  // Tensor for der
79  Tensor auxi_der (so.get_val_t().get_space(), val_res, type_ind, basis) ;
80 
81  //Loop on the components :
82  Index pos_auxi_der(auxi_der) ;
83  do {
84  for (int i=0 ; i<val_res-1 ; i++)
85  pos_so.set(i) = pos_auxi_der(i+1) ;
86  switch (pos_auxi_der(0)) {
87  case 0 :
88  // d/dr :
89  auxi_der.set(pos_auxi_der).set_domain(dom) = (*so.der_t)(pos_so)(dom).der_r() ;
90  break ;
91  case 1 :
92  // 1/r dtheta
93  auxi_der.set(pos_auxi_der).set_domain(dom) = (*so.der_t)(pos_so)(dom).der_var(2).div_r() ;
94  break ;
95  case 2 :
96  // 1/r sint d/dphi
97  auxi_der.set(pos_auxi_der).set_domain(dom) = 0. ;
98  break ;
99  default :
100  cerr << "Bad indice in Domain_polar_periodic_shell::derive_partial_spher" << endl ;
101  abort() ;
102  }
103  }
104  while (pos_auxi_der.inc()) ;
105 
106  return Term_eq (dom, auxi_val, auxi_der) ;
107  }
108 }
109 
110 Term_eq Domain_polar_periodic_shell::derive_flat_spher (int type_der, char ind_der, const Term_eq& so, const Metric* manipulator) const {
111 
112 
113  assert ((type_der==COV) || (type_der==CON)) ;
114  int val_res = so.val_t->get_valence() + 1 ;
115 
116  bool donames = (ind_der==' ') ? false : true ;
117  bool need_sum = false ;
118 
119  Array<int> type_ind (val_res) ;
120  type_ind.set(0) = COV ;
121  for (int i=1 ; i<val_res ; i++)
122  type_ind.set(i) = so.val_t->get_index_type(i-1) ;
123 
124  if (donames) {
125  if (so.val_t->get_valence()>0)
126  assert (so.val_t->is_name_affected()) ;
127  // Need for summation ?
128  for (int i=1 ; i<val_res ; i++)
129  if (ind_der== so.val_t->get_name_ind()[i-1])
130  need_sum = true ;
131  }
132 
133  // Tensor for val
134  Base_tensor basis (so.val_t->get_space(), SPHERICAL_BASIS) ;
135  Tensor auxi_val (so.val_t->get_space(), val_res, type_ind, basis, 3) ;
136 
137  if (donames) {
138  // Set the names of the indices :
139  auxi_val.set_name_affected() ;
140  auxi_val.set_name_ind(0, ind_der) ;
141  for (int i=1 ; i<val_res ; i++)
142  auxi_val.set_name_ind(i, so.val_t->get_name_ind()[i-1]) ;
143  }
144 
145  // Part derivative
146  //Loop on the components :
147  Index pos_auxi_bis(auxi_val) ;
148  Index pos_so_bis (*so.val_t) ;
149  do {
150  for (int i=0 ; i<val_res-1 ; i++)
151  pos_so_bis.set(i) = pos_auxi_bis(i+1) ;
152  switch (pos_auxi_bis(0)) {
153  case 0 :
154  // d/dr :
155  auxi_val.set(pos_auxi_bis).set_domain(num_dom) = (*so.val_t)(pos_so_bis)(num_dom).der_r() ;
156  break ;
157  case 1 :
158  // 1/r dtheta
159  auxi_val.set(pos_auxi_bis).set_domain(num_dom) = (*so.val_t)(pos_so_bis)(num_dom).der_var(2).div_r() ;
160  break ;
161  case 2 :
162  // 1/r sint d/dphi
163  auxi_val.set(pos_auxi_bis).set_domain(num_dom)= 0 ;
164  break ;
165  default :
166  cerr << "Bad indice in Domain_polar_periodic_shell::derive_flat_spher" << endl ;
167  abort() ;
168  }
169  }
170  while (pos_auxi_bis.inc()) ;
171 
172  // Loop indice summation on connection symbols
173  for (int ind_sum=0 ; ind_sum<val_res-1 ; ind_sum++) {
174 
175  //Loop on the components :
176  Index pos_auxi(auxi_val) ;
177  Index pos_so (*so.val_t) ;
178 
179  do {
180  for (int i=0 ; i<val_res-1 ; i++)
181  pos_so.set(i) = pos_auxi(i+1) ;
182  // Different cases of the derivative index :
183  switch (pos_auxi(0)) {
184  case 0 :
185  // Dr nothing
186  break ;
187  case 1 :
188  // Dtheta
189  // Different cases of the source index
190  switch (pos_auxi(ind_sum+1)) {
191  case 0 :
192  //Dtheta S_r
193  pos_so.set(ind_sum) = 1 ;
194  auxi_val.set(pos_auxi).set_domain(num_dom) -= (*so.val_t)(pos_so)(num_dom).div_r() ;
195  break ;
196  case 1 :
197  // Dtheta S_theta
198  pos_so.set(ind_sum) = 0 ;
199  auxi_val.set(pos_auxi).set_domain(num_dom) += (*so.val_t)(pos_so)(num_dom).div_r() ;
200  break ;
201  case 2 :
202  //Dtheta S_phi
203  break ;
204  default :
205  cerr << "Bad indice in Domain_polar_periodic_shell::derive_flat_spher" << endl ;
206  abort() ;
207  }
208  break ;
209  case 2 :
210  // Dphi
211  // Different cases of the source index
212  switch (pos_auxi(ind_sum+1)) {
213  case 0 :
214  //Dphi S_r
215  pos_so.set(ind_sum) = 2 ;
216  auxi_val.set(pos_auxi).set_domain(num_dom) -= (*so.val_t)(pos_so)(num_dom).div_r() ;
217  break ;
218  case 1 :
219  // Dphi S_theta
220  pos_so.set(ind_sum) = 2 ;
221  auxi_val.set(pos_auxi).set_domain(num_dom) -= (*so.val_t)(pos_so)(num_dom).div_r().mult_cos_theta().div_sin_theta() ;
222  break ;
223  case 2 :
224  //Dphi S_phi
225  pos_so.set(ind_sum) = 0 ;
226  auxi_val.set(pos_auxi).set_domain(num_dom) += (*so.val_t)(pos_so)(num_dom).div_r() ;
227  pos_so.set(ind_sum) = 1 ;
228  auxi_val.set(pos_auxi).set_domain(num_dom) += (*so.val_t)(pos_so)(num_dom).div_r().mult_cos_theta().div_sin_theta() ;
229  break ;
230  default :
231  cerr << "Bad indice in Domain_shell::derive_flat_spher" << endl ;
232  abort() ;
233  }
234  break ;
235  default :
236  cerr << "Bad indice in Domain_shell::derive_flat_spher" << endl ;
237  abort() ;
238  }
239  }
240  while (pos_auxi.inc()) ;
241  }
242 
243  if (so.der_t==0x0) {
244 
245  // No need for derivative :
246  Term_eq auxi (num_dom, auxi_val) ;
247  // If derive contravariant : manipulate first indice :
248  if (type_der==CON)
249  manipulator->manipulate_ind (auxi, 0) ;
250 
251  if (!need_sum)
252  return auxi ;
253  else
255  }
256  else {
257 
258  // Need to compute the derivative :
259  // Tensor for der
260  Tensor auxi_der (so.val_t->get_space(), val_res, type_ind, basis) ;
261 
262  if (donames) {
263  // Set the names of the indices :
264  auxi_der.set_name_affected() ;
265  auxi_der.set_name_ind(0, ind_der) ;
266  for (int i=1 ; i<val_res ; i++)
267  auxi_der.set_name_ind(i, so.der_t->get_name_ind()[i-1]) ;
268  }
269 
270  // Part derivative
271  //Loop on the components :
272  Index pos_auxi_der_bis(auxi_der) ;
273  do {
274  for (int i=0 ; i<val_res-1 ; i++)
275  pos_so_bis.set(i) = pos_auxi_der_bis(i+1) ;
276  switch (pos_auxi_der_bis(0)) {
277  case 0 :
278  // d/dr :
279  auxi_der.set(pos_auxi_der_bis).set_domain(num_dom) = (*so.der_t)(pos_so_bis)(num_dom).der_r() ;
280  break ;
281  case 1 :
282  // 1/r dtheta
283  auxi_der.set(pos_auxi_der_bis).set_domain(num_dom) = (*so.der_t)(pos_so_bis)(num_dom).der_var(2).div_r() ;
284  break ;
285  case 2 :
286  // 1/r sint d/dphi
287  auxi_der.set(pos_auxi_der_bis).set_domain(num_dom) = 0. ;
288  break ;
289  default :
290  cerr << "Bad indice in Domain_polar_periodic_shell::derive_flat_spher" << endl ;
291  abort() ;
292  }
293  }
294  while (pos_auxi_der_bis.inc()) ;
295 
296  // Loop indice summation on connection symbols
297  for (int ind_sum=0 ; ind_sum<val_res-1 ; ind_sum++) {
298 
299  //Loop on the components :
300  Index pos_auxi_der(auxi_val) ;
301  Index pos_so (*so.val_t) ;
302 
303  do {
304  for (int i=0 ; i<val_res-1 ; i++)
305  pos_so.set(i) = pos_auxi_der(i+1) ;
306  // Different cases of the derivative index :
307  switch (pos_auxi_der(0)) {
308  case 0 :
309  // Dr nothing
310  break ;
311  case 1 :
312  // Dtheta
313  // Different cases of the source index
314  switch (pos_auxi_der(ind_sum+1)) {
315  case 0 :
316  //Dtheta S_r
317  pos_so.set(ind_sum) = 1 ;
318  auxi_der.set(pos_auxi_der).set_domain(num_dom) -= (*so.der_t)(pos_so)(num_dom).div_r() ;
319  break ;
320  case 1 :
321  // Dtheta S_theta
322  pos_so.set(ind_sum) = 0 ;
323  auxi_der.set(pos_auxi_der).set_domain(num_dom) += (*so.der_t)(pos_so)(num_dom).div_r() ;
324  break ;
325  case 2 :
326  //Dtheta S_phi
327  break ;
328  default :
329  cerr << "Bad indice in Domain_shell::derive_flat_spher" << endl ;
330  abort() ;
331  }
332  break ;
333  case 2 :
334  // Dphi
335  // Different cases of the source index
336  switch (pos_auxi_der(ind_sum+1)) {
337  case 0 :
338  //Dphi S_r
339  pos_so.set(ind_sum) = 2 ;
340  auxi_der.set(pos_auxi_der).set_domain(num_dom) -= (*so.der_t)(pos_so)(num_dom).div_r() ;
341  break ;
342  case 1 :
343  // Dphi S_theta
344  pos_so.set(ind_sum) = 2 ;
345  auxi_der.set(pos_auxi_der).set_domain(num_dom) -= (*so.der_t)(pos_so)(num_dom).div_r().mult_cos_theta().div_sin_theta() ;
346  break ;
347  case 2 :
348  //Dphi S_phi
349  pos_so.set(ind_sum) = 0 ;
350  auxi_der.set(pos_auxi_der).set_domain(num_dom) += (*so.der_t)(pos_so)(num_dom).div_r() ;
351  pos_so.set(ind_sum) = 1 ;
352  auxi_der.set(pos_auxi_der).set_domain(num_dom) += (*so.der_t)(pos_so)(num_dom).div_r().mult_cos_theta().div_sin_theta() ;
353  break ;
354  default :
355  cerr << "Bad indice in Domain_polar_periodic_shell::derive_flat_spher" << endl ;
356  abort() ;
357  }
358  break ;
359  default :
360  cerr << "Bad indice in Domain_polar_periodic_shell::derive_flat_spher" << endl ;
361  abort() ;
362  }
363  }
364  while (pos_auxi_der.inc()) ;
365  }
366 
367 
368  // Need for derivative :
369  Term_eq auxi (num_dom, auxi_val, auxi_der) ;
370  // If derive contravariant : manipulate first indice :
371  if (type_der==CON)
372  manipulator->manipulate_ind (auxi, 0) ;
373 
374 
375  if (!need_sum)
376  return auxi ;
377  else
378  // Might be in the case where der_t has been destroyed
379  if (auxi.der_t==0x0)
381  else
384  }
385 }
386 }
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
int & set_basis(int nd)
Read/write the basis in a given domain.
Definition: base_tensor.hpp:91
virtual Val_domain div_r(const Val_domain &) const
Division by .
virtual Term_eq partial_spher(const Term_eq &) const
Computes the part of the gradient containing the partial derivative of the field, in spherical orthon...
virtual Term_eq derive_flat_spher(int, char, const Term_eq &, const Metric *) const
Computes the flat derivative of a Term_eq, in spherical orthonormal coordinates.
virtual Val_domain der_r(const Val_domain &) const
Compute the radial derivative of a scalar field.
int num_dom
Number of the current domain (used by the Space)
Definition: space.hpp:63
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 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
Val_domain & set_domain(int)
Read/write of a particular Val_domain.
Definition: scalar.hpp:555
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
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.
const Space & get_space() const
Returns the Space.
Definition: tensor.hpp:499
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
int get_dom() const
Definition: term_eq.hpp:135
Tensor const & get_val_t() const
Definition: term_eq.hpp:355
Tensor * val_t
Pointer on the value, if the Term_eq is a Tensor.
Definition: term_eq.hpp:68
Val_domain div_r() const
Division by the radius.
Definition: val_domain.cpp:743
Val_domain div_sin_theta() const
Division by .
Val_domain mult_cos_theta() const
Multiplication by .