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