OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
AmrOpenBoundary.h
Go to the documentation of this file.
1 //
2 // Class AmrOpenBoundary
3 // Open boundary condition
4 //
5 // Copyright (c) 2017 - 2020, Matthias Frey, Paul Scherrer Institut, Villigen PSI, Switzerland
6 // All rights reserved
7 //
8 // Implemented as part of the PhD thesis
9 // "Precise Simulations of Multibunches in High Intensity Cyclotrons"
10 //
11 // This file is part of OPAL.
12 //
13 // OPAL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU General Public License as published by
15 // the Free Software Foundation, either version 3 of the License, or
16 // (at your option) any later version.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
20 //
21 
22 #ifndef AMR_OPEN_BOUNDARY_H
23 #define AMR_OPEN_BOUNDARY_H
24 
25 #include "AmrBoundary.h"
26 
28 
29 template <class Level>
30 class AmrOpenBoundary : public AmrBoundary<Level> {
31 
32 public:
33  typedef typename Level::umap_t umap_t;
34  typedef typename Level::lo_t lo_t;
35  typedef typename Level::go_t go_t;
36  typedef typename Level::scalar_t scalar_t;
38 
39 public:
40 
42  : AmrBoundary<Level>(4)
43  , order_m(ABC::Robin)
44  , dist_m(1.7)
45  { }
46 
47  void apply(const AmrIntVect_t& iv,
48  const lo_t& dir,
49  umap_t& map,
50  const scalar_t& value,
51  Level* mglevel,
52  const go_t* nr);
53 
54  enum ABC {
59  Robin
60  };
61 
62 private:
63  int order_m;
64  double dist_m;
65 
67  const lo_t& dir,
68  Level* mglevel,
69  const go_t* nr);
70 
74  void robin_m(const AmrIntVect_t& iv,
75  const lo_t& dir,
76  umap_t& map,
77  const scalar_t& value,
78  Level* mglevel,
79  const go_t* nr);
80 
84  void abc0_m(const AmrIntVect_t& iv,
85  const lo_t& dir,
86  umap_t& map,
87  const scalar_t& value,
88  Level* mglevel,
89  const go_t* nr);
90 
91 
95  void abc1_m(const AmrIntVect_t& iv,
96  const lo_t& dir,
97  umap_t& map,
98  const scalar_t& value,
99  Level* mglevel,
100  const go_t* nr);
101 
105  void abc2_m(const AmrIntVect_t& iv,
106  const lo_t& dir,
107  umap_t& map,
108  const scalar_t& value,
109  Level* mglevel,
110  const go_t* nr);
111 
112 
116  void abc3_m(const AmrIntVect_t& iv,
117  const lo_t& dir,
118  umap_t& map,
119  const scalar_t& value,
120  Level* mglevel,
121  const go_t* nr);
122 
123 };
124 
125 
126 template <class Level>
128  const lo_t& dir,
129  umap_t& map,
130  const scalar_t& value,
131  Level* mglevel,
132  const go_t* nr)
133 {
134  switch ( order_m ) {
135  case ABC::Third:
136  {
137  this->abc3_m(iv, dir, map, value, mglevel, nr);
138  break;
139  }
140  case ABC::Second:
141  {
142  this->abc2_m(iv, dir, map, value, mglevel, nr);
143  break;
144  }
145  case ABC::First:
146  {
147  this->abc1_m(iv, dir, map, value, mglevel, nr);
148  break;
149  }
150  case ABC::Zeroth:
151  {
152  this->abc0_m(iv, dir, map, value, mglevel, nr);
153  break;
154  }
155  case ABC::Robin:
156  {
157  this->robin_m(iv, dir, map, value, mglevel, nr);
158  break;
159  }
160  default:
161  {
162  throw OpalException("AmrOpenBoundary<Level>::apply()",
163  "Order not supported.");
164  }
165  }
166 }
167 
168 
169 template <class Level>
171  const lo_t& dir,
172  umap_t& map,
173  const scalar_t& value,
174  Level* mglevel,
175  const go_t* nr)
176 {
177  AmrIntVect_t niv = iv;
178  AmrIntVect_t n2iv = iv;
179 
180  if ( iv[dir] == -1 ) {
181  // lower boundary
182  niv[dir] = 0;
183  n2iv[dir] = 1;
184  } else {
185  // upper boundary
186  niv[dir] = nr[dir] - 1;
187  n2iv[dir] = nr[dir] - 2;
188  }
189 
190  // correct cell size
191  scalar_t h = mglevel->cellSize(dir);
192 
193  // artificial distance
194  scalar_t d = dist_m;;
195 
196  map[mglevel->serialize(niv)] -= 2.0 * h / d * value;
197  map[mglevel->serialize(n2iv)] += value;
198 }
199 
200 
201 template <class Level>
203  const lo_t& dir,
204  umap_t& map,
205  const scalar_t& value,
206  Level* mglevel,
207  const go_t* nr)
208 {
209  // ABC0 == Dirichlet BC
210  AmrIntVect_t niv = iv;
211 
212  if ( iv[dir] == -1 ) {
213  // lower boundary
214  niv[dir] = 0;
215 
216  } else {
217  // upper boundary
218  niv[dir] = nr[dir] - 1;
219  }
220 
221  map[mglevel->serialize(niv)] -= value;
222 }
223 
224 
225 template <class Level>
227  const lo_t& dir,
228  umap_t& map,
229  const scalar_t& value,
230  Level* mglevel,
231  const go_t* nr)
232 {
233  // ABC1 == Robin BC (with normal derivatives) (i.e. Dirichlet BC + Neumann BC)
234  AmrIntVect_t niv = iv;
235  AmrIntVect_t n2iv = iv;
236 
237  scalar_t sign = 1.0;
238 
239  if ( iv[dir] == -1 ) {
240  // lower boundary
241  niv[dir] = 0;
242  n2iv[dir] = 1;
243 
244  sign = -1.0;
245 
246  } else {
247  // upper boundary
248  niv[dir] = nr[dir] - 1;
249  n2iv[dir] = nr[dir] - 2;
250  }
251 
252  // correct cell size
253  scalar_t h = mglevel->cellSize(dir);
254 
255  // coordinate of inner cell
256  scalar_t x = this->coordinate_m(niv, 0, mglevel, nr) + sign * dist_m * h;
257  scalar_t y = this->coordinate_m(niv, 1, mglevel, nr) + sign * dist_m * h;
258 #if AMREX_SPACEDIM == 3
259  scalar_t z = this->coordinate_m(niv, 2, mglevel, nr) + sign * dist_m * h;
260 #endif
261  scalar_t r = std::sqrt( AMREX_D_TERM(x * x, + y * y, + z * z) );
262 
263 // // artificial distance
264 // scalar_t d = dist_m * nr[dir] * h; // + r;
265  scalar_t d = r;
266 
267  map[mglevel->serialize(niv)] -= 2.0 * h / d * value;
268  map[mglevel->serialize(n2iv)] += value;
269 }
270 
271 
272 template <class Level>
274  const lo_t& dir,
275  umap_t& map,
276  const scalar_t& value,
277  Level* mglevel,
278  const go_t* nr)
279 {
280  AmrIntVect_t niv = iv;
281  AmrIntVect_t n2iv = iv;
282 
283  scalar_t sign = 1.0;
284 
285  if ( iv[dir] == -1 ) {
286  // lower boundary
287  niv[dir] = 0;
288  n2iv[dir] = 1;
289 
290  sign = -1.0;
291 
292  } else {
293  // upper boundary
294  niv[dir] = nr[dir] - 1;
295  n2iv[dir] = nr[dir] - 2;
296  }
297 
298  // correct cell size
299  scalar_t h = mglevel->cellSize(dir);
300 
301  // coordinate of inner cell
302  scalar_t x = this->coordinate_m(niv, 0, mglevel, nr) + sign * dist_m * h;
303  scalar_t y = this->coordinate_m(niv, 1, mglevel, nr) + sign * dist_m * h;
304 #if AMREX_SPACEDIM == 3
305  scalar_t z = this->coordinate_m(niv, 2, mglevel, nr) + sign * dist_m * h;
306 #endif
307  scalar_t r = std::sqrt( AMREX_D_TERM(x * x, + y * y, + z * z) );
308 
309 // scalar_t d = dist_m * nr[dir] * h; // + r;
310  scalar_t d = r;
311 
312  map[mglevel->serialize(niv)] += 2.0 * (d * d - h * h) / ( d * d + 2.0 * h * d ) * value;
313  map[mglevel->serialize(n2iv)] += (2.0 * h - d) / (2.0 * h + d) * value;
314 }
315 
316 
317 template <class Level>
319  const lo_t& dir,
320  umap_t& map,
321  const scalar_t& value,
322  Level* mglevel,
323  const go_t* nr)
324 {
325  AmrIntVect_t niv = iv;
326  AmrIntVect_t n1iv = iv;
327  AmrIntVect_t n2iv = iv;
328  AmrIntVect_t n3iv = iv;
329  AmrIntVect_t n4iv = iv;
330 
331  scalar_t sign = 1.0;
332 
333  if ( iv[dir] == -1 ) {
334  // lower boundary
335  niv[dir] = 0;
336  n1iv[dir] = 1;
337  n2iv[dir] = 2;
338  n3iv[dir] = 3;
339  n4iv[dir] = 4;
340 
341 
342 
343  } else {
344  // upper boundary
345  niv[dir] = nr[dir] - 1;
346  n1iv[dir] = nr[dir] - 2;
347  n2iv[dir] = nr[dir] - 3;
348  n3iv[dir] = nr[dir] - 4;
349  n4iv[dir] = nr[dir] - 5;
350 
351  sign *= -1.0;
352  }
353 
354  scalar_t h = mglevel->cellSize(dir);
355 
356 // scalar_t d = dist_m * nr[dir] * h; // + r;
357 
358  // coordinate of inner cell
359  scalar_t x = this->coordinate_m(niv, 0, mglevel, nr);
360  scalar_t y = this->coordinate_m(niv, 1, mglevel, nr);
361 #if AMREX_SPACEDIM == 3
362  scalar_t z = this->coordinate_m(niv, 2, mglevel, nr);
363 #endif
364 
365  scalar_t d = std::sqrt( AMREX_D_TERM(x * x, + y * y, + z * z) );
366 
367  scalar_t hd = h + d;
368 
369  map[mglevel->serialize(niv)] += (2.0 * d / hd - 2.0 * h * h / (3.0 * d * hd) + sign * 5.0 * d * d / (18.0 * h * hd)) * value;
370  map[mglevel->serialize(n1iv)] += (h / hd - d / hd - sign * d * d / ( hd * h) ) * value;
371  map[mglevel->serialize(n2iv)] += sign * 4.0 * d * d / (3.0 * h * hd) * value;
372  map[mglevel->serialize(n3iv)] -= sign * 7.0 * d * d / (9.0 * h * hd) * value;
373  map[mglevel->serialize(n4iv)] += sign * d * d / (6.0 * h * hd) * value;
374 }
375 
376 
377 template <class Level>
380  const lo_t& dir,
381  Level* mglevel,
382  const go_t* nr)
383 {
384  /*
385  * subtract / add half cell length in order to get
386  * cell centered position
387  */
388  scalar_t h = mglevel->cellSize(dir);
389 
390  scalar_t lower = mglevel->geom.ProbLo(dir) + 0.5 * h;
391  scalar_t upper = mglevel->geom.ProbHi(dir) - 0.5 * h;
392 
393  scalar_t m = (upper - lower) / ( nr[dir] - 1 );
394 
395  return m * iv[dir] + lower;
396 }
397 
398 #endif
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
const int nr
Definition: ClassicRandom.h:24
FnArg FnReal sign(a))
amrex::IntVect AmrIntVect_t
Definition: AmrDefs.h:48
double scalar_t
Level::umap_t umap_t
Definition: AmrBoundary.h:32
Level::scalar_t scalar_t
Definition: AmrBoundary.h:35
Level::lo_t lo_t
Definition: AmrBoundary.h:33
Level::go_t go_t
Definition: AmrBoundary.h:34
amr::AmrIntVect_t AmrIntVect_t
Definition: AmrBoundary.h:37
void abc2_m(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
amr::AmrIntVect_t AmrIntVect_t
Level::go_t go_t
void robin_m(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
void abc1_m(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
Level::lo_t lo_t
void apply(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
Level::umap_t umap_t
void abc3_m(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
Level::scalar_t scalar_t
scalar_t coordinate_m(const AmrIntVect_t &iv, const lo_t &dir, Level *mglevel, const go_t *nr)
void abc0_m(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
The base class for all OPAL exceptions.
Definition: OpalException.h:28