KADATH
domain_polar_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 "polar.hpp"
23 #include "point.hpp"
24 #include "array_math.hpp"
25 #include "val_domain.hpp"
26 namespace Kadath {
27 // Standard constructor
28 Domain_polar_compact::Domain_polar_compact (int num, int ttype, double r, const Point& cr, const Dim_array& nbr) : Domain(num, ttype, nbr), alpha(-0.5/r),
29  center(cr) {
30 
31  assert (nbr.get_ndim()==2) ;
32  assert (cr.get_ndim()==2) ;
33  do_coloc() ;
34 
35 }
36 
37 // Copy constructor
38 Domain_polar_compact::Domain_polar_compact (const Domain_polar_compact& so) : Domain(so), alpha(so.alpha), center(so.center){}
39 
40 
41 Domain_polar_compact::Domain_polar_compact (int num , FILE* fd) : Domain(num, fd), center(fd) {
42  fread_be (&alpha, sizeof(double), 1, fd) ;
43  do_coloc() ;
44 }
45 
46 // Destructor
47 Domain_polar_compact::~Domain_polar_compact() {}
48 
49 ostream& Domain_polar_compact::print (ostream& o) const {
50  o << "Compactified polar domain" << endl ;
51  o << "Rmin = " << -0.5/alpha << endl ;
52  o << "Center = " << center << endl ;
53  o << "Nbr pts = " << nbr_points << endl ;
54  o << endl ;
55  return o ;
56 }
57 
58 void Domain_polar_compact::save (FILE* fd) const {
59  nbr_points.save(fd) ;
60  nbr_coefs.save(fd) ;
61  fwrite_be (&ndim, sizeof(int), 1, fd) ;
62  fwrite_be (&type_base, sizeof(int), 1, fd) ;
63  center.save(fd) ;
64  fwrite_be (&alpha, sizeof(double), 1, fd) ;
65 }
66 
67 
69 
70  Val_domain res (so.der_var(1)) ;
71  switch (bound) {
72  case INNER_BC :
73  res = res.mult_xm1() ;
74  res = res.mult_xm1() ;
75  res *= -alpha ;
76  break ;
77  case OUTER_BC :
78  res = res.mult_xm1() ;
79  res = res.mult_xm1() ;
80  res *= -alpha ;
81  break ;
82  default:
83  cerr << "Unknown boundary case in Domain_polar_compact::der_normal" << endl ;
84  abort() ;
85  }
86 return res ;
87 }
88 
89 double Domain_polar_compact::integ (const Val_domain& so, int bound) const {
90  double res = 0 ;
91 
92  int baset = (*so.base.bases_1d[1]) (0) ;
93  if (baset != COS_EVEN) {
94  // Odd function
95  return res ;
96  }
97  else {
98  // For now only at infinity
99  if (bound!=OUTER_BC) {
100  cerr << "Domain_polar_compact::integ only defined for outer boundary" << endl ;
101  abort() ;
102  }
103 
104  Val_domain auxi (so.div_xm1()) ;
105  auxi = auxi.div_xm1() ;
106  auxi /= alpha * alpha ;
107  auxi.coef() ;
108 
109  //Loop on theta :
110  Index pos (get_nbr_coefs()) ;
111  for (int j=0 ; j<nbr_coefs(1) ; j++) {
112  pos.set(1) = j ;
113  double fact_tet = 2./double(1-4*j*j) ;
114  // Loop on r :
115  for (int i=0 ; i<nbr_coefs(0) ; i++) {
116  pos.set(0) = i ;
117  res += fact_tet*(*auxi.cf)(pos) ;
118  }
119  }
120  return res*2*M_PI ;
121  }
122 }
123 
124 // Computes the Cartesian coordinates
126  for (int i=0 ; i<2 ; i++)
127  assert (coloc[i] != 0x0) ;
128  for (int i=0 ; i<2 ; i++)
129  assert (absol[i] == 0x0) ;
130  for (int i=0 ; i<2 ; i++) {
131  absol[i] = new Val_domain(this) ;
132  absol[i]->allocate_conf() ;
133  }
134  Index index (nbr_points) ;
135  do {
136  absol[0]->set(index) = (1./alpha/ ((*coloc[0])(index(0))-1)) *
137  sin((*coloc[1])(index(1))) + center(1) ;
138  absol[1]->set(index) = (1./alpha/ ((*coloc[0])(index(0))-1)) * cos((*coloc[1])(index(1))) +
139  center(2) ;
140  }
141  while (index.inc()) ;
142 }
143 
144 // Computes the radius
146  for (int i=0 ; i<2 ; i++)
147  assert (coloc[i] != 0x0) ;
148  assert (radius == 0x0) ;
149  radius = new Val_domain(this) ;
150  radius->allocate_conf() ;
151  Index index (nbr_points) ;
152  do
153  radius->set(index) = 1./alpha/ ((*coloc[0])(index(0))-1) ;
154  while (index.inc()) ;
155 }
156 
157 // Computes the Cartesian coordinates
159  for (int i=0 ; i<2 ; i++)
160  assert (coloc[i] != 0x0) ;
161  for (int i=0 ; i<2 ; i++)
162  assert (cart[i] == 0x0) ;
163  for (int i=0 ; i<2 ; i++) {
164  cart[i] = new Val_domain(this) ;
165  cart[i]->allocate_conf() ;
166  }
167  Index index (nbr_points) ;
168  do {
169  cart[0]->set(index) = (1./alpha/ ((*coloc[0])(index(0))-1)) *
170  sin((*coloc[1])(index(1))) + center(1) ;
171  cart[1]->set(index) = (1./alpha/ ((*coloc[0])(index(0))-1)) * cos((*coloc[1])(index(1))) +
172  center(2) ;
173  }
174  while (index.inc()) ;
175 }
176 
177 // Computes the Cartesian coordinates ovzr radius
179  for (int i=0 ; i<2 ; i++)
180  assert (coloc[i] != 0x0) ;
181  for (int i=0 ; i<2 ; i++)
182  assert (cart_surr[i] == 0x0) ;
183  for (int i=0 ; i<2 ; i++) {
184  cart_surr[i] = new Val_domain(this) ;
185  cart_surr[i]->allocate_conf() ;
186  }
187  Index index (nbr_points) ;
188  do {
189  cart_surr[0]->set(index) = sin((*coloc[1])(index(1))) + center(1) ;
190  cart_surr[1]->set(index) = cos((*coloc[1])(index(1))) + center(2) ;
191  }
192  while (index.inc()) ;
193 }
194 
195 // Is inside ?
196 bool Domain_polar_compact::is_in (const Point& xx, double prec) const {
197 
198  assert (xx.get_ndim()==2) ;
199 
200  double rho_loc = xx(1) - center(1) ;
201  double z_loc = xx(2) - center(2) ;
202  double air_loc = sqrt (rho_loc*rho_loc + z_loc*z_loc) ;
203 
204  bool res = (air_loc >= -0.5/alpha-prec) ? true : false ;
205  return res ;
206 }
207 
208 // Converts the absolute coordinates to the numerical ones.
210 
211  assert (is_in(abs)) ;
212  Point num(3) ;
213 
214  double rho_loc = fabs(abs(1) - center(1)) ;
215  double z_loc = abs(2) - center(2) ;
216  double air = sqrt(rho_loc*rho_loc+z_loc*z_loc) ;
217  num.set(1) = 1. + 1./air/alpha ;
218 
219  if (rho_loc==0) {
220  // On the axis ?
221  num.set(2) = (z_loc>=0) ? 0 : M_PI ;
222  }
223  else {
224  num.set(2) = atan(rho_loc/z_loc) ;
225  }
226 
227  if (num(2) <0)
228  num.set(2) = M_PI + num(2) ;
229 
230  return num ;
231 }
232 
233 
234 double coloc_leg(int,int) ;
236 
237  switch (type_base) {
238  case CHEB_TYPE:
240  del_deriv() ;
241  for (int i=0 ; i<ndim ; i++)
242  coloc[i] = new Array<double> (nbr_points(i)) ;
243  for (int i=0 ; i<nbr_points(0) ; i++)
244  coloc[0]->set(i) = -cos(M_PI*i/(nbr_points(0)-1)) ;
245  for (int j=0 ; j<nbr_points(1) ; j++)
246  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
247  break ;
248  case LEG_TYPE:
250  del_deriv() ;
251  for (int i=0 ; i<ndim ; i++)
252  coloc[i] = new Array<double> (nbr_points(i)) ;
253  for (int i=0 ; i<nbr_points(0) ; i++)
254  coloc[0]->set(i) = coloc_leg(i, nbr_points(0)) ;
255  for (int j=0 ; j<nbr_points(1) ; j++)
256  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
257  break ;
258  default :
259  cerr << "Unknown type of basis in Domain_polar_compact::do_coloc" << endl ;
260  abort() ;
261  }
262 }
263 // standard base for a symetric function using Chebyshev
265  set_cheb_base_with_m(base, 0) ;
266 }
267 
268 // standard base for a anti-symetric function using Chebyshev
270  set_anti_cheb_base_with_m (base, 0) ;
271 }
272 // standard base for a symetric function using Legendre
274  set_legendre_base_with_m (base, 0) ;
275 }
276 
277 // standard base for a anti-symetric function using Legendre
280 }
281 
282 // standard base for a symetric function using Chebyshev
284 
285  assert (type_base == CHEB_TYPE) ;
286 
287  base.allocate(nbr_coefs) ;
288 
289  base.def =true ;
290 
291  base.bases_1d[1]->set(0) = (m%2==0) ? COS_EVEN : SIN_ODD ;
292  for (int j=0 ; j<nbr_coefs(1) ; j++)
293  base.bases_1d[0]->set(j) = CHEB ;
294 }
295 
296 // standard base for a anti-symetric function using Chebyshev
298  assert (type_base == CHEB_TYPE) ;
299 
300  base.allocate(nbr_coefs) ;
301 
302  base.def =true ;
303 
304  base.bases_1d[1]->set(0) = (m%2==0) ? COS_ODD : SIN_EVEN ;
305  for (int j=0 ; j<nbr_coefs(1) ; j++)
306  base.bases_1d[0]->set(j) = CHEB ;
307 }
308 // standard base for a symetric function using Legendre
310  assert (type_base == CHEB_TYPE) ;
311 
312  base.allocate(nbr_coefs) ;
313 
314  base.def =true ;
315 
316  base.bases_1d[1]->set(0) = (m%2==0) ? COS_EVEN : SIN_ODD ;
317  for (int j=0 ; j<nbr_coefs(1) ; j++)
318  base.bases_1d[0]->set(j) = LEG ;
319 }
320 
321 // standard base for a anti-symetric function using Legendre
323 
324  assert (type_base == CHEB_TYPE) ;
325 
326  base.allocate(nbr_coefs) ;
327 
328  base.def =true ;
329 
330  base.bases_1d[1]->set(0) = (m%2==0) ? COS_ODD : SIN_EVEN ;
331  for (int j=0 ; j<nbr_coefs(1) ; j++)
332  base.bases_1d[0]->set(j) = LEG ;
333 }
334 
335 
336 // sets the value at infinity
337 void Domain_polar_compact::set_val_inf (Val_domain& so, double x) const {
338 
339  assert (so.get_domain() == this) ;
340 
341  so.coef_i() ;
342  so.set_in_conf() ;
343  Index inf (nbr_points) ;
344  inf.set(0) = nbr_points(0)-1 ;
345  do
346  so.set(inf) = x ;
347  while (inf.inc1(1)) ;
348 }
349 
350 // Computes the derivatives with respect to XYZ as function of the numerical ones.
351 void Domain_polar_compact::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
352  Val_domain dr (-der_var[0]->mult_xm1()) ;
353 
354  // d/dx :
355  Val_domain auxi_x (dr.mult_sin_theta()+der_var[1]->mult_cos_theta()) ;
356  der_abs[0] = new Val_domain (alpha*auxi_x.mult_xm1()) ;
357 
358  // d/dz :
359  Val_domain auxi_z (dr.mult_cos_theta() - der_var[1]->mult_sin_theta()) ;
360  der_abs[1] = new Val_domain (alpha*auxi_z.mult_xm1()) ;
361 }
362 
363 // Rules for basis multiplication
365 
366  assert (a.ndim==2) ;
367  assert (b.ndim==2) ;
368 
369  Base_spectral res(2) ;
370  bool res_def = true ;
371 
372  if (!a.def)
373  res_def=false ;
374  if (!b.def)
375  res_def=false ;
376 
377  if (res_def) {
378 
379  // Bases in theta :
380  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
381  switch ((*a.bases_1d[1])(0)) {
382  case COS_EVEN:
383  switch ((*b.bases_1d[1])(0)) {
384  case COS_EVEN:
385  res.bases_1d[1]->set(0) = COS_EVEN ;
386  break ;
387  case COS_ODD:
388  res.bases_1d[1]->set(0) = COS_ODD ;
389  break ;
390  case SIN_EVEN:
391  res.bases_1d[1]->set(0) = SIN_EVEN ;
392  break ;
393  case SIN_ODD:
394  res.bases_1d[1]->set(0) = SIN_ODD ;
395  break ;
396  default:
397  res_def = false ;
398  break ;
399  }
400  break ;
401  case COS_ODD:
402  switch ((*b.bases_1d[1])(0)) {
403  case COS_EVEN:
404  res.bases_1d[1]->set(0) = COS_ODD ;
405  break ;
406  case COS_ODD:
407  res.bases_1d[1]->set(0) = COS_EVEN ;
408  break ;
409  case SIN_EVEN:
410  res.bases_1d[1]->set(0) = SIN_ODD ;
411  break ;
412  case SIN_ODD:
413  res.bases_1d[1]->set(0) = SIN_EVEN ;
414  break ;
415  default:
416  res_def = false ;
417  break ;
418  }
419  break ;
420  case SIN_EVEN:
421  switch ((*b.bases_1d[1])(0)) {
422  case COS_EVEN:
423  res.bases_1d[1]->set(0) = SIN_EVEN ;
424  break ;
425  case COS_ODD:
426  res.bases_1d[1]->set(0) = SIN_ODD ;
427  break ;
428  case SIN_EVEN:
429  res.bases_1d[1]->set(0) = COS_EVEN ;
430  break ;
431  case SIN_ODD:
432  res.bases_1d[1]->set(0) = COS_ODD ;
433  break ;
434  default:
435  res_def = false ;
436  break ;
437  }
438  break ;
439  case SIN_ODD:
440  switch ((*b.bases_1d[1])(0)) {
441  case COS_EVEN:
442  res.bases_1d[1]->set(0) = SIN_ODD ;
443  break ;
444  case COS_ODD:
445  res.bases_1d[1]->set(0) = SIN_EVEN ;
446  break ;
447  case SIN_EVEN:
448  res.bases_1d[1]->set(0) = COS_ODD ;
449  break ;
450  case SIN_ODD:
451  res.bases_1d[1]->set(0) = COS_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 
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:
471  switch ((*b.bases_1d[0])(index_0)) {
472  case CHEB:
473  res.bases_1d[0]->set(index_0) = CHEB ;
474  break ;
475  default:
476  res_def = false ;
477  break ;
478  }
479  break ;
480  case LEG:
481  switch ((*b.bases_1d[0])(index_0)) {
482  case LEG:
483  res.bases_1d[0]->set(index_0) = LEG ;
484  break ;
485  default:
486  res_def = false ;
487  break ;
488  }
489  break ;
490  default:
491  res_def = false ;
492  break ;
493  }
494  }
495  while (index_0.inc()) ;
496  }
497 
498  if (!res_def)
499  for (int dim=0 ; dim<a.ndim ; dim++)
500  if (res.bases_1d[dim]!= 0x0) {
501  delete res.bases_1d[dim] ;
502  res.bases_1d[dim] = 0x0 ;
503  }
504  res.def = res_def ;
505  return res ;
506 }
507 
509  int res = -1 ;
510  if (strcmp(p,"R ")==0)
511  res = 0 ;
512  if (strcmp(p,"T ")==0)
513  res = 1 ;
514  return res ;
515 }}
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 shell and a symmetry with respect to the plane .
Definition: polar.hpp:408
Point center
Absolute coordinates of the center.
Definition: polar.hpp:412
virtual void save(FILE *) const
Saving function.
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
virtual void set_legendre_base(Base_spectral &) const
Gives the standard base for Legendre polynomials.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
virtual void set_legendre_base_with_m(Base_spectral &, int m) const
Gives the stnadard base using Legendre polynomials.
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.
virtual Val_domain der_normal(const Val_domain &, int) const
Normal derivative with respect to a given surface.
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 .
double alpha
Relates the numerical to the physical radii.
Definition: polar.hpp:411
virtual void do_absol() const
Computes the absolute coordinates.
virtual void set_anti_legendre_base(Base_spectral &) const
Gives the base using Legendre polynomials, for functions antisymetric with respect to .
virtual void do_cart() const
Computes the Cartesian coordinates.
virtual ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
virtual void do_coloc()
Computes the colocation points.
Domain_polar_compact(int num, int ttype, double r_int, const Point &cr, const Dim_array &nbr)
Standard constructor :
virtual const Point absol_to_num(const Point &) const
Computes the numerical coordinates from the physical ones.
virtual void do_cart_surr() const
Computes the Cartesian coordinates over the radius.
virtual double integ(const Val_domain &, int) const
Surface integral on a given boundary.
virtual int give_place_var(char *) const
Translates a name of a coordinate into its corresponding numerical name.
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 void set_cheb_base_with_m(Base_spectral &, int m) const
Gives the standard base using Chebyshev polynomials.
virtual void do_radius() const
Computes the generalized radius.
virtual Val_domain mult_xm1(const Val_domain &) const
Multiplication by .
virtual void set_cheb_base(Base_spectral &) const
Gives the standard base for Chebyshev polynomials.
virtual void set_anti_cheb_base(Base_spectral &) const
Gives the base using Chebyshev polynomials, for functions antisymetric with respect to .
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
Dim_array const & get_nbr_coefs() const
Returns the number of coefficients.
Definition: space.hpp:94
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
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
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
Base_spectral base
Spectral basis of the field.
Definition: val_domain.hpp:72
void set_in_conf()
Destroys the values in the coefficient space.
Definition: val_domain.cpp:197
Val_domain div_xm1() const
Division by .
Val_domain mult_sin_theta() const
Multiplication by .
Array< double > * cf
Pointer on the Array of the values in the coefficients space.
Definition: val_domain.hpp:77
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_cos_theta() const
Multiplication by .
Val_domain mult_xm1() const
Multiplication by .
void coef() const
Computes the coefficients.
Definition: val_domain.cpp:622
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