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