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