KADATH
domain_spheric_periodic_shell.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_shell::Domain_spheric_periodic_shell (int num, int ttype, int typet, double rint, double rext, double oome, const Dim_array& nbr) :
33  Domain(num, ttype, nbr), alpha((rext-rint)/2.), beta((rext+rint)/2.), 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
50 Domain_spheric_periodic_shell::Domain_spheric_periodic_shell (const Domain_spheric_periodic_shell& so) : Domain(so), alpha(so.alpha), beta(so.beta), ome(so.ome),
51  type_time (so.type_time), maxt (so.maxt) {
52 }
53 
55  fread_be (&alpha, sizeof(double), 1, fd) ;
56  fread_be (&beta, 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_shell::~Domain_spheric_periodic_shell() {}
75 
76 void Domain_spheric_periodic_shell::save (FILE* fd) const {
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 (&beta, sizeof(double), 1, fd) ;
83  fwrite_be (&ome, sizeof(double), 1, fd) ;
84  fwrite_be (&type_time, sizeof(int), 1, fd) ;
85 }
86 
87 ostream& Domain_spheric_periodic_shell::print (ostream& o) const {
88  o << "Spheric-periodic shell" << endl ;
89  o << beta-alpha << " < r < " << beta+alpha << endl ;
90  o << "time goes to " << maxt << endl ;
91  o << "Omega = " << ome << endl ;
92  o << "Nbr pts = " << nbr_points << endl ;
93  o << endl ;
94  return o ;
95 }
96 
97 
99 
100  Val_domain res (so.der_var(1)) ;
101  switch (bound) {
102  case OUTER_BC :
103  res /= alpha ;
104  break ;
105  case INNER_BC :
106  res /= alpha ;
107  break ;
108  default:
109  cerr << "Unknown boundary case in Domain_spheric_periodic_shell::der_normal" << endl ;
110  abort() ;
111  }
112 return res ;
113 }
114 
115 // Computes the cartesian coordinates
117  for (int i=0 ; i<2 ; i++)
118  assert (coloc[i] != 0x0) ;
119  for (int i=0 ; i<2 ; i++)
120  assert (absol[i] == 0x0) ;
121  for (int i=0 ; i<2 ; i++) {
122  absol[i] = new Val_domain(this) ;
123  absol[i]->allocate_conf() ;
124  }
125  Index index (nbr_points) ;
126  do {
127  absol[0]->set(index) = alpha* ((*coloc[0])(index(0))) + beta;
128  absol[1]->set(index) = (*coloc[1])(index(1)) / ome ;
129  }
130  while (index.inc()) ;
131 
132 }
133 // Computes the radius
135 
136  for (int i=0 ; i<2 ; i++)
137  assert (coloc[i] != 0x0) ;
138  assert (radius == 0x0) ;
139  radius = new Val_domain(this) ;
140  radius->allocate_conf() ;
141  Index index (nbr_points) ;
142  do
143  radius->set(index) = alpha* ((*coloc[0])(index(0))) + beta ;
144  while (index.inc()) ;
145 }
146 
147 // Is a point inside this domain ?
148 bool Domain_spheric_periodic_shell::is_in (const Point& xx, double prec) const {
149 
150  assert (xx.get_ndim()==2) ;
151 
152 
153  bool res = ((xx(1) <= alpha+beta+prec) && (xx(1) >= beta-alpha-prec)) ? true : false ;
154  if ((xx(2)<0-prec) || (xx(2)>maxt/ome + prec))
155  res = false ;
156  return res ;
157 }
158 
159 // Convert absolute coordinates to numerical ones
161 
162  assert (is_in(abs)) ;
163  Point num(2) ;
164 
165  num.set(1) = (abs(1)-beta)/alpha ;
166  num.set(2) = abs(2)*ome ;
167 
168  return num ;
169 }
170 
171 double coloc_leg(int, int) ;
173 
174  switch (type_base) {
175  case CHEB_TYPE:
177  del_deriv() ;
178  for (int i=0 ; i<ndim ; i++)
179  coloc[i] = new Array<double> (nbr_points(i)) ;
180  for (int i=0 ; i<nbr_points(0) ; i++)
181  coloc[0]->set(i) = -cos(M_PI*i/(nbr_points(0)-1)) ;
182  for (int j=0 ; j<nbr_points(1) ; j++)
183  coloc[1]->set(j) = maxt*j/(nbr_points(1)-1) ;
184  break ;
185  case LEG_TYPE:
187  del_deriv() ;
188  for (int i=0 ; i<ndim ; i++)
189  coloc[i] = new Array<double> (nbr_points(i)) ;
190  for (int i=0 ; i<nbr_points(0) ; i++)
191  coloc[0]->set(i) = coloc_leg(i, nbr_points(0)) ;
192  for (int j=0 ; j<nbr_points(1) ; j++)
193  coloc[1]->set(j) = maxt*j/(nbr_points(1)-1) ;
194  break ;
195  default :
196  cerr << "Unknown type of basis in Domain_spheric_periodic_shell::do_coloc" << endl ;
197  abort() ;
198  }
199 }
200 
201 // Base for a function symetric in z, using Chebyshev
203 
204  assert (type_base == CHEB_TYPE) ;
205  base.allocate(nbr_coefs) ;
206 
207  Index index(base.bases_1d[0]->get_dimensions()) ;
208 
209  base.def=true ;
210  switch (type_time) {
211  case TO_PI :
212  base.bases_1d[1]->set(0) = COS ;
213  break ;
214  case TO_PI_OVER_2 :
215  base.bases_1d[1]->set(0) = COS_EVEN ;
216  break ;
217  default:
218  cerr << "Unknown case for type_time" << endl ;
219  abort() ;
220  }
221  for (int j=0 ; j<nbr_coefs(1) ; j++)
222  base.bases_1d[0]->set(j) = CHEB ;
223 }
224 
225 // Base for a function symetric in z, using Legendre
227 
228  assert (type_base == LEG_TYPE) ;
229  base.allocate(nbr_coefs) ;
230 
231  Index index(base.bases_1d[0]->get_dimensions()) ;
232  base.def=true ;
233  switch (type_time) {
234  case TO_PI :
235  base.bases_1d[1]->set(0) = COS ;
236  break ;
237  case TO_PI_OVER_2 :
238  base.bases_1d[1]->set(0) = COS_EVEN ;
239  break ;
240  default:
241  cerr << "Unknown case for type_time" << endl ;
242  abort() ;
243  }
244  for (int j=0 ; j<nbr_coefs(1) ; j++)
245  base.bases_1d[0]->set(j) = LEG ;
246  }
247 
249 
250  assert (type_base == CHEB_TYPE) ;
251  base.allocate(nbr_coefs) ;
252 
253  Index index(base.bases_1d[0]->get_dimensions()) ;
254 
255  base.def=true ;
256  switch (type_time) {
257  case TO_PI :
258  base.bases_1d[1]->set(0) = COS ;
259  break ;
260  case TO_PI_OVER_2 :
261  base.bases_1d[1]->set(0) = COS_EVEN ;
262  break ;
263  default:
264  cerr << "Unknown case for type_time" << endl ;
265  abort() ;
266  }
267  for (int j=0 ; j<nbr_coefs(1) ; j++)
268  base.bases_1d[0]->set(j) = CHEB ;
269 }
270 
272 
273  assert (type_base == LEG_TYPE) ;
274  base.allocate(nbr_coefs) ;
275 
276  Index index(base.bases_1d[0]->get_dimensions()) ;
277  base.def=true ;
278  switch (type_time) {
279  case TO_PI :
280  base.bases_1d[1]->set(0) = COS ;
281  break ;
282  case TO_PI_OVER_2 :
283  base.bases_1d[1]->set(0) = COS_EVEN ;
284  break ;
285  default:
286  cerr << "Unknown case for type_time" << endl ;
287  abort() ;
288  }
289  for (int j=0 ; j<nbr_coefs(1) ; j++)
290  base.bases_1d[0]->set(j) = LEG ;
291  }
292 
294 
295  assert (type_base == CHEB_TYPE) ;
296  base.allocate(nbr_coefs) ;
297 
298  Index index(base.bases_1d[0]->get_dimensions()) ;
299 
300  base.def=true ;
301  switch (type_time) {
302  case TO_PI_OVER_2 :
303  base.bases_1d[1]->set(0) = COS_ODD ;
304  break ;
305  default:
306  cerr << "Unknown case for type_time" << endl ;
307  abort() ;
308  }
309  for (int j=0 ; j<nbr_coefs(1) ; j++)
310  base.bases_1d[0]->set(j) = CHEB ;
311 }
312 
313 // Base for a function symetric in z, using Legendre
315 
316  assert (type_base == LEG_TYPE) ;
317  base.allocate(nbr_coefs) ;
318 
319  Index index(base.bases_1d[0]->get_dimensions()) ;
320  base.def=true ;
321  switch (type_time) {
322  case TO_PI_OVER_2 :
323  base.bases_1d[1]->set(0) = COS_ODD ;
324  break ;
325  default:
326  cerr << "Unknown case for type_time" << endl ;
327  abort() ;
328  }
329  for (int j=0 ; j<nbr_coefs(1) ; j++)
330  base.bases_1d[0]->set(j) = LEG ;
331  }
332 // Computes the derivatives with respect to rho,Z as a function of the numerical ones.
333 void Domain_spheric_periodic_shell::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
334  // d/dr
335  der_abs[0] = new Val_domain (*der_var[0]/alpha) ;
336  // d/dt :
337  der_abs[1] = new Val_domain (*der_var[1]*ome) ;
338 }
339 
340 // Rules for the multiplication of two basis.
342 
343  assert (a.ndim==2) ;
344  assert (b.ndim==2) ;
345 
346  Base_spectral res(2) ;
347  bool res_def = true ;
348 
349  if (!a.def)
350  res_def=false ;
351  if (!b.def)
352  res_def=false ;
353 
354  if (res_def) {
355 
356 
357  // Bases in theta :
358  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
359  switch ((*a.bases_1d[1])(0)) {
360  case COS:
361  switch ((*b.bases_1d[1])(0)) {
362  case COS:
363  res.bases_1d[1]->set(0) = COS ;
364  break ;
365  case SIN:
366  res.bases_1d[1]->set(0) = SIN ;
367  break ;
368  default:
369  res_def = false ;
370  break ;
371  }
372  break ;
373  case SIN:
374  switch ((*b.bases_1d[1])(0)) {
375  case COS:
376  res.bases_1d[1]->set(0) = SIN ;
377  break ;
378  case SIN:
379  res.bases_1d[1]->set(0) = COS ;
380  break ;
381  default:
382  res_def = false ;
383  break ;
384  }
385  break ;
386  case COS_EVEN:
387  switch ((*b.bases_1d[1])(0)) {
388  case COS_EVEN:
389  res.bases_1d[1]->set(0) = COS_EVEN ;
390  break ;
391  case COS_ODD:
392  res.bases_1d[1]->set(0) = COS_ODD ;
393  break ;
394  case SIN_EVEN:
395  res.bases_1d[1]->set(0) = SIN_EVEN ;
396  break ;
397  case SIN_ODD:
398  res.bases_1d[1]->set(0) = SIN_ODD ;
399  break ;
400  default:
401  res_def = false ;
402  break ;
403  }
404  break ;
405  case COS_ODD:
406  switch ((*b.bases_1d[1])(0)) {
407  case COS_EVEN:
408  res.bases_1d[1]->set(0) = COS_ODD ;
409  break ;
410  case COS_ODD:
411  res.bases_1d[1]->set(0) = COS_EVEN ;
412  break ;
413  case SIN_EVEN:
414  res.bases_1d[1]->set(0) = SIN_ODD ;
415  break ;
416  case SIN_ODD:
417  res.bases_1d[1]->set(0) = SIN_EVEN ;
418  break ;
419  default:
420  res_def = false ;
421  break ;
422  }
423  break ;
424  case SIN_EVEN:
425  switch ((*b.bases_1d[1])(0)) {
426  case COS_EVEN:
427  res.bases_1d[1]->set(0) = SIN_EVEN ;
428  break ;
429  case COS_ODD:
430  res.bases_1d[1]->set(0) = SIN_ODD ;
431  break ;
432  case SIN_EVEN:
433  res.bases_1d[1]->set(0) = COS_EVEN ;
434  break ;
435  case SIN_ODD:
436  res.bases_1d[1]->set(0) = COS_ODD ;
437  break ;
438  default:
439  res_def = false ;
440  break ;
441  }
442  break ;
443  case SIN_ODD:
444  switch ((*b.bases_1d[1])(0)) {
445  case COS_EVEN:
446  res.bases_1d[1]->set(0) = SIN_ODD ;
447  break ;
448  case COS_ODD:
449  res.bases_1d[1]->set(0) = SIN_EVEN ;
450  break ;
451  case SIN_EVEN:
452  res.bases_1d[1]->set(0) = COS_ODD ;
453  break ;
454  case SIN_ODD:
455  res.bases_1d[1]->set(0) = COS_EVEN ;
456  break ;
457  default:
458  res_def = false ;
459  break ;
460  }
461  break ;
462  default:
463  res_def = false ;
464  break ;
465  }
466 
467  // Base in r :
468  Index index_0 (a.bases_1d[0]->get_dimensions()) ;
469  res.bases_1d[0] = new Array<int> (a.bases_1d[0]->get_dimensions()) ;
470  do {
471  switch ((*a.bases_1d[0])(index_0)) {
472  case CHEB:
473  switch ((*b.bases_1d[0])(index_0)) {
474  case CHEB:
475  res.bases_1d[0]->set(index_0) = CHEB ;
476  break ;
477  default:
478  res_def = false ;
479  break ;
480  }
481  break ;
482  case LEG:
483  switch ((*b.bases_1d[0])(index_0)) {
484  case LEG:
485  res.bases_1d[0]->set(index_0) = LEG ;
486  break ;
487  default:
488  res_def = false ;
489  break ;
490  }
491  break ;
492  default:
493  res_def = false ;
494  break ;
495  }
496  }
497  while (index_0.inc()) ;
498  }
499 
500  if (!res_def)
501  for (int dim=0 ; dim<a.ndim ; dim++)
502  if (res.bases_1d[dim]!= 0x0) {
503  delete res.bases_1d[dim] ;
504  res.bases_1d[dim] = 0x0 ;
505  }
506  res.def = res_def ;
507  return res ;
508 }
509 }
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 bounded between two fixed radii and a symetry with respect...
double maxt
Upper bound of which is or .
virtual void set_anti_cheb_base(Base_spectral &) const
Gives the base using Chebyshev polynomials, for functions antisymetric with respect to .
virtual void do_absol() const
Computes the absolute coordinates.
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
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 set_anti_legendre_base(Base_spectral &) const
Gives the base using Legendre polynomials, for functions antisymetric with respect to .
virtual void save(FILE *) const
Saving function.
virtual void set_cheb_base(Base_spectral &) const
Gives the standard base for Chebyshev polynomials.
virtual void do_radius() const
Computes the generalized radius.
virtual void set_legendre_base_odd(Base_spectral &) const
Gives the base using odd Legendre polynomials$.
double alpha
Relates the numerical to the physical radii.
virtual void do_coloc()
Computes the colocation points.
double ome
Relates the numerical time to the physical one.
virtual void set_legendre_base(Base_spectral &) const
Gives the standard base for Legendre polynomials.
double beta
Relates the numerical to the physical radii.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
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 ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
Domain_spheric_periodic_shell(int num, int ttype, int typet, double r_int, double r_ext, double ome, const Dim_array &nbr)
Standard constructor :
virtual Val_domain der_normal(const Val_domain &, int) const
Normal derivative with respect to a given surface.
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