KADATH
space_bin_bh.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 "bin_bh.hpp"
22 #include "utilities.hpp"
23 #include "point.hpp"
24 #include "scalar.hpp"
25 #include "tensor_impl.hpp"
26 #include "system_of_eqs.hpp"
27 #include "name_tools.hpp"
28 namespace Kadath {
29 double eta_lim_chi (double chi, double rext, double a, double eta_c) ;
30 double chi_lim_eta (double chi, double rext, double a, double chi_c) ;
31 
32 double zerosec(double (*f)(double, const Param&), const Param& parf,
33  double x1, double x2, double precis, int nitermax, int& niter) ;
34 
35 
36 double func_ab (double aa, const Param& par) {
37  double r1 = par.get_double(0) ;
38  double r2 = par.get_double(1) ;
39  double d = par.get_double(2) ;
40  return (sqrt(aa*aa+r1*r1)+sqrt(aa*aa+r2*r2)-d) ;
41 }
42 
43 Space_bin_bh::Space_bin_bh (int ttype, double dist, double rbh1, double rbh2, double rext, int nr) {
44 
45  ndim = 3 ;
46 
47  nbr_domains = 12 ;
48  type_base = ttype ;
49  domains = new Domain* [nbr_domains] ;
50 
51  Dim_array res (ndim) ;
52  res.set(0) = nr ; res.set(1) = nr ; res.set(2) = nr-1 ;
53  Dim_array res_bi(ndim) ;
54  res_bi.set(0) = nr ; res_bi.set(1) = nr ; res_bi.set(2) = nr ;
55 
56  // Bispheric :
57  // Computation of aa
58  Param par_a ;
59  par_a.add_double(2*rbh1,0) ;
60  par_a.add_double(2*rbh2,1) ;
61  par_a.add_double(dist,2) ;
62  double a_min = 0 ;
63  double a_max = dist/2. ;
64  double precis = PRECISION ;
65  int nitermax = 500 ;
66  int niter ;
67  double aa = zerosec(func_ab, par_a, a_min, a_max, precis, nitermax, niter) ;
68  double eta_plus = asinh(aa/2/rbh2) ;
69  double eta_minus = -asinh(aa/2/rbh1) ;
70 
71  double chi_c = 2*atan(aa/rext) ;
72  double eta_c = log((1+rext/aa)/(rext/aa-1)) ;
73  double eta_lim = eta_c/2. ;
74  double chi_lim = chi_lim_eta (eta_lim, rext, aa, chi_c) ;
75 
76  // First BH
77  Point center_minus (ndim) ;
78  center_minus.set(1) = aa*cosh(eta_minus)/sinh(eta_minus) ;
79  domains[0] = new Domain_nucleus (0, ttype, rbh1/2., center_minus, res) ;
80  domains[1] = new Domain_shell_outer_homothetic (*this, 1, ttype, rbh1/2., rbh1, center_minus, res) ;
81  domains[2] = new Domain_shell_inner_homothetic (*this, 2, ttype, rbh1, rbh1*2., center_minus, res) ;
82 
83  // Second bh
84  Point center_plus (ndim) ;
85  center_plus.set(1) = aa*cosh(eta_plus)/sinh(eta_plus) ;
86  domains[3] = new Domain_nucleus (3, ttype, rbh2/2., center_plus, res) ;
87  domains[4] = new Domain_shell_outer_homothetic (*this, 4, ttype, rbh2/2., rbh2, center_plus, res) ;
88  domains[5] = new Domain_shell_inner_homothetic (*this, 5, ttype, rbh2, rbh2*2., center_plus, res) ;
89 
90  // Bispheric part
91  domains[6] = new Domain_bispheric_chi_first(6, ttype, aa, eta_minus, rext, chi_lim, res_bi) ;
92  domains[7] = new Domain_bispheric_rect(7, ttype, aa, rext, eta_minus, -eta_lim, chi_lim, res_bi) ;
93  domains[8] = new Domain_bispheric_eta_first(8, ttype, aa, rext, -eta_lim, eta_lim, res_bi) ;
94  domains[9] = new Domain_bispheric_rect(9, ttype, aa, rext, eta_plus, eta_lim, chi_lim, res_bi) ;
95  domains[10] = new Domain_bispheric_chi_first(10, ttype, aa, eta_plus, rext, chi_lim, res_bi) ;
96 
97  // Compactified domain
98  Point center(3) ;
99  domains[11] = new Domain_compact (11, ttype, rext, center, res) ;
100 
101  const Domain_shell_outer_homothetic* pouter_1 = dynamic_cast<const Domain_shell_outer_homothetic*> (domains[1]) ;
102  pouter_1->vars_to_terms() ;
103  pouter_1->update() ;
104  const Domain_shell_inner_homothetic* pinner_1 = dynamic_cast<const Domain_shell_inner_homothetic*> (domains[2]) ;
105  pinner_1->vars_to_terms() ;
106  pinner_1->update() ;
107  const Domain_shell_outer_homothetic* pouter_2 = dynamic_cast<const Domain_shell_outer_homothetic*> (domains[4]) ;
108  pouter_2->vars_to_terms() ;
109  pouter_2->update() ;
110  const Domain_shell_inner_homothetic* pinner_2 = dynamic_cast<const Domain_shell_inner_homothetic*> (domains[5]) ;
111  pinner_2->vars_to_terms() ;
112  pinner_2->update() ;
113 }
114 
115 
117  fread_be (&nbr_domains, sizeof(int), 1, fd) ;
118  fread_be (&ndim, sizeof(int), 1, fd) ;
119  fread_be (&type_base, sizeof(int), 1, fd) ;
120  domains = new Domain* [nbr_domains] ;
121  //First BH :
122  domains[0] = new Domain_nucleus (0, fd) ;
123  domains[1] = new Domain_shell_outer_homothetic (*this, 1, fd) ;
124  domains[2] = new Domain_shell_inner_homothetic (*this, 2, fd) ;
125 
126  //second BH :
127  domains[3] = new Domain_nucleus (3, fd) ;
128  domains[4] = new Domain_shell_outer_homothetic (*this, 4, fd) ;
129  domains[5] = new Domain_shell_inner_homothetic (*this, 5, fd) ;
130 
131  // Bispheric
132  domains[6] = new Domain_bispheric_chi_first(6, fd) ;
133  domains[7] = new Domain_bispheric_rect(7, fd) ;
134  domains[8] = new Domain_bispheric_eta_first(8, fd) ;
135  domains[9] = new Domain_bispheric_rect(9, fd) ;
136  domains[10] = new Domain_bispheric_chi_first(10, fd) ;
137 
138  // Compactified
139  domains[11] = new Domain_compact(11, fd) ;
140 
141  const Domain_shell_outer_homothetic* pouter_1 = dynamic_cast<const Domain_shell_outer_homothetic*> (domains[1]) ;
142  pouter_1->vars_to_terms() ;
143  pouter_1->update() ;
144  const Domain_shell_inner_homothetic* pinner_1 = dynamic_cast<const Domain_shell_inner_homothetic*> (domains[2]) ;
145  pinner_1->vars_to_terms() ;
146  pinner_1->update() ;
147  const Domain_shell_outer_homothetic* pouter_2 = dynamic_cast<const Domain_shell_outer_homothetic*> (domains[4]) ;
148  pouter_2->vars_to_terms() ;
149  pouter_2->update() ;
150  const Domain_shell_inner_homothetic* pinner_2 = dynamic_cast<const Domain_shell_inner_homothetic*> (domains[5]) ;
151  pinner_2->vars_to_terms() ;
152  pinner_2->update() ;
153 }
154 
157  pouter_1->del_deriv() ;
159  pinner_1->del_deriv() ;
161  pouter_2->del_deriv() ;
163  pinner_2->del_deriv() ;
164 }
165 
166 void Space_bin_bh::save (FILE* fd) const {
167  fwrite_be (&nbr_domains, sizeof(int), 1, fd) ;
168  fwrite_be (&ndim, sizeof(int), 1, fd) ;
169  fwrite_be (&type_base, sizeof(int), 1, fd) ;
170  for (int i=0 ; i<nbr_domains ; i++)
171  domains[i]->save(fd) ;
172 }
173 
175 
176  return (domains[2]->nbr_unknowns_from_adapted() + domains[5]->nbr_unknowns_from_adapted()) ;
177 }
178 
179 void Space_bin_bh::affecte_coef_to_variable_domains (int& pos, int cc, Array<int>& zedoms) const {
180 
181  // In BH 1 ?
182  bool found_outer_1 = false ;
183  int old_pos = pos ;
184  domains[1]->affecte_coef(pos, cc, found_outer_1) ;
185  pos = old_pos ;
186  bool found_inner_1 = false ;
187  domains[2]->affecte_coef(pos, cc, found_inner_1) ;
188  assert (found_outer_1 == found_inner_1) ;
189  if (found_outer_1) {
190  zedoms.set(0) = 1 ;
191  zedoms.set(1) = 2 ;
192  }
193  else {
194  zedoms.set(0) = -1 ;
195  zedoms.set(1) = -1 ;
196  }
197 
198  // In BH 2 ?
199  bool found_outer_2 = false ;
200  old_pos = pos ;
201  domains[4]->affecte_coef(pos, cc, found_outer_2) ;
202  pos = old_pos ;
203  bool found_inner_2 = false ;
204  domains[5]->affecte_coef(pos, cc, found_inner_2) ;
205  assert (found_outer_2 == found_inner_2) ;
206  if (found_outer_2) {
207  zedoms.set(0) = 4 ;
208  zedoms.set(1) = 5 ;
209  }
210 }
211 
212 void Space_bin_bh::xx_to_ders_variable_domains (const Array<double>& xx, int& conte) const {
213  // BH 1
214  int old_conte = conte ;
215  domains[1]->xx_to_ders_from_adapted(xx, conte) ;
216  conte = old_conte ;
217  domains[2]->xx_to_ders_from_adapted(xx, conte) ;
218  // bh2 2
219  old_conte = conte ;
220  domains[4]->xx_to_ders_from_adapted(xx, conte) ;
221  conte = old_conte ;
222  domains[5]->xx_to_ders_from_adapted(xx, conte) ;
223 }
224 
226 
227  // First get the corrections :
228  // BH 1
229  int old_pos = pos ;
230  Val_domain cor_outer_1 (domains[1]) ;
231  domains[1]->xx_to_vars_from_adapted(cor_outer_1, xx, pos) ;
232  pos = old_pos ;
233  Val_domain cor_inner_1 (domains[2]) ;
234  domains[2]->xx_to_vars_from_adapted(cor_inner_1, xx, pos) ;
235 
236  // BH 2
237  old_pos = pos ;
238  Val_domain cor_outer_2 (domains[4]) ;
239  domains[4]->xx_to_vars_from_adapted(cor_outer_2, xx, pos) ;
240  pos = old_pos ;
241  Val_domain cor_inner_2 (domains[5]) ;
242  domains[5]->xx_to_vars_from_adapted(cor_inner_2, xx, pos) ;
243 
244  // Now update the variables :
245  for (int i=0 ; i<sys->nvar ; i++) {
246  for (int n=0 ; n<sys->var[i]->get_n_comp() ; n++) {
247  Scalar res(*this) ;
248  domains[1]->update_variable(cor_outer_1, *sys->var[i]->cmp[n], res) ;
249  domains[2]->update_variable(cor_inner_1, *sys->var[i]->cmp[n], res) ;
250  domains[4]->update_variable(cor_outer_2, *sys->var[i]->cmp[n], res) ;
251  domains[5]->update_variable(cor_inner_2, *sys->var[i]->cmp[n], res) ;
252 
253 
254  sys->var[i]->cmp[n]->set_domain(1) = res(1) ;
255  sys->var[i]->cmp[n]->set_domain(2) = res(2) ;
256  sys->var[i]->cmp[n]->set_domain(4) = res(4) ;
257  sys->var[i]->cmp[n]->set_domain(5) = res(5) ;
258  }
259  }
260 
261  // Now the constants :
262  for (int i=0 ; i<sys->ncst ; i++)
263  if (sys->cst[i*(sys->dom_max-sys->dom_min+1)]->get_type_data()==TERM_T)
264  for (int n=0 ; n<sys->cst[i*(sys->dom_max-sys->dom_min+1)]->val_t->get_n_comp() ; n++) {
265 
266  Scalar so (*this) ;
267  so = 0 ;
268  for (int d=1 ; d<=5 ; d++)
269  if (d!=3)
270  so.set_domain(d) = (*sys->cst[i*(sys->dom_max-sys->dom_min+1)+d]->val_t->cmp[n])(d) ;
271 
272  Scalar res(*this) ;
273  res = 0 ;
274  domains[1]->update_constante(cor_outer_1, so, res) ;
275  domains[2]->update_constante(cor_inner_1, so, res) ;
276  domains[4]->update_constante(cor_outer_2, so, res) ;
277  domains[5]->update_constante(cor_inner_2, so, res) ;
278 
279  sys->cst[i*(sys->dom_max-sys->dom_min+1)+1]->val_t->cmp[n]->set_domain(1) = res(1) ;
280  sys->cst[i*(sys->dom_max-sys->dom_min+1)+2]->val_t->cmp[n]->set_domain(2) = res(2) ;
281  sys->cst[i*(sys->dom_max-sys->dom_min+1)+4]->val_t->cmp[n]->set_domain(4) = res(4) ;
282  sys->cst[i*(sys->dom_max-sys->dom_min+1)+5]->val_t->cmp[n]->set_domain(5) = res(5) ;
283  }
284 
285  // Update the mapping :
286  domains[1]->update_mapping(cor_outer_1) ;
287  domains[2]->update_mapping(cor_inner_1) ;
288  domains[4]->update_mapping(cor_outer_2) ;
289  domains[5]->update_mapping(cor_inner_2) ;
290 
291 }
292 
293 
295 
296  if (dom==2) {
297  // First BH ;
298  Array<int> res (2,2) ;
299  switch (bound) {
300  case OUTER_BC :
301  res.set(0,0) = 6 ; // Matching with chi first
302  res.set(1,0) = INNER_BC ;
303  res.set(0,1) = 7 ; // Matching with rect
304  res.set(1,1) = INNER_BC ;
305  break ;
306  default :
307  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ;
308  abort() ;
309  }
310  return res ;
311  }
312 
313  if (dom== 5) {
314  // second bh ;
315  Array<int> res(2, 2) ;
316  switch (bound) {
317  case OUTER_BC :
318  res.set(0,0) = 9 ; // Matching with rect
319  res.set(1,0) = INNER_BC ;
320  res.set(0,1) = 10 ; // Matching with chi_first
321  res.set(1,1) = INNER_BC ;
322  break ;
323  default :
324  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ; abort() ;
325  }
326  return res ;
327  }
328 
329  if (dom== 6) {
330  // first chi first :
331  Array<int> res(2,1) ;
332  switch (bound) {
333  case INNER_BC :
334  res.set(0,0) = 2 ; // First bh
335  res.set(1,0) = OUTER_BC ;
336  break ;
337  case OUTER_BC :
338  res.set(0,0) = 11 ; // Compactified domain or first shell
339  res.set(1,0) = INNER_BC ;
340  break ;
341  default :
342  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ; abort() ;
343  }
344  return res ;
345  }
346 
347  if (dom==7) {
348  // first rect :
349  Array<int> res(2, 1) ;
350  switch (bound) {
351  case INNER_BC :
352  res.set(0,0) = 2 ; // First bh
353  res.set(1,0) = OUTER_BC ;
354  break ;
355  case OUTER_BC :
356  res.set(0,0) = 11 ; // Compactified domain or first shell
357  res.set(1,0) = INNER_BC ;
358  break ;
359  default :
360  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ; abort() ;
361  }
362  return res ;
363  }
364 
365 
366  if (dom==8) {
367  // eta first
368  Array<int> res(2, 1) ;
369  switch (bound) {
370  case OUTER_BC :
371  res.set(0, 0) = 11 ; // Compactified domain or first shell
372  res.set(1, 0) = INNER_BC ;
373  break ;
374  default :
375  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ; abort() ;
376  }
377  return res ;
378  }
379 
380  if (dom==9) {
381  // second rect :
382  Array<int> res(2, 1) ;
383  switch (bound) {
384  case INNER_BC :
385  res.set(0, 0) = 5 ; // Second bh
386  res.set(1, 0) = OUTER_BC ;
387  break ;
388  case OUTER_BC :
389  res.set(0, 0) = 11 ; // Compactified domain or first shell
390  res.set(1, 0) = INNER_BC ;
391  break ;
392  default :
393  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ; abort() ;
394  }
395  return res ;
396  }
397 
398  if (dom==10) {
399  // second chi first :
400  Array<int> res(2, 1) ;
401  switch (bound) {
402  case INNER_BC :
403  res.set(0,0) = 5 ; // second nucleus
404  res.set(1,0) = OUTER_BC ;
405  break ;
406  case OUTER_BC :
407  res.set(0,0) = 11 ; // Compactified domain or first shell
408  res.set(1,0) = INNER_BC ;
409  break ;
410  default :
411  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ;
412  abort() ;
413  }
414  return res ;
415  }
416 
417  if (dom==11) {
418  // compactified domain or first shell :
419  Array<int> res(2,5) ;
420  switch (bound) {
421  case INNER_BC :
422  res.set(0,0) = 6 ; // first chi first
423  res.set(0,1) = 7 ; // first rect
424  res.set(0,2) = 8 ; // eta first
425  res.set(0,3) = 9 ; // second rect
426  res.set(0,4) = 10 ; // second chi first
427  // Outer BC for all :
428  for (int i=0 ; i<5 ; i++)
429  res.set(1,i) = OUTER_BC ;
430  break ;
431  default :
432  cerr << "Bad bound in Space_bin_bh::get_indices_matching_non_std" << endl ;
433  abort() ;
434  }
435  return res ;
436  }
437 
438  cerr << "Bad domain in Space_bin_bh::get_indices_matching_non_std" << endl ;
439  abort() ;
440 }
441 
442 }
reference set(const Index &pos)
Read/write of an element.
Definition: array.hpp:186
Class for storing the dimensions of an array.
Definition: dim_array.hpp:34
int & set(int i)
Read/write of the size of a given dimension.
Definition: dim_array.hpp:54
Class for bispherical coordinates with a symmetry with respect to the plane .
Definition: bispheric.hpp:460
Class for bispherical coordinates with a symmetry with respect to the plane .
Definition: bispheric.hpp:878
Class for bispherical coordinates with a symmetry with respect to the plane .
Definition: bispheric.hpp:64
Class for a spherical compactified domain and a symmetry with respect to the plane .
Definition: spheric.hpp:1007
Class for a spherical domain containing the origin and a symmetry with respect to the plane .
Definition: spheric.hpp:66
void update() const
Updates all the quantities that depend on the inner radius (like the normal vectors).
void del_deriv() override
Destroys the derivated members (like coloc, cart and radius), when changing the type of colocation po...
virtual void vars_to_terms() const
The Term_eq describing the variable shape of the Domain are updated.
Class for a spherical-like domain, having a symmetry with respect to the plane .
Definition: homothetic.hpp:45
void update() const
Updates all the quantities that depend on the inner radius (like the normal vectors).
void del_deriv() override
Destroys the derivated members (like coloc, cart and radius), when changing the type of colocation po...
virtual void vars_to_terms() const
The Term_eq describing the variable shape of the Domain are updated.
Class for a spherical-like domain, having a symmetry with respect to the plane .
Definition: homothetic.hpp:105
Abstract class that implements the fonctionnalities common to all the type of domains.
Definition: space.hpp:60
virtual void xx_to_ders_from_adapted(const Array< double > &xx, int &conte) const
Affects the derivative part of variable a Domain from a set of values.
Definition: space.hpp:928
virtual void affecte_coef(int &conte, int cc, bool &found) const
The variation of the functions describing the shape of the Domain are affected from the unknowns of t...
Definition: space.hpp:906
virtual void update_variable(const Val_domain &shape, const Scalar &oldval, Scalar &newval) const
Update the value of a scalar, after the shape of the Domain has been changed by the system.
Definition: space.hpp:942
virtual void xx_to_vars_from_adapted(Val_domain &shape, const Array< double > &xx, int &conte) const
Computes the new boundary of a Domain from a set of values.
Definition: space.hpp:913
virtual void update_mapping(const Val_domain &shape)
Updates the variables parts of the Domain.
Definition: space.hpp:977
virtual void update_constante(const Val_domain &shape, const Scalar &oldval, Scalar &newval) const
Update the value of a scalar, after the shape of the Domain has been changed by the system.
Definition: space.hpp:961
Parameter storage.
Definition: param.hpp:30
void add_double(double x, int position=0)
Adds the the address of a new double to the list.
Definition: param.cpp:115
The class Point is used to store the coordinates of a point.
Definition: point.hpp:30
double & set(int i)
Read/write of a coordinate.
Definition: point.hpp:47
The class Scalar does not really implements scalars in the mathematical sense but rather tensorial co...
Definition: scalar.hpp:67
Val_domain & set_domain(int)
Read/write of a particular Val_domain.
Definition: scalar.hpp:555
virtual void xx_to_vars_variable_domains(System_of_eqs *, const Array< double > &, int &) const
Update the variables of a system, from the variation of the shape of the domains.
virtual ~Space_bin_bh()
Destructor.
virtual Array< int > get_indices_matching_non_std(int dom, int bound) const
Gives the number of the other domains, touching a given boundary.
virtual int nbr_unknowns_from_variable_domains() const
Gives the number of unknowns coming from the variable shape of the domain.
virtual void affecte_coef_to_variable_domains(int &, int, Array< int > &) const
The variation of the functions describing the shape of the Domain are affected from the unknowns of t...
Space_bin_bh(int ttype, double dist, double rbh1, double rbh2, double rext, int nr)
Standard constructor
virtual void save(FILE *) const
Saving function.
virtual void xx_to_ders_variable_domains(const Array< double > &, int &) const
Update the vairable domains from a set of values.
int type_base
Type of basis used (i.e. using either Chebyshev or Legendre polynomials).
Definition: space.hpp:1367
int ndim
Number of dimensions (should be the same for all the Domains).
Definition: space.hpp:1366
Domain ** domains
Pointers on the various Domains.
Definition: space.hpp:1368
int nbr_domains
Number od Domains.
Definition: space.hpp:1365
Class used to describe and solve a system of equations.
MMPtr_array< Tensor > var
Pointer on the unknown fields.
MMPtr_array< Term_eq > cst
Pointers on the Term_eq coming from the constants passed by the user.
int dom_max
Highest domain number.
int ncst
Number of constants passed by the user.
int dom_min
Smallest domain number.
int nvar
Number of unknown fields.
Class for storing the basis of decompositions of a field and its values on both the configuration and...
Definition: val_domain.hpp:69