aboutsummaryrefslogtreecommitdiff
path: root/Source/Diagnostics/WarpXIO.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Diagnostics/WarpXIO.cpp')
-rw-r--r--Source/Diagnostics/WarpXIO.cpp1538
1 files changed, 1538 insertions, 0 deletions
diff --git a/Source/Diagnostics/WarpXIO.cpp b/Source/Diagnostics/WarpXIO.cpp
new file mode 100644
index 000000000..e68b4a4e8
--- /dev/null
+++ b/Source/Diagnostics/WarpXIO.cpp
@@ -0,0 +1,1538 @@
+
+#include <AMReX_MultiFabUtil.H>
+#include <AMReX_PlotFileUtil.H>
+#include <AMReX_FillPatchUtil_F.H>
+
+#include <WarpX.H>
+
+#include "AMReX_buildInfo.H"
+
+#ifdef BL_USE_SENSEI_INSITU
+#include <AMReX_AmrMeshInSituBridge.H>
+#endif
+
+using namespace amrex;
+
+namespace
+{
+ const std::string level_prefix {"Level_"};
+}
+
+void
+WarpX::GotoNextLine (std::istream& is)
+{
+ constexpr std::streamsize bl_ignore_max { 100000 };
+ is.ignore(bl_ignore_max, '\n');
+}
+
+void
+WarpX::WriteWarpXHeader(const std::string& name) const
+{
+ if (ParallelDescriptor::IOProcessor())
+ {
+ VisMF::IO_Buffer io_buffer(VisMF::IO_Buffer_Size);
+ std::ofstream HeaderFile;
+ HeaderFile.rdbuf()->pubsetbuf(io_buffer.dataPtr(), io_buffer.size());
+ std::string HeaderFileName(name + "/WarpXHeader");
+ HeaderFile.open(HeaderFileName.c_str(), std::ofstream::out |
+ std::ofstream::trunc |
+ std::ofstream::binary);
+ if( ! HeaderFile.good()) {
+ amrex::FileOpenFailed(HeaderFileName);
+ }
+
+ HeaderFile.precision(17);
+
+ HeaderFile << "Checkpoint version: 1\n";
+
+ const int nlevels = finestLevel()+1;
+ HeaderFile << nlevels << "\n";
+
+ for (int i = 0; i < istep.size(); ++i) {
+ HeaderFile << istep[i] << " ";
+ }
+ HeaderFile << "\n";
+
+ for (int i = 0; i < nsubsteps.size(); ++i) {
+ HeaderFile << nsubsteps[i] << " ";
+ }
+ HeaderFile << "\n";
+
+ for (int i = 0; i < t_new.size(); ++i) {
+ HeaderFile << t_new[i] << " ";
+ }
+ HeaderFile << "\n";
+
+ for (int i = 0; i < t_old.size(); ++i) {
+ HeaderFile << t_old[i] << " ";
+ }
+ HeaderFile << "\n";
+
+ for (int i = 0; i < dt.size(); ++i) {
+ HeaderFile << dt[i] << " ";
+ }
+ HeaderFile << "\n";
+
+ HeaderFile << moving_window_x << "\n";
+
+ HeaderFile << is_synchronized << "\n";
+
+ // Geometry
+ for (int i = 0; i < AMREX_SPACEDIM; ++i) {
+ HeaderFile << Geometry::ProbLo(i) << ' ';
+ }
+ HeaderFile << '\n';
+ for (int i = 0; i < AMREX_SPACEDIM; ++i) {
+ HeaderFile << Geometry::ProbHi(i) << ' ';
+ }
+ HeaderFile << '\n';
+
+ // BoxArray
+ for (int lev = 0; lev < nlevels; ++lev) {
+ boxArray(lev).writeOn(HeaderFile);
+ HeaderFile << '\n';
+ }
+
+ mypc->WriteHeader(HeaderFile);
+ }
+}
+
+void
+WarpX::WriteCheckPointFile() const
+{
+ BL_PROFILE("WarpX::WriteCheckPointFile()");
+
+ VisMF::Header::Version current_version = VisMF::GetHeaderVersion();
+ VisMF::SetHeaderVersion(checkpoint_headerversion);
+
+ const std::string& checkpointname = amrex::Concatenate(check_file,istep[0]);
+
+ amrex::Print() << " Writing checkpoint " << checkpointname << "\n";
+
+ const int nlevels = finestLevel()+1;
+ amrex::PreBuildDirectorHierarchy(checkpointname, level_prefix, nlevels, true);
+
+ WriteWarpXHeader(checkpointname);
+
+ WriteJobInfo(checkpointname);
+
+ for (int lev = 0; lev < nlevels; ++lev)
+ {
+ VisMF::Write(*Efield_fp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Ex_fp"));
+ VisMF::Write(*Efield_fp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Ey_fp"));
+ VisMF::Write(*Efield_fp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Ez_fp"));
+ VisMF::Write(*Bfield_fp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Bx_fp"));
+ VisMF::Write(*Bfield_fp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "By_fp"));
+ VisMF::Write(*Bfield_fp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Bz_fp"));
+ if (is_synchronized) {
+ // Need to save j if synchronized because after restart we need j to evolve E by dt/2.
+ VisMF::Write(*current_fp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "jx_fp"));
+ VisMF::Write(*current_fp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "jy_fp"));
+ VisMF::Write(*current_fp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "jz_fp"));
+ }
+
+ if (lev > 0)
+ {
+ VisMF::Write(*Efield_cp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Ex_cp"));
+ VisMF::Write(*Efield_cp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Ey_cp"));
+ VisMF::Write(*Efield_cp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Ez_cp"));
+ VisMF::Write(*Bfield_cp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Bx_cp"));
+ VisMF::Write(*Bfield_cp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "By_cp"));
+ VisMF::Write(*Bfield_cp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "Bz_cp"));
+ if (is_synchronized) {
+ // Need to save j if synchronized because after restart we need j to evolve E by dt/2.
+ VisMF::Write(*current_cp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "jx_cp"));
+ VisMF::Write(*current_cp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "jy_cp"));
+ VisMF::Write(*current_cp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "jz_cp"));
+ }
+ }
+
+ if (do_pml && pml[lev]) {
+ pml[lev]->CheckPoint(amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "pml"));
+ }
+
+ if (costs[lev]) {
+ VisMF::Write(*costs[lev],
+ amrex::MultiFabFileFullPrefix(lev, checkpointname, level_prefix, "costs"));
+ }
+ }
+
+ mypc->Checkpoint(checkpointname, true);
+
+ VisMF::SetHeaderVersion(current_version);
+}
+
+
+void
+WarpX::InitFromCheckpoint ()
+{
+ BL_PROFILE("WarpX::InitFromCheckpoint()");
+
+ amrex::Print() << " Restart from checkpoint " << restart_chkfile << "\n";
+
+ // Header
+ {
+ std::string File(restart_chkfile + "/WarpXHeader");
+
+ VisMF::IO_Buffer io_buffer(VisMF::GetIOBufferSize());
+
+ Vector<char> fileCharPtr;
+ ParallelDescriptor::ReadAndBcastFile(File, fileCharPtr);
+ std::string fileCharPtrString(fileCharPtr.dataPtr());
+ std::istringstream is(fileCharPtrString, std::istringstream::in);
+
+ std::string line, word;
+
+ std::getline(is, line);
+
+ int nlevs;
+ is >> nlevs;
+ GotoNextLine(is);
+ finest_level = nlevs-1;
+
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ istep[i++] = std::stoi(word);
+ }
+ }
+
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ nsubsteps[i++] = std::stoi(word);
+ }
+ }
+
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ t_new[i++] = std::stod(word);
+ }
+ }
+
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ t_old[i++] = std::stod(word);
+ }
+ }
+
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ dt[i++] = std::stod(word);
+ }
+ }
+
+ is >> moving_window_x;
+ GotoNextLine(is);
+
+ is >> is_synchronized;
+ GotoNextLine(is);
+
+ Real prob_lo[AMREX_SPACEDIM];
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ prob_lo[i++] = std::stod(word);
+ }
+ }
+
+ Real prob_hi[AMREX_SPACEDIM];
+ std::getline(is, line);
+ {
+ std::istringstream lis(line);
+ int i = 0;
+ while (lis >> word) {
+ prob_hi[i++] = std::stod(word);
+ }
+ }
+
+ Geometry::ProbDomain(RealBox(prob_lo,prob_hi));
+
+ for (int lev = 0; lev < nlevs; ++lev) {
+ BoxArray ba;
+ ba.readFrom(is);
+ GotoNextLine(is);
+ DistributionMapping dm { ba, ParallelDescriptor::NProcs() };
+ SetBoxArray(lev, ba);
+ SetDistributionMap(lev, dm);
+ AllocLevelData(lev, ba, dm);
+ }
+
+ mypc->ReadHeader(is);
+ }
+
+ const int nlevs = finestLevel()+1;
+
+ // Initialize the field data
+ for (int lev = 0; lev < nlevs; ++lev)
+ {
+ for (int i = 0; i < 3; ++i) {
+ current_fp[lev][i]->setVal(0.0);
+ Efield_fp[lev][i]->setVal(0.0);
+ Bfield_fp[lev][i]->setVal(0.0);
+ }
+
+ if (lev > 0) {
+ for (int i = 0; i < 3; ++i) {
+ Efield_aux[lev][i]->setVal(0.0);
+ Bfield_aux[lev][i]->setVal(0.0);
+
+ current_cp[lev][i]->setVal(0.0);
+ Efield_cp[lev][i]->setVal(0.0);
+ Bfield_cp[lev][i]->setVal(0.0);
+ }
+ }
+
+ VisMF::Read(*Efield_fp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Ex_fp"));
+ VisMF::Read(*Efield_fp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Ey_fp"));
+ VisMF::Read(*Efield_fp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Ez_fp"));
+
+ VisMF::Read(*Bfield_fp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Bx_fp"));
+ VisMF::Read(*Bfield_fp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "By_fp"));
+ VisMF::Read(*Bfield_fp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Bz_fp"));
+
+ if (is_synchronized) {
+ VisMF::Read(*current_fp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "jx_fp"));
+ VisMF::Read(*current_fp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "jy_fp"));
+ VisMF::Read(*current_fp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "jz_fp"));
+ }
+
+ if (lev > 0)
+ {
+ VisMF::Read(*Efield_cp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Ex_cp"));
+ VisMF::Read(*Efield_cp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Ey_cp"));
+ VisMF::Read(*Efield_cp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Ez_cp"));
+
+ VisMF::Read(*Bfield_cp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Bx_cp"));
+ VisMF::Read(*Bfield_cp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "By_cp"));
+ VisMF::Read(*Bfield_cp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "Bz_cp"));
+
+ if (is_synchronized) {
+ VisMF::Read(*current_cp[lev][0],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "jx_cp"));
+ VisMF::Read(*current_cp[lev][1],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "jy_cp"));
+ VisMF::Read(*current_cp[lev][2],
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "jz_cp"));
+ }
+ }
+
+ if (costs[lev]) {
+ const auto& cost_mf_name =
+ amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "costs");
+ if (VisMF::Exist(cost_mf_name)) {
+ VisMF::Read(*costs[lev], cost_mf_name);
+ } else {
+ costs[lev]->setVal(0.0);
+ }
+ }
+ }
+
+ if (do_pml)
+ {
+ InitPML();
+ for (int lev = 0; lev < nlevs; ++lev) {
+ pml[lev]->Restart(amrex::MultiFabFileFullPrefix(lev, restart_chkfile, level_prefix, "pml"));
+ }
+ }
+
+ // Initilize particles
+ mypc->AllocData();
+ mypc->Restart(restart_chkfile);
+
+#ifdef WARPX_DO_ELECTROSTATIC
+ if (do_electrostatic) {
+ getLevelMasks(masks);
+
+ // the plus one is to convert from num_cells to num_nodes
+ getLevelMasks(gather_masks, 4 + 1);
+ }
+#endif // WARPX_DO_ELECTROSTATIC
+}
+
+
+std::unique_ptr<MultiFab>
+WarpX::GetCellCenteredData() {
+
+ BL_PROFILE("WarpX::GetCellCenteredData");
+
+ const int ng = 1;
+ const int nc = 10;
+
+ Vector<std::unique_ptr<MultiFab> > cc(finest_level+1);
+
+ for (int lev = 0; lev <= finest_level; ++lev)
+ {
+ cc[lev].reset( new MultiFab(grids[lev], dmap[lev], nc, ng) );
+
+ Vector<const MultiFab*> srcmf(AMREX_SPACEDIM);
+ int dcomp = 0;
+
+ // first the electric field
+ PackPlotDataPtrs(srcmf, Efield_aux[lev]);
+ amrex::average_edge_to_cellcenter(*cc[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*cc[lev], *cc[lev], dcomp+1, dcomp+2, 1, ng);
+ amrex::average_node_to_cellcenter(*cc[lev], dcomp+1, *Efield_aux[lev][1], 0, 1);
+#endif
+ dcomp += 3;
+
+ // then the magnetic field
+ PackPlotDataPtrs(srcmf, Bfield_aux[lev]);
+ amrex::average_face_to_cellcenter(*cc[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*cc[lev], *cc[lev], dcomp+1, dcomp+2, 1, ng);
+ MultiFab::Copy(*cc[lev], *Bfield_aux[lev][1], 0, dcomp+1, 1, ng);
+#endif
+ dcomp += 3;
+
+ // then the current density
+ PackPlotDataPtrs(srcmf, current_fp[lev]);
+ amrex::average_edge_to_cellcenter(*cc[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*cc[lev], *cc[lev], dcomp+1, dcomp+2, 1, ng);
+ amrex::average_node_to_cellcenter(*cc[lev], dcomp+1, *current_fp[lev][1], 0, 1);
+#endif
+ dcomp += 3;
+
+ const std::unique_ptr<MultiFab>& charge_density = mypc->GetChargeDensity(lev);
+ amrex::average_node_to_cellcenter(*cc[lev], dcomp, *charge_density, 0, 1);
+
+ cc[lev]->FillBoundary(geom[lev].periodicity());
+ }
+
+ for (int lev = finest_level; lev > 0; --lev)
+ {
+ amrex::average_down(*cc[lev], *cc[lev-1], 0, nc, refRatio(lev-1));
+ }
+
+ return std::move(cc[0]);
+}
+
+void
+WarpX::UpdateInSitu () const
+{
+#ifdef BL_USE_SENSEI_INSITU
+ BL_PROFILE("WarpX::UpdateInSitu()");
+
+ int numLevels = finest_level + 1;
+ Vector<std::string> varnames;
+ Vector<MultiFab> mf;
+
+ const int ncomp = 3*3
+ + static_cast<int>(plot_part_per_cell)
+ + static_cast<int>(plot_part_per_grid)
+ + static_cast<int>(plot_part_per_proc)
+ + static_cast<int>(plot_proc_number)
+ + static_cast<int>(plot_divb)
+ + static_cast<int>(plot_dive)
+ + static_cast<int>(plot_rho)
+ + static_cast<int>(plot_F)
+ + static_cast<int>(plot_finepatch)*6
+ + static_cast<int>(plot_crsepatch)*6
+ + static_cast<int>(costs[0] != nullptr);
+
+ for (int lev = 0; lev <= finest_level; ++lev)
+ {
+ const int ngrow = 1;
+ mf.push_back(MultiFab(grids[lev], dmap[lev], ncomp, ngrow));
+
+ Vector<const MultiFab*> srcmf(AMREX_SPACEDIM);
+ PackPlotDataPtrs(srcmf, current_fp[lev]);
+ int dcomp = 0;
+ amrex::average_edge_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(mf[lev], dcomp+1, *current_fp[lev][1], 0, 1, ngrow);
+#endif
+ if (lev == 0)
+ {
+ varnames.push_back("jx");
+ varnames.push_back("jy");
+ varnames.push_back("jz");
+ }
+ dcomp += 3;
+
+ PackPlotDataPtrs(srcmf, Efield_aux[lev]);
+ amrex::average_edge_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(mf[lev], dcomp+1, *Efield_aux[lev][1], 0, 1, ngrow);
+#endif
+ if (lev == 0)
+ {
+ varnames.push_back("Ex");
+ varnames.push_back("Ey");
+ varnames.push_back("Ez");
+ }
+ dcomp += 3;
+
+ PackPlotDataPtrs(srcmf, Bfield_aux[lev]);
+ amrex::average_face_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ MultiFab::Copy(mf[lev], *Bfield_aux[lev][1], 0, dcomp+1, 1, ngrow);
+#endif
+ if (lev == 0)
+ {
+ varnames.push_back("Bx");
+ varnames.push_back("By");
+ varnames.push_back("Bz");
+ }
+ dcomp += 3;
+
+ if (plot_part_per_cell)
+ {
+ MultiFab temp_dat(grids[lev], mf[lev].DistributionMap(), 1, ngrow);
+ temp_dat.setVal(0, ngrow);
+
+ // MultiFab containing number of particles in each cell
+ mypc->Increment(temp_dat, lev);
+ MultiFab::Copy(mf[lev], temp_dat, 0, dcomp, 1, ngrow);
+ if (lev == 0)
+ varnames.push_back("part_per_cell");
+ dcomp += 1;
+ }
+
+ if (plot_part_per_grid || plot_part_per_proc)
+ {
+ const Vector<long>& npart_in_grid = mypc->NumberOfParticlesInGrid(lev);
+
+ if (plot_part_per_grid)
+ {
+#ifdef _OPENMP
+#pragma omp parallel
+#endif
+ for (MFIter mfi(mf[lev]); mfi.isValid(); ++mfi)
+ (mf[lev])[mfi].setVal(static_cast<Real>(npart_in_grid[mfi.index()]), dcomp);
+
+ if (lev == 0)
+ varnames.push_back("part_per_grid");
+
+ dcomp += 1;
+ }
+
+ if (plot_part_per_proc)
+ {
+ long n_per_proc = 0;
+#ifdef _OPENMP
+#pragma omp parallel reduction(+:n_per_proc)
+#endif
+ for (MFIter mfi(mf[lev]); mfi.isValid(); ++mfi)
+ n_per_proc += npart_in_grid[mfi.index()];
+
+ mf[lev].setVal(static_cast<Real>(n_per_proc), dcomp, ngrow);
+
+ if (lev == 0)
+ varnames.push_back("part_per_proc");
+
+ dcomp += 1;
+ }
+ }
+
+ if (plot_proc_number)
+ {
+ Real procid = static_cast<Real>(ParallelDescriptor::MyProc());
+#ifdef _OPENMP
+#pragma omp parallel
+#endif
+ for (MFIter mfi(mf[lev]); mfi.isValid(); ++mfi)
+ (mf[lev])[mfi].setVal(procid, dcomp);
+
+ if (lev == 0)
+ varnames.push_back("proc_number");
+
+ dcomp += 1;
+ }
+
+ if (plot_divb)
+ {
+ ComputeDivB(mf[lev], dcomp,
+ {Bfield_aux[lev][0].get(),Bfield_aux[lev][1].get(),Bfield_aux[lev][2].get()},
+ WarpX::CellSize(lev), ngrow);
+ if (lev == 0)
+ varnames.push_back("divB");
+
+ dcomp += 1;
+ }
+
+ if (plot_dive)
+ {
+ const BoxArray& ba = amrex::convert(boxArray(lev),IntVect::TheUnitVector());
+ MultiFab dive(ba, DistributionMap(lev), 1, ngrow);
+
+ ComputeDivE(dive, 0,
+ {Efield_aux[lev][0].get(), Efield_aux[lev][1].get(), Efield_aux[lev][2].get()},
+ WarpX::CellSize(lev), ngrow);
+
+ amrex::average_node_to_cellcenter(mf[lev], dcomp, dive, 0, 1, ngrow);
+
+ if (lev == 0)
+ varnames.push_back("divE");
+
+ dcomp += 1;
+ }
+
+ if (plot_rho)
+ {
+ amrex::average_node_to_cellcenter(mf[lev], dcomp, *rho_fp[lev], 0, 1, ngrow);
+ if (lev == 0)
+ varnames.push_back("rho");
+
+ dcomp += 1;
+ }
+
+ if (plot_F)
+ {
+ amrex::average_node_to_cellcenter(mf[lev], dcomp, *F_fp[lev], 0, 1, ngrow);
+
+ if (lev == 0)
+ varnames.push_back("F");
+
+ dcomp += 1;
+ }
+
+ if (plot_finepatch)
+ {
+ PackPlotDataPtrs(srcmf, Efield_fp[lev]);
+ amrex::average_edge_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(mf[lev], dcomp+1, *Efield_fp[lev][1], 0, 1, ngrow);
+#endif
+ if (lev == 0)
+ {
+ varnames.push_back("Ex_fp");
+ varnames.push_back("Ey_fp");
+ varnames.push_back("Ez_fp");
+ }
+ dcomp += 3;
+
+ PackPlotDataPtrs(srcmf, Bfield_fp[lev]);
+ amrex::average_face_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ MultiFab::Copy(mf[lev], *Bfield_fp[lev][1], 0, dcomp+1, 1, ngrow);
+#endif
+ if (lev == 0)
+ {
+ varnames.push_back("Bx_fp");
+ varnames.push_back("By_fp");
+ varnames.push_back("Bz_fp");
+ }
+ dcomp += 3;
+ }
+
+ if (plot_crsepatch)
+ {
+ // First the electric field
+ if (lev == 0)
+ {
+ mf[lev].setVal(0.0, dcomp, 3, ngrow);
+ }
+ else
+ {
+ std::array<std::unique_ptr<MultiFab>, 3> E = getInterpolatedE(lev);
+ PackPlotDataPtrs(srcmf, E);
+ amrex::average_edge_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(mf[lev], dcomp+1, *E[1], 0, 1, ngrow);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Ex_cp");
+ varnames.push_back("Ey_cp");
+ varnames.push_back("Ez_cp");
+ }
+ dcomp += 3;
+
+ // now the magnetic field
+ if (lev == 0)
+ {
+ mf[lev].setVal(0.0, dcomp, 3, ngrow);
+ }
+ else
+ {
+ std::array<std::unique_ptr<MultiFab>, 3> B = getInterpolatedB(lev);
+ PackPlotDataPtrs(srcmf, B);
+ amrex::average_face_to_cellcenter(mf[lev], dcomp, srcmf, ngrow);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(mf[lev], mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ MultiFab::Copy(mf[lev], *B[1], 0, dcomp+1, 1, ngrow);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Bx_cp");
+ varnames.push_back("By_cp");
+ varnames.push_back("Bz_cp");
+ }
+ dcomp += 3;
+ }
+
+ if (costs[0] != nullptr)
+ {
+ MultiFab::Copy(mf[lev], *costs[lev], 0, dcomp, 1, ngrow);
+ if (lev == 0)
+ {
+ varnames.push_back("costs");
+ }
+ dcomp += 1;
+ }
+
+ BL_ASSERT(dcomp == ncomp);
+ }
+
+ if (insitu_bridge->update(istep[0], t_new[0],
+ dynamic_cast<amrex::AmrMesh*>(const_cast<WarpX*>(this)),
+ {&mf}, {varnames}))
+ {
+ amrex::ErrorStream()
+ << "WarpXIO::UpdateInSitu : Failed to update the in situ bridge."
+ << std::endl;
+
+ amrex::Abort();
+ }
+#endif
+}
+
+void
+WarpX::WritePlotFile () const
+{
+ BL_PROFILE("WarpX::WritePlotFile()");
+
+ VisMF::Header::Version current_version = VisMF::GetHeaderVersion();
+ VisMF::SetHeaderVersion(plotfile_headerversion);
+
+ const std::string& plotfilename = amrex::Concatenate(plot_file,istep[0]);
+
+ amrex::Print() << " Writing plotfile " << plotfilename << "\n";
+
+ {
+ Vector<std::string> varnames;
+ Vector<std::unique_ptr<MultiFab> > mf(finest_level+1);
+
+ const int ncomp = 3*3
+ + static_cast<int>(plot_part_per_cell)
+ + static_cast<int>(plot_part_per_grid)
+ + static_cast<int>(plot_part_per_proc)
+ + static_cast<int>(plot_proc_number)
+ + static_cast<int>(plot_divb)
+ + static_cast<int>(plot_dive)
+ + static_cast<int>(plot_rho)
+ + static_cast<int>(plot_F)
+ + static_cast<int>(plot_finepatch)*6
+ + static_cast<int>(plot_crsepatch)*6
+ + static_cast<int>(costs[0] != nullptr);
+
+ for (int lev = 0; lev <= finest_level; ++lev)
+ {
+ const int ngrow = 0;
+ mf[lev].reset(new MultiFab(grids[lev], dmap[lev], ncomp, ngrow));
+
+ Vector<const MultiFab*> srcmf(AMREX_SPACEDIM);
+ int dcomp = 0;
+
+ // j
+ if (do_nodal)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp , *current_fp[lev][0], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *current_fp[lev][1], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+2, *current_fp[lev][2], 0, 1);
+ }
+ else
+ {
+ PackPlotDataPtrs(srcmf, current_fp[lev]);
+ amrex::average_edge_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *current_fp[lev][1], 0, 1);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("jx");
+ varnames.push_back("jy");
+ varnames.push_back("jz");
+ }
+ dcomp += 3;
+
+ // E
+ if (do_nodal)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp , *Efield_aux[lev][0], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *Efield_aux[lev][1], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+2, *Efield_aux[lev][2], 0, 1);
+ }
+ else
+ {
+ PackPlotDataPtrs(srcmf, Efield_aux[lev]);
+ amrex::average_edge_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *Efield_aux[lev][1], 0, 1);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Ex");
+ varnames.push_back("Ey");
+ varnames.push_back("Ez");
+ }
+ dcomp += 3;
+
+ // B
+ if (do_nodal)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp , *Bfield_aux[lev][0], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *Bfield_aux[lev][1], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+2, *Bfield_aux[lev][2], 0, 1);
+ }
+ else
+ {
+ PackPlotDataPtrs(srcmf, Bfield_aux[lev]);
+ amrex::average_face_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ MultiFab::Copy(*mf[lev], *Bfield_aux[lev][1], 0, dcomp+1, 1, ngrow);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Bx");
+ varnames.push_back("By");
+ varnames.push_back("Bz");
+ }
+ dcomp += 3;
+
+ if (plot_part_per_cell)
+ {
+ MultiFab temp_dat(grids[lev],mf[lev]->DistributionMap(),1,0);
+ temp_dat.setVal(0);
+
+ // MultiFab containing number of particles in each cell
+ mypc->Increment(temp_dat, lev);
+ MultiFab::Copy(*mf[lev], temp_dat, 0, dcomp, 1, 0);
+ if (lev == 0)
+ {
+ varnames.push_back("part_per_cell");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_part_per_grid || plot_part_per_proc)
+ {
+ const Vector<long>& npart_in_grid = mypc->NumberOfParticlesInGrid(lev);
+
+ if (plot_part_per_grid)
+ {
+ // MultiFab containing number of particles per grid (stored as constant for all cells in each grid)
+#ifdef _OPENMP
+#pragma omp parallel
+#endif
+ for (MFIter mfi(*mf[lev]); mfi.isValid(); ++mfi) {
+ (*mf[lev])[mfi].setVal(static_cast<Real>(npart_in_grid[mfi.index()]), dcomp);
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("part_per_grid");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_part_per_proc)
+ {
+ // MultiFab containing number of particles per process (stored as constant for all cells in each grid)
+ long n_per_proc = 0;
+#ifdef _OPENMP
+#pragma omp parallel reduction(+:n_per_proc)
+#endif
+ for (MFIter mfi(*mf[lev]); mfi.isValid(); ++mfi) {
+ n_per_proc += npart_in_grid[mfi.index()];
+ }
+ mf[lev]->setVal(static_cast<Real>(n_per_proc), dcomp,1);
+ if (lev == 0)
+ {
+ varnames.push_back("part_per_proc");
+ }
+ dcomp += 1;
+ }
+ }
+
+ if (plot_proc_number)
+ {
+ // MultiFab containing the Processor ID
+#ifdef _OPENMP
+#pragma omp parallel
+#endif
+ for (MFIter mfi(*mf[lev]); mfi.isValid(); ++mfi) {
+ (*mf[lev])[mfi].setVal(static_cast<Real>(ParallelDescriptor::MyProc()), dcomp);
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("proc_number");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_divb)
+ {
+ if (do_nodal) amrex::Abort("TODO: do_nodal && plot_divb");
+ ComputeDivB(*mf[lev], dcomp,
+ {Bfield_aux[lev][0].get(),Bfield_aux[lev][1].get(),Bfield_aux[lev][2].get()},
+ WarpX::CellSize(lev));
+ if (lev == 0)
+ {
+ varnames.push_back("divB");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_dive)
+ {
+ if (do_nodal) amrex::Abort("TODO: do_nodal && plot_dive");
+ const BoxArray& ba = amrex::convert(boxArray(lev),IntVect::TheUnitVector());
+ MultiFab dive(ba,DistributionMap(lev),1,0);
+ ComputeDivE(dive, 0,
+ {Efield_aux[lev][0].get(), Efield_aux[lev][1].get(), Efield_aux[lev][2].get()},
+ WarpX::CellSize(lev));
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp, dive, 0, 1);
+ if (lev == 0)
+ {
+ varnames.push_back("divE");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_rho)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp, *rho_fp[lev], 0, 1);
+ if (lev == 0)
+ {
+ varnames.push_back("rho");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_F)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp, *F_fp[lev], 0, 1);
+ if (lev == 0)
+ {
+ varnames.push_back("F");
+ }
+ dcomp += 1;
+ }
+
+ if (plot_finepatch)
+ {
+ if (do_nodal)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp , *Efield_fp[lev][0], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *Efield_fp[lev][1], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+2, *Efield_fp[lev][2], 0, 1);
+ }
+ else
+ {
+ PackPlotDataPtrs(srcmf, Efield_fp[lev]);
+ amrex::average_edge_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *Efield_fp[lev][1], 0, 1);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Ex_fp");
+ varnames.push_back("Ey_fp");
+ varnames.push_back("Ez_fp");
+ }
+ dcomp += 3;
+
+ if (do_nodal)
+ {
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp , *Bfield_fp[lev][0], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *Bfield_fp[lev][1], 0, 1);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+2, *Bfield_fp[lev][2], 0, 1);
+ }
+ else
+ {
+ PackPlotDataPtrs(srcmf, Bfield_fp[lev]);
+ amrex::average_face_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ MultiFab::Copy(*mf[lev], *Bfield_fp[lev][1], 0, dcomp+1, 1, ngrow);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Bx_fp");
+ varnames.push_back("By_fp");
+ varnames.push_back("Bz_fp");
+ }
+ dcomp += 3;
+ }
+
+ if (plot_crsepatch)
+ {
+ // First the electric field
+ if (lev == 0)
+ {
+ mf[lev]->setVal(0.0, dcomp, 3, ngrow);
+ }
+ else
+ {
+ if (do_nodal) amrex::Abort("TODO: do_nodal && plot_crsepatch");
+ std::array<std::unique_ptr<MultiFab>, 3> E = getInterpolatedE(lev);
+ PackPlotDataPtrs(srcmf, E);
+ amrex::average_edge_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ amrex::average_node_to_cellcenter(*mf[lev], dcomp+1, *E[1], 0, 1);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Ex_cp");
+ varnames.push_back("Ey_cp");
+ varnames.push_back("Ez_cp");
+ }
+ dcomp += 3;
+
+ // now the magnetic field
+ if (lev == 0)
+ {
+ mf[lev]->setVal(0.0, dcomp, 3, ngrow);
+ }
+ else
+ {
+ if (do_nodal) amrex::Abort("TODO: do_nodal && plot_crsepatch");
+ std::array<std::unique_ptr<MultiFab>, 3> B = getInterpolatedB(lev);
+ PackPlotDataPtrs(srcmf, B);
+ amrex::average_face_to_cellcenter(*mf[lev], dcomp, srcmf);
+#if (AMREX_SPACEDIM == 2)
+ MultiFab::Copy(*mf[lev], *mf[lev], dcomp+1, dcomp+2, 1, ngrow);
+ MultiFab::Copy(*mf[lev], *B[1], 0, dcomp+1, 1, ngrow);
+#endif
+ }
+ if (lev == 0)
+ {
+ varnames.push_back("Bx_cp");
+ varnames.push_back("By_cp");
+ varnames.push_back("Bz_cp");
+ }
+ dcomp += 3;
+ }
+
+ if (costs[0] != nullptr)
+ {
+ MultiFab::Copy(*mf[lev], *costs[lev], 0, dcomp, 1, 0);
+ if (lev == 0)
+ {
+ varnames.push_back("costs");
+ }
+ dcomp += 1;
+ }
+
+ BL_ASSERT(dcomp == ncomp);
+ }
+
+#if 0
+ for (int lev = finest_level; lev > 0; --lev)
+ {
+ amrex::average_down(*mf[lev], *mf[lev-1], 0, ncomp, refRatio(lev-1));
+ }
+#endif
+
+ Vector<std::string> rfs;
+ if (plot_raw_fields) rfs.emplace_back("raw_fields"); // pre-build raw_fields/
+ amrex::WriteMultiLevelPlotfile(plotfilename, finest_level+1,
+ amrex::GetVecOfConstPtrs(mf),
+ varnames, Geom(), t_new[0], istep, refRatio(),
+ "HyperCLaw-V1.1",
+ "Level_",
+ "Cell",
+ rfs);
+ }
+
+ if (plot_raw_fields)
+ {
+ const int nlevels = finestLevel()+1;
+ for (int lev = 0; lev < nlevels; ++lev)
+ {
+ const std::string raw_plotfilename = plotfilename + "/raw_fields";
+ // Plot auxilary patch
+ if (plot_raw_fields_guards) {
+ VisMF::Write(*Efield_aux[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_aux"));
+ VisMF::Write(*Efield_aux[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_aux"));
+ VisMF::Write(*Efield_aux[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_aux"));
+ VisMF::Write(*Bfield_aux[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_aux"));
+ VisMF::Write(*Bfield_aux[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_aux"));
+ VisMF::Write(*Bfield_aux[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_aux"));
+ } else {
+ const DistributionMapping& dm = DistributionMap(lev);
+ MultiFab Ex(Efield_aux[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab Ey(Efield_aux[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab Ez(Efield_aux[lev][2]->boxArray(), dm, 1, 0);
+ MultiFab Bx(Bfield_aux[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab By(Bfield_aux[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab Bz(Bfield_aux[lev][2]->boxArray(), dm, 1, 0);
+ MultiFab::Copy(Ex, *Efield_aux[lev][0], 0, 0, 1, 0);
+ MultiFab::Copy(Ey, *Efield_aux[lev][1], 0, 0, 1, 0);
+ MultiFab::Copy(Ez, *Efield_aux[lev][2], 0, 0, 1, 0);
+ MultiFab::Copy(Bx, *Bfield_aux[lev][0], 0, 0, 1, 0);
+ MultiFab::Copy(By, *Bfield_aux[lev][1], 0, 0, 1, 0);
+ MultiFab::Copy(Bz, *Bfield_aux[lev][2], 0, 0, 1, 0);
+ VisMF::Write(Ex, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_aux"));
+ VisMF::Write(Ey, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_aux"));
+ VisMF::Write(Ez, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_aux"));
+ VisMF::Write(Bx, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_aux"));
+ VisMF::Write(By, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_aux"));
+ VisMF::Write(Bz, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_aux"));
+ }
+
+ // Plot fine patch
+ if (plot_finepatch) {
+ if (plot_raw_fields_guards) {
+ VisMF::Write(*Efield_fp[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_fp"));
+ VisMF::Write(*Efield_fp[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_fp"));
+ VisMF::Write(*Efield_fp[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_fp"));
+ VisMF::Write(*Bfield_fp[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_fp"));
+ VisMF::Write(*Bfield_fp[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_fp"));
+ VisMF::Write(*Bfield_fp[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_fp"));
+ VisMF::Write(*current_fp[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "jx_fp"));
+ VisMF::Write(*current_fp[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "jy_fp"));
+ VisMF::Write(*current_fp[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "jz_fp"));
+ } else {
+ const DistributionMapping& dm = DistributionMap(lev);
+ MultiFab Ex(Efield_fp[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab Ey(Efield_fp[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab Ez(Efield_fp[lev][2]->boxArray(), dm, 1, 0);
+ MultiFab Bx(Bfield_fp[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab By(Bfield_fp[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab Bz(Bfield_fp[lev][2]->boxArray(), dm, 1, 0);
+ MultiFab jx(current_fp[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab jy(current_fp[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab jz(current_fp[lev][2]->boxArray(), dm, 1, 0);
+ MultiFab::Copy(Ex, *Efield_fp[lev][0], 0, 0, 1, 0);
+ MultiFab::Copy(Ey, *Efield_fp[lev][1], 0, 0, 1, 0);
+ MultiFab::Copy(Ez, *Efield_fp[lev][2], 0, 0, 1, 0);
+ MultiFab::Copy(Bx, *Bfield_fp[lev][0], 0, 0, 1, 0);
+ MultiFab::Copy(By, *Bfield_fp[lev][1], 0, 0, 1, 0);
+ MultiFab::Copy(Bz, *Bfield_fp[lev][2], 0, 0, 1, 0);
+ MultiFab::Copy(jx, *current_fp[lev][0], 0, 0, 1, 0);
+ MultiFab::Copy(jy, *current_fp[lev][1], 0, 0, 1, 0);
+ MultiFab::Copy(jz, *current_fp[lev][2], 0, 0, 1, 0);
+ VisMF::Write(Ex, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_fp"));
+ VisMF::Write(Ey, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_fp"));
+ VisMF::Write(Ez, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_fp"));
+ VisMF::Write(Bx, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_fp"));
+ VisMF::Write(By, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_fp"));
+ VisMF::Write(Bz, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_fp"));
+ VisMF::Write(jx, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "jx_fp"));
+ VisMF::Write(jy, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "jy_fp"));
+ VisMF::Write(jz, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "jz_fp"));
+ }
+ }
+
+ // Plot coarse patch
+ if (plot_crsepatch)
+ {
+ if (lev == 0)
+ {
+ const DistributionMapping& dm = DistributionMap(lev);
+ MultiFab Ex(Efield_aux[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab Ey(Efield_aux[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab Ez(Efield_aux[lev][2]->boxArray(), dm, 1, 0);
+ MultiFab Bx(Bfield_aux[lev][0]->boxArray(), dm, 1, 0);
+ MultiFab By(Bfield_aux[lev][1]->boxArray(), dm, 1, 0);
+ MultiFab Bz(Bfield_aux[lev][2]->boxArray(), dm, 1, 0);
+
+ Ex.setVal(0.0); Ey.setVal(0.0); Ez.setVal(0.0);
+ Bx.setVal(0.0); By.setVal(0.0); Bz.setVal(0.0);
+
+ VisMF::Write(Ex, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_cp"));
+ VisMF::Write(Ey, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_cp"));
+ VisMF::Write(Ez, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_cp"));
+ VisMF::Write(Bx, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_cp"));
+ VisMF::Write(By, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_cp"));
+ VisMF::Write(Bz, amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_cp"));
+ } else {
+
+ if (plot_raw_fields_guards) {
+ VisMF::Write(*Efield_cp[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_cp"));
+ VisMF::Write(*Efield_cp[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_cp"));
+ VisMF::Write(*Efield_cp[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_cp"));
+ VisMF::Write(*Bfield_cp[lev][0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_cp"));
+ VisMF::Write(*Bfield_cp[lev][1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_cp"));
+ VisMF::Write(*Bfield_cp[lev][2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_cp"));
+ } else {
+ std::array<std::unique_ptr<MultiFab>, 3> E = getInterpolatedE(lev);
+ std::array<std::unique_ptr<MultiFab>, 3> B = getInterpolatedB(lev);
+
+ VisMF::Write(*E[0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ex_cp"));
+ VisMF::Write(*E[1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ey_cp"));
+ VisMF::Write(*E[2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Ez_cp"));
+ VisMF::Write(*B[0], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bx_cp"));
+ VisMF::Write(*B[1], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "By_cp"));
+ VisMF::Write(*B[2], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "Bz_cp"));
+ }
+ }
+ }
+
+ if (F_fp[lev]) {
+ VisMF::Write(*F_fp[lev], amrex::MultiFabFileFullPrefix(lev, raw_plotfilename, level_prefix, "F_fp"));
+ }
+
+ }
+ }
+
+ Vector<std::string> particle_varnames;
+ particle_varnames.push_back("weight");
+
+ particle_varnames.push_back("momentum_x");
+ particle_varnames.push_back("momentum_y");
+ particle_varnames.push_back("momentum_z");
+
+ particle_varnames.push_back("Ex");
+ particle_varnames.push_back("Ey");
+ particle_varnames.push_back("Ez");
+
+ particle_varnames.push_back("Bx");
+ particle_varnames.push_back("By");
+ particle_varnames.push_back("Bz");
+
+#if (AMREX_SPACEDIM == 2) && WARPX_RZ
+ particle_varnames.push_back("theta");
+#endif
+
+#ifdef WARPX_STORE_OLD_PARTICLE_ATTRIBS
+ particle_varnames.push_back("xold");
+ particle_varnames.push_back("yold");
+ particle_varnames.push_back("zold");
+
+ particle_varnames.push_back("uxold");
+ particle_varnames.push_back("uyold");
+ particle_varnames.push_back("uzold");
+#endif
+
+ mypc->Checkpoint(plotfilename, true, particle_varnames);
+
+ WriteJobInfo(plotfilename);
+
+ WriteWarpXHeader(plotfilename);
+
+ VisMF::SetHeaderVersion(current_version);
+}
+
+void
+WarpX::WriteJobInfo (const std::string& dir) const
+{
+ if (ParallelDescriptor::IOProcessor())
+ {
+ // job_info file with details about the run
+ std::ofstream jobInfoFile;
+ std::string FullPathJobInfoFile = dir;
+
+ std::string PrettyLine = std::string(78, '=') + "\n";
+// std::string OtherLine = std::string(78, '-') + "\n";
+// std::string SkipSpace = std::string(8, ' ') + "\n";
+
+ FullPathJobInfoFile += "/warpx_job_info";
+ jobInfoFile.open(FullPathJobInfoFile.c_str(), std::ios::out);
+
+ // job information
+ jobInfoFile << PrettyLine;
+ jobInfoFile << " WarpX Job Information\n";
+ jobInfoFile << PrettyLine;
+
+ jobInfoFile << "number of MPI processes: " << ParallelDescriptor::NProcs() << "\n";
+#ifdef _OPENMP
+ jobInfoFile << "number of threads: " << omp_get_max_threads() << "\n";
+#endif
+
+ jobInfoFile << "\n\n";
+
+ // build information
+ jobInfoFile << PrettyLine;
+ jobInfoFile << " Build Information\n";
+ jobInfoFile << PrettyLine;
+
+ jobInfoFile << "build date: " << buildInfoGetBuildDate() << "\n";
+ jobInfoFile << "build machine: " << buildInfoGetBuildMachine() << "\n";
+ jobInfoFile << "build dir: " << buildInfoGetBuildDir() << "\n";
+ jobInfoFile << "AMReX dir: " << buildInfoGetAMReXDir() << "\n";
+
+ jobInfoFile << "\n";
+
+ jobInfoFile << "COMP: " << buildInfoGetComp() << "\n";
+ jobInfoFile << "COMP version: " << buildInfoGetCompVersion() << "\n";
+
+ jobInfoFile << "\n";
+
+ jobInfoFile << "C++ compiler: " << buildInfoGetCXXName() << "\n";
+ jobInfoFile << "C++ flags: " << buildInfoGetCXXFlags() << "\n";
+
+ jobInfoFile << "\n";
+
+ jobInfoFile << "Fortran comp: " << buildInfoGetFName() << "\n";
+ jobInfoFile << "Fortran flags: " << buildInfoGetFFlags() << "\n";
+
+ jobInfoFile << "\n";
+
+ jobInfoFile << "Link flags: " << buildInfoGetLinkFlags() << "\n";
+ jobInfoFile << "Libraries: " << buildInfoGetLibraries() << "\n";
+
+ jobInfoFile << "\n";
+
+ const char* githash1 = buildInfoGetGitHash(1);
+ const char* githash2 = buildInfoGetGitHash(2);
+ const char* githash3 = buildInfoGetGitHash(3);
+ if (strlen(githash1) > 0) {
+ jobInfoFile << "WarpX git describe: " << githash1 << "\n";
+ }
+ if (strlen(githash2) > 0) {
+ jobInfoFile << "AMReX git describe: " << githash2 << "\n";
+ }
+ if (strlen(githash3) > 0) {
+ jobInfoFile << "PICSAR git describe: " << githash3 << "\n";
+ }
+
+ jobInfoFile << "\n\n";
+
+ // grid information
+ jobInfoFile << PrettyLine;
+ jobInfoFile << " Grid Information\n";
+ jobInfoFile << PrettyLine;
+
+ for (int i = 0; i <= finest_level; i++)
+ {
+ jobInfoFile << " level: " << i << "\n";
+ jobInfoFile << " number of boxes = " << grids[i].size() << "\n";
+ jobInfoFile << " maximum zones = ";
+ for (int n = 0; n < AMREX_SPACEDIM; n++)
+ {
+ jobInfoFile << geom[i].Domain().length(n) << " ";
+ }
+ jobInfoFile << "\n\n";
+ }
+
+ jobInfoFile << " Boundary conditions\n";
+
+ jobInfoFile << " -x: " << "interior" << "\n";
+ jobInfoFile << " +x: " << "interior" << "\n";
+ if (AMREX_SPACEDIM >= 2) {
+ jobInfoFile << " -y: " << "interior" << "\n";
+ jobInfoFile << " +y: " << "interior" << "\n";
+ }
+ if (AMREX_SPACEDIM == 3) {
+ jobInfoFile << " -z: " << "interior" << "\n";
+ jobInfoFile << " +z: " << "interior" << "\n";
+ }
+
+ jobInfoFile << "\n\n";
+
+
+ // runtime parameters
+ jobInfoFile << PrettyLine;
+ jobInfoFile << " Inputs File Parameters\n";
+ jobInfoFile << PrettyLine;
+
+ ParmParse::dumpTable(jobInfoFile, true);
+
+ jobInfoFile.close();
+ }
+}
+
+std::array<std::unique_ptr<MultiFab>, 3> WarpX::getInterpolatedE(int lev) const
+{
+
+ const int ngrow = 0;
+
+ std::array<std::unique_ptr<MultiFab>, 3> interpolated_E;
+ for (int i = 0; i < 3; ++i) {
+ interpolated_E[i].reset( new MultiFab(Efield_aux[lev][i]->boxArray(), dmap[lev], 1, ngrow) );
+ interpolated_E[i]->setVal(0.0);
+ }
+
+ const int r_ratio = refRatio(lev-1)[0];
+ const int use_limiter = 0;
+#ifdef _OPEMP
+#pragma omp parallel
+#endif
+ {
+ std::array<FArrayBox,3> efab;
+ for (MFIter mfi(*interpolated_E[0]); mfi.isValid(); ++mfi)
+ {
+ Box ccbx = mfi.fabbox();
+ ccbx.enclosedCells();
+ ccbx.coarsen(r_ratio).refine(r_ratio); // so that ccbx is coarsenable
+
+ const FArrayBox& cxfab = (*Efield_cp[lev][0])[mfi];
+ const FArrayBox& cyfab = (*Efield_cp[lev][1])[mfi];
+ const FArrayBox& czfab = (*Efield_cp[lev][2])[mfi];
+
+ efab[0].resize(amrex::convert(ccbx,Ex_nodal_flag));
+ efab[1].resize(amrex::convert(ccbx,Ey_nodal_flag));
+ efab[2].resize(amrex::convert(ccbx,Ez_nodal_flag));
+
+#if (AMREX_SPACEDIM == 3)
+ amrex_interp_efield(ccbx.loVect(), ccbx.hiVect(),
+ BL_TO_FORTRAN_ANYD(efab[0]),
+ BL_TO_FORTRAN_ANYD(efab[1]),
+ BL_TO_FORTRAN_ANYD(efab[2]),
+ BL_TO_FORTRAN_ANYD(cxfab),
+ BL_TO_FORTRAN_ANYD(cyfab),
+ BL_TO_FORTRAN_ANYD(czfab),
+ &r_ratio,&use_limiter);
+#else
+ amrex_interp_efield(ccbx.loVect(), ccbx.hiVect(),
+ BL_TO_FORTRAN_ANYD(efab[0]),
+ BL_TO_FORTRAN_ANYD(efab[2]),
+ BL_TO_FORTRAN_ANYD(cxfab),
+ BL_TO_FORTRAN_ANYD(czfab),
+ &r_ratio,&use_limiter);
+ amrex_interp_nd_efield(ccbx.loVect(), ccbx.hiVect(),
+ BL_TO_FORTRAN_ANYD(efab[1]),
+ BL_TO_FORTRAN_ANYD(cyfab),
+ &r_ratio);
+#endif
+
+ for (int i = 0; i < 3; ++i) {
+ const Box& bx = (*interpolated_E[i])[mfi].box();
+ (*interpolated_E[i])[mfi].plus(efab[i], bx, bx, 0, 0, 1);
+ }
+ }
+ }
+
+ return interpolated_E;
+}
+
+std::array<std::unique_ptr<MultiFab>, 3> WarpX::getInterpolatedB(int lev) const
+{
+ const int ngrow = 0;
+
+ std::array<std::unique_ptr<MultiFab>, 3> interpolated_B;
+ for (int i = 0; i < 3; ++i) {
+ interpolated_B[i].reset( new MultiFab(Bfield_aux[lev][i]->boxArray(), dmap[lev], 1, ngrow) );
+ interpolated_B[i]->setVal(0.0);
+ }
+
+ const Real* dx = Geom(lev-1).CellSize();
+ const int r_ratio = refRatio(lev-1)[0];
+ const int use_limiter = 0;
+#ifdef _OPEMP
+#pragma omp parallel
+#endif
+ {
+ std::array<FArrayBox,3> bfab;
+ for (MFIter mfi(*interpolated_B[0]); mfi.isValid(); ++mfi)
+ {
+ Box ccbx = mfi.fabbox();
+ ccbx.enclosedCells();
+ ccbx.coarsen(r_ratio).refine(r_ratio); // so that ccbx is coarsenable
+
+ const FArrayBox& cxfab = (*Bfield_cp[lev][0])[mfi];
+ const FArrayBox& cyfab = (*Bfield_cp[lev][1])[mfi];
+ const FArrayBox& czfab = (*Bfield_cp[lev][2])[mfi];
+
+ bfab[0].resize(amrex::convert(ccbx,Bx_nodal_flag));
+ bfab[1].resize(amrex::convert(ccbx,By_nodal_flag));
+ bfab[2].resize(amrex::convert(ccbx,Bz_nodal_flag));
+
+#if (AMREX_SPACEDIM == 3)
+ amrex_interp_div_free_bfield(ccbx.loVect(), ccbx.hiVect(),
+ BL_TO_FORTRAN_ANYD(bfab[0]),
+ BL_TO_FORTRAN_ANYD(bfab[1]),
+ BL_TO_FORTRAN_ANYD(bfab[2]),
+ BL_TO_FORTRAN_ANYD(cxfab),
+ BL_TO_FORTRAN_ANYD(cyfab),
+ BL_TO_FORTRAN_ANYD(czfab),
+ dx, &r_ratio, &use_limiter);
+#else
+ amrex_interp_div_free_bfield(ccbx.loVect(), ccbx.hiVect(),
+ BL_TO_FORTRAN_ANYD(bfab[0]),
+ BL_TO_FORTRAN_ANYD(bfab[2]),
+ BL_TO_FORTRAN_ANYD(cxfab),
+ BL_TO_FORTRAN_ANYD(czfab),
+ dx, &r_ratio, &use_limiter);
+ amrex_interp_cc_bfield(ccbx.loVect(), ccbx.hiVect(),
+ BL_TO_FORTRAN_ANYD(bfab[1]),
+ BL_TO_FORTRAN_ANYD(cyfab),
+ &r_ratio, &use_limiter);
+#endif
+
+ for (int i = 0; i < 3; ++i) {
+ const Box& bx = (*interpolated_B[i])[mfi].box();
+ (*interpolated_B[i])[mfi].plus(bfab[i], bx, bx, 0, 0, 1);
+ }
+ }
+ }
+ return interpolated_B;
+}
+
+void
+WarpX::PackPlotDataPtrs (Vector<const MultiFab*>& pmf,
+ const std::array<std::unique_ptr<MultiFab>,3>& data)
+{
+ BL_ASSERT(pmf.size() == AMREX_SPACEDIM);
+#if (AMREX_SPACEDIM == 3)
+ pmf[0] = data[0].get();
+ pmf[1] = data[1].get();
+ pmf[2] = data[2].get();
+#elif (AMREX_SPACEDIM == 2)
+ pmf[0] = data[0].get();
+ pmf[1] = data[2].get();
+#endif
+}