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