KADATH
ope_inverse.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 "ope_eq.hpp"
21 #include "scalar.hpp"
22 #include "tensor_impl.hpp"
23 namespace Kadath {
24 Ope_inverse::Ope_inverse (const System_of_eqs* zesys, Ope_eq* target) : Ope_eq(zesys, target->get_dom(), 1) {
25  parts[0] = target ;
26 }
27 
29 }
30 
32 
33  Term_eq target (parts[0]->action()) ;
34 
35  // Various checks
36  if (target.type_data != TERM_T) {
37  cerr << "Ope_inverse only defined with respect for a tensor" << endl ;
38  abort() ;
39  }
40  if (target.val_t->get_valence()!=2) {
41  cerr << "Ope_inverse only defined with respect to a second order tensor" << endl ;
42  abort() ;
43  }
44  if (target.val_t->get_index_type(0)!=target.val_t->get_index_type(1)) {
45  cerr << "Ope_inverse only defined with respect to a tensor which indices are of the same type" << endl ;
46  abort() ;
47  }
48  int typeresult = - target.val_t->get_index_type(0) ;
49  int dim = target.val_t->get_space().get_ndim() ;
50 
51  bool m_doder = (target.der_t==0x0) ? false : true ;
52 
53  Term_eq** res(new Term_eq* [dim*(dim + 1)/2]); // 6 components to compute...
54  Scalar val(target.val_t->get_space()); // val and cmpval are more or less the same intermediate, but with different types
55  Scalar der(target.val_t->get_space());
56  Val_domain cmpval(target.val_t->get_space().get_domain(dom));
57  Val_domain cmpder(target.val_t->get_space().get_domain(dom));
58 
59  Val_domain detval(target.val_t->get_space().get_domain(dom)); // let's compute the determinant...
60  Val_domain detder(target.val_t->get_space().get_domain(dom)); // ... and its automatic derivative
61  detval = 0.0;
62  detder = 0.0;
63 
64  // compute determinant as a sum over permutations
65  double signature; // signature of the permutation
66  gsl_permutation* p(gsl_permutation_calloc(dim)); // initialise to identity 0, 1, 2
67  do
68  {
69  signature = sign(p);
70  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
71  int p2(static_cast<int>(gsl_permutation_get(p, 1)) + 1);
72  int p3(static_cast<int>(gsl_permutation_get(p, 2)) + 1);
73  detval += signature * (*target.val_t)(p1, 1)(dom) * (*target.val_t)(p2, 2)(dom) * (*target.val_t)(p3, 3)(dom); // sum on permutations
74  if (m_doder)
75  {
76  detder += signature *((*target.der_t)(p1, 1)(dom) * (*target.val_t)(p2, 2)(dom) * (*target.val_t)(p3, 3)(dom)
77  + (*target.val_t)(p1, 1)(dom) * (*target.der_t)(p2, 2)(dom) * (*target.val_t)(p3, 3)(dom)
78  + (*target.val_t)(p1, 1)(dom) * (*target.val_t)(p2, 2)(dom) * (*target.der_t)(p3, 3)(dom));
79  }
80  }while(gsl_permutation_next(p) == GSL_SUCCESS);
81  gsl_permutation_free(p);
82 
83  // compute the transposed comatrix
84  p = gsl_permutation_calloc(dim - 1); // initialise to identity 0, 1
85  for (int i(1) ; i <= dim ; ++i) // sum over components, only the upper triangular part
86  {
87  for (int j(i) ; j <= dim ; ++j)
88  {
89  cmpval = 0.0; // initialise to 0 before each computation
90  cmpder = 0.0; // initialise to 0 before each computation
91  do
92  {
93  signature = sign(p);
94  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
95  int p2(static_cast<int>(gsl_permutation_get(p, 1)) + 1);
96  vector<int> index1, index2; // manage the indices of the transposed comatrix
97  index1 = ind_com(i, j, p1, 1); // we need to play a bit with indices to get transpose(COM(metric))
98  index2 = ind_com(i, j, p2, 2);
99  cmpval += pow(-1.0, i + j)*signature*(*target.val_t)(index1[0], index1[1])(dom)*(*target.val_t)(index2[0],index2[1])(dom); // sum on permutations
100  if (m_doder)
101  cmpder += pow(-1.0, i + j)*signature*(*target.der_t)(index1[0], index1[1])(dom)*(*target.val_t)(index2[0], index2[1])(dom)
102  + pow(-1.0, i + j)*signature*(*target.val_t)(index1[0], index1[1])(dom)*(*target.der_t)(index2[0], index2[1])(dom);
103  }while(gsl_permutation_next(p) == GSL_SUCCESS);
104  gsl_permutation_free(p) ;
105  p = gsl_permutation_calloc(dim - 1); // reinitialise to identity 0, 1, ready to be used for next component
106  val.set_domain(dom) = cmpval / detval; // now we have the component of the inverse matrix
107  if (m_doder)
108  {
109  der.set_domain(dom) = cmpder / detval - cmpval * detder / (detval*detval);
110  res[j - 1 + dim*(i - 1) - i*(i - 1)/2] = new Term_eq (dom, 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)
111  }
112  else
113  res[j - 1 + dim*(i - 1) - i*(i - 1)/2] = new Term_eq (dom, val);
114  }
115  }
116  gsl_permutation_free(p);
117 
118  // Value field :
119  Metric_tensor resval(target.val_t->get_space() , typeresult, target.val_t->get_basis());
120  Metric_tensor resder(target.val_t->get_space() , typeresult, target.val_t->get_basis());
121  for (int i(1) ; i <= dim ; ++i)
122  for (int j(i) ; j <= dim ; ++j)
123  resval.set(i, j) = res[j - 1 + dim*(i - 1) - i*(i - 1)/2]->get_val_t();
124 
125  // Der field
126  if (m_doder) {
127  for (int i(1) ; i <= dim ; ++i)
128  for (int j(i) ; j <= dim ; ++j)
129  resder.set(i, j) = res[j - 1 + dim*(i - 1) - i*(i - 1)/2]->get_der_t();
130  }
131 
132  for (int i(0) ; i < dim*(dim + 1)/2 ; ++i)
133  delete res[i];
134  delete[] res;
135 
136  if (!m_doder)
137  return Term_eq (dom, resval) ;
138  else
139  return Term_eq (dom, resval, resder) ;
140 }
141 }
Particular type of Tensor, dedicated to the desription of metrics.
Abstract class that describes the various operators that can appear in the equations.
Definition: ope_eq.hpp:32
MMPtr_array< Ope_eq > parts
Pointers of the various parts of the current operator.
Definition: ope_eq.hpp:38
int dom
Index of the Domain where the operator is defined.
Definition: ope_eq.hpp:36
Term_eq action() const override
Computes the action of the current Ope_eq using its various parts.
Definition: ope_inverse.cpp:31
Ope_inverse(const System_of_eqs *syst, Ope_eq *so)
Constructor.
Definition: ope_inverse.cpp:24
~Ope_inverse() override
Destructor.
Definition: ope_inverse.cpp:28
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
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
Class used to describe and solve a system of equations.
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
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
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
const int type_data
Flag describing the type of data :
Definition: term_eq.hpp:75
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