REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_SumIQ.cpp
Go to the documentation of this file.
1#include <iomanip>
2
3#include "REMORA.H"
4#include "AMReX_MultiFab.H"
5
6using namespace amrex;
7/**
8 * @param[in ] time current time
9 */
10void
12{
13 BL_PROFILE("REMORA::sum_integrated_quantities()");
14
15 if (verbose <= 0)
16 return;
17
18 int datwidth = 14;
19 int datprecision = 6;
20
21 Real scalar = 0.0_rt;
22 Real kineng = 0.0_rt;
23 Real volume = 0.0_rt;
24 Real max_vel = 0.0_rt;
25
26 for (int lev = 0; lev <= finest_level; lev++)
27 {
28 MultiFab kineng_mf(grids[lev], dmap[lev], 1, 0);
29 MultiFab ones_mf(grids[lev], dmap[lev], 1, 0);
30 ones_mf.setVal(1.0_rt);
31
32#ifdef _OPENMP
33#pragma omp parallel if (Gpu::notInLaunchRegion())
34#endif
35 for (MFIter mfi(*cons_new[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
36 const Box& bx = mfi.tilebox();
37 const Array4< Real> kineng_arr = kineng_mf.array(mfi);
38 const Array4<const Real> xvel_u_arr = xvel_new[lev]->const_array(mfi);
39 const Array4<const Real> yvel_v_arr = yvel_new[lev]->const_array(mfi);
40 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
41 {
42 // This is the same expression for kinetic energy that is used in ROMS
43 kineng_arr(i,j,k) = 0.25_rt * ( xvel_u_arr(i,j,k)*xvel_u_arr(i,j,k) + xvel_u_arr(i+1,j,k)*xvel_u_arr(i+1,j,k) +
44 yvel_v_arr(i,j,k)*yvel_v_arr(i,j,k) + yvel_v_arr(i ,j+1,k)*yvel_v_arr(i,j+1,k));
45 });
46 } // mfi
47
48 const int icomp = 0;
49 Real max_vel_local = std::sqrt(2.0_rt * kineng_mf.max(icomp));
50
51 scalar += volWgtSumMF(lev,*cons_new[lev],Scalar_comp,false,true);
52 kineng += volWgtSumMF(lev,kineng_mf , 0,false,true);
53 volume += volWgtSumMF(lev,ones_mf , 0,false,true);
54 max_vel = std::max(max_vel, max_vel_local);
55 }
56
57 if (verbose > 0) {
58 const int n_sum_vars = 3;
59 Real sum_vars[n_sum_vars] = {scalar,kineng,volume};
60
61 const int n_max_vars = 1;
62 Real max_vars[n_max_vars] = {max_vel};
63#ifdef AMREX_LAZY
64 Lazy::QueueReduction([=]() mutable {
65#endif
66 ParallelDescriptor::ReduceRealSum(
67 sum_vars, n_sum_vars, ParallelDescriptor::IOProcessorNumber());
68 ParallelDescriptor::ReduceRealMax(
69 max_vars, n_max_vars, ParallelDescriptor::IOProcessorNumber());
70
71 if (ParallelDescriptor::IOProcessor()) {
72 int i = 0;
73 scalar = sum_vars[i++];
74 kineng = sum_vars[i++];
75 volume = sum_vars[i++];
76 int j = 0;
77 max_vel = max_vars[j++];
78
79 amrex::Print() << '\n';
80 amrex::Print() << "TIME= " << time << " SCALAR = " << scalar << '\n';
81 amrex::Print() << "TIME= " << time << " KIN. ENG. = " << kineng << '\n';
82 amrex::Print() << "TIME= " << time << " VOLUME = " << volume << '\n';
83 amrex::Print() << "TIME= " << time << " MAX. VEL. = " << max_vel << '\n';
84
85 if (NumDataLogs() > 0) {
86 std::ostream& data_log1 = DataLog(0);
87 if (data_log1.good()) {
88 if (time == 0.0_rt) {
89 data_log1 << std::setw(datwidth) << " time";
90 data_log1 << std::setw(datwidth) << " scalar";
91 data_log1 << std::setw(datwidth) << " kineng";
92 data_log1 << std::setw(datwidth) << " volume";
93 data_log1 << std::setw(datwidth) << " max_vel";
94 data_log1 << std::endl;
95 }
96
97 // Write the quantities at this time
98 data_log1 << std::setw(datwidth) << time;
99 data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
100 << scalar;
101 data_log1 << std::setw(datwidth) << std::setprecision(datprecision)
102 << kineng;
103 data_log1 << std::endl;
104 }
105 }
106 }
107#ifdef AMREX_LAZY
108 });
109#endif
110 }
111}
112
113/**
114 * @param[in ] lev level to calculate on
115 * @param[in ] mf data to sum over
116 * @param[in ] comp component on which to calculate sum
117 * @param[in ] local whether to do the sum locally
118 * @param[in ] finemask whether to mask fine level
119 */
120Real
121REMORA::volWgtSumMF(int lev, const MultiFab& mf, int comp, bool local, bool finemask)
122{
123 BL_PROFILE("REMORA::volWgtSumMF()");
124
125 Real sum = 0.0_rt;
126 MultiFab tmp(grids[lev], dmap[lev], 1, 0);
127 MultiFab::Copy(tmp, mf, comp, 0, 1, 0);
128
129 if (lev < finest_level && finemask) {
130 const MultiFab& mask = build_fine_mask(lev+1);
131 MultiFab::Multiply(tmp, mask, 0, 0, 1, 0);
132 }
133
134 MultiFab volume(grids[lev], dmap[lev], 1, 0);
135#ifdef _OPENMP
136#pragma omp parallel if (Gpu::notInLaunchRegion())
137#endif
138 for (MFIter mfi(*cons_new[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
139 const Box& bx = mfi.tilebox();
140 const Array4< Real> vol_arr = volume.array(mfi);
141 const Array4<const Real> Hz = vec_Hz[lev]->const_array(mfi);
142 const Array4<const Real> pm = vec_pm[lev]->const_array(mfi);
143 const Array4<const Real> pn = vec_pn[lev]->const_array(mfi);
144 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) noexcept
145 {
146 vol_arr(i,j,k) = Hz(i,j,k) / (pm(i,j,0) * pn(i,j,0));
147 });
148 } // mfi
149
150 sum = MultiFab::Dot(tmp, 0, volume, 0, 1, 0, local);
151
152 if (!local)
153 ParallelDescriptor::ReduceRealSum(sum);
154
155 return sum;
156}
157
158/**
159 * @param[in ] lev level to calculate on
160 */
161MultiFab&
163{
164 // Mask for zeroing covered cells
165 AMREX_ASSERT(level > 0);
166
167 const BoxArray& cba = grids[level-1];
168 const DistributionMapping& cdm = dmap[level-1];
169
170 // TODO -- we should make a vector of these a member of REMORA class
171 fine_mask.define(cba, cdm, 1, 0, MFInfo());
172 fine_mask.setVal(1.0_rt);
173
174 BoxArray fba = grids[level];
175 iMultiFab ifine_mask = makeFineMask(cba, cdm, fba, ref_ratio[level-1], 1, 0);
176
177 const auto fma = fine_mask.arrays();
178 const auto ifma = ifine_mask.arrays();
179 ParallelFor(fine_mask, [=] AMREX_GPU_DEVICE(int bno, int i, int j, int k) noexcept
180 {
181 fma[bno](i,j,k) = ifma[bno](i,j,k);
182 });
183
184 Gpu::synchronize();
185
186 return fine_mask;
187}
188
189/**
190 * @param[in ] nstep what step we're on
191 * @param[in ] lev level to calculate on
192 * @param[in ] dtlev time step for this level
193 * @param[in ] action_interval number of time steps between actions
194 * @param[in ] action_per time interval between actions
195 */
196bool
197REMORA::is_it_time_for_action(int nstep, Real time, Real dtlev, int action_interval, Real action_per)
198{
199 bool int_test = (action_interval > 0 && nstep % action_interval == 0);
200
201 bool per_test = false;
202 if (action_per > 0.0_rt) {
203 const int num_per_old = static_cast<int>(amrex::Math::floor((time - dtlev) / action_per));
204 const int num_per_new = static_cast<int>(amrex::Math::floor((time) / action_per));
205
206 if (num_per_old != num_per_new) {
207 per_test = true;
208 }
209 }
210
211 return int_test || per_test;
212}
#define Scalar_comp
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:355
amrex::MultiFab fine_mask
Mask that zeroes out values on a coarse level underlying grids on the next finest level.
Definition REMORA.H:1304
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive scalar
Definition REMORA.H:217
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Hz
Width of cells in the vertical (z-) direction (3D, Hz in ROMS)
Definition REMORA.H:232
amrex::Vector< amrex::MultiFab * > yvel_new
multilevel data container for current step's y velocities (v in ROMS)
Definition REMORA.H:221
amrex::MultiFab & build_fine_mask(int lev)
Make mask to zero out covered cells (for mesh refinement)
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:219
void sum_integrated_quantities(amrex::Real time)
Integrate conserved quantities for diagnostics.
AMREX_FORCE_INLINE int NumDataLogs() noexcept
Definition REMORA.H:1351
amrex::Real volWgtSumMF(int lev, const amrex::MultiFab &mf, int comp, bool local, bool finemask)
Perform the volume-weighted sum.
bool is_it_time_for_action(int nstep, amrex::Real time, amrex::Real dt, int action_interval, amrex::Real action_per)
Decide if it is time to take an action.
AMREX_FORCE_INLINE std::ostream & DataLog(int i)
Helper function for IO stream.
Definition REMORA.H:1344
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:357
static int verbose
Verbosity level of output.
Definition REMORA.H:1248