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