KADATH
domain_spheric_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 "spheric_periodic.hpp"
23 #include "point.hpp"
24 #include "array_math.hpp"
25 #include "val_domain.hpp"
26 
27 namespace Kadath {
28 void coef_1d (int, Array<double>&) ;
29 void coef_i_1d (int, Array<double>&) ;
30 int der_1d (int, Array<double>&) ;
31 
32 // Standard constructor
33 Domain_spheric_periodic_nucleus::Domain_spheric_periodic_nucleus (int num, int ttype, int typet, double r, double oome, const Dim_array& nbr) :
34  Domain(num, ttype, nbr), alpha(r), ome(oome), type_time(typet) {
35  assert (nbr.get_ndim()==2) ;
36  switch (type_time) {
37  case TO_PI :
38  maxt = M_PI ;
39  break ;
40  case TO_PI_OVER_2 :
41  maxt = M_PI / 2. ;
42  break ;
43  default:
44  cerr << "Unknown case for type_time" << endl ;
45  abort() ;
46  }
47  do_coloc() ;
48 }
49 
50 // Constructor by copy
52  type_time(so.type_time), maxt(so.maxt) {
53 }
54 
56  fread_be (&alpha, sizeof(double), 1, fd) ;
57  fread_be (&ome, sizeof(double), 1, fd) ;
58  fread_be (&type_time, sizeof(int), 1, fd) ;
59  switch (type_time) {
60  case TO_PI :
61  maxt = M_PI ;
62  break ;
63  case TO_PI_OVER_2 :
64  maxt = M_PI / 2. ;
65  break ;
66  default:
67  cerr << "Unknown case for type_time" << endl ;
68  abort() ;
69  }
70  do_coloc() ;
71 }
72 
73 // Destructor
74 Domain_spheric_periodic_nucleus::~Domain_spheric_periodic_nucleus() {}
75 
77  nbr_points.save(fd) ;
78  nbr_coefs.save(fd) ;
79  fwrite_be (&ndim, sizeof(int), 1, fd) ;
80  fwrite_be (&type_base, sizeof(int), 1, fd) ;
81  fwrite_be (&alpha, sizeof(double), 1, fd) ;
82  fwrite_be (&ome, sizeof(double), 1, fd) ;
83  fwrite_be (&type_time, sizeof(int), 1, fd) ;
84 }
85 
86 ostream& Domain_spheric_periodic_nucleus::print (ostream& o) const {
87  o << "Spheric-periodic nucleus" << endl ;
88  o << "time goes to " << maxt << endl ;
89  o << "Rmax = " << alpha << endl ;
90  o << "Omega = " << ome << endl ;
91  o << "Nbr pts = " << nbr_points << endl ;
92  o << endl ;
93  return o ;
94 }
95 
96 
98 
99  Val_domain res (so.der_var(1)) ;
100  switch (bound) {
101  case OUTER_BC :
102  res /= alpha ;
103  break ;
104  default:
105  cerr << "Unknown boundary case in Domain_spheric_periodic_nucleus::der_normal" << endl ;
106  abort() ;
107  }
108 return res ;
109 }
110 
111 // Computes the cartesian coordinates
113  for (int i=0 ; i<2 ; i++)
114  assert (coloc[i] != 0x0) ;
115  for (int i=0 ; i<2 ; i++)
116  assert (absol[i] == 0x0) ;
117  for (int i=0 ; i<2 ; i++) {
118  absol[i] = new Val_domain(this) ;
119  absol[i]->allocate_conf() ;
120  }
121  Index index (nbr_points) ;
122  do {
123  absol[0]->set(index) = alpha* ((*coloc[0])(index(0))) ;
124  absol[1]->set(index) = (*coloc[1])(index(1)) / ome ;
125  }
126  while (index.inc()) ;
127 
128 }
129 
130 // Computes the radius
132 
133  for (int i=0 ; i<2 ; i++)
134  assert (coloc[i] != 0x0) ;
135  assert (radius == 0x0) ;
136  radius = new Val_domain(this) ;
137  radius->allocate_conf() ;
138  Index index (nbr_points) ;
139  do
140  radius->set(index) = alpha* ((*coloc[0])(index(0))) ;
141  while (index.inc()) ;
142 }
143 
144 
145 // Is a point inside this domain ?
146 bool Domain_spheric_periodic_nucleus::is_in (const Point& xx, double prec) const {
147 
148  assert (xx.get_ndim()==2) ;
149 
150 
151  bool res = (xx(1) <= alpha+prec) ? true : false ;
152  if ((xx(2)<0-prec) || (xx(2)>maxt/ome + prec))
153  res = false ;
154  return res ;
155 }
156 
157 // Convert absolute coordinates to numerical ones
159 
160  assert (is_in(abs)) ;
161  Point num(2) ;
162 
163  num.set(1) = abs(1)/alpha ;
164  num.set(2) = abs(2)*ome ;
165 
166  return num ;
167 }
168 
169 double coloc_leg_parity(int, int) ;
171 
172  switch (type_base) {
173  case CHEB_TYPE:
175  del_deriv() ;
176  for (int i=0 ; i<ndim ; i++)
177  coloc[i] = new Array<double> (nbr_points(i)) ;
178  for (int i=0 ; i<nbr_points(0) ; i++)
179  coloc[0]->set(i) = sin(M_PI/2.*i/(nbr_points(0)-1)) ;
180  for (int j=0 ; j<nbr_points(1) ; j++)
181  coloc[1]->set(j) = maxt*j/(nbr_points(1)-1) ;
182  break ;
183  case LEG_TYPE:
185  del_deriv() ;
186  for (int i=0 ; i<ndim ; i++)
187  coloc[i] = new Array<double> (nbr_points(i)) ;
188  for (int i=0 ; i<nbr_points(0) ; i++)
189  coloc[0]->set(i) = coloc_leg_parity(i, nbr_points(0)) ;
190  for (int j=0 ; j<nbr_points(1) ; j++)
191  coloc[1]->set(j) = maxt*j/(nbr_points(1)-1) ;
192  break ;
193  default :
194  cerr << "Unknown type of basis in Domain_spheric_periodic_nucleus::do_coloc" << endl ;
195  abort() ;
196  }
197 }
198 
199 // Base for a function symetric in z, using Chebyshev
201 
202  assert (type_base == CHEB_TYPE) ;
203  base.allocate(nbr_coefs) ;
204 
205  Index index(base.bases_1d[0]->get_dimensions()) ;
206 
207  base.def=true ;
208  switch (type_time) {
209  case TO_PI :
210  base.bases_1d[1]->set(0) = COS ;
211  break ;
212  case TO_PI_OVER_2 :
213  base.bases_1d[1]->set(0) = COS_EVEN ;
214  break ;
215  default:
216  cerr << "Unknown case for type_time" << endl ;
217  abort() ;
218  }
219  for (int j=0 ; j<nbr_coefs(1) ; j++)
220  base.bases_1d[0]->set(j) = CHEB_EVEN ;
221 }
222 
223 // Base for a function symetric in z, using Legendre
225 
226  assert (type_base == LEG_TYPE) ;
227  base.allocate(nbr_coefs) ;
228 
229  Index index(base.bases_1d[0]->get_dimensions()) ;
230  base.def=true ;
231  switch (type_time) {
232  case TO_PI :
233  base.bases_1d[1]->set(0) = COS ;
234  break ;
235  case TO_PI_OVER_2 :
236  base.bases_1d[1]->set(0) = COS_EVEN ;
237  break ;
238  default:
239  cerr << "Unknown case for type_time" << endl ;
240  abort() ;
241  }
242  for (int j=0 ; j<nbr_coefs(1) ; j++)
243  base.bases_1d[0]->set(j) = LEG_EVEN ;
244  }
245 
247 
248  assert (type_base == CHEB_TYPE) ;
249  base.allocate(nbr_coefs) ;
250 
251  Index index(base.bases_1d[0]->get_dimensions()) ;
252 
253  base.def=true ;
254  switch (type_time) {
255  case TO_PI :
256  base.bases_1d[1]->set(0) = COS ;
257  break ;
258  case TO_PI_OVER_2 :
259  base.bases_1d[1]->set(0) = COS_EVEN ;
260  break ;
261  default:
262  cerr << "Unknown case for type_time" << endl ;
263  abort() ;
264  }
265  for (int j=0 ; j<nbr_coefs(1) ; j++)
266  base.bases_1d[0]->set(j) = CHEB_ODD ;
267 }
268 
270 
271  assert (type_base == LEG_TYPE) ;
272  base.allocate(nbr_coefs) ;
273 
274  Index index(base.bases_1d[0]->get_dimensions()) ;
275  base.def=true ;
276  switch (type_time) {
277  case TO_PI :
278  base.bases_1d[1]->set(0) = COS ;
279  break ;
280  case TO_PI_OVER_2 :
281  base.bases_1d[1]->set(0) = COS_EVEN ;
282  break ;
283  default:
284  cerr << "Unknown case for type_time" << endl ;
285  abort() ;
286  }
287  for (int j=0 ; j<nbr_coefs(1) ; j++)
288  base.bases_1d[0]->set(j) = LEG_ODD ;
289  }
290 
292 
293  assert (type_base == CHEB_TYPE) ;
294  base.allocate(nbr_coefs) ;
295 
296  Index index(base.bases_1d[0]->get_dimensions()) ;
297 
298  base.def=true ;
299  switch (type_time) {
300  case TO_PI_OVER_2 :
301  base.bases_1d[1]->set(0) = COS_ODD ;
302  break ;
303  default:
304  cerr << "Unknown case for type_time" << endl ;
305  abort() ;
306  }
307  for (int j=0 ; j<nbr_coefs(1) ; j++)
308  base.bases_1d[0]->set(j) = CHEB_EVEN ;
309 }
310 
311 // Base for a function symetric in z, using Legendre
313 
314  assert (type_base == LEG_TYPE) ;
315  base.allocate(nbr_coefs) ;
316 
317  Index index(base.bases_1d[0]->get_dimensions()) ;
318  base.def=true ;
319  switch (type_time) {
320  case TO_PI_OVER_2 :
321  base.bases_1d[1]->set(0) = COS_ODD ;
322  break ;
323  default:
324  cerr << "Unknown case for type_time" << endl ;
325  abort() ;
326  }
327  for (int j=0 ; j<nbr_coefs(1) ; j++)
328  base.bases_1d[0]->set(j) = LEG_EVEN ;
329  }
330 // Computes the derivatives with respect to rho,Z as a function of the numerical ones.
331 void Domain_spheric_periodic_nucleus::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
332  // d/dr
333  der_abs[0] = new Val_domain (*der_var[0]/alpha) ;
334  // d/dt :
335  der_abs[1] = new Val_domain (*der_var[1]*ome) ;
336 }
337 
338 // Rules for the multiplication of two basis.
340 
341  assert (a.ndim==2) ;
342  assert (b.ndim==2) ;
343 
344  Base_spectral res(2) ;
345  bool res_def = true ;
346 
347  if (!a.def)
348  res_def=false ;
349  if (!b.def)
350  res_def=false ;
351 
352  if (res_def) {
353 
354 
355  // Bases in time :
356  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
357  switch ((*a.bases_1d[1])(0)) {
358  case COS:
359  switch ((*b.bases_1d[1])(0)) {
360  case COS:
361  res.bases_1d[1]->set(0) = COS ;
362  break ;
363  case SIN:
364  res.bases_1d[1]->set(0) = SIN ;
365  break ;
366  default:
367  res_def = false ;
368  break ;
369  }
370  break ;
371  case SIN:
372  switch ((*b.bases_1d[1])(0)) {
373  case COS:
374  res.bases_1d[1]->set(0) = SIN ;
375  break ;
376  case SIN:
377  res.bases_1d[1]->set(0) = COS ;
378  break ;
379  default:
380  res_def = false ;
381  break ;
382  }
383  break ;
384  case COS_EVEN:
385  switch ((*b.bases_1d[1])(0)) {
386  case COS_EVEN:
387  res.bases_1d[1]->set(0) = COS_EVEN ;
388  break ;
389  case COS_ODD:
390  res.bases_1d[1]->set(0) = COS_ODD ;
391  break ;
392  case SIN_EVEN:
393  res.bases_1d[1]->set(0) = SIN_EVEN ;
394  break ;
395  case SIN_ODD:
396  res.bases_1d[1]->set(0) = SIN_ODD ;
397  break ;
398  default:
399  res_def = false ;
400  break ;
401  }
402  break ;
403  case COS_ODD:
404  switch ((*b.bases_1d[1])(0)) {
405  case COS_EVEN:
406  res.bases_1d[1]->set(0) = COS_ODD ;
407  break ;
408  case COS_ODD:
409  res.bases_1d[1]->set(0) = COS_EVEN ;
410  break ;
411  case SIN_EVEN:
412  res.bases_1d[1]->set(0) = SIN_ODD ;
413  break ;
414  case SIN_ODD:
415  res.bases_1d[1]->set(0) = SIN_EVEN ;
416  break ;
417  default:
418  res_def = false ;
419  break ;
420  }
421  break ;
422  case SIN_EVEN:
423  switch ((*b.bases_1d[1])(0)) {
424  case COS_EVEN:
425  res.bases_1d[1]->set(0) = SIN_EVEN ;
426  break ;
427  case COS_ODD:
428  res.bases_1d[1]->set(0) = SIN_ODD ;
429  break ;
430  case SIN_EVEN:
431  res.bases_1d[1]->set(0) = COS_EVEN ;
432  break ;
433  case SIN_ODD:
434  res.bases_1d[1]->set(0) = COS_ODD ;
435  break ;
436  default:
437  res_def = false ;
438  break ;
439  }
440  break ;
441  case SIN_ODD:
442  switch ((*b.bases_1d[1])(0)) {
443  case COS_EVEN:
444  res.bases_1d[1]->set(0) = SIN_ODD ;
445  break ;
446  case COS_ODD:
447  res.bases_1d[1]->set(0) = SIN_EVEN ;
448  break ;
449  case SIN_EVEN:
450  res.bases_1d[1]->set(0) = COS_ODD ;
451  break ;
452  case SIN_ODD:
453  res.bases_1d[1]->set(0) = COS_EVEN ;
454  break ;
455  default:
456  res_def = false ;
457  break ;
458  }
459  break ;
460  default:
461  res_def = false ;
462  break ;
463  }
464 
465  // Base in r :
466  Index index_0 (a.bases_1d[0]->get_dimensions()) ;
467  res.bases_1d[0] = new Array<int> (a.bases_1d[0]->get_dimensions()) ;
468  do {
469  switch ((*a.bases_1d[0])(index_0)) {
470  case CHEB_EVEN:
471  switch ((*b.bases_1d[0])(index_0)) {
472  case CHEB_EVEN:
473  res.bases_1d[0]->set(index_0) = CHEB_EVEN ;
474  break ;
475  case CHEB_ODD:
476  res.bases_1d[0]->set(index_0) = CHEB_ODD ;
477  break ;
478  default:
479  res_def = false ;
480  break ;
481  }
482  break ;
483  case CHEB_ODD:
484  switch ((*b.bases_1d[0])(index_0)) {
485  case CHEB_EVEN:
486  res.bases_1d[0]->set(index_0) = CHEB_ODD ;
487  break ;
488  case CHEB_ODD:
489  res.bases_1d[0]->set(index_0) = CHEB_EVEN ;
490  break ;
491  default:
492  res_def = false ;
493  break ;
494  }
495  break ;
496  case LEG_EVEN:
497  switch ((*b.bases_1d[0])(index_0)) {
498  case LEG_EVEN:
499  res.bases_1d[0]->set(index_0) = LEG_EVEN ;
500  break ;
501  case LEG_ODD:
502  res.bases_1d[0]->set(index_0) = LEG_ODD ;
503  break ;
504  default:
505  res_def = false ;
506  break ;
507  }
508  break ;
509  case LEG_ODD:
510  switch ((*b.bases_1d[0])(index_0)) {
511  case LEG_EVEN:
512  res.bases_1d[0]->set(index_0) = LEG_ODD ;
513  break ;
514  case LEG_ODD:
515  res.bases_1d[0]->set(index_0) = LEG_EVEN ;
516  break ;
517  default:
518  res_def = false ;
519  break ;
520  }
521  break ;
522  default:
523  res_def = false ;
524  break ;
525  }
526  }
527  while (index_0.inc()) ;
528  }
529  if (!res_def)
530  for (int dim=0 ; dim<a.ndim ; dim++)
531  if (res.bases_1d[dim]!= 0x0) {
532  delete res.bases_1d[dim] ;
533  res.bases_1d[dim] = 0x0 ;
534  }
535  res.def = res_def ;
536  return res ;
537 }
538 }
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
void save(FILE *) const
Save function.
Definition: dim_array.cpp:32
Class for a 2-dimensional spherical domain containing the origin and a symetry with respect to the pl...
double maxt
Upper bound of which is or .
virtual void do_coloc()
Computes the colocation points.
virtual void set_cheb_base(Base_spectral &) const
Gives the standard base for Chebyshev polynomials.
double ome
Relates the numerical time to the physical one.
virtual ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
double alpha
Relates the numerical radius to the physical one.
virtual void set_legendre_base_odd(Base_spectral &) const
Gives the base using odd Legendre polynomials$.
Domain_spheric_periodic_nucleus(int num, int ttype, int typet, double radius, double ome, const Dim_array &nbr)
Standard constructor :
virtual void set_anti_legendre_base(Base_spectral &) const
Gives the base using Legendre polynomials, for functions antisymetric with respect to .
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
virtual void set_anti_cheb_base(Base_spectral &) const
Gives the base using Chebyshev polynomials, for functions antisymetric with respect to .
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...
int type_time
Gives the type of time periodicity.
virtual Val_domain der_normal(const Val_domain &, int) const
Normal derivative with respect to a given surface.
virtual void set_legendre_base(Base_spectral &) const
Gives the standard base for Legendre polynomials.
virtual void set_cheb_base_odd(Base_spectral &) const
Gives the base using odd Chebyshev polynomials$.
virtual void do_absol() const
Computes the absolute coordinates.
virtual void do_radius() const
Computes the generalized radius.
virtual void save(FILE *) const
Saving function.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
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 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
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
double & set(const Index &pos)
Read/write the value of the field in the configuration space.
Definition: val_domain.cpp:171
Val_domain der_var(int i) const
Computes the derivative with respect to a numerical coordinate.
Definition: val_domain.cpp:670
void allocate_conf()
Allocates the values in the configuration space and destroys the values in the coefficients space.
Definition: val_domain.cpp:209