KADATH
tensor_math_one_dom.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 "scalar.hpp"
21 #include "tensor_impl.hpp"
22 #include "tensor.hpp"
23 namespace Kadath {
24 void affecte_one_dom (int dd, Tensor* res, const Tensor* so) {
25  if ((so->is_name_affected()) && (!res->is_name_affected())) {
26  res->set_name_affected() ;
27  for (int i=0 ; i<res->get_valence() ; i++)
28  res->set_name_ind(i, so->get_name_ind()[i]) ;
29  }
30 
31  if (!so->is_name_affected()) {
32  for (int i=0 ; i<res->get_n_comp() ; i++) {
33  Array<int> ind (res->indices(i)) ;
34  res->set(ind).set_domain(dd) = (*so)(ind)(dd) ;
35  }
36  }
37  else {
38  Array<int> perm (so->valence) ;
39  bool same_ind = res->find_indices(*so, perm) ;
40  if (!same_ind) {
41  cerr << "Indices do not match in affecte_one_dom" << endl ;
42  abort() ;
43  }
44  Array<int> ind_so (so->valence) ;
45 
46  for (int i=0 ; i<res->get_n_comp() ; i++) {
47  Array<int> ind (res->indices(i)) ;
48  for (int j=0 ; j<so->valence ; j++)
49  ind_so.set(perm(j)) = ind(j) ;
50  res->set(ind).set_domain(dd) = (*so)(ind_so)(dd) ;
51  }
52  }
53 }
54 
55 Tensor add_one_dom (int dd, const Tensor & t1, const Tensor & t2) {
56  assert (&t1.espace==&t2.espace) ;
57 
58  assert (t1.valence == t2.valence) ;
59  if (t1.valence != 0) {
60  assert (t1.basis.get_basis(dd) == t2.basis.get_basis(dd)) ;
61  }
62  // Check same type :
63  bool same = ((t1.give_place_array==t2.give_place_array) && (t1.give_place_index==t2.give_place_index) && (t1.give_indices==t2.give_indices)) ?
64  true : false ;
65 
66  Tensor aux (t1.espace, t1.valence, t1.type_indice, t1.basis) ;
67  int ncmp = (same) ? t1.n_comp : aux.n_comp ;
68  Tensor res (t1.espace, t1.valence, t1.type_indice, ncmp, t1.basis) ;
69 
70  if (same) {
72  res.give_place_index = t1.give_place_index ;
73  res.give_indices = t1.give_indices ;
74  }
75  else {
76  res.give_place_array = aux.give_place_array ;
77  res.give_place_index = aux.give_place_index ;
78  res.give_indices = aux.give_indices ;
79  }
80 
81 
82  // Case when one does not care about the indices :
83  if ((!t1.name_affected) || (!t2.name_affected)) {
84 
85  for (int i=0 ; i<t1.valence ; i++)
86  assert(t1.type_indice(i) == t2.type_indice(i)) ;
87 
88  for (int i=0 ; i<res.n_comp ; i++) {
89  Array<int> ind (res.indices(i)) ;
90  res.set(ind).set_domain(dd) = t1(ind)(dd) + t2(ind)(dd) ;
91  }
92  }
93  else {
94 
95  // Res with the same indices as t1
96  res.name_affected= true ;
97  for (int i=0 ; i<t1.valence ; i++)
98  res.name_indice[i] = t1.name_indice[i] ;
99 
100  // Find the permutation :
101  Array<int> perm (t1.valence) ;
102  bool same_ind = t1.find_indices(t2, perm) ;
103  if (!same_ind) {
104  cerr << "Indices do not match in add_one_dom" << endl ;
105  abort() ;
106  }
107  else
108  for (int i=0 ; i<res.n_comp ; i++) {
109  Array<int> ind (res.indices(i)) ;
110  Array<int> ind_t2 (t1.valence) ;
111  for (int j=0 ; j<t1.valence ; j++)
112  ind_t2.set(perm(j)) = ind(j) ;
113  res.set(ind).set_domain(dd) = t1(ind)(dd) + t2(ind_t2)(dd) ;
114  }
115  }
116 
117  // Put parameters :
118  int m_res = add_m_quant (t1.get_parameters(), t2.get_parameters()) ;
119  if (m_res!=0) {
120  res.set_parameters().set_m_quant() = m_res ;
121  }
122 
123  return res ;
124 }
125 
126 Tensor add_one_dom (int dd, const Tensor& t, double xx) {
127  Tensor res(t.espace, t.valence, t.type_indice, t.n_comp, t.basis) ;
130  res.give_indices = t.give_indices ;
131  for (int i=0 ; i<res.n_comp ; i++)
132  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)+xx ;
133 
134  // Copy parameters in this case...
135  if (t.parameters)
136  res.parameters = t.get_parameters() ;
137  return res ;
138 }
139 
140 Tensor add_one_dom (int dd, double xx, const Tensor& t) {
141  Tensor res(t.espace, t.valence, t.type_indice, t.n_comp, t.basis) ;
144  res.give_indices = t.give_indices ;
145  for (int i=0 ; i<res.n_comp ; i++)
146  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)+xx ;
147 
148  // Copy parameters in this case...
149  if (t.parameters)
150  res.parameters = t.get_parameters() ;
151  return res ;
152 }
153 
154 Tensor sub_one_dom (int dd, const Tensor & t1, const Tensor & t2) {
155  assert (&t1.espace==&t2.espace) ;
156 
157  assert (t1.valence == t2.valence) ;
158  if (t1.valence != 0) {
159  assert (t1.basis.get_basis(dd) == t2.basis.get_basis(dd)) ;
160  }
161 
162  // Check same type :
163  bool same = ((t1.give_place_array==t2.give_place_array) && (t1.give_place_index==t2.give_place_index) && (t1.give_indices==t2.give_indices)) ?
164  true : false ;
165  Tensor aux (t1.espace, t1.valence, t1.type_indice, t1.basis) ;
166  int ncmp = (same) ? t1.n_comp : aux.n_comp ;
167  Tensor res (t1.espace, t1.valence, t1.type_indice, ncmp, t1.basis) ;
168 
169  if (same) {
171  res.give_place_index = t1.give_place_index ;
172  res.give_indices = t1.give_indices ;
173  }
174  else {
175  res.give_place_array = aux.give_place_array ;
176  res.give_place_index = aux.give_place_index ;
177  res.give_indices = aux.give_indices ;
178  }
179 
180  // Case when one does not care about the indices :
181  if ((!t1.name_affected) || (!t2.name_affected)) {
182 
183  for (int i=0 ; i<t1.valence ; i++)
184  assert(t1.type_indice(i) == t2.type_indice(i)) ;
185 
186  for (int i=0 ; i<res.n_comp ; i++) {
187  Array<int> ind (res.indices(i)) ;
188  res.set(ind).set_domain(dd) = t1(ind)(dd) - t2(ind)(dd) ;
189  }
190  }
191  else {
192 
193  // Res with the same indices as t1
194  res.name_affected= true ;
195  for (int i=0 ; i<t1.valence ; i++)
196  res.name_indice[i] = t1.name_indice[i] ;
197 
198  // Find the permutation :
199  Array<int> perm (t1.valence) ;
200  bool same_ind = t1.find_indices(t2, perm) ;
201  if (!same_ind) {
202  cerr << "Indices do not match in sub_one_dom" << endl ;
203  abort() ;
204  }
205  else
206  for (int i=0 ; i<res.n_comp ; i++) {
207  Array<int> ind (res.indices(i)) ;
208  Array<int> ind_t2 (t1.valence) ;
209  for (int j=0 ; j<t1.valence ; j++)
210  ind_t2.set(perm(j)) = ind(j) ;
211  res.set(ind).set_domain(dd) = t1(ind)(dd) - t2(ind_t2)(dd) ;
212  }
213  }
214 
215  // Put parameters :
216  int m_res = add_m_quant (t1.get_parameters(), t2.get_parameters()) ;
217  if (m_res!=0) {
218  res.set_parameters().set_m_quant() = m_res ;
219  }
220 
221  return res ;
222 }
223 
224 Tensor sub_one_dom (int dd, const Tensor& t, double xx) {
225  Tensor res(t.espace, t.valence, t.type_indice, t.n_comp, t.basis) ;
228  res.give_indices = t.give_indices ;
229  for (int i=0 ; i<res.n_comp ; i++)
230  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)-xx ;
231  // Copy parameters in this case...
232  if (t.parameters)
233  res.parameters = t.get_parameters() ;
234  return res ;
235 }
236 
237 Tensor sub_one_dom (int dd, double xx, const Tensor& t) {
238  Tensor res(t.espace, t.valence, t.type_indice, t.n_comp, t.basis) ;
241  res.give_indices = t.give_indices ;
242  for (int i=0 ; i<res.n_comp ; i++)
243  res.cmp[i]->set_domain(dd) = -t(res.indices(i))(dd)+xx ;
244  // Copy parameters in this case...
245  if (t.parameters) res.parameters = t.get_parameters() ;
246  return res ;
247 }
248 
249 Tensor mult_one_dom (int dd, const Tensor& t1, const Tensor& t2) {
250  assert (&t1.espace==&t2.espace) ;
251 
252  if ((t1.valence!=0) && (t2.valence!=0))
253  assert (t1.basis.get_basis(dd)==t2.basis.get_basis(dd)) ;
254 
255  bool do_name = true ;
256  if ((!t1.name_affected) && (t1.valence!=0))
257  do_name = false ;
258  if ((!t2.name_affected) && (t2.valence!=0))
259  do_name = false ;
260 
261  if (!do_name) {
262  // Standard product
263  int val_res = t1.valence+t2.valence ;
264  Array<int> ind_res (val_res) ;
265  for (int i=0 ; i<t1.valence ; i++)
266  ind_res.set(i) = t1.type_indice(i) ;
267  for (int i=0 ; i<t2.valence ; i++)
268  ind_res.set(i+t1.valence) = t2.type_indice(i) ;
269 
270  const Base_tensor& base = (t1.valence!=0) ? t1.basis : t2.basis ;
271  Tensor res (t1.espace, val_res, ind_res, base) ;
272 
273  Array<int> ind1 (t1.valence) ;
274  Array<int> ind2 (t2.valence) ;
275  for (int i=0 ; i<res.n_comp ; i++) {
276  ind_res = res.indices(i) ;
277  for (int j=0 ; j<t1.valence ; j++)
278  ind1.set(j) = ind_res(j) ;
279  for (int j=0 ; j<t2.valence ; j++)
280  ind2.set(j) = ind_res(j+t1.valence) ;
281  res.set(ind_res).set_domain(dd) = (t1(ind1))(dd) * (t2(ind2))(dd) ;
282  }
283 
284  // Put parameters :
285  int m_res = mult_m_quant (t1.get_parameters(), t2.get_parameters()) ;
286  if (m_res!=0) {
287  res.set_parameters().set_m_quant() = m_res ;
288  }
289 
290  return res ;
291  }
292  else {
293 
294  // Check if one needs to sum on some indices :
295  Array<int> sum_1 (t1.valence) ;
296  Array<int> sum_2 (t2.valence) ;
297  for (int i=0 ; i<t2.valence ; i++)
298  sum_2.set(i) = -1 ;
299 
300  for (int i=0 ; i<t1.valence ; i++) {
301  sum_1.set(i) = -1 ;
302  for (int j=0 ; j<t2.valence ; j++)
303  if (t1.name_indice[i]==t2.name_indice[j]){
304  sum_1.set(i) = j ;
305  sum_2.set(j) = i ;
306  }
307  if ((sum_1(i)!=-1) && (t1.type_indice(i)==t2.type_indice(sum_1(i)))) {
308  cerr << "Can not sum on indices of the same type in operator*" << endl ;
309  abort() ;
310  }
311  }
312 
313  // Valence of the result
314  int val_res = 0 ;
315  for (int i=0 ; i<t1.valence ; i++)
316  if (sum_1(i)==-1)
317  val_res ++ ;
318  for (int i=0 ; i<t2.valence ; i++)
319  if (sum_2(i)==-1)
320  val_res ++ ;
321 
322  if (val_res>0) {
323 
324  // Type on indices
325  Array<int> ind_res (val_res) ;
326  int conte = 0 ;
327  for (int i=0 ; i<t1.valence ; i++)
328  if (sum_1(i)==-1) {
329  ind_res.set(conte)=t1.type_indice(i) ;
330  conte ++ ;
331  }
332  for (int i=0 ; i<t2.valence ; i++)
333  if (sum_2(i)==-1) {
334  ind_res.set(conte) = t2.type_indice(i) ;
335  conte ++ ;
336  }
337 
338  // Le tenseur
339  const Base_tensor& base = (t1.valence!=0) ? t1.basis : t2.basis ;
340  Tensor res (t1.espace, val_res, ind_res, base) ;
341 
342  // Name of the remaining variables :
343  res.name_affected = true ;
344  conte = 0 ;
345  for (int i=0 ; i<t1.valence ; i++)
346  if (sum_1(i)==-1) {
347  res.name_indice[conte] = t1.name_indice[i] ;
348  conte ++ ;
349  }
350  for (int i=0 ; i<t2.valence ; i++)
351  if (sum_2(i)==-1) {
352  res.name_indice[conte] = t2.name_indice[i] ;
353  conte ++ ;
354  }
355 
356  Array<bool> first (res.get_n_comp()) ;
357  first = true ;
358 
359  Index pos_t1 (t1) ;
360  Index pos_t2 (t2) ;
361  Index pos_res (res) ;
362 
363  do {
364  pos_t2.set_start() ;
365  do {
366  // Check if the summation indices are the same
367  bool same = true ;
368  for (int i=0 ; i<t1.valence ; i++)
369  if (sum_1(i)!=-1)
370  if (pos_t1(i)!=pos_t2(sum_1(i)))
371  same = false ;
372  // if the same :
373  if (same) {
374  conte = 0 ;
375  for (int i=0 ; i<t1.valence ; i++)
376  if (sum_1(i)==-1) {
377  pos_res.set(conte) = pos_t1(i) ;
378  conte ++ ;
379  }
380  for (int i=0 ; i<t2.valence ; i++)
381  if (sum_2(i)==-1) {
382  pos_res.set(conte) = pos_t2(i) ;
383  conte ++ ;
384  }
385  int ind (res.position(pos_res)) ;
386  if (first(ind)) {
387  res.set(pos_res).set_domain(dd) = t1(pos_t1)(dd)*t2(pos_t2)(dd) ;
388  first.set(ind) = false ;
389  }
390  else
391  res.set(pos_res).set_domain(dd) += t1(pos_t1)(dd)*t2(pos_t2)(dd) ;
392  }
393  }
394  while (pos_t2.inc()) ;
395  }
396  while (pos_t1.inc()) ;
397 
398  // Put parameters :
399  int m_res = mult_m_quant (t1.get_parameters(), t2.get_parameters()) ;
400  if (m_res!=0) {
401  res.set_parameters().set_m_quant() = m_res ;
402  }
403  return res ;
404  }
405  else {
406  // Result is a scalar :
407  Scalar res (t1.espace) ;
408  Index pos_t1 (t1) ;
409  Index pos_t2 (t2) ;
410  int first = true ;
411 
412  do {
413  pos_t2.set_start() ;
414  do {
415  // Check if the summation indices are the same
416  bool same = true ;
417  for (int i=0 ; i<t1.valence ; i++)
418  if (sum_1(i)!=-1)
419  if (pos_t1(i)!=pos_t2(sum_1(i)))
420  same = false ;
421  // if the same :
422  if (same) {
423  if (first) {
424  res.set_domain(dd) = t1(pos_t1)(dd)*t2(pos_t2)(dd) ;
425  first = false ;
426  }
427  else
428  res.set_domain(dd) += t1(pos_t1)(dd)*t2(pos_t2)(dd) ;
429  }
430  }
431  while (pos_t2.inc()) ;
432  }
433  while (pos_t1.inc()) ;
434  // Put parameters :
435  int m_res = mult_m_quant (t1.get_parameters(), t2.get_parameters()) ;
436  if (m_res!=0) {
437  res.set_parameters().set_m_quant() = m_res ;
438  }
439  return res ;
440  }
441  }
442 }
443 
444 Tensor mult_one_dom (int dd, const Tensor& t, double xx) {
445  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
446  for (int i=0 ; i<res.n_comp ; i++)
447  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)*xx ;
448 
449  // Les indices if needed :
450  if (t.name_affected) {
451  res.name_affected= true ;
452  for (int i=0 ; i<res.valence ; i++)
453  res.set_name_ind(i, t.name_indice[i]) ;
454  }
455 // Copy parameters in this case...
456  if (t.parameters)
457  res.parameters = t.get_parameters() ;
458  return res ;
459 }
460 
461 Tensor mult_one_dom (int dd, double xx, const Tensor& t) {
462  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
463  for (int i=0 ; i<res.n_comp ; i++)
464  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)*xx ;
465 
466  // Les indices if needed :
467  if (t.name_affected) {
468  res.name_affected= true ;
469  for (int i=0 ; i<res.valence ; i++)
470  res.set_name_ind(i, t.name_indice[i]) ;
471  }
472  // Copy parameters in this case...
473  if (t.parameters)
474  res.parameters = t.get_parameters() ;
475  return res ;
476 }
477 
478 Tensor mult_one_dom (int dd, const Tensor& t, int mm) {
479  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
480  for (int i=0 ; i<res.n_comp ; i++)
481  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)*mm ;
482 
483  // Les indices if needed :
484  if (t.name_affected) {
485  res.name_affected= true ;
486  for (int i=0 ; i<res.valence ; i++)
487  res.set_name_ind(i, t.name_indice[i]) ;
488  }
489 // Copy parameters in this case...
490  if (t.parameters)
491  res.parameters = t.get_parameters() ;
492  return res ;
493 }
494 
495 Tensor mult_one_dom (int dd, int mm, const Tensor& t) {
496  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
497  for (int i=0 ; i<res.n_comp ; i++)
498  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)*mm ;
499 
500  // Les indices if needed :
501  if (t.name_affected) {
502  res.name_affected= true ;
503  for (int i=0 ; i<res.valence ; i++)
504  res.set_name_ind(i, t.name_indice[i]) ;
505  }
506  // Copy parameters in this case...
507  if (t.parameters)
508  res.parameters = t.get_parameters() ;
509  return res ;
510 }
511 
512 Tensor div_one_dom (int dd, const Tensor& t1, const Tensor& t2) {
513  if (t2.valence !=0) {
514  cerr << "Division only defined for a scalar" << endl ;
515  abort() ;
516  }
517  Tensor res(t1.espace, t1.valence, t1.type_indice, t1.basis) ;
518 
519  for (int i=0 ; i<res.n_comp ; i++)
520  res.cmp[i]->set_domain(dd) = t1(res.indices(i))(dd)/(*t2.cmp[0])(dd) ;
521 
522  // Les indices if needed :
523  if (t1.name_affected) {
524  res.name_affected= true ;
525  for (int i=0 ; i<res.valence ; i++)
526  res.set_name_ind(i, t1.name_indice[i]) ;
527  }
528 
529  // Put parameters :
530  int m_res = div_m_quant (t1.get_parameters(), t2.get_parameters()) ;
531  if (m_res!=0) {
532  res.set_parameters().set_m_quant() = m_res ;
533  }
534  return res ;
535 }
536 
537 
538 Tensor div_one_dom (int dd, double x, const Tensor& t) {
539  if (t.valence !=0) {
540  cerr << "Division only defined for a scalar" << endl ;
541  abort() ;
542  }
543  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
544 
545  res.cmp[0]->set_domain(dd) = x/(*t.cmp[0])(dd) ;
546 
547  // Copy parameters in this case...
548  int m_res = inv_m_quant (t.get_parameters()) ;
549  if (m_res!=0) {
550  res.set_parameters().set_m_quant() = m_res ;
551  }
552  return res ;
553 }
554 
555 Tensor div_one_dom (int dd, const Tensor& t, double xx) {
556  Tensor res(t.espace, t.valence, t.type_indice, t.basis) ;
557  for (int i=0 ; i<res.n_comp ; i++)
558  res.cmp[i]->set_domain(dd) = t(res.indices(i))(dd)/xx ;
559 
560  // Les indices if needed :
561  if (t.name_affected) {
562  res.name_affected= true ;
563  for (int i=0 ; i<res.valence ; i++)
564  res.set_name_ind(i, t.name_indice[i]) ;
565  }
566 
567  // Copy parameters in this case...
568  if (t.parameters)
569  res.parameters = t.get_parameters() ;
570  return res ;
571 }
572 
573 Tensor scal_one_dom (int dd, const Tensor & t1, const Tensor & t2) {
574  assert (&t1.espace==&t2.espace) ;
575  assert (t1.valence == t2.valence) ;
576  assert (t1.valence!=0) ;
577  assert (t1.basis.get_basis(dd) == t2.basis.get_basis(dd)) ;
578 
579  Array<int> ind (t1.indices(0)) ;
580  Tensor auxi (mult_one_dom(dd, t1(ind), t2(ind))) ;
581  for (int i=1 ; i<t1.n_comp ; i++) {
582  ind = t1.indices(i) ;
583  auxi = add_one_dom(dd, auxi, mult_one_dom(dd, t1(ind), t2(ind))) ;
584  }
585 
586  return auxi ;
587 }
588 
589 
591 
592  if (!name_affected) {
593  cerr << "Names of indices must be affected in Tensor::do_summation" << endl ;
594  abort() ;
595  }
596 
597  Array<int> sum_ind (valence) ;
598  Array<int> nsame (valence) ;
599  sum_ind = -1 ;
600  nsame = 0 ;
601  for (int i=0 ; i<valence ; i++)
602  for (int j=i+1 ; j<valence ; j++) {
603  if (name_indice[i]==name_indice[j]) {
604  nsame.set(i) ++ ;
605  nsame.set(j) ++ ;
606  if ((nsame(i)>1) || (nsame(j)>1)) {
607  cerr << "Too many identical indices in Tensor::do_summation_one_dom" << endl ;
608  abort() ;
609  }
610  sum_ind.set(i) = j ;
611  sum_ind.set(j) = i ;
612  if (type_indice(i)==type_indice(j)) {
613  cerr << "Can not sum on indices of the same type in Tensor::do_summation_one_dom" << endl ;
614  abort() ;
615  }
616  }
617  }
618 
619  int valence_res = 0 ;
620  for (int i=0 ; i<valence ; i++)
621  if (nsame(i)==0)
622  valence_res ++ ;
623 
624  // difference Scalar or not :
625  if (valence_res > 0) {
626  Array<int> type_ind_res (valence_res) ;
627  char* name_ind_res = new char[valence_res] ;
628  int conte = 0 ;
629  for (int i=0 ; i<valence ; i++)
630  if (nsame(i)==0) {
631  type_ind_res.set(conte) = type_indice(i) ;
632  name_ind_res[conte] = name_indice[i] ;
633  conte ++ ;
634  }
635 
636  Tensor res (espace, valence_res, type_ind_res, basis) ;
637  res.name_affected = true ;
638  for (int i=0 ; i<valence_res ; i++)
639  res.name_indice[i] = name_ind_res[i] ;
640  delete [] name_ind_res ;
641 
642 
643  Index pos_res (res) ;
644  do {
645  res.set(pos_res).set_domain(dd) = 0 ;
646  }
647  while (pos_res.inc()) ;
648 
649  Array<bool> first (res.get_n_comp()) ;
650  first = true ;
651 
652  // Loop on the various components :
653  Index pos (*this) ;
654  do {
655  bool take = true ;
656  for (int i=0 ; i<valence ; i++)
657  if ((nsame(i)!=0) && (pos(sum_ind(i))!=pos(i)))
658  take = false ;
659 
660  if (take) {
661  conte = 0 ;
662  for (int i=0 ; i<valence ; i++)
663  if (nsame(i)==0) {
664  pos_res.set(conte)=pos(i) ;
665  conte ++ ;
666  }
667  int ind (res.position(pos_res)) ;
668  if (first(ind)) {
669  res.set(pos_res).set_domain(dd).set_base() = (*this)(pos)(dd).get_base() ;
670  first.set(ind) = false ;
671  }
672  res.set(pos_res).set_domain(dd) += (*this)(pos)(dd) ;
673  }
674  }
675  while (pos.inc()) ;
676  return res ;
677  }
678  else {
679  // Scalar case :
680  Scalar res(espace) ;
681  res.set_domain(dd) = 0 ;
682  Index pos (*this) ;
683  bool first = true ;
684  do {
685  bool take = true ;
686  for (int i=0 ; i<valence ; i++)
687  if (pos(sum_ind(i))!=pos(i))
688  take = false ;
689 
690  if (take) {
691  if (first) {
692  res.set_domain(dd).set_base() = (*this)(pos)(dd).get_base() ;
693  first = false ;
694  }
695  res.set_domain(dd) += (*this)(pos)(dd) ;
696  }
697  }
698  while (pos.inc()) ;
699  return res ;
700  }
701 }
702 
703 Tensor partial_one_dom (int dd, char ind_partial, const Tensor& so) {
704  //Check triad :
705  if ((so.valence>0) && (so.basis.get_basis(dd) != CARTESIAN_BASIS)) {
706  cerr << "Partial_one_dom only defined with respect to cartesian basis so far" << endl ;
707  abort() ;
708  }
709 
710  bool dosum = false ;
711  if (so.name_affected)
712  for (int i=0 ; i<so.valence ; i++)
713  if (ind_partial==so.name_indice[i])
714  dosum = true ;
715 
716  Array<int> type_res (so.valence+1) ;
717  type_res.set(0) = COV ;
718  for (int i=0 ; i<so.valence ; i++)
719  type_res.set(i+1) = so.type_indice(i) ;
720 
721  Base_tensor basis (so.get_space(), CARTESIAN_BASIS) ;
722 
723  Tensor res(so.espace, so.valence+1, type_res, basis) ;
724 
725  Index pos (res) ;
726  Index pos_so(so) ;
727  do {
728  for (int i=0 ; i<so.valence ; i++)
729  pos_so.set(i) = pos(i+1) ;
730  res.set(pos).set_domain(dd) = so(pos_so)(dd).der_abs(pos(0)+1) ;
731  }
732  while (pos.inc()) ;
733 
734  if ((so.name_affected) || (so.valence==0)) {
735  res.name_affected = true ;
736  res.name_indice[0] = ind_partial ;
737  for (int i=0 ; i<so.valence ; i++)
738  res.name_indice[i+1] = so.name_indice[i] ;
739  }
740 
741  if (dosum)
742  return res.do_summation_one_dom(dd) ;
743  else
744  return res ;
745 }
746 
747 Tensor sqrt_one_dom (int dd, const Tensor& t) {
748  if (t.get_valence() !=0) {
749  cerr << "sqrt_one_dom only defined for scalars" << endl ;
750  abort() ;
751  }
752  Scalar res (t.get_space()) ;
753  res.set_domain(dd) = sqrt(t()(dd)) ;
754  return res ;
755 }
756 
757 }
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 get_basis(int nd) const
Read only the basis in a given domain.
Definition: base_tensor.hpp:93
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
int & set_m_quant()
Sets .
Definition: tensor.hpp:757
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
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
void set_name_ind(int dd, char name)
Sets the name of one index ; the names must have been affected first.
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
int valence
Valence of the tensor (0 = scalar, 1 = vector, etc...)
Definition: tensor.hpp:157
void set_name_affected()
Affects the name of the indices.
Definition: tensor.hpp:435
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
Param_tensor & set_parameters()
Read/write of the parameters.
Definition: tensor.hpp:314
Memory_mapped_array< Scalar * > cmp
Array of size n_comp of pointers onto the components.
Definition: tensor.hpp:179
const Param_tensor & get_parameters() const
Returns a pointer on the possible additional parameter.
Definition: tensor.hpp:311
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_n_comp() const
Returns the number of stored components.
Definition: tensor.hpp:514
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
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
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.
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
const Space & get_space() const
Returns the Space.
Definition: tensor.hpp:499
Base_spectral & set_base()
Sets the basis of decomposition.
Definition: val_domain.hpp:126