REMORA
Regional Modeling of Oceans Refined Adaptively
Loading...
Searching...
No Matches
REMORA_Plotfile.cpp
Go to the documentation of this file.
1#include <REMORA.H>
2#include "AMReX_Interp_3D_C.H"
3#include "AMReX_PlotFileUtil.H"
4
5using namespace amrex;
6
7static PhysBCFunctNoOp null_bc_for_fill;
8
9template<typename V, typename T>
10bool containerHasElement(const V& iterable, const T& query) {
11 return std::find(iterable.begin(), iterable.end(), query) != iterable.end();
12}
13
14// Write plotfile to disk
15void
16REMORA::WritePlotFile (int istep_for_plot)
17{
18#ifndef REMORA_USE_NETCDF
19 amrex::ignore_unused(istep_for_plot);
20#endif
21 Vector<std::string> varnames_3d;
22 varnames_3d.insert(varnames_3d.end(), plot_var_names_3d.begin(), plot_var_names_3d.end());
23
24 Vector<std::string> varnames_2d;
25 varnames_2d.insert(varnames_2d.end(), plot_var_names_2d.begin(), plot_var_names_2d.end());
26
27 Vector<std::string> varnames_2d_rho;
28 Vector<std::string> varnames_2d_u;
29 Vector<std::string> varnames_2d_v;
30
31 const int ncomp_mf_3d = varnames_3d.size();
32 const auto ngrow_vars = IntVect(NGROW-1,NGROW-1,0);
33
34 // These are the ncomp for the 2D cell-centered, x-face-based, y-face-based MultiFabs respectively
35 int ncomp_mf_2d_rho = 0;
36 int ncomp_mf_2d_u = 0;
37 int ncomp_mf_2d_v = 0;
38
39 // Check to see if we found all the requested variables
40 for (auto plot_name : varnames_2d) {
41 {
42 if (plot_name == "zeta" ) {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
43 if (plot_name == "h" ) {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
44 if (plot_name == "f" ) {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
45 if (plot_name == "visc2") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
46 for (int n = 0; n < ncons; ++n) {
47 const std::string diff2_name = std::string("diff2_") + cons_names[n];
48 if (plot_name == diff2_name) {
49 varnames_2d_rho.push_back(plot_name);
50 ncomp_mf_2d_rho++;
51 }
52 }
53 for (int n = 0; n < ncons; ++n) {
54 const std::string stflux_name = std::string("stflux_") + cons_names[n];
55 if (plot_name == stflux_name) {
56 varnames_2d_rho.push_back(plot_name);
57 ncomp_mf_2d_rho++;
58 }
59 }
60 if (plot_name == "lrflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
61 if (plot_name == "lhflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
62 if (plot_name == "srflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
63 if (plot_name == "shflux") {varnames_2d_rho.push_back(plot_name); ncomp_mf_2d_rho++;}
64 if (plot_name == "ubar" ) {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
65 if (plot_name == "sustr") {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
66 if (plot_name == "bustr") {varnames_2d_u.push_back(plot_name); ncomp_mf_2d_u++;}
67 if (plot_name == "vbar" ) {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
68 if (plot_name == "svstr") {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
69 if (plot_name == "bvstr") {varnames_2d_v.push_back(plot_name); ncomp_mf_2d_v++;}
70 }
71 }
72
73 // We fillpatch here because some of the derived quantities require derivatives
74 // which require ghost cells to be filled. Don't fill the boundary, though.
75 for (int lev = 0; lev <= finest_level; ++lev) {
76 FillPatchNoBC(lev, t_new[lev], *cons_new[lev], cons_new, BdyVars::t,0,true,false);
77 FillPatchNoBC(lev, t_new[lev], *xvel_new[lev], xvel_new, BdyVars::u,0,true,false);
78 FillPatchNoBC(lev, t_new[lev], *yvel_new[lev], yvel_new, BdyVars::v,0,true,false);
79 FillPatchNoBC(lev, t_new[lev], *zvel_new[lev], zvel_new, BdyVars::null,0,true,false);
80 FillPatchNoBC(lev, t_new[lev], *vec_visc2_r[lev], GetVecOfPtrs(vec_visc2_r), BdyVars::null,0,true,false);
81 FillPatchNoBC(lev, t_new[lev], *vec_diff2[lev], GetVecOfPtrs(vec_diff2), BdyVars::null,0,true,false);
82 }
83
84 for (int lev = 0; lev <= finest_level; ++lev) {
86 }
87
88 // Array of 3D MultiFabs to hold the plotfile data
89 Vector<MultiFab> plotMF(finest_level+1);
90 for (int lev = 0; lev <= finest_level; ++lev) {
91 plotMF[lev].define(grids[lev], dmap[lev], ncomp_mf_3d, ngrow_vars);
92 plotMF[lev].setVal(1.234e20);
93 }
94
95 // Array of 2D MultiFabs to hold the plotfile data
96 Vector<MultiFab> mf_2d_rho(finest_level+1);
97 Vector<MultiFab> mf_2d_u(finest_level+1);
98 Vector<MultiFab> mf_2d_v(finest_level+1);
99 for (int lev = 0; lev <= finest_level; ++lev) {
100 BoxArray ba(grids[lev]);
101 BoxList bl2d = ba.boxList();
102 for (auto& b : bl2d) {
103 b.setRange(2,0);
104 }
105 BoxArray ba2d(std::move(bl2d));
106 mf_2d_rho[lev].define(ba2d, dmap[lev], ncomp_mf_2d_rho, IntVect(0,0,0));
107 mf_2d_u[lev].define(ba2d, dmap[lev], ncomp_mf_2d_u , IntVect(0,0,0));
108 mf_2d_v[lev].define(ba2d, dmap[lev], ncomp_mf_2d_v , IntVect(0,0,0));
109 }
110
111
112 // Array of MultiFabs for nodal data
113 Vector<MultiFab> mf_nd(finest_level+1);
114 if (plot_nodal_data) {
115 for (int lev = 0; lev <= finest_level; ++lev) {
116 BoxArray nodal_grids(grids[lev]); nodal_grids.surroundingNodes();
117 mf_nd[lev].define(nodal_grids, dmap[lev], AMREX_SPACEDIM, 0);
118 mf_nd[lev].setVal(0.);
119 }
120 }
121
122 // Vector of MultiFabs for face-centered velocity
123 Vector<MultiFab> mf_u(finest_level+1);
124 Vector<MultiFab> mf_v(finest_level+1);
125 Vector<MultiFab> mf_w(finest_level+1);
127 for (int lev = 0; lev <= finest_level; ++lev) {
128 BoxArray grid_stag_u(grids[lev]); grid_stag_u.surroundingNodes(0);
129 BoxArray grid_stag_v(grids[lev]); grid_stag_v.surroundingNodes(1);
130 BoxArray grid_stag_w(grids[lev]); grid_stag_w.surroundingNodes(2);
131 mf_u[lev].define(grid_stag_u, dmap[lev], 1, 0);
132 mf_v[lev].define(grid_stag_v, dmap[lev], 1, 0);
133 mf_w[lev].define(grid_stag_w, dmap[lev], 1, 0);
134 MultiFab::Copy(mf_u[lev],*xvel_new[lev],0,0,1,0);
135 MultiFab::Copy(mf_v[lev],*yvel_new[lev],0,0,1,0);
136 MultiFab::Copy(mf_w[lev],*zvel_new[lev],0,0,1,0);
137 }
138 }
139
140 // Array of MultiFabs for cell-centered velocity
141 Vector<MultiFab> mf_cc_vel(finest_level+1);
142
143 if (containerHasElement(plot_var_names_3d, "x_velocity") ||
144 containerHasElement(plot_var_names_3d, "y_velocity") ||
145 containerHasElement(plot_var_names_3d, "z_velocity") ||
146 containerHasElement(plot_var_names_3d, "vorticity") ) {
147
148 for (int lev = 0; lev <= finest_level; ++lev) {
149 mf_cc_vel[lev].define(grids[lev], dmap[lev], AMREX_SPACEDIM, IntVect(1,1,0));
150 mf_cc_vel[lev].setVal(0.0_rt); // zero out velocity in case we have any wall boundaries
151 average_face_to_cellcenter(mf_cc_vel[lev],0,
152 Array<const MultiFab*,3>{xvel_new[lev],yvel_new[lev],zvel_new[lev]},IntVect(1,1,0));
153 mf_cc_vel[lev].FillBoundary(geom[lev].periodicity());
154 } // lev
155
156 // We need ghost cells if computing vorticity
157 amrex::Interpolater* mapper = &cell_cons_interp;
158 if ( containerHasElement(plot_var_names_3d, "vorticity") ) {
159 for (int lev = 1; lev <= finest_level; ++lev) {
160 Vector<MultiFab*> fmf = {&(mf_cc_vel[lev]), &(mf_cc_vel[lev])};
161 Vector<Real> ftime = {t_new[lev], t_new[lev]};
162 Vector<MultiFab*> cmf = {&mf_cc_vel[lev-1], &mf_cc_vel[lev-1]};
163 Vector<Real> ctime = {t_new[lev], t_new[lev]};
164
165 MultiFab mf_to_fill;
166 amrex::FillPatchTwoLevels(mf_cc_vel[lev], mf_cc_vel[lev].nGrowVect(), IntVect(0,0,0),
167 t_new[lev], cmf, ctime, fmf, ftime,
168 0, 0, mf_cc_vel[lev].nComp(), geom[lev-1], geom[lev],
169 refRatio(lev-1), mapper, domain_bcs_type, foextrap_bc());
170 } // lev
171 } // if
172 } // if
173
174 int icomp_rho = 0;
175 for (auto plot_name : varnames_2d_rho)
176 {
177 if (plot_name == "zeta" ) {
178 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_Zt_avg1[lev],0,icomp_rho,1,0); }
179 icomp_rho++;
180 }
181 if (plot_name == "h" ) {
182 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_h[lev],0,icomp_rho,1,0); }
183 icomp_rho++;
184 }
185 if (plot_name == "f" ) {
186 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_fcor[lev],0,icomp_rho,1,0); }
187 icomp_rho++;
188 }
189 if (plot_name == "visc2" ) {
190 for (int lev = 0; lev <= finest_level; ++lev) {
191 if (vec_visc2_r[lev]->contains_nan(0, 1, 0, true) || vec_visc2_r[lev]->contains_inf(0, 1, 0, true)) {
192 amrex::Abort("Found while writing output: visc2 contains nan or inf");
193 }
194 for (MFIter mfi(mf_2d_rho[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
195 const Box& bx = mfi.validbox();
196 const int K = mfi.index();
197 auto dst = mf_2d_rho[lev].array(mfi, icomp_rho);
198 auto src = vec_visc2_r[lev]->const_array(K);
199 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept {
200 dst(i,j,0) = src(i,j,0);
201 });
202 }
203 }
204 icomp_rho++;
205 }
206 for (int n = 0; n < ncons; ++n) {
207 const std::string diff2_name = std::string("diff2_") + cons_names[n];
208 if (plot_name == diff2_name) {
209 for (int lev = 0; lev <= finest_level; ++lev) {
210 for (MFIter mfi(mf_2d_rho[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi) {
211 const Box& bx = mfi.validbox();
212 const int K = mfi.index();
213 auto dst = mf_2d_rho[lev].array(mfi, icomp_rho);
214 auto src = vec_diff2[lev]->const_array(K);
215 ParallelFor(makeSlab(bx,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int) noexcept {
216 dst(i,j,0) = src(i,j,0,n);
217 });
218 }
219 }
220 icomp_rho++;
221 }
222 }
223 for (int n = 0; n < ncons; ++n) {
224 const std::string stflux_name = std::string("stflux_") + cons_names[n];
225 if (plot_name == stflux_name) {
226 for (int lev = 0; lev <= finest_level; ++lev) {
227 MultiFab::Copy(mf_2d_rho[lev],*vec_stflux[lev],n,icomp_rho,1,0);
228 }
229 icomp_rho++;
230 }
231 }
232 if (plot_name == "lrflux" ) {
234 amrex::Abort("Attempting to write longwave radiation flux to plotfile. Variable not allocated when bulk_fluxes turned off");
235 }
236 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_lrflx[lev],0,icomp_rho,1,0); }
237 icomp_rho++;
238 }
239 if (plot_name == "lhflux" ) {
241 amrex::Abort("Attempting to write latent heat flux to plotfile. Variable not allocated when bulk_fluxes turned off");
242 }
243 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_lhflx[lev],0,icomp_rho,1,0); }
244 icomp_rho++;
245 }
246 if (plot_name == "srflux" ) {
248 amrex::Abort("Attempting to write shortwave radiation flux to plotfile. Variable not allocated when bulk_fluxes turned off");
249 }
250 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_srflx[lev],0,icomp_rho,1,0); }
251 icomp_rho++;
252 }
253 if (plot_name == "shflux" ) {
255 amrex::Abort("Attempting to write sensible heat flux to plotfile. Variable not allocated when bulk_fluxes turned off");
256 }
257 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_rho[lev],*vec_shflx[lev],0,icomp_rho,1,0); }
258 icomp_rho++;
259 }
260 }
261
262 int icomp_u = 0;
263 for (auto plot_name : varnames_2d_u)
264 {
265 if (plot_name == "ubar" ) {
266 for (int lev = 0; lev <= finest_level; ++lev) {
267 MultiFab::Copy(mf_2d_u[lev],*vec_DU_avg1[lev],0,icomp_u,1,0);
268 }
269 icomp_u++;
270 }
271 if (plot_name == "sustr" ) {
272 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_u[lev],*vec_sustr[lev],0,icomp_u,1,0); }
273 icomp_u++;
274 }
275 if (plot_name == "bustr" ) {
276 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_u[lev],*vec_bustr[lev],0,icomp_u,1,0); }
277 icomp_u++;
278 }
279 }
280
281 int icomp_v = 0;
282 for (auto plot_name : varnames_2d_v)
283 {
284 if (plot_name == "vbar" ) {
285 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_DV_avg1[lev],0,icomp_v,1,0); }
286 icomp_v++;
287 }
288 if (plot_name == "svstr" ) {
289 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_svstr[lev],0,icomp_v,1,0); }
290 icomp_v++;
291 }
292 if (plot_name == "bvstr" ) {
293 for (int lev = 0; lev <= finest_level; ++lev) { MultiFab::Copy(mf_2d_v[lev],*vec_bvstr[lev],0,icomp_v,1,0); }
294 icomp_v++;
295 }
296 }
297
298 for (int lev = 0; lev <= finest_level; ++lev)
299 {
300 int mf_comp = 0;
301
302 // First, copy any of the conserved state variables into the output plotfile
304 for (int i = 0; i < ncons; ++i) {
306 if (cons_new[lev]->contains_nan() || cons_new[lev]->contains_inf()) {
307 amrex::Abort("Found while writing output: Cons (salt, temp, or tracer, etc) contains nan or inf");
308 }
309 MultiFab::Copy(plotMF[lev],*cons_new[lev],i,mf_comp,1,ngrow_vars);
310 mf_comp++;
311 }
312 } // ncons
313
314 // Next, check for velocities
315 if (containerHasElement(plot_var_names_3d, "x_velocity")) {
316 if (mf_cc_vel[lev].contains_nan(0,1) || mf_cc_vel[lev].contains_inf(0,1)) {
317 amrex::Abort("Found while writing output: u velocity contains nan or inf");
318 }
319 MultiFab::Copy(plotMF[lev], mf_cc_vel[lev], 0, mf_comp, 1, 0);
320 mf_comp += 1;
321 }
322 if (containerHasElement(plot_var_names_3d, "y_velocity")) {
323 if (mf_cc_vel[lev].contains_nan(1,1) || mf_cc_vel[lev].contains_inf(1,1)) {
324 amrex::Abort("Found while writing output: v velocity contains nan or inf");
325 }
326 MultiFab::Copy(plotMF[lev], mf_cc_vel[lev], 1, mf_comp, 1, 0);
327 mf_comp += 1;
328 }
329 if (containerHasElement(plot_var_names_3d, "z_velocity")) {
330 if (mf_cc_vel[lev].contains_nan(2,1) || mf_cc_vel[lev].contains_inf(2,1)) {
331 amrex::Abort("Found while writing output: z velocity contains nan or inf");
332 }
333 MultiFab::Copy(plotMF[lev], mf_cc_vel[lev], 2, mf_comp, 1, 0);
334 mf_comp += 1;
335 }
336
337 // Define standard process for calling the functions in Derive.cpp
338 auto calculate_derived = [&](const std::string& der_name,
339 decltype(derived::remora_dernull)& der_function)
340 {
341 if (containerHasElement(plot_var_names_3d, der_name)) {
342 MultiFab dmf(plotMF[lev], make_alias, mf_comp, 1);
343#ifdef _OPENMP
344#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
345#endif
346 for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
347 {
348 const Box& bx = mfi.tilebox();
349 auto& dfab = dmf[mfi];
350
351 if (der_name == "vorticity") {
352 auto const& sfab = mf_cc_vel[lev][mfi];
353 der_function(bx, dfab, 0, 1, sfab, vec_pm[lev]->const_array(mfi), vec_pn[lev]->const_array(mfi), vec_mskr[lev]->const_array(mfi), Geom(lev), t_new[0], nullptr, lev);
354 } else {
355 auto const& sfab = (*cons_new[lev])[mfi];
356 der_function(bx, dfab, 0, 1, sfab, vec_pm[lev]->const_array(mfi), vec_pn[lev]->const_array(mfi), vec_mskr[lev]->const_array(mfi), Geom(lev), t_new[0], nullptr, lev);
357 }
358 }
359
360 mf_comp++;
361 }
362 };
363
364 // Note: All derived variables must be computed in order of "derived_names" defined in REMORA.H
365 calculate_derived("vorticity", derived::remora_dervort);
366
367 // Fill cell-centered location
368 Real dx = Geom()[lev].CellSizeArray()[0];
369 Real dy = Geom()[lev].CellSizeArray()[1];
370
371 // Next, check for location names -- if we write one we write all
375 {
376 MultiFab dmf(plotMF[lev], make_alias, mf_comp, AMREX_SPACEDIM);
377#ifdef _OPENMP
378#pragma omp parallel if (Gpu::notInLaunchRegion())
379#endif
380 for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
381 const Box& bx = mfi.tilebox();
382 const Array4<Real> loc_arr = dmf.array(mfi);
383 const Array4<Real const> zp_arr = vec_z_phys_nd[lev]->const_array(mfi);
384
385 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
386 loc_arr(i,j,k,0) = (i+0.5_rt) * dx;
387 loc_arr(i,j,k,1) = (j+0.5_rt) * dy;
388 loc_arr(i,j,k,2) = 0.125_rt * (zp_arr(i,j ,k ) + zp_arr(i+1,j ,k ) +
389 zp_arr(i,j+1,k ) + zp_arr(i+1,j+1,k ) +
390 zp_arr(i,j ,k+1) + zp_arr(i+1,j ,k+1) +
391 zp_arr(i,j+1,k+1) + zp_arr(i+1,j+1,k+1) );
392 });
393 } // mfi
394 mf_comp += AMREX_SPACEDIM;
395 } // if containerHasElement
396
397#ifdef REMORA_USE_PARTICLES
398 const auto& particles_namelist( particleData.getNames() );
399 for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++) {
400 if (containerHasElement(plot_var_names_3d, std::string(particles_namelist[i]+"_count")))
401 {
402 MultiFab temp_dat(plotMF[lev].boxArray(), plotMF[lev].DistributionMap(), 1, 0);
403 temp_dat.setVal(0);
404 particleData[particles_namelist[i]]->Increment(temp_dat, lev);
405 MultiFab::Copy(plotMF[lev], temp_dat, 0, mf_comp, 1, 0);
406 mf_comp += 1;
407 }
408 }
409
410 Vector<std::string> particle_mesh_plot_names(0);
411 particleData.GetMeshPlotVarNames( particle_mesh_plot_names );
412 for (int i = 0; i < particle_mesh_plot_names.size(); i++) {
413 std::string plot_var_name(particle_mesh_plot_names[i]);
414 if (containerHasElement(plot_var_names_3d, plot_var_name) ) {
415 MultiFab temp_dat(plotMF[lev].boxArray(), plotMF[lev].DistributionMap(), 1, 1);
416 temp_dat.setVal(0);
417 particleData.GetMeshPlotVar(plot_var_name, temp_dat, lev);
418 MultiFab::Copy(plotMF[lev], temp_dat, 0, mf_comp, 1, 0);
419 mf_comp += 1;
420 }
421 }
422#endif
423
424 if (plot_nodal_data) {
425 MultiFab::Copy(mf_nd[lev],*vec_z_phys_nd[lev],0,2,1,0);
426 Real dz = Geom()[lev].CellSizeArray()[2];
427 int N = Geom()[lev].Domain().size()[2];
428
429#ifdef _OPENMP
430#pragma omp parallel if (Gpu::notInLaunchRegion())
431#endif
432 for (MFIter mfi(mf_nd[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
433 {
434 const Box& bx = mfi.tilebox();
435 Array4<Real> mf_arr = mf_nd[lev].array(mfi);
436 ParallelFor(bx, [=] AMREX_GPU_DEVICE (int i, int j, int k) {
437 mf_arr(i,j,k,2) = mf_arr(i,j,k,2) + (N-k) * dz;
438 });
439 } // mfi
440 }
441 } // lev
442
444 {
445
446 std::string plotfilename = Concatenate(plot_file_name, istep[0], file_min_digits);
447
448 if (finest_level == 0)
449 {
451 amrex::Print() << "Writing plotfile " << plotfilename << "\n";
452 WriteMultiLevelPlotfileWithBathymetry(plotfilename, finest_level+1,
453 GetVecOfConstPtrs(plotMF),
454 GetVecOfConstPtrs(mf_nd),
455 GetVecOfConstPtrs(mf_u),
456 GetVecOfConstPtrs(mf_v),
457 GetVecOfConstPtrs(mf_w),
458 GetVecOfConstPtrs(mf_2d_rho),
459 GetVecOfConstPtrs(mf_2d_u),
460 GetVecOfConstPtrs(mf_2d_v),
461 varnames_3d, varnames_2d_rho,
462 varnames_2d_u, varnames_2d_v,
463 Geom(),
464 t_new[0], istep, refRatio());
465 writeJobInfo(plotfilename);
466
467#ifdef REMORA_USE_PARTICLES
468 particleData.Checkpoint(plotfilename);
469#endif
470
471 }
472
473 } else { // multilevel
475 amrex::Print() << "Writing plotfile " << plotfilename << "\n";
476 int lev0 = 0;
477 [[maybe_unused]] int desired_ratio = std::max(std::max(ref_ratio[lev0][0],ref_ratio[lev0][1]),ref_ratio[lev0][2]);
478 bool any_ratio_one = ( ( (ref_ratio[lev0][0] == 1) || (ref_ratio[lev0][1] == 1) ) ||
479 (ref_ratio[lev0][2] == 1) );
480 for (int lev = 1; lev < finest_level; lev++) {
481 any_ratio_one = any_ratio_one ||
482 ( ( (ref_ratio[lev][0] == 1) || (ref_ratio[lev][1] == 1) ) ||
483 (ref_ratio[lev][2] == 1) );
484 }
485 if (any_ratio_one && expand_plotvars_to_unif_rr) {
486 Vector<IntVect> r2(finest_level);
487 Vector<Geometry> g2(finest_level+1);
488 Vector<MultiFab> mf2(finest_level+1);
489
490 mf2[0].define(grids[0], dmap[0], ncomp_mf_3d, 0);
491
492 // Copy level 0 as is
493 MultiFab::Copy(mf2[0],plotMF[0],0,0,plotMF[0].nComp(),0);
494
495 // Define a new multi-level array of Geometry's so that we pass the new "domain" at lev > 0
496 Array<int,AMREX_SPACEDIM> periodicity =
497 {Geom()[0].isPeriodic(0),Geom()[0].isPeriodic(1),Geom()[0].isPeriodic(2)};
498 g2[0].define(Geom()[0].Domain(),&(Geom()[0].ProbDomain()),0,periodicity.data());
499
500 r2[0] = IntVect(1,1,ref_ratio[0][0]);
501 for (int lev = 1; lev <= finest_level; ++lev) {
502 if (lev > 1) {
503 r2[lev-1][0] = 1;
504 r2[lev-1][1] = 1;
505 r2[lev-1][2] = r2[lev-2][2] * ref_ratio[lev-1][0];
506 }
507
508 mf2[lev].define(refine(grids[lev],r2[lev-1]), dmap[lev], ncomp_mf_3d, 0);
509
510 // Set the new problem domain
511 Box d2(Geom()[lev].Domain());
512 d2.refine(r2[lev-1]);
513
514 g2[lev].define(d2,&(Geom()[lev].ProbDomain()),0,periodicity.data());
515 }
516
517 // Make a vector of BCRec with default values so we can use it here -- note the values
518 // aren't actually used because we do PCInterp
519 amrex::Vector<amrex::BCRec> null_dom_bcs;
520 null_dom_bcs.resize(mf2[0].nComp());
521 for (int n = 0; n < mf2[0].nComp(); n++) {
522 for (int dir = 0; dir < AMREX_SPACEDIM; dir++) {
523 null_dom_bcs[n].setLo(dir, REMORABCType::int_dir);
524 null_dom_bcs[n].setHi(dir, REMORABCType::int_dir);
525 }
526 }
527
528 // Do piecewise interpolation of mf into mf2
529 for (int lev = 1; lev <= finest_level; ++lev) {
530 Interpolater* mapper_c = &pc_interp;
531 InterpFromCoarseLevel(mf2[lev], t_new[lev], plotMF[lev],
532 0, 0, mf2[lev].nComp(),
533 geom[lev], g2[lev],
535 r2[lev-1], mapper_c, null_dom_bcs, 0);
536 }
537
538 // Define an effective ref_ratio which is isotropic to be passed into WriteMultiLevelPlotfile
539 Vector<IntVect> rr(finest_level);
540 for (int lev = 0; lev < finest_level; ++lev) {
541 rr[lev] = IntVect(ref_ratio[lev][0],ref_ratio[lev][1],ref_ratio[lev][0]);
542 }
543
544 WriteMultiLevelPlotfileWithBathymetry(plotfilename, finest_level+1,
545 GetVecOfConstPtrs(mf2),
546 GetVecOfConstPtrs(mf_nd),
547 GetVecOfConstPtrs(mf_u),
548 GetVecOfConstPtrs(mf_v),
549 GetVecOfConstPtrs(mf_w),
550 GetVecOfConstPtrs(mf_2d_rho),
551 GetVecOfConstPtrs(mf_2d_u),
552 GetVecOfConstPtrs(mf_2d_v),
553 varnames_3d, varnames_2d_rho,
554 varnames_2d_u, varnames_2d_v,
555 g2,
556 t_new[0], istep, rr);
557 writeJobInfo(plotfilename);
558
559#ifdef REMORA_USE_PARTICLES
560 particleData.Checkpoint(plotfilename);
561#endif
562 } else {
563 WriteMultiLevelPlotfileWithBathymetry(plotfilename, finest_level+1,
564 GetVecOfConstPtrs(plotMF),
565 GetVecOfConstPtrs(mf_nd),
566 GetVecOfConstPtrs(mf_u),
567 GetVecOfConstPtrs(mf_v),
568 GetVecOfConstPtrs(mf_w),
569 GetVecOfConstPtrs(mf_2d_rho),
570 GetVecOfConstPtrs(mf_2d_u),
571 GetVecOfConstPtrs(mf_2d_v),
572 varnames_3d, varnames_2d_rho,
573 varnames_2d_u, varnames_2d_v,
574 Geom(),
575 t_new[0], istep, ref_ratio);
576 writeJobInfo(plotfilename);
577#ifdef REMORA_USE_PARTICLES
578 particleData.Checkpoint(plotfilename);
579#endif
580 }
581 }
582 } // end multi-level
583 for (int lev = 0; lev <= finest_level; ++lev) {
585 }
586
587 }
588#ifdef REMORA_USE_NETCDF
590 {
591 // Currently this is hard-coded to plot only level 0
592 AMREX_ASSERT(finest_level == 0);
593 int lev = 0;
594 plotMF[0].FillBoundary(geom[lev].periodicity());
595 WriteNCPlotFile(istep_for_plot,&plotMF[lev]);
596 } // end if plotfile_type == netcdf
597#endif
598}
599
600/**
601 * @param plotfilename name of plotfile to write to
602 * @param nlevels number of levels to write out
603 * @param mf MultiFab of data to write out
604 * @param mf_nd Multifab of nodal data to write out
605 * @param varnames_3d 3D variable names to write out
606 * @param varnames_2d_rho 2D cell-centered variable names to write out
607 * @param varnames_2d_u 2D x-face-based variable names to write out
608 * @param varnames_2d_v 2D y-face-based variable names to write out
609 * @param my_geom geometry to use for writing plotfile
610 * @param time time at which to output
611 * @param level_steps vector over level of iterations
612 * @param rr refinement ratio to use for writing plotfile
613 * @param versionName version string for VisIt
614 * @param levelPrefix string to prepend to level number
615 * @param mfPrefix subdirectory for multifab data
616 * @param extra_dirs additional subdirectories within plotfile
617 */
618 void
619 REMORA::WriteMultiLevelPlotfileWithBathymetry (const std::string& plotfilename, int nlevels,
620 const Vector<const MultiFab*>& mf,
621 const Vector<const MultiFab*>& mf_nd,
622 const Vector<const MultiFab*>& mf_u,
623 const Vector<const MultiFab*>& mf_v,
624 const Vector<const MultiFab*>& mf_w,
625 const Vector<const MultiFab*>& mf_2d_rho,
626 const Vector<const MultiFab*>& mf_2d_u,
627 const Vector<const MultiFab*>& mf_2d_v,
628 const Vector<std::string>& varnames_3d,
629 const Vector<std::string>& varnames_2d_rho,
630 const Vector<std::string>& varnames_2d_u,
631 const Vector<std::string>& varnames_2d_v,
632 const Vector<Geometry>& my_geom,
633 Real time,
634 const Vector<int>& level_steps,
635 const Vector<IntVect>& rr,
636 const std::string &versionName,
637 const std::string &levelPrefix,
638 const std::string &mfPrefix,
639 const Vector<std::string>& extra_dirs) const
640{
641 BL_PROFILE("WriteMultiLevelPlotfileWithBathymetry()");
642
643 AMREX_ASSERT(nlevels <= mf.size());
644 AMREX_ASSERT(nlevels <= ref_ratio.size()+1);
645 AMREX_ASSERT(nlevels <= level_steps.size());
646
647 AMREX_ASSERT(mf[0]->nComp() == varnames_3d.size());
648
649 bool callBarrier(false);
650 PreBuildDirectorHierarchy(plotfilename, levelPrefix, nlevels, callBarrier);
651 if (!extra_dirs.empty()) {
652 for (const auto& d : extra_dirs) {
653 const std::string ed = plotfilename+"/"+d;
654 PreBuildDirectorHierarchy(ed, levelPrefix, nlevels, callBarrier);
655 }
656 }
657 ParallelDescriptor::Barrier();
658
659 if (ParallelDescriptor::MyProc() == ParallelDescriptor::NProcs()-1) {
660 Vector<BoxArray> boxArrays(nlevels);
661 for(int level(0); level < boxArrays.size(); ++level) {
662 boxArrays[level] = mf[level]->boxArray();
663 }
664
665 auto f = [this, plotfilename, nlevels, boxArrays, varnames_3d,
666 varnames_2d_rho, varnames_2d_u, varnames_2d_v, my_geom,
667 time, level_steps, rr, versionName, levelPrefix, mfPrefix]() {
668 VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size);
669 std::string HeaderFileName(plotfilename + "/Header");
670 std::ofstream HeaderFile;
671 HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size());
672 HeaderFile.open(HeaderFileName.c_str(), std::ofstream::out |
673 std::ofstream::trunc |
674 std::ofstream::binary);
675 if( ! HeaderFile.good()) FileOpenFailed(HeaderFileName);
676 WriteGenericPlotfileHeaderWithBathymetry(HeaderFile, nlevels, boxArrays, varnames_3d,
677 varnames_2d_rho, varnames_2d_u, varnames_2d_v,
678 my_geom, time, level_steps, rr, versionName,
679 levelPrefix, mfPrefix);
680 };
681
682 if (AsyncOut::UseAsyncOut()) {
683 AsyncOut::Submit(std::move(f));
684 } else {
685 f();
686 }
687 }
688
689 std::string mf_nodal_prefix = "Nu_nd";
690 std::string mf_uface_prefix = "UFace";
691 std::string mf_vface_prefix = "VFace";
692 std::string mf_wface_prefix = "WFace";
693 std::string mf_2d_rho_prefix = "rho2d";
694 std::string mf_2d_u_prefix = "u2d";
695 std::string mf_2d_v_prefix = "v2d";
696
697 for (int level = 0; level <= finest_level; ++level)
698 {
699 if (AsyncOut::UseAsyncOut()) {
700 VisMF::AsyncWrite(*mf[level],
701 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mfPrefix),
702 true);
703 if (plot_nodal_data) {
704 VisMF::AsyncWrite(*mf_nd[level],
705 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_nodal_prefix),
706 true);
707 }
709 VisMF::AsyncWrite(*mf_u[level],
710 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_uface_prefix),
711 true);
712 VisMF::AsyncWrite(*mf_v[level],
713 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_vface_prefix),
714 true);
715 VisMF::AsyncWrite(*mf_w[level],
716 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_wface_prefix),
717 true);
718 }
719 if (mf_2d_rho[level]->nComp() > 0) {
720 VisMF::AsyncWrite(*mf_2d_rho[level],
721 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_2d_rho_prefix),
722 true);
723 }
724 if (mf_2d_u[level]->nComp() > 0) {
725 VisMF::AsyncWrite(*mf_2d_u[level],
726 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_2d_u_prefix),
727 true);
728 }
729 if (mf_2d_v[level]->nComp() > 0) {
730 VisMF::AsyncWrite(*mf_2d_v[level],
731 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_2d_v_prefix),
732 true);
733 }
734 } else {
735 const MultiFab* data;
736 std::unique_ptr<MultiFab> mf_tmp;
737 if (mf[level]->nGrowVect() != 0) {
738 mf_tmp = std::make_unique<MultiFab>(mf[level]->boxArray(),
739 mf[level]->DistributionMap(),
740 mf[level]->nComp(), 0, MFInfo(),
741 mf[level]->Factory());
742 MultiFab::Copy(*mf_tmp, *mf[level], 0, 0, mf[level]->nComp(), 0);
743 data = mf_tmp.get();
744 } else {
745 data = mf[level];
746 }
747 VisMF::Write(*data , MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mfPrefix));
748 if (plot_nodal_data) {
749 VisMF::Write(*mf_nd[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_nodal_prefix));
750 }
752 VisMF::Write(*mf_u[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_uface_prefix));
753 VisMF::Write(*mf_v[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_vface_prefix));
754 VisMF::Write(*mf_w[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_wface_prefix));
755 }
756 if (mf_2d_rho[level]->nComp() > 0) {
757 VisMF::Write(*mf_2d_rho[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_2d_rho_prefix));
758 }
759 if (mf_2d_u[level]->nComp() > 0) {
760 VisMF::Write(*mf_2d_u[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_2d_u_prefix));
761 }
762 if (mf_2d_v[level]->nComp() > 0) {
763 VisMF::Write(*mf_2d_v[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_2d_v_prefix));
764 }
765 }
766 } // level
767}
768
769/**
770 * @param HeaderFile output stream for header
771 * @param nlevels number of levels to write out
772 * @param bArray vector over levels of BoxArrays
773 * @param varnames_3d 3D variable names to write out
774 * @param varnames_2d 2D variable names to write out
775 * @param my_geom geometry to use for writing plotfile
776 * @param time time at which to output
777 * @param level_steps vector over level of iterations
778 * @param my_ref_ratio refinement ratio to use for writing plotfile
779 * @param versionName version string for VisIt
780 * @param levelPrefix string to prepend to level number
781 * @param mfPrefix subdirectory for multifab data
782 */
783void
785 [[maybe_unused]] int nlevels,
786 const Vector<BoxArray> &bArray,
787 const Vector<std::string> &varnames_3d,
788 const Vector<std::string> &varnames_2d_rho,
789 const Vector<std::string> &varnames_2d_u,
790 const Vector<std::string> &varnames_2d_v,
791 const Vector<Geometry>& my_geom,
792 Real time,
793 const Vector<int> &level_steps,
794 const Vector<IntVect>& my_ref_ratio,
795 const std::string &versionName,
796 const std::string &levelPrefix,
797 const std::string &mfPrefix) const
798{
799 AMREX_ASSERT(nlevels <= bArray.size());
800 AMREX_ASSERT(nlevels <= ref_ratio.size()+1);
801 AMREX_ASSERT(nlevels <= level_steps.size());
802
803 int num_extra_mfs = 1; // for nodal, which is always on
805 num_extra_mfs += 3; // for nodal, which is always on
806 }
807
808 HeaderFile.precision(17);
809
810 // ---- this is the generic plot file type name
811 HeaderFile << versionName << '\n';
812
813 HeaderFile << varnames_3d.size() << '\n';
814
815 for (int ivar = 0; ivar < varnames_3d.size(); ++ivar) {
816 HeaderFile << varnames_3d[ivar] << "\n";
817 }
818 HeaderFile << AMREX_SPACEDIM << '\n';
819 HeaderFile << time << '\n';
820 HeaderFile << finest_level << '\n';
821 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
822 HeaderFile << my_geom[0].ProbLo(i) << ' ';
823 }
824 HeaderFile << '\n';
825 for (int i = 0; i < AMREX_SPACEDIM; ++i) {
826 HeaderFile << my_geom[0].ProbHi(i) << ' ';
827 }
828 HeaderFile << '\n';
829 for (int i = 0; i < finest_level; ++i) {
830 HeaderFile << my_ref_ratio[i][0] << ' ';
831 }
832 HeaderFile << '\n';
833 for (int i = 0; i <= finest_level; ++i) {
834 HeaderFile << my_geom[i].Domain() << ' ';
835 }
836 HeaderFile << '\n';
837 for (int i = 0; i <= finest_level; ++i) {
838 HeaderFile << level_steps[i] << ' ';
839 }
840 HeaderFile << '\n';
841 for (int i = 0; i <= finest_level; ++i) {
842 for (int k = 0; k < AMREX_SPACEDIM; ++k) {
843 HeaderFile << my_geom[i].CellSize()[k] << ' ';
844 }
845 HeaderFile << '\n';
846 }
847 HeaderFile << (int) my_geom[0].Coord() << '\n';
848 HeaderFile << "0\n";
849
850 for (int level = 0; level <= finest_level; ++level) {
851 HeaderFile << level << ' ' << bArray[level].size() << ' ' << time << '\n';
852 HeaderFile << level_steps[level] << '\n';
853
854 const IntVect& domain_lo = my_geom[level].Domain().smallEnd();
855 for (int i = 0; i < bArray[level].size(); ++i)
856 {
857 // Need to shift because the RealBox ctor we call takes the
858 // physical location of index (0,0,0). This does not affect
859 // the usual cases where the domain index starts with 0.
860 const Box& b = shift(bArray[level][i], -domain_lo);
861 RealBox loc = RealBox(b, my_geom[level].CellSize(), my_geom[level].ProbLo());
862 for (int n = 0; n < AMREX_SPACEDIM; ++n) {
863 HeaderFile << loc.lo(n) << ' ' << loc.hi(n) << '\n';
864 }
865 }
866
867 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mfPrefix) << '\n';
868 }
869 HeaderFile << num_extra_mfs << "\n";
870 HeaderFile << "3" << "\n";
871 HeaderFile << "amrexvec_nu_x" << "\n";
872 HeaderFile << "amrexvec_nu_y" << "\n";
873 HeaderFile << "amrexvec_nu_z" << "\n";
874 std::string mf_nodal_prefix = "Nu_nd";
875 for (int level = 0; level <= finest_level; ++level) {
876 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_nodal_prefix) << '\n';
877 }
879 HeaderFile << "1" << "\n"; // number of components in the multifab
880 HeaderFile << "u_vel" << "\n";
881 std::string mf_uface_prefix = "UFace";
882 for (int level = 0; level <= finest_level; ++level) {
883 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_uface_prefix) << '\n';
884 }
885 HeaderFile << "1" << "\n";
886 HeaderFile << "v_vel" << "\n";
887 std::string mf_vface_prefix = "VFace";
888 for (int level = 0; level <= finest_level; ++level) {
889 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_vface_prefix) << '\n';
890 }
891 HeaderFile << "1" << "\n";
892 HeaderFile << "w_vel" << "\n";
893 std::string mf_wface_prefix = "WFace";
894 for (int level = 0; level <= finest_level; ++level) {
895 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_wface_prefix) << '\n';
896 }
897 }
898
899 if (varnames_2d_rho.size() > 0) {
900 HeaderFile << varnames_2d_rho.size() << "\n"; // number of components in the 2D rho multifab
901 for (int ivar = 0; ivar < varnames_2d_rho.size(); ++ivar) {
902 HeaderFile << varnames_2d_rho[ivar] << "\n";
903 }
904 std::string mf_2d_rho_prefix = "rho2d";
905 for (int level = 0; level <= finest_level; ++level) {
906 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_2d_rho_prefix) << "\n";
907 }
908 }
909
910 if (varnames_2d_u.size() > 0) {
911 HeaderFile << varnames_2d_u.size() << "\n"; // number of components in the 2D rho multifab
912 for (int ivar = 0; ivar < varnames_2d_u.size(); ++ivar) {
913 HeaderFile << varnames_2d_u[ivar] << "\n";
914 }
915 std::string mf_2d_u_prefix = "u2d";
916 for (int level = 0; level <= finest_level; ++level) {
917 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_2d_u_prefix) << "\n";
918 }
919 }
920
921 if (varnames_2d_v.size() > 0) {
922 HeaderFile << varnames_2d_v.size() << "\n"; // number of components in the 2D v multifab
923 for (int ivar = 0; ivar < varnames_2d_v.size(); ++ivar) {
924 HeaderFile << varnames_2d_v[ivar] << "\n";
925 }
926 std::string mf_2d_v_prefix = "v2d";
927 for (int level = 0; level <= finest_level; ++level) {
928 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_2d_v_prefix) << "\n";
929 }
930 }
931}
932
933/**
934 * @param lev level to mask
935 * @param fill_value fill value to mask with
936 * @param fill_where value at cells where we will apply the mask. This is necessary because rivers
937 */
938void
939REMORA::mask_arrays_for_write(int lev, Real fill_value, Real fill_where)
940{
941 for (MFIter mfi(*cons_new[lev],false); mfi.isValid(); ++mfi) {
942 Box gbx1 = mfi.growntilebox(IntVect(NGROW+1,NGROW+1,0));
943 Box gbx_coeff = mfi.growntilebox(IntVect(NGROW,NGROW,0));
944 Box ubx = mfi.grownnodaltilebox(0,IntVect(NGROW,NGROW,0));
945 Box vbx = mfi.grownnodaltilebox(1,IntVect(NGROW,NGROW,0));
946
947 Array4<Real> const& Zt_avg1 = vec_Zt_avg1[lev]->array(mfi);
948 Array4<Real> const& ubar = vec_ubar[lev]->array(mfi);
949 Array4<Real> const& vbar = vec_vbar[lev]->array(mfi);
950 Array4<Real> const& xvel = xvel_new[lev]->array(mfi);
951 Array4<Real> const& yvel = yvel_new[lev]->array(mfi);
952 Array4<Real> const& visc2 = vec_visc2_r[lev]->array(mfi);
953 Array4<Real> const& diff2 = vec_diff2[lev]->array(mfi);
954 Array4<Real> const& temp = cons_new[lev]->array(mfi,Temp_comp);
955 Array4<Real> const& salt = cons_new[lev]->array(mfi,Salt_comp);
956
957 Array4<Real const> const& mskr = vec_mskr[lev]->array(mfi);
958 Array4<Real const> const& msku = vec_msku[lev]->array(mfi);
959 Array4<Real const> const& mskv = vec_mskv[lev]->array(mfi);
960 const int ncons_local = ncons;
961
962 ParallelFor(makeSlab(gbx1,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int )
963 {
964 if (mskr(i,j,0) == 0.0) { // Explicitly compare to 0.0
965 Zt_avg1(i,j,0) = fill_value;
966 }
967 });
968 ParallelFor(gbx1, [=] AMREX_GPU_DEVICE (int i, int j, int k)
969 {
970 if (mskr(i,j,0) == 0.0) { // Explicitly compare to 0.0
971 temp(i,j,k) = fill_value;
972 salt(i,j,k) = fill_value;
973 }
974 });
975 ParallelFor(makeSlab(gbx_coeff,2,0), [=] AMREX_GPU_DEVICE (int i, int j, int )
976 {
977 if (mskr(i,j,0) == 0.0) { // Explicitly compare to 0.0
978 visc2(i,j,0) = fill_value;
979 for (int n = 0; n < ncons_local; ++n) {
980 diff2(i,j,0,n) = fill_value;
981 }
982 }
983 });
984 ParallelFor(makeSlab(ubx,2,0), 3, [=] AMREX_GPU_DEVICE (int i, int j, int , int n)
985 {
986 if (msku(i,j,0) == 0.0 && ubar(i,j,0)==fill_where) { // Explicitly compare to 0.0
987 ubar(i,j,0,n) = fill_value;
988 }
989 });
990 ParallelFor(makeSlab(vbx,2,0), 3, [=] AMREX_GPU_DEVICE (int i, int j, int , int n)
991 {
992 if (mskv(i,j,0) == 0.0 && vbar(i,j,0)==fill_where) { // Explicitly compare to 0.0
993 vbar(i,j,0,n) = fill_value;
994 }
995 });
996 ParallelFor(ubx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
997 {
998 if (msku(i,j,0) == 0.0 && xvel(i,j,k)==fill_where) { // Explicitly compare to 0.0
999 xvel(i,j,k) = fill_value;
1000 }
1001 });
1002 ParallelFor(vbx, [=] AMREX_GPU_DEVICE (int i, int j, int k)
1003 {
1004 if (mskv(i,j,0) == 0.0 && yvel(i,j,k)==fill_where) { // Explicitly compare to 0.0
1005 yvel(i,j,k) = fill_value;
1006 }
1007 });
1008 } // mfi
1009 Gpu::streamSynchronize();
1010}
Coord
Coordinates.
#define NGROW
#define Temp_comp
#define Salt_comp
AMREX_ALWAYS_ASSERT(!NSPeriodic||!EWPeriodic)
pp_prob query("traditional", traditional)
bool containerHasElement(const V &iterable, const T &query)
static PhysBCFunctNoOp null_bc_for_fill
static PlotfileType plotfile_type
Native or NetCDF plotfile output.
Definition REMORA.H:1590
int ncons
Number of conserved scalars in the state (temperature + salt + passive scalars)
Definition REMORA.H:1480
static bool plot_staggered_vels
Whether to write the staggered velocities (not averaged to cell centers)
Definition REMORA.H:1584
amrex::Vector< amrex::BCRec > domain_bcs_type
vector (over BCVars) of BCRecs
Definition REMORA.H:1429
amrex::Vector< std::string > cons_names
Names of scalars for plotfile output.
Definition REMORA.H:1531
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_fcor
coriolis factor (2D)
Definition REMORA.H:500
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_h
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:335
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pm
horizontal scaling factor: 1 / dx (2D)
Definition REMORA.H:491
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_lrflx
longwave radiation
Definition REMORA.H:414
amrex::Vector< amrex::MultiFab * > cons_new
multilevel data container for current step's scalar data: temperature, salinity, passive tracer
Definition REMORA.H:315
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskr
land/sea mask at cell centers (2D)
Definition REMORA.H:480
amrex::Real plotfile_fill_value
fill value for masked arrays in amrex plotfiles
Definition REMORA.H:1543
void writeJobInfo(const std::string &dir) const
Write job info to stdout.
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_sustr
Surface stress in the u direction.
Definition REMORA.H:396
amrex::Vector< amrex::MultiFab * > zvel_new
multilevel data container for current step's z velocities (largely unused; W stored separately)
Definition REMORA.H:321
int foextrap_bc() const noexcept
Definition REMORA.H:1189
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_msku
land/sea mask at x-faces (2D)
Definition REMORA.H:482
void FillPatchNoBC(int lev, amrex::Real time, amrex::MultiFab &mf_to_be_filled, amrex::Vector< amrex::MultiFab * > const &mfs, const int bdy_var_type=BdyVars::null, const int icomp=0, const bool fill_all=true, const bool fill_set=true)
Fill a new MultiFab by copying in phi from valid region and filling ghost cells without applying boun...
amrex::Vector< amrex::MultiFab * > yvel_new
multilevel data container for current step's y velocities (v in ROMS)
Definition REMORA.H:319
static bool plot_nodal_data
Whether to write nodal data (Nu_nd) to plotfiles.
Definition REMORA.H:1587
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_shflx
sensible heat flux
Definition REMORA.H:420
amrex::Vector< amrex::MultiFab * > xvel_new
multilevel data container for current step's x velocities (u in ROMS)
Definition REMORA.H:317
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_lhflx
latent heat flux
Definition REMORA.H:418
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_mskv
land/sea mask at y-faces (2D)
Definition REMORA.H:484
amrex::Vector< int > istep
which step?
Definition REMORA.H:1403
void WriteMultiLevelPlotfileWithBathymetry(const std::string &plotfilename, int nlevels, const amrex::Vector< const amrex::MultiFab * > &mf, const amrex::Vector< const amrex::MultiFab * > &mf_nd, const amrex::Vector< const amrex::MultiFab * > &mf_u, const amrex::Vector< const amrex::MultiFab * > &mf_v, const amrex::Vector< const amrex::MultiFab * > &mf_w, const amrex::Vector< const amrex::MultiFab * > &mf_2d_rho, const amrex::Vector< const amrex::MultiFab * > &mf_2d_u, const amrex::Vector< const amrex::MultiFab * > &mf_2d_v, const amrex::Vector< std::string > &varnames_3d, const amrex::Vector< std::string > &varnames_2d_rho, const amrex::Vector< std::string > &varnames_2d_u, const amrex::Vector< std::string > &varnames_2d_v, const amrex::Vector< amrex::Geometry > &my_geom, amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &rr, const std::string &versionName="HyperCLaw-V1.1", const std::string &levelPrefix="Level_", const std::string &mfPrefix="Cell", const amrex::Vector< std::string > &extra_dirs=amrex::Vector< std::string >()) const
write out particular data to an AMReX plotfile
void mask_arrays_for_write(int lev, amrex::Real fill_value, amrex::Real fill_where)
Mask data arrays before writing output.
static int file_min_digits
Minimum number of digits in plotfile name or chunked history file.
Definition REMORA.H:1581
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_visc2_r
Harmonic viscosity defined on the rho points (centers)
Definition REMORA.H:365
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_svstr
Surface stress in the v direction.
Definition REMORA.H:398
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_DV_avg1
time average of barotropic y velocity flux
Definition REMORA.H:460
void WriteNCPlotFile(int istep, amrex::MultiFab const *plotMF)
Write plotfile using NetCDF (wrapper)
amrex::Vector< amrex::Real > t_new
new time at each level
Definition REMORA.H:1407
static SolverChoice solverChoice
Container for algorithmic choices.
Definition REMORA.H:1537
void WriteGenericPlotfileHeaderWithBathymetry(std::ostream &HeaderFile, int nlevels, const amrex::Vector< amrex::BoxArray > &bArray, const amrex::Vector< std::string > &varnames_3d, const amrex::Vector< std::string > &varnames_2d_rho, const amrex::Vector< std::string > &varnames_2d_u, const amrex::Vector< std::string > &varnames_2d_v, const amrex::Vector< amrex::Geometry > &my_geom, amrex::Real time, const amrex::Vector< int > &level_steps, const amrex::Vector< amrex::IntVect > &rr, const std::string &versionName, const std::string &levelPrefix, const std::string &mfPrefix) const
write out header data for an AMReX plotfile
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_vbar
barotropic y velocity (2D)
Definition REMORA.H:472
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_DU_avg1
time average of barotropic x velocity flux (2D)
Definition REMORA.H:456
bool expand_plotvars_to_unif_rr
whether plotfile variables should be expanded to a uniform refinement ratio
Definition REMORA.H:1540
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_ubar
barotropic x velocity (2D)
Definition REMORA.H:470
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_bustr
Bottom stress in the u direction.
Definition REMORA.H:451
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_bvstr
Bottom stress in the v direction.
Definition REMORA.H:453
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_z_phys_nd
z coordinates at psi points (cell nodes)
Definition REMORA.H:390
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_pn
horizontal scaling factor: 1 / dy (2D)
Definition REMORA.H:493
amrex::Vector< std::string > plot_var_names_3d
Names of 3D variables to output to AMReX plotfile.
Definition REMORA.H:1527
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_stflux
Surface tracer flux; input arrays.
Definition REMORA.H:425
std::string plot_file_name
Plotfile prefix.
Definition REMORA.H:1504
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_Zt_avg1
Average of the free surface, zeta (2D)
Definition REMORA.H:393
void WritePlotFile(int istep)
main driver for writing AMReX plotfiles
amrex::Vector< std::string > plot_var_names_2d
Names of 2D variables to output to AMReX plotfile.
Definition REMORA.H:1529
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_srflx
Shortwave radiation flux [W/m²], defined at rho-points.
Definition REMORA.H:412
amrex::Vector< std::unique_ptr< amrex::MultiFab > > vec_diff2
Harmonic diffusivity for temperature / salinity.
Definition REMORA.H:367
void remora_dervort(const amrex::Box &bx, amrex::FArrayBox &derfab, int dcomp, int ncomp, const amrex::FArrayBox &datfab, const amrex::Array4< const amrex::Real > &pm, const amrex::Array4< const amrex::Real > &pn, const amrex::Array4< const amrex::Real > &, const amrex::Geometry &, amrex::Real, const int *, const int)
void remora_dernull(const amrex::Box &, amrex::FArrayBox &, int, int, const amrex::FArrayBox &, const amrex::Array4< const amrex::Real > &, const amrex::Array4< const amrex::Real > &, const amrex::Array4< const amrex::Real > &, const amrex::Geometry &, amrex::Real, const int *, const int)