KADATH
domain_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 
22 #include "utilities.hpp"
23 #include "spheric.hpp"
24 #include "point.hpp"
25 #include "val_domain.hpp"
26 
27 namespace Kadath {
28 void coef_1d (int, Array<double>&) ;
29 void coef_i_1d (int, Array<double>&) ;
30 int der_1d (int, Array<double>&) ;
31 
32 // Standard constructor
33 Domain_nucleus::Domain_nucleus (int num, int ttype, double r, const Point& cr, const Dim_array& nbr) :
34  Domain(num, ttype, nbr), alpha(r),center(cr) {
35  assert (nbr.get_ndim()==3) ;
36  assert (cr.get_ndim()==3) ;
37  do_coloc() ;
38 }
39 
40 // Constructor by copy
41 Domain_nucleus::Domain_nucleus (const Domain_nucleus& so) : Domain(so), alpha(so.alpha), center(so.center) {
42 }
43 
44 Domain_nucleus::Domain_nucleus (int num, FILE* fd) : Domain(num, fd), center(fd) {
45  fread_be (&alpha, sizeof(double), 1, fd) ;
46  do_coloc() ;
47 }
48 
49 // Destructor
50 Domain_nucleus::~Domain_nucleus() {}
51 
52 void Domain_nucleus::save (FILE* fd) const {
53  nbr_points.save(fd) ;
54  nbr_coefs.save(fd) ;
55  fwrite_be (&ndim, sizeof(int), 1, fd) ;
56  fwrite_be (&type_base, sizeof(int), 1, fd) ;
57  center.save(fd) ;
58  fwrite_be (&alpha, sizeof(double), 1, fd) ;
59 }
60 
61 ostream& Domain_nucleus::print (ostream& o) const {
62  o << "Nucleus" << endl ;
63  o << "Rmax = " << alpha << endl ;
64  o << "Center = " << center << endl ;
65  o << "Nbr pts = " << nbr_points << endl ;
66  o << endl ;
67  return o ;
68 }
69 
70 
71 Val_domain Domain_nucleus::der_normal (const Val_domain& so, int bound) const {
72 
73  Val_domain res (so.der_var(1)) ;
74  switch (bound) {
75  case OUTER_BC :
76  res /= alpha ;
77  break ;
78  default:
79  cerr << "Unknown boundary case in Domain_nucleus::der_normal" << endl ;
80  abort() ;
81  }
82 return res ;
83 }
84 
85 // Computes the cartesian coordinates
86 void Domain_nucleus::do_absol () const {
87  for (int i=0 ; i<3 ; i++)
88  assert (coloc[i] != 0x0) ;
89  for (int i=0 ; i<3 ; i++)
90  assert (absol[i] == 0x0) ;
91  for (int i=0 ; i<3 ; i++) {
92  absol[i] = new Val_domain(this) ;
93  absol[i]->allocate_conf() ;
94  }
95  Index index (nbr_points) ;
96  do {
97  absol[0]->set(index) = alpha* ((*coloc[0])(index(0))) *
98  sin((*coloc[1])(index(1)))*cos((*coloc[2])(index(2))) + center(1);
99  absol[1]->set(index) = alpha* ((*coloc[0])(index(0))) *
100  sin((*coloc[1])(index(1)))*sin((*coloc[2])(index(2))) + center(2) ;
101  absol[2]->set(index) = alpha* ((*coloc[0])(index(0))) * cos((*coloc[1])(index(1))) + center(3) ;
102  }
103  while (index.inc()) ;
104 
105 }
106 
107 // Computes the radius
109 
110  for (int i=0 ; i<3 ; i++)
111  assert (coloc[i] != 0x0) ;
112  assert (radius == 0x0) ;
113  radius = new Val_domain(this) ;
114  radius->allocate_conf() ;
115  Index index (nbr_points) ;
116  do
117  radius->set(index) = alpha* ((*coloc[0])(index(0))) ;
118  while (index.inc()) ;
119 }
120 
121 // Computes the cartesian coordinates
122 void Domain_nucleus::do_cart () const {
123  for (int i=0 ; i<3 ; i++)
124  assert (coloc[i] != 0x0) ;
125  for (int i=0 ; i<3 ; i++)
126  assert (cart[i] == 0x0) ;
127  for (int i=0 ; i<3 ; i++) {
128  cart[i] = new Val_domain(this) ;
129  cart[i]->allocate_conf() ;
130  }
131  Index index (nbr_points) ;
132  do {
133  cart[0]->set(index) = alpha* ((*coloc[0])(index(0))) *
134  sin((*coloc[1])(index(1)))*cos((*coloc[2])(index(2))) + center(1);
135  cart[1]->set(index) = alpha* ((*coloc[0])(index(0))) *
136  sin((*coloc[1])(index(1)))*sin((*coloc[2])(index(2))) + center(2) ;
137  cart[2]->set(index) = alpha* ((*coloc[0])(index(0))) * cos((*coloc[1])(index(1))) + center(3) ;
138  }
139  while (index.inc()) ;
140 
141 }
142 // Computes the cartesian coordinates over the radius
144  for (int i=0 ; i<3 ; i++)
145  assert (coloc[i] != 0x0) ;
146  for (int i=0 ; i<3 ; i++)
147  assert (cart_surr[i] == 0x0) ;
148  for (int i=0 ; i<3 ; i++) {
149  cart_surr[i] = new Val_domain(this) ;
150  cart_surr[i]->allocate_conf() ;
151  }
152  Index index (nbr_points) ;
153  do {
154  cart_surr[0]->set(index) = sin((*coloc[1])(index(1)))*cos((*coloc[2])(index(2))) ;
155  cart_surr[1]->set(index) = sin((*coloc[1])(index(1)))*sin((*coloc[2])(index(2))) ;
156  cart_surr[2]->set(index) = cos((*coloc[1])(index(1))) ;
157  }
158  while (index.inc()) ;
159 
160 }
161 // Is a point inside this domain ?
162 bool Domain_nucleus::is_in (const Point& xx, double prec) const {
163 
164  assert (xx.get_ndim()==3) ;
165 
166  double x_loc = xx(1) - center(1) ;
167  double y_loc = xx(2) - center(2) ;
168  double z_loc = xx(3) - center(3) ;
169  double air_loc = sqrt (x_loc*x_loc + y_loc*y_loc + z_loc*z_loc) ;
170 
171  bool res = (air_loc/alpha -1 <= prec) ? true : false ;
172  return res ;
173 }
174 
175 
176 // Convert absolute coordinates to numerical ones
177 const Point Domain_nucleus::absol_to_num(const Point& abs) const {
178 
179  assert (is_in(abs)) ;
180  Point num(3) ;
181 
182  double x_loc = abs(1) - center(1) ;
183  double y_loc = abs(2) - center(2) ;
184  double z_loc = abs(3) - center(3) ;
185  double air = sqrt(x_loc*x_loc+y_loc*y_loc+z_loc*z_loc) ;
186  num.set(1) = air/alpha ;
187  double rho = sqrt(x_loc*x_loc+y_loc*y_loc) ;
188 
189  if (rho==0) {
190  // Sur l'axe
191  num.set(2) = (z_loc>=0) ? 0 : M_PI ;
192  num.set(3) = 0 ;
193  }
194  else {
195  num.set(2) = atan(rho/z_loc) ;
196  num.set(3) = atan2 (y_loc, x_loc) ;
197  }
198 
199  if (num(2) <0)
200  num.set(2) = M_PI + num(2) ;
201 
202  return num ;
203 }
204 
205 
206 // Convert absolute coordinates to numerical ones
207 const Point Domain_nucleus::absol_to_num_bound(const Point& abs, int bound) const {
208 
209  assert (bound==OUTER_BC) ;
210  assert (is_in(abs, 1e-3)) ;
211  Point num(3) ;
212 
213  double x_loc = abs(1) - center(1) ;
214  double y_loc = abs(2) - center(2) ;
215  double z_loc = abs(3) - center(3) ;
216  num.set(1) = 1 ;
217  double rho = sqrt(x_loc*x_loc+y_loc*y_loc) ;
218 
219  if (rho==0) {
220  // Sur l'axe
221  num.set(2) = (z_loc>=0) ? 0 : M_PI ;
222  num.set(3) = 0 ;
223  }
224  else {
225  num.set(2) = atan(rho/z_loc) ;
226  num.set(3) = atan2 (y_loc, x_loc) ;
227  }
228 
229  if (num(2) <0)
230  num.set(2) = M_PI + num(2) ;
231 
232  return num ;
233 }
234 
235 double coloc_leg_parity(int, int) ;
237 
238  switch (type_base) {
239  case CHEB_TYPE:
241  nbr_coefs.set(2) += 2 ;
242  del_deriv() ;
243  for (int i=0 ; i<ndim ; i++)
244  coloc[i] = new Array<double> (nbr_points(i)) ;
245  for (int i=0 ; i<nbr_points(0) ; i++)
246  coloc[0]->set(i) = sin(M_PI/2.*i/(nbr_points(0)-1)) ;
247  for (int j=0 ; j<nbr_points(1) ; j++)
248  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
249  for (int k=0 ; k<nbr_points(2) ; k++)
250  coloc[2]->set(k) = M_PI*2.*k/nbr_points(2) ;
251  break ;
252  case LEG_TYPE:
254  nbr_coefs.set(2) += 2 ;
255  del_deriv() ;
256  for (int i=0 ; i<ndim ; i++)
257  coloc[i] = new Array<double> (nbr_points(i)) ;
258  for (int i=0 ; i<nbr_points(0) ; i++)
259  coloc[0]->set(i) = coloc_leg_parity(i, nbr_points(0)) ;
260  for (int j=0 ; j<nbr_points(1) ; j++)
261  coloc[1]->set(j) = M_PI/2.*j/(nbr_points(1)-1) ;
262  for (int k=0 ; k<nbr_points(2) ; k++)
263  coloc[2]->set(k) = M_PI*2.*k/nbr_points(2) ;
264  break ;
265  default :
266  cerr << "Unknown type of basis in Domain_nucleus::do_coloc" << endl ;
267  abort() ;
268  }
269 }
270 
271 // Base for a function symetric in z, using Chebyshev
273 
274  int m,l ;
275 
276  assert (type_base == CHEB_TYPE) ;
277  base.allocate(nbr_coefs) ;
278 
279  Index index(base.bases_1d[0]->get_dimensions()) ;
280 
281  base.def=true ;
282  base.bases_1d[2]->set(0) = COSSIN ;
283  for (int k=0 ; k<nbr_coefs(2) ; k++) {
284  m = (k%2==0) ? k/2 : (k-1)/2 ;
285  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
286  for (int j=0 ; j<nbr_coefs(1) ; j++) {
287  l = (m%2==0) ? 2*j : 2*j+1 ;
288  index.set(0) = j ; index.set(1) = k ;
289  base.bases_1d[0]->set(index) = (l%2==0) ? CHEB_EVEN : CHEB_ODD ;
290  }
291  }
292 }
293 
294 // Base for a function symetric in z, using Chebyshev
296 
297  int m,l ;
298 
299  assert (type_base == CHEB_TYPE) ;
300  base.allocate(nbr_coefs) ;
301 
302  Index index(base.bases_1d[0]->get_dimensions()) ;
303 
304  if (mquant%2==0) {
305  base.def=true ;
306  base.bases_1d[2]->set(0) = COSSIN ;
307  for (int k=0 ; k<nbr_coefs(2) ; k++) {
308  m = (k%2==0) ? k/2 : (k-1)/2 ;
309  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
310  for (int j=0 ; j<nbr_coefs(1) ; j++) {
311  l = (m%2==0) ? 2*j : 2*j+1 ;
312  index.set(0) = j ; index.set(1) = k ;
313  base.bases_1d[0]->set(index) = (l%2==0) ? CHEB_EVEN : CHEB_ODD ;
314  }
315  }
316  }
317  else {
318  base.def=true ;
319  base.bases_1d[2]->set(0) = COSSIN ;
320  for (int k=0 ; k<nbr_coefs(2) ; k++) {
321  m = (k%2==0) ? k/2 : (k-1)/2 ;
322  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_ODD : COS_EVEN ;
323  for (int j=0 ; j<nbr_coefs(1) ; j++) {
324  l = (m%2==0) ? 2*j : 2*j+1 ;
325  index.set(0) = j ; index.set(1) = k ;
326  base.bases_1d[0]->set(index) = (l%2==0) ? CHEB_ODD : CHEB_EVEN ;
327  }
328  }
329  }
330 }
331 
332 // Base for a function anti-symetric in z, using Chebyshev
334 
335  int m,l ;
336 
337  assert (type_base == CHEB_TYPE) ;
338  base.allocate(nbr_coefs) ;
339 
340  Index index(base.bases_1d[0]->get_dimensions()) ;
341 
342  base.def=true ;
343  base.bases_1d[2]->set(0) = COSSIN ;
344  for (int k=0 ; k<nbr_coefs(2) ; k++) {
345  m = (k%2==0) ? k/2 : (k-1)/2 ;
346  base.bases_1d[1]->set(k) = (m%2==0) ? COS_ODD : SIN_EVEN ;
347  for (int j=0 ; j<nbr_coefs(1) ; j++) {
348  l = (m%2==0) ? 2*j+1 : 2*j ;
349  index.set(0) = j ; index.set(1) = k ;
350  base.bases_1d[0]->set(index) = (l%2==1) ? CHEB_ODD : CHEB_EVEN ;
351  }
352  }
353 }
354 
356 
357  int m ;
358 
359  assert (type_base == CHEB_TYPE) ;
360  base.allocate(nbr_coefs) ;
361 
362  Index index(base.bases_1d[0]->get_dimensions()) ;
363 
364  base.def=true ;
365  base.bases_1d[2]->set(0) = COSSIN ;
366  for (int k=0 ; k<nbr_coefs(2) ; k++) {
367  m = (k%2==0) ? k/2 : (k-1)/2 ;
368  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
369  for (int j=0 ; j<nbr_coefs(1) ; j++) {
370  index.set(0) = j ; index.set(1) = k ;
371  base.bases_1d[0]->set(index) = (m%2==0) ? CHEB_ODD : CHEB_EVEN ;
372  }
373  }
374 }
375 
377 
378  int m ;
379 
380  assert (type_base == CHEB_TYPE) ;
381  base.allocate(nbr_coefs) ;
382 
383  Index index(base.bases_1d[0]->get_dimensions()) ;
384 
385  base.def=true ;
386  base.bases_1d[2]->set(0) = COSSIN ;
387  for (int k=0 ; k<nbr_coefs(2) ; k++) {
388  m = (k%2==0) ? k/2 : (k-1)/2 ;
389  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_ODD : COS_EVEN ;
390  for (int j=0 ; j<nbr_coefs(1) ; j++) {
391  index.set(0) = j ; index.set(1) = k ;
392  base.bases_1d[0]->set(index) = (m%2==0) ? CHEB_ODD : CHEB_EVEN ;
393  }
394  }
395 }
396 
398 
399  int m ;
400 
401  assert (type_base == CHEB_TYPE) ;
402  base.allocate(nbr_coefs) ;
403 
404  Index index(base.bases_1d[0]->get_dimensions()) ;
405 
406  base.def=true ;
407  base.bases_1d[2]->set(0) = COSSIN ;
408  for (int k=0 ; k<nbr_coefs(2) ; k++) {
409  m = (k%2==0) ? k/2 : (k-1)/2 ;
410  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_EVEN : COS_ODD;
411  for (int j=0 ; j<nbr_coefs(1) ; j++) {
412  index.set(0) = j ; index.set(1) = k ;
413  base.bases_1d[0]->set(index) = (m%2==0) ? CHEB_ODD : CHEB_EVEN ;
414  }
415  }
416 }
417 
418 
420 
421  int m ;
422 
423  assert (type_base == CHEB_TYPE) ;
424  base.allocate(nbr_coefs) ;
425 
426  Index index(base.bases_1d[0]->get_dimensions()) ;
427 
428  base.def=true ;
429  base.bases_1d[2]->set(0) = COSSIN ;
430  for (int k=0 ; k<nbr_coefs(2) ; k++) {
431  m = (k%2==0) ? k/2 : (k-1)/2 ;
432  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
433  for (int j=0 ; j<nbr_coefs(1) ; j++) {
434  index.set(0) = j ; index.set(1) = k ;
435  base.bases_1d[0]->set(index) = (m%2==0) ? CHEB_ODD : CHEB_EVEN ;
436  }
437  }
438 }
439 
441 
442  int m ;
443 
444  assert (type_base == CHEB_TYPE) ;
445  base.allocate(nbr_coefs) ;
446 
447  Index index(base.bases_1d[0]->get_dimensions()) ;
448 
449  base.def=true ;
450  base.bases_1d[2]->set(0) = COSSIN ;
451  for (int k=0 ; k<nbr_coefs(2) ; k++) {
452  m = (k%2==0) ? k/2 : (k-1)/2 ;
453  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_EVEN : COS_ODD ;
454  for (int j=0 ; j<nbr_coefs(1) ; j++) {
455  index.set(0) = j ; index.set(1) = k ;
456  base.bases_1d[0]->set(index) = (m%2==0) ? CHEB_ODD : CHEB_EVEN ;
457  }
458  }
459 }
460 
462 
463  int m ;
464 
465  assert (type_base == CHEB_TYPE) ;
466  base.allocate(nbr_coefs) ;
467 
468  Index index(base.bases_1d[0]->get_dimensions()) ;
469 
470  base.def=true ;
471  base.bases_1d[2]->set(0) = COSSIN ;
472  for (int k=0 ; k<nbr_coefs(2) ; k++) {
473  m = (k%2==0) ? k/2 : (k-1)/2 ;
474  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_ODD : COS_EVEN;
475  for (int j=0 ; j<nbr_coefs(1) ; j++) {
476  index.set(0) = j ; index.set(1) = k ;
477  base.bases_1d[0]->set(index) = (m%2==0) ? CHEB_ODD : CHEB_EVEN ;
478  }
479  }
480 }
481 
483 
484  int m,l ;
485 
486  assert (type_base == CHEB_TYPE) ;
487  base.allocate(nbr_coefs) ;
488 
489  Index index(base.bases_1d[0]->get_dimensions()) ;
490 
491  base.def=true ;
492  base.bases_1d[2]->set(0) = COSSIN ;
493  for (int k=0 ; k<nbr_coefs(2) ; k++) {
494  m = (k%2==0) ? k/2 : (k-1)/2 ;
495  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
496  for (int j=0 ; j<nbr_coefs(1) ; j++) {
497  l = (m%2==0) ? 2*j : 2*j+1 ;
498  index.set(0) = j ; index.set(1) = k ;
499  base.bases_1d[0]->set(index) = (l%2==0) ? CHEB_ODD : CHEB_EVEN ;
500  }
501  }
502 }
503 
504 // Base for a function symetric in z, using Legendre
506 
507  int m,l ;
508 
509  assert (type_base == LEG_TYPE) ;
510  base.allocate(nbr_coefs) ;
511 
512  Index index(base.bases_1d[0]->get_dimensions()) ;
513 
514  base.def = true ;
515  base.bases_1d[2]->set(0) = COSSIN ;
516  for (int k=0 ; k<nbr_coefs(2) ; k++) {
517  m = (k%2==0) ? k/2 : (k-1)/2 ;
518  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
519  for (int j=0 ; j<nbr_coefs(1) ; j++) {
520  l = (m%2==0) ? 2*j : 2*j+1 ;
521  index.set(0) = j ; index.set(1) = k ;
522  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
523  }
524  }
525  }
526 
527 // Base for a function symetric in z, using Legendre
529 
530  int m,l ;
531 
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) = COSSIN ;
539  for (int k=0 ; k<nbr_coefs(2) ; k++) {
540  m = (k%2==0) ? k/2 : (k-1)/2 ;
541  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
542  for (int j=0 ; j<nbr_coefs(1) ; j++) {
543  l = (m%2==0) ? 2*j : 2*j+1 ;
544  index.set(0) = j ; index.set(1) = k ;
545  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_EVEN : LEG_ODD ;
546  }
547  }
548  }
549 
550 // Base for a function anti-symetric in z, using Legendre
552 
553  int m,l ;
554 
555  assert (type_base == LEG_TYPE) ;
556  base.allocate(nbr_coefs) ;
557 
558  Index index(base.bases_1d[0]->get_dimensions()) ;
559 
560  base.def = true ;
561  base.bases_1d[2]->set(0) = COSSIN ;
562  for (int k=0 ; k<nbr_coefs(2) ; k++) {
563  m = (k%2==0) ? k/2 : (k-1)/2 ;
564  base.bases_1d[1]->set(k) = (m%2==0) ? COS_ODD : SIN_EVEN ;
565  for (int j=0 ; j<nbr_coefs(1) ; j++) {
566  l = (m%2==0) ? 2*j+1 : 2*j ;
567  index.set(0) = j ; index.set(1) = k ;
568  base.bases_1d[0]->set(index) = (l%2==1) ? LEG_ODD : LEG_EVEN ;
569  }
570  }
571  }
572 
574 
575  int m,l ;
576 
577  assert (type_base == LEG_TYPE) ;
578  base.allocate(nbr_coefs) ;
579 
580  Index index(base.bases_1d[0]->get_dimensions()) ;
581 
582  base.def=true ;
583  base.bases_1d[2]->set(0) = COSSIN ;
584  for (int k=0 ; k<nbr_coefs(2) ; k++) {
585  m = (k%2==0) ? k/2 : (k-1)/2 ;
586  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
587  for (int j=0 ; j<nbr_coefs(1) ; j++) {
588  l = (m%2==0) ? 2*j : 2*j+1 ;
589  index.set(0) = j ; index.set(1) = k ;
590  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
591  }
592  }
593 }
594 
596 
597  int m,l ;
598 
599  assert (type_base == LEG_TYPE) ;
600  base.allocate(nbr_coefs) ;
601 
602  Index index(base.bases_1d[0]->get_dimensions()) ;
603 
604  base.def=true ;
605  base.bases_1d[2]->set(0) = COSSIN ;
606  for (int k=0 ; k<nbr_coefs(2) ; k++) {
607  m = (k%2==0) ? k/2 : (k-1)/2 ;
608  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_EVEN : COS_ODD ;
609  for (int j=0 ; j<nbr_coefs(1) ; j++) {
610  l = (m%2==0) ? 2*j : 2*j+1 ;
611  index.set(0) = j ; index.set(1) = k ;
612  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
613  }
614  }
615 }
616 
618 
619  int m,l ;
620 
621  assert (type_base == LEG_TYPE) ;
622  base.allocate(nbr_coefs) ;
623 
624  Index index(base.bases_1d[0]->get_dimensions()) ;
625 
626  base.def=true ;
627  base.bases_1d[2]->set(0) = COSSIN ;
628  for (int k=0 ; k<nbr_coefs(2) ; k++) {
629  m = (k%2==0) ? k/2 : (k-1)/2 ;
630  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_ODD : COS_EVEN;
631  for (int j=0 ; j<nbr_coefs(1) ; j++) {
632  l = (m%2==0) ? 2*j : 2*j+1 ;
633  index.set(0) = j ; index.set(1) = k ;
634  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
635  }
636  }
637 }
638 
640 
641  int m,l ;
642 
643  assert (type_base == LEG_TYPE) ;
644  base.allocate(nbr_coefs) ;
645 
646  Index index(base.bases_1d[0]->get_dimensions()) ;
647 
648  base.def=true ;
649  base.bases_1d[2]->set(0) = COSSIN ;
650  for (int k=0 ; k<nbr_coefs(2) ; k++) {
651  m = (k%2==0) ? k/2 : (k-1)/2 ;
652  base.bases_1d[1]->set(k) = (m%2==0) ? COS_EVEN : SIN_ODD ;
653  for (int j=0 ; j<nbr_coefs(1) ; j++) {
654  l = (m%2==0) ? 2*j : 2*j+1 ;
655  index.set(0) = j ; index.set(1) = k ;
656  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
657  }
658  }
659 }
660 
662 
663  int m,l ;
664 
665  assert (type_base == LEG_TYPE) ;
666  base.allocate(nbr_coefs) ;
667 
668  Index index(base.bases_1d[0]->get_dimensions()) ;
669 
670  base.def=true ;
671  base.bases_1d[2]->set(0) = COSSIN ;
672  for (int k=0 ; k<nbr_coefs(2) ; k++) {
673  m = (k%2==0) ? k/2 : (k-1)/2 ;
674  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_ODD : COS_EVEN ;
675  for (int j=0 ; j<nbr_coefs(1) ; j++) {
676  l = (m%2==0) ? 2*j : 2*j+1 ;
677  index.set(0) = j ; index.set(1) = k ;
678  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
679  }
680  }
681 }
682 
684 
685  int m,l ;
686 
687  assert (type_base == LEG_TYPE) ;
688  base.allocate(nbr_coefs) ;
689 
690  Index index(base.bases_1d[0]->get_dimensions()) ;
691 
692  base.def=true ;
693  base.bases_1d[2]->set(0) = COSSIN ;
694  for (int k=0 ; k<nbr_coefs(2) ; k++) {
695  m = (k%2==0) ? k/2 : (k-1)/2 ;
696  base.bases_1d[1]->set(k) = (m%2==0) ? SIN_EVEN : COS_ODD;
697  for (int j=0 ; j<nbr_coefs(1) ; j++) {
698  l = (m%2==0) ? 2*j : 2*j+1 ;
699  index.set(0) = j ; index.set(1) = k ;
700  base.bases_1d[0]->set(index) = (l%2==0) ? LEG_ODD : LEG_EVEN ;
701  }
702  }
703 }
704 
705 // Computes the derivativeswith respect to XYZ as a function of the numerical ones.
706 void Domain_nucleus::do_der_abs_from_der_var(const Val_domain *const *const der_var, Val_domain **const der_abs) const {
707 
708  // d/dx :
709  Val_domain sintdr (der_var[0]->mult_sin_theta()/alpha) ;
710  Val_domain dtsr (der_var[1]->div_x()/alpha) ;
711  Val_domain dpsr (der_var[2]->div_x()/alpha) ;
712  Val_domain costdtsr (dtsr.mult_cos_theta()) ;
713  Val_domain dpsrssint (dpsr.div_sin_theta()) ;
714 
715  der_abs[0] = new Val_domain ((sintdr+costdtsr).mult_cos_phi() - dpsrssint.mult_sin_phi()) ;
716 
717  // d/dy :
718  der_abs[1] = new Val_domain ((sintdr+costdtsr).mult_sin_phi() + dpsrssint.mult_cos_phi()) ;
719  // d/dz :
720  der_abs[2] = new Val_domain (der_var[0]->mult_cos_theta()/alpha - dtsr.mult_sin_theta()) ;
721 }
722 
723 // Rules for the multiplication of two basis.
725 
726  assert (a.ndim==3) ;
727  assert (b.ndim==3) ;
728 
729  Base_spectral res(3) ;
730  bool res_def = true ;
731 
732  if (!a.def)
733  res_def=false ;
734  if (!b.def)
735  res_def=false ;
736 
737  if (res_def) {
738 
739  // Base in phi :
740  res.bases_1d[2] = new Array<int> (a.bases_1d[2]->get_dimensions()) ;
741  switch ((*a.bases_1d[2])(0)) {
742  case COSSIN:
743  switch ((*b.bases_1d[2])(0)) {
744  case COSSIN:
745  res.bases_1d[2]->set(0) = COSSIN ;
746  break ;
747  default:
748  res_def = false ;
749  break ;
750  }
751  break ;
752  default:
753  res_def = false ;
754  break ;
755  }
756 
757  // Bases in theta :
758  // On check l'alternance :
759  Index index_1 (a.bases_1d[1]->get_dimensions()) ;
760  res.bases_1d[1] = new Array<int> (a.bases_1d[1]->get_dimensions()) ;
761  do {
762  switch ((*a.bases_1d[1])(index_1)) {
763  case COS_EVEN:
764  switch ((*b.bases_1d[1])(index_1)) {
765  case COS_EVEN:
766  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_EVEN : SIN_ODD ;
767  break ;
768  case COS_ODD:
769  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_ODD : SIN_EVEN ;
770  break ;
771  case SIN_EVEN:
772  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_EVEN : COS_ODD ;
773  break ;
774  case SIN_ODD:
775  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_ODD : COS_EVEN ;
776  break ;
777  default:
778  res_def = false ;
779  break ;
780  }
781  break ;
782  case COS_ODD:
783  switch ((*b.bases_1d[1])(index_1)) {
784  case COS_EVEN:
785  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_ODD : SIN_EVEN ;
786  break ;
787  case COS_ODD:
788  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_EVEN : SIN_ODD ;
789  break ;
790  case SIN_EVEN:
791  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_ODD : COS_EVEN ;
792  break ;
793  case SIN_ODD:
794  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_EVEN : COS_ODD ;
795  break ;
796  default:
797  res_def = false ;
798  break ;
799  }
800  break ;
801  case SIN_EVEN:
802  switch ((*b.bases_1d[1])(index_1)) {
803  case COS_EVEN:
804  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_EVEN : COS_ODD ;
805  break ;
806  case COS_ODD:
807  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_ODD : COS_EVEN ;
808  break ;
809  case SIN_EVEN:
810  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_EVEN : SIN_ODD ;
811  break ;
812  case SIN_ODD:
813  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_ODD : SIN_EVEN ;
814  break ;
815  default:
816  res_def = false ;
817  break ;
818  }
819  break ;
820  case SIN_ODD:
821  switch ((*b.bases_1d[1])(index_1)) {
822  case COS_EVEN:
823  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_ODD : COS_EVEN ;
824  break ;
825  case COS_ODD:
826  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? SIN_EVEN : COS_ODD ;
827  break ;
828  case SIN_EVEN:
829  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_ODD : SIN_EVEN ;
830  break ;
831  case SIN_ODD:
832  res.bases_1d[1]->set(index_1) = (index_1(0)%4<2) ? COS_EVEN : SIN_ODD ;
833  break ;
834  default:
835  res_def = false ;
836  break ;
837  }
838  break ;
839  default:
840  res_def = false ;
841  break ;
842  }
843  }
844  while (index_1.inc()) ;
845 
846 
847  // Base in r :
848  Index index_0 (a.bases_1d[0]->get_dimensions()) ;
849  res.bases_1d[0] = new Array<int> (a.bases_1d[0]->get_dimensions()) ;
850  do {
851  switch ((*a.bases_1d[0])(index_0)) {
852  case CHEB_EVEN:
853  switch ((*b.bases_1d[0])(index_0)) {
854  case CHEB_EVEN:
855  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? CHEB_EVEN : CHEB_ODD ;
856  break ;
857  case CHEB_ODD:
858  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? CHEB_ODD : CHEB_EVEN ;
859  break ;
860  default:
861  res_def = false ;
862  break ;
863  }
864  break ;
865  case CHEB_ODD:
866  switch ((*b.bases_1d[0])(index_0)) {
867  case CHEB_EVEN:
868  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? CHEB_ODD : CHEB_EVEN ;
869  break ;
870  case CHEB_ODD:
871  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? CHEB_EVEN : CHEB_ODD ;
872  break ;
873  default:
874  res_def = false ;
875  break ;
876  }
877  break ;
878  case LEG_EVEN:
879  switch ((*b.bases_1d[0])(index_0)) {
880  case LEG_EVEN:
881  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? LEG_EVEN : LEG_ODD ;
882  break ;
883  case LEG_ODD:
884  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? LEG_ODD : LEG_EVEN ;
885  break ;
886  default:
887  res_def = false ;
888  break ;
889  }
890  break ;
891  case LEG_ODD:
892  switch ((*b.bases_1d[0])(index_0)) {
893  case LEG_EVEN:
894  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? LEG_ODD : LEG_EVEN ;
895  break ;
896  case LEG_ODD:
897  res.bases_1d[0]->set(index_0) = (index_0(1)%4<2) ? LEG_EVEN : LEG_ODD ;
898  break ;
899  default:
900  res_def = false ;
901  break ;
902  }
903  break ;
904  default:
905  res_def = false ;
906  break ;
907  }
908  }
909  while (index_0.inc()) ;
910  }
911  if (!res_def)
912  for (int dim=0 ; dim<a.ndim ; dim++)
913  if (res.bases_1d[dim]!= 0x0) {
914  delete res.bases_1d[dim] ;
915  res.bases_1d[dim] = 0x0 ;
916  }
917  res.def = res_def ;
918  return res ;
919 }
920 
921 int Domain_nucleus::give_place_var (char* p) const {
922  int res = -1 ;
923  if (strcmp(p,"R ")==0)
924  res = 0 ;
925  if (strcmp(p,"T ")==0)
926  res = 1 ;
927  if (strcmp(p,"P ")==0)
928  res = 2 ;
929  return res ;
930 }
931 
932 double Domain_nucleus::integ(const Val_domain& so, int bound) const // compute int (so sin(theta) dtheta dphi) in x = 1 (r = outer_bc)
933 {
934  if (bound != OUTER_BC)
935  {
936  cerr << "Domain_nucleus::integ only defined for r=rmax yet..." << endl ;
937  abort() ;
938  }
939  double res(0.0);
940  int baset((*so.base.bases_1d[1])(0));
941  if (baset != COS_EVEN)
942  return res;
943  else
944  {
945  so.coef();
946  //Loop on theta :
947  Index pos(get_nbr_coefs());
948  pos.set(2) = 0;
949  for (int j(0) ; j < nbr_coefs(1) ; ++j)
950  {
951  pos.set(1) = j;
952  double fact_tet(2.0/(1.0 - 4.0*j*j));
953  // Loop on r :
954  for (int i(0) ; i < nbr_coefs(0) ; ++i)
955  {
956  pos.set(0) = i;
957  res += fact_tet*(*so.cf)(pos);
958  }
959  }
960  return res*2.0*M_PI;
961  }
962 }
963 }
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
int & set(int i)
Read/write of the size of a given dimension.
Definition: dim_array.hpp:54
void save(FILE *) const
Save function.
Definition: dim_array.cpp:32
Class for a spherical domain containing the origin and a symmetry with respect to the plane .
Definition: spheric.hpp:66
virtual void do_radius() const
Computes the generalized radius.
Point center
Absolute coordinates of the center.
Definition: spheric.hpp:70
virtual Val_domain der_normal(const Val_domain &, int) const
Normal derivative with respect to a given surface.
virtual bool is_in(const Point &xx, double prec=1e-13) const
Check whether a point lies inside Domain.
virtual void do_cart() const
Computes the Cartesian coordinates.
virtual void set_cheb_r_base(Base_spectral &) const
Gives the base using odd Chebyshev polynomials$ for the radius.
virtual Val_domain div_x(const Val_domain &) const
Division by .
virtual ostream & print(ostream &o) const
Delegate function to virtualize the << operator.
virtual void set_legendre_base_t_spher(Base_spectral &) const
Gives the base using Legendre polynomials, for the component of a vector.
virtual void set_legendre_base_p_spher(Base_spectral &) const
Gives the base using Legendre polynomials, for the component of a vector.
virtual double integ(const Val_domain &so, int bound) const
Surface integral on a given boundary.
virtual void set_legendre_base(Base_spectral &so) const
Sets the base to the standard one for Legendre polynomials.
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 do_cart_surr() const
Computes the Cartesian coordinates over the radius.
virtual void set_cheb_base_t_spher(Base_spectral &) const
Gives the base using Chebyshev polynomials, for the component of a vector.
virtual void set_anti_cheb_base(Base_spectral &so) const
Sets the base to the standard one for Chebyshev polynomials for functions antisymetric in The bases ...
virtual void set_cheb_base(Base_spectral &so) const
Sets the base to the standard one for Chebyshev polynomials.
virtual Base_spectral mult(const Base_spectral &, const Base_spectral &) const
Method for the multiplication of two Base_spectral.
virtual void set_legendre_base_t_mtz(Base_spectral &) const
Gives the base using Legendre polynomials, for the component of a vector in the MTZ context.
virtual void set_cheb_base_with_m(Base_spectral &so, int m) const
Gives the standard base using Chebyshev polynomials.
virtual void set_cheb_base_r_spher(Base_spectral &) const
Gives the base using Chebyshev polynomials, for the radial component of a vector.
virtual void set_legendre_base_r_spher(Base_spectral &) const
Gives the base using Legendre polynomials, for the radial component of a vector.
virtual Val_domain mult_sin_theta(const Val_domain &) const
Multiplication by .
virtual int give_place_var(char *) const
Translates a name of a coordinate into its corresponding numerical name.
Domain_nucleus(int num, int ttype, double radius, const Point &cr, const Dim_array &nbr)
Standard constructor :
virtual void save(FILE *) const
Saving function.
virtual void set_cheb_base_p_spher(Base_spectral &) const
Gives the base using Chebyshev polynomials, for the component of a vector.
virtual Val_domain mult_cos_theta(const Val_domain &) const
Multiplication by .
virtual void set_legendre_base_r_mtz(Base_spectral &) const
Gives the base using Legendre polynomials, for the radial component of a vector in the MTZ context.
virtual const Point absol_to_num(const Point &xxx) const
Computes the numerical coordinates from the physical ones.
virtual Val_domain mult_sin_phi(const Val_domain &) const
Multiplication by .
virtual void set_legendre_r_base(Base_spectral &) const
Gives the base using odd Legendre polynomials$ for the radius.
virtual void do_absol() const
Computes the absolute coordinates.
double alpha
Relates the numerical to the physical radii.
Definition: spheric.hpp:69
virtual void do_coloc()
Computes the colocation points.
virtual void set_cheb_base_t_mtz(Base_spectral &) const
Gives the base using Chebyshev polynomials, for the component of a vector in the MTZ setting.
virtual Val_domain mult_cos_phi(const Val_domain &) const
Multiplication by .
virtual void set_legendre_base_p_mtz(Base_spectral &) const
Gives the base using Legendre polynomials, for the component of a vector in the MTZ context.
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_cheb_base_p_mtz(Base_spectral &) const
Gives the base using Chebyshev polynomials, for the component of a vector in the MTZ setting.
virtual void set_cheb_base_r_mtz(Base_spectral &) const
Gives the base using Chebyshev polynomials, for the radial component of a vector in the MTZ setting.
virtual void set_anti_legendre_base(Base_spectral &so) const
Sets the base to the standard one for Legendre polynomials for functions antisymetric in The bases a...
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
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
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_phi() const
Multiplication by .
Val_domain mult_sin_theta() const
Multiplication by .
Val_domain mult_cos_phi() 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 div_sin_theta() const
Division by .
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