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