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