diff --git a/src/simulation.hpp b/src/simulation.hpp index 10dfd1445..200865f8c 100644 --- a/src/simulation.hpp +++ b/src/simulation.hpp @@ -307,6 +307,9 @@ template class AMRSimulation : public amrex::AmrCore template auto computePlaneProjection(F const &user_f, int dir) const -> amrex::BaseFab; + // compute volume integrals + template auto computeVolumeIntegral(F const &user_f) -> amrex::Real; + // I/O functions [[nodiscard]] auto PlotFileName(int lev) const -> std::string; [[nodiscard]] auto CustomPlotFileName(const char *base, int lev) const -> std::string; @@ -1958,6 +1961,32 @@ template void AMRSimulation::AverageDownTo(int c } } +template template auto AMRSimulation::computeVolumeIntegral(F const &user_f) -> amrex::Real +{ + // compute integral of user_f(i, j, k, state) along the given axis. + const BL_PROFILE("AMRSimulation::computeVolumeIntegral()"); + + // allocate temporary multifabs + amrex::Vector q; + q.resize(finest_level + 1); + for (int lev = 0; lev <= finest_level; ++lev) { + q[lev].define(boxArray(lev), DistributionMap(lev), 1, 0); + } + + // evaluate user_f on all levels + // (note: it is not necessary to average down) + for (int lev = 0; lev <= finest_level; ++lev) { + auto const &state = state_new_cc_[lev].const_arrays(); + auto const &result = q[lev].arrays(); + amrex::ParallelFor(q[lev], [=] AMREX_GPU_DEVICE(int bx, int i, int j, int k) { result[bx](i, j, k) = user_f(i, j, k, state[bx]); }); + } + amrex::Gpu::streamSynchronize(); + + // call amrex::volumeWeightedSum + const amrex::Real result = amrex::volumeWeightedSum(amrex::GetVecOfConstPtrs(q), 0, geom, ref_ratio); + return result; +} + #ifdef AMREX_PARTICLES template void AMRSimulation::InitParticles() {