diff options
Diffstat (limited to 'Source/Diagnostics/WarpXOpenPMD.cpp')
-rw-r--r-- | Source/Diagnostics/WarpXOpenPMD.cpp | 209 |
1 files changed, 118 insertions, 91 deletions
diff --git a/Source/Diagnostics/WarpXOpenPMD.cpp b/Source/Diagnostics/WarpXOpenPMD.cpp index db2def7c7..6bef287a6 100644 --- a/Source/Diagnostics/WarpXOpenPMD.cpp +++ b/Source/Diagnostics/WarpXOpenPMD.cpp @@ -238,32 +238,43 @@ void WarpXOpenPMDPlot::GetFileName(std::string& filename) } -void WarpXOpenPMDPlot::SetStep (int ts, const std::string& filePrefix) +void WarpXOpenPMDPlot::SetStep (int ts, const std::string& filePrefix, + bool isBTD) { - AMREX_ALWAYS_ASSERT_WITH_MESSAGE(ts >= 0 , "openPMD iterations are unsigned"); - - if (m_CurrentStep >= ts) { - // note m_Series is reset in Init(), so using m_Series->iterations.contains(ts) is only able to check the - // last written step in m_Series's life time, but not other earlier written steps by other m_Series - std::string warnMsg = " Warning from openPMD writer: Already written iteration:"+std::to_string(ts); - std::cout<<warnMsg<<std::endl; - amrex::Warning(warnMsg); - } - - m_CurrentStep = ts; - Init(openPMD::Access::CREATE, filePrefix); - + AMREX_ALWAYS_ASSERT_WITH_MESSAGE(ts >= 0 , "openPMD iterations are unsigned"); + + if( ! isBTD ) { + if (m_CurrentStep >= ts) { + // note m_Series is reset in Init(), so using m_Series->iterations.contains(ts) is only able to check the + // last written step in m_Series's life time, but not other earlier written steps by other m_Series + std::string warnMsg = + " Warning from openPMD writer: Already written iteration:" + std::to_string(ts); + std::cout << warnMsg << std::endl; + amrex::Warning(warnMsg); + } + } + m_CurrentStep = ts; + Init(openPMD::Access::CREATE, filePrefix, isBTD); } -void WarpXOpenPMDPlot::CloseStep () +void WarpXOpenPMDPlot::CloseStep (bool isBTD, bool isLastBTDFlush) { - if (m_Series) - m_Series->iterations[m_CurrentStep].close(); + // default close is true + bool callClose = true; + // close BTD file only when isLastBTDFlush is true + if (isBTD and !isLastBTDFlush) callClose = false; + if (callClose) { + if (m_Series) + m_Series->iterations[m_CurrentStep].close(); + } } void -WarpXOpenPMDPlot::Init (openPMD::Access access, const std::string& filePrefix) +WarpXOpenPMDPlot::Init (openPMD::Access access, const std::string& filePrefix, bool isBTD) { + if( isBTD && m_Series != nullptr ) + return; // already open for this snapshot (aka timestep in lab frame) + // either for the next ts file, // or init a single file for all ts std::string filename = filePrefix; @@ -273,8 +284,7 @@ WarpXOpenPMDPlot::Init (openPMD::Access access, const std::string& filePrefix) // see ADIOS1 limitation: https://github.com/openPMD/openPMD-api/pull/686 m_Series = nullptr; - if( amrex::ParallelDescriptor::NProcs() > 1 ) - { + if (amrex::ParallelDescriptor::NProcs() > 1) { #if defined(AMREX_USE_MPI) m_Series = std::make_unique<openPMD::Series>( filename, access, @@ -285,9 +295,7 @@ WarpXOpenPMDPlot::Init (openPMD::Access access, const std::string& filePrefix) #else amrex::Abort("openPMD-api not built with MPI support!"); #endif - } - else - { + } else { m_Series = std::make_unique<openPMD::Series>(filename, access); m_MPISize = 1; m_MPIRank = 1; @@ -746,30 +754,39 @@ WarpXOpenPMDPlot::SetupPos( // this is originally copied from FieldIO.cpp // void -WarpXOpenPMDPlot::WriteOpenPMDFields( //const std::string& filename, +WarpXOpenPMDPlot::WriteOpenPMDFields ( //const std::string& filename, const std::vector<std::string>& varnames, const amrex::MultiFab& mf, - const amrex::Geometry& geom, + const amrex::Geometry& geom, // geometry of the mf/Fab const int iteration, - const double time ) const + const double time, bool isBTD, + const amrex::Geometry& full_BTD_snapshot ) const { //This is AMReX's tiny profiler. Possibly will apply it later WARPX_PROFILE("WarpXOpenPMDPlot::WriteOpenPMDFields()"); AMREX_ALWAYS_ASSERT_WITH_MESSAGE(m_Series != nullptr, "openPMD series must be initialized"); + amrex::Geometry full_geom = geom; + if( isBTD ) + full_geom = full_BTD_snapshot; + + // is this either a regular write (true) or the first write in a + // backtransformed diagnostic (BTD): + bool const first_write_to_iteration = ! m_Series->iterations.contains( iteration ); + int const ncomp = mf.nComp(); // Create a few vectors that store info on the global domain // Swap the indices for each of them, since AMReX data is Fortran order // and since the openPMD API assumes contiguous C order // - Size of the box, in integer number of cells - amrex::Box const & global_box = geom.Domain(); + amrex::Box const & global_box = full_geom.Domain(); auto const global_size = getReversedVec(global_box.size()); // - Grid spacing - std::vector<double> const grid_spacing = getReversedVec(geom.CellSize()); + std::vector<double> const grid_spacing = getReversedVec(full_geom.CellSize()); // - Global offset - std::vector<double> const global_offset = getReversedVec(geom.ProbLo()); + std::vector<double> const global_offset = getReversedVec(full_geom.ProbLo()); // - AxisLabels std::vector<std::string> axis_labels = detail::getFieldAxisLabels(); @@ -779,64 +796,70 @@ WarpXOpenPMDPlot::WriteOpenPMDFields( //const std::string& filename, // meta data auto series_iteration = m_Series->iterations[iteration]; - series_iteration.setTime( time ); - - // meta data for ED-PIC extension - auto const period = geom.periodicity(); // TODO double-check: is this the proper global bound or of some level? - std::vector< std::string > fieldBoundary( 6, "reflecting" ); - std::vector< std::string > particleBoundary( 6, "absorbing" ); -#if AMREX_SPACEDIM!=3 - fieldBoundary.resize(4); - particleBoundary.resize(4); + auto meshes = series_iteration.meshes; + if( first_write_to_iteration ) { + series_iteration.setTime( time ); + + // meta data for ED-PIC extension + auto const period = full_geom.periodicity(); // TODO double-check: is this the proper global bound or of some level? + std::vector<std::string> fieldBoundary(6, "reflecting"); + std::vector<std::string> particleBoundary(6, "absorbing"); +#if AMREX_SPACEDIM != 3 + fieldBoundary.resize(4); + particleBoundary.resize(4); #endif - for( auto i = 0u; i < fieldBoundary.size() / 2u; ++i ) - if( m_fieldPMLdirections.at( i ) ) - fieldBoundary.at( i ) = "open"; - - for( auto i = 0u; i < fieldBoundary.size() / 2u; ++i ) - if( period.isPeriodic( i ) ) { - fieldBoundary.at(2u*i ) = "periodic"; - fieldBoundary.at(2u*i + 1u) = "periodic"; - particleBoundary.at(2u*i ) = "periodic"; - particleBoundary.at(2u*i + 1u) = "periodic"; - } - - auto meshes = series_iteration.meshes; - meshes.setAttribute( "fieldSolver", [](){ - switch( WarpX::maxwell_solver_id ) { - case MaxwellSolverAlgo::Yee : return "Yee"; - case MaxwellSolverAlgo::CKC : return "CK"; - case MaxwellSolverAlgo::PSATD : return "PSATD"; - default: return "other"; - } - }() ); - meshes.setAttribute( "fieldBoundary", fieldBoundary ); - meshes.setAttribute( "particleBoundary", particleBoundary ); - meshes.setAttribute( "currentSmoothing", [](){ - if( WarpX::use_filter ) return "Binomial"; + for (auto i = 0u; i < fieldBoundary.size() / 2u; ++i) + if (m_fieldPMLdirections.at(i)) + fieldBoundary.at(i) = "open"; + + for (auto i = 0u; i < fieldBoundary.size() / 2u; ++i) + if (period.isPeriodic(i)) { + fieldBoundary.at(2u * i) = "periodic"; + fieldBoundary.at(2u * i + 1u) = "periodic"; + particleBoundary.at(2u * i) = "periodic"; + particleBoundary.at(2u * i + 1u) = "periodic"; + } + + meshes.setAttribute("fieldSolver", []() { + switch (WarpX::maxwell_solver_id) { + case MaxwellSolverAlgo::Yee : + return "Yee"; + case MaxwellSolverAlgo::CKC : + return "CK"; + case MaxwellSolverAlgo::PSATD : + return "PSATD"; + default: + return "other"; + } + }()); + meshes.setAttribute("fieldBoundary", fieldBoundary); + meshes.setAttribute("particleBoundary", particleBoundary); + meshes.setAttribute("currentSmoothing", []() { + if (WarpX::use_filter) return "Binomial"; else return "none"; - }() ); - if( WarpX::use_filter ) - meshes.setAttribute( "currentSmoothingParameters", [](){ - std::stringstream ss; - ss << "period=1;compensator=false"; - ss << ";numPasses_x=" << WarpX::filter_npass_each_dir[0]; + }()); + if (WarpX::use_filter) + meshes.setAttribute("currentSmoothingParameters", []() { + std::stringstream ss; + ss << "period=1;compensator=false"; + ss << ";numPasses_x=" << WarpX::filter_npass_each_dir[0]; #if (AMREX_SPACEDIM == 3) - ss << ";numPasses_y=" << WarpX::filter_npass_each_dir[1]; - ss << ";numPasses_z=" << WarpX::filter_npass_each_dir[2]; + ss << ";numPasses_y=" << WarpX::filter_npass_each_dir[1]; + ss << ";numPasses_z=" << WarpX::filter_npass_each_dir[2]; #else - ss << ";numPasses_z=" << WarpX::filter_npass_each_dir[1]; + ss << ";numPasses_z=" << WarpX::filter_npass_each_dir[1]; #endif - std::string currentSmoothingParameters = ss.str(); - return currentSmoothingParameters; - }() ); - meshes.setAttribute("chargeCorrection", [](){ - if( WarpX::do_dive_cleaning ) return "hyperbolic"; // TODO or "spectral" or something? double-check - else return "none"; - }() ); - if( WarpX::do_dive_cleaning ) - meshes.setAttribute("chargeCorrectionParameters", "period=1"); + std::string currentSmoothingParameters = ss.str(); + return currentSmoothingParameters; + }()); + meshes.setAttribute("chargeCorrection", []() { + if (WarpX::do_dive_cleaning) return "hyperbolic"; // TODO or "spectral" or something? double-check + else return "none"; + }()); + if (WarpX::do_dive_cleaning) + meshes.setAttribute("chargeCorrectionParameters", "period=1"); + } // Loop through the different components, i.e. different fields stored in mf for (int icomp=0; icomp<ncomp; icomp++){ @@ -871,20 +894,24 @@ WarpXOpenPMDPlot::WriteOpenPMDFields( //const std::string& filename, // we invert (only) meta-data arrays to assign labels and offsets in the // order: slowest to fastest varying index when accessing the mesh // contiguously (as 1D flattened logical memory) - mesh.setDataOrder( openPMD::Mesh::DataOrder::C ); - mesh.setAxisLabels( axis_labels ); - mesh.setGridSpacing( grid_spacing ); - mesh.setGridGlobalOffset( global_offset ); - mesh.setAttribute( "fieldSmoothing", "none" ); - detail::setOpenPMDUnit( mesh, field_name ); + if( first_write_to_iteration ) { + mesh.setDataOrder(openPMD::Mesh::DataOrder::C); + mesh.setAxisLabels(axis_labels); + mesh.setGridSpacing(grid_spacing); + mesh.setGridGlobalOffset(global_offset); + mesh.setAttribute("fieldSmoothing", "none"); + detail::setOpenPMDUnit(mesh, field_name); + } // Create a new mesh record component, and store the associated metadata auto mesh_comp = mesh[comp_name]; - mesh_comp.resetDataset( dataset ); + if( first_write_to_iteration ) { + mesh_comp.resetDataset(dataset); - auto relative_cell_pos = utils::getRelativeCellPosition( mf ); // AMReX Fortran index order - std::reverse( relative_cell_pos.begin(), relative_cell_pos.end() ); // now in C order - mesh_comp.setPosition( relative_cell_pos ); + auto relative_cell_pos = utils::getRelativeCellPosition(mf); // AMReX Fortran index order + std::reverse(relative_cell_pos.begin(), relative_cell_pos.end()); // now in C order + mesh_comp.setPosition(relative_cell_pos); + } // Loop through the multifab, and store each box as a chunk, // in the openPMD file. |