Alamo
Util.cpp
Go to the documentation of this file.
1#include "Util.H"
2#include "AMReX_Config.H"
3#include "AMReX_DistributionMapping.H"
4#include "AMReX_VisMF.H"
5#include "Color.H"
6
7#include <chrono>
8#include <cstdlib>
9#include <filesystem>
10#include <iostream>
11#include <stdexcept>
12#include <string>
13#include <vector>
14
15#include "AMReX_ParallelDescriptor.H"
16#include "AMReX_Utility.H"
17
18#include "IO/ParmParse.H"
19#include "IO/WriteMetaData.H"
20#include "IO/FileNameParse.H"
21#include "Color.H"
22#include "Numeric/Stencil.H"
23#include "Util/MPI.H"
24#include <mpi.h>
25
26namespace
27{
28void
29ParseArgsError(const std::string &message)
30{
31 std::cerr << "ERROR: " << message << std::endl;
32 std::exit(EXIT_FAILURE);
33}
34
35bool
36IsInputDefinition(const std::string &arg)
37{
38 return arg == "input" || arg.rfind("input=", 0) == 0;
39}
40
41void
42RejectParseArgsInputFiles(const std::vector<char*> &argv)
43{
44 for (std::size_t i = 1; i < argv.size(); ++i)
45 {
46 const std::string arg(argv[i]);
47
48 if (arg == "--") break;
49
50 if (IsInputDefinition(arg))
51 {
52 ParseArgsError("--parse-args does not accept input-file directives: " + arg);
53 }
54
55 if (arg == "=") continue;
56 if (!arg.empty() && arg[0] == '-') continue;
57 if (arg.find('=') != std::string::npos) continue;
58 if (i + 1 < argv.size() && std::string(argv[i + 1]) == "=") continue;
59 if (i > 1 && std::string(argv[i - 1]) == "=") continue;
60
61 ParseArgsError("--parse-args does not accept input files or positional arguments: " + arg);
62 }
63}
64
65void
66InjectParseArgsDefaults()
67{
68 {
69 amrex::ParmParse pp("amr");
70
71 int max_level = 0;
72 pp.queryAdd("max_level", max_level);
73
74 std::vector<int> n_cell(AMREX_SPACEDIM, 1);
75 pp.queryAdd("n_cell", n_cell);
76
77 int max_grid_size = 1;
78 pp.queryAdd("max_grid_size", max_grid_size);
79
80 int blocking_factor = 1;
81 pp.queryAdd("blocking_factor", blocking_factor);
82 }
83
84 {
85 amrex::ParmParse pp("geometry");
86
87 std::vector<double> prob_lo(AMREX_SPACEDIM, 0.0);
88 pp.queryAdd("prob_lo", prob_lo, AMREX_SPACEDIM);
89
90 if (!pp.contains("prob_hi") && !pp.contains("prob_extent"))
91 {
92 std::vector<double> prob_hi(AMREX_SPACEDIM, 1.0);
93 pp.addarr("prob_hi", prob_hi);
94 }
95
96 std::vector<int> is_periodic(AMREX_SPACEDIM, 0);
97 pp.queryAdd("is_periodic", is_periodic, AMREX_SPACEDIM);
98 }
99
100 {
101 amrex::ParmParse pp;
102
103 std::string stop_time = "1.0";
104 pp.queryAdd("stop_time", stop_time);
105
106 std::string timestep = "1.0";
107 pp.queryAdd("timestep", timestep);
108 }
109}
110}
111
112namespace Util
113{
114
115std::string filename = "";
116std::string globalprefix = "";
117std::pair<std::string,std::string> file_overwrite;
118bool initialized = false;
119bool finalized = false;
120
121std::string GetFileName()
122{
123 if (filename == "")
124 {
125 IO::ParmParse pp;
126
127 pp.forbid("amr.plot_file","Depricated");
128
129 // Output file path
130 pp.query_default("plot_file", filename, "output"); // Name of directory containing all output data
131
133 // else
134 // if (amrex::ParallelDescriptor::IOProcessor())
135 // Util::Abort("No plot file specified! (Specify plot_file = \"plot_file_name\" in input file");
136 }
137 return filename;
138}
139void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
140{
141 if (IO::ParmParse::InTraversalMode()) return;
142
143 try
144 {
145 if (filename == "")
146 Util::Exception(INFO,"Cannot back up files yet because the output directory has not been specified");
147
148 std::string basefilename = std::filesystem::path(a_path).filename();
149 std::string absolutepath = std::filesystem::absolute(std::filesystem::path(a_path)).string();
150 std::string abspathfilename = absolutepath;
151 std::replace(abspathfilename.begin(),abspathfilename.end(),'/','_');
152 if (prefix != "")
153 {
154 abspathfilename = prefix + "__" + abspathfilename;
155 basefilename = prefix + "__" + abspathfilename;
156 }
157
158 if (amrex::ParallelDescriptor::IOProcessor())
159 {
160 std::string destinationpath;
161 if (fullpath) destinationpath = filename+"/"+abspathfilename;
162 else destinationpath = filename+"/"+basefilename;
163
164 // Copy the file where the file name is the absolute path, with / replaced with _
165 if (std::filesystem::exists(destinationpath))
166 Util::Exception(INFO,"Trying to copy ",destinationpath," but it already exists.");
167 std::filesystem::copy_file(a_path,destinationpath);
168 }
169 }
170 catch (std::filesystem::filesystem_error const& ex)
171 {
173 "file system error: \n",
174 " what(): " , ex.what() , '\n',
175 " path1(): " , ex.path1() , '\n',
176 " path2(): " , ex.path2() , '\n',
177 " code().value(): " , ex.code().value() , '\n',
178 " code().message(): " , ex.code().message() , '\n',
179 " code().category(): " , ex.code().category().name());
180 }
181}
182
183std::pair<std::string,std::string> GetOverwrittenFile()
184{
185 return file_overwrite;
186}
187
188void SignalHandler(int s)
189{
191 amrex::ParallelDescriptor::IOProcessor())
192 {
193 std::string filename = GetFileName();
195 if (s == SIGSEGV) status = IO::Status::Segfault;
196 else if (s == SIGINT) status = IO::Status::Interrupt;
197 if (s == SIGABRT) status = IO::Status::Abort;
198 if (filename != "")
200 }
201
202#ifdef MEME
203 IO::ParmParse pp;
204 if (!pp.contains("nomeme"))
205 {
206 time_t timer; time(&timer);
207 std::stringstream cmd;
208 cmd << "xdg-open " << BUILD_DIR << "/src/Util/Meme/cat0" << (1+((int)timer)%6) << ".gif &";
209 std::system(cmd.str().c_str());
210 std::cout << Color::Bold << Color::FG::Red << "PROGRAM FAILED!" << Color::Reset << " (Compile without -DMEME, or set nomeme = 1 in the input file to disable this!)";
211 }
212#endif
213
214 amrex::BLBackTrace::handler(s);
215}
216
217
219{
220 int argc = 0;
221 char **argv = nullptr;
222 Initialize(argc,argv);
223 initialized = true;
224}
225void Initialize (int argc, char* argv[])
226{
227 srand (time(NULL));
228
229 bool parse_args = false;
230 std::string parse_args_output = "alamo-inputs.schema.json";
231 std::vector<char*> amrex_argv;
232 amrex_argv.reserve(argc > 0 ? argc : 0);
233 for (int i = 0; i < argc; i++)
234 {
235 if (std::string(argv[i]) == "--parse-args")
236 {
237 parse_args = true;
238 continue;
239 }
240 if (std::string(argv[i]) == "--parse-args-output")
241 {
242 if (i + 1 >= argc)
243 ParseArgsError("--parse-args-output requires a file path");
244 parse_args_output = argv[++i];
245 continue;
246 }
247 amrex_argv.push_back(argv[i]);
248 }
249
250 if (parse_args) RejectParseArgsInputFiles(amrex_argv);
251
252 int amrex_argc = static_cast<int>(amrex_argv.size());
253 amrex_argv.push_back(nullptr);
254 char **amrex_argv_ptr = amrex_argc == 0 ? nullptr : amrex_argv.data();
255
257 if (parse_args)
258 IO::ParmParse::SetTraversalOutputFile(parse_args_output);
259
260 amrex::Initialize(amrex_argc, amrex_argv_ptr);
261
262 if (parse_args) InjectParseArgsDefaults();
263
264 IO::ParmParse pp;
265 pp.add("amrex.throw_exception",1);
266 //amrex.throw_exception=1
267
268 signal(SIGSEGV, Util::SignalHandler);
269 signal(SIGINT, Util::SignalHandler);
270 signal(SIGABRT, Util::SignalHandler);
271
272 std::string filename = GetFileName();
273
275 amrex::ParallelDescriptor::IOProcessor() && filename != "")
276 {
279 }
280
281 std::string length, time, mass, temperature, current, amount, luminousintensity;
282 // Set the system length unit
283 pp.query_default("system.length",length,"m");
284 // Set the system time unit
285 pp.query_default("system.time",time,"s");
286 // Set the system mass unit
287 pp.query_default("system.mass",mass,"kg");
288 // Set the system temperature unit
289 pp.query_default("system.temperature",temperature,"K");
290 // Set the system current unit
291 pp.query_default("system.current",current,"A");
292 // Set the system amount unit
293 pp.query_default("system.amount",amount,"mol");
294 // Set the system luminous intensity unit
295 pp.query_default("system.luminousintensity",luminousintensity,"cd");
296 try
297 {
298 Unit::setLengthUnit(length);
299 Unit::setTimeUnit(time);
300 Unit::setMassUnit(mass);
301 Unit::setTemperatureUnit(temperature);
302 Unit::setCurrentUnit(current);
303 Unit::setAmountUnit(amount);
304 Unit::setLuminousIntensityUnit(luminousintensity);
305
306 // Update Constants to desired system units
308 }
309 catch (std::runtime_error &e)
310 {
311 Util::Exception(INFO, "Error in setting system units: ", e.what());
312 }
313
314 //
315 // This is some logic to unit-ize the geometry.prob_lo, geometry.prob_hi input variables/
316 // We also do some checking to make sure the geometry is valid.
317 //
318 // Note that here, unlike most places, we actually **replace and overwrite** the
319 // geom.prob_* variables, since they are read deep inside amrex infrastructure.
320 //
321 {
322 IO::ParmParse pp("geometry");
323
324 if (IO::ParmParse::InTraversalMode() || pp.contains("prob_lo"))
325 {
326 std::vector<Set::Scalar> prob_lo, prob_hi;
327 // Location of the lower+left+bottom corner
328 pp.queryarr_required("prob_lo", prob_lo, Unit::Length());
329 // Location of the upper_right_top corner
330 pp.queryarr_required("prob_hi", prob_hi, Unit::Length());
331 pp.remove("prob_lo");
332 pp.remove("prob_hi");
333
334 Util::Assert( INFO,TEST(prob_lo[0] < prob_hi[0]),
335 "Invalid domain specified: ", prob_lo[0], " < x < ", prob_hi[0], " is incorrect.");
336 Util::Assert( INFO,TEST(prob_lo[1] < prob_hi[1]),
337 "Invalid domain specified: ", prob_lo[0], " < y < ", prob_hi[0], " is incorrect.");
338#if AMREX_SPACEDIM>2
339 Util::Assert( INFO,TEST(prob_lo[2] < prob_hi[2]),
340 "Invalid domain specified: ", prob_lo[0], " < z < ", prob_hi[0], " is incorrect.");
341#endif
342
343 Util::DebugMessage(INFO,"Domain lower left corner: ", Set::Vector(prob_lo.data()).transpose());
344 Util::DebugMessage(INFO,"Domain upper right corenr: ", Set::Vector(prob_hi.data()).transpose());
345
346 pp.addarr("prob_lo",prob_lo);
347 pp.addarr("prob_hi",prob_hi);
348 }
349 }
350
351
352 // This allows the user to ignore certain arguments that
353 // would otherwise cause problems.
354 // Most generally this is used in the event of a "above inputs
355 // specified but not used" error.
356 // The primary purpose of this was to fix those errors that arise
357 // in regression tests.
358
359 {
360 IO::ParmParse pp;
361 std::vector<std::string> ignore;
362 if (pp.contains("ignore")) Util::Message(INFO, "Ignore directive detected");
363 pp.queryarr("ignore", ignore); // Space-separated list of entries to ignore
364 for (unsigned int i = 0; i < ignore.size(); i++)
365 {
366 Util::Message(INFO, "ignoring ", ignore[i]);
367 pp.remove(ignore[i].c_str());
368 }
369 }
370}
371
373{
375 {
377 }
378 else
379 {
380 std::string filename = GetFileName();
381 if (filename != "")
383 }
384 amrex::Finalize();
385 finalized = true;
386}
387
388
389
390AMREX_GPU_HOST_DEVICE
391void
392Abort (const char * msg)
393{
394 AMREX_IF_ON_HOST((Terminate(msg, SIGABRT, true);))
395 AMREX_IF_ON_DEVICE((amrex::Abort();))
396}
397
398void
399Terminate(const char * /* msg */, int signal, bool /*backtrace*/)
400{
401 SignalHandler(signal);
402}
403
404std::pair<std::string,std::string>
405CreateCleanDirectory (const std::string &path, bool callbarrier)
406{
407 std::pair<std::string,std::string> ret("","");
408
409 if(amrex::ParallelDescriptor::IOProcessor()) {
410 if(amrex::FileExists(path)) {
411 std::time_t t = std::time(0);
412 std::tm * now = std::localtime(&t);
413 int year = now->tm_year+1900;
414 int month = now->tm_mon+1;
415 int day = now->tm_mday;
416 int hour = now->tm_hour;
417 int minute = now->tm_min;
418 int second = now->tm_sec;
419
420 std::stringstream ss;
421 ss << year
422 << std::setfill('0') << std::setw(2) << month
423 << std::setfill('0') << std::setw(2) << day
424 << std::setfill('0') << std::setw(2) << hour
425 << std::setfill('0') << std::setw(2) << minute
426 << std::setfill('0') << std::setw(2) << second;
427
428 std::string newoldname(path + ".old." + ss.str());
429 if (amrex::system::verbose) {
430 amrex::Print() << "Util::CreateCleanDirectory(): " << path
431 << " exists. Renaming to: " << newoldname << std::endl;
432 }
433 std::rename(path.c_str(), newoldname.c_str());
434 ret.first = path;
435 ret.second = newoldname;
436 }
437 if( ! amrex::UtilCreateDirectory(path, 0755)) {
438 amrex::CreateDirectoryFailed(path);
439 }
440 }
441 if(callbarrier) {
442 // Force other processors to wait until directory is built.
443 amrex::ParallelDescriptor::Barrier("amrex::UtilCreateCleanDirectory");
444 }
445 return ret;
446}
447
448
449namespace Test
450{
451int Message(std::string testname)
452{
453 if (amrex::ParallelDescriptor::IOProcessor())
454 std::cout << std::left
455 << Color::FG::White << Color::Bold << testname << Color::Reset << std::endl;
456 return 0;
457}
458int Message(std::string testname, int failed)
459{
460 if (amrex::ParallelDescriptor::IOProcessor())
461 {
462 winsize w;
463 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
464 std::stringstream ss;
465 if (!failed)
466 ss << "[" << Color::FG::Green << Color::Bold << "PASS" << Color::Reset << "]";
467 else
468 ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
469
470 int terminalwidth = 80; //std::min(w.ws_col,(short unsigned int) 100);
471
472 std::cout << std::left
473 << testname
474 << std::setw(terminalwidth - testname.size() + ss.str().size() - 6) << std::right << std::setfill('.') << ss.str() << std::endl;
475 }
476 return failed;
477}
478int SubMessage(std::string testname, int failed)
479{
480 if (amrex::ParallelDescriptor::IOProcessor())
481 {
482 winsize w;
483 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
484 std::stringstream ss;
485 if (!failed)
486 ss << "[" << Color::FG::LightGreen << Color::Bold << "PASS" << Color::Reset << "]";
487 else
488 ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
489
490 int terminalwidth = 80;
491
492 std::cout << std::left
493 << " ├ "
494 << testname
495 << std::setw(terminalwidth - testname.size() + ss.str().size() - 12) << std::right << std::setfill('.') << ss.str() << std::endl;
496 }
497 return failed;
498}
499void SubWarning(std::string testname)
500{
501 if (amrex::ParallelDescriptor::IOProcessor())
502 {
503 winsize w;
504 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
505 std::stringstream ss;
506 ss << "[" << Color::FG::LightYellow << Color::Bold << "WARN" << Color::Reset << "]";
507
508 int terminalwidth = 80;
509
510 std::cout << std::left
511 << " ├ "
512 << testname
513 << std::setw(terminalwidth - testname.size() + ss.str().size() - 12) << std::right << std::setfill('.') << ss.str() << std::endl;
514 }
515}
516int SubFinalMessage(int failed)
517{
518 if (amrex::ParallelDescriptor::IOProcessor())
519 {
520 winsize w;
521 ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
522 std::stringstream ss;
523 std::cout << std::left << " └ ";
524
525 if (!failed)
526 std::cout << Color::FG::Green << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
527 else
528 std::cout << Color::FG::Red << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
529 }
530 return failed;
531}
532
533}
534
535void AverageCellcenterToNode(amrex::MultiFab& node_mf, const int &dcomp, const amrex::MultiFab &cell_mf, const int &scomp, const int &ncomp/*, const int ngrow=0*/)
536{
537 Util::Assert(INFO,TEST(dcomp + ncomp <= node_mf.nComp()));
538 Util::Assert(INFO,TEST(scomp + ncomp <= cell_mf.nComp()));
539 //Util::Assert(INFO,TEST(cell_mf.boxArray() == node_mf.boxArray()));
540 Util::Assert(INFO,TEST(cell_mf.DistributionMap() == cell_mf.DistributionMap()));
541 Util::Assert(INFO,TEST(cell_mf.nGrow() > 0));
542 for (amrex::MFIter mfi(node_mf,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
543 {
544 amrex::Box bx = mfi.nodaltilebox();
545 amrex::Array4<Set::Scalar> const& node = node_mf.array(mfi);
546 amrex::Array4<const Set::Scalar> const& cell = cell_mf.array(mfi);
547 for (int n = 0; n < ncomp; n++)
548 amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
549 node(i,j,k,dcomp+n) = Numeric::Interpolate::CellToNodeAverage(cell,i,j,k,scomp+n);
550 });
551 }
552}
553
554
555}
std::time_t t
#define TEST(x)
Definition Util.H:25
#define INFO
Definition Util.H:24
void forbid(std::string name, std::string explanation, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:301
static void SetTraversalMode(bool enabled)
Definition ParmParse.cpp:8
int queryarr_required(std::string name, std::vector< T > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1223
int queryarr(std::string name, std::vector< T > &value, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:1024
static void SetTraversalOutputFile(std::string path)
Definition ParmParse.cpp:38
int query_default(std::string name, T &value, T defaultvalue, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:492
static const std::string & TraversalOutputFile()
Definition ParmParse.cpp:44
static void WriteInputTreeJsonFile(const std::string &path)
Definition ParmParse.cpp:56
static bool InTraversalMode()
Definition ParmParse.cpp:14
bool contains(std::string name, const std::source_location &location=std::source_location::current())
Definition ParmParse.H:318
static std::string LightYellow
Definition Color.H:30
static std::string Green
Definition Color.H:21
static std::string LightGreen
Definition Color.H:29
static std::string Red
Definition Color.H:20
static std::string White
Definition Color.H:34
static std::string Bold
Definition Color.H:9
static std::string Reset
Definition Color.H:8
void WriteMetaData(std::string plot_file, Status status, int per)
void FileNameParse(std::string &filename)
Internal function to do processing of the file name.
@ Segfault
@ Complete
@ Running
@ Interrupt
@ Abort
void SetGlobalConstants()
Definition Set.cpp:19
Eigen::Matrix< amrex::Real, AMREX_SPACEDIM, 1 > Vector
Definition Base.H:21
Definition GB.H:8
int Message(std::string testname)
Definition Util.cpp:451
int SubMessage(std::string testname, int failed)
Definition Util.cpp:478
int SubFinalMessage(int failed)
Definition Util.cpp:516
void SubWarning(std::string testname)
Definition Util.cpp:499
A collection of utility routines.
Definition Set.cpp:33
std::pair< std::string, std::string > CreateCleanDirectory(const std::string &path, bool callbarrier)
Definition Util.cpp:405
void DebugMessage(std::string, std::string, int, Args const &...)
Definition Util.H:187
std::string GetFileName()
Definition Util.cpp:121
bool finalized
Definition Util.cpp:119
std::string globalprefix
Definition Util.cpp:116
void Finalize()
Definition Util.cpp:372
std::string filename
Definition Util.cpp:115
void AverageCellcenterToNode(amrex::MultiFab &node_mf, const int &dcomp, const amrex::MultiFab &cell_mf, const int &scomp, const int &ncomp)
Definition Util.cpp:535
bool initialized
Definition Util.cpp:118
AMREX_FORCE_INLINE AMREX_GPU_HOST_DEVICE void Assert(const char *file, const char *func, int line, const char *smt, bool pass, Args const &... args)
Definition Util.H:60
std::pair< std::string, std::string > file_overwrite
Definition Util.cpp:117
void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
Definition Util.cpp:139
void Initialize()
Definition Util.cpp:218
std::pair< std::string, std::string > GetOverwrittenFile()
Definition Util.cpp:183
void Message(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:140
AMREX_GPU_HOST_DEVICE void Abort(const char *msg)
Definition Util.cpp:392
void Exception(std::string file, std::string func, int line, Args const &... args)
Definition Util.H:237
void Terminate(const char *, int signal, bool)
Definition Util.cpp:399
void SignalHandler(int s)
Definition Util.cpp:188
AMREX_GPU_HOST_DEVICE static AMREX_FORCE_INLINE T CellToNodeAverage(const amrex::Array4< const T > &f, const int &i, const int &j, const int &k, const int &m, std::array< StencilType, AMREX_SPACEDIM > stencil=DefaultType())
Definition Stencil.H:1396
static void setTimeUnit(std::string unit)
Definition Unit.H:377
static void setLuminousIntensityUnit(std::string unit)
Definition Unit.H:417
static void setLengthUnit(std::string unit)
Definition Unit.H:369
static void setMassUnit(std::string unit)
Definition Unit.H:385
static void setTemperatureUnit(std::string unit)
Definition Unit.H:393
static void setCurrentUnit(std::string unit)
Definition Unit.H:401
static void setAmountUnit(std::string unit)
Definition Unit.H:409
static Unit Length()
Definition Unit.H:198