Line data Source code
1 : #include "Util.H"
2 : #include "Color.H"
3 :
4 : #include <chrono>
5 : #include <filesystem>
6 :
7 : #include "AMReX_ParallelDescriptor.H"
8 : #include "AMReX_Utility.H"
9 :
10 : #include "IO/ParmParse.H"
11 : #include "IO/WriteMetaData.H"
12 : #include "IO/FileNameParse.H"
13 : #include "Color.H"
14 : #include "Numeric/Stencil.H"
15 :
16 : namespace Util
17 : {
18 :
19 : std::string filename = "";
20 : std::string globalprefix = "";
21 : std::pair<std::string,std::string> file_overwrite;
22 : bool initialized = false;
23 : bool finalized = false;
24 :
25 205 : std::string GetFileName()
26 : {
27 205 : if (filename == "")
28 : {
29 69 : IO::ParmParse pp;
30 69 : IO::ParmParse pp_amr("amr");
31 :
32 207 : if (pp_amr.contains("plot_file") && pp.contains("plot_file"))
33 0 : Util::Abort("plot_file specified in too many locations");
34 138 : else if (pp_amr.contains("plot_file"))
35 : {
36 0 : if (amrex::ParallelDescriptor::IOProcessor())
37 : amrex::Warning("amr.plot_file will be depricated; use plot_file instead");
38 0 : pp_amr.query("plot_file", filename);
39 :
40 : }
41 138 : else if (pp.contains("plot_file"))
42 : {
43 69 : pp_query("plot_file", filename); // Name of directory containing all output data
44 : }
45 69 : IO::FileNameParse(filename);
46 : // else
47 : // if (amrex::ParallelDescriptor::IOProcessor())
48 : // Util::Abort("No plot file specified! (Specify plot_file = \"plot_file_name\" in input file");
49 69 : }
50 205 : return filename;
51 : }
52 8 : void CopyFileToOutputDir(std::string a_path, bool fullpath, std::string prefix)
53 : {
54 : try
55 : {
56 8 : if (filename == "")
57 0 : Util::Exception(INFO,"Cannot back up files yet because the output directory has not been specified");
58 :
59 8 : std::string basefilename = std::filesystem::path(a_path).filename();
60 8 : std::string absolutepath = std::filesystem::absolute(std::filesystem::path(a_path)).string();
61 8 : std::string abspathfilename = absolutepath;
62 8 : std::replace(abspathfilename.begin(),abspathfilename.end(),'/','_');
63 8 : if (prefix != "")
64 : {
65 8 : abspathfilename = prefix + "__" + abspathfilename;
66 8 : basefilename = prefix + "__" + abspathfilename;
67 : }
68 :
69 8 : if (amrex::ParallelDescriptor::IOProcessor())
70 : {
71 8 : std::string destinationpath;
72 8 : if (fullpath) destinationpath = filename+"/"+abspathfilename;
73 0 : else destinationpath = filename+"/"+basefilename;
74 :
75 : // Copy the file where the file name is the absolute path, with / replaced with _
76 8 : if (std::filesystem::exists(destinationpath))
77 0 : Util::Exception(INFO,"Trying to copy ",destinationpath," but it already exists.");
78 8 : std::filesystem::copy_file(a_path,destinationpath);
79 8 : }
80 8 : }
81 0 : catch (std::filesystem::filesystem_error const& ex)
82 : {
83 0 : Util::Exception(INFO,
84 : "file system error: \n",
85 0 : " what(): " , ex.what() , '\n',
86 0 : " path1(): " , ex.path1() , '\n',
87 0 : " path2(): " , ex.path2() , '\n',
88 0 : " code().value(): " , ex.code().value() , '\n',
89 0 : " code().message(): " , ex.code().message() , '\n',
90 0 : " code().category(): " , ex.code().category().name());
91 0 : }
92 8 : }
93 :
94 0 : std::pair<std::string,std::string> GetOverwrittenFile()
95 : {
96 0 : return file_overwrite;
97 : }
98 :
99 36 : void SignalHandler(int s)
100 : {
101 36 : if (amrex::ParallelDescriptor::IOProcessor())
102 : {
103 36 : std::string filename = GetFileName();
104 36 : IO::Status status = IO::Status::Running;
105 36 : if (s == SIGSEGV) status = IO::Status::Segfault;
106 36 : else if (s == SIGINT) status = IO::Status::Interrupt;
107 36 : if (s == SIGABRT) status = IO::Status::Abort;
108 36 : if (filename != "")
109 36 : IO::WriteMetaData(filename,status);
110 36 : }
111 :
112 : #ifdef MEME
113 : IO::ParmParse pp;
114 : if (!pp.contains("nomeme"))
115 : {
116 : time_t timer; time(&timer);
117 : std::stringstream cmd;
118 : cmd << "xdg-open " << BUILD_DIR << "/src/Util/Meme/cat0" << (1+((int)timer)%6) << ".gif &";
119 : std::system(cmd.str().c_str());
120 : 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!)";
121 : }
122 : #endif
123 :
124 36 : amrex::BLBackTrace::handler(s);
125 0 : }
126 :
127 :
128 0 : void Initialize ()
129 : {
130 0 : int argc = 0;
131 0 : char **argv = nullptr;
132 0 : Initialize(argc,argv);
133 0 : initialized = true;
134 0 : }
135 69 : void Initialize (int argc, char* argv[])
136 : {
137 69 : srand (time(NULL));
138 :
139 69 : amrex::Initialize(argc, argv);
140 :
141 69 : IO::ParmParse pp_amrex("amrex");
142 69 : pp_amrex.add("throw_exception",1);
143 : //amrex.throw_exception=1
144 :
145 69 : signal(SIGSEGV, Util::SignalHandler);
146 69 : signal(SIGINT, Util::SignalHandler);
147 69 : signal(SIGABRT, Util::SignalHandler);
148 :
149 69 : std::string filename = GetFileName();
150 :
151 69 : if (amrex::ParallelDescriptor::IOProcessor() && filename != "")
152 : {
153 69 : file_overwrite = Util::CreateCleanDirectory(filename, false);
154 69 : IO::WriteMetaData(filename);
155 : }
156 69 : }
157 :
158 33 : void Finalize()
159 : {
160 33 : std::string filename = GetFileName();
161 33 : if (filename != "")
162 33 : IO::WriteMetaData(filename,IO::Status::Complete);
163 33 : amrex::Finalize();
164 33 : finalized = true;
165 33 : }
166 :
167 :
168 :
169 : void
170 0 : Abort (const char * msg) { Terminate(msg, SIGABRT, true); }
171 :
172 : void
173 0 : Terminate(const char * /* msg */, int signal, bool /*backtrace*/)
174 : {
175 0 : SignalHandler(signal);
176 0 : }
177 :
178 : std::pair<std::string,std::string>
179 69 : CreateCleanDirectory (const std::string &path, bool callbarrier)
180 : {
181 69 : std::pair<std::string,std::string> ret("","");
182 :
183 69 : if(amrex::ParallelDescriptor::IOProcessor()) {
184 69 : if(amrex::FileExists(path)) {
185 0 : std::time_t t = std::time(0);
186 0 : std::tm * now = std::localtime(&t);
187 0 : int year = now->tm_year+1900;
188 0 : int month = now->tm_mon+1;
189 0 : int day = now->tm_mday;
190 0 : int hour = now->tm_hour;
191 0 : int minute = now->tm_min;
192 0 : int second = now->tm_sec;
193 :
194 0 : std::stringstream ss;
195 : ss << year
196 0 : << std::setfill('0') << std::setw(2) << month
197 0 : << std::setfill('0') << std::setw(2) << day
198 0 : << std::setfill('0') << std::setw(2) << hour
199 0 : << std::setfill('0') << std::setw(2) << minute
200 0 : << std::setfill('0') << std::setw(2) << second;
201 :
202 0 : std::string newoldname(path + ".old." + ss.str());
203 0 : if (amrex::system::verbose) {
204 0 : amrex::Print() << "Util::CreateCleanDirectory(): " << path
205 0 : << " exists. Renaming to: " << newoldname << std::endl;
206 : }
207 0 : std::rename(path.c_str(), newoldname.c_str());
208 0 : ret.first = path;
209 0 : ret.second = newoldname;
210 0 : }
211 69 : if( ! amrex::UtilCreateDirectory(path, 0755)) {
212 0 : amrex::CreateDirectoryFailed(path);
213 : }
214 : }
215 69 : if(callbarrier) {
216 : // Force other processors to wait until directory is built.
217 0 : amrex::ParallelDescriptor::Barrier("amrex::UtilCreateCleanDirectory");
218 : }
219 69 : return ret;
220 0 : }
221 :
222 :
223 :
224 :
225 :
226 :
227 : namespace String
228 : {
229 1248 : int ReplaceAll(std::string &str, const std::string before, const std::string after)
230 : {
231 1248 : size_t start_pos = 0;
232 1404 : while((start_pos = str.find(before, start_pos)) != std::string::npos) {
233 156 : str.replace(start_pos, before.length(), after);
234 156 : start_pos += after.length();
235 : }
236 1248 : return 0;
237 : }
238 3677 : int ReplaceAll(std::string &str, const char before, const std::string after)
239 : {
240 3677 : size_t start_pos = 0;
241 3677 : while((start_pos = str.find(before, start_pos)) != std::string::npos) {
242 0 : str.replace(start_pos, 1, after);
243 0 : start_pos += after.length();
244 : }
245 3677 : return 0;
246 : }
247 :
248 0 : std::string Join(std::vector<std::string> & vec, char separator)
249 : {
250 0 : std::ostringstream oss;
251 0 : for (size_t i = 0; i < vec.size(); ++i) {
252 0 : oss << vec[i];
253 0 : if (i < vec.size() - 1) { // Don't add separator after the last element
254 0 : oss << separator;
255 : }
256 : }
257 0 : return oss.str();
258 0 : }
259 :
260 0 : std::string Wrap(std::string text, unsigned per_line)
261 : {
262 0 : unsigned line_begin = 0;
263 :
264 0 : while (line_begin < text.size())
265 : {
266 0 : const unsigned ideal_end = line_begin + per_line ;
267 0 : unsigned line_end = ideal_end <= text.size() ? ideal_end : text.size()-1;
268 :
269 0 : if (line_end == text.size() - 1)
270 0 : ++line_end;
271 0 : else if (std::isspace(text[line_end]))
272 : {
273 0 : text[line_end] = '\n';
274 0 : ++line_end;
275 : }
276 : else // backtrack
277 : {
278 0 : unsigned end = line_end;
279 0 : while ( end > line_begin && !std::isspace(text[end]))
280 0 : --end;
281 :
282 0 : if (end != line_begin)
283 : {
284 0 : line_end = end;
285 0 : text[line_end++] = '\n';
286 : }
287 : else
288 0 : text.insert(line_end++, 1, '\n');
289 : }
290 :
291 0 : line_begin = line_end;
292 : }
293 :
294 0 : return text;
295 : }
296 5246 : std::vector<std::string> Split(std::string &str, const char delim)
297 : {
298 5246 : std::vector<std::string> ret;
299 5246 : std::stringstream ss(str);
300 5246 : std::string item;
301 15800 : while (std::getline(ss, item, delim)) {
302 10554 : ret.push_back(item);
303 : }
304 10492 : return ret;
305 5246 : }
306 1074 : bool Contains(std::string &str, const std::string find)
307 : {
308 1074 : if (str.find(find) != std::string::npos) return true;
309 762 : else return false;
310 : }
311 :
312 : template<>
313 2 : std::complex<int> Parse(std::string input)
314 : {
315 2 : int re=0, im=0;
316 :
317 8 : ReplaceAll(input, "+", " +");
318 6 : ReplaceAll(input, "-", " -");
319 2 : std::vector<std::string> tokens = Split(input,' ');
320 4 : for (unsigned int i = 0; i < tokens.size(); i++)
321 : {
322 2 : if(tokens[i]=="") continue;
323 4 : if(Contains(tokens[i],"i"))
324 : {
325 0 : ReplaceAll(tokens[i],"i","");
326 0 : im += std::stoi(tokens[i]);
327 : }
328 : else
329 : {
330 2 : re += std::stoi(tokens[i]);
331 : }
332 : }
333 4 : return std::complex<int>(re,im);
334 2 : }
335 :
336 :
337 : }
338 :
339 :
340 : namespace Test
341 : {
342 28 : int Message(std::string testname)
343 : {
344 28 : if (amrex::ParallelDescriptor::IOProcessor())
345 28 : std::cout << std::left
346 28 : << Color::FG::White << Color::Bold << testname << Color::Reset << std::endl;
347 28 : return 0;
348 : }
349 0 : int Message(std::string testname, int failed)
350 : {
351 0 : if (amrex::ParallelDescriptor::IOProcessor())
352 : {
353 : winsize w;
354 0 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
355 0 : std::stringstream ss;
356 0 : if (!failed)
357 0 : ss << "[" << Color::FG::Green << Color::Bold << "PASS" << Color::Reset << "]";
358 : else
359 0 : ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
360 :
361 0 : int terminalwidth = 80; //std::min(w.ws_col,(short unsigned int) 100);
362 :
363 0 : std::cout << std::left
364 : << testname
365 0 : << std::setw(terminalwidth - testname.size() + ss.str().size() - 6) << std::right << std::setfill('.') << ss.str() << std::endl;
366 0 : }
367 0 : return failed;
368 : }
369 118 : int SubMessage(std::string testname, int failed)
370 : {
371 118 : if (amrex::ParallelDescriptor::IOProcessor())
372 : {
373 : winsize w;
374 118 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
375 118 : std::stringstream ss;
376 118 : if (!failed)
377 118 : ss << "[" << Color::FG::LightGreen << Color::Bold << "PASS" << Color::Reset << "]";
378 : else
379 0 : ss << "[" << Color::FG::Red << Color::Bold << "FAIL" << Color::Reset << "]";
380 :
381 118 : int terminalwidth = 80;
382 :
383 118 : std::cout << std::left
384 : << " ├ "
385 : << testname
386 118 : << std::setw(terminalwidth - testname.size() + ss.str().size() - 12) << std::right << std::setfill('.') << ss.str() << std::endl;
387 118 : }
388 118 : return failed;
389 : }
390 28 : int SubFinalMessage(int failed)
391 : {
392 28 : if (amrex::ParallelDescriptor::IOProcessor())
393 : {
394 : winsize w;
395 28 : ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
396 28 : std::stringstream ss;
397 28 : std::cout << std::left << " └ ";
398 :
399 28 : if (!failed)
400 28 : std::cout << Color::FG::Green << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
401 : else
402 0 : std::cout << Color::FG::Red << Color::Bold << failed << " tests failed" << Color::Reset << std::endl;
403 28 : }
404 28 : return failed;
405 : }
406 :
407 : }
408 :
409 224 : void AverageCellcenterToNode(amrex::MultiFab& node_mf, const int &dcomp, const amrex::MultiFab &cell_mf, const int &scomp, const int &ncomp/*, const int ngrow=0*/)
410 : {
411 1568 : Util::Assert(INFO,TEST(dcomp + ncomp <= node_mf.nComp()));
412 1568 : Util::Assert(INFO,TEST(scomp + ncomp <= cell_mf.nComp()));
413 : //Util::Assert(INFO,TEST(cell_mf.boxArray() == node_mf.boxArray()));
414 1568 : Util::Assert(INFO,TEST(cell_mf.DistributionMap() == cell_mf.DistributionMap()));
415 1568 : Util::Assert(INFO,TEST(cell_mf.nGrow() > 0));
416 1586 : for (amrex::MFIter mfi(node_mf,amrex::TilingIfNotGPU()); mfi.isValid(); ++mfi)
417 : {
418 1362 : amrex::Box bx = mfi.nodaltilebox();
419 1362 : amrex::Array4<Set::Scalar> const& node = node_mf.array(mfi);
420 1362 : amrex::Array4<const Set::Scalar> const& cell = cell_mf.array(mfi);
421 2724 : for (int n = 0; n < ncomp; n++)
422 1362 : amrex::ParallelFor (bx,[=] AMREX_GPU_DEVICE(int i, int j, int k) {
423 2693228 : node(i,j,k,dcomp+n) = Numeric::Interpolate::CellToNodeAverage(cell,i,j,k,scomp+n);
424 1346614 : });
425 224 : }
426 224 : }
427 :
428 :
429 : }
|