KADATH
domain_bispheric_rect.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 
23 #include "bispheric.hpp"
24 #include "array_math.hpp"
25 #include "param.hpp"
26 #include "val_domain.hpp"
27 namespace Kadath {
28 // standard constructor
29 Domain_bispheric_rect::Domain_bispheric_rect (int num, int ttype, double a, double rr, double etamin, double etapl, double chimin, const Dim_array& nbr) : Domain(num, ttype, nbr), aa(a), r_ext(rr), eta_minus(etamin), eta_plus(etapl), chi_min(chimin), p_eta(nullptr), p_chi(nullptr), p_phi(nullptr),
30 p_detadx(nullptr), p_detady(nullptr), p_detadz(nullptr), p_dchidx(nullptr), p_dchidy(nullptr), p_dchidz(nullptr), p_dphidy(nullptr), p_dphidz(nullptr), p_dsint(nullptr) {
31 
32  assert (nbr.get_ndim()==3) ;
33  do_coloc() ;
34 }
35 
36 // Copy constructor
38  eta_minus(so.eta_minus), eta_plus(so.eta_plus), chi_min(so.chi_min) {
39  p_eta = (so.p_eta!=nullptr) ? new Val_domain(*so.p_eta) : nullptr ;
40  p_chi = (so.p_chi!=nullptr) ? new Val_domain(*so.p_chi) : nullptr ;
41  p_phi = (so.p_phi!=nullptr) ? new Val_domain(*so.p_phi) : nullptr ;
42  p_detadx = (so.p_detadx!=nullptr) ? new Val_domain(*so.p_detadx) : nullptr ;
43  p_detady = (so.p_detady!=nullptr) ? new Val_domain(*so.p_detady) : nullptr ;
44  p_detadz = (so.p_detadz!=nullptr) ? new Val_domain(*so.p_detadz) : nullptr ;
45  p_dchidx = (so.p_dchidx!=nullptr) ? new Val_domain(*so.p_dchidx) : nullptr ;
46  p_dchidy = (so.p_dchidy!=nullptr) ? new Val_domain(*so.p_dchidy) : nullptr ;
47  p_dchidz = (so.p_dchidz!=nullptr) ? new Val_domain(*so.p_dchidz) : nullptr ;
48  p_dphidy = (so.p_dphidy!=nullptr) ? new Val_domain(*so.p_dphidy) : nullptr ;
49  p_dphidz = (so.p_dphidz!=nullptr) ? new Val_domain(*so.p_dphidz) : nullptr ;
50  p_dsint = (so.p_dsint!=nullptr) ? new Val_domain(*so.p_dsint) : nullptr ;
51 }
52 
53 Domain_bispheric_rect::Domain_bispheric_rect (int num, FILE* fd) : Domain(num, fd) {
54  fread_be (&aa, sizeof(double), 1, fd) ;
55  fread_be (&eta_minus, sizeof(double), 1, fd) ;
56  fread_be (&eta_plus, sizeof(double), 1, fd) ;
57  fread_be (&chi_min, sizeof(double), 1, fd) ;
58 
59  p_eta = nullptr ;
60  p_chi = nullptr ;
61  p_phi = nullptr ;
62  p_detadx = nullptr ;
63  p_detady = nullptr ;
64  p_detadz = nullptr ;
65  p_dchidx = nullptr ;
66  p_dchidy = nullptr ;
67  p_dchidz = nullptr ;
68  p_dphidy = nullptr ;
69  p_dphidz = nullptr ;
70  p_dsint = nullptr ;
71  do_coloc() ;
72 }
73 
74 // Destructor
75 Domain_bispheric_rect::~Domain_bispheric_rect() {
76  del_deriv() ;
77 }
78 
79 void Domain_bispheric_rect::save (FILE* fd) const {
80  nbr_points.save(fd) ;
81  nbr_coefs.save(fd) ;
82  fwrite_be (&ndim, sizeof(int), 1, fd) ;
83  fwrite_be (&type_base, sizeof(int), 1, fd) ;
84  fwrite_be (&aa, sizeof(double), 1, fd) ;
85  fwrite_be (&eta_minus, sizeof(double), 1, fd) ;
86  fwrite_be (&eta_plus, sizeof(double), 1, fd) ;
87  fwrite_be (&chi_min, sizeof(double), 1, fd) ;
88 }
89 
90 // Deletes the derived members
92  for (int l=0 ; l<ndim ; l++) {
93  safe_delete(coloc[l]);
94  safe_delete(cart[l]);
95  }
96  safe_delete(radius);
97  safe_delete(p_eta);
98  safe_delete(p_chi);
99  safe_delete(p_phi);
100  safe_delete(p_detadx);
101  safe_delete(p_detady);
102  safe_delete(p_detadz);
103  safe_delete(p_dchidx);
104  safe_delete(p_dchidy);
105  safe_delete(p_dchidz);
106  safe_delete(p_dphidy);
107  safe_delete(p_dphidz);
108  safe_delete(p_dsint);
109 }
110 
111 // Display
112 ostream& Domain_bispheric_rect::print (ostream& o) const {
113 
114  o << "Bispherical domain, rectangular part" << endl ;
115  o << "aa = " << aa << endl ;
116  o << eta_minus << " < eta < " << eta_plus << endl ;
117  o << chi_min << " < chi < pi " << endl ;
118  o << "Nbr pts = " << nbr_points << endl ;
119  o << endl ;
120  return o ;
121 }
122 
123 // Computes eta from eta star
125  for (int i=0 ; i<3 ; i++)
126  assert (coloc[i] != nullptr) ;
127  assert (p_eta==nullptr) ;
128  p_eta= new Val_domain(this) ;
129  p_eta->allocate_conf() ;
130  Index index (nbr_points) ;
131  do
132  p_eta->set(index) = (-eta_minus+eta_plus)/2.*((*coloc[0])(index(0))) + (eta_minus+eta_plus)/2. ;
133  while (index.inc()) ;
134 }
135 
136 // Computes chi from chi star
138  for (int i=0 ; i<3 ; i++)
139  assert (coloc[i] != nullptr) ;
140  assert (p_chi==nullptr) ;
141  p_chi= new Val_domain(this) ;
142  p_chi->allocate_conf() ;
143  Index index (nbr_points) ;
144  do
145  p_chi->set(index) = (chi_min-M_PI)*(*coloc[1])(index(1)) + M_PI ;
146  while (index.inc()) ;
147 }
148 
149 // Computes phi from phi star
151  for (int i=0 ; i<3 ; i++)
152  assert (coloc[i] != nullptr) ;
153  assert (p_phi==nullptr) ;
154  p_phi= new Val_domain(this) ;
155  p_phi->allocate_conf() ;
156  Index index (nbr_points) ;
157  do
158  p_phi->set(index) = ((*coloc[2])(index(2))) ;
159  while (index.inc()) ;
160 }
161 
163  if (p_chi==nullptr)
164  do_chi() ;
165  return *p_chi ;
166 }
167 
169  if (p_eta==nullptr)
170  do_eta() ;
171  return *p_eta ;
172 }
173 
175  for (int i=0 ; i<3 ; i++)
176  assert (coloc[i] != nullptr) ;
177  for (int i=0 ; i<3 ; i++)
178  assert (absol[i] == nullptr) ;
179  for (int i=0 ; i<3 ; i++) {
180  absol[i] = new Val_domain(this) ;
181  absol[i]->allocate_conf() ;
182  }
183 
184  if (p_eta==nullptr)
185  do_eta() ;
186  if (p_chi==nullptr)
187  do_chi() ;
188  if (p_phi==nullptr)
189  do_phi() ;
190 
191  Index index (nbr_points) ;
192  do {
193 
194  absol[0]->set(index) = aa*sinh((*p_eta)(index))/(cosh((*p_eta)(index))-cos((*p_chi)(index))) ;
195  absol[1]->set(index) =
196  aa*sin((*p_chi)(index))*cos((*p_phi)(index))/(cosh((*p_eta)(index))-cos((*p_chi)(index))) ;
197  absol[2]->set(index) =
198  aa*sin((*p_chi)(index))*sin((*p_phi)(index))/(cosh((*p_eta)(index))-cos((*p_chi)(index))) ;
199  }
200  while (index.inc()) ;
201 
202  // Basis
203  absol[0]->std_base() ;
204  absol[1]->std_base() ;
205  absol[2]->std_anti_base() ;
206 }
207 
208 
209 // Computes the generalized radius
211 
212  for (int i=0 ; i<3 ; i++)
213  assert (coloc[i] != nullptr) ;
214  assert (radius == nullptr) ;
215  radius = new Val_domain(sqrt (get_cart(1)*get_cart(1)+get_cart(2)*get_cart(2)+get_cart(3)*get_cart(3))) ;
216 }
217 
218 // Computes the Cartesian coordinates
220  for (int i=0 ; i<3 ; i++)
221  assert (coloc[i] != nullptr) ;
222  for (int i=0 ; i<3 ; i++)
223  assert (cart[i] == nullptr) ;
224  for (int i=0 ; i<3 ; i++) {
225  cart[i] = new Val_domain(this) ;
226  cart[i]->allocate_conf() ;
227  }
228 
229  if (p_eta==nullptr)
230  do_eta() ;
231  if (p_chi==nullptr)
232  do_chi() ;
233  if (p_phi==nullptr)
234  do_phi() ;
235 
236  Index index (nbr_points) ;
237  do {
238 
239  cart[0]->set(index) = aa*sinh((*p_eta)(index))/(cosh((*p_eta)(index))-cos((*p_chi)(index))) ;
240  cart[1]->set(index) =
241  aa*sin((*p_chi)(index))*cos((*p_phi)(index))/(cosh((*p_eta)(index))-cos((*p_chi)(index))) ;
242  cart[2]->set(index) =
243  aa*sin((*p_chi)(index))*sin((*p_phi)(index))/(cosh((*p_eta)(index))-cos((*p_chi)(index))) ;
244  }
245  while (index.inc()) ;
246 
247  // Basis
248  cart[0]->std_base() ;
249  cart[1]->std_base() ;
250  cart[2]->std_anti_base() ;
251 }
252 
253 
255  double rr = aa/sinh(fabs(eta_minus)) ;
256  double xc = aa*cosh(eta_minus)/sinh(eta_minus) ;
257 
258  Val_domain rho2 (get_cart(2)*get_cart(2)+get_cart(3)*get_cart(3)) ;
259  Val_domain xx (this) ;
260  xx = (xc<0) ? get_cart(1)-xc : xc-get_cart(1) ;
261 
262  assert (p_dsint==nullptr) ;
263  p_dsint = new Val_domain ((0.5*rho2.der_var(2)*xx - xx.der_var(2)*rho2)/rr) ;
264 }
265 
266 // Check if a point is inside ?
267 bool Domain_bispheric_rect::is_in (const Point& abs, double prec) const {
268  assert (abs.get_ndim()==3) ;
269 
270  double xx = abs(1) ;
271  double yy = abs(2) ;
272  double zz = abs(3) ;
273 
274  double air = sqrt (xx*xx+yy*yy+zz*zz) ;
275 
276  double chi ;
277  double rho = sqrt(yy*yy+zz*zz) ;
278 
279  double x_out = aa*cosh(eta_minus)/sinh(eta_minus) ;
280 
281  if (rho<prec)
282  chi = (fabs(xx)>fabs(x_out)) ? 0 : M_PI ;
283  else
284  chi = atan (2*aa*rho/(air*air-aa*aa)) ;
285 
286  if (chi<0)
287  chi += M_PI ;
288 
289  double eta = 0.5*log((1+(2*aa*xx)/(aa*aa+air*air))/(1-(2*aa*xx)/(aa*aa+air*air))) ;
290  double eta_num = 2./(eta_plus-eta_minus)*(eta-(eta_plus+eta_minus)/2.) ;
291 
292  bool res = true ;
293 
294  if (chi<chi_min-prec)
295  res = false ;
296  if (chi>M_PI+prec)
297  res = false ;
298 
299  if (eta_num<-1-prec)
300  res = false ;
301  if (eta_num>1+prec)
302  res = false ;
303 
304  return res ;
305 }
306 // Convert absolute coordinates to numerical ones
308 
309  assert (is_in(abs, 1e-12)) ;
310  Point num(3) ;
311 
312  double xx = abs(1) ;
313  double yy = abs(2) ;
314  double zz = abs(3) ;
315  double air = sqrt (xx*xx+yy*yy+zz*zz) ;
316 
317  num.set(3) = atan2 (zz, yy) ;
318 
319  if (num(3)<0)
320  num.set(3) += 2*M_PI ;
321 
322  double chi ;
323  double rho = sqrt(yy*yy+zz*zz) ;
324 
325  // On the axis ?
326  if (rho<PRECISION)
327  chi = M_PI ;
328  else
329  chi = atan (2*aa*rho/(air*air-aa*aa)) ;
330 
331  if (chi<0)
332  chi += M_PI ;
333 
334  double eta = 0.5*log((1+(2*aa*xx)/(aa*aa+air*air))/(1-(2*aa*xx)/(aa*aa+air*air))) ;
335 
336  num.set(1) = 2./(eta_plus-eta_minus)*(eta-(eta_plus+eta_minus)/2.) ;
337  num.set(2) = (chi-M_PI)/(chi_min-M_PI) ;
338 
339  return num ;
340 }
341 
342 const Point Domain_bispheric_rect::absol_to_num_bound(const Point& abs, int bound) const {
343 
344  assert (is_in(abs, 1e-3)) ;
345  Point num(3) ;
346 
347  double xx = abs(1) ;
348  double yy = abs(2) ;
349  double zz = abs(3) ;
350  double air = sqrt (xx*xx+yy*yy+zz*zz) ;
351 
352  num.set(3) = atan2 (zz, yy) ;
353 
354  if (num(3)<0)
355  num.set(3) += 2*M_PI ;
356 
357  double chi ;
358  double rho = sqrt(yy*yy+zz*zz) ;
359 
360  // On the axis ?
361  if (rho<PRECISION)
362  chi = M_PI ;
363  else
364  chi = atan (2*aa*rho/(air*air-aa*aa)) ;
365 
366  if (chi<0)
367  chi += M_PI ;
368 
369  double eta = 0.5*log((1+(2*aa*xx)/(aa*aa+air*air))/(1-(2*aa*xx)/(aa*aa+air*air))) ;
370 
371  num.set(1) = 2./(eta_plus-eta_minus)*(eta-(eta_plus+eta_minus)/2.) ;
372  num.set(2) = (chi-M_PI)/(chi_min-M_PI) ;
373 
374  switch (bound) {
375  case INNER_BC :
376  num.set(1) = -1 ;
377  break ;
378  case ETA_PLUS_BC :
379  num.set(1) = 1 ;
380  break ;
381  case CHI_ONE_BC :
382  num.set(2) = 1 ;
383  break ;
384  case OUTER_BC :
385  num.set(1) = 1 ;
386  num.set(2) = 1 ;
387  break ;
388  default :
389  cerr << "Unknown case in Domain_bispheric_rect::absol_to_num_bound" << endl ;
390  abort() ;
391  }
392  return num ;
393 }
394 
395 double coloc_leg(int,int) ;
396 double coloc_leg_parity(int,int) ;
398 
399  switch (type_base) {
400  case CHEB_TYPE:
402  del_deriv() ;
403  for (int i=0 ; i<ndim ; i++)
404  coloc[i] = new Array<double> (nbr_points(i)) ;
405  for (int i=0 ; i<nbr_points(0) ; i++)
406  coloc[0]->set(i) = -cos(M_PI*i/(nbr_points(0)-1)) ;
407  for (int j=0 ; j<nbr_points(1) ; j++)
408  coloc[1]->set(j) = sin(M_PI*j/2./(nbr_points(1)-1)) ;
409  for (int k=0 ; k<nbr_points(2) ; k++)
410  coloc[2]->set(k) = M_PI*k/(nbr_points(2)-1) ;
411  do_eta() ;
412  do_chi() ;
413  do_phi() ;
414  break ;
415  case LEG_TYPE:
417  del_deriv() ;
418  for (int i=0 ; i<ndim ; i++)
419  coloc[i] = new Array<double> (nbr_points(i)) ;
420  for (int i=0 ; i<nbr_points(0) ; i++)
421  coloc[0]->set(i) = coloc_leg(i,nbr_points(0)) ;
422  for (int j=0 ; j<nbr_points(1) ; j++)
423  coloc[1]->set(j) = coloc_leg_parity(j,nbr_points(1)) ;
424  for (int k=0 ; k<nbr_points(2) ; k++)
425  coloc[2]->set(k) = M_PI*k/(nbr_points(2)-1) ;
426  do_eta() ;
427  do_chi() ;
428  do_phi() ;
429  break ;
430  default :
431  cerr << "Unknown type of basis in Domain_bispheric_rect::do_coloc" << endl ;
432  abort() ;
433  }
434 }
435 
436 // Standard base fo Chebyshev
438 
439  assert (type_base == CHEB_TYPE) ;
440  base.allocate(nbr_coefs) ;
441 
442  Index index(base.bases_1d[0]->get_dimensions()) ;
443 
444  base.def=true ;
445  base.bases_1d[2]->set(0) = COS ;
446  for (int k=0 ; k<nbr_coefs(2) ; k++) {
447  base.bases_1d[1]->set(k) = (k%2==0) ? CHEB_EVEN : CHEB_ODD ;
448  for (int j=0 ; j<nbr_coefs(1) ; j++) {
449  index.set(0) = j ; index.set(1) = k ;
450  base.bases_1d[0]->set(index) = CHEB ;
451  }
452  }
453 }
454 
455 // Antisymetric base for Chebyshev
457 
458  assert (type_base == CHEB_TYPE) ;
459  base.allocate(nbr_coefs) ;
460 
461  Index index(base.bases_1d[0]->get_dimensions()) ;
462 
463  base.def=true ;
464  base.bases_1d[2]->set(0) = SIN ;
465  for (int k=0 ; k<nbr_coefs(2) ; k++) {
466  base.bases_1d[1]->set(k) = (k%2==0) ? CHEB_EVEN : CHEB_ODD ;
467  for (int j=0 ; j<nbr_coefs(1) ; j++) {
468  index.set(0) = j ; index.set(1) = k ;
469  base.bases_1d[0]->set(index) = CHEB ;
470  }
471  }
472 }
473 
474 double coloc_leg(int,int) ;
475 double coloc_leg_parity(int,int) ;
476 // Standard base for Legendre
478 
479  assert (type_base == LEG_TYPE) ;
480  base.allocate(nbr_coefs) ;
481 
482  Index index(base.bases_1d[0]->get_dimensions()) ;
483 
484  base.def=true ;
485  base.bases_1d[2]->set(0) = COS ;
486  for (int k=0 ; k<nbr_coefs(2) ; k++) {
487  base.bases_1d[1]->set(k) = (k%2==0) ? LEG_EVEN : LEG_ODD ;
488  for (int j=0 ; j<nbr_coefs(1) ; j++) {
489  index.set(0) = j ; index.set(1) = k ;
490  base.bases_1d[0]->set(index) = LEG ;
491  }
492  }
493 }
494 
495 // Antisymetric base for Legendre
497 
498  assert (type_base == LEG_TYPE) ;
499  base.allocate(nbr_coefs) ;
500 
501  Index index(base.bases_1d[0]->get_dimensions()) ;
502 
503  base.def=true ;
504  base.bases_1d[2]->set(0) = SIN ;
505  for (int k=0 ; k<nbr_coefs(2) ; k++) {
506  base.bases_1d[1]->set(k) = (k%2==0) ? LEG_EVEN : LEG_ODD ;
507  for (int j=0 ; j<nbr_coefs(1) ; j++) {
508  index.set(0) = j ; index.set(1) = k ;
509  base.bases_1d[0]->set(index) = LEG ;
510  }
511  }
512 }
513 
514 // Computes the partial derivatives of the numerical coordinates with respect to the Cartesian ones.
516 
517  if (cart[0]==nullptr)
518  do_cart() ;
519  if (radius==nullptr)
520  do_radius() ;
521 
522  // Partial derivatives of eta
523  Val_domain denom_eta
524  ((eta_plus-eta_minus)/2.*((aa*aa+(*radius)*(*radius))*((aa*aa+(*radius)*(*radius))) -
525  4.*aa*aa*(*cart[0])*(*cart[0]))) ;
526  p_detadx = new Val_domain ((2.*aa*(aa*aa+(*radius)*(*radius)-2.*(*cart[0])*(*cart[0])))/denom_eta) ;
527  p_detady = new Val_domain (-4.*aa*(*cart[0])*(*cart[1])/denom_eta) ;
528  p_detadz = new Val_domain (-4.*aa*(*cart[0])*(*cart[2])/denom_eta) ;
529 
530  // Partial derivatives of chi
531  Val_domain rho (sqrt((*cart[1])*(*cart[1])+(*cart[2])*(*cart[2]))) ;
532  Val_domain denom_chi ((chi_min-M_PI)*(((*radius)*(*radius)-aa*aa)*((*radius)*(*radius)-aa*aa) +
533  4.*aa*aa*rho*rho)) ;
534  p_dchidx = new Val_domain (-4.*aa*(*cart[0])*rho/denom_chi) ;
535  Val_domain chiyz (2.*aa*((*radius)*(*radius)-aa*aa-2*rho*rho)/denom_chi) ;
536 
537  // Partial derivatives of phi :
538  Val_domain phiyz (((exp(*p_eta)+exp(-*p_eta))/2.-cos(*p_chi))/aa) ;
539 
540  // The basis :
541  p_detadx->std_base() ;
542  p_detady->std_base() ;
545  chiyz.std_base() ;
546  phiyz.std_base() ;
547 
548  p_dchidy = new Val_domain (chiyz.mult_cos_phi()) ;
549  p_dchidz = new Val_domain (chiyz.mult_sin_phi()) ;
550  p_dphidy = new Val_domain (-phiyz.mult_sin_phi()) ;
551  p_dphidz = new Val_domain (phiyz.mult_cos_phi()) ;
552 }
553 
554 // Computes the derivatives with respect to the absolute coordinates with respect to the numerical ones.
555 void Domain_bispheric_rect::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
556  if (p_detadx==nullptr)
557  do_for_der() ;
558 
559  // d/dx :
560  der_abs[0] = new Val_domain((*der_var[0])*(*p_detadx) + (*der_var[1])*(*p_dchidx)) ;
561 
562  // d/dy :
563  Val_domain auchi_y ((*der_var[2])*(*p_dphidy)) ;
564  Val_domain part_y_phi (auchi_y.div_sin_chi()) ;
565  der_abs[1] = new Val_domain((*der_var[0])*(*p_detady) + (*der_var[1])*(*p_dchidy) + part_y_phi) ;
566 
567  // d/dz :
568  Val_domain auchi_z ((*der_var[2])*(*p_dphidz)) ;
569  Val_domain part_z_phi (auchi_z.div_sin_chi()) ;
570  der_abs[2] = new Val_domain((*der_var[0])*(*p_detadz) + (*der_var[1])*(*p_dchidz) + part_z_phi) ;
571 }
572 
573 // Multplication rules for the basis.
575 
576  assert (a.ndim==3) ;
577  assert (b.ndim==3) ;
578 
579  Base_spectral res(3) ;
580  bool res_def = true ;
581 
582  if (!a.def)
583  res_def=false ;
584  if (!b.def)
585  res_def=false ;
586 
587  if (res_def) {
588  // Base in phi :
589  res.bases_1d[2] = new Array<int> (a.bases_1d[2]->get_dimensions()) ;
590  switch ((*a.bases_1d[2])(0)) {
591  case COS:
592  switch ((*b.bases_1d[2])(0)) {
593  case COS:
594  res.bases_1d[2]->set(0) = COS ;
595  break ;
596  case SIN:
597  res.bases_1d[2]->set(0) = SIN ;
598  break ;
599  default:
600  res_def = false ;
601  break ;
602  }
603  break ;
604  case SIN:
605  switch ((*b.bases_1d[2])(0)) {
606  case COS:
607  res.bases_1d[2]->set(0) = SIN ;
608  break ;
609  case SIN:
610  res.bases_1d[2]->set(0) = COS ;
611  break ;
612  default:
613  res_def = false ;
614  break ;
615  }
616  break ;
617  default:
618  res_def = false ;
619  break ;
620  }
621 
622  // Bases in chi :
623  // On check l'alternance :
624  Index index_1 (a.bases_1d[1]->get_dimensions()) ;
625  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
626  do {
627  switch ((*a.bases_1d[1])(index_1)) {
628  case CHEB_EVEN:
629  switch ((*b.bases_1d[1])(index_1)) {
630  case CHEB_EVEN:
631  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? CHEB_EVEN : CHEB_ODD ;
632  break ;
633  case CHEB_ODD:
634  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? CHEB_ODD : CHEB_EVEN ;
635  break ;
636  default:
637  res_def = false ;
638  break ;
639  }
640  break ;
641  case CHEB_ODD:
642  switch ((*b.bases_1d[1])(index_1)) {
643  case CHEB_EVEN:
644  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? CHEB_ODD : CHEB_EVEN ;
645  break ;
646  case CHEB_ODD:
647  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? CHEB_EVEN : CHEB_ODD ;
648  break ;
649  default:
650  res_def = false ;
651  break ;
652  }
653  break ;
654  case LEG_EVEN:
655  switch ((*b.bases_1d[1])(index_1)) {
656  case LEG_EVEN:
657  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? LEG_EVEN : LEG_ODD ;
658  break ;
659  case LEG_ODD:
660  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? LEG_ODD : LEG_EVEN ;
661  break ;
662  default:
663  res_def = false ;
664  break ;
665  }
666  break ;
667  case LEG_ODD:
668  switch ((*b.bases_1d[1])(index_1)) {
669  case LEG_EVEN:
670  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? LEG_ODD : LEG_EVEN ;
671  break ;
672  case LEG_ODD:
673  res.bases_1d[1]->set(index_1) = (index_1(0)%2==0) ? LEG_EVEN : LEG_ODD ;
674  break ;
675  default:
676  res_def = false ;
677  break ;
678  }
679  break ;
680  default:
681  res_def = false ;
682  break ;
683  }
684  }
685  while (index_1.inc()) ;
686 
687  // Base in eta :
688  Index index_0 (a.bases_1d[0]->get_dimensions()) ;
689  res.bases_1d[0] = new Array<int> (a.bases_1d[0]->get_dimensions()) ;
690  do {
691  switch ((*a.bases_1d[0])(index_0)) {
692  case CHEB:
693  switch ((*b.bases_1d[0])(index_0)) {
694  case CHEB:
695  res.bases_1d[0]->set(index_0) = CHEB ;
696  break ;
697  default:
698  res_def = false ;
699  break ;
700  }
701  break ;
702  case LEG:
703  switch ((*b.bases_1d[0])(index_0)) {
704  case LEG:
705  res.bases_1d[0]->set(index_0) = LEG ;
706  break ;
707  default:
708  res_def = false ;
709  break ;
710  }
711  break ;
712  default:
713  res_def = false ;
714  break ;
715  }
716  }
717  while (index_0.inc()) ;
718  }
719 
720  if (!res_def)
721  for (int dim=0 ; dim<a.ndim ; dim++)
722  if (res.bases_1d[dim]!= nullptr) {
723  delete res.bases_1d[dim] ;
724  res.bases_1d[dim] = nullptr ;
725  }
726  res.def = res_def ;
727  return res ;
728 }
729 
730 
732 
733  double rr, xc ;
734  switch (bound) {
735  case INNER_BC :
736  xc = aa*cosh(eta_minus)/sinh(eta_minus) ;
737  rr = aa/sinh(fabs(eta_minus)) ;
738 
739  return Val_domain(so.der_abs(1)*(get_cart(1)-xc)/rr + so.der_abs(2)*get_cart(2)/rr +
740  so.der_abs(3)*get_cart(3)/rr) ;
741  case OUTER_BC :
742  return Val_domain(so.der_abs(1)*get_cart(1)/r_ext + so.der_abs(2)*get_cart(2)/r_ext +
743  so.der_abs(3)*get_cart(3)/r_ext) ;
744  case CHI_ONE_BC :
745  return Val_domain (so.der_var(2)/ (chi_min-M_PI)) ;
746  case ETA_PLUS_BC :
747  return Val_domain (so.der_var(1)/(eta_plus-eta_minus)*2.) ;
748  default:
749  cerr << "Unknown boundary case in Domain_bispheric_rect::der_normal" << endl ;
750  abort() ;
751  }
752 }
753 
754 double Domain_bispheric_rect::integ (const Val_domain& so, int bound) const {
755 
756  if (bound !=INNER_BC) {
757  cerr << "Domain_bispheric_rect::integ only defined for inner boundary yet" << endl ;
758  abort() ;
759  }
760 
761  double res = 0 ;
762 
763  int basep = (*so.base.bases_1d[2]) (0) ;
764  if (basep == SIN) {
765  // Odd function
766  return res ;
767  }
768  else {
769 
770  // Multiply by the surface element :
771  if (p_dsint==nullptr)
772  do_dsint() ;
773 
774  Val_domain auxi (so*(*p_dsint)) ;
775  auxi.coef() ;
776 
777  Index pos (get_nbr_coefs()) ;
778  pos.set(2) = 0 ;
779 
780  if (type_base==CHEB_TYPE) {
781  for (int j=0 ; j<nbr_coefs(1) ; j++) {
782  pos.set(1) = j ;
783  int base_chi = (*auxi.base.bases_1d[1]) (0) ;
784  double val_cheb ;
785  switch (base_chi) {
786  case CHEB_EVEN :
787  if (j==0)
788  val_cheb = 1. ;
789  else
790  val_cheb = double(2*j)/double(4*j*j-1) -1./double(2*j-1) ;
791  break ;
792  case CHEB_ODD :
793  if (j==0)
794  val_cheb = 1./2. ;
795  else
796  if (j%2==0)
797  val_cheb = 2*double(2*j+1)/double((2*j+1)*(2*j+1)-1) - 1./double(2*j) ;
798  else
799  val_cheb = -1./double(2*j) ;
800  break ;
801  default:
802  cerr << "Unknown basis in Domain_bispheric_rect::integ" << endl ;
803  abort() ;
804  }
805  for (int i=0 ; i<nbr_coefs(0) ; i++) {
806  pos.set(0) = i ;
807  if (i%2==0)
808  res += val_cheb * (*auxi.cf)(pos) ;
809  else
810  res -= val_cheb * (*auxi.cf)(pos) ;
811  }
812  }
813  }
814 
815  if (type_base==LEG_TYPE) {
816  int base_chi = (*auxi.base.bases_1d[1]) (0) ;
817 
818  double val_leg = 1. ;
819  double val_m1 = 1. ;
820  double val_m = -0.5 ;
821 
822  for (int j=0 ; j<nbr_coefs(1) ; j++) {
823  pos.set(1) = j ;
824 
825  switch (base_chi) {
826  case LEG_EVEN :
827  val_leg = 0. ;
828  break ;
829  case LEG_ODD :
830  val_leg = (val_m1 - val_m)/double(4*j+3) ;
831  val_m *= -double(2*j+3)/double(2*j+4) ;
832  val_m1 *= -double(2*j+1)/double(2*j+2) ;
833  break ;
834  default:
835  cerr << "Unknown basis in Domain_bispheric_rect::integ" << endl ;
836  abort() ;
837  }
838 
839  for (int i=0 ; i<nbr_coefs(0) ; i++) {
840  pos.set(0) = i ;
841  if (i%2==0)
842  res += val_leg*(*auxi.cf)(pos) ;
843  else
844  res -= val_leg*(*auxi.cf)(pos) ;
845  }
846  }
847  }
848  return res*M_PI*2 ;
849  }
850 }
851 
853  int res = -1 ;
854  if (strcmp(p,"ETA ")==0)
855  res = 0 ;
856  if (strcmp(p,"CHI ")==0)
857  res = 1 ;
858  if (strcmp(p,"P ")==0)
859  res = 2 ;
860  return res ;
861 }}
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 bispherical coordinates with a symmetry with respect to the plane .
Definition: bispheric.hpp:64
virtual void set_anti_cheb_base(Base_spectral &so) const
Sets the base to the standard one for Chebyshev polynomials and an astisymetric function with respect...
Val_domain * p_dsint
Pointer on a Val_domain containing the surface element on the inner boundary of the domain (being sph...
Definition: bispheric.hpp:161
Val_domain * p_dchidy
Pointer on a Val_domain containing The explicit expression are : .
Definition: bispheric.hpp:132
Val_domain * p_eta
Pointer on a Val_domain containing .
Definition: bispheric.hpp:73
void del_deriv() override
Destroys the derivated members (like coloc, cart and radius), when changing the type of colocation po...
double eta_plus
associated with .
Definition: bispheric.hpp:70
Val_domain * p_detadz
Pointer on a Val_domain containing The explicit expression are : .
Definition: bispheric.hpp:110
virtual void do_cart() const
Computes the Cartesian coordinates.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
Val_domain * p_detady
Pointer on a Val_domain containing The explicit expression are : .
Definition: bispheric.hpp:99
virtual void do_absol() const
Computes the absolute coordinates.
virtual const Val_domain & get_eta() const
Returns the variable .
double eta_minus
associated with .
Definition: bispheric.hpp:69
virtual Val_domain der_normal(const Val_domain &, int) const
Normal derivative with respect to a given surface.
virtual void do_radius() const
Computes the generalized radius.
void do_for_der() const
Computes the partial derivatives of the numerical coordinates with respect to the Cartesian ones like...
double aa
Distance scale .
Definition: bispheric.hpp:67
void do_chi() const
Computes in *p_chi.
Val_domain * p_dphidz
Pointer on a Val_domain containing The explicit expression is : .
Definition: bispheric.hpp:157
Val_domain * p_chi
Pointer on a Val_domain containing .
Definition: bispheric.hpp:74
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 ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
Val_domain * p_dphidy
Pointer on a Val_domain containing The explicit expression is : .
Definition: bispheric.hpp:150
virtual const Val_domain & get_chi() const
Returns the variable .
virtual const Point absol_to_num(const Point &xxx) const
Computes the numerical coordinates from the physical ones.
Val_domain * p_dchidx
Pointer on a Val_domain containing The explicit expression are : .
Definition: bispheric.hpp:121
void do_dsint() const
Computes the surface element and stores it in *p_dsint.
virtual void set_legendre_base(Base_spectral &so) const
Sets the base to the standard one for Legendre polynomials.
Val_domain * p_dchidz
Pointer on a Val_domain containing The explicit expression are : .
Definition: bispheric.hpp:143
virtual const Point absol_to_num_bound(const Point &, int) const
Computes the numerical coordinates from the physical ones for a point lying on a boundary.
Val_domain * p_detadx
Pointer on a Val_domain containing The explicit expression are : .
Definition: bispheric.hpp:88
double chi_min
Lower bound for .
Definition: bispheric.hpp:71
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...
double r_ext
Radius of the outer boundary.
Definition: bispheric.hpp:68
virtual void set_cheb_base(Base_spectral &so) const
Sets the base to the standard one for Chebyshev polynomials.
virtual double integ(const Val_domain &, int) const
Surface integral on a given boundary.
virtual void save(FILE *fd) const
Saving function.
void do_phi() const
Computes in *p_phi
virtual void set_anti_legendre_base(Base_spectral &so) const
Sets the base to the standard one for Legendre polynomials and an astisymetric function with respect ...
virtual void do_coloc()
Computes the colocation points.
Domain_bispheric_rect(int nd, int ttype, double aa, double rext, double eta_minus, double eta_plus, double chi_min, const Dim_array &nbr)
Standard constructor :
void do_eta() const
Computes in *p_eta.
Val_domain * p_phi
Pointer on a Val_domain containing .
Definition: bispheric.hpp:75
Abstract class that implements the fonctionnalities common to all the type of domains.
Definition: space.hpp:60
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
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
Val_domain const & get_cart(int i) const
Returns a Cartesian coordinates.
Definition: space.hpp:1471
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
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
Val_domain mult_sin_phi() const
Multiplication by .
Base_spectral base
Spectral basis of the field.
Definition: val_domain.hpp:72
Val_domain mult_cos_phi() const
Multiplication by .
Array< double > * cf
Pointer on the Array of the values in the coefficients space.
Definition: val_domain.hpp:77
double & set(const Index &pos)
Read/write the value of the field in the configuration space.
Definition: val_domain.cpp:171
void std_base()
Sets the standard basis of decomposition.
Definition: val_domain.cpp:246
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 std_anti_base()
Sets the standard, anti-symetric, basis of decomposition.
Definition: val_domain.cpp:279
Val_domain der_abs(int i) const
Computes the derivative with respect to an absolute coordinate (typically Cartesian).
Definition: val_domain.cpp:681
void allocate_conf()
Allocates the values in the configuration space and destroys the values in the coefficients space.
Definition: val_domain.cpp:209
Val_domain div_sin_chi() const
Division by .
const Base_spectral & get_base() const
Returns the basis of decomposition.
Definition: val_domain.hpp:122