Line data Source code
1 : #include "Util.H"
2 : #include "Color.H"
3 :
4 : #include <chrono>
5 : #include <cstdlib>
6 : #include <filesystem>
7 : #include <stdexcept>
8 :
9 : #include "AMReX_ParallelDescriptor.H"
10 : #include "AMReX_Utility.H"
11 :
12 : #include "IO/ParmParse.H"
13 : #include "IO/WriteMetaData.H"
14 : #include "IO/FileNameParse.H"
15 : #include "Color.H"
16 : #include "Numeric/Stencil.H"
17 :
18 : namespace Util
19 : {
20 :
21 : std::string filename = "";
22 : std::string globalprefix = "";
23 : std::pair<std::string,std::string> file_overwrite;
24 : bool initialized = false;
25 : bool finalized = false;
26 :
27 121 : std::string GetFileName()
28 : {
29 121 : if (filename == "")
30 : {
31 41 : IO::ParmParse pp;
32 41 : IO::ParmParse pp_amr("amr");
33 :
34 123 : if (pp_amr.contains("plot_file") && pp.contains("plot_file"))
35 0 : Util::Abort("plot_file specified in too many locations");
36 82 : else if (pp_amr.contains("plot_file"))
37 : {
38 0 : if (amrex::ParallelDescriptor::IOProcessor())
39 : amrex::Warning("amr.plot_file will be depricated; use plot_file instead");
40 0 : pp_amr.query("plot_file", filename);
41 :
42 : }
43 82 : else if (pp.contains("plot_file"))
44 : {
45 41 : pp_query("plot_file", filename); // Name of directory containing all output data
46 : }
47 41 : IO::FileNameParse(filename);
48 : // else
49 : // if (amrex::ParallelDescriptor::IOProcessor())
50 : // Util::Abort("No plot file specified! (Specify plot_file = \"plot_file_name\" in input file");
51 41 : }
52 121 : return filename;
53 : }
54 2 : void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
55 : {
56 : try
57 : {
58 2 : if (filename == "")
59 0 : Util::Exception(INFO,"Cannot back up files yet because the output directory has not been specified");
60 :
61 2 : std::string basefilename = std::filesystem::path(a_path).filename();
62 2 : std::string absolutepath = std::filesystem::absolute(std::filesystem::path(a_path)).string();
63 2 : std::string abspathfilename = absolutepath;
64 2 : std::replace(abspathfilename.begin(),abspathfilename.end(),'/','_');
65 2 : if (prefix != "")
66 : {
67 2 : abspathfilename = prefix + "__" + abspathfilename;
68 2 : basefilename = prefix + "__" + abspathfilename;
69 : }
70 :
71 2 : if (amrex::ParallelDescriptor::IOProcessor())
72 : {
73 2 : std::string destinationpath;
74 2 : if (fullpath) destinationpath = filename+"/"+abspathfilename;
75 0 : else destinationpath = filename+"/"+basefilename;
76 :
77 : // Copy the file where the file name is the absolute path, with / replaced with _
78 2 : if (std::filesystem::exists(destinationpath))
79 0 : Util::Exception(INFO,"Trying to copy ",destinationpath," but it already exists.");
80 2 : std::filesystem::copy_file(a_path,destinationpath);
81 2 : }
82 2 : }
83 0 : catch (std::filesystem::filesystem_error const& ex)
84 : {
85 0 : Util::Exception(INFO,
86 : "file system error: \n",
87 0 : " what(): " , ex.what() , '\n',
88 0 : " path1(): " , ex.path1() , '\n',
89 0 : " path2(): " , ex.path2() , '\n',
90 0 : " code().value(): " , ex.code().value() , '\n',
91 0 : " code().message(): " , ex.code().message() , '\n',
92 0 : " code().category(): " , ex.code().category().name());
93 0 : }
94 2 : }
95 :
96 0 : std::pair<std::string,std::string> GetOverwrittenFile()
97 : {
98 0 : return file_overwrite;
99 : }
100 :
101 0 : void SignalHandler(int s)
102 : {
103 0 : if (amrex::ParallelDescriptor::IOProcessor())
104 : {
105 0 : std::string filename = GetFileName();
106 0 : IO::Status status = IO::Status::Running;
107 0 : if (s == SIGSEGV) status = IO::Status::Segfault;
108 0 : else if (s == SIGINT) status = IO::Status::Interrupt;
109 0 : if (s == SIGABRT) status = IO::Status::Abort;
110 0 : if (filename != "")
111 0 : IO::WriteMetaData(filename,status);
112 0 : }
113 :
114 : #ifdef MEME
115 : IO::ParmParse pp;
116 : if (!pp.contains("nomeme"))
117 : {
118 : time_t timer; time(&timer);
119 : std::stringstream cmd;
120 : cmd << "xdg-open " << BUILD_DIR << "/src/Util/Meme/cat0" << (1+((int)timer)%6) << ".gif &";
121 : std::system(cmd.str().c_str());
122 : 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!)";
123 : }
124 : #endif
125 :
126 0 : amrex::BLBackTrace::handler(s);
127 0 : }
128 :
129 :
130 0 : void Initialize ()
131 : {
132 0 : int argc = 0;
133 0 : char **argv = nullptr;
134 0 : Initialize(argc,argv);
135 0 : initialized = true;
136 0 : }
137 41 : void Initialize (int argc, char* argv[])
138 : {
139 41 : srand (time(NULL));
140 :
141 41 : amrex::Initialize(argc, argv);
142 :
143 41 : IO::ParmParse pp_amrex("amrex");
144 41 : pp_amrex.add("throw_exception",1);
145 : //amrex.throw_exception=1
146 :
147 41 : signal(SIGSEGV, Util::SignalHandler);
148 41 : signal(SIGINT, Util::SignalHandler);
149 41 : signal(SIGABRT, Util::SignalHandler);
150 :
151 41 : std::string filename = GetFileName();
152 :
153 41 : if (amrex::ParallelDescriptor::IOProcessor() && filename != "")
154 : {
155 41 : file_overwrite = Util::CreateCleanDirectory(filename, false);
156 41 : IO::WriteMetaData(filename);
157 : }
158 :
159 41 : IO::ParmParse pp;
160 41 : std::string length, time, mass, temperature, current, amount, luminousintensity;
161 : // Set the system length unit
162 82 : pp.query_default("system.length",length,"m");
163 : // Set the system time unit
164 82 : pp.query_default("system.time",time,"s");
165 : // Set the system mass unit
166 82 : pp.query_default("system.mass",mass,"kg");
167 : // Set the system temperature unit
168 82 : pp.query_default("system.temperature",temperature,"K");
169 : // Set the system current unit
170 82 : pp.query_default("system.current",current,"A");
171 : // Set the system amount unit
172 82 : pp.query_default("system.amount",amount,"mol");
173 : // Set the system luminous intensity unit
174 41 : pp.query_default("system.luminousintensity",luminousintensity,"cd");
175 : try
176 : {
177 41 : Unit::setLengthUnit(length);
178 41 : Unit::setTimeUnit(time);
179 41 : Unit::setMassUnit(mass);
180 41 : Unit::setTemperatureUnit(temperature);
181 41 : Unit::setCurrentUnit(current);
182 41 : Unit::setAmountUnit(amount);
183 41 : Unit::setLuminousIntensityUnit(luminousintensity);
184 :
185 : // Update Constants to desired system units
186 41 : Set::Constant::SetGlobalConstants();
187 : }
188 0 : catch (std::runtime_error &e)
189 : {
190 0 : Util::Exception(INFO, "Error in setting system units: ", e.what());
191 0 : }
192 :
193 : //
194 : // This is some logic to unit-ize the geometry.prob_lo, geometry.prob_hi input variables/
195 : // We also do some checking to make sure the geometry is valid.
196 : //
197 : // Note that here, unlike most places, we actually **replace and overwrite** the
198 : // geom.prob_* variables, since they are read deep inside amrex infrastructure.
199 : //
200 : {
201 82 : IO::ParmParse pp("geometry");
202 :
203 82 : if (pp.contains("prob_lo"))
204 : {
205 39 : std::vector<Set::Scalar> prob_lo, prob_hi;
206 : // Location of the lower+left+bottom corner
207 78 : pp.queryarr("prob_lo", prob_lo, Unit::Length());
208 : // Location of the upper_right_top corner
209 78 : pp.queryarr("prob_hi", prob_hi, Unit::Length());
210 39 : pp.remove("prob_lo");
211 39 : pp.remove("prob_hi");
212 :
213 273 : Util::Assert( INFO,TEST(prob_lo[0] < prob_hi[0]),
214 39 : "Invalid domain specified: ", prob_lo[0], " < x < ", prob_hi[0], " is incorrect.");
215 273 : Util::Assert( INFO,TEST(prob_lo[1] < prob_hi[1]),
216 39 : "Invalid domain specified: ", prob_lo[0], " < y < ", prob_hi[0], " is incorrect.");
217 : #if AMREX_SPACEDIM>2
218 21 : Util::Assert( INFO,TEST(prob_lo[2] < prob_hi[2]),
219 3 : "Invalid domain specified: ", prob_lo[0], " < z < ", prob_hi[0], " is incorrect.");
220 : #endif
221 :
222 156 : Util::DebugMessage(INFO,"Domain lower left corner: ", Set::Vector(prob_lo.data()).transpose());
223 156 : Util::DebugMessage(INFO,"Domain upper right corenr: ", Set::Vector(prob_hi.data()).transpose());
224 :
225 39 : pp.addarr("prob_lo",prob_lo);
226 39 : pp.addarr("prob_hi",prob_hi);
227 39 : }
228 41 : }
229 41 : }
230 :
231 41 : void Finalize()
232 : {
233 41 : std::string filename = GetFileName();
234 41 : if (filename != "")
235 41 : IO::WriteMetaData(filename,IO::Status::Complete);
236 41 : amrex::Finalize();
237 41 : finalized = true;
238 41 : }
239 :
240 :
241 :
242 : void
243 0 : Abort (const char * msg) { Terminate(msg, SIGABRT, true); }
244 :
245 : void
246 0 : Terminate(const char * /* msg */, int signal, bool /*backtrace*/)
247 : {
248 0 : SignalHandler(signal);
249 0 : }
250 :
251 : std::pair<std::string,std::string>
252 41 : CreateCleanDirectory (const std::string &path, bool callbarrier)
253 : {
254 41 : std::pair<std::string,std::string> ret("","");
255 :
256 41 : if(amrex::ParallelDescriptor::IOProcessor()) {
257 41 : if(amrex::FileExists(path)) {
258 0 : std::time_t t = std::time(0);
259 0 : std::tm * now = std::localtime(&t);
260 0 : int year = now->tm_year+1900;
261 0 : int month = now->tm_mon+1;
262 0 : int day = now->tm_mday;
263 0 : int hour = now->tm_hour;
264 0 : int minute = now->tm_min;
265 0 : int second = now->tm_sec;
266 :
267 0 : std::stringstream ss;
268 : ss << year
269 0 : << std::setfill('0') << std::setw(2) << month
270 0 : << std::setfill('0') << std::setw(2) << day
271 0 : << std::setfill('0') << std::setw(2) << hour
272 0 : << std::setfill('0') << std::setw(2) << minute
273 0 : << std::setfill('0') << std::setw(2) << second;
274 :
275 0 : std::string newoldname(path + ".old." + ss.str());
276 0 : if (amrex::system::verbose) {
277 0 : amrex::Print() << "Util::CreateCleanDirectory(): " << path
278 0 : << " exists. Renaming to: " << newoldname << std::endl;
279 : }
280 0 : std::rename(path.c_str(), newoldname.c_str());
281 0 : ret.first = path;
282 0 : ret.second = newoldname;
283 0 : }
284 41 : if( ! amrex::UtilCreateDirectory(path, 0755)) {
285 0 : amrex::CreateDirectoryFailed(path);
286 : }
287 : }
288 41 : if(callbarrier) {
289 : // Force other processors to wait until directory is built.
290 0 : amrex::ParallelDescriptor::Barrier("amrex::UtilCreateCleanDirectory");
291 : }
292 41 : return ret;
293 0 : }
294 :
295 :
296 : namespace Test
297 : {
298 34 : int Message(std::string testname)
299 : {
300 34 : if (amrex::ParallelDescriptor::IOProcessor())
301 34 : std::cout << std::left
302 34 : << Color::FG::White << Color::Bold << testname << Color::Reset << std::endl;
303 34 : return 0;
304 : }
305 0 : int Message(std::string testname, int failed)
306 : {
307 0 : if (amrex::ParallelDescriptor::IOProcessor())
308 : {
309 : winsize w;
310 0 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
311 0 : std::stringstream ss;
312 0 : if (!failed)
313 0 : ss << "[" << Color::FG::Green << Color::Bold << "PASS" << Color::Reset << "]";
314 : else
315 0 : ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
316 :
317 0 : int terminalwidth = 80; //std::min(w.ws_col,(short unsigned int) 100);
318 :
319 0 : std::cout << std::left
320 : << testname
321 0 : << std::setw(terminalwidth - testname.size() + ss.str().size() - 6) << std::right << std::setfill('.') << ss.str() << std::endl;
322 0 : }
323 0 : return failed;
324 : }
325 136 : int SubMessage(std::string testname, int failed)
326 : {
327 136 : if (amrex::ParallelDescriptor::IOProcessor())
328 : {
329 : winsize w;
330 136 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
331 136 : std::stringstream ss;
332 136 : if (!failed)
333 136 : ss << "[" << Color::FG::LightGreen << Color::Bold << "PASS" << Color::Reset << "]";
334 : else
335 0 : ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
336 :
337 136 : int terminalwidth = 80;
338 :
339 136 : std::cout << std::left
340 : << " ├ "
341 : << testname
342 136 : << std::setw(terminalwidth - testname.size() + ss.str().size() - 12) << std::right << std::setfill('.') << ss.str() << std::endl;
343 136 : }
344 136 : return failed;
345 : }
346 32 : int SubFinalMessage(int failed)
347 : {
348 32 : if (amrex::ParallelDescriptor::IOProcessor())
349 : {
350 : winsize w;
351 32 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
352 32 : std::stringstream ss;
353 32 : std::cout << std::left << " └ ";
354 :
355 32 : if (!failed)
356 32 : std::cout << Color::FG::Green << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
357 : else
358 0 : std::cout << Color::FG::Red << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
359 32 : }
360 32 : return failed;
361 : }
362 :
363 : }
364 :
365 62 : void AverageCellcenterToNode(amrex::MultiFab& node_mf, const int &dcomp, const amrex::MultiFab &cell_mf, const int &scomp, const int &ncomp/*, const int ngrow=0*/)
366 : {
367 434 : Util::Assert(INFO,TEST(dcomp + ncomp <= node_mf.nComp()));
368 434 : Util::Assert(INFO,TEST(scomp + ncomp <= cell_mf.nComp()));
369 : //Util::Assert(INFO,TEST(cell_mf.boxArray() == node_mf.boxArray()));
370 434 : Util::Assert(INFO,TEST(cell_mf.DistributionMap() == cell_mf.DistributionMap()));
371 434 : Util::Assert(INFO,TEST(cell_mf.nGrow() > 0));
372 269 : for (amrex::MFIter mfi(node_mf,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
373 : {
374 207 : amrex::Box bx = mfi.nodaltilebox();
375 207 : amrex::Array4<Set::Scalar> const& node = node_mf.array(mfi);
376 207 : amrex::Array4<const Set::Scalar> const& cell = cell_mf.array(mfi);
377 414 : for (int n = 0; n < ncomp; n++)
378 207 : amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
379 212934 : node(i,j,k,dcomp+n) = Numeric::Interpolate::CellToNodeAverage(cell,i,j,k,scomp+n);
380 106467 : });
381 62 : }
382 62 : }
383 :
384 :
385 : }
|