KADATH
tensor.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 /*
21  * Methods of class Tensor
22  *
23 
24  */
25 
26 
27 #include "headcpp.hpp"
28 #include "tensor.hpp"
29 #include "scalar.hpp"
30 #include "tensor_impl.hpp"
31 #include "vector.hpp"
32 #include "metric_tensor.hpp"
33 
34 namespace Kadath {
35 // Functions standard for storage :
36  int std_position_array (const Array<int>& idx, int ndim) {
37  assert (idx.get_ndim() == 1) ;
38  int valence =idx.get_size(0) ;
39 
40  for (int i=0 ; i<valence ; i++)
41  assert ((idx(i)>=1) && (idx(i)<=ndim)) ;
42  int res = 0 ;
43  for (int i=0 ; i<valence ; i++)
44  res = ndim*res+(idx(i)-1) ;
45 
46  return res;
47  }
48 
49  int std_position_index (const Index& idx, int ndim) {
50  int valence =idx.get_ndim() ;
51  for (int i=0 ; i<valence ; i++)
52  assert ((idx(i)>=0) && (idx(i)<ndim)) ;
53  int res = 0 ;
54  for (int i=0 ; i<valence ; i++)
55  res = ndim*res+(idx(i)) ;
56 
57  return res;
58  }
59 
60  Array<int> std_indices (int place, int valence, int ndim) {
61  Array<int> res(valence) ;
62  for (int i=valence-1 ; i>=0 ; i--) {
63  res.set(i) = div(place, ndim).rem ;
64  place = int((place-res(i))/ndim) ;
65  res.set(i)++ ;
66  }
67  return res ;
68  }
69 
70 
71  //--------------//
72  // Constructors //
73  //--------------//
74 
75 // Standard constructor
76 // --------------------
77  Tensor::Tensor(const Space& sp, int val, const Array<int>& tipe, const Base_tensor& bb)
78  : espace(sp), ndom(espace.get_nbr_domains()), ndim(espace.get_ndim()),
79  valence(val), basis(bb), type_indice(tipe), name_affected{false}, name_indice{valence},
80  n_comp(int(pow(espace.get_ndim(), val))), cmp{n_comp}, parameters{}
81  {
82  assert (valence >= 0) ;
83  assert (tipe.get_ndim() == 1) ;
84  assert (valence == tipe.get_size(0)) ;
85 #ifdef DEBUG_MODE
86  for (int i=0 ; i<valence ; i++)
87  assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
88 #endif
89  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace};
90 
91  // Storage methods :
92  give_place_array = std_position_array ;
93  give_place_index = std_position_index ;
94  give_indices = std_indices ;
95  }
96 
97  Tensor::Tensor(const Space& sp, int val, int tipe, const Base_tensor& bb)
98  : espace(sp), ndom(espace.get_nbr_domains()), ndim(espace.get_ndim()),
99  valence(val), basis(bb), type_indice(val), name_affected{false}, name_indice{valence},
100  n_comp(int(pow(espace.get_ndim(), val))), cmp{n_comp}, parameters{}
101  {
102  assert (valence >= 0) ;
103  assert ((tipe == COV) || (tipe == CON)) ;
104  type_indice = tipe;
105  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
106 
107  // Storage methods :
108  give_place_array = std_position_array ;
109  give_place_index = std_position_index ;
110  give_indices = std_indices ;
111  }
112 
113  Tensor::Tensor(const Space& sp, int val, const Array<int>& tipe, const Base_tensor& bb, int dim)
114  : espace(sp), ndom(espace.get_nbr_domains()), ndim(dim),
115  valence(val), basis(bb), type_indice(tipe), name_affected{false}, name_indice{valence},
116  n_comp(int(pow(ndim, val))), cmp{n_comp}, parameters{}
117  {
118  assert (valence >= 0) ;
119  assert (tipe.get_ndim() == 1) ;
120  assert (valence == tipe.get_size(0)) ;
121 #ifdef DEBUG_MODE
122  for (int i=0 ; i<valence ; i++)
123  assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
124 #endif
125  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
126 
127  // Storage methods :
128  give_place_array = std_position_array ;
129  give_place_index = std_position_index ;
130  give_indices = std_indices ;
131  }
132 
133  Tensor::Tensor(const Space& sp, int val, int tipe, const Base_tensor& bb, int dim)
134  : espace(sp), ndom(espace.get_nbr_domains()), ndim(dim),
135  valence(val), basis(bb), type_indice(val), name_affected{false}, name_indice{valence},
136  n_comp(int(pow(ndim, val))), cmp{n_comp}, parameters{}
137  {
138  assert (valence >= 0) ;
139  assert ((tipe == COV) || (tipe == CON)) ;
140  type_indice = tipe;
141  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
142 
143  // Storage methods :
144  give_place_array = std_position_array ;
145  give_place_index = std_position_index ;
146  give_indices = std_indices ;
147  }
148 
149 
150 
151 // Copy constructor
152 // ----------------
153  Tensor::Tensor (const Tensor& source, bool copy) :
154  espace(source.espace), ndom(source.ndom), ndim(source.ndim), valence(source.valence), basis(source.basis),
155  type_indice(source.type_indice), name_affected{copy && source.name_affected}, name_indice{valence},
156  n_comp (source.n_comp), cmp{n_comp}, parameters{source.parameters}
157  {
158  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{*source.cmp[i], copy} ;
159  if (name_affected) {
160  for (int i=0 ; i<valence ; i++)
161  name_indice[i] = source.name_indice[i] ;
162  }
163 
164  // Storage methods :
167  give_indices = source.give_indices ;
168  }
169 
170 // Constructor for a scalar field: to be used by the derived
171 // class {\tt Scalar}
172 //-----------------------------------------------------------
173  Tensor::Tensor(const Space& sp) : espace(sp), ndom(espace.get_nbr_domains()), ndim(espace.get_ndim()),
174  valence(0), basis(sp), type_indice(0), name_affected{false}, name_indice{},
175  n_comp{1}, cmp{1}, parameters{}
176  {
177  cmp[0] = nullptr ;
178 
179  // Storage methods :
180  give_place_array = std_position_array ;
181  give_place_index = std_position_index ;
182  give_indices = std_indices ;
183  }
184 
185  Tensor::Tensor(const Space& sp, int val, int tipe, int ncompi, const Base_tensor& bb)
186  : espace(sp), ndom(espace.get_nbr_domains()), ndim(espace.get_ndim()),
187  valence(val), basis(bb), type_indice(val), name_affected{false}, name_indice{valence},
188  n_comp(ncompi), cmp{n_comp}, parameters{}
189  {
190  assert (valence >= 0) ;
191  assert ((tipe == COV) || (tipe == CON)) ;
192  type_indice = tipe;
193  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
194  }
195 
196  Tensor::Tensor(const Space& sp, int val, const Array<int>& tipe, int ncompi, const Base_tensor& bb)
197  : espace(sp), ndom(espace.get_nbr_domains()), ndim(espace.get_ndim()),
198  valence(val), basis(bb), type_indice(tipe), name_affected{false}, name_indice{valence},
199  n_comp(ncompi), cmp{n_comp}, parameters{}
200  {
201  // Des verifs :
202  assert (valence >= 0) ;
203  assert (tipe.get_ndim() == 1) ;
204  assert (valence == tipe.get_size(0)) ;
205 #ifdef DEBUG_MODE
206  for (int i=0 ; i<valence ; i++)
207  assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
208 #endif
209  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
210  }
211 
212  Tensor::Tensor(const Space& sp, int val, int tipe, int ncompi, const Base_tensor& bb, int dim)
213  : espace(sp), ndom(espace.get_nbr_domains()), ndim(dim),
214  valence(val), basis(bb), type_indice(val), name_affected{false}, name_indice{valence},
215  n_comp(ncompi), cmp{n_comp}, parameters{}
216  {
217  assert (valence >= 0) ;
218  assert ((tipe == COV) || (tipe == CON)) ;
219  type_indice = tipe;
220  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
221  }
222 
223  Tensor::Tensor(const Space& sp, int val, const Array<int>& tipe, int ncompi, const Base_tensor& bb, int dim)
224  : espace(sp), ndom(espace.get_nbr_domains()), ndim(dim),
225  valence(val), basis(bb), type_indice(tipe), name_affected{false}, name_indice{valence},
226  n_comp(ncompi), cmp{n_comp}, parameters{}
227  {
228  // Des verifs :
229  assert (valence >= 0) ;
230  assert (tipe.get_ndim() == 1) ;
231  assert (valence == tipe.get_size(0)) ;
232 #ifdef DEBUG_MODE
233  for (int i=0 ; i<valence ; i++)
234  assert ((tipe(i) == COV) || (tipe(i) == CON)) ;
235 #endif
236  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace} ;
237  }
238 
239 
240  Tensor::Tensor (const Space& sp, FILE* fd) :
241  espace(sp), ndom(espace.get_nbr_domains()), ndim(espace.get_ndim()),
242  basis(sp, fd), type_indice(fd), name_affected{false}, name_indice{valence}, n_comp{}, cmp{}, parameters{}
243  {
244  fread_be (&valence, sizeof(int), 1, fd) ;
245  assert (type_indice.get_size(0) == valence) ;
246  fread_be (&n_comp, sizeof(int), 1, fd) ;
247  cmp.resize(n_comp);
248  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace, fd} ;
249  // Storage methods (overwritten in case of non std things)
250  give_place_array = std_position_array ;
251  give_place_index = std_position_index ;
252  give_indices = std_indices ;
253  }
254 
255  Tensor::Tensor (const Space& sp, int dim, FILE* fd) :
256  espace(sp), ndom(espace.get_nbr_domains()), ndim(dim),
257  basis(sp, fd), type_indice(fd), name_affected{false}, name_indice{valence}, n_comp{}, cmp{}, parameters{}
258  {
259  fread_be (&valence, sizeof(int), 1, fd) ;
260  assert (type_indice.get_size(0) == valence) ;
261  fread_be (&n_comp, sizeof(int), 1, fd) ;
262  cmp.resize(n_comp);
263  for (int i=0 ; i<n_comp ; i++) cmp[i] = new Scalar{espace, fd} ;
264  // Storage methods (overwritten in case of non std things)
265  give_place_array = std_position_array ;
266  give_place_index = std_position_index ;
267  give_indices = std_indices ;
268  }
269 
270  void Tensor::swap(Tensor & so) noexcept {
271  assert(&espace == &so.espace);
272  std::swap(ndom,so.ndom);
273  std::swap(ndim,so.ndim);
274  std::swap(valence,so.valence);
275  basis.swap(so.basis);
276  type_indice.swap(so.type_indice);
277  std::swap(name_affected,so.name_affected);
278  name_indice.swap(so.name_indice);
279  std::swap(n_comp,so.n_comp);
280  cmp.swap(so.cmp);
281  parameters.swap(so.parameters);
282  std::swap(give_place_array,so.give_place_array);
283  std::swap(give_place_index,so.give_place_index);
284  std::swap(give_indices,so.give_indices);
285  }
286 
287 #ifdef TENSOR_MOVE_SEMANTIC
288  Tensor::Tensor(Tensor&& so) noexcept: espace{so.espace}, ndom{so.ndom}, ndim{so.ndim}, valence{so.valence},
289  basis{std::move(so.basis)}, type_indice{std::move(so.type_indice)}, name_affected{so.name_affected},
290  name_indice{std::move(so.name_indice)}, n_comp{so.n_comp}, cmp{std::move(so.cmp)},
291  parameters{std::move(so.parameters)}, give_place_array{so.give_place_array},
292  give_place_index{so.give_place_index}, give_indices{so.give_indices}
293  {}
294 
295  void Tensor::do_move(Tensor &&so, bool move_cmp) noexcept
296  {
297  std::swap(ndom,so.ndom);
298  ndim = so.ndim;
299  valence = so.valence;
300  basis = std::move(so.basis);
301  type_indice = std::move(so.type_indice);
302  name_affected = so.name_affected;
303  std::swap(name_indice,so.name_indice);
304  std::swap(n_comp,so.n_comp);
305  if(move_cmp) cmp = std::move(so.cmp);
306  std::swap(parameters,so.parameters);
307  give_place_array = so.give_place_array;
308  give_place_index = so.give_place_index;
309  give_indices = so.give_indices;
310  }
311 
312  Tensor & Tensor::operator=(Tensor && so) noexcept
313  {
314  this->do_move(std::move(so),true);
315  return *this;
316  }
317 #endif //#ifdef TENSOR_MOVE_SEMANTIC
318  //--------------//
319  // Destructor //
320  //--------------//
321 
322 
324  for(auto & v : cmp) safe_delete(v);
325  }
326 
327  void Tensor::save (FILE* fd) const {
328  basis.save(fd) ;
329  type_indice.save(fd) ;
330  fwrite_be (&valence, sizeof(int), 1, fd) ;
331  assert (type_indice.get_size(0) == valence) ;
332  fwrite_be (&n_comp, sizeof(int), 1, fd) ;
333  for (int i=0 ; i<n_comp ; i++)
334  cmp[i]->save(fd) ;
335  }
336 
337 
338  // Le cout :
339  ostream& operator<<(ostream& flux, const Tensor &source ) {
340 
341  flux << '\n' ;
342  flux << "Class : " << typeid(source).name()
343  << " Valence : " << source.valence << '\n' ;
344 
345  if (source.valence!=0) {
346  flux << source.get_basis() << endl ;
347  }
348 
349  if (source.valence != 0) {
350  flux << "Type of the indices : " ;
351  for (int i=0 ; i<source.valence ; i++) {
352  flux << "index " << i << " : " ;
353  if (source.type_indice(i) == CON)
354  flux << " contravariant." << '\n' ;
355  else
356  flux << " covariant." << '\n' ;
357  if ( i < source.valence-1 ) flux << " " ;
358  }
359  flux << '\n' ;
360  }
361 
362  for (int i=0 ; i<source.n_comp ; i++) {
363 
364  if (source.valence == 0) {
365  flux <<
366  "===================== Scalar field ========================= \n" ;
367  }
368  else {
369  flux << "================ Component " ;
370  Array<int> num_indices (source.indices(i)) ;
371  for (int j=0 ; j<source.valence ; j++) {
372  flux << " " << num_indices(j) ;
373  }
374  flux << " ================ \n" ;
375  }
376  flux << '\n' ;
377 
378  flux << *source.cmp[i] << '\n' ;
379  }
380 
381  return flux ;
382  }
383 
384  // Sets the standard spectal bases of decomposition for each component
386  // Loop on the domains
387  for (int d=0 ; d<ndom ; d++) {
388 
389  switch (valence) {
390 
391  case 0 : {
392  if (!is_m_quant_affected())
393  cmp[0]->std_base_domain(d) ;
394  else
395  cmp[0]->std_base_domain(d, parameters.get_m_quant()) ;
396  break ;
397  }
398  case 1 : {
399  bool done = false ;
400  if (basis.get_basis(d) ==CARTESIAN_BASIS) {
401  cmp[0]->std_base_x_cart_domain(d) ;
402  cmp[1]->std_base_y_cart_domain(d) ;
403  cmp[2]->std_base_z_cart_domain(d) ;
404  done = true ;
405  }
406  if (basis.get_basis(d) == SPHERICAL_BASIS) {
407  cmp[0]->std_base_r_spher_domain(d) ;
408  cmp[1]->std_base_t_spher_domain(d) ;
409  cmp[2]->std_base_p_spher_domain(d) ;
410  done = true ;
411  }
412  if (basis.get_basis(d) == MTZ_BASIS) {
413  cmp[0]->std_base_r_mtz_domain(d) ;
414  cmp[1]->std_base_t_mtz_domain(d) ;
415  cmp[2]->std_base_p_mtz_domain(d) ;
416  done = true ;
417  }
418 #ifndef REMOVE_ALL_CHECKS
419  if (!done) {
420  cerr << "Tensor::std_base not yet implemented for " << basis << endl ;
421  abort() ;
422  }
423 #endif
424  break ;
425  }
426  default : {
427  Vector auxi (espace, CON, basis) ;
428  auxi.std_base() ;
429 
430  for (int cc=0 ; cc<n_comp ; cc++) {
431  Array<int> ind (indices(cc)) ;
432  Base_spectral result (auxi(ind(0))(d).get_base()) ;
433  for (int i=1 ; i<valence ; i++)
434  result = espace.get_domain(d)->mult(result, auxi(ind(i))(d).get_base()) ;
435  cmp[cc]->set_domain(d).set_base() = result ;
436 
437  }
438  }
439  break ;
440  }
441  }
442  }
443 
444 
445  bool Tensor::find_indices (const Tensor& tt, Array<int>& perm) const {
446 
447  assert (name_affected) ;
448  bool res = true ;
449  Array<bool> found (valence) ;
450  found = false ;
451  for (int ncmp=0 ; ncmp<valence ; ncmp++) {
452  int pos=0 ;
453  bool finloop = false ;
454  do {
455  if ((!found(pos)) && (tt.name_indice[pos]==name_indice[ncmp])) {
456  found.set(pos) = true ;
457  perm.set(ncmp) = pos ;
458  finloop = true ;
459  // Check valence :
460  if (type_indice(ncmp) != tt.type_indice(pos))
461  res = false ;
462  }
463  pos ++ ;
464  if ((pos == valence) && (!finloop)) {
465  finloop = true ;
466  res = false ;
467  }
468  }
469  while ((!finloop) && (res));
470  }
471  return res ;
472  }
473 
475  {
476  for (int d(0) ; d <= espace.get_nbr_domains() - 1 ; ++d)
477  {
479  auxi = espace.get_domain(d)->change_basis_spher_to_cart(d, *this);
480  Index pos(auxi);
481  do
482  {
483  set(pos).set_domain(d) = auxi(pos)(d);
484  }while(pos.inc());
485  set_basis(d) = CARTESIAN_BASIS;
486  }
487  }
488 
490  {
491  for (int d(0) ; d <= espace.get_nbr_domains() - 1 ; ++d)
492  {
494  auxi = espace.get_domain(d)->change_basis_cart_to_spher(d, *this);
495  Index pos(auxi);
496  do
497  {
498  set(pos).set_domain(d) = auxi(pos)(d);
499  }while(pos.inc());
500  set_basis(d) = SPHERICAL_BASIS;
501  }
502  }
503 
504 
505 
506 }
reference set(const Index &pos)
Read/write of an element.
Definition: array.hpp:186
int get_ndim() const
Returns the number of dimensions.
Definition: array.hpp:323
int get_size(int i) const
Returns the size of a given dimension.
Definition: array.hpp:331
void save(FILE *fd, Array_ordering order=last_index) const
Save in a file.
Definition: array.hpp:502
Class for storing the basis of decompositions of a field.
Describes the tensorial basis used by the various tensors.
Definition: base_tensor.hpp:49
int get_basis(int nd) const
Read only the basis in a given domain.
Definition: base_tensor.hpp:93
void save(FILE *fd) const
Saving function.
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
Definition: domain.cpp:966
virtual Tensor change_basis_cart_to_spher(int dd, const Tensor &so) const
Changes the tensorial basis from Cartsian to spherical in a given domain.
Definition: domain.cpp:1357
virtual Tensor change_basis_spher_to_cart(int dd, const Tensor &so) const
Changes the tensorial basis from spherical to Cartesian in a given domain.
Definition: domain.cpp:1363
Class that gives the position inside a multi-dimensional Array.
Definition: index.hpp:38
bool inc(int increm, int var=0)
Increments the position of the Index.
Definition: index.hpp:99
int get_m_quant() const
Returns .
Definition: tensor.hpp:747
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_nbr_domains() const
Returns the number of Domains.
Definition: space.hpp:1375
Tensor handling.
Definition: tensor.hpp:149
virtual ~Tensor()
Destructor.
Definition: tensor.cpp:323
bool name_affected
Indicator that states if the indices have been given names.
Definition: tensor.hpp:172
Memory_mapped_array< char > name_indice
If the indices haves names they are stored here.
Definition: tensor.hpp:176
void swap(Tensor &) noexcept
Swap method.
Definition: tensor.cpp:270
virtual Tensor & operator=(const Tensor &)
Assignment to a Tensor.
Definition: tensor_math.cpp:27
Base_tensor basis
Tensorial basis with respect to which the tensor components are defined.
Definition: tensor.hpp:163
void change_basis_spher_to_cart()
Changes the tensorial basis from orthonormal spherical to Cartesian.
Definition: tensor.cpp:474
bool find_indices(const Tensor &tt, Array< int > &output_ind) const
Checks whether the current Tensor and tt have compatible indices (i.e.
Definition: tensor.cpp:445
int ndom
The number of Domain.
Definition: tensor.hpp:155
Tensor(const Space &sp, int val, const Array< int > &tipe, const Base_tensor &ba)
Constructor.
Definition: tensor.cpp:77
int valence
Valence of the tensor (0 = scalar, 1 = vector, etc...)
Definition: tensor.hpp:157
int(* give_place_index)(const Index &, int)
Pointer on the function that gives the storage location corresponding to a set of indices values....
Definition: tensor.hpp:185
Array< int > type_indice
1D array of integers of size valence containing the type of each index: COV for a covariant one and C...
Definition: tensor.hpp:170
Param_tensor parameters
Possible additional parameters relevant for the current Tensor.
Definition: tensor.hpp:181
Array< int >(* give_indices)(int, int, int)
Pointer on the function that gives the indices corresponding to a give storage location.
Definition: tensor.hpp:186
virtual void std_base()
Sets the standard spectal bases of decomposition for each component.
Definition: tensor.cpp:385
Memory_mapped_array< Scalar * > cmp
Array of size n_comp of pointers onto the components.
Definition: tensor.hpp:179
Array< int > get_index_type() const
Definition: tensor.hpp:531
void change_basis_cart_to_spher()
Changes the tensorial basis from Cartesian to orthonormal spherical.
Definition: tensor.cpp:489
const Base_tensor & get_basis() const
Returns the vectorial basis (triad) on which the components are defined.
Definition: tensor.hpp:504
virtual void save(FILE *) const
Saving operator.
Definition: tensor.cpp:327
Scalar & set()
Read/write for a Scalar.
Definition: tensor.hpp:364
virtual Array< int > indices(int pos) const
Gives the values of the indices corresponding to a location in the array used for storage of the comp...
Definition: tensor.hpp:484
int n_comp
Number of stored components, depending on the symmetry.
Definition: tensor.hpp:178
const Space & espace
The Space.
Definition: tensor.hpp:154
int get_valence() const
Returns the valence.
Definition: tensor.hpp:509
bool is_m_quant_affected() const
Checks whether the additional parameter is affected (used for boson stars for instance).
Definition: tensor.hpp:326
int(* give_place_array)(const Array< int > &, int)
Pointer on the function that gives the storage location corresponding to a set of indices values....
Definition: tensor.hpp:184
int & set_basis(int dd)
Assigns a new tensorial basis in a given domain.
Definition: tensor.hpp:331
A class derived from Tensor to deal specificaly with objects of valence 1 (and so also 1-forms).
Definition: vector.hpp:41