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