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 115 : std::string GetFileName()
28 : {
29 115 : if (filename == "")
30 : {
31 39 : IO::ParmParse pp;
32 39 : IO::ParmParse pp_amr("amr");
33 :
34 117 : if (pp_amr.contains("plot_file") && pp.contains("plot_file"))
35 0 : Util::Abort("plot_file specified in too many locations");
36 78 : 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 78 : else if (pp.contains("plot_file"))
44 : {
45 39 : pp_query("plot_file", filename); // Name of directory containing all output data
46 : }
47 39 : 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 39 : }
52 115 : 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 39 : void Initialize (int argc, char* argv[])
138 : {
139 39 : srand (time(NULL));
140 :
141 39 : amrex::Initialize(argc, argv);
142 :
143 39 : IO::ParmParse pp_amrex("amrex");
144 39 : pp_amrex.add("throw_exception",1);
145 : //amrex.throw_exception=1
146 :
147 39 : signal(SIGSEGV, Util::SignalHandler);
148 39 : signal(SIGINT, Util::SignalHandler);
149 39 : signal(SIGABRT, Util::SignalHandler);
150 :
151 39 : std::string filename = GetFileName();
152 :
153 39 : if (amrex::ParallelDescriptor::IOProcessor() && filename != "")
154 : {
155 39 : file_overwrite = Util::CreateCleanDirectory(filename, false);
156 39 : IO::WriteMetaData(filename);
157 : }
158 :
159 39 : IO::ParmParse pp;
160 39 : std::string length, time;
161 : // Set the system length unit
162 78 : pp.query_default("system.length",length,"m");
163 : // Set the system time unit
164 39 : pp.query_default("system.time",time,"s");
165 : try
166 : {
167 39 : Unit::setLengthUnit(length);
168 39 : Unit::setTimeUnit(time);
169 : }
170 0 : catch (std::runtime_error &e)
171 : {
172 0 : Util::Exception(INFO, "Error in setting system units: ", e.what());
173 0 : }
174 :
175 : //
176 : // This is some logic to unit-ize the geometry.prob_lo, geometry.prob_hi input variables/
177 : // We also do some checking to make sure the geometry is valid.
178 : //
179 : // Note that here, unlike most places, we actually **replace and overwrite** the
180 : // geom.prob_* variables, since they are read deep inside amrex infrastructure.
181 : //
182 : {
183 78 : IO::ParmParse pp("geometry");
184 :
185 78 : if (pp.contains("prob_lo"))
186 : {
187 37 : std::vector<Set::Scalar> prob_lo, prob_hi;
188 : // Location of the lower+left+bottom corner
189 74 : pp.queryarr("prob_lo", prob_lo, Unit::Length());
190 : // Location of the upper_right_top corner
191 74 : pp.queryarr("prob_hi", prob_hi, Unit::Length());
192 37 : pp.remove("prob_lo");
193 37 : pp.remove("prob_hi");
194 :
195 259 : Util::Assert( INFO,TEST(prob_lo[0] < prob_hi[0]),
196 37 : "Invalid domain specified: ", prob_lo[0], " < x < ", prob_hi[0], " is incorrect.");
197 259 : Util::Assert( INFO,TEST(prob_lo[1] < prob_hi[1]),
198 37 : "Invalid domain specified: ", prob_lo[0], " < y < ", prob_hi[0], " is incorrect.");
199 : #if AMREX_SPACEDIM>2
200 21 : Util::Assert( INFO,TEST(prob_lo[2] < prob_hi[2]),
201 3 : "Invalid domain specified: ", prob_lo[0], " < z < ", prob_hi[0], " is incorrect.");
202 : #endif
203 :
204 148 : Util::DebugMessage(INFO,"Domain lower left corner: ", Set::Vector(prob_lo.data()).transpose());
205 148 : Util::DebugMessage(INFO,"Domain upper right corenr: ", Set::Vector(prob_hi.data()).transpose());
206 :
207 37 : pp.addarr("prob_lo",prob_lo);
208 37 : pp.addarr("prob_hi",prob_hi);
209 37 : }
210 39 : }
211 39 : }
212 :
213 39 : void Finalize()
214 : {
215 39 : std::string filename = GetFileName();
216 39 : if (filename != "")
217 39 : IO::WriteMetaData(filename,IO::Status::Complete);
218 39 : amrex::Finalize();
219 39 : finalized = true;
220 39 : }
221 :
222 :
223 :
224 : void
225 0 : Abort (const char * msg) { Terminate(msg, SIGABRT, true); }
226 :
227 : void
228 0 : Terminate(const char * /* msg */, int signal, bool /*backtrace*/)
229 : {
230 0 : SignalHandler(signal);
231 0 : }
232 :
233 : std::pair<std::string,std::string>
234 39 : CreateCleanDirectory (const std::string &path, bool callbarrier)
235 : {
236 39 : std::pair<std::string,std::string> ret("","");
237 :
238 39 : if(amrex::ParallelDescriptor::IOProcessor()) {
239 39 : if(amrex::FileExists(path)) {
240 0 : std::time_t t = std::time(0);
241 0 : std::tm * now = std::localtime(&t);
242 0 : int year = now->tm_year+1900;
243 0 : int month = now->tm_mon+1;
244 0 : int day = now->tm_mday;
245 0 : int hour = now->tm_hour;
246 0 : int minute = now->tm_min;
247 0 : int second = now->tm_sec;
248 :
249 0 : std::stringstream ss;
250 : ss << year
251 0 : << std::setfill('0') << std::setw(2) << month
252 0 : << std::setfill('0') << std::setw(2) << day
253 0 : << std::setfill('0') << std::setw(2) << hour
254 0 : << std::setfill('0') << std::setw(2) << minute
255 0 : << std::setfill('0') << std::setw(2) << second;
256 :
257 0 : std::string newoldname(path + ".old." + ss.str());
258 0 : if (amrex::system::verbose) {
259 0 : amrex::Print() << "Util::CreateCleanDirectory(): " << path
260 0 : << " exists. Renaming to: " << newoldname << std::endl;
261 : }
262 0 : std::rename(path.c_str(), newoldname.c_str());
263 0 : ret.first = path;
264 0 : ret.second = newoldname;
265 0 : }
266 39 : if( ! amrex::UtilCreateDirectory(path, 0755)) {
267 0 : amrex::CreateDirectoryFailed(path);
268 : }
269 : }
270 39 : if(callbarrier) {
271 : // Force other processors to wait until directory is built.
272 0 : amrex::ParallelDescriptor::Barrier("amrex::UtilCreateCleanDirectory");
273 : }
274 39 : return ret;
275 0 : }
276 :
277 :
278 : namespace Test
279 : {
280 32 : int Message(std::string testname)
281 : {
282 32 : if (amrex::ParallelDescriptor::IOProcessor())
283 32 : std::cout << std::left
284 32 : << Color::FG::White << Color::Bold << testname << Color::Reset << std::endl;
285 32 : return 0;
286 : }
287 0 : int Message(std::string testname, int failed)
288 : {
289 0 : if (amrex::ParallelDescriptor::IOProcessor())
290 : {
291 : winsize w;
292 0 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
293 0 : std::stringstream ss;
294 0 : if (!failed)
295 0 : ss << "[" << Color::FG::Green << Color::Bold << "PASS" << Color::Reset << "]";
296 : else
297 0 : ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
298 :
299 0 : int terminalwidth = 80; //std::min(w.ws_col,(short unsigned int) 100);
300 :
301 0 : std::cout << std::left
302 : << testname
303 0 : << std::setw(terminalwidth - testname.size() + ss.str().size() - 6) << std::right << std::setfill('.') << ss.str() << std::endl;
304 0 : }
305 0 : return failed;
306 : }
307 134 : int SubMessage(std::string testname, int failed)
308 : {
309 134 : if (amrex::ParallelDescriptor::IOProcessor())
310 : {
311 : winsize w;
312 134 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
313 134 : std::stringstream ss;
314 134 : if (!failed)
315 134 : ss << "[" << Color::FG::LightGreen << Color::Bold << "PASS" << Color::Reset << "]";
316 : else
317 0 : ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
318 :
319 134 : int terminalwidth = 80;
320 :
321 134 : std::cout << std::left
322 : << " ├ "
323 : << testname
324 134 : << std::setw(terminalwidth - testname.size() + ss.str().size() - 12) << std::right << std::setfill('.') << ss.str() << std::endl;
325 134 : }
326 134 : return failed;
327 : }
328 32 : int SubFinalMessage(int failed)
329 : {
330 32 : if (amrex::ParallelDescriptor::IOProcessor())
331 : {
332 : winsize w;
333 32 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
334 32 : std::stringstream ss;
335 32 : std::cout << std::left << " └ ";
336 :
337 32 : if (!failed)
338 32 : std::cout << Color::FG::Green << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
339 : else
340 0 : std::cout << Color::FG::Red << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
341 32 : }
342 32 : return failed;
343 : }
344 :
345 : }
346 :
347 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*/)
348 : {
349 434 : Util::Assert(INFO,TEST(dcomp + ncomp <= node_mf.nComp()));
350 434 : Util::Assert(INFO,TEST(scomp + ncomp <= cell_mf.nComp()));
351 : //Util::Assert(INFO,TEST(cell_mf.boxArray() == node_mf.boxArray()));
352 434 : Util::Assert(INFO,TEST(cell_mf.DistributionMap() == cell_mf.DistributionMap()));
353 434 : Util::Assert(INFO,TEST(cell_mf.nGrow() > 0));
354 269 : for (amrex::MFIter mfi(node_mf,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
355 : {
356 207 : amrex::Box bx = mfi.nodaltilebox();
357 207 : amrex::Array4<Set::Scalar> const& node = node_mf.array(mfi);
358 207 : amrex::Array4<const Set::Scalar> const& cell = cell_mf.array(mfi);
359 414 : for (int n = 0; n < ncomp; n++)
360 207 : amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
361 212934 : node(i,j,k,dcomp+n) = Numeric::Interpolate::CellToNodeAverage(cell,i,j,k,scomp+n);
362 106467 : });
363 62 : }
364 62 : }
365 :
366 :
367 : }
|