90 BL_PROFILE(
"Operator::Fsmooth()");
92 amrex::Box domain(m_geom[amrlev][mglev].Domain());
94 int ncomp = b.nComp();
98 amrex::MultiFab Ax(x.boxArray(), x.DistributionMap(), ncomp, nghost);
99 amrex::MultiFab Dx(x.boxArray(), x.DistributionMap(), ncomp, nghost);
100 amrex::MultiFab Rx(x.boxArray(), x.DistributionMap(), ncomp, nghost);
102 if (!m_diagonal_computed)
Util::Abort(
INFO,
"Operator::Diagonal() must be called before using Fsmooth");
106 for (
int ctr = 0; ctr < 2; ctr++)
108 Fapply(amrlev, mglev, Ax, x);
110 amrex::MultiFab::Copy(Dx, x, 0, 0, ncomp, nghost);
111 amrex::MultiFab::Multiply(Dx, *m_diag[amrlev][mglev], 0, 0, ncomp, nghost);
113 amrex::MultiFab::Copy(Rx, Ax, 0, 0, ncomp, nghost);
114 amrex::MultiFab::Subtract(Rx, Dx, 0, 0, ncomp, nghost);
116 for (MFIter mfi(x,
false); mfi.isValid(); ++mfi)
118 const Box& bx = mfi.validbox();
119 amrex::FArrayBox& xfab = x[mfi];
120 const amrex::FArrayBox& bfab = b[mfi];
122 const amrex::FArrayBox& Rxfab = Rx[mfi];
123 const amrex::FArrayBox& diagfab = (*m_diag[amrlev][mglev])[mfi];
125 for (
int n = 0; n < ncomp; n++)
127 AMREX_D_TERM(
for (
int m1 = bx.loVect()[0] - 2; m1 <= bx.hiVect()[0] + 2; m1++),
128 for (
int m2 = bx.loVect()[1] - 2; m2 <= bx.hiVect()[1] + 2; m2++),
129 for (
int m3 = bx.loVect()[2] - 2; m3 <= bx.hiVect()[2] + 2; m3++))
135 if (AMREX_D_TERM(m[0] < domain.loVect()[0], ||
136 m[1] < domain.loVect()[1], ||
137 m[2] < domain.loVect()[2]))
continue;
138 if (AMREX_D_TERM(m[0] > domain.hiVect()[0] + 1, ||
139 m[1] > domain.hiVect()[1] + 1, ||
140 m[2] > domain.hiVect()[2] + 1))
continue;
142 if (AMREX_D_TERM(m[0] == bx.loVect()[0] - nghost || m[0] == bx.hiVect()[0] + nghost, ||
143 m[1] == bx.loVect()[1] - nghost || m[1] == bx.hiVect()[1] + nghost, ||
144 m[2] == bx.loVect()[2] - nghost || m[2] == bx.hiVect()[2] + nghost))
151 xfab(m, n) = (1. - m_omega) * xfab(m, n) + m_omega * (bfab(m, n) - Rxfab(m, n)) / diagfab(m, n);
156 amrex::Geometry geom = m_geom[amrlev][mglev];
157 realFillBoundary(x, geom);
158 nodalSync(amrlev, mglev, x);
291 BL_PROFILE(
"Operator::restriction()");
293 applyBC(amrlev, cmglev - 1, fine, BCMode::Homogeneous, StateMode::Solution);
295 amrex::Box cdomain = m_geom[amrlev][cmglev].Domain();
296 cdomain.convert(amrex::IntVect::TheNodeVector());
298 bool need_parallel_copy = !amrex::isMFIterSafe(crse, fine);
300 if (need_parallel_copy) {
301 const BoxArray& ba = amrex::coarsen(fine.boxArray(), 2);
302 cfine.define(ba, fine.DistributionMap(), fine.nComp(), fine.nGrow());
305 MultiFab* pcrse = (need_parallel_copy) ? &cfine : &crse;
307 for (MFIter mfi(*pcrse, amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
309 const Box& bx = mfi.tilebox();
311 amrex::Array4<const amrex::Real>
const& fdata = fine.array(mfi);
312 amrex::Array4<amrex::Real>
const& cdata = pcrse->array(mfi);
314 const Dim3 lo = amrex::lbound(cdomain), hi = amrex::ubound(cdomain);
317 for (
int n = 0; n < crse.nComp(); n++)
321 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int I,
int J,
int K) {
322 int i = 2 * I, j = 2 * J, k = 2 * K;
324 if ((I == lo.x || I == hi.x) &&
325 (J == lo.y || J == hi.y) &&
326 (K == lo.z || K == hi.z))
328 cdata(I, J, K, n) = fdata(i, j, k, n);
330 else if ((J == lo.y || J == hi.y) &&
331 (K == lo.z || K == hi.z))
333 cdata(I, J, K, n) = 0.25 * fdata(i - 1, j, k, n) + 0.5 * fdata(i, j, k, n) + 0.25 * fdata(i + 1, j, k, n);
335 else if ((K == lo.z || K == hi.z) &&
336 (I == lo.x || I == hi.x))
338 cdata(I, J, K, n) = 0.25 * fdata(i, j - 1, k, n) + 0.5 * fdata(i, j, k, n) + 0.25 * fdata(i, j + 1, k, n);
340 else if ((I == lo.x || I == hi.x) &&
341 (J == lo.y || J == hi.y))
343 cdata(I, J, K, n) = 0.25 * fdata(i, j, k - 1, n) + 0.5 * fdata(i, j, k, n) + 0.25 * fdata(i, j, k + 1, n);
345 else if (I == lo.x || I == hi.x)
348 (+fdata(i, j - 1, k - 1, n) + 2.0 * fdata(i, j, k - 1, n) + fdata(i, j + 1, k - 1, n)
349 + 2.0 * fdata(i, j - 1, k, n) + 4.0 * fdata(i, j, k, n) + 2.0 * fdata(i, j + 1, k, n)
350 + fdata(i, j - 1, k + 1, n) + 2.0 * fdata(i, j, k + 1, n) + fdata(i, j + 1, k + 1, n)) / 16.0;
352 else if (J == lo.y || J == hi.y)
355 (+fdata(i - 1, j, k - 1, n) + 2.0 * fdata(i - 1, j, k, n) + fdata(i - 1, j, k + 1, n)
356 + 2.0 * fdata(i, j, k - 1, n) + 4.0 * fdata(i, j, k, n) + 2.0 * fdata(i, j, k + 1, n)
357 + fdata(i + 1, j, k - 1, n) + 2.0 * fdata(i + 1, j, k, n) + fdata(i + 1, j, k + 1, n)) / 16.0;
359 else if (K == lo.z || K == hi.z)
362 (+fdata(i - 1, j - 1, k, n) + 2.0 * fdata(i, j - 1, k, n) + fdata(i + 1, j - 1, k, n)
363 + 2.0 * fdata(i - 1, j, k, n) + 4.0 * fdata(i, j, k, n) + 2.0 * fdata(i + 1, j, k, n)
364 + fdata(i - 1, j + 1, k, n) + 2.0 * fdata(i, j + 1, k, n) + fdata(i + 1, j + 1, k, n)) / 16.0;
368 (fdata(i - 1, j - 1, k - 1, n) + fdata(i - 1, j - 1, k + 1, n) + fdata(i - 1, j + 1, k - 1, n) + fdata(i - 1, j + 1, k + 1, n) +
369 fdata(i + 1, j - 1, k - 1, n) + fdata(i + 1, j - 1, k + 1, n) + fdata(i + 1, j + 1, k - 1, n) + fdata(i + 1, j + 1, k + 1, n)) / 64.0
371 (fdata(i, j - 1, k - 1, n) + fdata(i, j - 1, k + 1, n) + fdata(i, j + 1, k - 1, n) + fdata(i, j + 1, k + 1, n) +
372 fdata(i - 1, j, k - 1, n) + fdata(i + 1, j, k - 1, n) + fdata(i - 1, j, k + 1, n) + fdata(i + 1, j, k + 1, n) +
373 fdata(i - 1, j - 1, k, n) + fdata(i - 1, j + 1, k, n) + fdata(i + 1, j - 1, k, n) + fdata(i + 1, j + 1, k, n)) / 32.0
375 (fdata(i - 1, j, k, n) + fdata(i, j - 1, k, n) + fdata(i, j, k - 1, n) +
376 fdata(i + 1, j, k, n) + fdata(i, j + 1, k, n) + fdata(i, j, k + 1, n)) / 16.0
378 fdata(i, j, k, n) / 8.0;
383 if (need_parallel_copy) {
384 crse.ParallelCopy(cfine);
387 amrex::Geometry geom = m_geom[amrlev][cmglev];
388 realFillBoundary(crse, geom);
389 nodalSync(amrlev, cmglev, crse);
394 BL_PROFILE(
"Operator::interpolation()");
396 amrex::Box fdomain = m_geom[amrlev][fmglev].Domain(); fdomain.convert(amrex::IntVect::TheNodeVector());
398 bool need_parallel_copy = !amrex::isMFIterSafe(crse, fine);
400 const MultiFab* cmf = &crse;
401 if (need_parallel_copy) {
402 const BoxArray& ba = amrex::coarsen(fine.boxArray(), 2);
403 cfine.define(ba, fine.DistributionMap(), crse.nComp(), crse.nGrow());
404 cfine.ParallelCopy(crse);
408 for (MFIter mfi(fine,
false); mfi.isValid(); ++mfi)
410 const Box& fine_bx = mfi.validbox() & fdomain;
411 const Box& course_bx = amrex::coarsen(fine_bx, 2);
412 const Box& tmpbx = amrex::refine(course_bx, 2);
414 tmpfab.resize(tmpbx, fine.nComp());
416 const amrex::FArrayBox& crsefab = (*cmf)[mfi];
418 amrex::Array4<const amrex::Real>
const& cdata = crsefab.const_array();
419 amrex::Array4<amrex::Real>
const& fdata = tmpfab.array();
421 for (
int n = 0; n < crse.nComp(); n++)
425 amrex::ParallelFor(fine_bx, [=] AMREX_GPU_DEVICE(
int i,
int j,
int k) {
427 int I = i / 2, J = j / 2, K = k / 2;
429 if (i % 2 == 0 && j % 2 == 0 && k % 2 == 0)
430 fdata(i, j, k, n) = cdata(I, J, K, n);
431 else if (j % 2 == 0 && k % 2 == 0)
432 fdata(i, j, k, n) = 0.5 * (cdata(I, J, K, n) + cdata(I + 1, J, K, n));
433 else if (k % 2 == 0 && i % 2 == 0)
434 fdata(i, j, k, n) = 0.5 * (cdata(I, J, K, n) + cdata(I, J + 1, K, n));
435 else if (i % 2 == 0 && j % 2 == 0)
436 fdata(i, j, k, n) = 0.5 * (cdata(I, J, K, n) + cdata(I, J, K + 1, n));
438 fdata(i, j, k, n) = 0.25 * (cdata(I, J, K, n) + cdata(I, J + 1, K, n) +
439 cdata(I, J, K + 1, n) + cdata(I, J + 1, K + 1, n));
441 fdata(i, j, k, n) = 0.25 * (cdata(I, J, K, n) + cdata(I, J, K + 1, n) +
442 cdata(I + 1, J, K, n) + cdata(I + 1, J, K + 1, n));
444 fdata(i, j, k, n) = 0.25 * (cdata(I, J, K, n) + cdata(I + 1, J, K, n) +
445 cdata(I, J + 1, K, n) + cdata(I + 1, J + 1, K, n));
447 fdata(i, j, k, n) = 0.125 * (cdata(I, J, K, n) +
448 cdata(I + 1, J, K, n) + cdata(I, J + 1, K, n) + cdata(I, J, K + 1, n) +
449 cdata(I, J + 1, K + 1, n) + cdata(I + 1, J, K + 1, n) + cdata(I + 1, J + 1, K, n) +
450 cdata(I + 1, J + 1, K + 1, n));
454 fine[mfi].plus(tmpfab, fine_bx, fine_bx, 0, 0, fine.nComp());
457 amrex::Geometry geom = m_geom[amrlev][fmglev];
458 realFillBoundary(fine, geom);
459 nodalSync(amrlev, fmglev, fine);
552 MultiFab& res,
const MultiFab& ,
const MultiFab& ,
553 MultiFab& fine_res, MultiFab& ,
const MultiFab& )
const
555 BL_PROFILE(
"Operator::Elastic::reflux()");
557 int ncomp = AMREX_SPACEDIM;
559 amrex::Box cdomain(m_geom[crse_amrlev][0].Domain());
560 cdomain.convert(amrex::IntVect::TheNodeVector());
562 const Geometry& cgeom = m_geom[crse_amrlev][0];
564 const BoxArray& fba = fine_res.boxArray();
565 const DistributionMapping& fdm = fine_res.DistributionMap();
567 MultiFab fine_res_for_coarse(amrex::coarsen(fba, 2), fdm, ncomp, 2);
568 fine_res_for_coarse.ParallelCopy(res, 0, 0, ncomp, 0, 0, cgeom.periodicity());
570 applyBC(crse_amrlev + 1, 0, fine_res, BCMode::Inhomogeneous, StateMode::Solution);
574 const int coarse_fine_node = 1;
575 const int fine_fine_node = 2;
577 amrex::iMultiFab nodemask(amrex::coarsen(fba, 2), fdm, 1, 2);
578 nodemask.ParallelCopy(*m_nd_fine_mask[crse_amrlev], 0, 0, 1, 0, 0, cgeom.periodicity());
580 amrex::iMultiFab cellmask(amrex::convert(amrex::coarsen(fba, 2), amrex::IntVect::TheCellVector()), fdm, 1, 2);
581 cellmask.ParallelCopy(*m_cc_fine_mask[crse_amrlev], 0, 0, 1, 1, 1, cgeom.periodicity());
583 for (MFIter mfi(fine_res_for_coarse,
false); mfi.isValid(); ++mfi)
585 const Box& bx = mfi.validbox();
587 amrex::Array4<const int>
const& nmask = nodemask.array(mfi);
590 amrex::Array4<amrex::Real>
const& cdata = fine_res_for_coarse.array(mfi);
591 amrex::Array4<const amrex::Real>
const& fdata = fine_res.array(mfi);
593 const Dim3 lo = amrex::lbound(cdomain), hi = amrex::ubound(cdomain);
595 for (
int n = 0; n < fine_res.nComp(); n++)
599 amrex::ParallelFor(bx, [=] AMREX_GPU_DEVICE(
int I,
int J,
int K) {
600 int i = I * 2, j = J * 2, k = K * 2;
602 if (nmask(I, J, K) == fine_fine_node || nmask(I, J, K) == coarse_fine_node)
604 if ((I == lo.x || I == hi.x) &&
605 (J == lo.y || J == hi.y) &&
606 (K == lo.z || K == hi.z))
607 cdata(I, J, K, n) = fdata(i, j, k, n);
608 else if ((J == lo.y || J == hi.y) &&
609 (K == lo.z || K == hi.z))
610 cdata(I, J, K, n) = 0.25 * fdata(i - 1, j, k, n) + 0.5 * fdata(i, j, k, n) + 0.25 * fdata(i + 1, j, k, n);
611 else if ((K == lo.z || K == hi.z) &&
612 (I == lo.x || I == hi.x))
613 cdata(I, J, K, n) = 0.25 * fdata(i, j - 1, k, n) + 0.5 * fdata(i, j, k, n) + 0.25 * fdata(i, j + 1, k, n);
614 else if ((I == lo.x || I == hi.x) &&
615 (J == lo.y || J == hi.y))
616 cdata(I, J, K, n) = 0.25 * fdata(i, j, k - 1, n) + 0.5 * fdata(i, j, k, n) + 0.25 * fdata(i, j, k + 1, n);
617 else if (I == lo.x || I == hi.x)
619 (+fdata(i, j - 1, k - 1, n) + 2.0 * fdata(i, j, k - 1, n) + fdata(i, j + 1, k - 1, n)
620 + 2.0 * fdata(i, j - 1, k, n) + 4.0 * fdata(i, j, k, n) + 2.0 * fdata(i, j + 1, k, n)
621 + fdata(i, j - 1, k + 1, n) + 2.0 * fdata(i, j, k + 1, n) + fdata(i, j + 1, k + 1, n)) / 16.0;
622 else if (J == lo.y || J == hi.y)
624 (+fdata(i - 1, j, k - 1, n) + 2.0 * fdata(i - 1, j, k, n) + fdata(i - 1, j, k + 1, n)
625 + 2.0 * fdata(i, j, k - 1, n) + 4.0 * fdata(i, j, k, n) + 2.0 * fdata(i, j, k + 1, n)
626 + fdata(i + 1, j, k - 1, n) + 2.0 * fdata(i + 1, j, k, n) + fdata(i + 1, j, k + 1, n)) / 16.0;
627 else if (K == lo.z || K == hi.z)
629 (+fdata(i - 1, j - 1, k, n) + 2.0 * fdata(i, j - 1, k, n) + fdata(i + 1, j - 1, k, n)
630 + 2.0 * fdata(i - 1, j, k, n) + 4.0 * fdata(i, j, k, n) + 2.0 * fdata(i + 1, j, k, n)
631 + fdata(i - 1, j + 1, k, n) + 2.0 * fdata(i, j + 1, k, n) + fdata(i + 1, j + 1, k, n)) / 16.0;
634 (fdata(i - 1, j - 1, k - 1, n) + fdata(i - 1, j - 1, k + 1, n) + fdata(i - 1, j + 1, k - 1, n) + fdata(i - 1, j + 1, k + 1, n) +
635 fdata(i + 1, j - 1, k - 1, n) + fdata(i + 1, j - 1, k + 1, n) + fdata(i + 1, j + 1, k - 1, n) + fdata(i + 1, j + 1, k + 1, n)) / 64.0
637 (fdata(i, j - 1, k - 1, n) + fdata(i, j - 1, k + 1, n) + fdata(i, j + 1, k - 1, n) + fdata(i, j + 1, k + 1, n) +
638 fdata(i - 1, j, k - 1, n) + fdata(i + 1, j, k - 1, n) + fdata(i - 1, j, k + 1, n) + fdata(i + 1, j, k + 1, n) +
639 fdata(i - 1, j - 1, k, n) + fdata(i - 1, j + 1, k, n) + fdata(i + 1, j - 1, k, n) + fdata(i + 1, j + 1, k, n)) / 32.0
641 (fdata(i - 1, j, k, n) + fdata(i, j - 1, k, n) + fdata(i, j, k - 1, n) +
642 fdata(i + 1, j, k, n) + fdata(i, j + 1, k, n) + fdata(i, j, k + 1, n)) / 16.0
644 fdata(i, j, k, n) / 8.0;
653 res.ParallelCopy(fine_res_for_coarse, 0, 0, ncomp, 0, 0, cgeom.periodicity());
658 amrex::Geometry geom = m_geom[crse_amrlev][mglev];
659 realFillBoundary(res, geom);
660 nodalSync(crse_amrlev, mglev, res);