KADATH
tensor_math.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 "scalar.hpp"
23 #include "tensor_impl.hpp"
24 #include "tensor.hpp"
25 
26 namespace Kadath {
28 
29  assert (valence == t.valence) ;
30  assert (&espace==&t.espace) ;
31 
32  basis = t.basis ;
33 
34  // Case when one does not care about the indices :
35  if ((!t.name_affected) || (!name_affected)) {
36 
37  for (int i=0 ; i<valence ; i++)
38  assert(t.type_indice(i) == type_indice(i)) ;
39 
40  for (int i=0 ; i<n_comp ; i++) {
41  int place_t = t.position(indices(i)) ;
42  *cmp[i] = *t.cmp[place_t] ;
43  }
44  }
45  else {
46  // Find the permutation :
47  Array<int> perm (valence) ;
48  bool same_ind = find_indices(t, perm) ;
49  if (!same_ind) {
50  cerr << "Indices do not match in Tensor::operator=" << endl ;
51  abort() ;
52  }
53  else
54  for (int i=0 ; i<n_comp ; i++) {
55  Array<int> ind (indices(i)) ;
56  Array<int> ind_t (valence) ;
57  for (int j=0 ; j<valence ; j++)
58  ind_t.set(perm(j)) = ind(j) ;
59  set(ind) = t(ind_t) ;
60  }
61  }
62  return *this;
63 }
64 Tensor & Tensor::operator=(double xx) {
65  for (int i=0 ; i<n_comp ; i++)
66  *cmp[i] = xx ;
67  return *this;
68 }
69 void Tensor::operator+=(const Tensor& t) {
70 
71  assert (&espace == &t.espace) ;
72  assert (valence == t.valence) ;
73  assert (basis == t.basis) ;
74 
75  // Case when one does not care about the indices :
76  if ((!t.name_affected) || (!name_affected)) {
77 
78  for (int i=0 ; i<valence ; i++)
79  assert(t.type_indice(i) == type_indice(i)) ;
80 
81  for (int i=0 ; i<n_comp ; i++) {
82  int place_t = t.position(indices(i)) ;
83  *cmp[i] += *t.cmp[place_t] ;
84  }
85  }
86  else {
87  // Find the permutation :
88  Array<int> perm (valence) ;
89  bool same_ind = find_indices(t, perm) ;
90  if (!same_ind) {
91  cerr << "Indices do not match in Tensor::operator+=" << endl ;
92  abort() ;
93  }
94  else
95  for (int i=0 ; i<n_comp ; i++) {
96  Array<int> ind (indices(i)) ;
97  Array<int> ind_t (valence) ;
98  for (int j=0 ; j<valence ; j++)
99  ind_t.set(perm(j)) = ind(j) ;
100  set(ind) += t(ind_t) ;
101  }
102  }
103 }
104 
105 void Tensor::operator-=(const Tensor& t) {
106  assert (&espace==&t.espace) ;
107  assert (valence == t.valence) ;
108  assert (basis == t.basis) ;
109 
110  // Case when one does not care about the indices :
111  if ((!t.name_affected) || (!name_affected)) {
112 
113  for (int i=0 ; i<valence ; i++)
114  assert(t.type_indice(i) == type_indice(i)) ;
115 
116  for (int i=0 ; i<n_comp ; i++) {
117  int place_t = t.position(indices(i)) ;
118  *cmp[i] -= *t.cmp[place_t] ;
119  }
120  }
121  else {
122  // Find the permutation :
123  Array<int> perm (valence) ;
124  bool same_ind = find_indices(t, perm) ;
125  if (!same_ind) {
126  cerr << "Indices do not match in Tensor::operator-=" << endl ;
127  abort() ;
128  }
129  else
130  for (int i=0 ; i<n_comp ; i++) {
131  Array<int> ind (indices(i)) ;
132  Array<int> ind_t (valence) ;
133  for (int j=0 ; j<valence ; j++)
134  ind_t.set(perm(j)) = ind(j) ;
135  set(ind) -= t(ind_t) ;
136  }
137  }
138 }
139 
140  //********************//
141  // OPERATEURS UNAIRES //
142  //********************//
143 
144 Tensor operator+(const Tensor & t) {
145 
146  return t ;
147 
148 }
149 
150 Tensor operator-(const Tensor & t) {
151 
152  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
153 
154  res.name_affected = t.name_affected ;
155  if (res.name_affected) {
156  for (int i=0 ; i<res.valence ; i++)
157  res.name_indice[i] = t.name_indice[i] ;
158  }
159 
160  for (int i=0 ; i<res.n_comp ; i++) {
161  Array<int> ind (res.indices(i)) ;
162  res.set(ind) = - (t(ind)) ;
163  }
164  return res ;
165 
166 }
167 
168  //**********
169  // ADDITION
170  //*********
171 
172 Tensor operator+(const Tensor & t1, const Tensor & t2) {
173 
174  Tensor res(t1) ;
175  res += t2 ;
176  return res ;
177 }
178 
179 
180 Scalar operator+(const Tensor& t1, const Scalar& t2) {
181  assert (t1.valence == 0) ;
182  Scalar res(t1) ;
183  res += t2 ;
184  return res ;
185 }
186 
187 Scalar operator+(const Scalar& t1, const Tensor& t2) {
188  assert (t2.valence == 0) ;
189  Scalar res(t2) ;
190  res += t1 ;
191  return res ;
192 }
193 
194 Tensor operator+ (const Tensor& t, double xx) {
195  Tensor res(t) ;
196  for (int i=0 ; i<res.n_comp ; i++){
197  Array<int> ind (res.indices(i)) ;
198  res.set(ind) = res(ind)+xx ;
199  }
200  return res ;
201 }
202 
203 Tensor operator+ (double xx, const Tensor& t) {
204  Tensor res(t) ;
205  for (int i=0 ; i<res.n_comp ; i++){
206  Array<int> ind (res.indices(i)) ;
207  res.set(ind) = res(ind)+xx ;
208  }
209  return res ;
210 }
211 
212 
213  //*************
214  // SOUSTRACTION
215  //*************
216 
217 Tensor operator-(const Tensor & t1, const Tensor & t2) {
218  Tensor res (t1) ;
219  res -= t2 ;
220  return res ;
221 }
222 
223 
224 Scalar operator-(const Tensor& t1, const Scalar& t2) {
225  assert (t1.valence == 0) ;
226  Scalar res (t1) ;
227  res -= t2 ;
228  return res ;
229 }
230 
231 Scalar operator-(const Scalar& t1, const Tensor& t2) {
232  assert (t2.valence == 0) ;
233  Scalar res (-t2) ;
234  res += t1 ;
235  return res ;
236 }
237 
238 
239 Tensor operator- (const Tensor& t, double xx) {
240  Tensor res(t) ;
241  for (int i=0 ; i<res.n_comp ; i++){
242  Array<int> ind (res.indices(i)) ;
243  res.set(ind) = res(ind)-xx ;
244  }
245  return res ;
246 }
247 
248 Tensor operator- (double xx, const Tensor& t) {
249  Tensor res(t) ;
250  for (int i=0 ; i<res.n_comp ; i++){
251  Array<int> ind (res.indices(i)) ;
252  res.set(ind) = -res(ind)+xx ;
253  }
254  return res ;
255 }
256 
257  //***************
258  // MULTIPLICATION
259  //***************
260 
261 
262 
263 Tensor operator*(const Scalar& t1, const Tensor& t2) {
264  assert (&t1.espace==&t2.espace) ;
265  Tensor res(t2) ;
266 
267  for (int ic=0 ; ic<res.n_comp ; ic++) {
268  Array<int> ind = res.indices(ic) ;
269  res.set(ind) *= t1 ;
270  }
271  return res ;
272 }
273 
274 
275 Tensor operator*(const Tensor& t2, const Scalar& t1) {
276  return t1*t2 ;
277 }
278 
279 
280 
281 Tensor operator*(double x, const Tensor& t) {
282 
283  Tensor res(t) ;
284 
285  for (int i=0 ; i<res.n_comp ; i++) {
286  Array<int> ind (res.indices(i)) ;
287  res.set(ind) *= x ;
288  }
289 
290  return res ;
291 
292 }
293 
294 
295 Tensor operator* (const Tensor& t, double x) {
296  return x * t ;
297 }
298 
299 Tensor operator*(int m, const Tensor& t) {
300  Tensor res(t) ;
301 
302  for (int i=0 ; i<res.n_comp ; i++) {
303  Array<int> ind (res.indices(i)) ;
304  res.set(ind) *= m ;
305  }
306 
307  return res ;
308 }
309 
310 
311 Tensor operator* (const Tensor& t, int m) {
312  return m * t ;
313 }
314 
315 
316 Tensor operator* (const Tensor& t1, const Tensor& t2) {
317 
318  assert (&t1.espace==&t2.espace) ;
319 
320  if (t1.valence==0) {
321  Tensor res (Scalar(t1)*t2) ;
322  return res ;
323  }
324  else if (t2.valence==0) {
325  Tensor res (t1*Scalar(t2)) ;
326  return res ;
327  }
328  else {
329  assert (t1.basis==t2.basis) ;
330 
331  if ((!t1.name_affected) || (!t2.name_affected)) {
332  // Standard product
333  int val_res = t1.valence+t2.valence ;
334  Array<int> ind_res (val_res) ;
335  for (int i=0 ; i<t1.valence ; i++)
336  ind_res.set(i) = t1.type_indice(i) ;
337  for (int i=0 ; i<t2.valence ; i++)
338  ind_res.set(i+t1.valence) = t2.type_indice(i) ;
339 
340  const Base_tensor& base = (t1.valence!=0) ? t1.basis : t2.basis ;
341  Tensor res (t1.espace, val_res, ind_res, base) ;
342 
343  Array<int> ind1 (t1.valence) ;
344  Array<int> ind2 (t2.valence) ;
345  for (int i=0 ; i<res.n_comp ; i++) {
346  ind_res = res.indices(i) ;
347  for (int j=0 ; j<t1.valence ; j++)
348  ind1.set(j) = ind_res(j) ;
349  for (int j=0 ; j<t2.valence ; j++)
350  ind2.set(j) = ind_res(j+t1.valence) ;
351  res.set(ind_res) = t1(ind1) * t2(ind2) ;
352  }
353 
354  return res ;
355  }
356 
357  else {
358  // Case with indices name
359 
360  // Check if one needs to sum on some indices :
361  Array<int> sum_1 (t1.valence) ;
362  Array<int> sum_2 (t2.valence) ;
363  for (int i=0 ; i<t2.valence ; i++)
364  sum_2.set(i) = -1 ;
365 
366  for (int i=0 ; i<t1.valence ; i++) {
367  sum_1.set(i) = -1 ;
368  for (int j=0 ; j<t2.valence ; j++)
369  if (t1.name_indice[i]==t2.name_indice[j]){
370  sum_1.set(i) = j ;
371  sum_2.set(j) = i ;
372  }
373  if ((sum_1(i)!=-1) && (t1.type_indice(i)==t2.type_indice(sum_1(i)))) {
374  cerr << "Can not sum on indices of the same type in operator*" << endl ;
375  abort() ;
376  }
377  }
378 
379  // Valence of the result
380  int val_res = 0 ;
381  for (int i=0 ; i<t1.valence ; i++)
382  if (sum_1(i)==-1)
383  val_res ++ ;
384  for (int i=0 ; i<t2.valence ; i++)
385  if (sum_2(i)==-1)
386  val_res ++ ;
387 
388  if (val_res>0) {
389  // Type on indices
390  Array<int> ind_res (val_res) ;
391  int conte = 0 ;
392  for (int i=0 ; i<t1.valence ; i++)
393  if (sum_1(i)==-1) {
394  ind_res.set(conte)=t1.type_indice(i) ;
395  conte ++ ;
396  }
397  for (int i=0 ; i<t2.valence ; i++)
398  if (sum_2(i)==-1) {
399  ind_res.set(conte) = t2.type_indice(i) ;
400  conte ++ ;
401  }
402 
403  // Le tenseur
404  const Base_tensor& base = (t1.valence!=0) ? t1.basis : t2.basis ;
405  Tensor res (t1.espace, val_res, ind_res, base) ;
406 
407  // Name of the remaining variables :
408  res.name_affected = true ;
409  conte = 0 ;
410  for (int i=0 ; i<t1.valence ; i++)
411  if (sum_1(i)==-1) {
412  res.name_indice[conte] = t1.name_indice[i] ;
413  conte ++ ;
414  }
415  for (int i=0 ; i<t2.valence ; i++)
416  if (sum_2(i)==-1) {
417  res.name_indice[conte] = t2.name_indice[i] ;
418  conte ++ ;
419  }
420 
421  Array<bool> first (res.get_n_comp()) ;
422  first = true ;
423 
424  Index pos_t1 (t1) ;
425  Index pos_t2 (t2) ;
426  Index pos_res (res) ;
427 
428  do {
429  pos_t2.set_start() ;
430  do {
431  // Check if the summation indices are the same
432  bool same = true ;
433  for (int i=0 ; i<t1.valence ; i++)
434  if (sum_1(i)!=-1)
435  if (pos_t1(i)!=pos_t2(sum_1(i)))
436  same = false ;
437  // if the same :
438  if (same) {
439  conte = 0 ;
440  for (int i=0 ; i<t1.valence ; i++)
441  if (sum_1(i)==-1) {
442  pos_res.set(conte) = pos_t1(i) ;
443  conte ++ ;
444  }
445  for (int i=0 ; i<t2.valence ; i++)
446  if (sum_2(i)==-1) {
447  pos_res.set(conte) = pos_t2(i) ;
448  conte ++ ;
449  }
450 
451  int ind (res.position(pos_res)) ;
452  if (first(ind)) {
453  res.set(pos_res) = t1(pos_t1)*t2(pos_t2) ;
454  first.set(ind) = false ;
455  }
456  else
457  res.set(pos_res) += t1(pos_t1)*t2(pos_t2) ;
458  }
459  }
460  while (pos_t2.inc()) ;
461  }
462  while (pos_t1.inc()) ;
463 
464  return res ;
465  }
466  else {
467  // Result is a scalar :
468  Scalar res (t1.espace) ;
469  Index pos_t1 (t1) ;
470  Index pos_t2 (t2) ;
471  int first = true ;
472 
473  do {
474  pos_t2.set_start() ;
475  do {
476  // Check if the summation indices are the same
477  bool same = true ;
478  for (int i=0 ; i<t1.valence ; i++)
479  if (sum_1(i)!=-1)
480  if (pos_t1(i)!=pos_t2(sum_1(i)))
481  same = false ;
482  // if the same :
483  if (same) {
484  if (first) {
485  res = t1(pos_t1)*t2(pos_t2) ;
486  first = false ;
487  }
488  else
489  res += t1(pos_t1)*t2(pos_t2) ;
490  }
491  }
492  while (pos_t2.inc()) ;
493  }
494  while (pos_t1.inc()) ;
495  return res ;
496  }
497  }
498  }
499 }
500 
501 
502  //*********
503  // DIVISION
504  //*********
505 
506 Tensor operator/(const Tensor& t1, const Scalar& s2) {
507 
508  // Protections
509  assert(&t1.espace == &s2.espace) ;
510 
511  Tensor res(t1) ;
512 
513  for (int i=0 ; i<res.n_comp ; i++) {
514  Array<int> ind (res.indices(i)) ;
515  res.set(ind) /= s2 ;
516  }
517  return res ;
518 }
519 
520 
521 Tensor operator/ (const Tensor& t, double x) {
522 
523  if ( x == double(0) ) {
524  cerr << "Division by 0 in Tensor / double !" << endl ;
525  abort() ;
526  }
527 
528  if (x == double(1))
529  return t ;
530  else {
531  Tensor res(t) ;
532 
533  for (int i=0 ; i<res.n_comp ; i++) {
534  Array<int> ind (res.indices(i)) ;
535  res.set(ind) /= x ;
536  }
537  return res ;
538  }
539 }
540 
541 Tensor operator/ (const Tensor& t, int m) {
542 
543  return t / double(m) ;
544 }
545 
546 
547 
548 double maxval (const Tensor& target) {
549 
550  Tensor so (target) ;
551 
552 
553  double res = 0 ;
554  int ndom = so.get_space().get_nbr_domains() ;
555 
556 
557 
558  for (int c=0 ; c<so.get_n_comp() ; c++) {
559  Array<int> indices (so.indices(c)) ;
560 
561  for (int d=0 ; d<ndom ; d++)
562  if (!so(indices)(d).check_if_zero()) {
563 
564  so.set(indices).coef_i() ;
565  Index pos(so.get_space().get_domain(d)->get_nbr_points()) ;
566  do {
567 
568  double value = so(indices)(d)(pos) ;
569 
570  if (fabs(value)>res)
571  res = fabs(value) ;
572  }
573  while (pos.inc()) ;
574 
575  }
576  }
577  return res ;
578 }
579 
580 double minval (const Tensor& target) {
581 
582  Tensor so (target) ;
583 
584 
585  double res = -1 ;
586  int ndom = so.get_space().get_nbr_domains() ;
587 
588 
589 
590  for (int c=0 ; c<so.get_n_comp() ; c++) {
591  Array<int> indices (so.indices(c)) ;
592 
593  for (int d=0 ; d<ndom ; d++)
594  if (!so(indices)(d).check_if_zero()) {
595 
596  so.set(indices).coef_i() ;
597  Index pos(so.get_space().get_domain(d)->get_nbr_points()) ;
598  do {
599 
600  double value = so(indices)(d)(pos) ;
601  if (res<0)
602  res = fabs(value) ;
603 
604  if (fabs(value)<res)
605  res = fabs(value) ;
606  }
607  while (pos.inc()) ;
608 
609  }
610  }
611  return res ;
612 }
613 
614 
615 }
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
Dim_array const & get_nbr_points() const
Returns the number of points.
Definition: space.hpp:92
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
The class Scalar does not really implements scalars in the mathematical sense but rather tensorial co...
Definition: scalar.hpp:67
void coef_i() const
Computes the values in the configuration space.
Definition: scalar.hpp:574
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
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
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
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
void operator-=(const Tensor &)
-= Tensor
int valence
Valence of the tensor (0 = scalar, 1 = vector, etc...)
Definition: tensor.hpp:157
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
Memory_mapped_array< Scalar * > cmp
Array of size n_comp of pointers onto the components.
Definition: tensor.hpp:179
Scalar & set(const Array< int > &ind)
Returns the value of a component (read/write version).
Definition: tensor_impl.hpp:91
void operator+=(const Tensor &)
+= Tensor
Definition: tensor_math.cpp:69
int get_n_comp() const
Returns the number of stored components.
Definition: tensor.hpp:514
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
virtual int position(const Array< int > &idx) const
Gives the location of a given component in the array used for storage (Array version).
Definition: tensor.hpp:470
const Space & get_space() const
Returns the Space.
Definition: tensor.hpp:499