https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MooseUtils.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10// MOOSE includes
11#include "MooseUtils.h"
12#include "MooseError.h"
13#include "MooseEnum.h"
14#include "MaterialProperty.h"
15#include "MultiMooseEnum.h"
16#include "InputParameters.h"
17#include "ExecFlagEnum.h"
18#include "InfixIterator.h"
19#include "Registry.h"
22#include "ExecFlagRegistry.h"
24
25#include "libmesh/utility.h"
26#include "libmesh/elem.h"
27#include "libmesh/equation_systems.h"
28#include "libmesh/string_to_enum.h"
29
30// External includes
31#include "pcrecpp.h"
32#include "tinydir.h"
33
34// C++ includes
35#include <iostream>
36#include <fstream>
37#include <istream>
38#include <iterator>
39#include <filesystem>
40#include <ctime>
41#include <cstdlib>
42#include <cmath>
43#include <regex>
44
45// System includes
46#include <sys/stat.h>
47#include <numeric>
48#include <unistd.h>
49
50#include "petscsys.h"
51
52#ifdef __WIN32__
53#include <windows.h>
54#include <winbase.h>
55#include <fileapi.h>
56#else
57#include <sys/ioctl.h>
58#endif
59
60namespace MooseUtils
61{
62bool
63isFinitePoint(const Point & point)
64{
65 for (const auto component : make_range(Moose::dim))
66 if (!std::isfinite(point(component)))
67 return false;
68
69 return true;
70}
71
72namespace
73{
74bool
75defaultPRefinement(const libMesh::Order order, const libMesh::FEFamily family)
76{
78 return false;
79
80 switch (family)
81 {
86 case libMesh::CLOUGH:
89 return false;
90
91 default:
92 return true;
93 }
94}
95}
96
99{
100 const auto order =
101 libMesh::Utility::string_to_enum<libMesh::Order>(params.get<MooseEnum>("order"));
102 const auto family =
103 libMesh::Utility::string_to_enum<libMesh::FEFamily>(params.get<MooseEnum>("family"));
104
105 bool p_refinement = defaultPRefinement(order, family);
106 if (params.isParamValid("p_refinement"))
107 p_refinement = params.get<bool>("p_refinement");
108
109 if (params.isParamValid("disable_p_refinement"))
110 {
111 if (params.isParamSetByUser("p_refinement"))
112 params.paramError("disable_p_refinement",
113 "Cannot be supplied together with 'p_refinement'. Use "
114 "'p_refinement = false' instead.");
115 p_refinement = !params.get<bool>("disable_p_refinement");
116 }
117
118 return libMesh::FEType(order, family).set_p_refinement(p_refinement);
119}
120
121std::filesystem::path
122pathjoin(const std::filesystem::path & p)
123{
124 return p;
125}
126
127std::string
129{
130 auto build_loc = pathjoin(Moose::getExecutablePath(), "run_tests");
131 if (pathExists(build_loc) && checkFileReadable(build_loc))
132 return build_loc;
133 // TODO: maybe no path prefix - just moose_test_runner here?
134 return pathjoin(Moose::getExecutablePath(), "moose_test_runner");
135}
136
137std::string
139{
140 std::string path = ".";
141 for (int i = 0; i < 5; i++)
142 {
143 auto testroot = pathjoin(path, "testroot");
144 if (pathExists(testroot) && checkFileReadable(testroot))
145 return testroot;
146 path += "/..";
147 }
148 return "";
149}
150
151bool
152parsesToReal(const std::string & input, Real * parsed_real)
153{
154 std::istringstream ss(input);
155 Real real_value;
156 if (ss >> real_value && ss.eof())
157 {
158 if (parsed_real)
159 (*parsed_real) = real_value;
160 return true;
161 }
162 return false;
163}
164
165std::string
166installedInputsDir(const std::string & app_name,
167 const std::string & dir_name,
168 const std::string & extra_error_msg)
169{
170 // See moose.mk for a detailed explanation of the assumed installed application
171 // layout. Installed inputs are expected to be installed in "share/<app_name>/<folder>".
172 // The binary, which has a defined location will be in "bin", a peer directory to "share".
173 std::string installed_path =
174 pathjoin(Moose::getExecutablePath(), "..", "share", app_name, dir_name);
175
176 auto test_root = pathjoin(installed_path, "testroot");
177 if (!pathExists(installed_path))
178 mooseError("Couldn't locate any installed inputs to copy in path: ",
179 installed_path,
180 '\n',
181 extra_error_msg);
182
183 checkFileReadable(test_root);
184 return installed_path;
185}
186
187std::string
188docsDir(const std::string & app_name)
189{
190 // See moose.mk for a detailed explanation of the assumed installed application
191 // layout. Installed docs are expected to be installed in "share/<app_name>/doc".
192 // The binary, which has a defined location will be in "bin", a peer directory to "share".
193 std::string installed_path = pathjoin(Moose::getExecutablePath(), "..", "share", app_name, "doc");
194
195 auto docfile = pathjoin(installed_path, "css", "moose.css");
196 if (pathExists(docfile) && checkFileReadable(docfile))
197 return installed_path;
198 return "";
199}
200
201std::string
202mooseDocsURL(const std::string & path)
203{
204 return "https://mooseframework.inl.gov/" + path;
205}
206
207std::string
208replaceAll(std::string str, const std::string & from, const std::string & to)
209{
210 size_t start_pos = 0;
211 while ((start_pos = str.find(from, start_pos)) != std::string::npos)
212 {
213 str.replace(start_pos, from.length(), to);
214 start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
215 }
216 return str;
217}
218
219std::string
220convertLatestCheckpoint(std::string orig)
221{
222 auto slash_pos = orig.find_last_of("/");
223 auto path = orig.substr(0, slash_pos);
224 auto file = orig.substr(slash_pos + 1);
225 if (file != "LATEST")
226 return orig;
227
229
230 if (converted.empty())
231 mooseError("Unable to find suitable recovery file!");
232
233 return converted;
234}
235
236// this implementation is copied from
237// https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C.2B.2B
238int
239levenshteinDist(const std::string & s1, const std::string & s2)
240{
241 // To change the type this function manipulates and returns, change
242 // the return type and the types of the two variables below.
243 auto s1len = s1.size();
244 auto s2len = s2.size();
245
246 auto column_start = (decltype(s1len))1;
247
248 auto column = new decltype(s1len)[s1len + 1];
249 std::iota(column + column_start, column + s1len + 1, column_start);
250
251 for (auto x = column_start; x <= s2len; x++)
252 {
253 column[0] = x;
254 auto last_diagonal = x - column_start;
255 for (auto y = column_start; y <= s1len; y++)
256 {
257 auto old_diagonal = column[y];
258 auto possibilities = {
259 column[y] + 1, column[y - 1] + 1, last_diagonal + (s1[y - 1] == s2[x - 1] ? 0 : 1)};
260 column[y] = std::min(possibilities);
261 last_diagonal = old_diagonal;
262 }
263 }
264 auto result = column[s1len];
265 delete[] column;
266 return result;
267}
268
269void
270escape(std::string & str)
271{
272 std::map<char, std::string> escapes;
273 escapes['\a'] = "\\a";
274 escapes['\b'] = "\\b";
275 escapes['\f'] = "\\f";
276 escapes['\n'] = "\\n";
277 escapes['\t'] = "\\t";
278 escapes['\v'] = "\\v";
279 escapes['\r'] = "\\r";
280
281 for (const auto & it : escapes)
282 for (size_t pos = 0; (pos = str.find(it.first, pos)) != std::string::npos;
283 pos += it.second.size())
284 str.replace(pos, 1, it.second);
285}
286
287std::string
288removeExtraWhitespace(const std::string & input)
289{
290 return std::regex_replace(input, std::regex("^\\s+|\\s+$|\\s+(?=\\s)"), "");
291}
292
293bool
294pathContains(const std::string & expression,
295 const std::string & string_to_find,
296 const std::string & delims)
297{
298 std::vector<std::string> elements;
299 tokenize(expression, elements, 0, delims);
300
301 std::vector<std::string>::iterator found_it =
302 std::find(elements.begin(), elements.end(), string_to_find);
303 if (found_it != elements.end())
304 return true;
305 else
306 return false;
307}
308
309bool
310pathExists(const std::string & path)
311{
312 struct stat buffer;
313 return (stat(path.c_str(), &buffer) == 0);
314}
315
316bool
317checkFileReadable(const std::string & filename,
318 bool check_line_endings,
319 bool throw_on_unreadable,
320 bool check_for_git_lfs_pointer)
321{
322 std::ifstream in(filename.c_str(), std::ifstream::in);
323 if (in.fail())
324 {
325 if (throw_on_unreadable)
327 (std::string("Unable to open file \"") + filename +
328 std::string("\". Check to make sure that it exists and that you have read permission."))
329 .c_str());
330 else
331 return false;
332 }
333
334 if (check_line_endings)
335 {
336 std::istream_iterator<char> iter(in);
337 std::istream_iterator<char> eos;
338 in >> std::noskipws;
339 while (iter != eos)
340 if (*iter++ == '\r')
341 mooseError(filename + " contains Windows(DOS) line endings which are not supported.");
342 }
343
344 if (check_for_git_lfs_pointer && checkForGitLFSPointer(in))
345 mooseError(filename + " appears to be a Git-LFS pointer. Make sure you have \"git-lfs\" "
346 "installed so that you may pull this file.");
347 in.close();
348
349 return true;
350}
351
352bool
353checkForGitLFSPointer(std::ifstream & file)
354{
355 mooseAssert(file.is_open(), "Passed in file handle is not open");
356
357 std::string line;
358
359 // git-lfs pointer files contain several name value pairs. The specification states that the
360 // first name/value pair must be "version {url}". We'll do a simplified check for that.
361 file.seekg(0);
362 std::getline(file, line);
363 if (line.find("version https://") != std::string::npos)
364 return true;
365 else
366 return false;
367}
368
369bool
370checkFileWriteable(const std::string & filename, bool throw_on_unwritable)
371{
372 std::ofstream out(filename.c_str(), std::ios_base::app);
373 if (out.fail())
374 {
375 if (throw_on_unwritable)
377 (std::string("Unable to open file \"") + filename +
378 std::string("\". Check to make sure that it exists and that you have write permission."))
379 .c_str());
380 else
381 return false;
382 }
383
384 out.close();
385
386 return true;
387}
388
389void
391{
392 processor_id_type secondary_processor_id;
393
394 if (messaging)
395 Moose::out << "Waiting For Other Processors To Finish" << std::endl;
396 if (comm.rank() == 0)
397 {
398 // The primary process is already through, so report it
399 if (messaging)
400 Moose::out << "Jobs complete: 1/" << comm.size() << (1 == comm.size() ? "\n" : "\r")
401 << std::flush;
402 for (unsigned int i = 2; i <= comm.size(); ++i)
403 {
404 comm.receive(MPI_ANY_SOURCE, secondary_processor_id);
405 if (messaging)
406 Moose::out << "Jobs complete: " << i << "/" << comm.size()
407 << (i == comm.size() ? "\n" : "\r") << std::flush;
408 }
409 }
410 else
411 {
412 secondary_processor_id = comm.rank();
413 comm.send(0, secondary_processor_id);
414 }
415
416 comm.barrier();
417}
418
419void
421{
422 // unless we are the first processor...
423 if (comm.rank() > 0)
424 {
425 // ...wait for the previous processor to finish
426 int dummy = 0;
427 comm.receive(comm.rank() - 1, dummy);
428 }
429 else if (warn)
430 mooseWarning("Entering serial execution block (use only for debugging)");
431}
432
433void
435{
436 // unless we are the last processor...
437 if (comm.rank() + 1 < comm.size())
438 {
439 // ...notify the next processor of its turn
440 int dummy = 0;
441 comm.send(comm.rank() + 1, dummy);
442 }
443
444 comm.barrier();
445 if (comm.rank() == 0 && warn)
446 mooseWarning("Leaving serial execution block (use only for debugging)");
447}
448
449bool
450hasExtension(const std::string & filename, std::string ext, bool strip_exodus_ext)
451{
452 // Extract the extension, w/o the '.'
453 std::string file_ext;
454 if (strip_exodus_ext)
455 {
456 pcrecpp::RE re(
457 ".*\\.([^\\.]*?)(?:-s\\d+)?\\s*$"); // capture the complete extension, ignoring -s*
458 re.FullMatch(filename, &file_ext);
459 }
460 else
461 {
462 pcrecpp::RE re(".*\\.([^\\.]*?)\\s*$"); // capture the complete extension
463 re.FullMatch(filename, &file_ext);
464 }
465
466 // Perform the comparision
467 if (file_ext == ext)
468 return true;
469 else
470 return false;
471}
472
473std::string
474getExtension(const std::string & filename, const bool rfind)
475{
476 std::string file_ext = "";
477 if (filename != "")
478 {
479 // The next line splits filename at the last "/" and gives the file name after "/"
480 const std::string stripped_filename = splitFileName<std::string>(filename).second;
481 auto pos = rfind ? stripped_filename.rfind(".") : stripped_filename.find(".");
482 if (pos != std::string::npos)
483 file_ext += stripped_filename.substr(pos + 1, std::string::npos);
484 }
485
486 return file_ext;
487}
488
489std::string
490stripExtension(const std::string & s, const bool rfind)
491{
492 const std::string ext = getExtension(s, rfind);
493 const bool offset = (ext.size() != 0);
494 // -1 offset accounts for the extension's leading dot ("."), if there is an extension
495 return s.substr(0, s.size() - ext.size() - offset);
496}
497
498std::string
500{
501 // Note: At the time of creating this method, our minimum compiler still
502 // does not support <filesystem>. Additionally, the inclusion of that header
503 // requires an additional library to be linked so for now, we'll just
504 // use the Unix standard library to get us the cwd().
505 constexpr unsigned int BUF_SIZE = 1024;
506 char buffer[BUF_SIZE];
507
508 return getcwd(buffer, BUF_SIZE) != nullptr ? buffer : "";
509}
510
511void
512makedirs(const std::string & dir_name, bool throw_on_failure)
513{
514 // split path into directories with delimiter '/'
515 std::vector<std::string> split_dir_names;
516 MooseUtils::tokenize(dir_name, split_dir_names);
517
518 auto n = split_dir_names.size();
519
520 // remove '.' and '..' when possible
521 auto i = n;
522 i = 0;
523 while (i != n)
524 {
525 if (split_dir_names[i] == ".")
526 {
527 for (auto j = i + 1; j < n; ++j)
528 split_dir_names[j - 1] = split_dir_names[j];
529 --n;
530 }
531 else if (i > 0 && split_dir_names[i] == ".." && split_dir_names[i - 1] != "..")
532 {
533 for (auto j = i + 1; j < n; ++j)
534 split_dir_names[j - 2] = split_dir_names[j];
535 n -= 2;
536 --i;
537 }
538 else
539 ++i;
540 }
541 if (n == 0)
542 return;
543
544 split_dir_names.resize(n);
545
546 // start creating directories recursively
547 std::string cur_dir = dir_name[0] == '/' ? "" : ".";
548 for (auto & dir : split_dir_names)
549 {
550 cur_dir += "/" + dir;
551
552 if (!pathExists(cur_dir))
553 {
554 auto code = Utility::mkdir(cur_dir.c_str());
555 if (code != 0)
556 {
557 std::string msg = "Failed creating directory " + dir_name;
558 if (throw_on_failure)
559 throw std::invalid_argument(msg);
560 else
561 mooseError(msg);
562 }
563 }
564 }
565}
566
567void
568removedirs(const std::string & dir_name, bool throw_on_failure)
569{
570 // split path into directories with delimiter '/'
571 std::vector<std::string> split_dir_names;
572 MooseUtils::tokenize(dir_name, split_dir_names);
573
574 auto n = split_dir_names.size();
575
576 // remove '.' and '..' when possible
577 auto i = n;
578 i = 0;
579 while (i != n)
580 {
581 if (split_dir_names[i] == ".")
582 {
583 for (auto j = i + 1; j < n; ++j)
584 split_dir_names[j - 1] = split_dir_names[j];
585 --n;
586 }
587 else if (i > 0 && split_dir_names[i] == ".." && split_dir_names[i - 1] != "..")
588 {
589 for (auto j = i + 1; j < n; ++j)
590 split_dir_names[j - 2] = split_dir_names[j];
591 n -= 2;
592 --i;
593 }
594 else
595 ++i;
596 }
597 if (n == 0)
598 return;
599
600 split_dir_names.resize(n);
601
602 // start removing directories recursively
603 std::string base_dir = dir_name[0] == '/' ? "" : ".";
604 for (i = n; i > 0; --i)
605 {
606 std::string cur_dir = base_dir;
607 auto j = i;
608 for (j = 0; j < i; ++j)
609 cur_dir += "/" + split_dir_names[j];
610
611 // listDir should return at least '.' and '..'
612 if (pathExists(cur_dir) && listDir(cur_dir).size() == 2)
613 {
614 auto code = rmdir(cur_dir.c_str());
615 if (code != 0)
616 {
617 std::string msg = "Failed removing directory " + dir_name;
618 if (throw_on_failure)
619 throw std::invalid_argument(msg);
620 else
621 mooseError(msg);
622 }
623 }
624 else
625 // stop removing
626 break;
627 }
628}
629
630std::string
631camelCaseToUnderscore(const std::string & camel_case_name)
632{
633 std::string replaced = camel_case_name;
634 // Put underscores in front of each contiguous set of capital letters
635 pcrecpp::RE("(?!^)(?<![A-Z_])([A-Z]+)").GlobalReplace("_\\1", &replaced);
636
637 // Convert all capital letters to lower case
638 std::transform(replaced.begin(), replaced.end(), replaced.begin(), ::tolower);
639 return replaced;
640}
641
642std::string
643underscoreToCamelCase(const std::string & underscore_name, bool leading_upper_case)
644{
645 pcrecpp::StringPiece input(underscore_name);
646 pcrecpp::RE re("([^_]*)(_|$)");
647
648 std::string result;
649 std::string us, not_us;
650 bool make_upper = leading_upper_case;
651 while (re.Consume(&input, &not_us, &us))
652 {
653 if (not_us.length() > 0)
654 {
655 if (make_upper)
656 {
657 result += std::toupper(not_us[0]);
658 if (not_us.length() > 1)
659 result += not_us.substr(1);
660 }
661 else
662 result += not_us;
663 }
664 if (us == "")
665 break;
666
667 // Toggle flag so next match is upper cased
668 make_upper = true;
669 }
670
671 return result;
672}
673
674std::string
675shortName(const std::string & name)
676{
677 return name.substr(name.find_last_of('/') != std::string::npos ? name.find_last_of('/') + 1 : 0);
678}
679
680std::string
681baseName(const std::string & name)
682{
683 return name.substr(0, name.find_last_of('/') != std::string::npos ? name.find_last_of('/') : 0);
684}
685
686std::string
688{
689 char hostname[1024];
690 hostname[1023] = '\0';
691#ifndef __WIN32__
692 if (gethostname(hostname, 1023))
693 mooseError("Failed to retrieve hostname!");
694#else
695 DWORD dwSize = sizeof(hostname);
696 if (!GetComputerNameEx(ComputerNamePhysicalDnsHostname, hostname, &dwSize))
697 mooseError("Failed to retrieve hostname!");
698#endif
699 return hostname;
700}
701
702unsigned short
703getTermWidth(bool use_environment)
704{
705#ifndef __WIN32__
706 struct winsize w;
707#else
708 struct
709 {
710 unsigned short ws_col;
711 } w;
712#endif
717 w.ws_col = std::numeric_limits<unsigned short>::max();
718
719 if (use_environment)
720 {
721 char * pps_width = std::getenv("MOOSE_PPS_WIDTH");
722 if (pps_width != NULL)
723 {
724 std::stringstream ss(pps_width);
725 ss >> w.ws_col;
726 }
727 }
728 // Default to AUTO if no environment variable was set
729 if (w.ws_col == std::numeric_limits<unsigned short>::max())
730 {
731#ifndef __WIN32__
732 try
733 {
734 ioctl(0, TIOCGWINSZ, &w);
735 }
736 catch (...)
737#endif
738 {
739 }
740 }
741
742 // Something bad happened, make sure we have a sane value
743 // 132 seems good for medium sized screens, and is available as a GNOME preset
744 if (w.ws_col == std::numeric_limits<unsigned short>::max())
745 w.ws_col = 132;
746
747 return w.ws_col;
748}
749
750void
753{
754 // Loop through the elements
755 for (const auto & elem_it : props)
756 {
757 Moose::out << "Element " << elem_it.first->id() << '\n';
758
759 // Loop through the sides
760 for (const auto & side_it : elem_it.second)
761 {
762 Moose::out << " Side " << side_it.first << '\n';
763
764 // Loop over properties
765 unsigned int cnt = 0;
766 for (const auto & mat_prop : side_it.second)
767 {
768 if (auto mp = dynamic_cast<const MaterialProperty<Real> *>(&mat_prop))
769 {
770 Moose::out << " Property " << cnt << '\n';
771 cnt++;
772
773 // Loop over quadrature points
774 for (unsigned int qp = 0; qp < mp->size(); ++qp)
775 Moose::out << " prop[" << qp << "] = " << (*mp)[qp] << '\n';
776 }
777 }
778 }
779 }
780
781 Moose::out << std::flush;
782}
783
784std::string &
785removeColor(std::string & msg)
786{
787 pcrecpp::RE re("(\\33\\[3[0-7]m))", pcrecpp::DOTALL());
788 re.GlobalReplace(std::string(""), &msg);
789 return msg;
790}
791
792void
793addLineBreaks(std::string & message,
794 unsigned int line_width /*= ConsoleUtils::console_line_length*/)
795{
796 for (auto i : make_range(int(message.length() / line_width)))
797 message.insert((i + 1) * (line_width + 2) - 2, "\n");
798}
799
800void
801indentMessage(const std::string & prefix,
802 std::string & message,
803 const char * color /*= COLOR_CYAN*/,
804 bool indent_first_line,
805 const std::string & post_prefix)
806{
807 // First we need to see if the message we need to indent (with color) also contains color codes
808 // that span lines.
809 // The code matches all of the XTERM constants (see XTermConstants.h). If it does, then we'll work
810 // on formatting
811 // each colored multiline chunk one at a time with the right codes.
812 std::string colored_message;
813 std::string curr_color = COLOR_DEFAULT; // tracks last color code before newline
814 std::string line, color_code;
815
816 bool ends_in_newline = message.empty() ? true : message.back() == '\n';
817
818 bool first = true;
819
820 std::istringstream iss(message);
821 for (std::string line; std::getline(iss, line);) // loop over each line
822 {
823 const static pcrecpp::RE match_color(".*(\\33\\[3\\dm)((?!\\33\\[3\\d)[^\n])*");
824 pcrecpp::StringPiece line_piece(line);
825 match_color.FindAndConsume(&line_piece, &color_code);
826
827 if (!first || indent_first_line)
828 colored_message += color + prefix + post_prefix + curr_color;
829
830 colored_message += line;
831
832 // Only add a newline to the last line if it had one to begin with!
833 if (!iss.eof() || ends_in_newline)
834 colored_message += "\n";
835
836 if (!color_code.empty())
837 curr_color = color_code; // remember last color of this line
838
839 first = false;
840 }
841 message = colored_message;
842}
843
844std::list<std::string>
845listDir(const std::string path, bool files_only)
846{
847 std::list<std::string> files;
848
849 tinydir_dir dir;
850 dir.has_next = 0; // Avoid a garbage value in has_next (clang StaticAnalysis)
851 tinydir_open(&dir, path.c_str());
852
853 while (dir.has_next)
854 {
855 tinydir_file file;
856 file.is_dir = 0; // Avoid a garbage value in is_dir (clang StaticAnalysis)
857 tinydir_readfile(&dir, &file);
858
859 if (!files_only || !file.is_dir)
860 files.push_back(path + "/" + file.name);
861
862 tinydir_next(&dir);
863 }
864
865 tinydir_close(&dir);
866
867 return files;
868}
869
870std::list<std::string>
871getFilesInDirs(const std::list<std::string> & directory_list, const bool files_only /* = true */)
872{
873 std::list<std::string> files;
874
875 for (const auto & dir_name : directory_list)
876 files.splice(files.end(), listDir(dir_name, files_only));
877
878 return files;
879}
880
881std::string
882getLatestCheckpointFilePrefix(const std::list<std::string> & checkpoint_files)
883{
884 // Create storage for newest restart files
885 // Note that these might have the same modification time if the simulation was fast.
886 // In that case we're going to save all of the "newest" files and sort it out momentarily
887 std::time_t newest_time = 0;
888 std::list<std::string> newest_restart_files;
889
890 // Loop through all possible files and store the newest
891 for (const auto & cp_file : checkpoint_files)
892 {
893 if (MooseUtils::hasExtension(cp_file, "rd"))
894 {
895 struct stat stats;
896 stat(cp_file.c_str(), &stats);
897
898 std::time_t mod_time = stats.st_mtime;
899 if (mod_time > newest_time)
900 {
901 newest_restart_files.clear(); // If the modification time is greater, clear the list
902 newest_time = mod_time;
903 }
904
905 if (mod_time == newest_time)
906 newest_restart_files.push_back(cp_file);
907 }
908 }
909
910 // Loop through all of the newest files according the number in the file name
911 int max_file_num = -1;
912 std::string max_file;
913 std::string max_prefix;
914
915 // Pull out the path including the number and the number itself
916 // This takes something_blah_out_cp/0024-restart-1.rd
917 // and returns "something_blah_out_cp/0024" as the "prefix"
918 // and then "24" as the number itself
919 pcrecpp::RE re_file_num("(.*?(\\d+))-restart-\\d+.rd$");
920
921 // Now, out of the newest files find the one with the largest number in it
922 for (const auto & res_file : newest_restart_files)
923 {
924 int file_num = 0;
925
926 // All of the file up to and including the digits
927 std::string file_prefix;
928
929 re_file_num.FullMatch(res_file, &file_prefix, &file_num);
930
931 if (file_num > max_file_num)
932 {
933 // Need both the header and the data
935 continue;
936
937 max_file_num = file_num;
938 max_file = res_file;
939 max_prefix = file_prefix;
940 }
941 }
942
943 // Error if nothing was located
944 if (max_file_num == -1)
945 mooseError("No checkpoint file found!");
946
947 return max_prefix;
948}
949
950bool
951wildCardMatch(std::string name, std::string search_string)
952{
953 // Assume that an empty string matches anything
954 if (search_string == "")
955 return true;
956
957 // transform to lower for case insenstive matching
958 std::transform(name.begin(), name.end(), name.begin(), (int (*)(int))std::toupper);
959 std::transform(search_string.begin(),
960 search_string.end(),
961 search_string.begin(),
962 (int (*)(int))std::toupper);
963
964 // exact match!
965 if (search_string.find("*") == std::string::npos)
966 return search_string == name;
967
968 // wildcard
969 std::vector<std::string> tokens;
970 MooseUtils::tokenize(search_string, tokens, 1, "*");
971
972 size_t pos = 0;
973 for (unsigned int i = 0; i < tokens.size() && pos != std::string::npos; ++i)
974 {
975 pos = name.find(tokens[i], pos);
976 // See if we have a leading wildcard
977 if (search_string[0] != '*' && i == 0 && pos != 0)
978 return false;
979 }
980
981 if (pos != std::string::npos && tokens.size() > 0)
982 {
983 // Now see if we have a trailing wildcard
984 size_t last_token_length = tokens.back().length();
985 if (*search_string.rbegin() == '*' || pos == name.size() - last_token_length)
986 return true;
987 else
988 return false;
989 }
990 else
991 return false;
992}
993
994bool
995globCompare(const std::string & candidate,
996 const std::string & pattern,
997 std::size_t c,
998 std::size_t p)
999{
1000 if (p == pattern.size())
1001 return c == candidate.size();
1002
1003 if (pattern[p] == '*')
1004 {
1005 for (; c < candidate.size(); ++c)
1006 if (globCompare(candidate, pattern, c, p + 1))
1007 return true;
1008 return globCompare(candidate, pattern, c, p + 1);
1009 }
1010
1011 if (pattern[p] != '?' && pattern[p] != candidate[c])
1012 return false;
1013
1014 return globCompare(candidate, pattern, c + 1, p + 1);
1015}
1016
1017bool
1018beginsWith(const std::string & value, const std::string & begin_value)
1019{
1020 return value.rfind(begin_value, 0) == 0;
1021}
1022
1028
1029int
1030stringToInteger(const std::string & input, bool throw_on_failure)
1031{
1032 return convert<int>(input, throw_on_failure);
1033}
1034
1035void
1036linearPartitionItems(dof_id_type num_items,
1037 dof_id_type num_chunks,
1038 dof_id_type chunk_id,
1039 dof_id_type & num_local_items,
1040 dof_id_type & local_items_begin,
1041 dof_id_type & local_items_end)
1042{
1043 auto global_num_local_items = num_items / num_chunks;
1044
1045 num_local_items = global_num_local_items;
1046
1047 auto leftovers = num_items % num_chunks;
1048
1049 if (chunk_id < leftovers)
1050 {
1051 num_local_items++;
1052 local_items_begin = num_local_items * chunk_id;
1053 }
1054 else
1055 local_items_begin =
1056 (global_num_local_items + 1) * leftovers + global_num_local_items * (chunk_id - leftovers);
1057
1058 local_items_end = local_items_begin + num_local_items;
1059}
1060
1061processor_id_type
1062linearPartitionChunk(dof_id_type num_items, dof_id_type num_chunks, dof_id_type item_id)
1063{
1064 auto global_num_local_items = num_items / num_chunks;
1065
1066 auto leftovers = num_items % num_chunks;
1067
1068 auto first_item_past_first_part = leftovers * (global_num_local_items + 1);
1069
1070 // Is it in the first section (that gets an extra item)
1071 if (item_id < first_item_past_first_part)
1072 return item_id / (global_num_local_items + 1);
1073 else
1074 {
1075 auto new_item_id = item_id - first_item_past_first_part;
1076
1077 // First chunk after the first section + the number of chunks after that
1078 return leftovers + (new_item_id / global_num_local_items);
1079 }
1080}
1081
1082std::vector<std::string>
1083split(const std::string & str, const std::string & delimiter, std::size_t max_count)
1084{
1085 std::vector<std::string> output;
1086 std::size_t count = 0;
1087 size_t prev = 0, pos = 0;
1088 do
1089 {
1090 pos = str.find(delimiter, prev);
1091 output.push_back(str.substr(prev, pos - prev));
1092 prev = pos + delimiter.length();
1093 count += 1;
1094 } while (pos != std::string::npos && count < max_count);
1095
1096 if (pos != std::string::npos)
1097 output.push_back(str.substr(prev));
1098
1099 return output;
1100}
1101
1102std::vector<std::string>
1103rsplit(const std::string & str, const std::string & delimiter, std::size_t max_count)
1104{
1105 std::vector<std::string> output;
1106 std::size_t count = 0;
1107 size_t prev = str.length(), pos = str.length();
1108 do
1109 {
1110 pos = str.rfind(delimiter, prev);
1111 output.insert(output.begin(), str.substr(pos + delimiter.length(), prev - pos));
1112 prev = pos - delimiter.length();
1113 count += 1;
1114 } while (pos != std::string::npos && pos > 0 && count < max_count);
1115
1116 if (pos != std::string::npos)
1117 output.insert(output.begin(), str.substr(0, pos));
1118
1119 return output;
1120}
1121
1122void
1123createSymlink(const std::string & target, const std::string & link)
1124{
1125 clearSymlink(link);
1126#ifndef __WIN32__
1127 auto err = symlink(target.c_str(), link.c_str());
1128#else
1129 auto err = CreateSymbolicLink(target.c_str(), link.c_str(), 0);
1130#endif
1131 if (err)
1132 mooseError("Failed to create symbolic link (via 'symlink') from ", target, " to ", link);
1133}
1134
1135void
1136clearSymlink(const std::string & link)
1137{
1138#ifndef __WIN32__
1139 struct stat sbuf;
1140 if (lstat(link.c_str(), &sbuf) == 0)
1141 {
1142 auto err = unlink(link.c_str());
1143 if (err != 0)
1144 mooseError("Failed to remove symbolic link (via 'unlink') to ", link);
1145 }
1146#else
1147 auto attr = GetFileAttributesA(link.c_str());
1148 if (attr != INVALID_FILE_ATTRIBUTES)
1149 {
1150 auto err = _unlink(link.c_str());
1151 if (err != 0)
1152 mooseError("Failed to remove link/file (via '_unlink') to ", link);
1153 }
1154#endif
1155}
1156
1157std::size_t
1158fileSize(const std::string & filename)
1159{
1160#ifndef __WIN32__
1161 struct stat buffer;
1162 if (!stat(filename.c_str(), &buffer))
1163 return buffer.st_size;
1164#else
1165 HANDLE hFile = CreateFile(filename.c_str(),
1166 GENERIC_READ,
1167 FILE_SHARE_READ | FILE_SHARE_WRITE,
1168 NULL,
1169 OPEN_EXISTING,
1170 FILE_ATTRIBUTE_NORMAL,
1171 NULL);
1172 if (hFile == INVALID_HANDLE_VALUE)
1173 return 0;
1174
1175 LARGE_INTEGER size;
1176 if (GetFileSizeEx(hFile, &size))
1177 {
1178 CloseHandle(hFile);
1179 return size.QuadPart;
1180 }
1181
1182 CloseHandle(hFile);
1183#endif
1184 return 0;
1185}
1186
1187std::string
1188realpath(const std::string & path)
1189{
1190 return std::filesystem::absolute(path);
1191}
1192
1193BoundingBox
1194buildBoundingBox(const Point & p1, const Point & p2)
1195{
1196 BoundingBox bb;
1197 bb.union_with(p1);
1198 bb.union_with(p2);
1199 return bb;
1200}
1201
1202std::string
1203prettyCppType(const std::string & cpp_type)
1204{
1205 // On mac many of the std:: classes are inline namespaced with __1
1206 // On linux std::string can be inline namespaced with __cxx11
1207 std::string s = cpp_type;
1208 // Remove all spaces surrounding a >
1209 pcrecpp::RE("\\s(?=>)").GlobalReplace("", &s);
1210 pcrecpp::RE("std::__\\w+::").GlobalReplace("std::", &s);
1211 // It would be nice if std::string actually looked normal
1212 pcrecpp::RE("\\s*std::basic_string<char, std::char_traits<char>, std::allocator<char>>\\s*")
1213 .GlobalReplace("std::string", &s);
1214 // It would be nice if std::vector looked normal
1215 pcrecpp::RE r("std::vector<([[:print:]]+),\\s?std::allocator<\\s?\\1\\s?>\\s?>");
1216 r.GlobalReplace("std::vector<\\1>", &s);
1217 // Do it again for nested vectors
1218 r.GlobalReplace("std::vector<\\1>", &s);
1219 // It would be nice if std::map and unordered map looked normal
1220 pcrecpp::RE r_map(
1221 "std::map<\\s*((?:[^,<]|<[^>]*>)+)\\s*,\\s*((?:[^,<]|<[^>]*>)+)\\s*,\\s*"
1222 "std::less<\\s*\\1\\s*>\\s*,\\s*"
1223 "std::allocator<\\s*std::pair<\\s*(?:const\\s*\\1|\\1\\s*const)\\s*,\\s*\\2\\s*>\\s*>\\s*>");
1224 r_map.GlobalReplace("std::map<\\1, \\2>", &s);
1225 pcrecpp::RE r_umap(
1226 "std::unordered_map<\\s*([^,]+)\\s*,\\s*([^,]+)\\s*,\\s*"
1227 "std::hash<\\s*\\1\\s*>\\s*,\\s*"
1228 "std::equal_to<\\s*\\1\\s*>\\s*,\\s*"
1229 "std::allocator<\\s*std::pair<\\s*(?:const\\s*\\1|\\1\\s*const)\\s*,\\s*\\2\\s*>\\s*>\\s*>");
1230 r_umap.GlobalReplace("std::unordered_map<\\1, \\2>", &s);
1231
1232 return s;
1233}
1234
1235std::string
1236canonicalPath(const std::string & path)
1237{
1238 return std::filesystem::weakly_canonical(path).c_str();
1239}
1240
1241bool
1242startsWith(const std::string & string1, const std::string & string2)
1243{
1244 if (string2.size() > string1.size())
1245 return false;
1246 return string1.compare(0, string2.size(), string2) == 0;
1247}
1248
1249void
1250replaceStart(std::string & string1, const std::string & string2, const std::string & string3)
1251{
1252 mooseAssert(startsWith(string1, string2),
1253 "Cannot replace the start because it doesn't match the start string");
1254 string1.replace(0, string2.size(), string3);
1255}
1256
1257bool
1258isAllLowercase(const std::string & str)
1259{
1260 return std::all_of(
1261 str.begin(), str.end(), [](unsigned char c) { return !std::isalpha(c) || std::islower(c); });
1262}
1263} // MooseUtils namespace
1264
1265void
1266removeSubstring(std::string & main, const std::string & sub)
1267{
1268 std::string::size_type n = sub.length();
1269 for (std::string::size_type i = main.find(sub); i != std::string::npos; i = main.find(sub))
1270 main.erase(i, n);
1271}
1272
1273std::string
1274removeSubstring(const std::string & main, const std::string & sub)
1275{
1276 std::string copy_main = main;
1277 std::string::size_type n = sub.length();
1278 for (std::string::size_type i = copy_main.find(sub); i != std::string::npos;
1279 i = copy_main.find(sub))
1280 copy_main.erase(i, n);
1281 return copy_main;
1282}
void mooseWarning(Args &&... args)
Emit a warning message with the given stringified, concatenated args.
Definition MooseError.h:345
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
void removeSubstring(std::string &main, const std::string &sub)
unsigned int count
Definition MortarUtils.C:53
void ErrorVector unsigned int
A MultiMooseEnum object to hold "execute_on" flags.
HashMap is an abstraction for dictionary data type, we make it thread-safe by locking inserts.
Definition HashMap.h:19
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
void paramError(const std::string &param, Args... args) const
Emits a parameter error prefixed with the parameter location and object information if available.
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another,...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition MooseEnum.h:55
static bool isAvailable(const std::filesystem::path &folder_base)
processor_id_type size() const
processor_id_type rank() const
Status receive(const unsigned int dest_processor_id, T &buf, const MessageTag &tag=any_tag) const
void send(const unsigned int dest_processor_id, const T &buf, const MessageTag &tag=no_tag) const
static bool is_elemental_data_fe_type(const FEType &type)
FEType set_p_refinement(bool p) &
const ExecFlagEnum & getDefaultFlags() const
static ExecFlagRegistry & getExecFlagRegistry()
Return Singleton instance.
std::string hostname()
Definition MooseUtils.C:687
void replaceStart(std::string &string1, const std::string &string2, const std::string &string3)
void linearPartitionItems(dof_id_type num_items, dof_id_type num_chunks, dof_id_type chunk_id, dof_id_type &num_local_items, dof_id_type &local_items_begin, dof_id_type &local_items_end)
int stringToInteger(const std::string &input, bool throw_on_failure)
bool isFinitePoint(const Point &point)
Definition MooseUtils.C:63
std::string mooseDocsURL(const std::string &path)
Definition MooseUtils.C:202
bool checkForGitLFSPointer(std::ifstream &file)
Definition MooseUtils.C:353
std::string & removeColor(std::string &msg)
Definition MooseUtils.C:785
libMesh::FEType variableFEType(const InputParameters &params)
Definition MooseUtils.C:98
std::string realpath(const std::string &path)
void removedirs(const std::string &dir_name, bool throw_on_failure)
Definition MooseUtils.C:568
std::filesystem::path pathjoin(const std::filesystem::path &p)
Definition MooseUtils.C:122
bool hasExtension(const std::string &filename, std::string ext, bool strip_exodus_ext)
Definition MooseUtils.C:450
unsigned short getTermWidth(bool use_environment)
Definition MooseUtils.C:703
std::string canonicalPath(const std::string &path)
void indentMessage(const std::string &prefix, std::string &message, const char *color, bool indent_first_line, const std::string &post_prefix)
Definition MooseUtils.C:801
std::string removeExtraWhitespace(const std::string &input)
Definition MooseUtils.C:288
std::string getCurrentWorkingDir()
Definition MooseUtils.C:499
std::string camelCaseToUnderscore(const std::string &camel_case_name)
Definition MooseUtils.C:631
std::string baseName(const std::string &name)
Definition MooseUtils.C:681
bool pathContains(const std::string &expression, const std::string &string_to_find, const std::string &delims)
Definition MooseUtils.C:294
void createSymlink(const std::string &target, const std::string &link)
void makedirs(const std::string &dir_name, bool throw_on_failure)
Definition MooseUtils.C:512
std::string installedInputsDir(const std::string &app_name, const std::string &dir_name, const std::string &extra_error_msg)
Definition MooseUtils.C:166
std::vector< std::string > split(const std::string &str, const std::string &delimiter, std::size_t max_count)
void tokenize(const std::string &str, std::vector< T > &elements, unsigned int min_len=1, const std::string &delims="/")
This function will split the passed in string on a set of delimiters appending the substrings to the ...
std::list< std::string > getFilesInDirs(const std::list< std::string > &directory_list, const bool files_only)
Definition MooseUtils.C:871
bool checkFileWriteable(const std::string &filename, bool throw_on_unwritable)
Definition MooseUtils.C:370
void serialEnd(const libMesh::Parallel::Communicator &comm, bool warn)
Definition MooseUtils.C:434
std::string getExtension(const std::string &filename, const bool rfind)
Definition MooseUtils.C:474
bool isAllLowercase(const std::string &str)
bool pathExists(const std::string &path)
Definition MooseUtils.C:310
int levenshteinDist(const std::string &s1, const std::string &s2)
Definition MooseUtils.C:239
std::string docsDir(const std::string &app_name)
Definition MooseUtils.C:188
bool startsWith(const std::string &string1, const std::string &string2)
bool parsesToReal(const std::string &input, Real *parsed_real)
Definition MooseUtils.C:152
std::string replaceAll(std::string str, const std::string &from, const std::string &to)
Definition MooseUtils.C:208
processor_id_type linearPartitionChunk(dof_id_type num_items, dof_id_type num_chunks, dof_id_type item_id)
void escape(std::string &str)
Definition MooseUtils.C:270
std::string convertLatestCheckpoint(std::string orig)
Definition MooseUtils.C:220
std::string underscoreToCamelCase(const std::string &underscore_name, bool leading_upper_case)
Definition MooseUtils.C:643
bool globCompare(const std::string &candidate, const std::string &pattern, std::size_t c, std::size_t p)
Definition MooseUtils.C:995
ExecFlagEnum getDefaultExecFlagEnum()
bool beginsWith(const std::string &value, const std::string &begin_value)
void parallelBarrierNotify(const Parallel::Communicator &comm, bool messaging)
Definition MooseUtils.C:390
BoundingBox buildBoundingBox(const Point &p1, const Point &p2)
void MaterialPropertyStorageDump(const HashMap< const libMesh::Elem *, HashMap< unsigned int, MaterialProperties > > &props)
Definition MooseUtils.C:751
std::string prettyCppType(const std::string &cpp_type)
std::string stripExtension(const std::string &s, const bool rfind)
Definition MooseUtils.C:490
std::string findTestRoot()
Definition MooseUtils.C:138
std::size_t fileSize(const std::string &filename)
bool wildCardMatch(std::string name, std::string search_string)
Definition MooseUtils.C:951
void addLineBreaks(std::string &message, unsigned int line_width)
Definition MooseUtils.C:793
std::list< std::string > listDir(const std::string path, bool files_only)
Definition MooseUtils.C:845
void serialBegin(const libMesh::Parallel::Communicator &comm, bool warn)
Definition MooseUtils.C:420
std::string getLatestCheckpointFilePrefix(const std::list< std::string > &checkpoint_files)
Definition MooseUtils.C:882
void clearSymlink(const std::string &link)
bool checkFileReadable(const std::string &filename, bool check_line_endings, bool throw_on_unreadable, bool check_for_git_lfs_pointer)
Definition MooseUtils.C:317
std::string runTestsExecutable()
Definition MooseUtils.C:128
std::string shortName(const std::string &name)
Definition MooseUtils.C:675
std::vector< std::string > rsplit(const std::string &str, const std::string &delimiter, std::size_t max_count)
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition Moose.h:175
std::string getExecutablePath()
Gets the directory the running executable is on Mac OS X and linux.
int mkdir(const char *pathname)
RATIONAL_BERNSTEIN
int main()