KADATH
domain_fourD_periodic_nucleus.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 #include "utilities.hpp"
22 #include "fourD_periodic.hpp"
23 #include "point.hpp"
24 #include "array_math.hpp"
25 #include "val_domain.hpp"
26 #include "term_eq.hpp"
27 #include "scalar.hpp"
28 #include "tensor_impl.hpp"
29 
30 namespace Kadath {
31 void coef_1d (int, Array<double>&) ;
32 void coef_i_1d (int, Array<double>&) ;
33 int der_1d (int, Array<double>&) ;
34 
35 // Standard constructor
36 Domain_fourD_periodic_nucleus::Domain_fourD_periodic_nucleus (int num, int ttype, double r, double oome, const Dim_array& nbr) :
37  Domain(num, ttype, nbr), alpha(r), ome(oome), type_time(TO_PI) {
38  assert (nbr.get_ndim()==4) ;
39  switch (type_time) {
40  case TO_PI :
41  maxt = M_PI ;
42  break ;
43  default:
44  cerr << "Unknown case for type_time" << endl ;
45  abort() ;
46  }
47 
48  do_coloc() ;
49 }
50 
51 // Constructor by copy
53  type_time(so.type_time), maxt(so.maxt) {
54 }
55 
57  fread_be (&alpha, sizeof(double), 1, fd) ;
58  fread_be (&ome, sizeof(double), 1, fd) ;
59  fread_be (&type_time, sizeof(int), 1, fd) ;
60  switch (type_time) {
61  case TO_PI :
62  maxt = M_PI ;
63  break ;
64  default:
65  cerr << "Unknown case for type_time" << endl ;
66  abort() ;
67  }
68  do_coloc() ;
69 }
70 
71 // Destructor
72 Domain_fourD_periodic_nucleus::~Domain_fourD_periodic_nucleus() {
73 }
74 
75 void Domain_fourD_periodic_nucleus::save (FILE* fd) const {
76  nbr_points.save(fd) ;
77  nbr_coefs.save(fd) ;
78  fwrite_be (&ndim, sizeof(int), 1, fd) ;
79  fwrite_be (&type_base, sizeof(int), 1, fd) ;
80  fwrite_be (&alpha, sizeof(double), 1, fd) ;
81  fwrite_be (&ome, sizeof(double), 1, fd) ;
82  fwrite_be (&type_time, sizeof(int), 1, fd) ;
83 }
84 
85 ostream& Domain_fourD_periodic_nucleus::print (ostream& o) const {
86  o << "fourD_periodic nucleus" << endl ;
87  o << "time goes to " << maxt << endl ;
88  o << "Rmax = " << alpha << endl ;
89  o << "Omega = " << ome << endl ;
90  o << "Nbr pts = " << nbr_points << endl ;
91  o << endl ;
92  return o ;
93 }
94 
95 // Computes the cartesian coordinates
97  for (int i=0 ; i<4 ; i++)
98  assert (coloc[i] != 0x0) ;
99  for (int i=0 ; i<4 ; i++)
100  assert (absol[i] == 0x0) ;
101  for (int i=0 ; i<4 ; i++) {
102  absol[i] = new Val_domain(this) ;
103  absol[i]->allocate_conf() ;
104  }
105  Index index (nbr_points) ;
106  do {
107  absol[0]->set(index) = alpha* ((*coloc[0])(index(0))) *
108  sin((*coloc[1])(index(1)))*cos((*coloc[2])(index(2))) ; // xx
109  absol[1]->set(index) = alpha* ((*coloc[0])(index(0))) *
110  sin((*coloc[1])(index(1)))*sin((*coloc[2])(index(2))) ; // yy
111  absol[2]->set(index) = alpha* ((*coloc[0])(index(0))) * cos((*coloc[1])(index(1))) ; //zz
112  absol[3]->set(index) = (*coloc[3])(index(3)) / ome ; // time
113  }
114  while (index.inc()) ;
115 
116 }
117 
118 // Computes the radius
120 
121  for (int i=0 ; i<4 ; i++)
122  assert (coloc[i] != 0x0) ;
123  assert (radius == 0x0) ;
124  radius = new Val_domain(this) ;
125  radius->allocate_conf() ;
126  Index index (nbr_points) ;
127  do
128  radius->set(index) = alpha* ((*coloc[0])(index(0))) ;
129  while (index.inc()) ;
130 }
131 
132 
133 // Is a point inside this domain ?
134 bool Domain_fourD_periodic_nucleus::is_in (const Point& xx, double prec) const {
135 
136  assert (xx.get_ndim()==4) ;
137 
138  double x_loc = xx(1) ;
139  double y_loc = xx(2) ;
140  double z_loc = xx(3) ;
141  double air_loc = sqrt (x_loc*x_loc + y_loc*y_loc + z_loc*z_loc) ;
142 
143  bool res = (air_loc <= alpha+prec) ? true : false ;
144 
145  if ((xx(4)<0-prec) || (xx(4)>maxt/ome + prec))
146  res = false ;
147 
148  return res ;
149 }
150 
151 // Convert absolute coordinates to numerical ones
153 
154  Point num(4) ;
155 
156  double x_loc = abs(1) ;
157  double y_loc = abs(2) ;
158  double z_loc = abs(3) ;
159  double air = sqrt(x_loc*x_loc+y_loc*y_loc+z_loc*z_loc) ;
160  num.set(1) = air/alpha ;
161  double rho = sqrt(x_loc*x_loc+y_loc*y_loc) ;
162 
163  if (rho==0) {
164  // Sur l'axe
165  num.set(2) = (z_loc>=0) ? 0 : M_PI ;
166  num.set(3) = 0 ;
167  }
168  else {
169  num.set(2) = atan(rho/z_loc) ;
170  num.set(3) = atan2 (y_loc, x_loc) ;
171  }
172 
173  if (num(2) <0)
174  num.set(2) = M_PI + num(2) ;
175 
176  num.set(4) = abs(4)*ome ;
177 
178  return num ;
179 }
180 
181 double coloc_leg_parity(int, int) ;
183 
184  switch (type_base) {
185  case CHEB_TYPE:
187  nbr_coefs.set(2) += 2 ;
188  del_deriv() ;
189  for (int i=0 ; i<ndim ; i++)
190  coloc[i] = new Array<double> (nbr_points(i)) ;
191  for (int i=0 ; i<nbr_points(0) ; i++)
192  coloc[0]->set(i) = sin(M_PI/2.*i/(nbr_points(0)-1)) ;
193  for (int j=0 ; j<nbr_points(1) ; j++)
194  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
195  for (int k=0 ; k<nbr_points(2) ; k++)
196  coloc[2]->set(k) = M_PI*2.*k/nbr_points(2) ;
197  for (int l=0 ; l<nbr_points(3) ; l++)
198  coloc[3]->set(l) = maxt*l/(nbr_points(3)-1) ;
199  break ;
200  case LEG_TYPE:
202  nbr_coefs.set(2) += 2 ;
203  del_deriv() ;
204  for (int i=0 ; i<ndim ; i++)
205  coloc[i] = new Array<double> (nbr_points(i)) ;
206  for (int i=0 ; i<nbr_points(0) ; i++)
207  coloc[0]->set(i) = coloc_leg_parity(i, nbr_points(0)) ;
208  for (int j=0 ; j<nbr_points(1) ; j++)
209  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
210  for (int k=0 ; k<nbr_points(2) ; k++)
211  coloc[2]->set(k) = M_PI*2.*k/nbr_points(2) ;
212  for (int l=0 ; l<nbr_points(3) ; l++)
213  coloc[3]->set(l) = maxt*l/(nbr_points(3)-1) ;
214  break ;
215  default :
216  cerr << "Unknown type of basis in Domain_fourD_periodic_nucleus::do_coloc" << endl ;
217  abort() ;
218  }
219 }
220 
221 // Computes the derivatives with respect to rho,Z as a function of the numerical ones.
222 void Domain_fourD_periodic_nucleus::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
223 
224  // d/dx :
225  Val_domain sintdr (der_var[0]->mult_sin_theta()/alpha) ;
226  Val_domain dtsr (der_var[1]->div_x()/alpha) ;
227  Val_domain dpsr (der_var[2]->div_x()/alpha) ;
228  Val_domain costdtsr (dtsr.mult_cos_theta()) ;
229  Val_domain dpsrssint (dpsr.div_sin_theta()) ;
230 
231  der_abs[0] = new Val_domain ((sintdr+costdtsr).mult_cos_phi() - dpsrssint.mult_sin_phi()) ;
232 
233  // d/dy :
234  der_abs[1] = new Val_domain ((sintdr+costdtsr).mult_sin_phi() + dpsrssint.mult_cos_phi()) ;
235  // d/dz :
236  der_abs[2] = new Val_domain (der_var[0]->mult_cos_theta()/alpha - dtsr.mult_sin_theta()) ;
237 
238  // d/dt :
239  der_abs[3] = new Val_domain (*der_var[3]*ome) ;
240 }
241 
242 // Rules for the multiplication of two basis.
244 
245  assert (a.ndim==4) ;
246  assert (b.ndim==4) ;
247 
248  Base_spectral res(4) ;
249  bool res_def = true ;
250 
251  if (!a.def)
252  res_def=false ;
253  if (!b.def)
254  res_def=false ;
255 
256  if (res_def) {
257 
258 
259  // Bases in time :
260  res.bases_1d[3] = new Array<int> (a.bases_1d[3]->get_dimensions()) ;
261  switch ((*a.bases_1d[3])(0)) {
262  case COS:
263  switch ((*b.bases_1d[3])(0)) {
264  case COS:
265  res.bases_1d[3]->set(0) = COS ;
266  break ;
267  case SIN:
268  res.bases_1d[3]->set(0) = SIN ;
269  break ;
270  default:
271  res_def = false ;
272  break ;
273  }
274  break ;
275  case SIN:
276  switch ((*b.bases_1d[3])(0)) {
277  case COS:
278  res.bases_1d[3]->set(0) = SIN ;
279  break ;
280  case SIN:
281  res.bases_1d[3]->set(0) = COS ;
282  break ;
283  default:
284  res_def = false ;
285  break ;
286  }
287  break ;
288  }
289 
290 
291  // Base in phi :
292  Index index_2 (a.bases_1d[2]->get_dimensions()) ;
293  res.bases_1d[2] = new Array<int> (a.bases_1d[2]->get_dimensions()) ;
294  do {
295  switch ((*a.bases_1d[2])(index_2)) {
296  case COSSIN:
297  switch ((*b.bases_1d[2])(index_2)) {
298  case COSSIN:
299  res.bases_1d[2]->set(index_2) = COSSIN ;
300  break ;
301  default:
302  res_def = false ;
303  break ;
304  }
305  break ;
306  default:
307  res_def = false ;
308  break ;
309  }
310  } while (index_2.inc()) ;
311 
312  // Bases in theta :
313  Index index_1 (a.bases_1d[1]->get_dimensions()) ;
314  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
315  do {
316  switch ((*a.bases_1d[1])(index_1)) {
317  case COS_EVEN:
318  switch ((*b.bases_1d[1])(index_1)) {
319  case COS_EVEN:
320  res.bases_1d[1]->set(index_1) = COS_EVEN ;
321  break ;
322  case COS_ODD:
323  res.bases_1d[1]->set(index_1) = COS_ODD ;
324  break ;
325  case SIN_EVEN:
326  res.bases_1d[1]->set(index_1) = SIN_EVEN ;
327  break ;
328  case SIN_ODD:
329  res.bases_1d[1]->set(index_1) = SIN_ODD ;
330  break ;
331  default:
332  res_def = false ;
333  break ;
334  }
335  break ;
336  case COS_ODD:
337  switch ((*b.bases_1d[1])(index_1)) {
338  case COS_EVEN:
339  res.bases_1d[1]->set(index_1) = COS_ODD ;
340  break ;
341  case COS_ODD:
342  res.bases_1d[1]->set(index_1) = COS_EVEN ;
343  break ;
344  case SIN_EVEN:
345  res.bases_1d[1]->set(index_1) = SIN_ODD ;
346  break ;
347  case SIN_ODD:
348  res.bases_1d[1]->set(index_1) = SIN_EVEN ;
349  break ;
350  default:
351  res_def = false ;
352  break ;
353  }
354  break ;
355  case SIN_EVEN:
356  switch ((*b.bases_1d[1])(index_1)) {
357  case COS_EVEN:
358  res.bases_1d[1]->set(index_1) = SIN_EVEN ;
359  break ;
360  case COS_ODD:
361  res.bases_1d[1]->set(index_1) = SIN_ODD ;
362  break ;
363  case SIN_EVEN:
364  res.bases_1d[1]->set(index_1) = COS_EVEN ;
365  break ;
366  case SIN_ODD:
367  res.bases_1d[1]->set(index_1) = COS_ODD ;
368  break ;
369  default:
370  res_def = false ;
371  break ;
372  }
373  break ;
374  case SIN_ODD:
375  switch ((*b.bases_1d[1])(index_1)) {
376  case COS_EVEN:
377  res.bases_1d[1]->set(index_1) = SIN_ODD ;
378  break ;
379  case COS_ODD:
380  res.bases_1d[1]->set(index_1) = SIN_EVEN ;
381  break ;
382  case SIN_EVEN:
383  res.bases_1d[1]->set(index_1) = COS_ODD ;
384  break ;
385  case SIN_ODD:
386  res.bases_1d[1]->set(index_1) = COS_EVEN ;
387  break ;
388  default:
389  res_def = false ;
390  break ;
391  }
392  break ;
393  default:
394  res_def = false ;
395  break ;
396  }
397  }
398  while (index_1.inc()) ;
399 
400 
401  // Base in r :
402  Index index_0 (a.bases_1d[0]->get_dimensions()) ;
403  res.bases_1d[0] = new Array<int> (a.bases_1d[0]->get_dimensions()) ;
404  do {
405  switch ((*a.bases_1d[0])(index_0)) {
406  case CHEB_EVEN:
407  switch ((*b.bases_1d[0])(index_0)) {
408  case CHEB_EVEN:
409  res.bases_1d[0]->set(index_0) = CHEB_EVEN ;
410  break ;
411  case CHEB_ODD:
412  res.bases_1d[0]->set(index_0) = CHEB_ODD ;
413  break ;
414  default:
415  res_def = false ;
416  break ;
417  }
418  break ;
419  case CHEB_ODD:
420  switch ((*b.bases_1d[0])(index_0)) {
421  case CHEB_EVEN:
422  res.bases_1d[0]->set(index_0) = CHEB_ODD ;
423  break ;
424  case CHEB_ODD:
425  res.bases_1d[0]->set(index_0) = CHEB_EVEN ;
426  break ;
427  default:
428  res_def = false ;
429  break ;
430  }
431  break ;
432  case LEG_EVEN:
433  switch ((*b.bases_1d[0])(index_0)) {
434  case LEG_EVEN:
435  res.bases_1d[0]->set(index_0) = LEG_EVEN ;
436  break ;
437  case LEG_ODD:
438  res.bases_1d[0]->set(index_0) = LEG_ODD ;
439  break ;
440  default:
441  res_def = false ;
442  break ;
443  }
444  break ;
445  case LEG_ODD:
446  switch ((*b.bases_1d[0])(index_0)) {
447  case LEG_EVEN:
448  res.bases_1d[0]->set(index_0) = LEG_ODD ;
449  break ;
450  case LEG_ODD:
451  res.bases_1d[0]->set(index_0) = LEG_EVEN ;
452  break ;
453  default:
454  res_def = false ;
455  break ;
456  }
457  break ;
458  default:
459  res_def = false ;
460  break ;
461  }
462  }
463  while (index_0.inc()) ;
464  }
465 
466 
467  if (!res_def)
468  for (int dim=0 ; dim<a.ndim ; dim++)
469  if (res.bases_1d[dim]!= 0x0) {
470  delete res.bases_1d[dim] ;
471  res.bases_1d[dim] = 0x0 ;
472  }
473  res.def = res_def ;
474  return res ;
475 }
476 
478 
479  Val_domain res(this) ;
480 
481  // Construction bases
482  Base_spectral base (4) ;
483  base.allocate (get_nbr_coefs()) ;
484 
485  // Time base
486  base.bases_1d[3] = new Array<int> (1) ;
487  base.bases_1d[3]->set(0) = (*so.get_base().bases_1d[2])(0) ;
488 
489  // Phi base
490  base.bases_1d[2] = new Array<int> (get_nbr_coefs()(3)) ;
491  for (int i=0 ; i<get_nbr_coefs()(3) ; i++)
492  base.bases_1d[2]->set(i) = COSSIN ;
493 
494  // Theta base
495  base.bases_1d[1] = new Array<int> (get_nbr_coefs()(2), get_nbr_coefs()(3)) ;
496  for (int l=0 ; l<get_nbr_coefs()(3) ; l++)
497  for (int k=0 ; k<get_nbr_coefs()(2) ; k++) {
498  base.bases_1d[1]->set(k,l) = (*so.get_base().bases_1d[1])(l) ;
499  }
500 
501  // radial base
502  base.bases_1d[0] = new Array<int> (get_nbr_coefs()(1), get_nbr_coefs()(2), get_nbr_coefs()(3)) ;
503  for (int l=0 ; l<get_nbr_coefs()(3) ; l++)
504  for (int k=0 ; k<get_nbr_coefs()(2) ; k++)
505  for (int j=0 ; j<get_nbr_coefs()(1) ; j++) {
506  base.bases_1d[0]->set(j, k,l) = (*so.get_base().bases_1d[0])(j, l) ;
507  }
508  base.def = true ;
509  res.set_base() = base ;
510 
511  // Now affecte the coefficients
512  so.coef() ;
513  res.annule_hard() ;
514  res.coef() ;
515  Index pso (so.get_domain()->get_nbr_coefs()) ;
516  Index pcf (get_nbr_coefs()) ;
517 
518  do {
519  pcf.set(3) = pso(2) ; // t coef
520  pcf.set(2) = 0. ; // phi coef
521  pcf.set(1) = pso(1) ; // Theta coef
522  pcf.set(0) = pso(0) ; // r coef
523  res.set_coef(pcf) = so.get_coef(pso) ;
524  }
525  while (pso.inc()) ;
526 
527  return res ;
528 
529 }
530 
531 }
Class for storing the basis of decompositions of a field.
Bases_container bases_1d
Arrays containing the various basis of decomposition.
void allocate(const Dim_array &nbr_coefs)
Allocates the various arrays, for a given number of coefficients.
bool def
true if the Base_spectral is defined and false otherwise.
int ndim
Number of dimensions.
Class for storing the dimensions of an array.
Definition: dim_array.hpp:34
int get_ndim() const
Returns the number of dimensions.
Definition: dim_array.hpp:63
int & set(int i)
Read/write of the size of a given dimension.
Definition: dim_array.hpp:54
void save(FILE *) const
Save function.
Definition: dim_array.cpp:32
Class for a spherical nucleus.
virtual void save(FILE *) const
Saving function.
double maxt
Upper bound of which is or .
virtual Val_domain mult_cos_phi(const Val_domain &) const
Multiplication by .
virtual ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
Val_domain translate(const Val_domain &so) const
Generates a Val_domain, from another one assumed to be on a Polar_periodic_nucleus.
virtual Val_domain mult_sin_phi(const Val_domain &) const
Multiplication by .
virtual void do_absol() const
Computes the absolute coordinates.
Domain_fourD_periodic_nucleus(int num, int ttype, double radius, double ome, const Dim_array &nbr)
Standard constructor :
virtual void do_radius() const
Computes the generalized radius.
double alpha
Relates the numerical radius to the physical one.
virtual Val_domain div_x(const Val_domain &) const
Division by .
virtual const Point absol_to_num(const Point &) const
Computes the numerical coordinates from the physical ones.
virtual void do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const
Computes the derivative with respect to the absolute Cartesian coordinates from the derivative with r...
virtual void do_coloc()
Computes the colocation points.
int type_time
Gives the type of time periodicity.
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
virtual Val_domain mult_cos_theta(const Val_domain &) const
Multiplication by .
virtual Val_domain mult_sin_theta(const Val_domain &) const
Multiplication by .
Abstract class that implements the fonctionnalities common to all the type of domains.
Definition: space.hpp:60
virtual void del_deriv()
Destroys the derivated members (like coloc, cart and radius), when changing the type of colocation po...
Definition: domain.cpp:77
Val_domain * radius
The generalized radius.
Definition: space.hpp:78
Memory_mapped_array< Val_domain * > absol
Asbolute coordinates (if defined ; usually Cartesian-like)
Definition: space.hpp:76
int ndim
Number of dimensions.
Definition: space.hpp:64
Dim_array const & get_nbr_coefs() const
Returns the number of coefficients.
Definition: space.hpp:94
Dim_array nbr_coefs
Number of coefficients.
Definition: space.hpp:66
Dim_array nbr_points
Number of colocation points.
Definition: space.hpp:65
int type_base
Type of colocation point :
Definition: space.hpp:73
Memory_mapped_array< Array< double > * > coloc
Colocation points in each dimension (stored in ndim 1d- arrays)
Definition: space.hpp:75
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
bool inc(int increm, int var=0)
Increments the position of the Index.
Definition: index.hpp:99
The class Point is used to store the coordinates of a point.
Definition: point.hpp:30
const int & get_ndim() const
Returns the number of dimensions.
Definition: point.hpp:51
double & set(int i)
Read/write of a coordinate.
Definition: point.hpp:47
Class for storing the basis of decompositions of a field and its values on both the configuration and...
Definition: val_domain.hpp:69
Val_domain mult_sin_phi() const
Multiplication by .
double & set_coef(const Index &pos)
Read/write the value of the field in the coefficient space.
Definition: val_domain.cpp:177
Val_domain mult_sin_theta() const
Multiplication by .
Val_domain mult_cos_phi() const
Multiplication by .
double & set(const Index &pos)
Read/write the value of the field in the configuration space.
Definition: val_domain.cpp:171
Val_domain div_sin_theta() const
Division by .
Val_domain mult_cos_theta() const
Multiplication by .
void coef() const
Computes the coefficients.
Definition: val_domain.cpp:622
Base_spectral & set_base()
Sets the basis of decomposition.
Definition: val_domain.hpp:126
Array< double > get_coef() const
Definition: val_domain.hpp:136
void annule_hard()
Sets all the arrays to zero (the logical state is NOT set to zero).
Definition: val_domain.cpp:159
void allocate_conf()
Allocates the values in the configuration space and destroys the values in the coefficients space.
Definition: val_domain.cpp:209
const Domain * get_domain() const
Definition: val_domain.hpp:111
const Base_spectral & get_base() const
Returns the basis of decomposition.
Definition: val_domain.hpp:122