OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
29template <class Level>
30class AmrOpenBoundary : public AmrBoundary<Level> {
31
32public:
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
39public:
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
62private:
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
126template <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
169template <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
201template <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
225template <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
272template <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
317template <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
377template <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
const int nr
Definition: ClassicRandom.h:24
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
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