KADATH
val_domain_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 #include "headcpp.hpp"
20 #include "val_domain.hpp"
21 #include "array_math.hpp"
22 #include <gsl/gsl_sf_bessel.h>
23 
24 namespace Kadath {
25 
27  *this = *this + so ;
28 }
29 
31  *this = *this - so ;
32 }
33 
35  *this = *this * so ;
36 }
37 
39  *this = *this / so ;
40 }
41 
42 void Val_domain::operator+= (double xx) {
43  *this = *this + xx ;
44 }
45 
46 void Val_domain::operator-= (double xx) {
47  *this = *this - xx ;
48 }
49 
50 
51 void Val_domain::operator*= (double xx) {
52  *this = *this * xx ;
53 }
54 
55 
56 void Val_domain::operator/= (double xx) {
57  *this = *this / xx ;
58 }
59 
60 
61 Val_domain sin(const Val_domain& so) {
62  if (so.is_zero)
63  return so ;
64  else {
65  so.coef_i() ;
66  Val_domain res (so.zone) ;
67  res.set_in_conf() ;
68  res.c = new Array<double> (sin(*so.c)) ;
69  return res ;
70  }
71 }
72 
73 
74 Val_domain cos(const Val_domain& so ) {
75 
76  if (so.is_zero) {
77  Val_domain res(so) ;
78  res.is_zero = false ;
79  res.allocate_conf() ;
80  *res.c = 1. ;
81  res.std_base();
82  return res ;
83  }
84  else {
85  so.coef_i() ;
86  Val_domain res (so.zone) ;
87  res.set_in_conf() ;
88  res.c = new Array<double> (cos(*so.c)) ;
89  return res ;
90  }
91 }
92 
93 Val_domain cosh(const Val_domain& so ) {
94 
95  if (so.is_zero) {
96  Val_domain res(so) ;
97  res.is_zero = false ;
98  res.allocate_conf() ;
99  *res.c = 1. ;
100  res.std_base();
101  return res ;
102  }
103  else {
104  so.coef_i() ;
105  Val_domain res (so.zone) ;
106  res.set_in_conf() ;
107  res.c = new Array<double> (cosh(*so.c)) ;
108  res.std_base();
109  return res ;
110  }
111 }
112 
113 Val_domain sinh(const Val_domain& so ) {
114 
115  if (so.is_zero) {
116  Val_domain res(so) ;
117  res.is_zero = false ;
118  res.allocate_conf() ;
119  *res.c = 1. ;
120  res.std_base();
121  return res ;
122  }
123  else {
124  so.coef_i() ;
125  Val_domain res (so.zone) ;
126  res.set_in_conf() ;
127  res.c = new Array<double> (sinh(*so.c)) ;
128  res.std_base();
129  return res ;
130  }
131 }
132 
133 Val_domain operator+ (const Val_domain& so) {
134  Val_domain res (so) ;
135  return res ;
136 }
137 
138 Val_domain operator- (const Val_domain& so) {
139  Val_domain res (so) ;
140  if (so.in_conf)
141  *res.c *= -1 ;
142  if (so.in_coef)
143  *res.cf *= -1 ;
144  return res ;
145 }
146 
147 
148 Val_domain operator+ (const Val_domain& a, const Val_domain& b) {
149  assert (a.zone == b.zone) ;
150 
151  if (a.is_zero)
152  return b ;
153  else if (b.is_zero)
154  return a ;
155  else {
156  Val_domain res (a.zone) ;
157 
158  if (a.in_conf) {
159  if (!b.in_conf)
160  b.coef_i() ;
161  res.c = new Array<double> (*a.c + *b.c) ;
162  res.in_conf=true ;
163  }
164  else if (b.in_conf) {
165  if (!a.in_conf)
166  a.coef_i() ;
167  res.c = new Array<double> (*a.c + *b.c) ;
168  res.in_conf=true ;
169  }
170 
171  if (!res.in_conf) {
172  if (a.in_coef) {
173  if (!b.in_coef)
174  b.coef() ;
175  res.cf = new Array<double> (*a.cf + *b.cf) ;
176  res.in_coef=true ;
177  }
178  else if (b.in_coef) {
179  if (!a.in_coef)
180  a.coef() ;
181  res.cf = new Array<double> (*a.cf + *b.cf) ;
182  res.in_coef=true ;
183  }
184  }
185  if ((a.base.is_def()) && (b.base.is_def())) {
186  assert (a.base==b.base) ;
187  res.base = a.base ;
188  }
189 
190  return res ;
191  }
192 }
193 
194 
195 Val_domain operator+ (const Val_domain& so, double x) {
196  if (so.is_zero) {
197  Val_domain res (so.zone) ;
198  res.allocate_conf() ;
199  *res.c = x ;
200  res.std_base() ;
201  return res ;
202  }
203  else {
204  so.coef_i() ;
205  Val_domain res (so.zone) ;
206  res.set_in_conf() ;
207  res.c = new Array<double> (*so.c + x) ;
208  res.base = so.base ;
209  return res ;
210  }
211 }
212 
213 
214 Val_domain operator+ (double x, const Val_domain& so) {
215  return so+x ;
216 }
217 
218 Val_domain operator- (const Val_domain& a, const Val_domain& b) {
219  assert (a.zone == b.zone) ;
220 
221  if (a.is_zero)
222  return -b ;
223  else if (b.is_zero)
224  return a ;
225  else {
226  Val_domain res (a.zone) ;
227  if (a.in_conf) {
228  if (!b.in_conf)
229  b.coef_i() ;
230  res.c = new Array<double> (*a.c - *b.c) ;
231  res.in_conf=true ;
232  }
233  else if (b.in_conf) {
234  if (!a.in_conf)
235  a.coef_i() ;
236  res.c = new Array<double> (*a.c - *b.c) ;
237  res.in_conf=true ;
238  }
239  if (!res.in_conf) {
240  if (a.in_coef) {
241  if (!b.in_coef)
242  b.coef() ;
243  assert (a.base == b.base) ;
244  res.cf = new Array<double> (*a.cf - *b.cf) ;
245  res.in_coef=true ;
246  }
247  else if (b.in_coef) {
248  if (!a.in_coef)
249  a.coef() ;
250  res.cf = new Array<double> (*a.cf - *b.cf) ;
251  res.in_coef=true ;
252  }
253  }
254  if ((a.base.is_def()) && (b.base.is_def())) {
255  assert (a.base==b.base) ;
256  res.base = a.base ;
257  }
258 
259  return res ;
260  }
261 }
262 
263 Val_domain operator- (const Val_domain& so, double x) {
264 
265  if (so.is_zero) {
266  Val_domain res (so.zone) ;
267  res.allocate_conf() ;
268  *res.c = -x ;
269  res.std_base() ;
270  return res ;
271  }
272  else {
273  so.coef_i() ;
274  Val_domain res (so.zone) ;
275  res.set_in_conf() ;
276  res.c = new Array<double> (*so.c - x) ;
277  res.base = so.base ;
278  return res ;
279  }
280 }
281 
282 Val_domain operator- (double x, const Val_domain& so) {
283  if (so.is_zero) {
284  Val_domain res (so.zone) ;
285  res.allocate_conf() ;
286  *res.c = x ;
287  res.std_base() ;
288  return res ;
289  }
290  else {
291  so.coef_i() ;
292  Val_domain res (so.zone) ;
293  res.set_in_conf() ;
294  res.c = new Array<double> (x-*so.c) ;
295  res.base = so.base ;
296  return res ;
297  }
298 }
299 
300 Val_domain operator* (const Val_domain& a, const Val_domain& b) {
301  if (a.is_zero)
302  return a ;
303  else if (b.is_zero)
304  return b ;
305  else {
306  a.coef_i() ;
307  b.coef_i() ;
308  assert (a.zone==b.zone) ;
309  Val_domain res (a.zone) ;
310  res.allocate_conf() ;
311  *res.c = (*a.c)* (*b.c) ;
312  res.base = a.zone->mult(a.base, b.base) ;
313  return res ;
314  }
315 }
316 
317 
318 Val_domain operator* (const Val_domain& so, double x) {
319  if (so.is_zero)
320  return so ;
321  else {
322  Val_domain res (so) ;
323  if (res.in_conf)
324  *res.c *= x ;
325  if (res.in_coef)
326  *res.cf *= x ;
327  return res ;
328  }
329 }
330 
331 Val_domain operator* (double x, const Val_domain& so) {
332  return (so*x);
333 }
334 
335 Val_domain operator* (const Val_domain& so, int nn) {
336  if (so.is_zero)
337  return so ;
338  else
339  if (nn==0) {
340  Val_domain res(so, false) ;
341  res.set_zero() ;
342  return res ;
343  }
344  else {
345  Val_domain res (so) ;
346  if (res.in_conf)
347  *res.c *= nn ;
348  if (res.in_coef)
349  *res.cf *= nn ;
350  return res ;
351  }
352 }
353 
354 Val_domain operator* (int nn, const Val_domain& so) {
355  return (so*nn);
356 }
357 
358 Val_domain operator* (const Val_domain& so, long int nn) {
359  if (so.is_zero)
360  return so ;
361  else
362  if (nn==0) {
363  Val_domain res(so, false) ;
364  res.set_zero() ;
365  return res ;
366  }
367  else {
368  Val_domain res (so) ;
369  if (res.in_conf)
370  *res.c *= static_cast<double>(nn) ;
371  if (res.in_coef)
372  *res.cf *= static_cast<double>(nn) ;
373  return res ;
374  }
375 }
376 
377 Val_domain operator* (long int nn, const Val_domain& so) {
378  return (so*nn);
379 }
380 Val_domain operator/ (const Val_domain& a, const Val_domain& b) {
381  if (a.is_zero)
382  return a ;
383  else if (b.is_zero) {
384  cerr << "Division by zero" << endl ;
385  abort() ;
386  }
387  else {
388  a.coef_i() ;
389  b.coef_i() ;
390  assert (a.zone==b.zone) ;
391  Val_domain res (a.zone) ;
392  res.allocate_conf() ;
393  *res.c = (*a.c)/ (*b.c) ;
394  res.base = a.zone->mult(a.base, b.base) ;
395  return res ;
396  }
397 }
398 
399 Val_domain operator/ (const Val_domain& so, double x) {
400  if (so.is_zero)
401  return so ;
402  else {
403  Val_domain res (so) ;
404  if (res.in_conf)
405  *res.c /= x ;
406  if (res.in_coef)
407  *res.cf /= x ;
408  return res ;
409  }
410 }
411 
412 Val_domain operator/ (double x, const Val_domain& so) {
413  if (so.is_zero) {
414  cerr << "Division by zero" << endl ;
415  abort() ;
416  }
417  else {
418  so.coef_i() ;
419  Val_domain res (so.zone) ;
420  res.set_in_conf() ;
421  res.c = new Array<double> (x/ *so.c) ;
422  // No sense if the base is not the standard one !
423  res.std_base() ;
424  return res ;
425  }
426 }
427 
428 Val_domain pow (const Val_domain& so, int n) {
429  if (so.is_zero)
430  return so ;
431  else {
432  if (n<=0) {
433  so.coef_i() ;
434  Val_domain res (so.zone) ;
435  res.set_in_conf() ;
436  res.c = new Array<double> (pow(*so.c,n)) ;
437  return res ;
438  }
439  else {
440  Val_domain res (so) ;
441  for (int i=1 ; i<n ; i++)
442  res *= so ;
443  return res ;
444  }
445  }
446 }
447 
448 Val_domain pow (const Val_domain& so, double nn) {
449  if (so.is_zero)
450  return so ;
451  else {
452  so.coef_i() ;
453  Val_domain res (so.zone) ;
454  res.set_in_conf() ;
455  res.c = new Array<double> (pow(*so.c,nn)) ;
456  return res ;
457  }
458 }
459 
460 Val_domain sqrt (const Val_domain& so) {
461  if (so.is_zero)
462  return so ;
463  else {
464  so.coef_i() ;
465  Val_domain res (so.zone) ;
466  res.set_in_conf() ;
467  res.c = new Array<double> (sqrt(*so.c)) ;
468  // Provisory ? same base as so...
469  res.base = so.base ;
470  return res ;
471  }
472 }
473 
474 Val_domain exp (const Val_domain& so) {
475  if (so.is_zero) {
476  Val_domain res(so) ;
477  res.is_zero = false ;
478  res.allocate_conf() ;
479  *res.c = 1. ;
480  return res ;
481  }
482  else {
483  so.coef_i() ;
484  Val_domain res (so.zone) ;
485  res.set_in_conf() ;
486  res.c = new Array<double> (exp(*so.c)) ;
487  // Provisory ? same base as so...
488  res.base = so.base ;
489  return res ;
490  }
491 }
492 
493 Val_domain log (const Val_domain& so) {
494 
495  so.coef_i() ;
496  Val_domain res (so.zone) ;
497  res.set_in_conf() ;
498  res.c = new Array<double> (log(*so.c)) ;
499  // Provisory ? same base as so...
500  res.base = so.base ;
501  return res ;
502 }
503 
504 Val_domain atanh (const Val_domain& so) {
505 
506  so.coef_i() ;
507  Val_domain res (so.zone) ;
508  res.set_in_conf() ;
509  res.c = new Array<double> (atanh(*so.c)) ;
510  // Provisory ? same base as so...
511  res.base = so.base ;
512  return res ;
513 }
514 
515 double diffmax (const Val_domain& aa, const Val_domain& bb) {
516  aa.coef_i() ;
517  bb.coef_i() ;
518  return diffmax (*aa.c, *bb.c) ;
519 }
520 
521 Val_domain bessel_jl (const Val_domain& so, int l) {
522 
523  Val_domain res (so.get_domain()) ;
524  res.allocate_conf() ;
525  Index pos (res.get_domain()->get_nbr_points()) ;
526  do {
527  res.set(pos) = gsl_sf_bessel_jl (l, so(pos)) ;
528  }
529  while (pos.inc()) ;
530  res.std_base() ;
531  return res ;
532 }
533 
534 
535 Val_domain bessel_yl (const Val_domain& so, int l) {
536 
537  Val_domain res (so.get_domain()) ;
538  res.allocate_conf() ;
539  Index pos (res.get_domain()->get_nbr_points()) ;
540  do {
541  res.set(pos) = gsl_sf_bessel_yl (l, so(pos)) ;
542  }
543  while (pos.inc()) ;
544  res.std_base() ;
545  return res ;
546 }
547 
548 Val_domain bessel_djl (const Val_domain& so, int l) {
549 
550  Val_domain res (so.get_domain()) ;
551  res.allocate_conf() ;
552  Index pos (res.get_domain()->get_nbr_points()) ;
553  do {
554  if (l==0)
555  res.set(pos) = cos(so(pos))/so(pos) - sin(so(pos))/so(pos)/so(pos) ;
556  else
557  res.set(pos) = gsl_sf_bessel_jl (l-1, so(pos)) - (l+1) * gsl_sf_bessel_jl (l, so(pos))/so(pos) ;
558  }
559  while (pos.inc()) ;
560  res.std_base() ;
561  return res ;
562 }
563 
564 
565 Val_domain bessel_dyl (const Val_domain& so, int l) {
566 
567  Val_domain res (so.get_domain()) ;
568  res.allocate_conf() ;
569  Index pos (res.get_domain()->get_nbr_points()) ;
570  do {
571  if (l==0)
572  res.set(pos) = sin(so(pos))/so(pos) + cos(so(pos))/so(pos)/so(pos) ;
573  else
574  res.set(pos) = gsl_sf_bessel_yl (l-1, so(pos)) - (l+1) * gsl_sf_bessel_yl (l, so(pos))/so(pos) ;
575  }
576  while (pos.inc()) ;
577  res.std_base() ;
578  return res ;
579 }
580 
581 Val_domain atan (const Val_domain& so) {
582 
583  so.coef_i() ;
584  Val_domain res (so.zone) ;
585  res.set_in_conf() ;
586  res.c = new Array<double> (atan(*so.c)) ;
587  // Provisory ? same base as so...
588  res.base = so.base ;
589  return res ;
590 }
591 
592 double maxval (const Val_domain& target)
593 {
594  Val_domain so(target);
595  double res(0);
596  double value(0.0);
597  if (!so.check_if_zero())
598  {
599  so.coef_i() ;
600  Index pos(so.get_domain()->get_nbr_points()) ;
601  do
602  {
603  value = so(pos);
604  if (fabs(value) > res) res = fabs(value);
605  }while (pos.inc());
606  }
607  return res ;
608 }
609 }
610 
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
Definition: domain.cpp:966
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
bool inc(int increm, int var=0)
Increments the position of the Index.
Definition: index.hpp:99
Class for storing the basis of decompositions of a field and its values on both the configuration and...
Definition: val_domain.hpp:69
void operator/=(const Val_domain &)
Operator /=.
Base_spectral base
Spectral basis of the field.
Definition: val_domain.hpp:72
void set_in_conf()
Destroys the values in the coefficient space.
Definition: val_domain.cpp:197
void set_zero()
Sets the Val_domain to zero (logical state to zero and arrays destroyed).
Definition: val_domain.cpp:223
bool check_if_zero() const
Check whether the logical state is zero or not.
Definition: val_domain.hpp:142
bool in_conf
Is the field known in the configuration space ?
Definition: val_domain.hpp:78
Array< double > * cf
Pointer on the Array of the values in the coefficients space.
Definition: val_domain.hpp:77
void coef_i() const
Computes the values in the configuration space.
Definition: val_domain.cpp:637
double & set(const Index &pos)
Read/write the value of the field in the configuration space.
Definition: val_domain.cpp:171
bool is_zero
Indicator used for null fields (for speed issues).
Definition: val_domain.hpp:74
void std_base()
Sets the standard basis of decomposition.
Definition: val_domain.cpp:246
void operator*=(const Val_domain &)
Operator *=.
bool in_coef
Is the field known in the coefficient space ?
Definition: val_domain.hpp:79
void coef() const
Computes the coefficients.
Definition: val_domain.cpp:622
void operator-=(const Val_domain &)
Operator -=.
Array< double > * c
Pointer on the Array of the values in the configuration space.
Definition: val_domain.hpp:76
void allocate_conf()
Allocates the values in the configuration space and destroys the values in the coefficients space.
Definition: val_domain.cpp:209
void operator+=(const Val_domain &)
Operator +=.
const Domain * get_domain() const
Definition: val_domain.hpp:111
const Domain * zone
Pointer to the associated Domain.
Definition: val_domain.hpp:71