149 Vector<std::string> varnames;
152 const int ncomp_mf = varnames.size();
153 const auto ngrow_vars = IntVect(
NGROW-1,
NGROW-1,0);
161 for (
int lev = 0; lev <= finest_level; ++lev) {
169 Vector<MultiFab> mf(finest_level+1);
170 for (
int lev = 0; lev <= finest_level; ++lev) {
171 mf[lev].define(grids[lev], dmap[lev], ncomp_mf, ngrow_vars);
175 Vector<MultiFab> mf_nd(finest_level+1);
176 for (
int lev = 0; lev <= finest_level; ++lev) {
177 BoxArray nodal_grids(grids[lev]); nodal_grids.surroundingNodes();
178 mf_nd[lev].define(nodal_grids, dmap[lev], AMREX_SPACEDIM, 0);
179 mf_nd[lev].setVal(0.);
183 Vector<MultiFab> mf_cc_vel(finest_level+1);
190 for (
int lev = 0; lev <= finest_level; ++lev) {
191 mf_cc_vel[lev].define(grids[lev], dmap[lev], AMREX_SPACEDIM, IntVect(1,1,0));
192 mf_cc_vel[lev].setVal(0.0_rt);
193 average_face_to_cellcenter(mf_cc_vel[lev],0,
195 mf_cc_vel[lev].FillBoundary(geom[lev].periodicity());
199 amrex::Interpolater* mapper = &cell_cons_interp;
201 for (
int lev = 1; lev <= finest_level; ++lev) {
202 Vector<MultiFab*> fmf = {&(mf_cc_vel[lev]), &(mf_cc_vel[lev])};
203 Vector<Real> ftime = {
t_new[lev],
t_new[lev]};
204 Vector<MultiFab*> cmf = {&mf_cc_vel[lev-1], &mf_cc_vel[lev-1]};
205 Vector<Real> ctime = {
t_new[lev],
t_new[lev]};
208 amrex::FillPatchTwoLevels(mf_cc_vel[lev],
t_new[lev], cmf, ctime, fmf, ftime,
209 0, 0, AMREX_SPACEDIM, geom[lev-1], geom[lev],
216 for (
int lev = 0; lev <= finest_level; ++lev)
222 for (
int i = 0; i <
NCONS; ++i) {
225 amrex::Abort(
"Found while writing output: Cons (salt, temp, or scalar, etc) contains nan or inf");
227 MultiFab::Copy(mf[lev],*
cons_new[lev],i,mf_comp,1,ngrow_vars);
234 if (mf_cc_vel[lev].contains_nan(0,1) || mf_cc_vel[lev].contains_inf(0,1)) {
235 amrex::Abort(
"Found while writing output: u velocity contains nan or inf");
237 MultiFab::Copy(mf[lev], mf_cc_vel[lev], 0, mf_comp, 1, 0);
241 if (mf_cc_vel[lev].contains_nan(1,1) || mf_cc_vel[lev].contains_inf(1,1)) {
242 amrex::Abort(
"Found while writing output: v velocity contains nan or inf");
244 MultiFab::Copy(mf[lev], mf_cc_vel[lev], 1, mf_comp, 1, 0);
248 if (mf_cc_vel[lev].contains_nan(2,1) || mf_cc_vel[lev].contains_inf(2,1)) {
249 amrex::Abort(
"Found while writing output: z velocity contains nan or inf");
251 MultiFab::Copy(mf[lev], mf_cc_vel[lev], 2, mf_comp, 1, 0);
256 auto calculate_derived = [&](
const std::string& der_name,
260 MultiFab dmf(mf[lev], make_alias, mf_comp, 1);
262#pragma omp parallel if (amrex::Gpu::notInLaunchRegion())
264 for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi)
266 const Box& bx = mfi.tilebox();
267 auto& dfab = dmf[mfi];
269 if (der_name ==
"vorticity") {
270 auto const& sfab = mf_cc_vel[lev][mfi];
271 der_function(bx, dfab, 0, 1, sfab,
vec_pm[lev]->const_array(mfi),
vec_pn[lev]->const_array(mfi), Geom(lev),
t_new[0],
nullptr, lev);
273 auto const& sfab = (*
cons_new[lev])[mfi];
274 der_function(bx, dfab, 0, 1, sfab,
vec_pm[lev]->const_array(mfi),
vec_pn[lev]->const_array(mfi), Geom(lev),
t_new[0],
nullptr, lev);
286 Real dx = Geom()[lev].CellSizeArray()[0];
287 Real dy = Geom()[lev].CellSizeArray()[1];
294 MultiFab dmf(mf[lev], make_alias, mf_comp, AMREX_SPACEDIM);
296#pragma omp parallel if (Gpu::notInLaunchRegion())
298 for (MFIter mfi(dmf, TilingIfNotGPU()); mfi.isValid(); ++mfi) {
299 const Box& bx = mfi.tilebox();
300 const Array4<Real> loc_arr = dmf.array(mfi);
301 const Array4<Real const> zp_arr =
vec_z_phys_nd[lev]->const_array(mfi);
303 ParallelFor(bx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
304 loc_arr(i,j,k,0) = (i+0.5_rt) * dx;
305 loc_arr(i,j,k,1) = (j+0.5_rt) * dy;
306 loc_arr(i,j,k,2) = 0.125_rt * (zp_arr(i,j ,k ) + zp_arr(i+1,j ,k ) +
307 zp_arr(i,j+1,k ) + zp_arr(i+1,j+1,k ) +
308 zp_arr(i,j ,k+1) + zp_arr(i+1,j ,k+1) +
309 zp_arr(i,j+1,k+1) + zp_arr(i+1,j+1,k+1) );
312 mf_comp += AMREX_SPACEDIM;
315#ifdef REMORA_USE_PARTICLES
316 const auto& particles_namelist( particleData.getNames() );
317 for (ParticlesNamesVector::size_type i = 0; i < particles_namelist.size(); i++) {
319 MultiFab temp_dat(mf[lev].boxArray(), mf[lev].DistributionMap(), 1, 0);
321 particleData[particles_namelist[i]]->Increment(temp_dat, lev);
322 MultiFab::Copy(mf[lev], temp_dat, 0, mf_comp, 1, 0);
327 Vector<std::string> particle_mesh_plot_names(0);
328 particleData.GetMeshPlotVarNames( particle_mesh_plot_names );
329 for (
int i = 0; i < particle_mesh_plot_names.size(); i++) {
330 std::string plot_var_name(particle_mesh_plot_names[i]);
332 MultiFab temp_dat(mf[lev].boxArray(), mf[lev].DistributionMap(), 1, 1);
334 particleData.GetMeshPlotVar(plot_var_name, temp_dat, lev);
335 MultiFab::Copy(mf[lev], temp_dat, 0, mf_comp, 1, 0);
342 Real dz = Geom()[lev].CellSizeArray()[2];
343 int N = Geom()[lev].Domain().size()[2];
346#pragma omp parallel if (Gpu::notInLaunchRegion())
348 for (MFIter mfi(mf_nd[lev], TilingIfNotGPU()); mfi.isValid(); ++mfi)
350 const Box& bx = mfi.tilebox();
351 Array4<Real> mf_arr = mf_nd[lev].array(mfi);
352 ParallelFor(bx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k) {
353 mf_arr(i,j,k,2) = mf_arr(i,j,k,2) + (N-k) * dz;
361 if (finest_level == 0)
364 amrex::Print() <<
"Writing plotfile " << plotfilename <<
"\n";
366 GetVecOfConstPtrs(mf),
367 GetVecOfConstPtrs(mf_nd),
372#ifdef REMORA_USE_PARTICLES
373 particleData.Checkpoint(plotfilename);
376#ifdef REMORA_USE_HDF5
378 amrex::Print() <<
"Writing plotfile " << plotfilename+
"d01.h5" <<
"\n";
379 WriteMultiLevelPlotfileHDF5(plotfilename, finest_level+1,
380 GetVecOfConstPtrs(mf),
385 amrex::Abort(
"User specified unknown plot_filetype");
390 Vector<IntVect> r2(finest_level);
391 Vector<Geometry> g2(finest_level+1);
392 Vector<MultiFab> mf2(finest_level+1);
394 mf2[0].define(grids[0], dmap[0], ncomp_mf, 0);
397 MultiFab::Copy(mf2[0],mf[0],0,0,mf[0].nComp(),0);
400 Array<int,AMREX_SPACEDIM> periodicity =
401 {Geom()[0].isPeriodic(0),Geom()[0].isPeriodic(1),Geom()[0].isPeriodic(2)};
402 g2[0].define(Geom()[0].Domain(),&(Geom()[0].ProbDomain()),0,periodicity.data());
405 r2[0] = IntVect(1,1,ref_ratio[0][0]);
406 for (
int lev = 1; lev <= finest_level; ++lev) {
410 r2[lev-1][2] = r2[lev-2][2] * ref_ratio[lev-1][0];
413 mf2[lev].define(refine(grids[lev],r2[lev-1]), dmap[lev], ncomp_mf, 0);
416 Box d2(Geom()[lev].Domain());
417 d2.refine(r2[lev-1]);
419 g2[lev].define(d2,&(Geom()[lev].ProbDomain()),0,periodicity.data());
424 amrex::Vector<amrex::BCRec> null_dom_bcs;
425 null_dom_bcs.resize(mf2[0].nComp());
426 for (
int n = 0; n < mf2[0].nComp(); n++) {
427 for (
int dir = 0; dir < AMREX_SPACEDIM; dir++) {
434 for (
int lev = 1; lev <= finest_level; ++lev) {
435 Interpolater* mapper_c = &pc_interp;
436 InterpFromCoarseLevel(mf2[lev],
t_new[lev], mf[lev],
437 0, 0, mf2[lev].nComp(),
440 r2[lev-1], mapper_c, null_dom_bcs, 0);
444 Vector<IntVect> rr(finest_level);
445 for (
int lev = 0; lev < finest_level; ++lev) {
446 rr[lev] = IntVect(ref_ratio[lev][0],ref_ratio[lev][1],ref_ratio[lev][0]);
449 WriteMultiLevelPlotfile(plotfilename, finest_level+1, GetVecOfConstPtrs(mf2), varnames,
453#ifdef REMORA_USE_PARTICLES
454 particleData.Checkpoint(plotfilename);
475 const Vector<const MultiFab*>& mf,
476 const Vector<const MultiFab*>& mf_nd,
477 const Vector<std::string>& varnames,
479 const Vector<int>& level_steps,
480 const std::string &versionName,
481 const std::string &levelPrefix,
482 const std::string &mfPrefix,
483 const Vector<std::string>& extra_dirs)
const
485 BL_PROFILE(
"WriteMultiLevelPlotfileWithBathymetry()");
487 BL_ASSERT(nlevels <= mf.size());
488 BL_ASSERT(nlevels <= ref_ratio.size()+1);
489 BL_ASSERT(nlevels <= level_steps.size());
490 BL_ASSERT(mf[0]->nComp() == varnames.size());
492 bool callBarrier(
false);
493 PreBuildDirectorHierarchy(plotfilename, levelPrefix, nlevels, callBarrier);
494 if (!extra_dirs.empty()) {
495 for (
const auto& d : extra_dirs) {
496 const std::string ed = plotfilename+
"/"+d;
497 PreBuildDirectorHierarchy(ed, levelPrefix, nlevels, callBarrier);
500 ParallelDescriptor::Barrier();
502 if (ParallelDescriptor::MyProc() == ParallelDescriptor::NProcs()-1) {
503 Vector<BoxArray> boxArrays(nlevels);
504 for(
int level(0); level < boxArrays.size(); ++level) {
505 boxArrays[level] = mf[level]->boxArray();
509 VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size);
510 std::string HeaderFileName(plotfilename +
"/Header");
511 std::ofstream HeaderFile;
512 HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size());
513 HeaderFile.open(HeaderFileName.c_str(), std::ofstream::out |
514 std::ofstream::trunc |
515 std::ofstream::binary);
516 if( ! HeaderFile.good()) FileOpenFailed(HeaderFileName);
518 time, level_steps, versionName,
519 levelPrefix, mfPrefix);
522 if (AsyncOut::UseAsyncOut()) {
523 AsyncOut::Submit(std::move(f));
529 std::string mf_nodal_prefix =
"Nu_nd";
530 for (
int level = 0; level <= finest_level; ++level)
532 if (AsyncOut::UseAsyncOut()) {
533 VisMF::AsyncWrite(*mf[level],
534 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mfPrefix),
536 VisMF::AsyncWrite(*mf_nd[level],
537 MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_nodal_prefix),
540 const MultiFab* data;
541 std::unique_ptr<MultiFab> mf_tmp;
542 if (mf[level]->nGrowVect() != 0) {
543 mf_tmp = std::make_unique<MultiFab>(mf[level]->boxArray(),
544 mf[level]->DistributionMap(),
545 mf[level]->nComp(), 0, MFInfo(),
546 mf[level]->Factory());
547 MultiFab::Copy(*mf_tmp, *mf[level], 0, 0, mf[level]->nComp(), 0);
552 VisMF::Write(*data , MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mfPrefix));
553 VisMF::Write(*mf_nd[level], MultiFabFileFullPrefix(level, plotfilename, levelPrefix, mf_nodal_prefix));
572 const Vector<BoxArray> &bArray,
573 const Vector<std::string> &varnames,
575 const Vector<int> &level_steps,
576 const std::string &versionName,
577 const std::string &levelPrefix,
578 const std::string &mfPrefix)
const
580 BL_ASSERT(nlevels <= bArray.size());
581 BL_ASSERT(nlevels <= ref_ratio.size()+1);
582 BL_ASSERT(nlevels <= level_steps.size());
584 HeaderFile.precision(17);
587 HeaderFile << versionName <<
'\n';
589 HeaderFile << varnames.size() <<
'\n';
591 for (
int ivar = 0; ivar < varnames.size(); ++ivar) {
592 HeaderFile << varnames[ivar] <<
"\n";
594 HeaderFile << AMREX_SPACEDIM <<
'\n';
595 HeaderFile << time <<
'\n';
596 HeaderFile << finest_level <<
'\n';
597 for (
int i = 0; i < AMREX_SPACEDIM; ++i) {
598 HeaderFile << geom[0].ProbLo(i) <<
' ';
601 for (
int i = 0; i < AMREX_SPACEDIM; ++i) {
602 HeaderFile << geom[0].ProbHi(i) <<
' ';
605 for (
int i = 0; i < finest_level; ++i) {
606 HeaderFile << ref_ratio[i][0] <<
' ';
609 for (
int i = 0; i <= finest_level; ++i) {
610 HeaderFile << geom[i].Domain() <<
' ';
613 for (
int i = 0; i <= finest_level; ++i) {
614 HeaderFile << level_steps[i] <<
' ';
617 for (
int i = 0; i <= finest_level; ++i) {
618 for (
int k = 0; k < AMREX_SPACEDIM; ++k) {
619 HeaderFile << geom[i].CellSize()[k] <<
' ';
623 HeaderFile << (int) geom[0].
Coord() <<
'\n';
626 for (
int level = 0; level <= finest_level; ++level) {
627 HeaderFile << level <<
' ' << bArray[level].size() <<
' ' << time <<
'\n';
628 HeaderFile << level_steps[level] <<
'\n';
630 const IntVect& domain_lo = geom[level].Domain().smallEnd();
631 for (
int i = 0; i < bArray[level].size(); ++i)
636 const Box& b = shift(bArray[level][i], -domain_lo);
637 RealBox loc = RealBox(b, geom[level].CellSize(), geom[level].ProbLo());
638 for (
int n = 0; n < AMREX_SPACEDIM; ++n) {
639 HeaderFile << loc.lo(n) <<
' ' << loc.hi(n) <<
'\n';
643 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mfPrefix) <<
'\n';
645 HeaderFile <<
"1" <<
"\n";
646 HeaderFile <<
"3" <<
"\n";
647 HeaderFile <<
"amrexvec_nu_x" <<
"\n";
648 HeaderFile <<
"amrexvec_nu_y" <<
"\n";
649 HeaderFile <<
"amrexvec_nu_z" <<
"\n";
650 std::string mf_nodal_prefix =
"Nu_nd";
651 for (
int level = 0; level <= finest_level; ++level) {
652 HeaderFile << MultiFabHeaderPath(level, levelPrefix, mf_nodal_prefix) <<
'\n';
663 for (MFIter mfi(*
cons_new[lev],
false); mfi.isValid(); ++mfi) {
664 Box gbx1 = mfi.growntilebox(IntVect(
NGROW+1,
NGROW+1,0));
665 Box ubx = mfi.grownnodaltilebox(0,IntVect(
NGROW,
NGROW,0));
666 Box vbx = mfi.grownnodaltilebox(1,IntVect(
NGROW,
NGROW,0));
668 Array4<Real>
const& Zt_avg1 =
vec_Zt_avg1[lev]->array(mfi);
669 Array4<Real>
const& ubar =
vec_ubar[lev]->array(mfi);
670 Array4<Real>
const& vbar =
vec_vbar[lev]->array(mfi);
671 Array4<Real>
const& xvel =
xvel_new[lev]->array(mfi);
672 Array4<Real>
const& yvel =
yvel_new[lev]->array(mfi);
676 Array4<Real const>
const& mskr =
vec_mskr[lev]->array(mfi);
677 Array4<Real const>
const& msku =
vec_msku[lev]->array(mfi);
678 Array4<Real const>
const& mskv =
vec_mskv[lev]->array(mfi);
680 ParallelFor(makeSlab(gbx1,2,0), [=] AMREX_GPU_DEVICE (
int i,
int j,
int )
683 Zt_avg1(i,j,0) = fill_value;
686 ParallelFor(gbx1, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
689 temp(i,j,k) = fill_value;
690 salt(i,j,k) = fill_value;
693 ParallelFor(makeSlab(ubx,2,0), 3, [=] AMREX_GPU_DEVICE (
int i,
int j,
int ,
int n)
695 if (!msku(i,j,0) && ubar(i,j,0)==fill_where) {
696 ubar(i,j,0,n) = fill_value;
699 ParallelFor(makeSlab(vbx,2,0), 3, [=] AMREX_GPU_DEVICE (
int i,
int j,
int ,
int n)
701 if (!mskv(i,j,0) && vbar(i,j,0)==fill_where) {
702 vbar(i,j,0,n) = fill_value;
705 ParallelFor(ubx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
707 if (!msku(i,j,0) && xvel(i,j,k)==fill_where) {
708 xvel(i,j,k) = fill_value;
711 ParallelFor(vbx, [=] AMREX_GPU_DEVICE (
int i,
int j,
int k)
713 if (!mskv(i,j,0) && yvel(i,j,k)==fill_where) {
714 yvel(i,j,k) = fill_value;
718 Gpu::streamSynchronize();