LCOV - code coverage report
Current view: top level - src/Integrator - Integrator.H (source / functions) Hit Total Coverage
Test: coverage_merged.info Lines: 80 86 93.0 %
Date: 2024-11-18 05:28:54 Functions: 30 74 40.5 %

          Line data    Source code
       1             : //
       2             : // Pure abstract class for managing data structures, time integration (with substepping),
       3             : // mesh refinement, and I/O. 
       4             : //
       5             : // Native input file parameters:
       6             : //
       7             : // .. code-block:: make
       8             : //
       9             : //     max_step  = [maximum number of timesteps]
      10             : //     stop_time = [maximum simulation time]
      11             : //     timestep  = [time step for coarsest level]
      12             : //
      13             : //     amr.regrid_int = [number of timesteps between regridding]
      14             : //     amr.plot_int   = [number of timesteps between dumping output]
      15             : //     amr.plot_file  = [base name of output directory]
      16             : //     
      17             : //     amr.nsubsteps  = [number of temporal substeps at each level. This can be
      18             : //                       either a single int (which is then applied to every refinement
      19             : //                       level) or an array of ints (equal to amr.max_level) 
      20             : //                       corresponding to the refinement for each level.]
      21             : //
      22             : // Inherited input file parameters (from amrex AmrMesh class):
      23             : //
      24             : // .. code-block:: make
      25             : //
      26             : //     amr.v                  = [verbosity level]
      27             : //     amr.max_level          = [maximum level of refinement]
      28             : //     amr.n_proper           = 
      29             : //     amr.grid_eff           = 
      30             : //     amr.n_error_buff       = 
      31             : //     amr.ref_ratio_vect     = [refinement ratios in each direction]
      32             : //     amr.ref_ratio          = [refinement ratio in all directions (cannot be used with ref_ratio_vect)]
      33             : //     amr.max_grid_x         = 
      34             : //     amr.blocking_factor    =
      35             : //     amr.n_cell             = [number of cells on coarsest level]
      36             : //     amr.refine_grid_layout = 
      37             : //     amr.check_input        = 
      38             : //
      39             : 
      40             : #ifndef INTEGRATOR_INTEGRATOR_H
      41             : #define INTEGRATOR_INTEGRATOR_H
      42             : 
      43             : #include <chrono>
      44             : #include <ctime>
      45             : #include <string>
      46             : #include <limits>
      47             : #include <memory>
      48             : 
      49             : #ifdef _OPENMP
      50             : #include <omp.h>
      51             : #endif
      52             : 
      53             : #include <AMReX_ParallelDescriptor.H>
      54             : #include <AMReX_ParmParse.H>
      55             : #include <AMReX_MultiFabUtil.H>
      56             : #include <AMReX_FillPatchUtil.H>
      57             : #include <AMReX_BC_TYPES.H>
      58             : #include <AMReX_AmrCore.H>
      59             : #include <AMReX_FluxRegister.H>
      60             : #include <AMReX_Utility.H>
      61             : #include <AMReX_PlotFileUtil.H>
      62             : 
      63             : #include "Set/Set.H"
      64             : #include "BC/BC.H"
      65             : #include "BC/Nothing.H"
      66             : #include "IO/WriteMetaData.H"
      67             : #include "BaseField.H"
      68             : 
      69             : /// \brief Collection of numerical integrator objects
      70             : namespace Integrator
      71             : {
      72             : 
      73             : class Integrator
      74             :     : public amrex::AmrCore
      75             : {
      76             : public:
      77             : 
      78             :     /// \function Integrator
      79             :     /// \brief Constructor
      80             :     ///
      81             :     /// Does the following things:
      82             :     ///    - Read in simulation TIME(STEP) information
      83             :     ///    - Read in simulation output and AMR information
      84             :     ///    - Initalize timestep substep information
      85             :     ///    - Create a clean directory
      86             :     /// For derived classes this **must** be called for the derived constructor. For instance: `code`
      87             :     /// ```cpp
      88             :     /// class MyDerivedClass : Integrator
      89             :     /// {
      90             :     ///    MyDerivedClass() : Integrator() { ... }
      91             :     ///    ...
      92             :     /// }
      93             :     /// ```
      94             :     Integrator();
      95             : 
      96             :     virtual ~Integrator();
      97             : 
      98             :     /// \fn    FrontData
      99             :     /// \brief Front-end method to initialize simulation
     100             :     void InitData();
     101             : 
     102             :     void Restart(std::string restartfile, bool a_node = false);
     103             : 
     104             :     /// \fn    Evolve
     105             :     /// \brief Front-end method to start simulation
     106             :     void Evolve();
     107             : 
     108             :     void SetFilename(std::string _plot_file) { plot_file = _plot_file; };
     109             :     std::string GetFilename() { return plot_file; };
     110             : 
     111        2196 :     void regrid(int lbase, Set::Scalar time, bool initial = false) override
     112             :     {
     113        2196 :         if (!explicitmesh.on)
     114        2188 :             AmrCore::regrid(lbase, time, initial);
     115        2196 :     }
     116             : 
     117          31 :     void InitFromScratch(Set::Scalar time)
     118             :     {
     119          31 :         if (!explicitmesh.on) AmrCore::InitFromScratch(time);
     120             :         else
     121             :         {
     122             :             // Generate the coarse level mesh.
     123             :             {
     124           7 :                 finest_level = 0;
     125          14 :                 const amrex::BoxArray& ba = MakeBaseGrids();
     126          14 :                 amrex::DistributionMapping dm(ba);
     127           7 :                 const auto old_num_setdm = num_setdm;
     128           7 :                 const auto old_num_setba = num_setba;
     129           7 :                 MakeNewLevelFromScratch(0, time, ba, dm);
     130           7 :                 if (old_num_setba == num_setba) SetBoxArray(0, ba);
     131           7 :                 if (old_num_setdm == num_setdm) SetDistributionMap(0, dm);
     132             :             }
     133             :             // Generate subsequent level meshes based on user input
     134          13 :             for (int ilev = 0; ilev < maxLevel(); ++ilev)
     135             :             {
     136           6 :                 finest_level = ilev + 1;
     137          12 :                 amrex::BoxArray grids(explicitmesh.box[ilev]);
     138           6 :                 ChopGrids(ilev + 1, grids, amrex::ParallelDescriptor::NProcs());
     139          12 :                 amrex::DistributionMapping dmap(grids);
     140           6 :                 SetBoxArray(ilev + 1, grids);
     141           6 :                 SetDistributionMap(ilev + 1, dmap);
     142           6 :                 MakeNewLevelFromScratch(ilev + 1, time, grids, dmap);
     143             :             }
     144             : 
     145             :         }
     146          31 :     }
     147             : 
     148             : protected:
     149             : 
     150             :     /// \fn    Initialize
     151             :     /// \brief Apply initial conditions
     152             :     ///
     153             :     /// You **must** override this function to inherit this class.
     154             :     /// This function is called before the simulation begins, and is where
     155             :     /// initial conditions should be applied.
     156             :     virtual void Initialize(int lev ///<[in] AMR Level
     157             :     ) = 0;
     158             : 
     159             :     /// \fn    Advance
     160             :     /// \brief Perform computation
     161             :     ///
     162             :     /// You **must** override this function to inherit this class.
     163             :     /// Advance is called every time(sub)step, and implements the evolution of 
     164             :     /// the system in time.
     165             :     /// 
     166             :     virtual void Advance(int lev,          ///<[in] AMR Level
     167             :         amrex::Real time, ///< [in] System time
     168             :         amrex::Real dt    ///< [in] Timestep for this level
     169             :     ) = 0;
     170             : 
     171             :     /// \fn    TagCellsForRefinement
     172             :     /// \brief Tag cells where mesh refinement is needed
     173             :     ///
     174             :     /// You **must** override this function to inherit this class.
     175             :     /// Advance is called every time(sub)step, and implements the evolution of 
     176             :     /// the system in time.
     177             :     /// 
     178             :     virtual void TagCellsForRefinement(int lev, amrex::TagBoxArray& tags, amrex::Real time,
     179             :         int ngrow) = 0;
     180             : 
     181             :     /// \fn    TimeStepBegin
     182             :     /// \brief Run another system calculation (e.g. implicit solve) before integration step
     183             :     ///
     184             :     /// This function is called at the beginning of every timestep. This function can be used
     185             :     /// to complete additional global solves, e.g. a MLMG implicit solve.
     186             :     ///
     187             :     /// Overriding is optional; the default is to do nothing.
     188             :     ///
     189        1606 :     virtual void TimeStepBegin(Set::Scalar /*time*/, int /*iter*/) {};
     190             : 
     191             :     /// \fn    TimeStepComplete
     192             :     /// \brief Run another system calculation (e.g. implicit solve) after integration step
     193             :     ///
     194             :     /// This function is called at the end of every timestep. This function can be used
     195             :     /// to complete additional global solves, e.g. a MLMG implicit solve.
     196             :     ///
     197             :     /// Overriding is optional; the default is to do nothing.
     198             :     ///
     199        2032 :     virtual void TimeStepComplete(Set::Scalar /*time*/, int /*iter*/) {};
     200             : 
     201             :     /// \fn    Integrate
     202             :     /// \brief Perform an integration to compute integrated quantities
     203             :     ///
     204             :     /// This is a function that is called by `Integrator` to update the variables registered in
     205             :     /// RegisterIntegratedVariable.
     206             :     /// The following variables are used:
     207             :     ///   -  amrlev: current amr level
     208             :     ///   -  time: current simulation time
     209             :     ///   -  iter: current simulation iteration
     210             :     ///   -  mfi:  current MFIter object (used to get FArrayBox from MultiFab)
     211             :     ///   -  box:  Use this box (not mfi.tilebox). This box covers only cells on this level that are
     212             :     ///            not also on a finer level.
     213           0 :     virtual void Integrate(int /*amrlev*/, Set::Scalar /*time*/, int /*iter*/,
     214             :         const amrex::MFIter&/*mfi*/, const amrex::Box&/*box*/)
     215             :     {
     216           0 :         if (thermo.number > 0)
     217           0 :             Util::Warning(INFO, "integrated variables registered, but no integration implemented!");
     218           0 :     }
     219             : 
     220         409 :     virtual void Regrid(int /* amrlev */, Set::Scalar /* time */)
     221         409 :     {}
     222             : 
     223             : 
     224             : 
     225             : 
     226             :     /// \fn    RegisterNewFab
     227             :     /// \brief Register a field variable for AMR with this class 
     228             :     void RegisterNewFab(Set::Field<Set::Scalar>& new_fab, BC::BC<Set::Scalar>* new_bc, int ncomp, int nghost, std::string name, bool writeout);
     229             :     void RegisterNewFab(Set::Field<Set::Scalar>& new_fab, int ncomp, std::string name, bool writeout);
     230             :     void RegisterNodalFab(Set::Field<Set::Scalar>& new_fab, int ncomp, int nghost, std::string name, bool writeout);
     231             :     void RegisterNodalFab(Set::Field<Set::Scalar>& new_fab, BC::BC<Set::Scalar>* new_bc, int ncomp, int nghost, std::string name, bool writeout);
     232             :     template<class T>
     233             :     void RegisterGeneralFab(Set::Field<T>& new_fab, int ncomp, int nghost, bool evolving = true);
     234             :     template<class T>
     235             :     void RegisterGeneralFab(Set::Field<T>& new_fab, int ncomp, int nghost, std::string a_name, bool evolving = true);
     236             :     template<class T>
     237             :     void RegisterGeneralFab(Set::Field<T>& new_fab, int ncomp, int nghost, bool writeout, std::string a_name, bool evolving = true);
     238             : 
     239             :     template<class T, int d>
     240             :     void AddField(Set::Field<T>& new_field, BC::BC<T>* new_bc, int ncomp, int nghost, std::string, bool writeout, bool evolving);
     241             : 
     242       70407 :     void SetFinestLevel(const int a_finestlevel)
     243             :     {
     244      232949 :         for (unsigned int i = 0; i < cell.fab_array.size(); i++)
     245      162542 :             cell.fab_array[i]->finest_level = a_finestlevel;
     246      125200 :         for (unsigned int i = 0; i < node.fab_array.size(); i++)
     247       54793 :             node.fab_array[i]->finest_level = a_finestlevel;
     248       70407 :         for (unsigned int i = 0; i < m_basefields_cell.size(); i++)
     249           0 :             m_basefields_cell[i]->SetFinestLevel(finest_level);
     250       74227 :         for (unsigned int i = 0; i < m_basefields.size(); i++)
     251        3820 :             m_basefields[i]->SetFinestLevel(finest_level);
     252       70407 :     }
     253             : 
     254             :     void RegisterIntegratedVariable(Set::Scalar* integrated_variable, std::string name, bool extensive=true);
     255             : 
     256             :     void SetTimestep(Set::Scalar _timestep);
     257             :     void SetPlotInt(int plot_int);
     258           1 :     void SetThermoInt(int a_thermo_int) { thermo.interval = a_thermo_int; }
     259             :     void SetThermoPlotInt(int a_thermo_plot_int) { thermo.plot_int = a_thermo_plot_int; }
     260             :     void SetStopTime(Set::Scalar a_stop_time) { stop_time = a_stop_time; }
     261             : 
     262             :     amrex::Vector<amrex::Real> t_new;         ///< Keep track of current old simulation time on each level
     263             :     amrex::Vector<int> istep;           ///< Keep track of where each level is
     264             :     // PLOT FILES
     265             :     std::string plot_file{ "plt" };   ///< Plotfile name
     266             : 
     267             : private:
     268             :     virtual void MakeNewLevelFromScratch(int lev, amrex::Real time, const amrex::BoxArray& ba,
     269             :         const amrex::DistributionMapping& dm) override;
     270             :     virtual void MakeNewLevelFromCoarse(int lev, amrex::Real time, const amrex::BoxArray& ba,
     271             :         const amrex::DistributionMapping& dm) override;
     272             :     virtual void RemakeLevel(int lev, amrex::Real time, const amrex::BoxArray& ba,
     273             :         const amrex::DistributionMapping& dm) override;
     274             :     virtual void ClearLevel(int lev) override;
     275             :     virtual void ErrorEst(int lev, amrex::TagBoxArray& tags, amrex::Real time, int ngrow) override;
     276             : 
     277             : 
     278             :     void FillPatch(int lev, amrex::Real time,
     279             :         amrex::Vector<std::unique_ptr<amrex::MultiFab>>& source_mf,
     280             :         amrex::MultiFab& destination_multifab,
     281             :         BC::BC<Set::Scalar>& physbc,
     282             :         int icomp);
     283             :     long CountCells(int lev);
     284             :     void TimeStep(int lev, amrex::Real time, int iteration);
     285             :     void FillCoarsePatch(int lev, amrex::Real time, Set::Field<Set::Scalar>& mf, BC::BC<Set::Scalar>& physbc, int icomp, int ncomp);
     286             :     void GetData(const int lev, const amrex::Real time, amrex::Vector<amrex::MultiFab*>& data, amrex::Vector<amrex::Real>& datatime);
     287             : 
     288             :     std::vector<std::string> PlotFileName(int lev, std::string prefix = "") const;
     289             : protected:
     290             :     void IntegrateVariables(Set::Scalar cur_time, int step);
     291             :     void WritePlotFile(bool initial = false) const;
     292             :     void WritePlotFile(std::string prefix, Set::Scalar time, int step) const;
     293             :     void WritePlotFile(Set::Scalar time, amrex::Vector<int> iter, bool initial = false, std::string prefix = "") const;
     294             : 
     295             :     //
     296             :     // MEMBER VARIABLES
     297             :     //
     298             : 
     299             :     // TIME (STEP) KEEPINGamrex::Vector<std::unique_ptr<amrex::MultiFab> >
     300             : protected:
     301             :     amrex::Real timestep = NAN;   ///< Timestep for the base level of refinement
     302             : private:
     303             :     amrex::Vector<amrex::Real> dt;  ///< Timesteps for each level of refinement
     304             :     amrex::Vector<int> nsubsteps;   ///< how many substeps on each level?
     305             :     int max_plot_level = -1;
     306             : 
     307             :     amrex::Vector<amrex::Real> t_old;///< Keep track of current old simulation time on each level
     308             :     int max_step = std::numeric_limits<int>::max(); ///< Maximum allowable timestep
     309             :     amrex::Real tstart = 0; ///< Default start time (default: 0)
     310             :     amrex::Real stop_time = NAN; ///< Default stop time 
     311             : 
     312             : protected:
     313             :     bool integrate_variables_before_advance = true;
     314             :     bool integrate_variables_after_advance = false;
     315             : 
     316             : protected:
     317             :     struct {
     318             :         int number_of_fabs = 0;
     319             :         std::vector<Set::Field<Set::Scalar>*> fab_array;
     320             :         std::vector<int> ncomp_array;
     321             :         std::vector<int> nghost_array;
     322             :         std::vector<std::string> name_array;
     323             :         std::vector<BC::BC<Set::Scalar>*> physbc_array;
     324             :         std::vector<bool> writeout_array;
     325             :         bool any = true;
     326             :         bool all = false;
     327             :     } node;
     328             : 
     329             :     struct {
     330             :         int number_of_fabs = 0;
     331             :         std::vector<Set::Field<Set::Scalar>*> fab_array;
     332             :         std::vector<int> ncomp_array;
     333             :         std::vector<int> nghost_array;
     334             :         std::vector<std::string> name_array;
     335             :         std::vector<BC::BC<Set::Scalar>*> physbc_array;
     336             :         std::vector<bool> writeout_array;
     337             :         bool any = true;
     338             :         bool all = false;
     339             :     } cell;
     340             : 
     341             :     std::vector<BaseField*> m_basefields;
     342             :     std::vector<BaseField*> m_basefields_cell;
     343             : 
     344             :     BC::Nothing bcnothing;
     345             : 
     346             :     // KEEP TRACK OF ALL INTEGRATED VARIABLES
     347             :     struct {
     348             :         int interval = -1;
     349             :         Set::Scalar dt = NAN;
     350             :         int plot_int = -1;
     351             :         Set::Scalar plot_dt = NAN;
     352             :         int number = 0;
     353             :         std::vector<Set::Scalar*> vars;
     354             :         std::vector<std::string> names;
     355             :         std::vector<bool> extensives;
     356             :     } thermo;
     357             : 
     358             :     // REGRIDDING
     359             :     int regrid_int = -1;       ///< Determine how often to regrid (default: 2)
     360             :     int base_regrid_int = -1; ///< Determine how often to regrid based on coarse level only (default: 0)
     361             : 
     362             :     std::string restart_file_cell = "";
     363             :     std::string restart_file_node = "";
     364             : 
     365             :     struct {
     366             :         int on = 0;
     367             :         std::vector<amrex::Box> box;
     368             :     } explicitmesh;
     369             : 
     370             : protected:
     371             :     int plot_int = -1;               ///< How frequently to dump plot file (default: never)
     372             :     Set::Scalar plot_dt = -1.0;
     373             : 
     374             :     int abort_on_nan = true;
     375             : };
     376             : 
     377             : 
     378             : template<>
     379             : ALAMO_SINGLE_DEFINITION
     380          40 : void Integrator::AddField<Set::Scalar, Set::Hypercube::Cell>(Set::Field<Set::Scalar>& new_field,
     381             :     BC::BC<Set::Scalar>* new_bc,
     382             :     int ncomp,
     383             :     int nghost,
     384             :     std::string name,
     385             :     bool writeout,
     386             :     bool /*evolving*/)
     387             : {
     388          40 :     int nlevs_max = maxLevel() + 1;
     389          40 :     new_field.resize(nlevs_max);
     390          40 :     cell.fab_array.push_back(&new_field);
     391          40 :     if (new_bc != nullptr) cell.physbc_array.push_back(new_bc);
     392           0 :     else                   cell.physbc_array.push_back(&bcnothing);
     393          40 :     cell.ncomp_array.push_back(ncomp);
     394          40 :     cell.nghost_array.push_back(nghost);
     395          40 :     cell.name_array.push_back(name);
     396          40 :     cell.writeout_array.push_back(writeout);
     397          40 :     cell.number_of_fabs++;
     398          40 : }
     399             : 
     400             : template<>
     401             : ALAMO_SINGLE_DEFINITION
     402          21 : void Integrator::AddField<Set::Scalar, Set::Hypercube::Node>(Set::Field<Set::Scalar>& new_field,
     403             :     BC::BC<Set::Scalar>* new_bc,
     404             :     int ncomp,
     405             :     int nghost,
     406             :     std::string name,
     407             :     bool writeout,
     408             :     bool /*evolving*/)
     409             : {
     410             :     BL_PROFILE("Integrator::RegisterNodalFab");
     411          42 :     Util::Assert(INFO, TEST(new_bc == nullptr));
     412          21 :     int nlevs_max = maxLevel() + 1;
     413          21 :     new_field.resize(nlevs_max);
     414          21 :     node.fab_array.push_back(&new_field);
     415          21 :     node.physbc_array.push_back(&bcnothing);
     416          21 :     node.ncomp_array.push_back(ncomp);
     417          21 :     node.nghost_array.push_back(nghost);
     418          21 :     node.name_array.push_back(name);
     419          21 :     node.writeout_array.push_back(writeout);
     420          21 :     node.number_of_fabs++;
     421          21 : }
     422             : 
     423             : template<class T, int d>
     424             : ALAMO_SINGLE_DEFINITION
     425          98 : void Integrator::AddField(Set::Field<T>& new_field, BC::BC<T>* new_bc, int ncomp, int nghost, std::string name, bool writeout, bool evolving)
     426             : {
     427             :     if (d == Set::Hypercube::Node)
     428             :     {
     429         196 :         Util::Assert(INFO, TEST(new_bc == nullptr));
     430          98 :         int nlevs_max = maxLevel() + 1;
     431          98 :         new_field.resize(nlevs_max);
     432          98 :         m_basefields.push_back(new Field<T>(new_field, geom, refRatio(), ncomp, nghost));
     433          98 :         m_basefields.back()->evolving = evolving;
     434          98 :         m_basefields.back()->writeout = writeout;
     435          98 :         m_basefields.back()->setName(name);
     436          98 :         m_basefields.back()->evolving = evolving;
     437          98 :         m_basefields.back()->m_gridtype = Set::Hypercube::Node;
     438             :     }
     439             :     else if (d == Set::Hypercube::Cell)
     440             :     {
     441             :         int nlevs_max = maxLevel() + 1;
     442             :         new_field.resize(nlevs_max);
     443             :         m_basefields_cell.push_back(new Field<T>(new_field, geom, refRatio(), ncomp, nghost));
     444             :         m_basefields_cell.back()->evolving = evolving;
     445             :         m_basefields_cell.back()->writeout = writeout;
     446             :         m_basefields_cell.back()->setName(name);
     447             :         m_basefields_cell.back()->evolving = evolving;
     448             :         if (new_bc) m_basefields_cell.back()->setBC(new_bc);
     449             :         else m_basefields_cell.back()->setBC(&bcnothing);
     450             :         m_basefields_cell.back()->m_gridtype = Set::Hypercube::Cell;
     451             :     }
     452             :     else
     453             :     {
     454             :         Util::Abort(INFO, "Only node and cell based fields can be added at this time");
     455             :     }
     456          98 : }
     457             : 
     458             : 
     459             : 
     460             : template<class T>
     461             : ALAMO_SINGLE_DEFINITION
     462          19 : void Integrator::RegisterGeneralFab(Set::Field<T>& new_fab, int ncomp, int nghost, bool evolving) 
     463             : {
     464             :     //Util::Warning(INFO, "RegisterGeneralFab is depricated. Please replace with AddField");
     465          19 :     AddField<T, Set::Hypercube::Node>(new_fab, nullptr, ncomp, nghost, "", true, evolving);
     466          19 : }
     467             : template<class T>
     468             : ALAMO_SINGLE_DEFINITION
     469           3 : void Integrator::RegisterGeneralFab(Set::Field<T>& new_fab, int ncomp, int nghost, std::string a_name, bool evolving)
     470             : {
     471             :     //Util::Warning(INFO, "RegisterGeneralFab is depricated. Please replace with AddField");
     472           3 :     AddField<T, Set::Hypercube::Node>(new_fab, nullptr, ncomp, nghost, a_name, true, evolving);
     473           3 : }
     474             : template<class T>
     475             : AMREX_ATTRIBUTE_WEAK
     476          76 : void Integrator::RegisterGeneralFab(Set::Field<T>& new_fab, int ncomp, int nghost, bool writeout, std::string a_name, bool evolving)
     477             : {
     478             :     //Util::Warning(INFO, "RegisterGeneralFab is depricated. Please replace with AddField");
     479          76 :     AddField<T, Set::Hypercube::Node>(new_fab, nullptr, ncomp, nghost, a_name, writeout, evolving);
     480          76 : }
     481             : 
     482             : }
     483             : #endif

Generated by: LCOV version 1.14