LCOV - code coverage report
Current view: top level - src/Integrator - Integrator.cpp (source / functions) Coverage Total Hit
Test: coverage_merged.info Lines: 70.8 % 653 462
Test Date: 2025-08-05 17:56:56 Functions: 70.4 % 27 19

            Line data    Source code
       1              : ///
       2              : /// \file Integrator.cpp
       3              : /// \brief Compute the volume integral of two multiplied Fourier series
       4              : ///
       5              : 
       6              : #include "Integrator.H"
       7              : #include "IO/FileNameParse.H"
       8              : #include "IO/ParmParse.H"
       9              : #include "Util/Util.H"
      10              : #include "Unit/Unit.H"
      11              : #include <numeric>
      12              : 
      13              : 
      14              : 
      15              : namespace Integrator
      16              : {
      17              : 
      18          259 : Integrator::Integrator() : amrex::AmrCore()
      19              : {
      20              :     BL_PROFILE("Integrator::Integrator()");
      21              :     {
      22              :         // These are basic parameters that are, in 
      23              :         // general, common to all Alamo simulations.
      24           37 :         IO::ParmParse pp;
      25              :         // Number of iterations before ending (default is maximum possible int)
      26           74 :         pp_query_default("max_step", max_step, 2147483647);  
      27              :         // Simulation time before ending
      28           74 :         pp_query_required("stop_time", stop_time, Unit::Time());    
      29              :         // Nominal timestep on amrlev = 0
      30           74 :         pp_query_required("timestep", timestep, Unit::Time());      
      31           37 :         pp_query("restart", restart_file_cell);       // Name of restart file to READ from
      32           37 :         pp_query("restart_cell", restart_file_cell);  // Name of cell-fab restart file to read from
      33           37 :         pp_query("restart_node", restart_file_node);  // Name of node-fab restart file to read from
      34           37 :     }
      35              : 
      36              :     {
      37              :         // This allows the user to ignore certain arguments that
      38              :         // would otherwise cause problems.
      39              :         // Most generally this is used in the event of a "above inputs
      40              :         // specified but not used" error.
      41              :         // The primary purpose of this was to fix those errors that arise
      42              :         // in regression tests.
      43           37 :         IO::ParmParse pp;
      44           37 :         std::vector<std::string> ignore;
      45           82 :         if (pp.contains("ignore")) Util::Message(INFO, "Ignore directive detected");
      46           37 :         pp_queryarr("ignore", ignore); // Space-separated list of entries to ignore
      47           41 :         for (unsigned int i = 0; i < ignore.size(); i++)
      48              :         {
      49           16 :             Util::Message(INFO, "ignoring ", ignore[i]);
      50            4 :             pp.remove(ignore[i].c_str());
      51              :         }
      52           37 :     }
      53              :     {
      54              :         // These are parameters that are specific to
      55              :         // the AMR/regridding part of the code.
      56           37 :         IO::ParmParse pp("amr");
      57           74 :         pp_query_default("regrid_int", regrid_int, 2);           // Regridding interval in step numbers
      58           74 :         pp_query_default("base_regrid_int", base_regrid_int, 0); // Regridding interval based on coarse level only
      59           74 :         pp_query_default("plot_int", plot_int, -1);               // Interval (in timesteps) between plotfiles (Default negative value will cause the plot interval to be ignored.)
      60          148 :         pp.query_default("plot_dt", plot_dt, "-1.0", Unit::Time());                 // Interval (in simulation time) between plotfiles (Default negative value will cause the plot dt to be ignored.)
      61              : 
      62              : 
      63              :         // Output file: see IO::FileNameParse for wildcards and variable substitution
      64           74 :         pp_query_default("plot_file", plot_file, "output");
      65              : 
      66           74 :         pp_query_default("cell.all", cell.all, false);                // Turn on to write all output in cell fabs (default: off)
      67           74 :         pp_query_default("cell.any", cell.any, true);                // Turn off to prevent any cell based output (default: on)
      68           74 :         pp_query_default("node.all", node.all, false);                // Turn on to write all output in node fabs (default: off)
      69           74 :         pp_query_default("node.any", node.any, true);                // Turn off to prevent any node based output (default: on)
      70              : 
      71           74 :         pp_query_default("abort_on_nan",abort_on_nan, true); // Abort if a plotfile contains nan or inf.
      72              : 
      73          259 :         Util::Assert(INFO, TEST(!(!cell.any && cell.all)));
      74          259 :         Util::Assert(INFO, TEST(!(!node.any && node.all)));
      75              : 
      76           74 :         pp_query_default("max_plot_level", max_plot_level, -1);    // Specify a maximum level of refinement for output files (NO REFINEMENT)
      77              : 
      78           37 :         IO::FileNameParse(plot_file);
      79              : 
      80           37 :         nsubsteps.resize(maxLevel() + 1, 1);
      81           37 :         int cnt = pp.countval("nsubsteps");
      82           37 :         if (cnt != 0)
      83            0 :             if (cnt == maxLevel()) {
      84            0 :                 pp_queryarr("nsubsteps", nsubsteps); // Number of substeps to take on each level (default: 2)
      85            0 :                 nsubsteps.insert(nsubsteps.begin(), 1);
      86            0 :                 nsubsteps.pop_back();
      87              :             }
      88            0 :             else if (cnt == 1)
      89              :             {
      90              :                 int nsubsteps_all;
      91            0 :                 pp_query_required("nsubsteps", nsubsteps_all);// Number of substeps to take on each level (set all levels to this value)
      92            0 :                 for (int lev = 1; lev <= maxLevel(); ++lev) nsubsteps[lev] = nsubsteps_all;
      93              :             }
      94              :             else
      95            0 :                 Util::Abort(INFO, "number of nsubsteps input must equal either 1 or amr.max_level");
      96              :         else
      97          103 :             for (int lev = 1; lev <= maxLevel(); ++lev)
      98           66 :                 nsubsteps[lev] = MaxRefRatio(lev - 1);
      99           37 :     }
     100              :     {
     101           37 :         IO::ParmParse pp("dynamictimestep");
     102              :         // activate dynamic CFL-based timestep
     103           37 :         pp_query("on",dynamictimestep.on);
     104           37 :         if (dynamictimestep.on)
     105              :         {
     106              :             // how much information to print
     107            0 :             pp_query_validate("verbose",dynamictimestep.verbose,{0,1});
     108              :             // number of previous timesteps for rolling average
     109            0 :             pp_query_default("nprevious",dynamictimestep.nprevious,5);
     110              :             // dynamic teimstep CFL condition
     111            0 :             pp_query_default("cfl",dynamictimestep.cfl,1.0);
     112              :             // minimum timestep size allowed shen stepping dynamically
     113            0 :             pp_query_default("min",dynamictimestep.min,timestep);
     114              :             // maximum timestep size allowed shen stepping dynamically
     115            0 :             pp_query_default("max",dynamictimestep.max,timestep);
     116              : 
     117            0 :             Util::AssertException(INFO,TEST(dynamictimestep.max >= dynamictimestep.min));
     118              :         }
     119           37 :     }
     120              :     {
     121              :         // Information on how to generate thermodynamic
     122              :         // data (to show up in thermo.dat)
     123           37 :         IO::ParmParse pp("amr.thermo");
     124           37 :         thermo.interval = 1;                                       // Default: integrate every time.
     125           74 :         pp_query_default("int", thermo.interval, 1);               // Integration interval (1)
     126           74 :         pp_query_default("plot_int", thermo.plot_int, -1);         // Interval (in timesteps) between writing (Default negative value will cause the plot interval to be ignored.)
     127          148 :         pp_query_default("plot_dt", thermo.plot_dt, "-1.0", Unit::Time());         // Interval (in simulation time) between writing (Default negative value will cause the plot dt to be ignored.)
     128           37 :     }
     129              : 
     130              :     {
     131              :         // Instead of using AMR, prescribe an explicit, user-defined
     132              :         // set of grids to work on. This is pretty much always used
     133              :         // for testing purposes only.
     134           37 :         IO::ParmParse pp("explicitmesh");
     135           74 :         pp_query_default("on", explicitmesh.on, 0); // Use explicit mesh instead of AMR
     136           37 :         if (explicitmesh.on)
     137              :         {
     138           13 :             for (int ilev = 0; ilev < maxLevel(); ++ilev)
     139              :             {
     140            6 :                 std::string strlo = "lo" + std::to_string(ilev + 1);
     141            6 :                 std::string strhi = "hi" + std::to_string(ilev + 1);
     142              : 
     143           54 :                 Util::Assert(INFO, TEST(pp.contains(strlo.c_str())));
     144           48 :                 Util::Assert(INFO, TEST(pp.contains(strhi.c_str())));
     145              : 
     146            6 :                 amrex::Vector<int> lodata, hidata;
     147           12 :                 pp_queryarr(strlo.c_str(), lodata);
     148            6 :                 pp_queryarr(strhi.c_str(), hidata);
     149            6 :                 amrex::IntVect lo(AMREX_D_DECL(lodata[0], lodata[1], lodata[2]));
     150            6 :                 amrex::IntVect hi(AMREX_D_DECL(hidata[0], hidata[1], hidata[2]));
     151              : 
     152            6 :                 explicitmesh.box.push_back(amrex::Box(lo, hi));
     153            6 :             }
     154              :         }
     155           37 :     }
     156              : 
     157           37 :     int nlevs_max = maxLevel() + 1;
     158              : 
     159           37 :     istep.resize(nlevs_max, 0);
     160              : 
     161           37 :     t_new.resize(nlevs_max, 0.0);
     162           37 :     t_old.resize(nlevs_max, -1.e100);
     163           37 :     SetTimestep(timestep);
     164              : 
     165           37 :     plot_file = Util::GetFileName();
     166           37 :     IO::WriteMetaData(plot_file, IO::Status::Running, 0);
     167           37 : }
     168              : 
     169              : // Destructor
     170           37 : Integrator::~Integrator()
     171              : {
     172           37 :     if (Util::finalized)
     173              :     {
     174            0 :         std::cout << "!! ERROR !! Integrator destructor called after alamo has been finalized." << std::endl;
     175            0 :         std::cout << "            Behavior occurring after this is undefined." << std::endl;
     176            0 :         std::abort();
     177              :     }
     178              : 
     179              :     // Close out the metadata file and mark completed.
     180           37 :     IO::WriteMetaData(plot_file, IO::Status::Complete);
     181              : 
     182              :     // De-initialize all of the base fields and clear the arrays.
     183          135 :     for (unsigned int i = 0; i < m_basefields.size(); i++) delete m_basefields[i];
     184           37 :     for (unsigned int i = 0; i < m_basefields_cell.size(); i++) delete m_basefields_cell[i];
     185           37 :     m_basefields.clear();
     186           37 :     m_basefields_cell.clear();
     187           37 : }
     188              : 
     189           77 : void Integrator::SetTimestep(Set::Scalar _timestep)
     190              : {
     191              :     BL_PROFILE("Integrator::SetTimestep");
     192           77 :     int nlevs_max = maxLevel() + 1;
     193           77 :     timestep = _timestep;
     194           77 :     dt.resize(nlevs_max, 1.e100);
     195           77 :     dt[0] = timestep;
     196          223 :     for (int i = 1; i < nlevs_max; i++)
     197          146 :         dt[i] = dt[i - 1] / (amrex::Real)nsubsteps[i];
     198           77 : }
     199            0 : void Integrator::SetPlotInt(int a_plot_int)
     200              : {
     201              :     BL_PROFILE("Integrator::SetPlotInt");
     202            0 :     plot_int = a_plot_int;
     203            0 : }
     204              : 
     205              : /// \fn    Integrator::MakeNewLevelFromCoarse
     206              : /// \brief Wrapper to call FillCoarsePatch
     207              : /// \note **THIS OVERRIDES A PURE VIRTUAL METHOD - DO NOT CHANGE**
     208              : ///
     209              : void
     210            5 : Integrator::MakeNewLevelFromCoarse(int lev, amrex::Real time, const amrex::BoxArray& cgrids, const amrex::DistributionMapping& dm)
     211              : {
     212              :     BL_PROFILE("Integrator::MakeNewLevelFromCoarse");
     213              : 
     214            9 :     for (int n = 0; n < cell.number_of_fabs; n++)
     215              :     {
     216            4 :         const int ncomp = (*cell.fab_array[n])[lev - 1]->nComp();
     217            4 :         const int nghost = (*cell.fab_array[n])[lev - 1]->nGrow();
     218              : 
     219            4 :         (*cell.fab_array[n])[lev].reset(new amrex::MultiFab(cgrids, dm, ncomp, nghost));
     220              : 
     221            4 :         (*cell.fab_array[n])[lev]->setVal(0.0);
     222              : 
     223            4 :         FillCoarsePatch(lev, time, *cell.fab_array[n], *cell.physbc_array[n], 0, ncomp);
     224              :     }
     225              : 
     226            5 :     amrex::BoxArray ngrids = cgrids;
     227            5 :     ngrids.convert(amrex::IntVect::TheNodeVector());
     228              : 
     229            8 :     for (int n = 0; n < node.number_of_fabs; n++)
     230              :     {
     231            3 :         const int ncomp = (*node.fab_array[n])[lev - 1]->nComp();
     232            3 :         const int nghost = (*node.fab_array[n])[lev - 1]->nGrow();
     233              : 
     234            3 :         (*node.fab_array[n])[lev].reset(new amrex::MultiFab(ngrids, dm, ncomp, nghost));
     235            3 :         (*node.fab_array[n])[lev]->setVal(0.0);
     236              : 
     237            3 :         FillCoarsePatch(lev, time, *node.fab_array[n], *node.physbc_array[n], 0, ncomp);
     238              :     }
     239              : 
     240           32 :     for (unsigned int n = 0; n < m_basefields.size(); n++)
     241              :     {
     242           27 :         m_basefields[n]->MakeNewLevelFromCoarse(lev, time, cgrids, dm);
     243              :     }
     244            5 :     for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
     245              :     {
     246            0 :         m_basefields_cell[n]->MakeNewLevelFromCoarse(lev, time, cgrids, dm);
     247              :     }
     248              : 
     249            5 :     Regrid(lev, time);
     250            5 : }
     251              : 
     252              : 
     253              : ///
     254              : /// RESETS ALL MULTIFABS AT A GIVEN LEVEL
     255              : ///
     256              : /// (OVERRIDES PURE VIRTUAL METHOD - DO NOT CHANGE)
     257              : ///
     258              : void
     259          796 : Integrator::RemakeLevel(int lev,                             ///<[in] AMR Level
     260              :                         amrex::Real time,                    ///<[in] Simulation time
     261              :                         const amrex::BoxArray &cgrids,       ///<[in] Coarse grids
     262              :                         const amrex::DistributionMapping &dm ///[in] Distribution mapping
     263              :     )
     264              : {
     265              :     BL_PROFILE("Integrator::RemakeLevel");
     266         2391 :     for (int n = 0; n < cell.number_of_fabs; n++)
     267              :     {
     268         1595 :         const int ncomp = (*cell.fab_array[n])[lev]->nComp();
     269         1595 :         const int nghost = (*cell.fab_array[n])[lev]->nGrow();
     270              : 
     271         1595 :         amrex::MultiFab new_state(cgrids, dm, ncomp, nghost);
     272              : 
     273         1595 :         new_state.setVal(0.0);
     274         1595 :         FillPatch(lev, time, *cell.fab_array[n], new_state, *cell.physbc_array[n], 0);
     275         1595 :         std::swap(new_state, *(*cell.fab_array[n])[lev]);
     276         1595 :     }
     277              : 
     278          796 :     amrex::BoxArray ngrids = cgrids;
     279          796 :     ngrids.convert(amrex::IntVect::TheNodeVector());
     280              : 
     281          799 :     for (int n = 0; n < node.number_of_fabs; n++)
     282              :     {
     283            3 :         const int ncomp = (*node.fab_array[n])[lev]->nComp();
     284            3 :         const int nghost = (*node.fab_array[n])[lev]->nGrow();
     285              : 
     286            3 :         amrex::MultiFab new_state(ngrids, dm, ncomp, nghost);
     287              : 
     288            3 :         new_state.setVal(0.0);
     289            3 :         FillPatch(lev, time, *node.fab_array[n], new_state, *node.physbc_array[n], 0);
     290            3 :         std::swap(new_state, *(*node.fab_array[n])[lev]);
     291            3 :     }
     292              : 
     293          796 :     for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
     294              :     {
     295            0 :         m_basefields_cell[n]->RemakeLevel(lev, time, cgrids, dm);
     296              :     }
     297          801 :     for (unsigned int n = 0; n < m_basefields.size(); n++)
     298              :     {
     299            5 :         m_basefields[n]->RemakeLevel(lev, time, cgrids, dm);
     300              :     }
     301          796 :     Regrid(lev, time);
     302          796 : }
     303              : 
     304              : //
     305              : // DELETE EVERYTHING
     306              : //
     307              : // (OVERRIDES PURE VIRTUAL METHOD - DO NOT CHANGE)
     308              : //
     309              : void
     310            0 : Integrator::ClearLevel(int lev)
     311              : {
     312              :     BL_PROFILE("Integrator::ClearLevel");
     313            0 :     for (int n = 0; n < cell.number_of_fabs; n++)
     314              :     {
     315            0 :         (*cell.fab_array[n])[lev].reset(nullptr);
     316              :     }
     317            0 :     for (int n = 0; n < node.number_of_fabs; n++)
     318              :     {
     319            0 :         (*node.fab_array[n])[lev].reset(nullptr);
     320              :     }
     321            0 : }
     322              : 
     323              : //
     324              : //
     325              : //
     326              : 
     327              : 
     328              : 
     329              : 
     330              : 
     331              : void
     332          152 : Integrator::RegisterNewFab(Set::Field<Set::Scalar>& new_fab, BC::BC<Set::Scalar>* new_bc, int ncomp, int nghost, std::string name, bool writeout, bool evolving, std::vector<std::string> suffix)
     333              : {
     334              :     //Util::Warning(INFO, "RegisterNewFab is depricated. Please replace with AddField");
     335          152 :     AddField<Set::Scalar, Set::Hypercube::Cell>(new_fab, new_bc, ncomp, nghost, name, writeout, evolving, suffix);
     336          152 : }
     337              : void
     338            0 : Integrator::RegisterNewFab(Set::Field<Set::Scalar>& new_fab, int ncomp, std::string name, bool writeout, bool evolving, std::vector<std::string> suffix)
     339              : {
     340              :     //Util::Warning(INFO, "RegisterNewFab is depricated. Please replace with AddField");
     341            0 :     AddField<Set::Scalar, Set::Hypercube::Cell>(new_fab, nullptr, ncomp, 0, name, writeout, evolving, suffix);
     342            0 : }
     343              : void
     344            0 : Integrator::RegisterNodalFab(Set::Field<Set::Scalar>& new_fab, BC::BC<Set::Scalar>* new_bc, int ncomp, int nghost, std::string name, bool writeout, bool evolving, std::vector<std::string> suffix)
     345              : {
     346              :     //Util::Warning(INFO, "RegisterNodalFab is depricated. Please replace with AddField");
     347            0 :     AddField<Set::Scalar, Set::Hypercube::Node>(new_fab, new_bc, ncomp, nghost, name, writeout, evolving,suffix);
     348            0 : }
     349              : void
     350           21 : Integrator::RegisterNodalFab(Set::Field<Set::Scalar>& new_fab, int ncomp, int nghost, std::string name, bool writeout, bool evolving, std::vector<std::string> suffix)
     351              : {
     352              :     //Util::Warning(INFO, "RegisterNodalFab is depricated. Please replace with AddField");
     353           21 :     AddField<Set::Scalar, Set::Hypercube::Node>(new_fab, nullptr, ncomp, nghost, name, writeout, evolving,suffix);
     354           21 : }
     355              : 
     356              : 
     357              : 
     358              : 
     359              : void // CUSTOM METHOD - CHANGEABLE
     360          174 : Integrator::RegisterIntegratedVariable(Set::Scalar *integrated_variable, std::string name, bool extensive)
     361              : {
     362              :     BL_PROFILE("Integrator::RegisterIntegratedVariable");
     363          174 :     thermo.vars.push_back(integrated_variable);
     364          174 :     thermo.names.push_back(name);
     365          174 :     thermo.extensives.push_back(extensive);
     366          174 :     thermo.number++;
     367          174 : }
     368              : 
     369              : long // CUSTOM METHOD - CHANGEABLE
     370            0 : Integrator::CountCells(int lev)
     371              : {
     372              :     BL_PROFILE("Integrator::CountCells");
     373            0 :     const int N = grids[lev].size();
     374              : 
     375            0 :     long cnt = 0;
     376              : 
     377            0 :     for (int i = 0; i < N; ++i)
     378              :     {
     379            0 :         cnt += grids[lev][i].numPts();
     380              :     }
     381              : 
     382            0 :     return cnt;
     383              : }
     384              : 
     385              : void  // CUSTOM METHOD - CHANGEABLE
     386       270290 : Integrator::FillPatch(int lev, amrex::Real time,
     387              :     amrex::Vector<std::unique_ptr<amrex::MultiFab>>& source_mf,
     388              :     amrex::MultiFab& destination_mf,
     389              :     BC::BC<Set::Scalar>& physbc, int icomp)
     390              : {
     391              :     BL_PROFILE("Integrator::FillPatch");
     392       270290 :     if (lev == 0)
     393              :     {
     394              : 
     395        46460 :         amrex::Vector<amrex::MultiFab*> smf;
     396        46460 :         smf.push_back(source_mf[lev].get());
     397        46460 :         amrex::Vector<amrex::Real> stime;
     398        46460 :         stime.push_back(time);
     399              : 
     400        46460 :         physbc.define(geom[lev]);
     401        46460 :         amrex::FillPatchSingleLevel(destination_mf,     // Multifab
     402              :             time,                         // time
     403              :             smf,                // Vector<MultiFab*> &smf (CONST)
     404              :             stime,          // Vector<Real> &stime    (CONST)
     405              :             0,              // scomp - Source component 
     406              :             icomp,          // dcomp - Destination component
     407              :             destination_mf.nComp(), // ncomp - Number of components
     408        46460 :             geom[lev],          // Geometry (CONST)
     409              :             physbc,
     410              :             0);         // BC
     411        46460 :     }
     412              :     else
     413              :     {
     414       223830 :         amrex::Vector<amrex::MultiFab*> cmf, fmf;
     415       223830 :         cmf.push_back(source_mf[lev - 1].get());
     416       223830 :         fmf.push_back(source_mf[lev].get());
     417       223830 :         amrex::Vector<amrex::Real> ctime, ftime;
     418       223830 :         ctime.push_back(time);
     419       223830 :         ftime.push_back(time);
     420              : 
     421       223830 :         physbc.define(geom[lev]);
     422              : 
     423              :         amrex::Interpolater* mapper;
     424              : 
     425       447660 :         if (destination_mf.boxArray().ixType() == amrex::IndexType::TheNodeType())
     426         7679 :             mapper = &amrex::node_bilinear_interp;
     427              :         else
     428       216151 :             mapper = &amrex::cell_cons_interp;
     429              : 
     430       223830 :         amrex::Vector<amrex::BCRec> bcs(destination_mf.nComp(), physbc.GetBCRec()); // todo
     431       223830 :         amrex::FillPatchTwoLevels(destination_mf, time, cmf, ctime, fmf, ftime,
     432       223830 :             0, icomp, destination_mf.nComp(), geom[lev - 1], geom[lev],
     433              :             physbc, 0,
     434              :             physbc, 0,
     435       223830 :             refRatio(lev - 1),
     436              :             mapper, bcs, 0);
     437       223830 :     }
     438       270290 : }
     439              : 
     440              : /// \fn    Integrator::FillCoarsePatch
     441              : /// \brief Fill a fab at current level with the data from one level up
     442              : ///
     443              : /// \note  This is a custom method and is changeable
     444              : void
     445            7 : Integrator::FillCoarsePatch(int lev, ///<[in] AMR level
     446              :     amrex::Real time, ///<[in] Simulatinon time
     447              :     Set::Field<Set::Scalar>& mf, ///<[in] Fab to fill
     448              :     BC::BC<Set::Scalar>& physbc, ///<[in] BC object applying to Fab
     449              :     int icomp, ///<[in] start component
     450              :     int ncomp) ///<[in] end component (i.e. applies to components `icomp`...`ncomp`)
     451              : {
     452              :     BL_PROFILE("Integrator::FillCoarsePatch");
     453              :     AMREX_ASSERT(lev > 0);
     454            7 :     amrex::Vector<amrex::MultiFab*> cmf;
     455            7 :     cmf.push_back(mf[lev - 1].get());
     456            7 :     amrex::Vector<amrex::Real> ctime;
     457            7 :     ctime.push_back(time);
     458              : 
     459            7 :     physbc.define(geom[lev]);
     460              : 
     461              :     amrex::Interpolater* mapper;
     462           14 :     if (mf[lev]->boxArray().ixType() == amrex::IndexType::TheNodeType())
     463            3 :         mapper = &amrex::node_bilinear_interp;
     464              :     else
     465            4 :         mapper = &amrex::cell_cons_interp;
     466              : 
     467            7 :     amrex::Vector<amrex::BCRec> bcs(ncomp, physbc.GetBCRec());
     468            7 :     amrex::InterpFromCoarseLevel(*mf[lev], time, *cmf[0], 0, icomp, ncomp, geom[lev - 1], geom[lev],
     469              :         physbc, 0,
     470              :         physbc, 0,
     471            7 :         refRatio(lev - 1),
     472              :         mapper, bcs, 0);
     473            7 : }
     474              : 
     475              : void
     476        31290 : Integrator::ErrorEst(int lev, amrex::TagBoxArray& tags, amrex::Real time, int ngrow)
     477              : {
     478              :     BL_PROFILE("Integrator::ErrorEst");
     479        31290 :     TagCellsForRefinement(lev, tags, time, ngrow);
     480        31290 : }
     481              : 
     482              : 
     483              : void
     484           37 : Integrator::InitData()
     485              : {
     486              :     BL_PROFILE("Integrator::InitData");
     487              : 
     488           37 :     if (restart_file_cell == "" && restart_file_node == "")
     489              :     {
     490           37 :         const amrex::Real time = 0.0;
     491           37 :         InitFromScratch(time);
     492              : 
     493           98 :         for (int lev = finest_level - 1; lev >= 0; --lev)
     494              :         {
     495           61 :             if (lev < max_level) regrid(lev, 0.0);
     496          192 :             for (int n = 0; n < cell.number_of_fabs; n++)
     497          262 :                 amrex::average_down(*(*cell.fab_array[n])[lev + 1], *(*cell.fab_array[n])[lev],
     498          131 :                     geom[lev + 1], geom[lev],
     499          262 :                     0, (*cell.fab_array[n])[lev]->nComp(), refRatio(lev));
     500              :         }
     501           37 :         SetFinestLevel(finest_level);
     502              :     }
     503           37 :     if (restart_file_cell != "")
     504              :     {
     505            0 :         Restart(restart_file_cell, false);
     506              :     }
     507           37 :     if (restart_file_node != "")
     508              :     {
     509            0 :         Restart(restart_file_node, true);
     510              :     }
     511              : 
     512           37 :     if (plot_int > 0 || plot_dt > 0.0) {
     513           37 :         WritePlotFile();
     514              :     }
     515           37 : }
     516              : 
     517              : void
     518            0 : Integrator::Restart(const std::string dirname, bool a_nodal)
     519              : {
     520              :     BL_PROFILE("Integrator::Restart");
     521              : 
     522            0 :     if (a_nodal && node.fab_array.size() == 0)
     523              :     {
     524            0 :         Util::Message(INFO, "Nothing here for nodal fabs");
     525            0 :         return;
     526              :     }
     527            0 :     if (!a_nodal && cell.fab_array.size() == 0)
     528              :     {
     529            0 :         Util::Message(INFO, "Nothing here for cell-based fabs");
     530            0 :         return;
     531              :     }
     532              : 
     533            0 :     std::string filename = dirname + "/Header";
     534            0 :     std::string chkptfilename = dirname + "/Checkpoint";
     535            0 :     amrex::VisMF::IO_Buffer io_buffer(amrex::VisMF::GetIOBufferSize());
     536            0 :     amrex::Vector<char> fileCharPtr, chkptfileCharPtr;
     537            0 :     amrex::ParallelDescriptor::ReadAndBcastFile(filename, fileCharPtr);
     538            0 :     amrex::ParallelDescriptor::ReadAndBcastFile(chkptfilename, chkptfileCharPtr);
     539            0 :     std::string fileCharPtrString(fileCharPtr.dataPtr());
     540            0 :     std::string chkptfileCharPtrString(chkptfileCharPtr.dataPtr());
     541            0 :     std::istringstream is(fileCharPtrString, std::istringstream::in);
     542            0 :     std::istringstream chkpt_is(chkptfileCharPtrString, std::istringstream::in);
     543              : 
     544            0 :     std::string line, word;
     545              : 
     546              :     // Get version
     547            0 :     std::getline(is, line);
     548            0 :     Util::Message(INFO, "Version: ", line);
     549              : 
     550              :     // Get number of fabs
     551              :     int tmp_numfabs;
     552            0 :     std::getline(is, line); tmp_numfabs = std::stoi(line);
     553            0 :     Util::Message(INFO, "number of fabs:", tmp_numfabs);
     554            0 :     std::vector<std::string> tmp_name_array;
     555              : 
     556            0 :     for (int i = 0; i < tmp_numfabs; i++)
     557              :     {
     558            0 :         std::getline(is, line);
     559            0 :         tmp_name_array.push_back(line);
     560              :     }
     561              : 
     562              :     // Dimension?
     563            0 :     std::getline(is, line);
     564            0 :     Util::Warning(INFO, "Dimension: " + line);
     565              : 
     566              :     // Current time
     567            0 :     Set::Scalar tmp_time = 0.0;
     568            0 :     std::getline(is, line); tmp_time = std::stof(line); Util::Message(INFO, "Current time: ", tmp_time);
     569            0 :     for (int i = 0; i < max_level + 1; i++)
     570              :     {
     571            0 :         t_new[i] = tmp_time; t_old[i] = tmp_time;
     572              :     }
     573              : 
     574              :     // AMR level
     575              :     int tmp_max_level;
     576            0 :     std::getline(is, line); tmp_max_level = std::stoi(line); Util::Message(INFO, "Max AMR level: ", line);
     577            0 :     if (tmp_max_level != max_level)
     578            0 :         Util::Abort(INFO, "The max level specified (", max_level, ") does not match the max level in the restart file (", tmp_max_level, ")");
     579            0 :     finest_level = tmp_max_level;
     580              :     // Geometry ?
     581            0 :     std::getline(is, line); Util::Message(INFO, "Input geometry: ", line);
     582            0 :     std::getline(is, line); Util::Message(INFO, "                ", line);
     583              : 
     584              :     // Mesh refinement ratio?
     585            0 :     std::getline(is, line); Util::Message(INFO, "Mesh refinement ratio: ", line);
     586              : 
     587              :     // Domain
     588            0 :     std::getline(is, line); Util::Warning(INFO, "Domain: ", line);
     589              : 
     590              :     // Domain
     591            0 :     std::getline(is, line);
     592              :     std::vector<std::string> tmp_iters = Util::String::Split(line);
     593            0 :     if (tmp_iters.size() != (unsigned int)(max_level + 1)) Util::Abort(INFO, "Error reading in interation counts: line = ", line);
     594            0 :     for (int lev = 0; lev <= max_level; lev++) { istep[lev] = std::stoi(tmp_iters[lev]); Util::Message(INFO, "Iter on level ", lev, " = ", istep[lev]); }
     595              : 
     596            0 :     amrex::Vector<amrex::MultiFab> tmpdata(tmp_max_level + 1);
     597            0 :     int total_ncomp = 0;
     598              : 
     599            0 :     if (a_nodal) for (unsigned int i = 0; i < node.fab_array.size(); i++) total_ncomp += node.ncomp_array[i];
     600            0 :     else         for (unsigned int i = 0; i < cell.fab_array.size(); i++) total_ncomp += cell.ncomp_array[i];
     601              : 
     602            0 :     int total_nghost = a_nodal ? 0 : cell.nghost_array[0];
     603              : 
     604            0 :     for (int lev = 0; lev <= max_level; lev++)
     605              :     {
     606            0 :         amrex::BoxArray tmp_ba;
     607            0 :         tmp_ba.readFrom(chkpt_is);
     608            0 :         SetBoxArray(lev, tmp_ba);
     609            0 :         amrex::DistributionMapping tmp_dm(tmp_ba, amrex::ParallelDescriptor::NProcs());
     610            0 :         SetDistributionMap(lev, tmp_dm);
     611              : 
     612            0 :         if (a_nodal)
     613              :         {
     614            0 :             amrex::BoxArray ngrids = grids[lev];
     615            0 :             ngrids.convert(amrex::IntVect::TheNodeVector());
     616            0 :             tmpdata[lev].define(ngrids, dmap[lev], total_ncomp, total_nghost);
     617            0 :         }
     618              :         else
     619              :         {
     620            0 :             tmpdata[lev].define(grids[lev], dmap[lev], total_ncomp, total_nghost);
     621              :         }
     622            0 :         amrex::VisMF::Read(tmpdata[lev],
     623            0 :             amrex::MultiFabFileFullPrefix(lev, dirname, "Level_", "Cell"));
     624              : 
     625              : 
     626            0 :         if (a_nodal)
     627            0 :             for (int i = 0; i < node.number_of_fabs; i++)
     628              :             {
     629            0 :                 amrex::BoxArray ngrids = grids[lev];
     630            0 :                 ngrids.convert(amrex::IntVect::TheNodeVector());
     631            0 :                 (*node.fab_array[i])[lev].reset(new amrex::MultiFab(ngrids, dmap[lev], node.ncomp_array[i], node.nghost_array[i]));
     632            0 :                 (*node.fab_array[i])[lev]->setVal(0.);
     633            0 :             }
     634              :         else
     635            0 :             for (int i = 0; i < cell.number_of_fabs; i++)
     636            0 :                 (*cell.fab_array[i])[lev].reset(new amrex::MultiFab(grids[lev], dmap[lev], cell.ncomp_array[i], cell.nghost_array[i]));
     637            0 :         for (int i = 0; i < tmp_numfabs; i++)
     638              :         {
     639            0 :             bool match = false;
     640            0 :             if (a_nodal)
     641              :             {
     642            0 :                 for (int j = 0; j < node.number_of_fabs; j++)
     643              :                 {
     644            0 :                     if (tmp_name_array[i] == node.name_array[i][j])
     645              :                     {
     646            0 :                         match = true;
     647            0 :                         Util::Message(INFO, "Initializing ", node.name_array[i][j], "; nghost=", node.nghost_array[j], " with ", tmp_name_array[i]);
     648            0 :                         amrex::MultiFab::Copy(*((*node.fab_array[j])[lev]).get(), tmpdata[lev], i, 0, 1, total_nghost);
     649              :                     }
     650            0 :                     for (int k = 0; k < node.ncomp_array[j]; k++)
     651              :                     {
     652            0 :                         if (tmp_name_array[i] == node.name_array[j][k])
     653              :                         {
     654            0 :                             match = true;
     655            0 :                             Util::Message(INFO, "Initializing ", node.name_array[j][k], "; ncomp=", node.ncomp_array[j], "; nghost=", node.nghost_array[j], " with ", tmp_name_array[i]);
     656            0 :                             amrex::MultiFab::Copy(*((*node.fab_array[j])[lev]).get(), tmpdata[lev], i, k, 1, total_nghost);
     657              :                         }
     658              :                     }
     659            0 :                     Util::RealFillBoundary(*((*node.fab_array[j])[lev]).get(), geom[lev]);
     660              :                 }
     661              :             }
     662              :             else
     663              :             {
     664            0 :                 for (int j = 0; j < cell.number_of_fabs; j++)
     665            0 :                     for (int k = 0; k < cell.ncomp_array[j]; k++)
     666              :                     {
     667            0 :                         if (tmp_name_array[i] == cell.name_array[j][k])
     668              :                         {
     669            0 :                             match = true;
     670            0 :                             Util::Message(INFO, "Initializing ", cell.name_array[j][k], "; ncomp=", cell.ncomp_array[j], "; nghost=", cell.nghost_array[j], " with ", tmp_name_array[i]);
     671            0 :                             amrex::MultiFab::Copy(*((*cell.fab_array[j])[lev]).get(), tmpdata[lev], i, k, 1, cell.nghost_array[j]);
     672              :                         }
     673              :                     }
     674              :             }
     675            0 :             if (!match) Util::Warning(INFO, "Fab ", tmp_name_array[i], " is in the restart file, but there is no fab with that name here.");
     676              :         }
     677              : 
     678            0 :         for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
     679              :         {
     680            0 :             m_basefields_cell[n]->MakeNewLevelFromScratch(lev, t_new[lev], grids[lev], dmap[lev]);
     681              :         }
     682            0 :         for (unsigned int n = 0; n < m_basefields.size(); n++)
     683              :         {
     684            0 :             m_basefields[n]->MakeNewLevelFromScratch(lev, t_new[lev], grids[lev], dmap[lev]);
     685              :         }
     686            0 :     }
     687              : 
     688            0 :     SetFinestLevel(max_level);
     689            0 : }
     690              : 
     691              : void
     692          139 : Integrator::MakeNewLevelFromScratch(int lev, amrex::Real t, const amrex::BoxArray& cgrids,
     693              :     const amrex::DistributionMapping& dm)
     694              : {
     695              :     BL_PROFILE("Integrator::MakeNewLevelFromScratch");
     696          464 :     for (int n = 0; n < cell.number_of_fabs; n++)
     697              :     {
     698          325 :         (*cell.fab_array[n])[lev].reset(new amrex::MultiFab(cgrids, dm, cell.ncomp_array[n], cell.nghost_array[n]));
     699          325 :         (*cell.fab_array[n])[lev]->setVal(0.0);
     700              :     }
     701              : 
     702          139 :     amrex::BoxArray ngrids = cgrids;
     703          139 :     ngrids.convert(amrex::IntVect::TheNodeVector());
     704          226 :     for (int n = 0; n < node.number_of_fabs; n++)
     705              :     {
     706           87 :         (*node.fab_array[n])[lev].reset(new amrex::MultiFab(ngrids, dm, node.ncomp_array[n], node.nghost_array[n]));
     707           87 :         (*node.fab_array[n])[lev]->setVal(0.0);
     708              :     }
     709          139 :     for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
     710              :     {
     711            0 :         m_basefields_cell[n]->MakeNewLevelFromScratch(lev, t, cgrids, dm);
     712              :     }
     713          534 :     for (unsigned int n = 0; n < m_basefields.size(); n++)
     714              :     {
     715          395 :         m_basefields[n]->MakeNewLevelFromScratch(lev, t, cgrids, dm);
     716              :     }
     717              : 
     718          139 :     t_new[lev] = t;
     719          139 :     t_old[lev] = t - dt[lev];
     720              : 
     721          139 :     Initialize(lev);
     722              : 
     723          464 :     for (int n = 0; n < cell.number_of_fabs; n++)
     724              :     {
     725          325 :         cell.physbc_array[n]->define(geom[lev]);
     726          325 :         cell.physbc_array[n]->FillBoundary(*(*cell.fab_array[n])[lev], 0, 0, t, 0);
     727              :     }
     728              : 
     729              :     //for (int n = 0 ; n < node.number_of_fabs; n++)
     730              :     //{
     731              :     //    bcnothing->define(geom[lev]);
     732              :     //    for (amrex::MFIter mfi(*(*node.fab_array[n])[lev],true); mfi.isValid(); ++mfi)
     733              :     //    {
     734              :     //        amrex::BaseFab<Set::Scalar> &patch = (*(*node.fab_array[n])[lev])[mfi];
     735              :     //        const amrex::Box& box = mfi.tilebox();
     736              :     //        bcnothing->FillBoundary(patch,box,0,0,0,t);
     737              :     //    }
     738              :     //}
     739              : 
     740          139 :     for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
     741              :     {
     742            0 :         m_basefields_cell[n]->FillBoundary(lev, t);
     743              :     }
     744          534 :     for (unsigned int n = 0; n < m_basefields.size(); n++)
     745              :     {
     746          395 :         m_basefields[n]->FillBoundary(lev, t);
     747              :     }
     748          139 : }
     749              : 
     750              : std::vector<std::string>
     751          250 : Integrator::PlotFileName(int lev, std::string prefix) const
     752              : {
     753              :     BL_PROFILE("Integrator::PlotFileName");
     754          250 :     std::vector<std::string> name;
     755          250 :     name.push_back(plot_file + "/" + prefix + "/");
     756          250 :     name.push_back(amrex::Concatenate("", lev, 5));
     757          250 :     return name;
     758            0 : }
     759              : 
     760              : void
     761          250 : Integrator::WritePlotFile(bool initial) const
     762              : {
     763          250 :     WritePlotFile(t_new[0], istep, initial, "");
     764          250 : }
     765              : void
     766            0 : Integrator::WritePlotFile(std::string prefix, Set::Scalar time, int step) const
     767              : {
     768            0 :     amrex::Vector<int> istep(max_level + 1, step);
     769            0 :     WritePlotFile(time, istep, false, prefix);
     770            0 : }
     771              : 
     772              : void
     773          250 : Integrator::WritePlotFile(Set::Scalar time, amrex::Vector<int> iter, bool initial, std::string prefix) const
     774              : {
     775              :     BL_PROFILE("Integrator::WritePlotFile");
     776          250 :     int nlevels = finest_level + 1;
     777          250 :     if (max_plot_level >= 0) nlevels = std::min(nlevels, max_plot_level);
     778              : 
     779          250 :     int ccomponents = 0, ncomponents = 0, bfcomponents_cell = 0, bfcomponents = 0;
     780          250 :     amrex::Vector<std::string> cnames, nnames, bfnames_cell, bfnames;
     781         1226 :     for (int i = 0; i < cell.number_of_fabs; i++)
     782              :     {
     783          976 :         if (!cell.writeout_array[i]) continue;
     784          731 :         ccomponents += cell.ncomp_array[i];
     785          731 :         if (cell.ncomp_array[i] > 1)
     786          737 :             for (int j = 0; j < cell.ncomp_array[i]; j++)
     787          518 :                 cnames.push_back(cell.name_array[i][j]);
     788              :         else
     789          512 :             cnames.push_back(cell.name_array[i][0]);
     790              :     }
     791          335 :     for (int i = 0; i < node.number_of_fabs; i++)
     792              :     {
     793           85 :         if (!node.writeout_array[i]) continue;
     794           85 :         ncomponents += node.ncomp_array[i];
     795           85 :         if (node.ncomp_array[i] > 1)
     796           18 :             for (int j = 0; j < node.ncomp_array[i]; j++)
     797           12 :                 nnames.push_back(node.name_array[i][j]);
     798              :         else
     799           79 :             nnames.push_back(node.name_array[i][0]);
     800              :     }
     801          250 :     for (unsigned int i = 0; i < m_basefields_cell.size(); i++)
     802              :     {
     803            0 :         if (m_basefields_cell[i]->writeout)
     804              :         {
     805            0 :             bfcomponents_cell += m_basefields_cell[i]->NComp();
     806            0 :             for (int j = 0; j < m_basefields_cell[i]->NComp(); j++)
     807            0 :                 bfnames_cell.push_back(m_basefields_cell[i]->Name(j));
     808              :         }
     809              :     }
     810          677 :     for (unsigned int i = 0; i < m_basefields.size(); i++)
     811              :     {
     812          427 :         if (m_basefields[i]->writeout)
     813              :         {
     814          427 :             bfcomponents += m_basefields[i]->NComp();
     815         2057 :             for (int j = 0; j < m_basefields[i]->NComp(); j++)
     816         1630 :                 bfnames.push_back(m_basefields[i]->Name(j));
     817              :         }
     818              :     }
     819              : 
     820          750 :     amrex::Vector<amrex::MultiFab> cplotmf(nlevels), nplotmf(nlevels);
     821              : 
     822          250 :     bool do_cell_plotfile = (ccomponents + bfcomponents_cell > 0 || (ncomponents + bfcomponents > 0 && cell.all)) && cell.any;
     823          250 :     bool do_node_plotfile = (ncomponents + bfcomponents > 0 || (ccomponents + bfcomponents_cell > 0 && node.all)) && node.any;
     824              : 
     825          953 :     for (int ilev = 0; ilev < nlevels; ++ilev)
     826              :     {
     827          703 :         if (do_cell_plotfile)
     828              :         {
     829          653 :             int ncomp = ccomponents + bfcomponents_cell;
     830          653 :             if (cell.all) ncomp += ncomponents + bfcomponents;
     831          653 :             cplotmf[ilev].define(grids[ilev], dmap[ilev], ncomp, 0);
     832              : 
     833          653 :             int n = 0;
     834          653 :             int cnames_cnt = 0;
     835         2480 :             for (int i = 0; i < cell.number_of_fabs; i++)
     836              :             {
     837         1827 :                 if (!cell.writeout_array[i]) continue;
     838         1188 :                 if ((*cell.fab_array[i])[ilev]->contains_nan())
     839              :                 {
     840            0 :                     if (abort_on_nan) Util::Abort(INFO, cnames[cnames_cnt], " contains nan (i=", i, ")");
     841            0 :                     else              Util::Warning(INFO, cnames[cnames_cnt], " contains nan (i=", i, ")");
     842              :                 }
     843         1188 :                 if ((*cell.fab_array[i])[ilev]->contains_inf())
     844              :                 {
     845            0 :                     if (abort_on_nan) Util::Abort(INFO, cnames[cnames_cnt], " contains inf (i=", i, ")");
     846            0 :                     else              Util::Warning(INFO, cnames[cnames_cnt], " contains inf (i=", i, ")");
     847              :                 }
     848         1188 :                 cnames_cnt++;
     849         1188 :                 amrex::MultiFab::Copy(cplotmf[ilev], *(*cell.fab_array[i])[ilev], 0, n, cell.ncomp_array[i], 0);
     850         1188 :                 n += cell.ncomp_array[i];
     851              :             }
     852          653 :             for (unsigned int i = 0; i < m_basefields_cell.size(); i++)
     853              :             {
     854            0 :                 if (m_basefields_cell[i]->writeout)
     855              :                 {
     856            0 :                     m_basefields_cell[i]->Copy(ilev, cplotmf[ilev], n, 0);
     857            0 :                     n += m_basefields_cell[i]->NComp();
     858              :                 }
     859              :             }
     860              : 
     861          653 :             if (cell.all)
     862              :             {
     863          108 :                 int nnames_cnt = 0;
     864          216 :                 for (int i = 0; i < node.number_of_fabs; i++)
     865              :                 {
     866          108 :                     if (!node.writeout_array[i]) continue;
     867          108 :                     if ((*node.fab_array[i])[ilev]->contains_nan())
     868              :                     {
     869            0 :                         if (abort_on_nan) Util::Abort(INFO, nnames[nnames_cnt], " contains nan (i=", i, ")");
     870            0 :                         else              Util::Warning(INFO, nnames[nnames_cnt], " contains nan (i=", i, ")");
     871              :                     }
     872          108 :                     if ((*node.fab_array[i])[ilev]->contains_inf())
     873              :                     {
     874            0 :                         if (abort_on_nan) Util::Abort(INFO, nnames[nnames_cnt], " contains inf (i=", i, ")");
     875            0 :                         else              Util::Warning(INFO, nnames[nnames_cnt], " contains inf (i=", i, ")");
     876              :                     }
     877          108 :                     nnames_cnt++;
     878          108 :                     amrex::average_node_to_cellcenter(cplotmf[ilev], n, *(*node.fab_array[i])[ilev], 0, node.ncomp_array[i], 0);
     879          108 :                     n += node.ncomp_array[i];
     880              :                 }
     881          108 :                 if (bfcomponents > 0)
     882              :                 {
     883          108 :                     amrex::BoxArray ngrids = grids[ilev];
     884          108 :                     ngrids.convert(amrex::IntVect::TheNodeVector());
     885          108 :                     amrex::MultiFab bfplotmf(ngrids, dmap[ilev], bfcomponents, 0);
     886          108 :                     int ctr = 0;
     887          672 :                     for (unsigned int i = 0; i < m_basefields.size(); i++)
     888              :                     {
     889          564 :                         if (m_basefields[i]->writeout)
     890              :                         {
     891          564 :                             m_basefields[i]->Copy(ilev, bfplotmf, ctr, 0);
     892          564 :                             ctr += m_basefields[i]->NComp();
     893              :                         }
     894              :                     }
     895          108 :                     amrex::average_node_to_cellcenter(cplotmf[ilev], n, bfplotmf, 0, bfcomponents);
     896          108 :                     n += bfcomponents;
     897          108 :                 }
     898              :             }
     899              :         }
     900              : 
     901          703 :         if (do_node_plotfile)
     902              :         {
     903          175 :             amrex::BoxArray ngrids = grids[ilev];
     904          175 :             ngrids.convert(amrex::IntVect::TheNodeVector());
     905          175 :             int ncomp = ncomponents + bfcomponents;
     906          175 :             if (node.all) ncomp += ccomponents + bfcomponents_cell;
     907          175 :             nplotmf[ilev].define(ngrids, dmap[ilev], ncomp, 0);
     908              : 
     909          175 :             int n = 0;
     910          345 :             for (int i = 0; i < node.number_of_fabs; i++)
     911              :             {
     912          170 :                 if (!node.writeout_array[i]) continue;
     913          170 :                 if ((*node.fab_array[i])[ilev]->contains_nan()) Util::Warning(INFO, nnames[i], " contains nan (i=", i, "). Resetting to zero.");
     914          170 :                 if ((*node.fab_array[i])[ilev]->contains_inf()) Util::Abort(INFO, nnames[i], " contains inf (i=", i, ")");
     915          170 :                 amrex::MultiFab::Copy(nplotmf[ilev], *(*node.fab_array[i])[ilev], 0, n, node.ncomp_array[i], 0);
     916          170 :                 n += node.ncomp_array[i];
     917              :             }
     918          994 :             for (unsigned int i = 0; i < m_basefields.size(); i++)
     919              :             {
     920          819 :                 if (m_basefields[i]->writeout)
     921              :                 {
     922          819 :                     m_basefields[i]->Copy(ilev, nplotmf[ilev], n, 0);
     923          819 :                     n += m_basefields[i]->NComp();
     924              :                 }
     925              :             }
     926              : 
     927          175 :             if (node.all)
     928              :             {
     929          129 :                 for (int i = 0; i < cell.number_of_fabs; i++)
     930              :                 {
     931           67 :                     if (!cell.writeout_array[i]) continue;
     932           62 :                     if ((*cell.fab_array[i])[ilev]->contains_nan()) Util::Warning(INFO, cnames[i], " contains nan (i=", i, "). Resetting to zero.");
     933           62 :                     if ((*cell.fab_array[i])[ilev]->contains_inf()) Util::Abort(INFO, cnames[i], " contains inf (i=", i, ")");
     934           62 :                     if ((*cell.fab_array[i])[ilev]->nGrow() == 0)
     935              :                     {
     936            0 :                         if (initial) Util::Warning(INFO, cnames[i], " has no ghost cells and will not be included in nodal output");
     937            0 :                         continue;
     938              :                     }
     939           62 :                     Util::AverageCellcenterToNode(nplotmf[ilev], n, *(*cell.fab_array[i])[ilev], 0, cell.ncomp_array[i]);
     940           62 :                     n += cell.ncomp_array[i];
     941              :                 }
     942              : 
     943           62 :                 if (bfcomponents_cell > 0)
     944              :                 {
     945            0 :                     amrex::BoxArray cgrids = grids[ilev];
     946            0 :                     amrex::MultiFab bfplotmf(cgrids, dmap[ilev], bfcomponents_cell, 0);
     947            0 :                     int ctr = 0;
     948            0 :                     for (unsigned int i = 0; i < m_basefields_cell.size(); i++)
     949              :                     {
     950            0 :                         if (m_basefields_cell[i]->writeout)
     951              :                         {
     952            0 :                             m_basefields_cell[i]->Copy(ilev, bfplotmf, ctr, 0);
     953            0 :                             ctr += m_basefields_cell[i]->NComp();
     954              :                         }
     955              :                     }
     956            0 :                     Util::AverageCellcenterToNode(nplotmf[ilev], n, bfplotmf, 0, bfcomponents_cell);
     957            0 :                     n += bfcomponents_cell;
     958            0 :                 }
     959              :             }
     960          175 :         }
     961              :     }
     962              : 
     963          250 :     std::vector<std::string> plotfilename = PlotFileName(istep[0], prefix);
     964          250 :     if (initial) plotfilename[1] = plotfilename[1] + "init";
     965              : 
     966          250 :     if (do_cell_plotfile)
     967              :     {
     968          204 :         amrex::Vector<std::string> allnames = cnames;
     969          204 :         allnames.insert(allnames.end(), bfnames_cell.begin(), bfnames_cell.end());
     970          204 :         if (cell.all) {
     971           35 :             allnames.insert(allnames.end(), nnames.begin(), nnames.end());
     972           35 :             allnames.insert(allnames.end(), bfnames.begin(), bfnames.end());
     973              :         }
     974         1428 :         WriteMultiLevelPlotfile(plotfilename[0] + plotfilename[1] + "cell", nlevels, amrex::GetVecOfConstPtrs(cplotmf), allnames,
     975              :             Geom(), time, iter, refRatio());
     976              : 
     977          204 :         std::ofstream chkptfile;
     978          204 :         chkptfile.open(plotfilename[0] + plotfilename[1] + "cell/Checkpoint");
     979          864 :         for (int i = 0; i <= max_level; i++) boxArray(i).writeOn(chkptfile);
     980          204 :         chkptfile.close();
     981          204 :     }
     982              : 
     983          250 :     if (do_node_plotfile)
     984              :     {
     985           86 :         amrex::Vector<std::string> allnames = nnames;
     986           86 :         allnames.insert(allnames.end(), bfnames.begin(), bfnames.end());
     987           86 :         if (node.all) allnames.insert(allnames.end(), cnames.begin(), cnames.end());
     988          602 :         WriteMultiLevelPlotfile(plotfilename[0] + plotfilename[1] + "node", nlevels, amrex::GetVecOfConstPtrs(nplotmf), allnames,
     989              :             Geom(), time, iter, refRatio());
     990              : 
     991           86 :         std::ofstream chkptfile;
     992           86 :         chkptfile.open(plotfilename[0] + plotfilename[1] + "node/Checkpoint");
     993          265 :         for (int i = 0; i <= max_level; i++) boxArray(i).writeOn(chkptfile);
     994           86 :         chkptfile.close();
     995           86 :     }
     996              : 
     997          250 :     if (amrex::ParallelDescriptor::IOProcessor())
     998              :     {
     999          250 :         std::ofstream coutfile, noutfile;
    1000          250 :         if (istep[0] == 0)
    1001              :         {
    1002           37 :             if (do_cell_plotfile) coutfile.open(plot_file + "/celloutput.visit", std::ios_base::out);
    1003           37 :             if (do_node_plotfile) noutfile.open(plot_file + "/nodeoutput.visit", std::ios_base::out);
    1004              :         }
    1005              :         else
    1006              :         {
    1007          213 :             if (do_cell_plotfile) coutfile.open(plot_file + "/celloutput.visit", std::ios_base::app);
    1008          213 :             if (do_node_plotfile) noutfile.open(plot_file + "/nodeoutput.visit", std::ios_base::app);
    1009              :         }
    1010          250 :         if (do_cell_plotfile) coutfile << plotfilename[1] + "cell" + "/Header" << std::endl;
    1011          250 :         if (do_node_plotfile) noutfile << plotfilename[1] + "node" + "/Header" << std::endl;
    1012          250 :     }
    1013          250 : }
    1014              : 
    1015              : void
    1016           37 : Integrator::Evolve()
    1017              : {
    1018              :     BL_PROFILE("Integrator::Evolve");
    1019           37 :     amrex::Real cur_time = t_new[0];
    1020           37 :     int last_plot_file_step = 0;
    1021              : 
    1022        12040 :     for (int step = istep[0]; step < max_step && cur_time < stop_time; ++step)
    1023              :     {
    1024        12040 :         if (amrex::ParallelDescriptor::IOProcessor()) {
    1025        12040 :             std::cout << "\nSTEP " << step + 1 << " starts ..." << std::endl;
    1026              :         }
    1027        12040 :         int lev = 0;
    1028        12040 :         int iteration = 1;
    1029        12040 :         TimeStepBegin(cur_time, step);
    1030        12040 :         if (integrate_variables_before_advance) IntegrateVariables(cur_time, step);
    1031        12040 :         TimeStep(lev, cur_time, iteration);
    1032        12040 :         if (integrate_variables_after_advance) IntegrateVariables(cur_time, step);
    1033        12040 :         TimeStepComplete(cur_time, step);
    1034        12040 :         cur_time += dt[0];
    1035              : 
    1036        12040 :         if (amrex::ParallelDescriptor::IOProcessor()) {
    1037        12040 :             std::cout << "STEP " << step + 1 << " ends."
    1038        12040 :                 << " TIME = " << cur_time << " DT = " << dt[0]
    1039        12040 :                 << std::endl;
    1040              :         }
    1041              : 
    1042              :         // sync up time
    1043        46111 :         for (int lev = 0; lev <= finest_level; ++lev) {
    1044        34071 :             t_new[lev] = cur_time;
    1045              :         }
    1046              : 
    1047        12040 :         if (plot_int > 0 && (step + 1) % plot_int == 0) {
    1048          133 :             last_plot_file_step = step + 1;
    1049          133 :             WritePlotFile();
    1050          133 :             IO::WriteMetaData(plot_file, IO::Status::Running, (int)(100.0 * cur_time / stop_time));
    1051              :         }
    1052        11907 :         else if (std::fabs(std::remainder(cur_time, plot_dt)) < 0.5 * dt[0])
    1053              :         {
    1054           76 :             last_plot_file_step = step + 1;
    1055           76 :             WritePlotFile();
    1056           76 :             IO::WriteMetaData(plot_file, IO::Status::Running, (int)(100.0 * cur_time / stop_time));
    1057              :         }
    1058              : 
    1059        12040 :         if (cur_time >= stop_time - 1.e-6 * dt[0]) break;
    1060              :     }
    1061           37 :     if (plot_int > 0 && istep[0] > last_plot_file_step) {
    1062            4 :         WritePlotFile();
    1063              :     }
    1064           37 : }
    1065              : 
    1066              : void
    1067        12040 : Integrator::IntegrateVariables(amrex::Real time, int step)
    1068              : {
    1069              :     BL_PROFILE("Integrator::IntegrateVariables");
    1070        12040 :     if (!thermo.number) return;
    1071              : 
    1072          480 :     if ((thermo.interval > 0 && (step) % thermo.interval == 0) ||
    1073            0 :         ((thermo.dt > 0.0) && (std::fabs(std::remainder(time, plot_dt)) < 0.5 * dt[0])))
    1074              :     {
    1075              :         // Zero out all variables
    1076         4146 :         for (int i = 0; i < thermo.number; i++)
    1077              :         {
    1078         3666 :             if (thermo.extensives[i]) *thermo.vars[i] = 0;
    1079              :         }
    1080              : 
    1081              :         // All levels except the finest
    1082          696 :         for (int ilev = 0; ilev < max_level; ilev++)
    1083              :         {
    1084          216 :             const amrex::BoxArray& cfba = amrex::coarsen(grids[ilev + 1], refRatio(ilev));
    1085              : 
    1086              : #ifdef OMP
    1087              : #pragma omp parallel
    1088              : #endif
    1089         6205 :             for (amrex::MFIter mfi(grids[ilev], dmap[ilev], true); mfi.isValid(); ++mfi)
    1090              :             {
    1091         5989 :                 const amrex::Box& box = mfi.tilebox();
    1092         5989 :                 const amrex::BoxArray& comp = amrex::complementIn(box, cfba);
    1093              : 
    1094        13579 :                 for (int i = 0; i < comp.size(); i++)
    1095              :                 {
    1096         7590 :                     Integrate(ilev, time, step,
    1097        15180 :                         mfi, comp[i]);
    1098              :                 }
    1099         6205 :             }
    1100          216 :         }
    1101              :         // Now do the finest level
    1102              :         {
    1103              : #ifdef OMP
    1104              : #pragma omp parallel
    1105              : #endif 
    1106         5864 :             for (amrex::MFIter mfi(grids[max_level], dmap[max_level], true); mfi.isValid(); ++mfi)
    1107              :             {
    1108         5384 :                 const amrex::Box& box = mfi.tilebox();
    1109         5384 :                 Integrate(max_level, time, step, mfi, box);
    1110          480 :             }
    1111              :         }
    1112              : 
    1113              :         // Sum up across all processors
    1114         4146 :         for (int i = 0; i < thermo.number; i++)
    1115              :         {
    1116         3666 :             if (thermo.extensives[i])
    1117         3666 :                 amrex::ParallelDescriptor::ReduceRealSum(*thermo.vars[i]);
    1118              :         }
    1119              :     }
    1120          960 :     if (amrex::ParallelDescriptor::IOProcessor() &&
    1121              :         (
    1122          480 :             (thermo.plot_int > 0 && step % thermo.plot_int == 0) ||
    1123           69 :             (thermo.plot_dt > 0.0 && std::fabs(std::remainder(time, thermo.plot_dt)) < 0.5 * dt[0])
    1124              :             ))
    1125              :     {
    1126          414 :         std::ofstream outfile;
    1127          414 :         if (step == 0)
    1128              :         {
    1129            8 :             outfile.open(plot_file + "/thermo.dat", std::ios_base::out);
    1130            8 :             outfile << "time";
    1131           73 :             for (int i = 0; i < thermo.number; i++)
    1132           65 :                 outfile << "\t" << thermo.names[i];
    1133            8 :             outfile << std::endl;
    1134              :         }
    1135          406 :         else outfile.open(plot_file + "/thermo.dat", std::ios_base::app);
    1136          414 :         outfile << time;
    1137         3731 :         for (int i = 0; i < thermo.number; i++)
    1138         3317 :             outfile << "\t" << *thermo.vars[i];
    1139          414 :         outfile << std::endl;
    1140          414 :         outfile.close();
    1141          414 :     }
    1142              : 
    1143              : }
    1144              : 
    1145              : 
    1146              : void
    1147       110612 : Integrator::TimeStep(int lev, amrex::Real time, int /*iteration*/)
    1148              : {
    1149              :     BL_PROFILE("Integrator::TimeStep");
    1150       110612 :     if (base_regrid_int <= 0 || istep[0] % base_regrid_int == 0)
    1151              :     {
    1152       102942 :         if (regrid_int > 0 || base_regrid_int > 0)  // We may need to regrid
    1153              :         {
    1154       102851 :             static amrex::Vector<int> last_regrid_step(max_level + 1, 0);
    1155              : 
    1156              :             // regrid doesn't change the base level, so we don't regrid on max_level
    1157       102816 :             if (lev < max_level && istep[lev] > last_regrid_step[lev])
    1158              :             {
    1159        45735 :                 if (istep[lev] % regrid_int == 0)
    1160              :                 {
    1161        19967 :                     regrid(lev, time, false);
    1162              :                 }
    1163              :             }
    1164              :         }
    1165              :     }
    1166       110612 :     SetFinestLevel(finest_level);
    1167              : 
    1168       110612 :     if (Verbose() && amrex::ParallelDescriptor::IOProcessor()) {
    1169            0 :         std::cout << "[Level " << lev
    1170            0 :             << " step " << istep[lev] + 1 << "] ";
    1171            0 :         std::cout << "ADVANCE with dt = "
    1172            0 :             << dt[lev]
    1173            0 :             << std::endl;
    1174              :     }
    1175              : 
    1176       410536 :     for (int n = 0; n < cell.number_of_fabs; n++)
    1177       299924 :         if (cell.evolving_array[n]) FillPatch(lev, time, *cell.fab_array[n], *(*cell.fab_array[n])[lev], *cell.physbc_array[n], 0);
    1178       119530 :     for (int n = 0; n < node.number_of_fabs; n++)
    1179         8918 :         if (node.evolving_array[n]) FillPatch(lev, time, *node.fab_array[n], *(*node.fab_array[n])[lev], *node.physbc_array[n], 0);
    1180       110612 :     for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
    1181            0 :         if (m_basefields_cell[n]->evolving) m_basefields_cell[n]->FillPatch(lev, time);
    1182       114334 :     for (unsigned int n = 0; n < m_basefields.size(); n++)
    1183         3722 :         if (m_basefields[n]->evolving) m_basefields[n]->FillPatch(lev, time);
    1184              : 
    1185       110612 :     Advance(lev, time, dt[lev]);
    1186       110612 :     ++istep[lev];
    1187              : 
    1188       110612 :     if (Verbose() && amrex::ParallelDescriptor::IOProcessor())
    1189              :     {
    1190            0 :         std::cout << "[Level " << lev
    1191            0 :             << " step " << istep[lev] << "] ";
    1192            0 :         std::cout << "Advanced "
    1193            0 :             << CountCells(lev)
    1194            0 :             << " cells"
    1195            0 :             << std::endl;
    1196              :     }
    1197              : 
    1198       110612 :     if (lev < finest_level)
    1199              :     {
    1200       147858 :         for (int i = 1; i <= nsubsteps[lev + 1]; ++i)
    1201        98572 :             TimeStep(lev + 1, time + (i - 1) * dt[lev + 1], i);
    1202              : 
    1203       156564 :         for (int n = 0; n < cell.number_of_fabs; n++)
    1204              :         {
    1205       214556 :             amrex::average_down(*(*cell.fab_array[n])[lev + 1], *(*cell.fab_array[n])[lev],
    1206       107278 :                 geom[lev + 1], geom[lev],
    1207       214556 :                 0, (*cell.fab_array[n])[lev]->nComp(), refRatio(lev));
    1208              :         }
    1209        53124 :         for (int n = 0; n < node.number_of_fabs; n++)
    1210              :         {
    1211         3838 :             amrex::average_down(*(*node.fab_array[n])[lev + 1], *(*node.fab_array[n])[lev],
    1212         7676 :                 0, (*node.fab_array[n])[lev]->nComp(), refRatio(lev));
    1213              :         }
    1214        49286 :         for (unsigned int n = 0; n < m_basefields_cell.size(); n++)
    1215              :         {
    1216            0 :             if (m_basefields_cell[n]->evolving)
    1217            0 :                 m_basefields_cell[n]->AverageDown(lev, refRatio(lev));
    1218              :         }
    1219        50080 :         for (unsigned int n = 0; n < m_basefields.size(); n++)
    1220              :         {
    1221          794 :             if (m_basefields[n]->evolving)
    1222            0 :                 m_basefields[n]->AverageDown(lev, refRatio(lev));
    1223              :         }
    1224              : 
    1225              :     }
    1226       110612 : }
    1227              : }
        

Generated by: LCOV version 2.0-1