OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
AmrOpenBoundary.h
Go to the documentation of this file.
1 #ifndef AMR_OPEN_BOUNDARY_H
2 #define AMR_OPEN_BOUNDARY_H
3 
4 #include "AmrBoundary.h"
5 
7 
8 template <class Level>
9 class AmrOpenBoundary : public AmrBoundary<Level> {
10 
11 public:
12  typedef typename Level::umap_t umap_t;
13  typedef typename Level::lo_t lo_t;
14  typedef typename Level::go_t go_t;
15  typedef typename Level::scalar_t scalar_t;
17 
18 public:
19 
21  : AmrBoundary<Level>(4)
22  , order_m(ABC::Robin)
23  , dist_m(1.7)
24  { }
25 
26  void apply(const AmrIntVect_t& iv,
27  const lo_t& dir,
28  umap_t& map,
29  const scalar_t& value,
30  Level* mglevel,
31  const go_t* nr);
32 
33  enum ABC {
39  };
40 
41 private:
42  int order_m;
43  double dist_m;
44 
46  const lo_t& dir,
47  Level* mglevel,
48  const go_t* nr);
49 
53  void robin_m(const AmrIntVect_t& iv,
54  const lo_t& dir,
55  umap_t& map,
56  const scalar_t& value,
57  Level* mglevel,
58  const go_t* nr);
59 
63  void abc0_m(const AmrIntVect_t& iv,
64  const lo_t& dir,
65  umap_t& map,
66  const scalar_t& value,
67  Level* mglevel,
68  const go_t* nr);
69 
70 
74  void abc1_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 abc2_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 abc3_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 
102 };
103 
104 
105 template <class Level>
107  const lo_t& dir,
108  umap_t& map,
109  const scalar_t& value,
110  Level* mglevel,
111  const go_t* nr)
112 {
113  switch ( order_m ) {
114  case ABC::Third:
115  {
116  this->abc3_m(iv, dir, map, value, mglevel, nr);
117  break;
118  }
119  case ABC::Second:
120  {
121  this->abc2_m(iv, dir, map, value, mglevel, nr);
122  break;
123  }
124  case ABC::First:
125  {
126  this->abc1_m(iv, dir, map, value, mglevel, nr);
127  break;
128  }
129  case ABC::Zeroth:
130  {
131  this->abc0_m(iv, dir, map, value, mglevel, nr);
132  break;
133  }
134  case ABC::Robin:
135  {
136  this->robin_m(iv, dir, map, value, mglevel, nr);
137  break;
138  }
139  default:
140  {
141  throw OpalException("AmrOpenBoundary<Level>::apply()",
142  "Order not supported.");
143  }
144  }
145 }
146 
147 
148 template <class Level>
150  const lo_t& dir,
151  umap_t& map,
152  const scalar_t& value,
153  Level* mglevel,
154  const go_t* nr)
155 {
156  AmrIntVect_t niv = iv;
157  AmrIntVect_t n2iv = iv;
158 
159  if ( iv[dir] == -1 ) {
160  // lower boundary
161  niv[dir] = 0;
162  n2iv[dir] = 1;
163  } else {
164  // upper boundary
165  niv[dir] = nr[dir] - 1;
166  n2iv[dir] = nr[dir] - 2;
167  }
168 
169  // correct cell size
170  scalar_t h = mglevel->cellSize(dir);
171 
172  // artificial distance
173  scalar_t d = dist_m;;
174 
175  map[mglevel->serialize(niv)] -= 2.0 * h / d * value;
176  map[mglevel->serialize(n2iv)] += value;
177 }
178 
179 
180 template <class Level>
182  const lo_t& dir,
183  umap_t& map,
184  const scalar_t& value,
185  Level* mglevel,
186  const go_t* nr)
187 {
188  // ABC0 == Dirichlet BC
189  AmrIntVect_t niv = iv;
190 
191  if ( iv[dir] == -1 ) {
192  // lower boundary
193  niv[dir] = 0;
194 
195  } else {
196  // upper boundary
197  niv[dir] = nr[dir] - 1;
198  }
199 
200  map[mglevel->serialize(niv)] -= value;
201 }
202 
203 
204 template <class Level>
206  const lo_t& dir,
207  umap_t& map,
208  const scalar_t& value,
209  Level* mglevel,
210  const go_t* nr)
211 {
212  // ABC1 == Robin BC (with normal derivatives) (i.e. Dirichlet BC + Neumann BC)
213  AmrIntVect_t niv = iv;
214  AmrIntVect_t n2iv = iv;
215 
216  scalar_t sign = 1.0;
217 
218  if ( iv[dir] == -1 ) {
219  // lower boundary
220  niv[dir] = 0;
221  n2iv[dir] = 1;
222 
223  sign = -1.0;
224 
225  } else {
226  // upper boundary
227  niv[dir] = nr[dir] - 1;
228  n2iv[dir] = nr[dir] - 2;
229  }
230 
231  // correct cell size
232  scalar_t h = mglevel->cellSize(dir);
233 
234  // coordinate of inner cell
235  scalar_t x = this->coordinate_m(niv, 0, mglevel, nr) + sign * dist_m * h;
236  scalar_t y = this->coordinate_m(niv, 1, mglevel, nr) + sign * dist_m * h;
237 #if AMREX_SPACEDIM == 3
238  scalar_t z = this->coordinate_m(niv, 2, mglevel, nr) + sign * dist_m * h;
239 #endif
240  scalar_t r = std::sqrt( AMREX_D_TERM(x * x, + y * y, + z * z) );
241 
242 // // artificial distance
243 // scalar_t d = dist_m * nr[dir] * h; // + r;
244  scalar_t d = r;
245 
246  map[mglevel->serialize(niv)] -= 2.0 * h / d * value;
247  map[mglevel->serialize(n2iv)] += value;
248 }
249 
250 
251 template <class Level>
253  const lo_t& dir,
254  umap_t& map,
255  const scalar_t& value,
256  Level* mglevel,
257  const go_t* nr)
258 {
259  AmrIntVect_t niv = iv;
260  AmrIntVect_t n2iv = iv;
261 
262  scalar_t sign = 1.0;
263 
264  if ( iv[dir] == -1 ) {
265  // lower boundary
266  niv[dir] = 0;
267  n2iv[dir] = 1;
268 
269  sign = -1.0;
270 
271  } else {
272  // upper boundary
273  niv[dir] = nr[dir] - 1;
274  n2iv[dir] = nr[dir] - 2;
275  }
276 
277  // correct cell size
278  scalar_t h = mglevel->cellSize(dir);
279 
280  // coordinate of inner cell
281  scalar_t x = this->coordinate_m(niv, 0, mglevel, nr) + sign * dist_m * h;
282  scalar_t y = this->coordinate_m(niv, 1, mglevel, nr) + sign * dist_m * h;
283 #if AMREX_SPACEDIM == 3
284  scalar_t z = this->coordinate_m(niv, 2, mglevel, nr) + sign * dist_m * h;
285 #endif
286  scalar_t r = std::sqrt( AMREX_D_TERM(x * x, + y * y, + z * z) );
287 
288 // scalar_t d = dist_m * nr[dir] * h; // + r;
289  scalar_t d = r;
290 
291  map[mglevel->serialize(niv)] += 2.0 * (d * d - h * h) / ( d * d + 2.0 * h * d ) * value;
292  map[mglevel->serialize(n2iv)] += (2.0 * h - d) / (2.0 * h + d) * value;
293 }
294 
295 
296 template <class Level>
298  const lo_t& dir,
299  umap_t& map,
300  const scalar_t& value,
301  Level* mglevel,
302  const go_t* nr)
303 {
304  AmrIntVect_t niv = iv;
305  AmrIntVect_t n1iv = iv;
306  AmrIntVect_t n2iv = iv;
307  AmrIntVect_t n3iv = iv;
308  AmrIntVect_t n4iv = iv;
309 
310  scalar_t sign = 1.0;
311 
312  if ( iv[dir] == -1 ) {
313  // lower boundary
314  niv[dir] = 0;
315  n1iv[dir] = 1;
316  n2iv[dir] = 2;
317  n3iv[dir] = 3;
318  n4iv[dir] = 4;
319 
320 
321 
322  } else {
323  // upper boundary
324  niv[dir] = nr[dir] - 1;
325  n1iv[dir] = nr[dir] - 2;
326  n2iv[dir] = nr[dir] - 3;
327  n3iv[dir] = nr[dir] - 4;
328  n4iv[dir] = nr[dir] - 5;
329 
330  sign *= -1.0;
331  }
332 
333  scalar_t h = mglevel->cellSize(dir);
334 
335 // scalar_t d = dist_m * nr[dir] * h; // + r;
336 
337  // coordinate of inner cell
338  scalar_t x = this->coordinate_m(niv, 0, mglevel, nr);
339  scalar_t y = this->coordinate_m(niv, 1, mglevel, nr);
340 #if AMREX_SPACEDIM == 3
341  scalar_t z = this->coordinate_m(niv, 2, mglevel, nr);
342 #endif
343 
344  scalar_t d = std::sqrt( AMREX_D_TERM(x * x, + y * y, + z * z) );
345 
346  scalar_t hd = h + d;
347 
348  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;
349  map[mglevel->serialize(n1iv)] += (h / hd - d / hd - sign * d * d / ( hd * h) ) * value;
350  map[mglevel->serialize(n2iv)] += sign * 4.0 * d * d / (3.0 * h * hd) * value;
351  map[mglevel->serialize(n3iv)] -= sign * 7.0 * d * d / (9.0 * h * hd) * value;
352  map[mglevel->serialize(n4iv)] += sign * d * d / (6.0 * h * hd) * value;
353 }
354 
355 
356 template <class Level>
359  const lo_t& dir,
360  Level* mglevel,
361  const go_t* nr)
362 {
363  /*
364  * subtract / add half cell length in order to get
365  * cell centered position
366  */
367  scalar_t h = mglevel->cellSize(dir);
368 
369  scalar_t lower = mglevel->geom.ProbLo(dir) + 0.5 * h;
370  scalar_t upper = mglevel->geom.ProbHi(dir) - 0.5 * h;
371 
372  scalar_t m = (upper - lower) / ( nr[dir] - 1 );
373 
374  return m * iv[dir] + lower;
375 }
376 
377 #endif
amr::AmrIntVect_t AmrIntVect_t
Definition: AmrBoundary.h:17
Level::lo_t lo_t
Definition: AmrBoundary.h:13
Level::umap_t umap_t
Definition: AmrBoundary.h:12
Level::umap_t umap_t
scalar_t coordinate_m(const AmrIntVect_t &iv, const lo_t &dir, Level *mglevel, const go_t *nr)
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Level::lo_t lo_t
const int nr
Definition: ClassicRandom.h:24
amrex::IntVect AmrIntVect_t
Definition: AmrDefs.h:28
Level::go_t go_t
Definition: AmrBoundary.h:14
void apply(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, Level *mglevel, const go_t *nr)
void abc2_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
void abc3_m(const AmrIntVect_t &iv, const lo_t &dir, umap_t &map, const scalar_t &value, 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)
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)
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
FnArg FnReal sign(a))
amr::AmrIntVect_t AmrIntVect_t
Level::scalar_t scalar_t
Definition: AmrBoundary.h:15
double scalar_t
Level::go_t go_t