KADATH
domain_polar_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 "polar.hpp"
22 #include "point.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_polar_nucleus::Domain_polar_nucleus (int num, int ttype, double r, const Point& cr, const Dim_array& nbr) :
33  Domain(num, ttype, nbr), alpha(r),center(cr) {
34  assert (nbr.get_ndim()==2) ;
35  assert (cr.get_ndim()==2) ;
36  do_coloc() ;
37 }
38 
39 // Constructor by copy
40 Domain_polar_nucleus::Domain_polar_nucleus (const Domain_polar_nucleus& so) : Domain(so), alpha(so.alpha), center(so.center) {
41 }
42 
43 Domain_polar_nucleus::Domain_polar_nucleus (int num, FILE* fd) : Domain(num, fd), center(fd) {
44  fread_be (&alpha, sizeof(double), 1, fd) ;
45  do_coloc() ;
46 }
47 
48 // Destructor
49 Domain_polar_nucleus::~Domain_polar_nucleus() {}
50 
51 void Domain_polar_nucleus::save (FILE* fd) const {
52  nbr_points.save(fd) ;
53  nbr_coefs.save(fd) ;
54  fwrite_be (&ndim, sizeof(int), 1, fd) ;
55  fwrite_be (&type_base, sizeof(int), 1, fd) ;
56  center.save(fd) ;
57  fwrite_be (&alpha, sizeof(double), 1, fd) ;
58 }
59 
60 ostream& Domain_polar_nucleus::print (ostream& o) const {
61  o << "Polar nucleus" << endl ;
62  o << "Rmax = " << alpha << endl ;
63  o << "Center = " << center << endl ;
64  o << "Nbr pts = " << nbr_points << endl ;
65  o << endl ;
66  return o ;
67 }
68 
69 
71 
72  Val_domain res (so.der_var(1)) ;
73  switch (bound) {
74  case OUTER_BC :
75  res /= alpha ;
76  break ;
77  default:
78  cerr << "Unknown boundary case in Domain_polar_nucleus::der_normal" << endl ;
79  abort() ;
80  }
81 return res ;
82 }
83 
84 // Computes the cartesian coordinates
86  for (int i=0 ; i<2 ; i++)
87  assert (coloc[i] != 0x0) ;
88  for (int i=0 ; i<2 ; i++)
89  assert (absol[i] == 0x0) ;
90  for (int i=0 ; i<2 ; i++) {
91  absol[i] = new Val_domain(this) ;
92  absol[i]->allocate_conf() ;
93  }
94  Index index (nbr_points) ;
95  do {
96  absol[0]->set(index) = alpha* ((*coloc[0])(index(0))) *
97  sin((*coloc[1])(index(1))) + center(1);
98  absol[1]->set(index) = alpha* ((*coloc[0])(index(0))) * cos((*coloc[1])(index(1))) + center(2) ;
99  }
100  while (index.inc()) ;
101 
102 }
103 
104 // Computes the radius
106 
107  for (int i=0 ; i<2 ; i++)
108  assert (coloc[i] != 0x0) ;
109  assert (radius == 0x0) ;
110  radius = new Val_domain(this) ;
111  radius->allocate_conf() ;
112  Index index (nbr_points) ;
113  do
114  radius->set(index) = alpha* ((*coloc[0])(index(0))) ;
115  while (index.inc()) ;
116 }
117 
118 // Computes the cartesian coordinates
120  for (int i=0 ; i<2 ; i++)
121  assert (coloc[i] != 0x0) ;
122  for (int i=0 ; i<2 ; i++)
123  assert (cart[i] == 0x0) ;
124  for (int i=0 ; i<2 ; i++) {
125  cart[i] = new Val_domain(this) ;
126  cart[i]->allocate_conf() ;
127  }
128  Index index (nbr_points) ;
129  do {
130  cart[0]->set(index) = alpha* ((*coloc[0])(index(0))) *
131  sin((*coloc[1])(index(1))) + center(1);
132  cart[1]->set(index) = alpha* ((*coloc[0])(index(0))) * cos((*coloc[1])(index(1))) + center(2) ;
133  }
134  while (index.inc()) ;
135 
136 }
137 
138 // Computes the cartesian coordinates over the radius
140  for (int i=0 ; i<2 ; i++)
141  assert (coloc[i] != 0x0) ;
142  for (int i=0 ; i<2 ; i++)
143  assert (cart_surr[i] == 0x0) ;
144  for (int i=0 ; i<2 ; i++) {
145  cart_surr[i] = new Val_domain(this) ;
146  cart_surr[i]->allocate_conf() ;
147  }
148  Index index (nbr_points) ;
149  do {
150  cart_surr[0]->set(index) = sin((*coloc[1])(index(1))) + center(1);
151  cart_surr[1]->set(index) = cos((*coloc[1])(index(1))) + center(2) ;
152  }
153  while (index.inc()) ;
154 
155 }
156 
157 // Is a point inside this domain ?
158 bool Domain_polar_nucleus::is_in (const Point& xx, double prec) const {
159 
160  assert (xx.get_ndim()==2) ;
161 
162  double rho_loc = xx(1) - center(1) ;
163  double z_loc = xx(2) - center(2) ;
164  double air_loc = sqrt (rho_loc*rho_loc + z_loc*z_loc) ;
165 
166  bool res = (air_loc <= alpha+prec) ? true : false ;
167  return res ;
168 }
169 
170 // Convert absolute coordinates to numerical ones
172 
173  assert (is_in(abs)) ;
174  Point num(2) ;
175 
176  double rho_loc = fabs(abs(1) - center(1)) ;
177  double z_loc = abs(2) - center(2) ;
178  double air = sqrt(rho_loc*rho_loc+z_loc*z_loc) ;
179  num.set(1) = air/alpha ;
180 
181  if (rho_loc==0) {
182  // Sur l'axe
183  num.set(2) = (z_loc>=0) ? 0 : M_PI ;
184  }
185  else {
186  num.set(2) = atan(rho_loc/z_loc) ;
187  }
188 
189  if (num(2) <0)
190  num.set(2) = M_PI + num(2) ;
191 
192  return num ;
193 }
194 
195 double coloc_leg_parity(int, int) ;
197 
198  switch (type_base) {
199  case CHEB_TYPE:
201  del_deriv() ;
202  for (int i=0 ; i<ndim ; i++)
203  coloc[i] = new Array<double> (nbr_points(i)) ;
204  for (int i=0 ; i<nbr_points(0) ; i++)
205  coloc[0]->set(i) = sin(M_PI/2.*i/(nbr_points(0)-1)) ;
206  for (int j=0 ; j<nbr_points(1) ; j++)
207  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
208  break ;
209  case LEG_TYPE:
211  del_deriv() ;
212  for (int i=0 ; i<ndim ; i++)
213  coloc[i] = new Array<double> (nbr_points(i)) ;
214  for (int i=0 ; i<nbr_points(0) ; i++)
215  coloc[0]->set(i) = coloc_leg_parity(i, nbr_points(0)) ;
216  for (int j=0 ; j<nbr_points(1) ; j++)
217  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
218  break ;
219  default :
220  cerr << "Unknown type of basis in Domain_polar_nucleus::do_coloc" << endl ;
221  abort() ;
222  }
223 }
224 
225 // Base for a function symetric in z, using Chebyshev
227  set_cheb_base_with_m (base, 0) ;
228 }
229 
230 // Base for a function anti-symetric in z, using Chebyshev
232  set_anti_cheb_base_with_m(base, 0) ;
233 }
234 
235 // Base for a function symetric in z, using Legendre
237  set_legendre_base_with_m(base, 0) ;
238  }
239 
240 // Base for a function anti-symetric in z, using Legendre
243  }
244 
245 // Base for a function symetric in z, using Chebyshev
247 
248  int l ;
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  base.bases_1d[1]->set(0) = (m%2==0) ? COS_EVEN : SIN_ODD ;
257  for (int j=0 ; j<nbr_coefs(1) ; j++) {
258  l = (m%2==0) ? 2*j : 2*j+1 ;
259  base.bases_1d[0]->set(j) = (l%2==0) ? CHEB_EVEN : CHEB_ODD ;
260  }
261 }
262 
263 // Base for a function anti-symetric in z, using Chebyshev
265 
266  int l ;
267 
268  assert (type_base == CHEB_TYPE) ;
269  base.allocate(nbr_coefs) ;
270 
271  Index index(base.bases_1d[0]->get_dimensions()) ;
272 
273  base.def=true ;
274  base.bases_1d[1]->set(0) = (m%2==0) ? COS_ODD : SIN_EVEN ;
275  for (int j=0 ; j<nbr_coefs(1) ; j++) {
276  l = (m%2==0) ? 2*j+1 : 2*j ;
277  base.bases_1d[0]->set(j) = (l%2==1) ? CHEB_ODD : CHEB_EVEN ;
278  }
279 }
280 
281 // Base for a function symetric in z, using Legendre
283 
284  int l ;
285 
286  assert (type_base == LEG_TYPE) ;
287  base.allocate(nbr_coefs) ;
288 
289  Index index(base.bases_1d[0]->get_dimensions()) ;
290 
291  base.def = true ;
292  base.bases_1d[1]->set(0) = (m%2==0) ? COS_EVEN : SIN_ODD ;
293  for (int j=0 ; j<nbr_coefs(1) ; j++) {
294  l = (m%2==0) ? 2*j : 2*j+1 ;
295  base.bases_1d[0]->set(j) = (l%2==0) ? LEG_EVEN : LEG_ODD ;
296  }
297  }
298 
299 // Base for a function anti-symetric in z, using Legendre
301 
302  int l ;
303 
304  assert (type_base == LEG_TYPE) ;
305  base.allocate(nbr_coefs) ;
306 
307  Index index(base.bases_1d[0]->get_dimensions()) ;
308 
309  base.def = true ;
310  base.bases_1d[1]->set(0) = (m%2==0) ? COS_ODD : SIN_EVEN ;
311  for (int j=0 ; j<nbr_coefs(1) ; j++) {
312  l = (m%2==0) ? 2*j+1 : 2*j ;
313  base.bases_1d[0]->set(j) = (l%2==1) ? LEG_ODD : LEG_EVEN ;
314  }
315  }
316 
317 // Computes the derivatives with respect to rho,Z as a function of the numerical ones.
318 void Domain_polar_nucleus::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
319  Val_domain dr (*der_var[0]/alpha) ;
320  Val_domain dtsr (der_var[1]->div_x()/alpha) ;
321 
322  // D / drho
323  der_abs[0] = new Val_domain (dr.mult_sin_theta() + dtsr.mult_cos_theta()) ;
324  // d/dz :
325  der_abs[1] = new Val_domain (dr.mult_cos_theta() - dtsr.mult_sin_theta()) ;
326 }
327 
328 // Rules for the multiplication of two basis.
330 
331  assert (a.ndim==2) ;
332  assert (b.ndim==2) ;
333 
334  Base_spectral res(2) ;
335  bool res_def = true ;
336 
337  if (!a.def)
338  res_def=false ;
339  if (!b.def)
340  res_def=false ;
341 
342  if (res_def) {
343 
344 
345  // Bases in theta :
346  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
347  switch ((*a.bases_1d[1])(0)) {
348  case COS_EVEN:
349  switch ((*b.bases_1d[1])(0)) {
350  case COS_EVEN:
351  res.bases_1d[1]->set(0) = COS_EVEN ;
352  break ;
353  case COS_ODD:
354  res.bases_1d[1]->set(0) = COS_ODD ;
355  break ;
356  case SIN_EVEN:
357  res.bases_1d[1]->set(0) = SIN_EVEN ;
358  break ;
359  case SIN_ODD:
360  res.bases_1d[1]->set(0) = SIN_ODD ;
361  break ;
362  default:
363  res_def = false ;
364  break ;
365  }
366  break ;
367  case COS_ODD:
368  switch ((*b.bases_1d[1])(0)) {
369  case COS_EVEN:
370  res.bases_1d[1]->set(0) = COS_ODD ;
371  break ;
372  case COS_ODD:
373  res.bases_1d[1]->set(0) = COS_EVEN ;
374  break ;
375  case SIN_EVEN:
376  res.bases_1d[1]->set(0) = SIN_ODD ;
377  break ;
378  case SIN_ODD:
379  res.bases_1d[1]->set(0) = SIN_EVEN ;
380  break ;
381  default:
382  res_def = false ;
383  break ;
384  }
385  break ;
386  case SIN_EVEN:
387  switch ((*b.bases_1d[1])(0)) {
388  case COS_EVEN:
389  res.bases_1d[1]->set(0) = SIN_EVEN ;
390  break ;
391  case COS_ODD:
392  res.bases_1d[1]->set(0) = SIN_ODD ;
393  break ;
394  case SIN_EVEN:
395  res.bases_1d[1]->set(0) = COS_EVEN ;
396  break ;
397  case SIN_ODD:
398  res.bases_1d[1]->set(0) = COS_ODD ;
399  break ;
400  default:
401  res_def = false ;
402  break ;
403  }
404  break ;
405  case SIN_ODD:
406  switch ((*b.bases_1d[1])(0)) {
407  case COS_EVEN:
408  res.bases_1d[1]->set(0) = SIN_ODD ;
409  break ;
410  case COS_ODD:
411  res.bases_1d[1]->set(0) = SIN_EVEN ;
412  break ;
413  case SIN_EVEN:
414  res.bases_1d[1]->set(0) = COS_ODD ;
415  break ;
416  case SIN_ODD:
417  res.bases_1d[1]->set(0) = COS_EVEN ;
418  break ;
419  default:
420  res_def = false ;
421  break ;
422  }
423  break ;
424  default:
425  res_def = false ;
426  break ;
427  }
428 
429  // Base in r :
430  Index index_0 (a.bases_1d[0]->get_dimensions()) ;
431  res.bases_1d[0] = new Array<int> (a.bases_1d[0]->get_dimensions()) ;
432  do {
433  switch ((*a.bases_1d[0])(index_0)) {
434  case CHEB_EVEN:
435  switch ((*b.bases_1d[0])(index_0)) {
436  case CHEB_EVEN:
437  res.bases_1d[0]->set(index_0) = CHEB_EVEN ;
438  break ;
439  case CHEB_ODD:
440  res.bases_1d[0]->set(index_0) = CHEB_ODD ;
441  break ;
442  default:
443  res_def = false ;
444  break ;
445  }
446  break ;
447  case CHEB_ODD:
448  switch ((*b.bases_1d[0])(index_0)) {
449  case CHEB_EVEN:
450  res.bases_1d[0]->set(index_0) = CHEB_ODD ;
451  break ;
452  case CHEB_ODD:
453  res.bases_1d[0]->set(index_0) = CHEB_EVEN ;
454  break ;
455  default:
456  res_def = false ;
457  break ;
458  }
459  break ;
460  case LEG_EVEN:
461  switch ((*b.bases_1d[0])(index_0)) {
462  case LEG_EVEN:
463  res.bases_1d[0]->set(index_0) = LEG_EVEN ;
464  break ;
465  case LEG_ODD:
466  res.bases_1d[0]->set(index_0) = LEG_ODD ;
467  break ;
468  default:
469  res_def = false ;
470  break ;
471  }
472  break ;
473  case LEG_ODD:
474  switch ((*b.bases_1d[0])(index_0)) {
475  case LEG_EVEN:
476  res.bases_1d[0]->set(index_0) = LEG_ODD ;
477  break ;
478  case LEG_ODD:
479  res.bases_1d[0]->set(index_0) = LEG_EVEN ;
480  break ;
481  default:
482  res_def = false ;
483  break ;
484  }
485  break ;
486  default:
487  res_def = false ;
488  break ;
489  }
490  }
491  while (index_0.inc()) ;
492  }
493  if (!res_def)
494  for (int dim=0 ; dim<a.ndim ; dim++)
495  if (res.bases_1d[dim]!= 0x0) {
496  delete res.bases_1d[dim] ;
497  res.bases_1d[dim] = 0x0 ;
498  }
499  res.def = res_def ;
500  return res ;
501 }
502 
504  int res = -1 ;
505  if (strcmp(p,"R ")==0)
506  res = 0 ;
507  if (strcmp(p,"T ")==0)
508  res = 1 ;
509  return res ;
510 }
511 }
512 
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...
Definition: polar.hpp:45
virtual Val_domain der_normal(const Val_domain &, int) const
Normal derivative with respect to a given surface.
Domain_polar_nucleus(int num, int ttype, double radius, const Point &cr, const Dim_array &nbr)
Standard constructor :
virtual void set_anti_cheb_base_with_m(Base_spectral &, int m) const
Gives the base using Chebyshev polynomials, for functions antisymetric with respect to .
virtual void set_legendre_base_with_m(Base_spectral &, int m) const
Gives the stnadard base using Legendre polynomials.
virtual void set_cheb_base(Base_spectral &) const
Gives the standard base for Chebyshev polynomials.
virtual void do_cart_surr() const
Computes the Cartesian coordinates over the 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 set_anti_legendre_base_with_m(Base_spectral &, int m) 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 int give_place_var(char *) const
Translates a name of a coordinate into its corresponding numerical name.
virtual Val_domain div_x(const Val_domain &) const
Division by .
Point center
Absolute coordinates of the center.
Definition: polar.hpp:49
virtual void do_coloc()
Computes the colocation points.
virtual void set_cheb_base_with_m(Base_spectral &, int m) const
Gives the standard base using Chebyshev polynomials.
virtual void set_anti_legendre_base(Base_spectral &) const
Gives the base using Legendre polynomials, for functions antisymetric with respect to .
virtual void set_legendre_base(Base_spectral &) const
Gives the standard base for Legendre polynomials.
virtual void do_cart() const
Computes the Cartesian coordinates.
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 ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
virtual void save(FILE *) const
Saving function.
virtual void do_radius() const
Computes the generalized radius.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
double alpha
Relates the numerical to the physical radii.
Definition: polar.hpp:48
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 * > cart
Cartesian coordinates.
Definition: space.hpp:77
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
Memory_mapped_array< Val_domain * > cart_surr
Cartesian coordinates divided by the radius.
Definition: space.hpp:79
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
void save(FILE *) const
Saving function.
Definition: point.cpp:33
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_theta() 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 mult_cos_theta() 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