Block-Structured AMR Software Framework
Loading...
Searching...
No Matches
AMReX_PhysBCFunct.H
Go to the documentation of this file.
1#ifndef AMREX_PhysBCFunct_H_
2#define AMREX_PhysBCFunct_H_
3#include <AMReX_Config.H>
4
5#include <AMReX_BCRec.H>
6#include <AMReX_Geometry.H>
7#include <AMReX_MultiFab.H>
8#include <AMReX_ArrayLim.H>
9#include <AMReX_FilCC_C.H>
10#include <AMReX_FilND_C.H>
11#include <AMReX_FilFC_C.H>
12#include <AMReX_TypeTraits.H>
13
14namespace amrex {
15
16extern "C"
17{
18 using BndryFuncDefault = void (*)(Real* data, AMREX_ARLIM_P(lo), AMREX_ARLIM_P(hi),
19 const int* dom_lo, const int* dom_hi,
20 const Real* dx, const Real* grd_lo,
21 const Real* time, const int* bc);
22 using BndryFunc3DDefault = void (*)(Real* data, const int* lo, const int* hi,
23 const int* dom_lo, const int* dom_hi,
24 const Real* dx, const Real* grd_lo,
25 const Real* time, const int* bc);
26}
27
28using UserFillBox = void (*)(Box const& bx, Array4<Real> const& dest,
29 int dcomp, int numcomp,
30 GeometryData const& geom, Real time,
31 const BCRec* bcr, int bcomp,
32 int orig_comp);
33
36{
37public:
38 BndryFuncArray () noexcept = default;
39 BndryFuncArray (BndryFuncDefault inFunc) noexcept : m_func(inFunc) {}
40 BndryFuncArray (BndryFunc3DDefault inFunc) noexcept : m_func3D(inFunc) {}
41
42 void operator() (Box const& bx, FArrayBox& dest,
43 int dcomp, int numcomp,
44 Geometry const& geom, Real time,
45 const Vector<BCRec>& bcr, int bcomp,
46 int orig_comp);
47
48 [[nodiscard]] bool RunOnGPU () const noexcept { return m_run_on_gpu; }
49// void setRunOnGPU (bool b) noexcept { m_run_on_gpu = b; }
50
51protected:
54 bool m_run_on_gpu = false;
55};
56
62template <class F>
64{
65public:
66 GpuBndryFuncFab () = default;
67 GpuBndryFuncFab (F const& a_f) : m_user_f(a_f) {}
68 GpuBndryFuncFab (F&& a_f) : m_user_f(std::move(a_f)) {}
69
70 void operator() (Box const& bx, FArrayBox& dest,
71 int dcomp, int numcomp,
72 Geometry const& geom, Real time,
73 const Vector<BCRec>& bcr, int bcomp,
74 int orig_comp);
75
76 template <class FF>
77 void ccfcdoit (Box const& bx, FArrayBox& dest,
78 int dcomp, int numcomp,
79 Geometry const& geom, Real time,
80 const Vector<BCRec>& bcr, int bcomp,
81 int orig_comp, FF const& fillfunc);
82
83 void nddoit (Box const& bx, FArrayBox& dest,
84 int dcomp, int numcomp,
85 Geometry const& geom, Real time,
86 const Vector<BCRec>& bcr, int bcomp,
87 int orig_comp);
88
89protected:
91};
92
94{
97 int, int, amrex::GeometryData const&, amrex::Real,
98 const amrex::BCRec*, int, int) const
99 {}
100};
101
104{
105public:
106 CpuBndryFuncFab () = default;
108
109 void operator() (Box const& bx, FArrayBox& dest,
110 int dcomp, int numcomp,
111 Geometry const& geom, Real time,
112 const Vector<BCRec>& bcr, int bcomp,
113 int orig_comp);
114
115protected:
117};
118
120{
121public:
122 void operator() (MultiFab& /*mf*/, int /*dcomp*/, int /*ncomp*/, IntVect const& /*nghost*/,
123 Real /*time*/, int /*bccomp*/) {}
124};
125
127{
128public:
129
130 PhysBCFunctUseCoarseGhost (IntVect const& a_fp1_src_ghost)
131 : fp1_src_ghost(a_fp1_src_ghost) {}
132
133 template <typename MF, typename Interp>
134 PhysBCFunctUseCoarseGhost (MF const& cmf, IntVect const& a_nghost,
135 IntVect const& a_nghost_outside_domain,
136 IntVect const& ratio, Interp* mapper)
137 : nghost(a_nghost),
138 nghost_outside_domain(a_nghost_outside_domain),
139 cghost(cmf.nGrowVect())
140 {
141 IndexType typ = cmf.ixType();
142
143 const auto& coarsener = mapper->BoxCoarsener(ratio);
144 Box tmp(-nghost, IntVect(32), typ);
145 Box tmp2 = coarsener.doit(tmp);
146 src_ghost = -tmp2.smallEnd();
147
148 tmp = Box(-nghost_outside_domain, IntVect(32), typ);
149 tmp2 = coarsener.doit(tmp);
151
154 }
155
156 void operator() (MultiFab& /*mf*/, int /*dcomp*/, int /*ncomp*/, IntVect const& /*nghost*/,
157 Real /*time*/, int /*bccomp*/) {}
158
159 IntVect nghost; // # of fine ghosts inside domain to be filled
160
161 IntVect nghost_outside_domain; // # of fine ghosts outside domain to be filled
162
163 // This is the number of coarse ghost cells needed to interpolate fine
164 // ghost cells inside the domain
166
167 // This is the number of coarse ghost cells needed to interpolate
168 // nghost_outside_domain fine ghost cells outside the domain
170
171 // This is the minimum number of ghost cells needed in coarse MF
173
174 IntVect fp1_src_ghost; // Used to pass information into FillPatchSingleLevel
175};
176
177template <class F>
179{
180public:
181 PhysBCFunct () = default;
182
183 PhysBCFunct (const Geometry& geom, const Vector<BCRec>& bcr, F const& f)
184 : m_geom(geom), m_bcr(bcr), m_f(f)
185 {}
186
187 PhysBCFunct (const Geometry& geom, const Vector<BCRec>& bcr, F&& f)
188 : m_geom(geom), m_bcr(bcr), m_f(std::move(f))
189 {}
190
191 void define (const Geometry& geom, const Vector<BCRec>& bcr, F const& f) {
192 m_geom = geom; m_bcr = bcr; m_f = f;
193 }
194
195 void define (const Geometry& geom, const Vector<BCRec>& bcr, F&& f) {
196 m_geom = geom; m_bcr = bcr; m_f = std::move(f);
197 }
198
199 void operator() (MultiFab& mf, int icomp, int ncomp, IntVect const& nghost,
200 Real time, int bccomp)
201 {
202 if (m_geom.isAllPeriodic()) { return; }
203
204 BL_PROFILE("PhysBCFunct::()");
205
206 AMREX_ASSERT(nghost.allLE(mf.nGrowVect()));
207
209 const Box& domain = amrex::convert(m_geom.Domain(), mf.boxArray().ixType());
210 Box gdomain = domain;
211 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
212 if (m_geom.isPeriodic(i)) {
213 gdomain.grow(i, nghost[i]);
214 }
215 }
216
217#ifdef AMREX_USE_OMP
218#pragma omp parallel if (Gpu::notInLaunchRegion())
219#endif
220 {
221 Vector<BCRec> bcrs(ncomp);
222 for (MFIter mfi(mf); mfi.isValid(); ++mfi)
223 {
224 FArrayBox& dest = mf[mfi];
225 const Box& bx = grow(mfi.validbox(),nghost);
226
230 if (!gdomain.contains(bx))
231 {
233 amrex::setBC(bx, domain, bccomp, 0, ncomp, m_bcr, bcrs);
234
236 m_f(bx, dest, icomp, ncomp, m_geom, time, bcrs, 0, bccomp);
237 }
238 }
239 }
240 }
241
242 // For backward compatibility
243 void FillBoundary (MultiFab& mf, int icomp, int ncomp, IntVect const& nghost,
244 Real time, int bccomp) {
245 // NOLINTNEXTLINE(readability-suspicious-call-argument)
246 this->operator()(mf,icomp,ncomp,nghost,time,bccomp);
247 }
248
249private:
250 Geometry m_geom;
251 Vector<BCRec> m_bcr;
252 F m_f;
253};
254
255template <class F>
256void
258 int dcomp, int numcomp,
259 Geometry const& geom, Real time,
260 const Vector<BCRec>& bcr, int bcomp,
261 int orig_comp)
262{
263 if (bx.ixType().cellCentered()) {
264 ccfcdoit(bx,dest,dcomp,numcomp,geom,time,bcr,bcomp,orig_comp, FilccCell{});
265 } else if (bx.ixType().nodeCentered()) {
266 nddoit(bx,dest,dcomp,numcomp,geom,time,bcr,bcomp,orig_comp);
267 } else {
268 ccfcdoit(bx,dest,dcomp,numcomp,geom,time,bcr,bcomp,orig_comp, FilfcFace{});
269 }
270}
271
272template <class F>
273void
275 int dcomp, int numcomp,
276 Geometry const& geom, Real time,
277 const Vector<BCRec>& bcr, int bcomp,
278 int orig_comp)
279{
280 const IntVect& len = bx.length();
281
282 Box const& domain = amrex::convert(geom.Domain(),IntVect::TheNodeVector());
283 Box gdomain = domain;
284 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
285 if (geom.isPeriodic(idim)) {
286 gdomain.grow(idim,len[idim]);
287 }
288 }
289
290 if (gdomain.contains(bx)) { return; }
291
292 Array4<Real> const& fab = dest.array();
293 const auto geomdata = geom.data();
294
295 AsyncArray<BCRec> bcr_aa(bcr.data()+bcomp, numcomp);
296 BCRec* bcr_p = bcr_aa.data();
297
298 const auto f_user = m_user_f;
299
300 // xlo
301 if (!geom.isPeriodic(0) && bx.smallEnd(0) < domain.smallEnd(0)) {
302 Box bndry = bx;
303 int dxlo = domain.smallEnd(0);
304 bndry.setBig(0,dxlo-1);
305 amrex::ParallelFor(bndry, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
306 {
307 for (int n = dcomp; n < dcomp+numcomp; ++n) {
308 fab(i,j,k,n) = fab(dxlo,j,k,n);
309 }
310 f_user(IntVect(AMREX_D_DECL(i,j,k)), fab, dcomp, numcomp, geomdata, time,
311 bcr_p, 0, orig_comp);
312 });
313 }
314
315 // xhi
316 if (!geom.isPeriodic(0) && bx.bigEnd(0) > domain.bigEnd(0)) {
317 Box bndry = bx;
318 int dxhi = domain.bigEnd(0);
319 bndry.setSmall(0,dxhi+1);
320 amrex::ParallelFor(bndry, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
321 {
322 for (int n = dcomp; n < dcomp+numcomp; ++n) {
323 fab(i,j,k,n) = fab(dxhi,j,k,n);
324 }
325 f_user(IntVect(AMREX_D_DECL(i,j,k)), fab, dcomp, numcomp, geomdata, time,
326 bcr_p, 0, orig_comp);
327 });
328 }
329
330#if (AMREX_SPACEDIM >= 2)
331 // ylo
332 if (!geom.isPeriodic(1) && bx.smallEnd(1) < domain.smallEnd(1)) {
333 Box bndry = bx;
334 int dylo = domain.smallEnd(1);
335 bndry.setBig(1,dylo-1);
336 amrex::ParallelFor(bndry, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
337 {
338 for (int n = dcomp; n < dcomp+numcomp; ++n) {
339 fab(i,j,k,n) = fab(i,dylo,k,n);
340 }
341 f_user(IntVect(AMREX_D_DECL(i,j,k)), fab, dcomp, numcomp, geomdata, time,
342 bcr_p, 0, orig_comp);
343 });
344 }
345
346 // yhi
347 if (!geom.isPeriodic(1) && bx.bigEnd(1) > domain.bigEnd(1)) {
348 Box bndry = bx;
349 int dyhi = domain.bigEnd(1);
350 bndry.setSmall(1,dyhi+1);
351 amrex::ParallelFor(bndry, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
352 {
353 for (int n = dcomp; n < dcomp+numcomp; ++n) {
354 fab(i,j,k,n) = fab(i,dyhi,k,n);
355 }
356 f_user(IntVect(AMREX_D_DECL(i,j,k)), fab, dcomp, numcomp, geomdata, time,
357 bcr_p, 0, orig_comp);
358 });
359 }
360#endif
361
362#if (AMREX_SPACEDIM == 3)
363 // zlo
364 if (!geom.isPeriodic(2) && bx.smallEnd(2) < domain.smallEnd(2)) {
365 Box bndry = bx;
366 int dzlo = domain.smallEnd(2);
367 bndry.setBig(2,dzlo-1);
368 amrex::ParallelFor(bndry, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
369 {
370 for (int n = dcomp; n < dcomp+numcomp; ++n) {
371 fab(i,j,k,n) = fab(i,j,dzlo,n);
372 }
373 f_user(IntVect(AMREX_D_DECL(i,j,k)), fab, dcomp, numcomp, geomdata, time,
374 bcr_p, 0, orig_comp);
375 });
376 }
377
378 // zhi
379 if (!geom.isPeriodic(2) && bx.bigEnd(2) > domain.bigEnd(2)) {
380 Box bndry = bx;
381 int dzhi = domain.bigEnd(2);
382 bndry.setSmall(2,dzhi+1);
383 amrex::ParallelFor(bndry, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
384 {
385 for (int n = dcomp; n < dcomp+numcomp; ++n) {
386 fab(i,j,k,n) = fab(i,j,dzhi,n);
387 }
388 f_user(IntVect(AMREX_D_DECL(i,j,k)), fab, dcomp, numcomp, geomdata, time,
389 bcr_p, 0, orig_comp);
390 });
391 }
392#endif
393}
394
395template <class F>
396template <class FF>
397void
399 int dcomp, int numcomp,
400 Geometry const& geom, Real time,
401 const Vector<BCRec>& bcr, int bcomp,
402 int orig_comp, FF const& fillfunc)
403{
404 const IntVect& len = bx.length();
405
406 IndexType idxType = bx.ixType();
407 Box const& domain = amrex::convert(geom.Domain(),idxType);
408 Box gdomain = domain;
409 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
410 if (geom.isPeriodic(idim)) {
411 gdomain.grow(idim,len[idim]);
412 }
413 }
414
415 if (gdomain.contains(bx)) { return; }
416
417 Array4<Real> const& fab = dest.array();
418 const auto geomdata = geom.data();
419
420#ifdef AMREX_USE_GPU
421 AsyncArray<BCRec> bcr_aa(bcr.data()+bcomp, numcomp);
422 BCRec* bcr_p = bcr_aa.data();
423
424 const auto f_user = m_user_f;
425
426 // fill on the faces first
427 {
428 Array<Box,2*AMREX_SPACEDIM> dom_face_boxes
429 = { AMREX_D_DECL(amrex::convert(amrex::adjCellLo(gdomain, 0, len[0]),idxType),
430 amrex::convert(amrex::adjCellLo(gdomain, 1, len[1]),idxType),
431 amrex::convert(amrex::adjCellLo(gdomain, 2, len[2]),idxType)),
432 AMREX_D_DECL(amrex::convert(amrex::adjCellHi(gdomain, 0, len[0]),idxType),
433 amrex::convert(amrex::adjCellHi(gdomain, 1, len[1]),idxType),
434 amrex::convert(amrex::adjCellHi(gdomain, 2, len[2]),idxType)) };
435
436 Vector<Box> face_boxes;
437 for (const Box& b : dom_face_boxes) {
438 Box tmp = b & bx;
439 if (tmp.ok()) { face_boxes.push_back(tmp); }
440 }
441 const int n_face_boxes = face_boxes.size();
442 // For non-cell-centered data the boxes share nodes, so they must be
443 // launched separately to avoid races, like in the CPU version below.
444 if (n_face_boxes == 1 || ! idxType.cellCentered()) {
445 for (const Box& b : face_boxes) {
447 [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
448 {
450 IntVect const idx(AMREX_D_DECL(i,j,k));
451 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
452 f_user(idx, fab, dcomp, numcomp, geomdata, time,
453 bcr_p, 0, orig_comp);
454 });
455 }
456 } else if (n_face_boxes > 1) {
457 AsyncArray<Box> face_boxes_aa(face_boxes.data(), n_face_boxes);
458 Box* boxes_p = face_boxes_aa.data();
459 Long ncounts = 0;
460 for (const auto& b : face_boxes) {
461 ncounts += b.numPts();
462 }
463 amrex::ParallelFor(ncounts,
464 [=] AMREX_GPU_DEVICE (Long icount) noexcept
465 {
466 const auto& idx = getCell(boxes_p, n_face_boxes, icount);
467 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
468 f_user(idx, fab, dcomp, numcomp, geomdata, time,
469 bcr_p, 0, orig_comp);
470 });
471 }
472 }
473
474#if (AMREX_SPACEDIM >= 2)
475 // fill on the box edges
476 {
477#if (AMREX_SPACEDIM == 2)
478 Array<Box,4> dom_edge_boxes
479 = {{ amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
480 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType),
481 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
482 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType) }};
483#else
484 Array<Box,12> dom_edge_boxes
485 = {{ amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
486 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType),
487 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
488 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType),
489 //
490 amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),2,len[2]),idxType),
491 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),2,len[2]),idxType),
492 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),2,len[2]),idxType),
493 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),2,len[2]),idxType),
494 //
495 amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,1,len[1]),2,len[2]),idxType),
496 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,1,len[1]),2,len[2]),idxType),
497 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,1,len[1]),2,len[2]),idxType),
498 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,1,len[1]),2,len[2]),idxType) }};
499#endif
500 Vector<Box> edge_boxes;
501 for (const Box& b : dom_edge_boxes) {
502 Box tmp = b & bx;
503 if (tmp.ok()) { edge_boxes.push_back(tmp); }
504 }
505 const int n_edge_boxes = edge_boxes.size();
506 // For non-cell-centered data the boxes share nodes, so they must be
507 // launched separately to avoid races, like in the CPU version below.
508 if (n_edge_boxes == 1 || ! idxType.cellCentered()) {
509 for (const Box& b : edge_boxes) {
511 [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
512 {
514 IntVect const idx(AMREX_D_DECL(i,j,k));
515 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
516 f_user(idx, fab, dcomp, numcomp, geomdata, time,
517 bcr_p, 0, orig_comp);
518 });
519 }
520 } else if (n_edge_boxes > 1) {
521 AsyncArray<Box> edge_boxes_aa(edge_boxes.data(), n_edge_boxes);
522 Box* boxes_p = edge_boxes_aa.data();
523 Long ncounts = 0;
524 for (const auto& b : edge_boxes) {
525 ncounts += b.numPts();
526 }
527 amrex::ParallelFor(ncounts,
528 [=] AMREX_GPU_DEVICE (Long icount) noexcept
529 {
530 const auto& idx = getCell(boxes_p, n_edge_boxes, icount);
531 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
532 f_user(idx, fab, dcomp, numcomp, geomdata, time,
533 bcr_p, 0, orig_comp);
534 });
535 }
536 }
537#endif
538
539#if (AMREX_SPACEDIM == 3)
540 // fill on corners
541 {
542 Array<Box,8> dom_corner_boxes
543 = {{ amrex::convert(amrex::adjCellLo(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
544 amrex::convert(amrex::adjCellLo(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
545 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
546 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
547 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
548 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
549 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
550 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType) }};
551
552 Vector<Box> corner_boxes;
553 for (const Box& b : dom_corner_boxes) {
554 Box tmp = b & bx;
555 if (tmp.ok()) { corner_boxes.push_back(tmp); }
556 }
557 const int n_corner_boxes = corner_boxes.size();
558 if (n_corner_boxes == 1) {
559 amrex::ParallelFor(corner_boxes[0],
560 [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
561 {
562 IntVect const idx(AMREX_D_DECL(i,j,k));
563 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
564 f_user(idx, fab, dcomp, numcomp, geomdata, time,
565 bcr_p, 0, orig_comp);
566 });
567 } else if (n_corner_boxes > 1) {
568 AsyncArray<Box> corner_boxes_aa(corner_boxes.data(), n_corner_boxes);
569 Box* boxes_p = corner_boxes_aa.data();
570 Long ncounts = 0;
571 for (const auto& b : corner_boxes) {
572 ncounts += b.numPts();
573 }
574 amrex::ParallelFor(ncounts,
575 [=] AMREX_GPU_DEVICE (Long icount) noexcept
576 {
577 const auto& idx = getCell(boxes_p, n_corner_boxes, icount);
578 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
579 f_user(idx, fab, dcomp, numcomp, geomdata, time,
580 bcr_p, 0, orig_comp);
581 });
582 }
583 }
584#endif
585
586#else
587 BCRec const* bcr_p = bcr.data()+bcomp;
588
589 const auto& f_user = m_user_f;
590
591 // fill on the box faces first
592 {
593 Array<Box,2*AMREX_SPACEDIM> dom_face_boxes
594 = {{ AMREX_D_DECL(amrex::convert(amrex::adjCellLo(gdomain, 0, len[0]),idxType),
595 amrex::convert(amrex::adjCellLo(gdomain, 1, len[1]),idxType),
596 amrex::convert(amrex::adjCellLo(gdomain, 2, len[2]),idxType)),
597 AMREX_D_DECL(amrex::convert(amrex::adjCellHi(gdomain, 0, len[0]),idxType),
598 amrex::convert(amrex::adjCellHi(gdomain, 1, len[1]),idxType),
599 amrex::convert(amrex::adjCellHi(gdomain, 2, len[2]),idxType)) }};
600
601 for (const Box& b : dom_face_boxes) {
602 Box tmp = b & bx;
603 amrex::For(tmp, [=] (int i, int j, int k) noexcept
604 {
606 IntVect const idx(AMREX_D_DECL(i,j,k));
607 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
608 f_user(idx, fab, dcomp, numcomp, geomdata, time,
609 bcr_p, 0, orig_comp);
610 });
611 }
612 }
613
614#if (AMREX_SPACEDIM >= 2)
615 // fill on the box edges
616 {
617#if (AMREX_SPACEDIM == 2)
618 Array<Box,4> dom_edge_boxes
619 = {{ amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
620 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType),
621 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
622 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType) }};
623#else
624 Array<Box,12> dom_edge_boxes
625 = {{ amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
626 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType),
627 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),idxType),
628 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),idxType),
629 //
630 amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),2,len[2]),idxType),
631 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),2,len[2]),idxType),
632 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),2,len[2]),idxType),
633 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),2,len[2]),idxType),
634 //
635 amrex::convert(amrex::adjCellLo(amrex::adjCellLo(gdomain,1,len[1]),2,len[2]),idxType),
636 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(gdomain,1,len[1]),2,len[2]),idxType),
637 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(gdomain,1,len[1]),2,len[2]),idxType),
638 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(gdomain,1,len[1]),2,len[2]),idxType) }};
639#endif
640
641 for (const Box& b : dom_edge_boxes) {
642 Box tmp = b & bx;
643 amrex::For(tmp, [=] (int i, int j, int k) noexcept
644 {
646 IntVect const idx(AMREX_D_DECL(i,j,k));
647 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
648 f_user(idx, fab, dcomp, numcomp, geomdata, time,
649 bcr_p, 0, orig_comp);
650 });
651 }
652 }
653#endif
654
655#if (AMREX_SPACEDIM == 3)
656 // fill on box corners
657 {
658 Array<Box,8> dom_corner_boxes
659 = {{ amrex::convert(amrex::adjCellLo(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
660 amrex::convert(amrex::adjCellLo(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
661 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
662 amrex::convert(amrex::adjCellLo(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
663 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
664 amrex::convert(amrex::adjCellHi(amrex::adjCellLo(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
665 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(amrex::adjCellLo(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType),
666 amrex::convert(amrex::adjCellHi(amrex::adjCellHi(amrex::adjCellHi(gdomain,0,len[0]),1,len[1]),2,len[2]),idxType) }};
667
668 for (const Box& b : dom_corner_boxes) {
669 Box tmp = b & bx;
670 amrex::For(tmp, [=] (int i, int j, int k) noexcept
671 {
672 IntVect const idx(AMREX_D_DECL(i,j,k));
673 fillfunc(idx, fab, dcomp, numcomp, domain, bcr_p, 0);
674 f_user(idx, fab, dcomp, numcomp, geomdata, time,
675 bcr_p, 0, orig_comp);
676 });
677 }
678 }
679#endif
680
681#endif
682}
683
684}
685#endif
#define AMREX_ARLIM_P(x)
Definition AMReX_ArrayLim.H:30
Boundary condition descriptors used throughout AMReX.
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:562
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
Problem-domain geometry: maps between index space and physical space.
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
#define AMREX_D_PICK(a, b, c)
Definition AMReX_SPACE.H:173
#define AMREX_D_DECL(a, b, c)
Definition AMReX_SPACE.H:171
Boundary condition record storing low/high face types per coordinate.
Definition AMReX_BCRec.H:25
Array4< T const > array() const noexcept
Create an Array4 view over all components.
Definition AMReX_BaseFab.H:475
This version calls function working on array.
Definition AMReX_PhysBCFunct.H:36
BndryFuncArray() noexcept=default
bool m_run_on_gpu
Definition AMReX_PhysBCFunct.H:54
void operator()(Box const &bx, FArrayBox &dest, int dcomp, int numcomp, Geometry const &geom, Real time, const Vector< BCRec > &bcr, int bcomp, int orig_comp)
Definition AMReX_PhysBCFunct.cpp:7
BndryFuncArray(BndryFunc3DDefault inFunc) noexcept
Definition AMReX_PhysBCFunct.H:40
BndryFunc3DDefault m_func3D
Definition AMReX_PhysBCFunct.H:53
BndryFuncDefault m_func
Definition AMReX_PhysBCFunct.H:52
bool RunOnGPU() const noexcept
Definition AMReX_PhysBCFunct.H:48
IndexType ixType() const noexcept
Return index type of this BoxArray.
Definition AMReX_BoxArray.H:1268
__host__ __device__ BoxND & grow(int i) noexcept
Grow in all directions by i cells (negative shrinks).
Definition AMReX_Box.H:668
__host__ __device__ const IntVectND< dim > & bigEnd() const &noexcept
Return the inclusive upper bound of the box.
Definition AMReX_Box.H:136
__host__ __device__ BoxND & setBig(const IntVectND< dim > &bg) noexcept
Redefine the big end of the BoxND.
Definition AMReX_Box.H:516
__host__ __device__ IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:167
__host__ __device__ bool contains(const IntVectND< dim > &p) const noexcept
Return true if argument is contained within BoxND.
Definition AMReX_Box.H:233
__host__ __device__ IndexTypeND< dim > ixType() const noexcept
Return the indexing type.
Definition AMReX_Box.H:148
__host__ __device__ bool ok() const noexcept
Return true if high bounds are >= low bounds and the index type is valid.
Definition AMReX_Box.H:229
__host__ __device__ const IntVectND< dim > & smallEnd() const &noexcept
Return the inclusive lower bound of the box.
Definition AMReX_Box.H:124
__host__ __device__ BoxND & setSmall(const IntVectND< dim > &sm) noexcept
Definition AMReX_Box.H:508
This cpu version calls function working on FArrayBox.
Definition AMReX_PhysBCFunct.H:104
UserFillBox f_user
Definition AMReX_PhysBCFunct.H:116
CpuBndryFuncFab(UserFillBox a_f)
Definition AMReX_PhysBCFunct.H:107
void operator()(Box const &bx, FArrayBox &dest, int dcomp, int numcomp, Geometry const &geom, Real time, const Vector< BCRec > &bcr, int bcomp, int orig_comp)
Definition AMReX_PhysBCFunct.cpp:48
A Fortran Array of REALs.
Definition AMReX_FArrayBox.H:237
IntVect nGrowVect() const noexcept
Definition AMReX_FabArrayBase.H:85
const BoxArray & boxArray() const noexcept
Return a constant reference to the BoxArray that defines the valid region associated with this FabArr...
Definition AMReX_FabArrayBase.H:100
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:85
const Box & Domain() const noexcept
Returns our rectangular domain.
Definition AMReX_Geometry.H:244
GeometryData data() const noexcept
Return a GPU-safe snapshot of the Geometry data.
Definition AMReX_Geometry.H:134
bool isAllPeriodic() const noexcept
Is domain periodic in all directions?
Definition AMReX_Geometry.H:404
bool isPeriodic(int dir) const noexcept
Is the domain periodic in the specified direction?
Definition AMReX_Geometry.H:397
Definition AMReX_PhysBCFunct.H:64
GpuBndryFuncFab(F const &a_f)
Definition AMReX_PhysBCFunct.H:67
void nddoit(Box const &bx, FArrayBox &dest, int dcomp, int numcomp, Geometry const &geom, Real time, const Vector< BCRec > &bcr, int bcomp, int orig_comp)
Definition AMReX_PhysBCFunct.H:274
GpuBndryFuncFab(F &&a_f)
Definition AMReX_PhysBCFunct.H:68
void ccfcdoit(Box const &bx, FArrayBox &dest, int dcomp, int numcomp, Geometry const &geom, Real time, const Vector< BCRec > &bcr, int bcomp, int orig_comp, FF const &fillfunc)
Definition AMReX_PhysBCFunct.H:398
void operator()(Box const &bx, FArrayBox &dest, int dcomp, int numcomp, Geometry const &geom, Real time, const Vector< BCRec > &bcr, int bcomp, int orig_comp)
Definition AMReX_PhysBCFunct.H:257
F m_user_f
Definition AMReX_PhysBCFunct.H:90
Definition AMReX_GpuAsyncArray.H:35
T const * data() const noexcept
Definition AMReX_GpuAsyncArray.H:76
__host__ __device__ constexpr CellIndex ixType(int dir) const noexcept
Returns the CellIndex in direction dir.
Definition AMReX_IndexType.H:117
__host__ __device__ bool cellCentered() const noexcept
True if the IndexTypeND is CELL based in all directions.
Definition AMReX_IndexType.H:102
__host__ __device__ constexpr int min() const noexcept
minimum (no absolute values) value
Definition AMReX_IntVect.H:324
__host__ __device__ constexpr bool allGE(const IntVectND< dim > &rhs) const noexcept
Returns true if this is greater than or equal to argument for all components. NOTE: This is NOT a str...
Definition AMReX_IntVect.H:542
__host__ static __device__ constexpr IntVectND< dim > TheNodeVector() noexcept
This static member function returns a reference to a constant IntVectND object, all of whose dim argu...
Definition AMReX_IntVect.H:801
__host__ __device__ constexpr bool allLE(const IntVectND< dim > &rhs) const noexcept
Returns true if this is less than or equal to argument for all components. NOTE: This is NOT a strict...
Definition AMReX_IntVect.H:492
Iterator for looping ever tiles and boxes of amrex::FabArray based containers.
Definition AMReX_MFIter.H:88
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:176
A collection (stored as an array) of FArrayBox objects.
Definition AMReX_MultiFab.H:40
Definition AMReX_PhysBCFunct.H:120
void operator()(MultiFab &, int, int, IntVect const &, Real, int)
Definition AMReX_PhysBCFunct.H:122
Definition AMReX_PhysBCFunct.H:127
IntVect src_ghost_outside_domain
Definition AMReX_PhysBCFunct.H:169
IntVect fp1_src_ghost
Definition AMReX_PhysBCFunct.H:174
PhysBCFunctUseCoarseGhost(IntVect const &a_fp1_src_ghost)
Definition AMReX_PhysBCFunct.H:130
IntVect cghost
Definition AMReX_PhysBCFunct.H:172
void operator()(MultiFab &, int, int, IntVect const &, Real, int)
Definition AMReX_PhysBCFunct.H:156
IntVect src_ghost
Definition AMReX_PhysBCFunct.H:165
IntVect nghost
Definition AMReX_PhysBCFunct.H:159
PhysBCFunctUseCoarseGhost(MF const &cmf, IntVect const &a_nghost, IntVect const &a_nghost_outside_domain, IntVect const &ratio, Interp *mapper)
Definition AMReX_PhysBCFunct.H:134
IntVect nghost_outside_domain
Definition AMReX_PhysBCFunct.H:161
Definition AMReX_PhysBCFunct.H:179
void define(const Geometry &geom, const Vector< BCRec > &bcr, F const &f)
Definition AMReX_PhysBCFunct.H:191
void define(const Geometry &geom, const Vector< BCRec > &bcr, F &&f)
Definition AMReX_PhysBCFunct.H:195
PhysBCFunct(const Geometry &geom, const Vector< BCRec > &bcr, F const &f)
Definition AMReX_PhysBCFunct.H:183
void operator()(MultiFab &mf, int icomp, int ncomp, IntVect const &nghost, Real time, int bccomp)
Definition AMReX_PhysBCFunct.H:199
PhysBCFunct(const Geometry &geom, const Vector< BCRec > &bcr, F &&f)
Definition AMReX_PhysBCFunct.H:187
PhysBCFunct()=default
void FillBoundary(MultiFab &mf, int icomp, int ncomp, IntVect const &nghost, Real time, int bccomp)
Definition AMReX_PhysBCFunct.H:243
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:29
Long size() const noexcept
Definition AMReX_Vector.H:54
amrex_real Real
Floating Point Type for Fields.
Definition AMReX_REAL.H:80
amrex_long Long
Definition AMReX_INT.H:30
__host__ __device__ BoxND< dim > adjCellHi(const BoxND< dim > &b, int dir, int len=1) noexcept
Return the BoxND of length len adjacent to b on the high end along coordinate direction dir.
Definition AMReX_Box.H:1848
__host__ __device__ BoxND< dim > convert(const BoxND< dim > &b, const IntVectND< dim > &typ) noexcept
Return a copy of b converted to the nodal flags typ.
Definition AMReX_Box.H:1630
__host__ __device__ BoxND< dim > adjCellLo(const BoxND< dim > &b, int dir, int len=1) noexcept
Return the BoxND of length len adjacent to b on the low end along coordinate direction dir.
Definition AMReX_Box.H:1817
__host__ __device__ BoxND< dim > grow(const BoxND< dim > &b, int i) noexcept
Return a copy of b grown uniformly by i cells in every direction.
Definition AMReX_Box.H:1326
std::array< T, N > Array
Definition AMReX_Array.H:31
Definition AMReX_Amr.cpp:50
__host__ __device__ void ignore_unused(const Ts &...)
No-op helper that marks variables as intentionally unused.
Definition AMReX.H:259
void(*)(Real *data, const int &, const int &, const int &, const int &, const int &, const int &, const int *dom_lo, const int *dom_hi, const Real *dx, const Real *grd_lo, const Real *time, const int *bc) BndryFuncDefault
Definition AMReX_PhysBCFunct.H:21
void For(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:400
void ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:202
void(*)(Real *data, const int *lo, const int *hi, const int *dom_lo, const int *dom_hi, const Real *dx, const Real *grd_lo, const Real *time, const int *bc) BndryFunc3DDefault
Definition AMReX_PhysBCFunct.H:25
BoxND< 3 > Box
Box is an alias for amrex::BoxND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:35
void(*)(Box const &bx, Array4< Real > const &dest, int dcomp, int numcomp, GeometryData const &geom, Real time, const BCRec *bcr, int bcomp, int orig_comp) UserFillBox
Definition AMReX_PhysBCFunct.H:32
IntVectND< 3 > IntVect
IntVect is an alias for amrex::IntVectND instantiated with AMREX_SPACEDIM.
Definition AMReX_BaseFwd.H:38
IntVect nGrowVect(FabArrayBase const &fa)
Convenience wrapper that forwards to fa.nGrowVect().
Definition AMReX_FabArrayBase.cpp:2865
void setBC(const Box &bx, const Box &domain, int src_comp, int dest_comp, int ncomp, const Vector< BCRec > &bc_dom, Vector< BCRec > &bcr) noexcept
Populate a span of BCRec objects based on a domain record.
Definition AMReX_BCRec.cpp:8
__host__ __device__ IntVectND< dim > getCell(BoxND< dim > const *boxes, int nboxes, Long icell) noexcept
Return the point coordinate corresponding to the flattened index icell.
Definition AMReX_Box.H:2408
A multidimensional array accessor.
Definition AMReX_Array4.H:289
Definition AMReX_PhysBCFunct.H:94
__device__ void operator()(const amrex::IntVect &, amrex::Array4< amrex::Real > const &, int, int, amrex::GeometryData const &, amrex::Real, const amrex::BCRec *, int, int) const
Definition AMReX_PhysBCFunct.H:96
GPU-safe snapshot of Geometry data suitable for capture in GPU kernels.
Definition AMReX_Geometry.H:36