Block-Structured AMR Software Framework
 
Loading...
Searching...
No Matches
AMReX_MLABecLaplacian.H
Go to the documentation of this file.
1#ifndef AMREX_ML_ABECLAPLACIAN_H_
2#define AMREX_ML_ABECLAPLACIAN_H_
3#include <AMReX_Config.H>
4
6#include <AMReX_MLABecLap_K.H>
7
8namespace amrex {
9
10// (alpha * a - beta * (del dot b grad)) phi
11
12template <typename MF>
14 : public MLCellABecLapT<MF>
15{
16public:
17
18 using FAB = typename MF::fab_type;
19 using RT = typename MF::value_type;
20
21 using BCType = LinOpBCType;
23
24 MLABecLaplacianT () = default;
26 const Vector<BoxArray>& a_grids,
27 const Vector<DistributionMapping>& a_dmap,
28 const LPInfo& a_info = LPInfo(),
29 const Vector<FabFactory<FAB> const*>& a_factory = {},
30 int a_ncomp = 1);
31
33 const Vector<BoxArray>& a_grids,
34 const Vector<DistributionMapping>& a_dmap,
35 const Vector<iMultiFab const*>& a_overset_mask, // 1: unknown, 0: known
36 const LPInfo& a_info = LPInfo(),
37 const Vector<FabFactory<FAB> const*>& a_factory = {},
38 int a_ncomp = 1);
39
40 ~MLABecLaplacianT () override;
41
46
47 void define (const Vector<Geometry>& a_geom,
48 const Vector<BoxArray>& a_grids,
49 const Vector<DistributionMapping>& a_dmap,
50 const LPInfo& a_info = LPInfo(),
51 const Vector<FabFactory<FAB> const*>& a_factory = {},
52 int a_ncomp = 1);
53
54 void define (const Vector<Geometry>& a_geom,
55 const Vector<BoxArray>& a_grids,
56 const Vector<DistributionMapping>& a_dmap,
57 const Vector<iMultiFab const*>& a_overset_mask,
58 const LPInfo& a_info = LPInfo(),
59 const Vector<FabFactory<FAB> const*>& a_factory = {},
60 int a_ncomp = 1);
61
67 template <typename T1, typename T2,
68 std::enable_if_t<std::is_convertible_v<T1,typename MF::value_type> &&
69 std::is_convertible_v<T2,typename MF::value_type>,
70 int> = 0>
71 void setScalars (T1 a, T2 b) noexcept;
72
82 template <typename AMF,
83 std::enable_if_t<IsFabArray<AMF>::value &&
84 std::is_convertible_v<typename AMF::value_type,
85 typename MF::value_type>,
86 int> = 0>
87 void setACoeffs (int amrlev, const AMF& alpha);
88
98 template <typename T,
99 std::enable_if_t<std::is_convertible_v<T,typename MF::value_type>,
100 int> = 0>
101 void setACoeffs (int amrlev, T alpha);
102
112 template <typename AMF,
113 std::enable_if_t<IsFabArray<AMF>::value &&
114 std::is_convertible_v<typename AMF::value_type,
115 typename MF::value_type>,
116 int> = 0>
117 void setBCoeffs (int amrlev, const Array<AMF const*,AMREX_SPACEDIM>& beta);
118
128 template <typename T,
129 std::enable_if_t<std::is_convertible_v<T,typename MF::value_type>,
130 int> = 0>
131 void setBCoeffs (int amrlev, T beta);
132
142 template <typename T,
143 std::enable_if_t<std::is_convertible_v<T,typename MF::value_type>,
144 int> = 0>
145 void setBCoeffs (int amrlev, Vector<T> const& beta);
146
147 [[nodiscard]] int getNComp () const override { return m_ncomp; }
148
149 [[nodiscard]] bool needsUpdate () const override {
151 }
152 void update () override;
153
154 void prepareForSolve () override;
155 [[nodiscard]] bool isSingular (int amrlev) const override { return m_is_singular[amrlev]; }
156 [[nodiscard]] bool isBottomSingular () const override { return m_is_singular[0]; }
157 void Fapply (int amrlev, int mglev, MF& out, const MF& in) const final;
158 void Fsmooth (int amrlev, int mglev, MF& sol, const MF& rhs, int redblack) const final;
159 void FFlux (int amrlev, const MFIter& mfi,
160 const Array<FAB*,AMREX_SPACEDIM>& flux,
161 const FAB& sol, Location /* loc */,
162 int face_only=0) const final;
163
164 void normalize (int amrlev, int mglev, MF& mf) const final;
165
166 [[nodiscard]] RT getAScalar () const final { return m_a_scalar; }
167 [[nodiscard]] RT getBScalar () const final { return m_b_scalar; }
168 [[nodiscard]] MF const* getACoeffs (int amrlev, int mglev) const final
169 { return &(m_a_coeffs[amrlev][mglev]); }
170 [[nodiscard]] Array<MF const*,AMREX_SPACEDIM> getBCoeffs (int amrlev, int mglev) const final
171 { return amrex::GetArrOfConstPtrs(m_b_coeffs[amrlev][mglev]); }
172
173 [[nodiscard]] std::unique_ptr<MLLinOpT<MF>> makeNLinOp (int /*grid_size*/) const final;
174
175 [[nodiscard]] bool supportNSolve () const final;
176
177 void copyNSolveSolution (MF& dst, MF const& src) const final;
178
179 void averageDownCoeffsSameAmrLevel (int amrlev, Vector<MF>& a,
180 Vector<Array<MF,AMREX_SPACEDIM> >& b);
181 void averageDownCoeffs ();
182 void averageDownCoeffsToCoarseAmrLevel (int flev);
183
185
187
188 static void FFlux (Box const& box, Real const* dxinv, RT bscalar,
189 Array<FAB const*, AMREX_SPACEDIM> const& bcoef,
190 Array<FAB*,AMREX_SPACEDIM> const& flux,
191 FAB const& sol, int face_only, int ncomp);
192
193 RT m_a_scalar = std::numeric_limits<RT>::quiet_NaN();
194 RT m_b_scalar = std::numeric_limits<RT>::quiet_NaN();
196 Vector<Vector<Array<MF,AMREX_SPACEDIM> > > m_b_coeffs;
197
198 bool m_scalars_set = false;
199 bool m_acoef_set = false;
200
201protected:
202
203 bool m_needs_update = true;
204
206
207 [[nodiscard]] bool supportRobinBC () const noexcept override { return true; }
208
209private:
210
211 int m_ncomp = 1;
212
213 void define_ab_coeffs ();
214
215 void update_singular_flags ();
216};
217
218template <typename MF>
220 const Vector<BoxArray>& a_grids,
221 const Vector<DistributionMapping>& a_dmap,
222 const LPInfo& a_info,
223 const Vector<FabFactory<FAB> const*>& a_factory,
224 int a_ncomp)
225{
226 define(a_geom, a_grids, a_dmap, a_info, a_factory, a_ncomp);
227}
228
229template <typename MF>
231 const Vector<BoxArray>& a_grids,
232 const Vector<DistributionMapping>& a_dmap,
233 const Vector<iMultiFab const*>& a_overset_mask,
234 const LPInfo& a_info,
235 const Vector<FabFactory<FAB> const*>& a_factory,
236 int a_ncomp)
237{
238 define(a_geom, a_grids, a_dmap, a_overset_mask, a_info, a_factory, a_ncomp);
239}
240
241template <typename MF> MLABecLaplacianT<MF>::~MLABecLaplacianT () = default;
242
243template <typename MF>
244void
246 const Vector<BoxArray>& a_grids,
247 const Vector<DistributionMapping>& a_dmap,
248 const LPInfo& a_info,
249 const Vector<FabFactory<FAB> const*>& a_factory,
250 int a_ncomp)
251{
252 BL_PROFILE("MLABecLaplacian::define()");
253 this->m_ncomp = a_ncomp;
254 MLCellABecLapT<MF>::define(a_geom, a_grids, a_dmap, a_info, a_factory);
255 define_ab_coeffs();
256}
257
258template <typename MF>
259void
261 const Vector<BoxArray>& a_grids,
262 const Vector<DistributionMapping>& a_dmap,
263 const Vector<iMultiFab const*>& a_overset_mask,
264 const LPInfo& a_info,
265 const Vector<FabFactory<FAB> const*>& a_factory,
266 int a_ncomp)
267{
268 BL_PROFILE("MLABecLaplacian::define(overset)");
269 this->m_ncomp = a_ncomp;
270 MLCellABecLapT<MF>::define(a_geom, a_grids, a_dmap, a_overset_mask, a_info, a_factory);
271 define_ab_coeffs();
272}
273
274template <typename MF>
275void
277{
278 m_a_coeffs.resize(this->m_num_amr_levels);
279 m_b_coeffs.resize(this->m_num_amr_levels);
280 for (int amrlev = 0; amrlev < this->m_num_amr_levels; ++amrlev)
281 {
282 m_a_coeffs[amrlev].resize(this->m_num_mg_levels[amrlev]);
283 m_b_coeffs[amrlev].resize(this->m_num_mg_levels[amrlev]);
284 for (int mglev = 0; mglev < this->m_num_mg_levels[amrlev]; ++mglev)
285 {
286 m_a_coeffs[amrlev][mglev].define
287 (this->m_grids[amrlev][mglev], this->m_dmap[amrlev][mglev],
288 1, 0, MFInfo(), *(this->m_factory[amrlev][mglev]));
289 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim)
290 {
291 const BoxArray& ba = amrex::convert(this->m_grids[amrlev][mglev],
293 m_b_coeffs[amrlev][mglev][idim].define
294 (ba, this->m_dmap[amrlev][mglev], m_ncomp, 0, MFInfo(),
295 *(this->m_factory[amrlev][mglev]));
296 }
297 }
298 }
299}
300
301template <typename MF>
302template <typename T1, typename T2,
303 std::enable_if_t<std::is_convertible_v<T1,typename MF::value_type> &&
304 std::is_convertible_v<T2,typename MF::value_type>, int>>
305void
307{
308 m_a_scalar = RT(a);
309 m_b_scalar = RT(b);
310 if (m_a_scalar == RT(0.0)) {
311 for (int amrlev = 0; amrlev < this->m_num_amr_levels; ++amrlev) {
312 m_a_coeffs[amrlev][0].setVal(RT(0.0));
313 }
314 m_acoef_set = true;
315 }
316 m_scalars_set = true;
317}
318
319template <typename MF>
320template <typename AMF,
321 std::enable_if_t<IsFabArray<AMF>::value &&
322 std::is_convertible_v<typename AMF::value_type,
323 typename MF::value_type>, int>>
324void
325MLABecLaplacianT<MF>::setACoeffs (int amrlev, const AMF& alpha)
326{
327 AMREX_ASSERT_WITH_MESSAGE(alpha.nComp() == 1,
328 "MLABecLaplacian::setACoeffs: alpha is supposed to be single component.");
329 m_a_coeffs[amrlev][0].LocalCopy(alpha, 0, 0, 1, IntVect(0));
330 m_needs_update = true;
331 m_acoef_set = true;
332}
333
334template <typename MF>
335template <typename T,
336 std::enable_if_t<std::is_convertible_v<T,typename MF::value_type>,int>>
337void
339{
340 m_a_coeffs[amrlev][0].setVal(RT(alpha));
341 m_needs_update = true;
342 m_acoef_set = true;
343}
344
345
346template <typename MF>
347template <typename AMF,
348 std::enable_if_t<IsFabArray<AMF>::value &&
349 std::is_convertible_v<typename AMF::value_type,
350 typename MF::value_type>, int>>
351void
354{
355 const int ncomp = this->getNComp();
356 AMREX_ASSERT(beta[0]->nComp() == 1 || beta[0]->nComp() == ncomp);
357 if (beta[0]->nComp() == ncomp) {
358 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
359 for (int icomp = 0; icomp < ncomp; ++icomp) {
360 m_b_coeffs[amrlev][0][idim].LocalCopy(*beta[idim], icomp, icomp, 1, IntVect(0));
361 }
362 }
363 } else {
364 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
365 for (int icomp = 0; icomp < ncomp; ++icomp) {
366 m_b_coeffs[amrlev][0][idim].LocalCopy(*beta[idim], 0, icomp, 1, IntVect(0));
367 }
368 }
369 }
370 m_needs_update = true;
371}
372
373template <typename MF>
374template <typename T,
375 std::enable_if_t<std::is_convertible_v<T,typename MF::value_type>,int>>
376void
378{
379 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
380 m_b_coeffs[amrlev][0][idim].setVal(RT(beta));
381 }
382 m_needs_update = true;
383}
384
385template <typename MF>
386template <typename T,
387 std::enable_if_t<std::is_convertible_v<T,typename MF::value_type>,int>>
388void
390{
391 const int ncomp = this->getNComp();
392 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
393 for (int icomp = 0; icomp < ncomp; ++icomp) {
394 m_b_coeffs[amrlev][0][idim].setVal(RT(beta[icomp]));
395 }
396 }
397 m_needs_update = true;
398}
399
400template <typename MF>
401void
403{
406 }
407
408#if (AMREX_SPACEDIM != 3)
409 applyMetricTermsCoeffs();
410#endif
411
412 applyRobinBCTermsCoeffs();
413
414 averageDownCoeffs();
415
416 update_singular_flags();
417
418 m_needs_update = false;
419}
420
421template <typename MF>
422void
424{
425 BL_PROFILE("MLABecLaplacian::prepareForSolve()");
426
428
429#if (AMREX_SPACEDIM != 3)
430 applyMetricTermsCoeffs();
431#endif
432
433 applyRobinBCTermsCoeffs();
434
435 averageDownCoeffs();
436
437 update_singular_flags();
438
439 m_needs_update = false;
440}
441
442template <typename MF>
443void
445{
446#if (AMREX_SPACEDIM != 3)
447 for (int alev = 0; alev < this->m_num_amr_levels; ++alev)
448 {
449 const int mglev = 0;
450 this->applyMetricTerm(alev, mglev, m_a_coeffs[alev][mglev]);
451 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim)
452 {
453 this->applyMetricTerm(alev, mglev, m_b_coeffs[alev][mglev][idim]);
454 }
455 }
456#endif
457}
458
459//
460// Suppose we are solving `alpha u - del (beta grad u) = rhs` (Scalar
461// coefficients can be easily added back in the end) and there is Robin BC
462// `a u + b du/dn = f` at the upper end of the x-direction. The 1D
463// discretization at the last cell i is
464//
465// alpha u_i + (beta_{i-1/2} (du/dx)_{i-1/2} - beta_{i+1/2} (du/dx)_{i+1/2}) / h = rhs_i
466//
467// where h is the cell size. At `i+1/2` (i.e., the boundary), we have
468//
469// a (u_i + u_{i+1})/2 + b (u_{i+1}-u_i)/h = f,
470//
471// according to the Robin BC. This gives
472//
473// u_{i+1} = A + B u_i,
474//
475// where `A = f/(b/h + a/2)` and `B = (b/h - a/2) / (b/h + a/2). We then
476// use `u_i` and `u_{i+1}` to compute `(du/dx)_{i+1/2}`. The discretization
477// at cell i then becomes
478//
479// \tilde{alpha}_i u_i + (beta_{i-1/2} (du/dx)_{i-1/2} - 0) / h = \tilde{rhs}_i
480//
481// This is equivalent to having homogeneous Neumann BC with modified alpha and rhs.
482//
483// \tilde{alpha}_i = alpha_i + (1-B) beta_{i+1/2} / h^2
484// \tilde{rhs}_i = rhs_i + A beta_{i+1/2} / h^2
485//
486namespace detail {
487template <typename LP>
489{
490 using RT = typename LP::RT;
491
492 const int ncomp = linop.getNComp();
493 bool reset_alpha = false;
494 if (linop.m_a_scalar == RT(0.0)) {
495 linop.m_a_scalar = RT(1.0);
496 reset_alpha = true;
497 }
498 const RT bovera = linop.m_b_scalar/linop.m_a_scalar;
499
500 if (!reset_alpha) {
501 AMREX_ALWAYS_ASSERT_WITH_MESSAGE(linop.m_scalars_set && linop.m_acoef_set,
502 "To reuse solver With Robin BC, one must re-call setScalars (and setACoeffs if the scalar is not zero)");
503 }
504
505 linop.m_scalars_set = false;
506 linop.m_acoef_set = false;
507
508 for (int amrlev = 0; amrlev < linop.NAMRLevels(); ++amrlev) {
509 const int mglev = 0;
510 const Box& domain = linop.Geom(amrlev,mglev).Domain();
511 const RT dxi = static_cast<RT>(linop.Geom(amrlev,mglev).InvCellSize(0));
512 const RT dyi = static_cast<RT>((AMREX_SPACEDIM >= 2) ? linop.Geom(amrlev,mglev).InvCellSize(1) : Real(1.0));
513 const RT dzi = static_cast<RT>((AMREX_SPACEDIM == 3) ? linop.Geom(amrlev,mglev).InvCellSize(2) : Real(1.0));
514
515 if (reset_alpha) {
516 linop.m_a_coeffs[amrlev][mglev].setVal(RT(0.0));
517 }
518
519 MFItInfo mfi_info;
520 if (Gpu::notInLaunchRegion()) { mfi_info.SetDynamic(true); }
521
522#ifdef AMREX_USE_OMP
523#pragma omp parallel if (Gpu::notInLaunchRegion())
524#endif
525 for (MFIter mfi(linop.m_a_coeffs[amrlev][mglev], mfi_info); mfi.isValid(); ++mfi)
526 {
527 const Box& vbx = mfi.validbox();
528 auto const& afab = linop.m_a_coeffs[amrlev][mglev].array(mfi);
529 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
530 auto const& bfab = linop.m_b_coeffs[amrlev][mglev][idim].const_array(mfi);
531 const Box& blo = amrex::adjCellLo(vbx,idim);
532 const Box& bhi = amrex::adjCellHi(vbx,idim);
533 bool outside_domain_lo = !(domain.contains(blo));
534 bool outside_domain_hi = !(domain.contains(bhi));
535 if ((!outside_domain_lo) && (!outside_domain_hi)) { continue; }
536 for (int icomp = 0; icomp < ncomp; ++icomp) {
537 auto const& rbc = (*(linop.m_robin_bcval[amrlev]))[mfi].const_array(icomp*3);
538 if (linop.m_lobc_orig[icomp][idim] == LinOpBCType::Robin && outside_domain_lo)
539 {
540 if (idim == 0) {
541 RT fac = bovera*dxi*dxi;
542 AMREX_HOST_DEVICE_FOR_3D(blo, i, j, k,
543 {
544 RT B = (rbc(i,j,k,1)*dxi - rbc(i,j,k,0)*RT(0.5))
545 / (rbc(i,j,k,1)*dxi + rbc(i,j,k,0)*RT(0.5));
546 afab(i+1,j,k,icomp) += fac*bfab(i+1,j,k,icomp)*(RT(1.0)-B);
547 });
548 } else if (idim == 1) {
549 RT fac = bovera*dyi*dyi;
550 AMREX_HOST_DEVICE_FOR_3D(blo, i, j, k,
551 {
552 RT B = (rbc(i,j,k,1)*dyi - rbc(i,j,k,0)*RT(0.5))
553 / (rbc(i,j,k,1)*dyi + rbc(i,j,k,0)*RT(0.5));
554 afab(i,j+1,k,icomp) += fac*bfab(i,j+1,k,icomp)*(RT(1.0)-B);
555 });
556 } else {
557 RT fac = bovera*dzi*dzi;
558 AMREX_HOST_DEVICE_FOR_3D(blo, i, j, k,
559 {
560 RT B = (rbc(i,j,k,1)*dzi - rbc(i,j,k,0)*RT(0.5))
561 / (rbc(i,j,k,1)*dzi + rbc(i,j,k,0)*RT(0.5));
562 afab(i,j,k+1,icomp) += fac*bfab(i,j,k+1,icomp)*(RT(1.0)-B);
563 });
564 }
565 }
566 if (linop.m_hibc_orig[icomp][idim] == LinOpBCType::Robin && outside_domain_hi)
567 {
568 if (idim == 0) {
569 RT fac = bovera*dxi*dxi;
570 AMREX_HOST_DEVICE_FOR_3D(bhi, i, j, k,
571 {
572 RT B = (rbc(i,j,k,1)*dxi - rbc(i,j,k,0)*RT(0.5))
573 / (rbc(i,j,k,1)*dxi + rbc(i,j,k,0)*RT(0.5));
574 afab(i-1,j,k,icomp) += fac*bfab(i,j,k,icomp)*(RT(1.0)-B);
575 });
576 } else if (idim == 1) {
577 RT fac = bovera*dyi*dyi;
578 AMREX_HOST_DEVICE_FOR_3D(bhi, i, j, k,
579 {
580 RT B = (rbc(i,j,k,1)*dyi - rbc(i,j,k,0)*RT(0.5))
581 / (rbc(i,j,k,1)*dyi + rbc(i,j,k,0)*RT(0.5));
582 afab(i,j-1,k,icomp) += fac*bfab(i,j,k,icomp)*(RT(1.0)-B);
583 });
584 } else {
585 RT fac = bovera*dzi*dzi;
586 AMREX_HOST_DEVICE_FOR_3D(bhi, i, j, k,
587 {
588 RT B = (rbc(i,j,k,1)*dzi - rbc(i,j,k,0)*RT(0.5))
589 / (rbc(i,j,k,1)*dzi + rbc(i,j,k,0)*RT(0.5));
590 afab(i,j,k-1,icomp) += fac*bfab(i,j,k,icomp)*(RT(1.0)-B);
591 });
592 }
593 }
594 }
595 }
596 }
597 }
598}
599} // namespace detail
600
601template <typename MF>
602void
604{
605 if (this->hasRobinBC()) {
607 }
608}
609
610template <typename MF>
611void
613{
614 BL_PROFILE("MLABecLaplacian::averageDownCoeffs()");
615
616 for (int amrlev = this->m_num_amr_levels-1; amrlev > 0; --amrlev)
617 {
618 auto& fine_a_coeffs = m_a_coeffs[amrlev];
619 auto& fine_b_coeffs = m_b_coeffs[amrlev];
620
621 averageDownCoeffsSameAmrLevel(amrlev, fine_a_coeffs, fine_b_coeffs);
622 averageDownCoeffsToCoarseAmrLevel(amrlev);
623 }
624
625 averageDownCoeffsSameAmrLevel(0, m_a_coeffs[0], m_b_coeffs[0]);
626}
627
628template <typename MF>
629void
632{
633 int nmglevs = a.size();
634 for (int mglev = 1; mglev < nmglevs; ++mglev)
635 {
636 IntVect ratio = (amrlev > 0) ? IntVect(this->mg_coarsen_ratio) : this->mg_coarsen_ratio_vec[mglev-1];
637
638 if (m_a_scalar == 0.0)
639 {
640 a[mglev].setVal(RT(0.0));
641 }
642 else
643 {
644 amrex::average_down(a[mglev-1], a[mglev], 0, 1, ratio);
645 }
646
647 Vector<const MF*> fine {AMREX_D_DECL(&(b[mglev-1][0]),
648 &(b[mglev-1][1]),
649 &(b[mglev-1][2]))};
650 Vector<MF*> crse {AMREX_D_DECL(&(b[mglev][0]),
651 &(b[mglev][1]),
652 &(b[mglev][2]))};
653
655 }
656
657 for (int mglev = 1; mglev < nmglevs; ++mglev)
658 {
659 if (this->m_overset_mask[amrlev][mglev]) {
660 const RT fac = static_cast<RT>(1 << mglev); // 2**mglev
661 const RT osfac = RT(2.0)*fac/(fac+RT(1.0));
662 const int ncomp = this->getNComp();
663#ifdef AMREX_USE_OMP
664#pragma omp parallel if (Gpu::notInLaunchRegion())
665#endif
666 for (MFIter mfi(a[mglev],TilingIfNotGPU()); mfi.isValid(); ++mfi)
667 {
668 AMREX_D_TERM(Box const& xbx = mfi.nodaltilebox(0);,
669 Box const& ybx = mfi.nodaltilebox(1);,
670 Box const& zbx = mfi.nodaltilebox(2));
671 AMREX_D_TERM(auto const& bx = b[mglev][0].array(mfi);,
672 auto const& by = b[mglev][1].array(mfi);,
673 auto const& bz = b[mglev][2].array(mfi));
674 auto const& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
675#if defined(AMREX_USE_CUDA) && defined(_WIN32)
677 (xbx, t_xbx,
678 {
679 overset_rescale_bcoef_x(t_xbx, bx, osm, ncomp, osfac);
680 });
681#if (AMREX_SPACEDIM >= 2)
683 (ybx, t_ybx,
684 {
685 overset_rescale_bcoef_y(t_ybx, by, osm, ncomp, osfac);
686 });
687#endif
688#if (AMREX_SPACEDIM == 3)
690 (zbx, t_zbx,
691 {
692 overset_rescale_bcoef_z(t_zbx, bz, osm, ncomp, osfac);
693 });
694#endif
695#else
697 (xbx, t_xbx,
698 {
699 overset_rescale_bcoef_x(t_xbx, bx, osm, ncomp, osfac);
700 },
701 ybx, t_ybx,
702 {
703 overset_rescale_bcoef_y(t_ybx, by, osm, ncomp, osfac);
704 },
705 zbx, t_zbx,
706 {
707 overset_rescale_bcoef_z(t_zbx, bz, osm, ncomp, osfac);
708 });
709#endif
710 }
711 }
712 }
713}
714
715template <typename MF>
716void
718{
719 auto& fine_a_coeffs = m_a_coeffs[flev ].back();
720 auto& fine_b_coeffs = m_b_coeffs[flev ].back();
721 auto& crse_a_coeffs = m_a_coeffs[flev-1].front();
722 auto& crse_b_coeffs = m_b_coeffs[flev-1].front();
723
724 if (m_a_scalar != 0.0) {
725 // We coarsen from the back of flev to the front of flev-1.
726 // So we use mg_coarsen_ratio.
727 amrex::average_down(fine_a_coeffs, crse_a_coeffs, 0, 1, this->mg_coarsen_ratio);
728 }
729
731 amrex::GetArrOfPtrs(crse_b_coeffs),
732 IntVect(this->mg_coarsen_ratio),
733 this->m_geom[flev-1][0]);
734}
735
736template <typename MF>
737void
739{
740 m_is_singular.clear();
741 m_is_singular.resize(this->m_num_amr_levels, false);
742 auto itlo = std::find(this->m_lobc[0].begin(), this->m_lobc[0].end(), BCType::Dirichlet);
743 auto ithi = std::find(this->m_hibc[0].begin(), this->m_hibc[0].end(), BCType::Dirichlet);
744 if (itlo == this->m_lobc[0].end() && ithi == this->m_hibc[0].end())
745 { // No Dirichlet
746 for (int alev = 0; alev < this->m_num_amr_levels; ++alev)
747 {
748 // For now this assumes that overset regions are treated as Dirichlet bc's
749 if (this->m_domain_covered[alev] && !this->m_overset_mask[alev][0])
750 {
751 if (m_a_scalar == Real(0.0))
752 {
753 m_is_singular[alev] = true;
754 }
755 else
756 {
757 RT asum = m_a_coeffs[alev].back().sum(0,IntVect(0));
758 RT amax = m_a_coeffs[alev].back().norminf(0,1,IntVect(0));
759 m_is_singular[alev] = (std::abs(asum) <= amax * RT(1.e-12));
760 }
761 }
762 }
763 }
764
765 if (!m_is_singular[0] && this->m_needs_coarse_data_for_bc &&
766 this->m_coarse_fine_bc_type == LinOpBCType::Neumann)
767 {
768 AMREX_ASSERT(this->m_overset_mask[0][0] == nullptr);
769
770 bool lev0_a_is_zero = false;
771 if (m_a_scalar == Real(0.0)) {
772 lev0_a_is_zero = true;
773 } else {
774 RT asum = m_a_coeffs[0].back().sum(0,IntVect(0));
775 RT amax = m_a_coeffs[0].back().norminf(0,1,IntVect(0));
776 bool a_is_almost_zero = std::abs(asum) <= amax * RT(1.e-12);
777 if (a_is_almost_zero) { lev0_a_is_zero = true; }
778 }
779
780 if (lev0_a_is_zero) {
781 auto bbox = this->m_grids[0][0].minimalBox();
782 for (int idim = 0; idim < AMREX_SPACEDIM; ++idim) {
783 if (this->m_lobc[0][idim] == LinOpBCType::Dirichlet) {
784 bbox.growLo(idim,1);
785 }
786 if (this->m_hibc[0][idim] == LinOpBCType::Dirichlet) {
787 bbox.growHi(idim,1);
788 }
789 }
790 if (this->m_geom[0][0].Domain().contains(bbox)) {
791 m_is_singular[0] = true;
792 }
793 }
794 }
795}
796
797template <typename MF>
798void
799MLABecLaplacianT<MF>::Fapply (int amrlev, int mglev, MF& out, const MF& in) const
800{
801 BL_PROFILE("MLABecLaplacian::Fapply()");
802
803 const MF& acoef = m_a_coeffs[amrlev][mglev];
804 AMREX_D_TERM(const MF& bxcoef = m_b_coeffs[amrlev][mglev][0];,
805 const MF& bycoef = m_b_coeffs[amrlev][mglev][1];,
806 const MF& bzcoef = m_b_coeffs[amrlev][mglev][2];);
807
809 {AMREX_D_DECL(static_cast<RT>(this->m_geom[amrlev][mglev].InvCellSize(0)),
810 static_cast<RT>(this->m_geom[amrlev][mglev].InvCellSize(1)),
811 static_cast<RT>(this->m_geom[amrlev][mglev].InvCellSize(2)))};
812
813 const RT ascalar = m_a_scalar;
814 const RT bscalar = m_b_scalar;
815
816 const int ncomp = this->getNComp();
817
818#ifdef AMREX_USE_GPU
819 if (Gpu::inLaunchRegion()) {
820 const auto& xma = in.const_arrays();
821 const auto& yma = out.arrays();
822 const auto& ama = acoef.arrays();
823 AMREX_D_TERM(const auto& bxma = bxcoef.const_arrays();,
824 const auto& byma = bycoef.const_arrays();,
825 const auto& bzma = bzcoef.const_arrays(););
826 if (this->m_overset_mask[amrlev][mglev]) {
827 const auto& osmma = this->m_overset_mask[amrlev][mglev]->const_arrays();
828 ParallelFor(out, IntVect(0), ncomp,
829 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
830 {
831 mlabeclap_adotx_os(i,j,k,n, yma[box_no], xma[box_no], ama[box_no],
832 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
833 osmma[box_no], dxinv, ascalar, bscalar);
834 });
835 } else {
836 ParallelFor(out, IntVect(0), ncomp,
837 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
838 {
839 mlabeclap_adotx(i,j,k,n, yma[box_no], xma[box_no], ama[box_no],
840 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
841 dxinv, ascalar, bscalar);
842 });
843 }
845 } else
846#endif
847 {
848#ifdef AMREX_USE_OMP
849#pragma omp parallel if (Gpu::notInLaunchRegion())
850#endif
851 for (MFIter mfi(out, TilingIfNotGPU()); mfi.isValid(); ++mfi)
852 {
853 const Box& bx = mfi.tilebox();
854 const auto& xfab = in.array(mfi);
855 const auto& yfab = out.array(mfi);
856 const auto& afab = acoef.array(mfi);
857 AMREX_D_TERM(const auto& bxfab = bxcoef.array(mfi);,
858 const auto& byfab = bycoef.array(mfi);,
859 const auto& bzfab = bzcoef.array(mfi););
860 if (this->m_overset_mask[amrlev][mglev]) {
861 const auto& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
862 AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n,
863 {
864 mlabeclap_adotx_os(i,j,k,n, yfab, xfab, afab, AMREX_D_DECL(bxfab,byfab,bzfab),
865 osm, dxinv, ascalar, bscalar);
866 });
867 } else {
868 AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n,
869 {
870 mlabeclap_adotx(i,j,k,n, yfab, xfab, afab, AMREX_D_DECL(bxfab,byfab,bzfab),
871 dxinv, ascalar, bscalar);
872 });
873 }
874 }
875 }
876}
877
878template <typename MF>
879void
880MLABecLaplacianT<MF>::Fsmooth (int amrlev, int mglev, MF& sol, const MF& rhs, int redblack) const
881{
882 BL_PROFILE("MLABecLaplacian::Fsmooth()");
883
884 bool regular_coarsening = true;
885 if (amrlev == 0 && mglev > 0) {
886 regular_coarsening = this->mg_coarsen_ratio_vec[mglev-1] == this->mg_coarsen_ratio;
887 }
888
889 MF Ax;
890 if (! this->m_use_gauss_seidel && regular_coarsening) { // jacobi
891 Ax.define(sol.boxArray(), sol.DistributionMap(), sol.nComp(), 0);
892 Fapply(amrlev, mglev, Ax, sol);
893 }
894
895 const MF& acoef = m_a_coeffs[amrlev][mglev];
896 AMREX_ALWAYS_ASSERT(acoef.nGrowVect() == 0);
897 AMREX_D_TERM(const MF& bxcoef = m_b_coeffs[amrlev][mglev][0];,
898 const MF& bycoef = m_b_coeffs[amrlev][mglev][1];,
899 const MF& bzcoef = m_b_coeffs[amrlev][mglev][2];);
900 const auto& undrrelxr = this->m_undrrelxr[amrlev][mglev];
901 const auto& maskvals = this->m_maskvals [amrlev][mglev];
902
903 OrientationIter oitr;
904
905 const auto& f0 = undrrelxr[oitr()]; ++oitr;
906 const auto& f1 = undrrelxr[oitr()]; ++oitr;
907#if (AMREX_SPACEDIM > 1)
908 const auto& f2 = undrrelxr[oitr()]; ++oitr;
909 const auto& f3 = undrrelxr[oitr()]; ++oitr;
910#if (AMREX_SPACEDIM > 2)
911 const auto& f4 = undrrelxr[oitr()]; ++oitr;
912 const auto& f5 = undrrelxr[oitr()]; ++oitr;
913#endif
914#endif
915
916 const MultiMask& mm0 = maskvals[0];
917 const MultiMask& mm1 = maskvals[1];
918#if (AMREX_SPACEDIM > 1)
919 const MultiMask& mm2 = maskvals[2];
920 const MultiMask& mm3 = maskvals[3];
921#if (AMREX_SPACEDIM > 2)
922 const MultiMask& mm4 = maskvals[4];
923 const MultiMask& mm5 = maskvals[5];
924#endif
925#endif
926
927 const int nc = this->getNComp();
928 const Real* h = this->m_geom[amrlev][mglev].CellSize();
929 AMREX_D_TERM(const RT dhx = m_b_scalar/static_cast<RT>(h[0]*h[0]);,
930 const RT dhy = m_b_scalar/static_cast<RT>(h[1]*h[1]);,
931 const RT dhz = m_b_scalar/static_cast<RT>(h[2]*h[2]));
932 const RT alpha = m_a_scalar;
933
934#ifdef AMREX_USE_GPU
936 && (this->m_overset_mask[amrlev][mglev] || regular_coarsening))
937 {
938 const auto& m0ma = mm0.const_arrays();
939 const auto& m1ma = mm1.const_arrays();
940#if (AMREX_SPACEDIM > 1)
941 const auto& m2ma = mm2.const_arrays();
942 const auto& m3ma = mm3.const_arrays();
943#if (AMREX_SPACEDIM > 2)
944 const auto& m4ma = mm4.const_arrays();
945 const auto& m5ma = mm5.const_arrays();
946#endif
947#endif
948
949 const auto& solnma = sol.arrays();
950 const auto& rhsma = rhs.const_arrays();
951 const auto& ama = acoef.const_arrays();
952
953 AMREX_D_TERM(const auto& bxma = bxcoef.const_arrays();,
954 const auto& byma = bycoef.const_arrays();,
955 const auto& bzma = bzcoef.const_arrays(););
956
957 const auto& f0ma = f0.const_arrays();
958 const auto& f1ma = f1.const_arrays();
959#if (AMREX_SPACEDIM > 1)
960 const auto& f2ma = f2.const_arrays();
961 const auto& f3ma = f3.const_arrays();
962#if (AMREX_SPACEDIM > 2)
963 const auto& f4ma = f4.const_arrays();
964 const auto& f5ma = f5.const_arrays();
965#endif
966#endif
967
968 if (this->m_overset_mask[amrlev][mglev]) {
969 const auto& osmma = this->m_overset_mask[amrlev][mglev]->const_arrays();
970 if (this->m_use_gauss_seidel) {
971 ParallelFor(sol, IntVect(0), nc,
972 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
973 {
974 Box vbx(ama[box_no]);
975 abec_gsrb_os(i,j,k,n, solnma[box_no], rhsma[box_no], alpha, ama[box_no],
976 AMREX_D_DECL(dhx, dhy, dhz),
977 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
978 AMREX_D_DECL(m0ma[box_no],m2ma[box_no],m4ma[box_no]),
979 AMREX_D_DECL(m1ma[box_no],m3ma[box_no],m5ma[box_no]),
980 AMREX_D_DECL(f0ma[box_no],f2ma[box_no],f4ma[box_no]),
981 AMREX_D_DECL(f1ma[box_no],f3ma[box_no],f5ma[box_no]),
982 osmma[box_no], vbx, redblack);
983 });
984 } else {
985 const auto& axma = Ax.const_arrays();
986 ParallelFor(sol, IntVect(0), nc,
987 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
988 {
989 Box vbx(ama[box_no]);
990 abec_jacobi_os(i,j,k,n, solnma[box_no], rhsma[box_no], axma[box_no],
991 alpha, ama[box_no],
992 AMREX_D_DECL(dhx, dhy, dhz),
993 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
994 AMREX_D_DECL(m0ma[box_no],m2ma[box_no],m4ma[box_no]),
995 AMREX_D_DECL(m1ma[box_no],m3ma[box_no],m5ma[box_no]),
996 AMREX_D_DECL(f0ma[box_no],f2ma[box_no],f4ma[box_no]),
997 AMREX_D_DECL(f1ma[box_no],f3ma[box_no],f5ma[box_no]),
998 osmma[box_no], vbx);
999 });
1000 }
1001 } else if (regular_coarsening) {
1002 if (this->m_use_gauss_seidel) {
1003 ParallelFor(sol, IntVect(0), nc,
1004 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1005 {
1006 Box vbx(ama[box_no]);
1007 abec_gsrb(i,j,k,n, solnma[box_no], rhsma[box_no], alpha, ama[box_no],
1008 AMREX_D_DECL(dhx, dhy, dhz),
1009 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
1010 AMREX_D_DECL(m0ma[box_no],m2ma[box_no],m4ma[box_no]),
1011 AMREX_D_DECL(m1ma[box_no],m3ma[box_no],m5ma[box_no]),
1012 AMREX_D_DECL(f0ma[box_no],f2ma[box_no],f4ma[box_no]),
1013 AMREX_D_DECL(f1ma[box_no],f3ma[box_no],f5ma[box_no]),
1014 vbx, redblack);
1015 });
1016 } else {
1017 const auto& axma = Ax.const_arrays();
1018 ParallelFor(sol, IntVect(0), nc,
1019 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1020 {
1021 Box vbx(ama[box_no]);
1022 abec_jacobi(i,j,k,n, solnma[box_no], rhsma[box_no], axma[box_no],
1023 alpha, ama[box_no],
1024 AMREX_D_DECL(dhx, dhy, dhz),
1025 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
1026 AMREX_D_DECL(m0ma[box_no],m2ma[box_no],m4ma[box_no]),
1027 AMREX_D_DECL(m1ma[box_no],m3ma[box_no],m5ma[box_no]),
1028 AMREX_D_DECL(f0ma[box_no],f2ma[box_no],f4ma[box_no]),
1029 AMREX_D_DECL(f1ma[box_no],f3ma[box_no],f5ma[box_no]),
1030 vbx);
1031 });
1032 }
1033 }
1035 } else
1036#endif
1037 {
1038 MFItInfo mfi_info;
1039 mfi_info.EnableTiling().SetDynamic(true);
1040
1041#ifdef AMREX_USE_OMP
1042#pragma omp parallel if (Gpu::notInLaunchRegion())
1043#endif
1044 for (MFIter mfi(sol,mfi_info); mfi.isValid(); ++mfi)
1045 {
1046 const auto& m0 = mm0.array(mfi);
1047 const auto& m1 = mm1.array(mfi);
1048#if (AMREX_SPACEDIM > 1)
1049 const auto& m2 = mm2.array(mfi);
1050 const auto& m3 = mm3.array(mfi);
1051#if (AMREX_SPACEDIM > 2)
1052 const auto& m4 = mm4.array(mfi);
1053 const auto& m5 = mm5.array(mfi);
1054#endif
1055#endif
1056
1057 const Box& tbx = mfi.tilebox();
1058 const Box& vbx = mfi.validbox();
1059 const auto& solnfab = sol.array(mfi);
1060 const auto& rhsfab = rhs.const_array(mfi);
1061 const auto& afab = acoef.const_array(mfi);
1062
1063 AMREX_D_TERM(const auto& bxfab = bxcoef.const_array(mfi);,
1064 const auto& byfab = bycoef.const_array(mfi);,
1065 const auto& bzfab = bzcoef.const_array(mfi););
1066
1067 const auto& f0fab = f0.const_array(mfi);
1068 const auto& f1fab = f1.const_array(mfi);
1069#if (AMREX_SPACEDIM > 1)
1070 const auto& f2fab = f2.const_array(mfi);
1071 const auto& f3fab = f3.const_array(mfi);
1072#if (AMREX_SPACEDIM > 2)
1073 const auto& f4fab = f4.const_array(mfi);
1074 const auto& f5fab = f5.const_array(mfi);
1075#endif
1076#endif
1077
1078 if (this->m_overset_mask[amrlev][mglev]) {
1079 const auto& osm = this->m_overset_mask[amrlev][mglev]->const_array(mfi);
1080 if (this->m_use_gauss_seidel) {
1081 AMREX_LOOP_4D(tbx, nc, i, j, k, n,
1082 {
1083 abec_gsrb_os(i,j,k,n, solnfab, rhsfab, alpha, afab,
1084 AMREX_D_DECL(dhx, dhy, dhz),
1085 AMREX_D_DECL(bxfab, byfab, bzfab),
1086 AMREX_D_DECL(m0,m2,m4),
1087 AMREX_D_DECL(m1,m3,m5),
1088 AMREX_D_DECL(f0fab,f2fab,f4fab),
1089 AMREX_D_DECL(f1fab,f3fab,f5fab),
1090 osm, vbx, redblack);
1091 });
1092 } else {
1093 const auto& axfab = Ax.const_array(mfi);
1094 AMREX_LOOP_4D(tbx, nc, i, j, k, n,
1095 {
1096 abec_jacobi_os(i,j,k,n, solnfab, rhsfab, axfab,
1097 alpha, afab,
1098 AMREX_D_DECL(dhx, dhy, dhz),
1099 AMREX_D_DECL(bxfab, byfab, bzfab),
1100 AMREX_D_DECL(m0,m2,m4),
1101 AMREX_D_DECL(m1,m3,m5),
1102 AMREX_D_DECL(f0fab,f2fab,f4fab),
1103 AMREX_D_DECL(f1fab,f3fab,f5fab),
1104 osm, vbx);
1105 });
1106 }
1107 } else if (regular_coarsening) {
1108 if (this->m_use_gauss_seidel) {
1109 AMREX_LOOP_4D(tbx, nc, i, j, k, n,
1110 {
1111 abec_gsrb(i,j,k,n, solnfab, rhsfab, alpha, afab,
1112 AMREX_D_DECL(dhx, dhy, dhz),
1113 AMREX_D_DECL(bxfab, byfab, bzfab),
1114 AMREX_D_DECL(m0,m2,m4),
1115 AMREX_D_DECL(m1,m3,m5),
1116 AMREX_D_DECL(f0fab,f2fab,f4fab),
1117 AMREX_D_DECL(f1fab,f3fab,f5fab),
1118 vbx, redblack);
1119 });
1120 } else {
1121 const auto& axfab = Ax.const_array(mfi);
1122 AMREX_LOOP_4D(tbx, nc, i, j, k, n,
1123 {
1124 abec_jacobi(i,j,k,n, solnfab, rhsfab, axfab,
1125 alpha, afab,
1126 AMREX_D_DECL(dhx, dhy, dhz),
1127 AMREX_D_DECL(bxfab, byfab, bzfab),
1128 AMREX_D_DECL(m0,m2,m4),
1129 AMREX_D_DECL(m1,m3,m5),
1130 AMREX_D_DECL(f0fab,f2fab,f4fab),
1131 AMREX_D_DECL(f1fab,f3fab,f5fab),
1132 vbx);
1133 });
1134 }
1135 } else {
1136 // line solve does not with with GPU
1137 abec_gsrb_with_line_solve(tbx, solnfab, rhsfab, alpha, afab,
1138 AMREX_D_DECL(dhx, dhy, dhz),
1139 AMREX_D_DECL(bxfab, byfab, bzfab),
1140 AMREX_D_DECL(m0,m2,m4),
1141 AMREX_D_DECL(m1,m3,m5),
1142 AMREX_D_DECL(f0fab,f2fab,f4fab),
1143 AMREX_D_DECL(f1fab,f3fab,f5fab),
1144 vbx, redblack, nc);
1145 }
1146 }
1147 }
1148}
1149
1150template <typename MF>
1151void
1152MLABecLaplacianT<MF>::FFlux (int amrlev, const MFIter& mfi,
1153 const Array<FAB*,AMREX_SPACEDIM>& flux,
1154 const FAB& sol, Location, int face_only) const
1155{
1156 BL_PROFILE("MLABecLaplacian::FFlux()");
1157
1158 const int mglev = 0;
1159 const Box& box = mfi.tilebox();
1160 const Real* dxinv = this->m_geom[amrlev][mglev].InvCellSize();
1161 const int ncomp = this->getNComp();
1162 FFlux(box, dxinv, m_b_scalar,
1163 Array<FAB const*,AMREX_SPACEDIM>{{AMREX_D_DECL(&(m_b_coeffs[amrlev][mglev][0][mfi]),
1164 &(m_b_coeffs[amrlev][mglev][1][mfi]),
1165 &(m_b_coeffs[amrlev][mglev][2][mfi]))}},
1166 flux, sol, face_only, ncomp);
1167}
1168
1169template <typename MF>
1170void
1171MLABecLaplacianT<MF>::FFlux (Box const& box, Real const* dxinv, RT bscalar,
1173 Array<FAB*,AMREX_SPACEDIM> const& flux,
1174 FAB const& sol, int face_only, int ncomp)
1175{
1176 AMREX_D_TERM(const auto bx = bcoef[0]->const_array();,
1177 const auto by = bcoef[1]->const_array();,
1178 const auto bz = bcoef[2]->const_array(););
1179 AMREX_D_TERM(const auto& fxarr = flux[0]->array();,
1180 const auto& fyarr = flux[1]->array();,
1181 const auto& fzarr = flux[2]->array(););
1182 const auto& solarr = sol.array();
1183
1184 if (face_only)
1185 {
1186 RT fac = bscalar*static_cast<RT>(dxinv[0]);
1187 Box blo = amrex::bdryLo(box, 0);
1188 int blen = box.length(0);
1190 {
1191 mlabeclap_flux_xface(tbox, fxarr, solarr, bx, fac, blen, ncomp);
1192 });
1193#if (AMREX_SPACEDIM >= 2)
1194 fac = bscalar*static_cast<RT>(dxinv[1]);
1195 blo = amrex::bdryLo(box, 1);
1196 blen = box.length(1);
1198 {
1199 mlabeclap_flux_yface(tbox, fyarr, solarr, by, fac, blen, ncomp);
1200 });
1201#endif
1202#if (AMREX_SPACEDIM == 3)
1203 fac = bscalar*static_cast<RT>(dxinv[2]);
1204 blo = amrex::bdryLo(box, 2);
1205 blen = box.length(2);
1207 {
1208 mlabeclap_flux_zface(tbox, fzarr, solarr, bz, fac, blen, ncomp);
1209 });
1210#endif
1211 }
1212 else
1213 {
1214 RT fac = bscalar*static_cast<RT>(dxinv[0]);
1215 Box bflux = amrex::surroundingNodes(box, 0);
1217 {
1218 mlabeclap_flux_x(tbox, fxarr, solarr, bx, fac, ncomp);
1219 });
1220#if (AMREX_SPACEDIM >= 2)
1221 fac = bscalar*static_cast<RT>(dxinv[1]);
1222 bflux = amrex::surroundingNodes(box, 1);
1224 {
1225 mlabeclap_flux_y(tbox, fyarr, solarr, by, fac, ncomp);
1226 });
1227#endif
1228#if (AMREX_SPACEDIM == 3)
1229 fac = bscalar*static_cast<RT>(dxinv[2]);
1230 bflux = amrex::surroundingNodes(box, 2);
1232 {
1233 mlabeclap_flux_z(tbox, fzarr, solarr, bz, fac, ncomp);
1234 });
1235#endif
1236 }
1237}
1238
1239template <typename MF>
1240void
1241MLABecLaplacianT<MF>::normalize (int amrlev, int mglev, MF& mf) const
1242{
1243 BL_PROFILE("MLABecLaplacian::normalize()");
1244
1245 const auto& acoef = m_a_coeffs[amrlev][mglev];
1246 AMREX_D_TERM(const auto& bxcoef = m_b_coeffs[amrlev][mglev][0];,
1247 const auto& bycoef = m_b_coeffs[amrlev][mglev][1];,
1248 const auto& bzcoef = m_b_coeffs[amrlev][mglev][2];);
1249
1250 const GpuArray<RT,AMREX_SPACEDIM> dxinv
1251 {AMREX_D_DECL(static_cast<RT>(this->m_geom[amrlev][mglev].InvCellSize(0)),
1252 static_cast<RT>(this->m_geom[amrlev][mglev].InvCellSize(1)),
1253 static_cast<RT>(this->m_geom[amrlev][mglev].InvCellSize(2)))};
1254
1255 const RT ascalar = m_a_scalar;
1256 const RT bscalar = m_b_scalar;
1257
1258 const int ncomp = getNComp();
1259
1260#ifdef AMREX_USE_GPU
1261 if (Gpu::inLaunchRegion()) {
1262 const auto& ma = mf.arrays();
1263 const auto& ama = acoef.const_arrays();
1264 AMREX_D_TERM(const auto& bxma = bxcoef.const_arrays();,
1265 const auto& byma = bycoef.const_arrays();,
1266 const auto& bzma = bzcoef.const_arrays(););
1267 ParallelFor(mf, IntVect(0), ncomp,
1268 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1269 {
1270 mlabeclap_normalize(i,j,k,n, ma[box_no], ama[box_no],
1271 AMREX_D_DECL(bxma[box_no],byma[box_no],bzma[box_no]),
1272 dxinv, ascalar, bscalar);
1273 });
1275 } else
1276#endif
1277 {
1278#ifdef AMREX_USE_OMP
1279#pragma omp parallel if (Gpu::notInLaunchRegion())
1280#endif
1281 for (MFIter mfi(mf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
1282 {
1283 const Box& bx = mfi.tilebox();
1284 const auto& fab = mf.array(mfi);
1285 const auto& afab = acoef.array(mfi);
1286 AMREX_D_TERM(const auto& bxfab = bxcoef.array(mfi);,
1287 const auto& byfab = bycoef.array(mfi);,
1288 const auto& bzfab = bzcoef.array(mfi););
1289
1290 AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n,
1291 {
1292 mlabeclap_normalize(i,j,k,n, fab, afab, AMREX_D_DECL(bxfab,byfab,bzfab),
1293 dxinv, ascalar, bscalar);
1294 });
1295 }
1296 }
1297}
1298
1299template <typename MF>
1300bool
1302{
1303 bool support = false;
1304 if (this->m_overset_mask[0][0]) {
1305 if (this->m_geom[0].back().Domain().coarsenable(MLLinOp::mg_coarsen_ratio,
1306 this->mg_domain_min_width)
1307 && this->m_grids[0].back().coarsenable(MLLinOp::mg_coarsen_ratio, MLLinOp::mg_box_min_width))
1308 {
1309 support = true;
1310 }
1311 }
1312 return support;
1313}
1314
1315template <typename MF>
1316std::unique_ptr<MLLinOpT<MF>>
1317MLABecLaplacianT<MF>::makeNLinOp (int /*grid_size*/) const
1318{
1319 if (this->m_overset_mask[0][0] == nullptr) { return nullptr; }
1320
1321 const Geometry& geom = this->m_geom[0].back();
1322 const BoxArray& ba = this->m_grids[0].back();
1323 const DistributionMapping& dm = this->m_dmap[0].back();
1324
1325 std::unique_ptr<MLLinOpT<MF>> r
1326 {new MLABecLaplacianT<MF>({geom}, {ba}, {dm}, this->m_lpinfo_arg)};
1327
1328 auto nop = dynamic_cast<MLABecLaplacianT<MF>*>(r.get());
1329 if (!nop) {
1330 return nullptr;
1331 }
1332
1333 nop->m_parent = this;
1334
1335 nop->setMaxOrder(this->maxorder);
1336 nop->setVerbose(this->verbose);
1337
1338 nop->setDomainBC(this->m_lobc, this->m_hibc);
1339
1340 if (this->needsCoarseDataForBC())
1341 {
1342 const Real* dx0 = this->m_geom[0][0].CellSize();
1343 RealVect fac(this->m_coarse_data_crse_ratio);
1344 fac *= Real(0.5);
1345 RealVect cbloc {AMREX_D_DECL(dx0[0]*fac[0], dx0[1]*fac[1], dx0[2]*fac[2])};
1346 nop->setCoarseFineBCLocation(cbloc);
1347 }
1348
1349 nop->setScalars(m_a_scalar, m_b_scalar);
1350
1351 MF const& alpha_bottom = m_a_coeffs[0].back();
1352 iMultiFab const& osm_bottom = *(this->m_overset_mask[0].back());
1353 const int ncomp = alpha_bottom.nComp();
1354 MF alpha(ba, dm, ncomp, 0);
1355
1356 RT a_max = alpha_bottom.norminf(0, ncomp, IntVect(0), true, true);
1357 const int ncomp_b = m_b_coeffs[0].back()[0].nComp();
1358 AMREX_D_TERM(RT bx_max = m_b_coeffs[0].back()[0].norminf(0,ncomp_b,IntVect(0),true,true);,
1359 RT by_max = m_b_coeffs[0].back()[1].norminf(0,ncomp_b,IntVect(0),true,true);,
1360 RT bz_max = m_b_coeffs[0].back()[2].norminf(0,ncomp_b,IntVect(0),true,true));
1361 const GpuArray<RT,AMREX_SPACEDIM> dxinv
1362 {AMREX_D_DECL(static_cast<RT>(geom.InvCellSize(0)),
1363 static_cast<RT>(geom.InvCellSize(1)),
1364 static_cast<RT>(geom.InvCellSize(2)))};
1365 RT huge_alpha = RT(1.e30) *
1366 amrex::max(a_max*std::abs(m_a_scalar),
1367 AMREX_D_DECL(std::abs(m_b_scalar)*bx_max*dxinv[0]*dxinv[0],
1368 std::abs(m_b_scalar)*by_max*dxinv[1]*dxinv[1],
1369 std::abs(m_b_scalar)*bz_max*dxinv[2]*dxinv[2]));
1371
1372#ifdef AMREX_USE_GPU
1373 if (Gpu::inLaunchRegion() && alpha.isFusingCandidate()) {
1374 auto const& ama = alpha.arrays();
1375 auto const& abotma = alpha_bottom.const_arrays();
1376 auto const& mma = osm_bottom.const_arrays();
1377 ParallelFor(alpha, IntVect(0), ncomp,
1378 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1379 {
1380 if (mma[box_no](i,j,k)) {
1381 ama[box_no](i,j,k,n) = abotma[box_no](i,j,k,n);
1382 } else {
1383 ama[box_no](i,j,k,n) = huge_alpha;
1384 }
1385 });
1387 } else
1388#endif
1389 {
1390#ifdef AMREX_USE_OMP
1391#pragma omp parallel if (Gpu::notInLaunchRegion())
1392#endif
1393 for (MFIter mfi(alpha,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
1394 Box const& bx = mfi.tilebox();
1395 auto const& a = alpha.array(mfi);
1396 auto const& abot = alpha_bottom.const_array(mfi);
1397 auto const& m = osm_bottom.const_array(mfi);
1398 AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n,
1399 {
1400 if (m(i,j,k)) {
1401 a(i,j,k,n) = abot(i,j,k,n);
1402 } else {
1403 a(i,j,k,n) = huge_alpha;
1404 }
1405 });
1406 }
1407 }
1408
1409 nop->setACoeffs(0, alpha);
1410 nop->setBCoeffs(0, GetArrOfConstPtrs(m_b_coeffs[0].back()));
1411
1412 return r;
1413}
1414
1415template <typename MF>
1416void
1417MLABecLaplacianT<MF>::copyNSolveSolution (MF& dst, MF const& src) const
1418{
1419 if (this->m_overset_mask[0].back() == nullptr) { return; }
1420
1421 const int ncomp = dst.nComp();
1422
1423#ifdef AMREX_USE_GPU
1424 if (Gpu::inLaunchRegion() && dst.isFusingCandidate()) {
1425 auto const& dstma = dst.arrays();
1426 auto const& srcma = src.const_arrays();
1427 auto const& mma = this->m_overset_mask[0].back()->const_arrays();
1428 ParallelFor(dst, IntVect(0), ncomp,
1429 [=] AMREX_GPU_DEVICE (int box_no, int i, int j, int k, int n) noexcept
1430 {
1431 if (mma[box_no](i,j,k)) {
1432 dstma[box_no](i,j,k,n) = srcma[box_no](i,j,k,n);
1433 } else {
1434 dstma[box_no](i,j,k,n) = RT(0.0);
1435 }
1436 });
1438 } else
1439#endif
1440 {
1441#ifdef AMREX_USE_OMP
1442#pragma omp parallel if (Gpu::notInLaunchRegion())
1443#endif
1444 for (MFIter mfi(dst,TilingIfNotGPU()); mfi.isValid(); ++mfi) {
1445 Box const& bx = mfi.tilebox();
1446 auto const& dfab = dst.array(mfi);
1447 auto const& sfab = src.const_array(mfi);
1448 auto const& m = this->m_overset_mask[0].back()->const_array(mfi);
1449 AMREX_HOST_DEVICE_PARALLEL_FOR_4D(bx, ncomp, i, j, k, n,
1450 {
1451 if (m(i,j,k)) {
1452 dfab(i,j,k,n) = sfab(i,j,k,n);
1453 } else {
1454 dfab(i,j,k,n) = RT(0.0);
1455 }
1456 });
1457 }
1458 }
1459}
1460
1461extern template class MLABecLaplacianT<MultiFab>;
1462
1464
1465}
1466
1467#endif
#define BL_PROFILE(a)
Definition AMReX_BLProfiler.H:551
#define AMREX_ALWAYS_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:49
#define AMREX_ASSERT_WITH_MESSAGE(EX, MSG)
Definition AMReX_BLassert.H:37
#define AMREX_ASSERT(EX)
Definition AMReX_BLassert.H:38
#define AMREX_ALWAYS_ASSERT(EX)
Definition AMReX_BLassert.H:50
#define AMREX_GPU_LAUNCH_HOST_DEVICE_LAMBDA_RANGE(TN, TI, block)
Definition AMReX_GpuLaunchMacrosC.nolint.H:4
#define AMREX_HOST_DEVICE_FOR_3D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:106
#define AMREX_HOST_DEVICE_PARALLEL_FOR_4D(...)
Definition AMReX_GpuLaunchMacrosC.nolint.H:111
#define AMREX_LAUNCH_HOST_DEVICE_LAMBDA_DIM(a1, a2, a3, b1, b2, b3, c1, c2, c3)
Definition AMReX_GpuLaunch.nolint.H:29
#define AMREX_GPU_DEVICE
Definition AMReX_GpuQualifiers.H:18
Array4< Real > fine
Definition AMReX_InterpFaceRegister.cpp:90
Array4< Real const > crse
Definition AMReX_InterpFaceRegister.cpp:92
#define AMREX_LOOP_4D(bx, ncomp, i, j, k, n, block)
Definition AMReX_Loop.nolint.H:16
#define AMREX_D_TERM(a, b, c)
Definition AMReX_SPACE.H:129
A collection of Boxes stored in an Array.
Definition AMReX_BoxArray.H:550
AMREX_GPU_HOST_DEVICE IntVectND< dim > length() const noexcept
Return the length of the BoxND.
Definition AMReX_Box.H:146
AMREX_GPU_HOST_DEVICE bool contains(const IntVectND< dim > &p) const noexcept
Returns true if argument is contained within BoxND.
Definition AMReX_Box.H:204
const Real * InvCellSize() const noexcept
Returns the inverse cellsize for each coordinate direction.
Definition AMReX_CoordSys.H:82
Calculates the distribution of FABs to MPI processes.
Definition AMReX_DistributionMapping.H:41
int nComp() const noexcept
Return number of variables (aka components) associated with each point.
Definition AMReX_FabArrayBase.H:82
Array4< typename FabArray< FAB >::value_type const > const_array(const MFIter &mfi) const noexcept
Definition AMReX_FabArray.H:584
MultiArray4< typename FabArray< FAB >::value_type const > const_arrays() const noexcept
Definition AMReX_FabArray.H:646
Definition AMReX_FabFactory.H:50
Rectangular problem domain geometry.
Definition AMReX_Geometry.H:73
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE constexpr IntVectND< dim > TheDimensionVector(int d) noexcept
This static member function returns a reference to a constant IntVectND object, all of whose dim argu...
Definition AMReX_IntVect.H:691
Definition AMReX_MFIter.H:57
Box tilebox() const noexcept
Return the tile Box at the current index.
Definition AMReX_MFIter.cpp:385
bool isValid() const noexcept
Is the iterator valid i.e. is it associated with a FAB?
Definition AMReX_MFIter.H:141
Definition AMReX_MLABecLaplacian.H:15
void setACoeffs(int amrlev, const AMF &alpha)
Definition AMReX_MLABecLaplacian.H:325
RT getBScalar() const final
Definition AMReX_MLABecLaplacian.H:167
int getNComp() const override
Return number of components.
Definition AMReX_MLABecLaplacian.H:147
int m_ncomp
Definition AMReX_MLABecLaplacian.H:211
bool isSingular(int amrlev) const override
Is it singular on given AMR level?
Definition AMReX_MLABecLaplacian.H:155
LinOpBCType BCType
Definition AMReX_MLABecLaplacian.H:21
Array< MF const *, AMREX_SPACEDIM > getBCoeffs(int amrlev, int mglev) const final
Definition AMReX_MLABecLaplacian.H:170
void applyRobinBCTermsCoeffs()
Definition AMReX_MLABecLaplacian.H:603
void update_singular_flags()
Definition AMReX_MLABecLaplacian.H:738
typename MF::fab_type FAB
Definition AMReX_MLABecLaplacian.H:18
MLABecLaplacianT< MF > & operator=(const MLABecLaplacianT< MF > &)=delete
bool supportRobinBC() const noexcept override
Definition AMReX_MLABecLaplacian.H:207
RT m_b_scalar
Definition AMReX_MLABecLaplacian.H:194
typename MF::value_type RT
Definition AMReX_MLABecLaplacian.H:19
~MLABecLaplacianT() override
void prepareForSolve() override
Definition AMReX_MLABecLaplacian.H:423
void define(const Vector< Geometry > &a_geom, const Vector< BoxArray > &a_grids, const Vector< DistributionMapping > &a_dmap, const LPInfo &a_info=LPInfo(), const Vector< FabFactory< FAB > const * > &a_factory={}, int a_ncomp=1)
Definition AMReX_MLABecLaplacian.H:245
RT m_a_scalar
Definition AMReX_MLABecLaplacian.H:193
void define_ab_coeffs()
Definition AMReX_MLABecLaplacian.H:276
void averageDownCoeffsSameAmrLevel(int amrlev, Vector< MF > &a, Vector< Array< MF, AMREX_SPACEDIM > > &b)
Definition AMReX_MLABecLaplacian.H:630
void Fapply(int amrlev, int mglev, MF &out, const MF &in) const final
Definition AMReX_MLABecLaplacian.H:799
void averageDownCoeffsToCoarseAmrLevel(int flev)
Definition AMReX_MLABecLaplacian.H:717
bool m_scalars_set
Definition AMReX_MLABecLaplacian.H:198
Vector< int > m_is_singular
Definition AMReX_MLABecLaplacian.H:205
void setBCoeffs(int amrlev, const Array< AMF const *, AMREX_SPACEDIM > &beta)
Definition AMReX_MLABecLaplacian.H:352
void normalize(int amrlev, int mglev, MF &mf) const final
Divide mf by the diagonal component of the operator. Used by bicgstab.
Definition AMReX_MLABecLaplacian.H:1241
void averageDownCoeffs()
Definition AMReX_MLABecLaplacian.H:612
RT getAScalar() const final
Definition AMReX_MLABecLaplacian.H:166
bool m_needs_update
Definition AMReX_MLABecLaplacian.H:203
bool supportNSolve() const final
Definition AMReX_MLABecLaplacian.H:1301
std::unique_ptr< MLLinOpT< MF > > makeNLinOp(int) const final
Definition AMReX_MLABecLaplacian.H:1317
bool m_acoef_set
Definition AMReX_MLABecLaplacian.H:199
MLABecLaplacianT(MLABecLaplacianT< MF > &&)=delete
Vector< Vector< MF > > m_a_coeffs
Definition AMReX_MLABecLaplacian.H:195
void Fsmooth(int amrlev, int mglev, MF &sol, const MF &rhs, int redblack) const final
Definition AMReX_MLABecLaplacian.H:880
bool isBottomSingular() const override
Is the bottom of MG singular?
Definition AMReX_MLABecLaplacian.H:156
void applyMetricTermsCoeffs()
Definition AMReX_MLABecLaplacian.H:444
void copyNSolveSolution(MF &dst, MF const &src) const final
Definition AMReX_MLABecLaplacian.H:1417
typename MLLinOpT< MF >::Location Location
Definition AMReX_MLABecLaplacian.H:22
MF const * getACoeffs(int amrlev, int mglev) const final
Definition AMReX_MLABecLaplacian.H:168
void update() override
Update for reuse.
Definition AMReX_MLABecLaplacian.H:402
void FFlux(int amrlev, const MFIter &mfi, const Array< FAB *, AMREX_SPACEDIM > &flux, const FAB &sol, Location, int face_only=0) const final
Definition AMReX_MLABecLaplacian.H:1152
bool needsUpdate() const override
Does it need update if it's reused?
Definition AMReX_MLABecLaplacian.H:149
void setScalars(T1 a, T2 b) noexcept
Definition AMReX_MLABecLaplacian.H:306
MLABecLaplacianT(const MLABecLaplacianT< MF > &)=delete
Vector< Vector< Array< MF, AMREX_SPACEDIM > > > m_b_coeffs
Definition AMReX_MLABecLaplacian.H:196
Definition AMReX_MLCellABecLap.H:13
void define(const Vector< Geometry > &a_geom, const Vector< BoxArray > &a_grids, const Vector< DistributionMapping > &a_dmap, const LPInfo &a_info=LPInfo(), const Vector< FabFactory< FAB > const * > &a_factory={})
Definition AMReX_MLCellABecLap.H:94
void prepareForSolve() override
Definition AMReX_MLCellABecLap.H:247
void update() override
Update for reuse.
Definition AMReX_MLCellABecLap.H:240
static constexpr int mg_coarsen_ratio
Definition AMReX_MLLinOp.H:580
static constexpr int mg_box_min_width
Definition AMReX_MLLinOp.H:581
const MLLinOpT< MF > * m_parent
Definition AMReX_MLLinOp.H:596
Definition AMReX_MultiMask.H:18
MultiArray4< int const > const_arrays() const noexcept
Definition AMReX_MultiMask.H:48
Array4< int const > array(const MFIter &mfi) const noexcept
Definition AMReX_MultiMask.H:40
An Iterator over the Orientation of Faces of a Box.
Definition AMReX_Orientation.H:135
A Real vector in SpaceDim-dimensional space.
Definition AMReX_RealVect.H:32
This class is a thin wrapper around std::vector. Unlike vector, Vector::operator[] provides bound che...
Definition AMReX_Vector.H:27
Long size() const noexcept
Definition AMReX_Vector.H:50
Definition AMReX_iMultiFab.H:32
void streamSynchronize() noexcept
Definition AMReX_GpuDevice.H:237
bool inLaunchRegion() noexcept
Definition AMReX_GpuControl.H:86
bool notInLaunchRegion() noexcept
Definition AMReX_GpuControl.H:87
void Max(KeyValuePair< K, V > &vi, MPI_Comm comm)
Definition AMReX_ParallelReduce.H:126
MPI_Comm CommunicatorSub() noexcept
sub-communicator for current frame
Definition AMReX_ParallelContext.H:70
void applyRobinBCTermsCoeffs(LP &linop)
Definition AMReX_MLABecLaplacian.H:488
Definition AMReX_Amr.cpp:49
MF::value_type norminf(MF const &mf, int scomp, int ncomp, IntVect const &nghost, bool local=false)
Definition AMReX_FabArrayUtility.H:1883
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void overset_rescale_bcoef_x(Box const &box, Array4< T > const &bX, Array4< int const > const &osm, int ncomp, T osfac) noexcept
Definition AMReX_MLABecLap_1D_K.H:239
int nComp(FabArrayBase const &fa)
std::enable_if_t< std::is_integral_v< T > > ParallelFor(TypeList< CTOs... > ctos, std::array< int, sizeof...(CTOs)> const &runtime_options, T N, F &&f)
Definition AMReX_CTOParallelForImpl.H:191
void average_down(const MultiFab &S_fine, MultiFab &S_crse, const Geometry &fgeom, const Geometry &cgeom, int scomp, int ncomp, int rr)
Definition AMReX_MultiFabUtil.cpp:314
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > surroundingNodes(const BoxND< dim > &b, int dir) noexcept
Returns a BoxND with NODE based coordinates in direction dir that encloses BoxND b....
Definition AMReX_Box.H:1399
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > convert(const BoxND< dim > &b, const IntVectND< dim > &typ) noexcept
Returns a BoxND with different type.
Definition AMReX_Box.H:1435
void average_down_faces(const Vector< const MF * > &fine, const Vector< MF * > &crse, const IntVect &ratio, int ngcrse=0)
Average fine face-based FabArray onto crse face-based FabArray.
Definition AMReX_MultiFabUtil.H:851
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > adjCellLo(const BoxND< dim > &b, int dir, int len=1) noexcept
Returns the cell centered BoxND of length len adjacent to b on the low end along the coordinate direc...
Definition AMReX_Box.H:1591
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_adotx_os(int i, int, int, int n, Array4< T > const &y, Array4< T const > const &x, Array4< T const > const &a, Array4< T const > const &bX, Array4< int const > const &osm, GpuArray< T, AMREX_SPACEDIM > const &dxinv, T alpha, T beta) noexcept
Definition AMReX_MLABecLap_1D_K.H:24
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_flux_x(Box const &box, Array4< T > const &fx, Array4< T const > const &sol, Array4< T const > const &bx, T fac, int ncomp) noexcept
Definition AMReX_MLABecLap_1D_K.H:56
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_flux_z(Box const &box, Array4< T > const &fz, Array4< T const > const &sol, Array4< T const > const &bz, T fac, int ncomp) noexcept
Definition AMReX_MLABecLap_3D_K.H:163
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_flux_y(Box const &box, Array4< T > const &fy, Array4< T const > const &sol, Array4< T const > const &by, T fac, int ncomp) noexcept
Definition AMReX_MLABecLap_2D_K.H:104
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 end(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1890
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void abec_gsrb_os(int i, int, int, int n, Array4< T > const &phi, Array4< T const > const &rhs, T alpha, Array4< T const > const &a, T dhx, Array4< T const > const &bX, Array4< int const > const &m0, Array4< int const > const &m1, Array4< T const > const &f0, Array4< T const > const &f1, Array4< int const > const &osm, Box const &vbox, int redblack) noexcept
Definition AMReX_MLABecLap_1D_K.H:121
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void overset_rescale_bcoef_y(Box const &box, Array4< T > const &bY, Array4< int const > const &osm, int ncomp, T osfac) noexcept
Definition AMReX_MLABecLap_2D_K.H:437
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void abec_jacobi(int i, int, int, int n, Array4< T > const &phi, Array4< T const > const &rhs, Array4< T const > const &Ax, T alpha, Array4< T const > const &a, T dhx, Array4< T const > const &bX, Array4< int const > const &m0, Array4< int const > const &m1, Array4< T const > const &f0, Array4< T const > const &f1, Box const &vbox) noexcept
Definition AMReX_MLABecLap_1D_K.H:160
IntVectND< AMREX_SPACEDIM > IntVect
Definition AMReX_BaseFwd.H:30
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > bdryLo(const BoxND< dim > &b, int dir, int len=1) noexcept
Returns the edge-centered BoxND (in direction dir) defining the low side of BoxND b.
Definition AMReX_Box.H:1502
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void abec_gsrb(int i, int, int, int n, Array4< T > const &phi, Array4< T const > const &rhs, T alpha, Array4< T const > const &a, T dhx, Array4< T const > const &bX, Array4< int const > const &m0, Array4< int const > const &m1, Array4< T const > const &f0, Array4< T const > const &f1, Box const &vbox, int redblack) noexcept
Definition AMReX_MLABecLap_1D_K.H:87
AMREX_FORCE_INLINE void abec_gsrb_with_line_solve(Box const &, Array4< T > const &, Array4< T const > const &, T, Array4< T const > const &, T, Array4< T const > const &, Array4< int const > const &, Array4< int const > const &, Array4< T const > const &, Array4< T const > const &, Box const &, int, int) noexcept
Definition AMReX_MLABecLap_1D_K.H:223
std::array< T *, AMREX_SPACEDIM > GetArrOfPtrs(std::array< T, AMREX_SPACEDIM > &a) noexcept
Definition AMReX_Array.H:852
bool TilingIfNotGPU() noexcept
Definition AMReX_MFIter.H:12
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE Dim3 begin(BoxND< dim > const &box) noexcept
Definition AMReX_Box.H:1881
std::array< T const *, AMREX_SPACEDIM > GetArrOfConstPtrs(const std::array< T, AMREX_SPACEDIM > &a) noexcept
Definition AMReX_Array.H:864
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_flux_yface(Box const &box, Array4< T > const &fy, Array4< T const > const &sol, Array4< T const > const &by, T fac, int ylen, int ncomp) noexcept
Definition AMReX_MLABecLap_2D_K.H:122
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_normalize(int i, int, int, int n, Array4< T > const &x, Array4< T const > const &a, Array4< T const > const &bX, GpuArray< T, AMREX_SPACEDIM > const &dxinv, T alpha, T beta) noexcept
Definition AMReX_MLABecLap_1D_K.H:44
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE constexpr const T & max(const T &a, const T &b) noexcept
Definition AMReX_Algorithm.H:35
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_flux_zface(Box const &box, Array4< T > const &fz, Array4< T const > const &sol, Array4< T const > const &bz, T fac, int zlen, int ncomp) noexcept
Definition AMReX_MLABecLap_3D_K.H:183
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE BoxND< dim > adjCellHi(const BoxND< dim > &b, int dir, int len=1) noexcept
Similar to adjCellLo but builds an adjacent BoxND on the high end.
Definition AMReX_Box.H:1612
int verbose
Definition AMReX_DistributionMapping.cpp:36
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void abec_jacobi_os(int i, int, int, int n, Array4< T > const &phi, Array4< T const > const &rhs, Array4< T const > const &Ax, T alpha, Array4< T const > const &a, T dhx, Array4< T const > const &bX, Array4< int const > const &m0, Array4< int const > const &m1, Array4< T const > const &f0, Array4< T const > const &f1, Array4< int const > const &osm, Box const &vbox) noexcept
Definition AMReX_MLABecLap_1D_K.H:189
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_flux_xface(Box const &box, Array4< T > const &fx, Array4< T const > const &sol, Array4< T const > const &bx, T fac, int xlen, int ncomp) noexcept
Definition AMReX_MLABecLap_1D_K.H:72
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void overset_rescale_bcoef_z(Box const &box, Array4< T > const &bZ, Array4< int const > const &osm, int ncomp, T osfac) noexcept
Definition AMReX_MLABecLap_3D_K.H:777
std::array< T, N > Array
Definition AMReX_Array.H:24
AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE void mlabeclap_adotx(int i, int, int, int n, Array4< T > const &y, Array4< T const > const &x, Array4< T const > const &a, Array4< T const > const &bX, GpuArray< T, AMREX_SPACEDIM > const &dxinv, T alpha, T beta) noexcept
Definition AMReX_MLABecLap_1D_K.H:9
Definition AMReX_FabArrayCommI.H:896
Definition AMReX_Array.H:34
Definition AMReX_MLLinOp.H:35
Location
Definition AMReX_MLLinOp.H:87
FabArray memory allocation information.
Definition AMReX_FabArray.H:66
Definition AMReX_MFIter.H:20
MFItInfo & SetDynamic(bool f) noexcept
Definition AMReX_MFIter.H:34
MFItInfo & EnableTiling(const IntVect &ts=FabArrayBase::mfiter_tile_size) noexcept
Definition AMReX_MFIter.H:29