LCOV - code coverage report
Current view: top level - include/utils - MooseUtils.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 165 169 97.6 %
Date: 2025-07-17 01:28:37 Functions: 169 476 35.5 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #pragma once
      11             : 
      12             : // MOOSE includes
      13             : #include "MooseTypes.h"
      14             : #include "HashMap.h"
      15             : #include "InfixIterator.h"
      16             : #include "MooseEnumItem.h"
      17             : #include "MooseError.h"
      18             : #include "Moose.h"
      19             : #include "ExecutablePath.h"
      20             : #include "ConsoleUtils.h"
      21             : #include "MooseStringUtils.h"
      22             : 
      23             : #include "libmesh/compare_types.h"
      24             : #include "libmesh/bounding_box.h"
      25             : #include "libmesh/int_range.h"
      26             : #include "libmesh/tensor_tools.h"
      27             : #include "metaphysicl/raw_type.h"
      28             : #include "metaphysicl/metaphysicl_version.h"
      29             : #include "metaphysicl/dualnumber_decl.h"
      30             : #include "metaphysicl/dynamic_std_array_wrapper.h"
      31             : #include "timpi/standard_type.h"
      32             : 
      33             : // C++ includes
      34             : #include <string>
      35             : #include <vector>
      36             : #include <map>
      37             : #include <list>
      38             : #include <filesystem>
      39             : #include <deque>
      40             : #include <regex>
      41             : 
      42             : // Forward Declarations
      43             : class InputParameters;
      44             : class ExecFlagEnum;
      45             : class MaterialProperties;
      46             : class MaterialBase;
      47             : 
      48             : namespace libMesh
      49             : {
      50             : class Elem;
      51             : namespace Parallel
      52             : {
      53             : class Communicator;
      54             : }
      55             : }
      56             : class MultiMooseEnum;
      57             : 
      58             : namespace MooseUtils
      59             : {
      60             : 
      61             : std::filesystem::path pathjoin(const std::filesystem::path & p);
      62             : 
      63             : template <typename... Args>
      64             : std::filesystem::path
      65      318645 : pathjoin(const std::filesystem::path & p, Args... args)
      66             : {
      67      318645 :   return p / pathjoin(args...);
      68             : }
      69             : 
      70             : /// Check if the input string can be parsed into a Real
      71             : bool parsesToReal(const std::string & input);
      72             : 
      73             : /// Returns the location of either a local repo run_tests script - or an
      74             : /// installed test executor script if run_tests isn't found.
      75             : std::string runTestsExecutable();
      76             : 
      77             : /// Searches in the current working directory and then recursively up in each
      78             : /// parent directory looking for a "testroot" file.  Returns the full path to
      79             : /// the first testroot file found.
      80             : std::string findTestRoot();
      81             : 
      82             : /// Returns the directory of any installed inputs or the empty string if none are found.
      83             : std::string installedInputsDir(const std::string & app_name,
      84             :                                const std::string & dir_name,
      85             :                                const std::string & extra_error_msg = "");
      86             : 
      87             : /// Returns the directory of any installed docs/site.
      88             : std::string docsDir(const std::string & app_name);
      89             : 
      90             : /**
      91             :  * Returns the URL of a page located on the MOOSE documentation site.
      92             :  *
      93             :  * @param[in] path   URL path following the domain name. For example, in the
      94             :  *                   URL "www.example.com/folder1/folder2/file.html", this
      95             :  *                   would be "folder1/folder2/file.html".
      96             :  */
      97             : std::string mooseDocsURL(const std::string & path);
      98             : 
      99             : /// Replaces all occurrences of from in str with to and returns the result.
     100             : std::string replaceAll(std::string str, const std::string & from, const std::string & to);
     101             : 
     102             : /**
     103             :  * Replaces "LATEST" placeholders with the latest checkpoint file name.
     104             :  */
     105             : std::string convertLatestCheckpoint(std::string orig);
     106             : 
     107             : /// Computes and returns the Levenshtein distance between strings s1 and s2.
     108             : int levenshteinDist(const std::string & s1, const std::string & s2);
     109             : 
     110             : /**
     111             :  * This function will escape all of the standard C++ escape characters so that they can be printed.
     112             :  * The
     113             :  * passed in parameter is modified in place
     114             :  */
     115             : void escape(std::string & str);
     116             : 
     117             : /**
     118             :  * Removes additional whitespace from a string
     119             :  *
     120             :  * Removes beginning whitespace, end whitespace, and repeated whitespace into a single space
     121             :  */
     122             : std::string removeExtraWhitespace(const std::string & str);
     123             : 
     124             : /**
     125             :  * Python like split functions for strings.
     126             :  *
     127             :  * NOTE: This is similar to the tokenize function, but it maintains empty items, which tokenize does
     128             :  *       not. For example, "foo;bar;;" becomes {"foo", "bar", "", ""}.
     129             :  */
     130             : std::vector<std::string> split(const std::string & str,
     131             :                                const std::string & delimiter,
     132             :                                std::size_t max_count = std::numeric_limits<std::size_t>::max());
     133             : std::vector<std::string> rsplit(const std::string & str,
     134             :                                 const std::string & delimiter,
     135             :                                 std::size_t max_count = std::numeric_limits<std::size_t>::max());
     136             : 
     137             : /**
     138             :  * Python-like join function for strings over an iterator range.
     139             :  */
     140             : template <typename Iterator>
     141             : std::string
     142       99791 : join(Iterator begin, Iterator end, const std::string & delimiter)
     143             : {
     144       99791 :   std::ostringstream oss;
     145       99791 :   std::copy(begin, end, infix_ostream_iterator<std::string>(oss, delimiter.c_str()));
     146      199582 :   return oss.str();
     147       99791 : }
     148             : 
     149             : /**
     150             :  * Python-like join function for strings over a container.
     151             :  */
     152             : template <typename T>
     153             : std::string
     154       99653 : join(const T & strings, const std::string & delimiter)
     155             : {
     156       99653 :   return join(strings.begin(), strings.end(), delimiter);
     157             : }
     158             : 
     159             : /**
     160             :  * Check the file size.
     161             :  */
     162             : std::size_t fileSize(const std::string & filename);
     163             : 
     164             : /**
     165             :  * This function tokenizes a path and checks to see if it contains the string to look for
     166             :  */
     167             : bool pathContains(const std::string & expression,
     168             :                   const std::string & string_to_find,
     169             :                   const std::string & delims = "/");
     170             : 
     171             : /**
     172             :  * Checks to see if a file is readable (exists and permissions)
     173             :  * @param filename The filename to check
     174             :  * @param check_line_endings Whether or not to see if the file contains DOS line endings.
     175             :  * @param throw_on_unreadable Whether or not to throw a MOOSE error if the file doesn't exist
     176             :  * @param check_for_git_lfs_pointer Whether or not to call a subroutine utility to make sure that
     177             :  *   the file in question is not actually a git-lfs pointer.
     178             :  * @return a Boolean indicating whether the file exists and is readable
     179             :  */
     180             : bool checkFileReadable(const std::string & filename,
     181             :                        bool check_line_endings = false,
     182             :                        bool throw_on_unreadable = true,
     183             :                        bool check_for_git_lfs_pointer = true);
     184             : 
     185             : /**
     186             :  * Check if the file is writable (path exists and permissions)
     187             :  * @param filename The filename you want to see if you can write to.
     188             :  * @param throw_on_unwritable Whether or not to throw a MOOSE error if the file is not writable
     189             :  * return a Boolean indicating whether the file exists and is writable
     190             :  */
     191             : bool checkFileWriteable(const std::string & filename, bool throw_on_unwritable = true);
     192             : 
     193             : /**
     194             :  * Check if the file is a Git-LFS pointer. When using a repository that utilizes Git-LFS,
     195             :  * it's possible that the client may not have the right packages installed in which case
     196             :  * the clone will contain plain-text files with key information for retrieving the actual
     197             :  * (large) files. This can cause odd errors since the file technically exists, is readable,
     198             :  * and even has the right name/extension. However, the content of the file will not match
     199             :  * the expected content.
     200             :  * @param file A pointer to the open filestream.
     201             :  */
     202             : bool checkForGitLFSPointer(std::ifstream & file);
     203             : 
     204             : /**
     205             :  * This function implements a parallel barrier function but writes progress
     206             :  * to stdout.
     207             :  */
     208             : void parallelBarrierNotify(const libMesh::Parallel::Communicator & comm, bool messaging = true);
     209             : 
     210             : /**
     211             :  * This function marks the begin of a section of code that is executed in serial
     212             :  * rank by rank. The section must be closed with a call to serialEnd.
     213             :  * These functions are intended for debugging use to obtain clean terminal output
     214             :  * from multiple ranks (use --keep-cout).
     215             :  * @param comm The communicator to use
     216             :  * @param warn Whether or not to warn that something is being serialized
     217             :  */
     218             : void serialBegin(const libMesh::Parallel::Communicator & comm, bool warn = true);
     219             : 
     220             : /**
     221             :  * Closes a section of code that is executed in serial rank by rank, and that was
     222             :  * opened with a call to serialBegin. No MPI communication can happen in this block.
     223             :  * @param comm The communicator to use
     224             :  * @param warn Whether or not to warn that something is being serialized
     225             :  */
     226             : void serialEnd(const libMesh::Parallel::Communicator & comm, bool warn = true);
     227             : 
     228             : /**
     229             :  * Function tests if the supplied filename as the desired extension
     230             :  * @param filename The filename to test the extension
     231             :  * @param ext The extension to test for (do not include the .)
     232             :  * @param strip_exodus_ext When true, this function ignores -s* from the end of the extension
     233             :  * @return True if the filename has the supplied extension
     234             :  */
     235             : bool hasExtension(const std::string & filename, std::string ext, bool strip_exodus_ext = false);
     236             : 
     237             : /**
     238             :  * Gets the extension of the passed file name.
     239             :  * @param filename The filename of which to get the extension
     240             :  * @param rfind When true, searches for last "." in filename. Otherwise, searches for first "."
     241             :  * @return file_ext The extension of filename (does not include the leading "."). If filename has no
     242             :  * extension, returns "".
     243             :  */
     244             : std::string getExtension(const std::string & filename, const bool rfind = false);
     245             : 
     246             : /**
     247             :  * Removes any file extension from the given string s (i.e. any ".[extension]" suffix of s) and
     248             :  * returns the result.
     249             :  */
     250             : std::string stripExtension(const std::string & s, const bool rfind = false);
     251             : 
     252             : /**
     253             :  * Function for splitting path and filename
     254             :  * @param full_file A complete filename and path
     255             :  * @return A std::pair<std::string, std::string> containing the path and filename
     256             :  *
     257             :  * If the supplied filename does not contain a path, it returns "." as the path
     258             :  */
     259             : template <typename T>
     260             : std::pair<std::filesystem::path, std::filesystem::path>
     261       63690 : splitFileName(const T & full_file)
     262             : {
     263       63690 :   const auto p = std::filesystem::path(std::string(full_file));
     264             :   // Error if path ends with /
     265       63690 :   if (!p.has_filename())
     266           1 :     mooseError("Invalid full file name: ", p);
     267             : 
     268       63689 :   const auto d = p.parent_path();
     269      127378 :   return {d.empty() ? "." : d, p.filename()};
     270       63690 : }
     271             : 
     272             : /**
     273             :  * Returns the current working directory as a string. If there's a problem
     274             :  * obtaining the current working directory, this function just returns an
     275             :  * empty string. It doesn't not throw.
     276             :  */
     277             : std::string getCurrentWorkingDir();
     278             : 
     279             : /**
     280             :  * Recursively make directories
     281             :  * @param dir_name A complete path
     282             :  * @param throw_on_failure True to throw instead of error out when creating a directory is failed.
     283             :  *
     284             :  * The path can be relative like 'a/b/c' or absolute like '/a/b/c'.
     285             :  * The path is allowed to contain '.' or '..'.
     286             :  */
     287             : void makedirs(const std::string & dir_name, bool throw_on_failure = false);
     288             : 
     289             : /**
     290             :  * Recursively remove directories from inner-most when the directories are empty
     291             :  * @param dir_name A complete path
     292             :  * @param throw_on_failure True to throw instead of error out when deleting a directory is failed.
     293             :  *
     294             :  * The path can be relative like 'a/b/c' or absolute like '/a/b/c'.
     295             :  * The path is allowed to contain '.' or '..'.
     296             :  */
     297             : void removedirs(const std::string & dir_name, bool throw_on_failure = false);
     298             : 
     299             : /**
     300             :  * Function for converting a camel case name to a name containing underscores.
     301             :  * @param camel_case_name A string containing camel casing
     302             :  * @return a string containing no capital letters with underscores as appropriate
     303             :  */
     304             : std::string camelCaseToUnderscore(const std::string & camel_case_name);
     305             : 
     306             : /**
     307             :  * Function for converting an underscore name to a camel case name.
     308             :  * @param underscore_name A string containing underscores
     309             :  * @return a string containing camel casing
     310             :  */
     311             : std::string underscoreToCamelCase(const std::string & underscore_name, bool leading_upper_case);
     312             : 
     313             : /**
     314             :  * Function for stripping name after the file / in parser block
     315             :  */
     316             : std::string shortName(const std::string & name);
     317             : 
     318             : /**
     319             :  * Function for string the information before the final / in a parser block
     320             :  */
     321             : std::string baseName(const std::string & name);
     322             : 
     323             : /**
     324             :  * Get the hostname the current process is running on
     325             :  */
     326             : std::string hostname();
     327             : 
     328             : /**
     329             :  * Returns the width of the terminal using sys/ioctl
     330             :  */
     331             : unsigned short getTermWidth(bool use_environment);
     332             : 
     333             : /**
     334             :  * @returns A cleaner representation of the c++ type \p cpp_type.
     335             :  */
     336             : std::string prettyCppType(const std::string & cpp_type);
     337             : 
     338             : /**
     339             :  * @returns A cleaner representation of the type for the given object
     340             :  */
     341             : template <typename T>
     342             : std::string
     343      147214 : prettyCppType(const T * obj = nullptr)
     344             : {
     345      147214 :   if (obj)
     346       12000 :     return prettyCppType(libMesh::demangle(typeid(*obj).name()));
     347             :   else
     348      135214 :     return prettyCppType(libMesh::demangle(typeid(T).name()));
     349             : }
     350             : 
     351             : /**
     352             :  * This routine is a simple helper function for searching a map by values instead of keys
     353             :  */
     354             : template <typename T1, typename T2>
     355             : bool
     356      108390 : doesMapContainValue(const std::map<T1, T2> & the_map, const T2 & value)
     357             : {
     358      368709 :   for (typename std::map<T1, T2>::const_iterator iter = the_map.begin(); iter != the_map.end();
     359      260319 :        ++iter)
     360      352653 :     if (iter->second == value)
     361       92334 :       return true;
     362       16056 :   return false;
     363             : }
     364             : 
     365             : /**
     366             :  * Function to check whether two variables are equal within an absolute tolerance
     367             :  * @param var1 The first variable to be checked
     368             :  * @param var2 The second variable to be checked
     369             :  * @param tol The tolerance to be used
     370             :  * @return true if var1 and var2 are equal within tol
     371             :  */
     372             : template <
     373             :     typename T,
     374             :     typename T2,
     375             :     typename T3 = T,
     376             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     377             :                                 libMesh::ScalarTraits<T3>::value,
     378             :                             int>::type = 0>
     379             : bool
     380    40623479 : absoluteFuzzyEqual(const T & var1,
     381             :                    const T2 & var2,
     382    69541869 :                    const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     383             : {
     384    40623479 :   return (std::abs(MetaPhysicL::raw_value(var1) - MetaPhysicL::raw_value(var2)) <=
     385    40623479 :           MetaPhysicL::raw_value(tol));
     386             : }
     387             : 
     388             : /**
     389             :  * Function to check whether a variable is greater than or equal to another variable within an
     390             :  * absolute tolerance
     391             :  * @param var1 The first variable to be checked
     392             :  * @param var2 The second variable to be checked
     393             :  * @param tol The tolerance to be used
     394             :  * @return true if var1 > var2 or var1 == var2 within tol
     395             :  */
     396             : template <
     397             :     typename T,
     398             :     typename T2,
     399             :     typename T3 = T,
     400             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     401             :                                 libMesh::ScalarTraits<T3>::value,
     402             :                             int>::type = 0>
     403             : bool
     404      257022 : absoluteFuzzyGreaterEqual(const T & var1,
     405             :                           const T2 & var2,
     406      345653 :                           const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     407             : {
     408      257022 :   return (MetaPhysicL::raw_value(var1) >=
     409      257022 :           (MetaPhysicL::raw_value(var2) - MetaPhysicL::raw_value(tol)));
     410             : }
     411             : 
     412             : /**
     413             :  * Function to check whether a variable is greater than another variable within an absolute
     414             :  * tolerance
     415             :  * @param var1 The first variable to be checked
     416             :  * @param var2 The second variable to be checked
     417             :  * @param tol The tolerance to be used
     418             :  * @return true if var1 > var2 and var1 != var2 within tol
     419             :  */
     420             : template <
     421             :     typename T,
     422             :     typename T2,
     423             :     typename T3 = T,
     424             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     425             :                                 libMesh::ScalarTraits<T3>::value,
     426             :                             int>::type = 0>
     427             : bool
     428     4747202 : absoluteFuzzyGreaterThan(const T & var1,
     429             :                          const T2 & var2,
     430     7149437 :                          const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     431             : {
     432     4747202 :   return (MetaPhysicL::raw_value(var1) >
     433     4747202 :           (MetaPhysicL::raw_value(var2) + MetaPhysicL::raw_value(tol)));
     434             : }
     435             : 
     436             : /**
     437             :  * Function to check whether a variable is less than or equal to another variable within an absolute
     438             :  * tolerance
     439             :  * @param var1 The first variable to be checked
     440             :  * @param var2 The second variable to be checked
     441             :  * @param tol The tolerance to be used
     442             :  * @return true if var1 < var2 or var1 == var2 within tol
     443             :  */
     444             : template <
     445             :     typename T,
     446             :     typename T2,
     447             :     typename T3 = T,
     448             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     449             :                                 libMesh::ScalarTraits<T3>::value,
     450             :                             int>::type = 0>
     451             : bool
     452         270 : absoluteFuzzyLessEqual(const T & var1,
     453             :                        const T2 & var2,
     454         237 :                        const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     455             : {
     456         270 :   return (MetaPhysicL::raw_value(var1) <=
     457         270 :           (MetaPhysicL::raw_value(var2) + MetaPhysicL::raw_value(tol)));
     458             : }
     459             : 
     460             : /**
     461             :  * Function to check whether a variable is less than another variable within an absolute tolerance
     462             :  * @param var1 The first variable to be checked
     463             :  * @param var2 The second variable to be checked
     464             :  * @param tol The tolerance to be used
     465             :  * @return true if var1 < var2 and var1 != var2 within tol
     466             :  */
     467             : template <
     468             :     typename T,
     469             :     typename T2,
     470             :     typename T3 = T,
     471             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     472             :                                 libMesh::ScalarTraits<T3>::value,
     473             :                             int>::type = 0>
     474             : bool
     475      622313 : absoluteFuzzyLessThan(const T & var1,
     476             :                       const T2 & var2,
     477      827368 :                       const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     478             : {
     479      622313 :   return (MetaPhysicL::raw_value(var1) <
     480      622313 :           (MetaPhysicL::raw_value(var2) - MetaPhysicL::raw_value(tol)));
     481             : }
     482             : 
     483             : /**
     484             :  * Function to check whether two variables are equal within a relative tolerance
     485             :  * @param var1 The first variable to be checked
     486             :  * @param var2 The second variable to be checked
     487             :  * @param tol The relative tolerance to be used
     488             :  * @return true if var1 and var2 are equal within relative tol
     489             :  */
     490             : template <typename T, typename T2, typename T3 = Real>
     491             : bool
     492     5384148 : relativeFuzzyEqual(const T & var1,
     493             :                    const T2 & var2,
     494         637 :                    const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     495             : {
     496             :   if constexpr (libMesh::ScalarTraits<T>::value ||
     497             :                 libMesh::TensorTools::MathWrapperTraits<T>::value)
     498             :   {
     499             :     static_assert(libMesh::TensorTools::TensorTraits<T>::rank ==
     500             :                       libMesh::TensorTools::TensorTraits<T2>::rank,
     501             :                   "Mathematical types must be same for arguments to relativelyFuzzEqual");
     502             :     if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 0)
     503    10768296 :       return absoluteFuzzyEqual(
     504             :           var1,
     505             :           var2,
     506     5384148 :           tol * (std::abs(MetaPhysicL::raw_value(var1)) + std::abs(MetaPhysicL::raw_value(var2))));
     507             :     else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 1)
     508             :     {
     509             :       for (const auto i : make_range(Moose::dim))
     510             :         if (!relativeFuzzyEqual(var1(i), var2(i), tol))
     511             :           return false;
     512             : 
     513             :       return true;
     514             :     }
     515             :     else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 2)
     516             :     {
     517             :       for (const auto i : make_range(Moose::dim))
     518             :         for (const auto j : make_range(Moose::dim))
     519             :           if (!relativeFuzzyEqual(var1(i, j), var2(i, j), tol))
     520             :             return false;
     521             : 
     522             :       return true;
     523             :     }
     524             :   }
     525             :   else
     526             :   {
     527             :     // We dare to dream
     528             :     mooseAssert(var1.size() == var2.size(), "These must be the same size");
     529             :     for (const auto i : index_range(var1))
     530             :       if (!relativeFuzzyEqual(var1(i), var2(i), tol))
     531             :         return false;
     532             : 
     533             :     return true;
     534             :   }
     535             : }
     536             : 
     537             : /**
     538             :  * Function to check whether a variable is greater than or equal to another variable within a
     539             :  * relative tolerance
     540             :  * @param var1 The first variable to be checked
     541             :  * @param var2 The second variable to be checked
     542             :  * @param tol The tolerance to be used
     543             :  * @return true if var1 > var2 or var1 == var2 within relative tol
     544             :  */
     545             : template <
     546             :     typename T,
     547             :     typename T2,
     548             :     typename T3 = T,
     549             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     550             :                                 libMesh::ScalarTraits<T3>::value,
     551             :                             int>::type = 0>
     552             : bool
     553           4 : relativeFuzzyGreaterEqual(const T & var1,
     554             :                           const T2 & var2,
     555           8 :                           const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     556             : {
     557           8 :   return (absoluteFuzzyGreaterEqual(
     558             :       var1,
     559             :       var2,
     560           4 :       tol * (std::abs(MetaPhysicL::raw_value(var1)) + std::abs(MetaPhysicL::raw_value(var2)))));
     561             : }
     562             : 
     563             : /**
     564             :  * Function to check whether a variable is greater than another variable within a relative tolerance
     565             :  * @param var1 The first variable to be checked
     566             :  * @param var2 The second variable to be checked
     567             :  * @param tol The tolerance to be used
     568             :  * @return true if var1 > var2 and var1 != var2 within relative tol
     569             :  */
     570             : template <
     571             :     typename T,
     572             :     typename T2,
     573             :     typename T3 = T,
     574             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     575             :                                 libMesh::ScalarTraits<T3>::value,
     576             :                             int>::type = 0>
     577             : bool
     578           2 : relativeFuzzyGreaterThan(const T & var1,
     579             :                          const T2 & var2,
     580           4 :                          const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     581             : {
     582           4 :   return (absoluteFuzzyGreaterThan(
     583             :       var1,
     584             :       var2,
     585           2 :       tol * (std::abs(MetaPhysicL::raw_value(var1)) + std::abs(MetaPhysicL::raw_value(var2)))));
     586             : }
     587             : 
     588             : /**
     589             :  * Function to check whether a variable is less than or equal to another variable within a relative
     590             :  * tolerance
     591             :  * @param var1 The first variable to be checked
     592             :  * @param var2 The second variable to be checked
     593             :  * @param tol The tolerance to be used
     594             :  * @return true if var1 < var2 or var1 == var2 within relative tol
     595             :  */
     596             : template <
     597             :     typename T,
     598             :     typename T2,
     599             :     typename T3 = T,
     600             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     601             :                                 libMesh::ScalarTraits<T3>::value,
     602             :                             int>::type = 0>
     603             : bool
     604           4 : relativeFuzzyLessEqual(const T & var1,
     605             :                        const T2 & var2,
     606           8 :                        const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     607             : {
     608           8 :   return (absoluteFuzzyLessEqual(
     609             :       var1,
     610             :       var2,
     611           4 :       tol * (std::abs(MetaPhysicL::raw_value(var1)) + std::abs(MetaPhysicL::raw_value(var2)))));
     612             : }
     613             : 
     614             : /**
     615             :  * Function to check whether a variable is less than another variable within a relative tolerance
     616             :  * @param var1 The first variable to be checked
     617             :  * @param var2 The second variable to be checked
     618             :  * @param tol The tolerance to be used
     619             :  * @return true if var1 < var2 and var1 != var2 within relative tol
     620             :  */
     621             : template <
     622             :     typename T,
     623             :     typename T2,
     624             :     typename T3 = T,
     625             :     typename std::enable_if<libMesh::ScalarTraits<T>::value && libMesh::ScalarTraits<T2>::value &&
     626             :                                 libMesh::ScalarTraits<T3>::value,
     627             :                             int>::type = 0>
     628             : bool
     629        4714 : relativeFuzzyLessThan(const T & var1,
     630             :                       const T2 & var2,
     631        7072 :                       const T3 & tol = libMesh::TOLERANCE * libMesh::TOLERANCE)
     632             : {
     633        9428 :   return (absoluteFuzzyLessThan(
     634             :       var1,
     635             :       var2,
     636        4714 :       tol * (std::abs(MetaPhysicL::raw_value(var1)) + std::abs(MetaPhysicL::raw_value(var2)))));
     637             : }
     638             : 
     639             : /**
     640             :  * Function which takes the union of \p vector1 and \p vector2 and copies them
     641             :  * to \p common . Depending on the vector size and data type this can be very expensive!
     642             :  */
     643             : template <typename T>
     644             : void
     645       39419 : getUnion(const std::vector<T> & vector1, const std::vector<T> & vector2, std::vector<T> & common)
     646             : {
     647       39419 :   std::unordered_set<T> unique_elements;
     648       39419 :   unique_elements.reserve(vector1.size() + vector2.size());
     649             : 
     650       74812 :   for (const T & entry : vector1)
     651       35393 :     unique_elements.insert(entry);
     652       74812 :   for (const T & entry : vector2)
     653       35393 :     unique_elements.insert(entry);
     654             : 
     655             :   // Now populate the common vector with the union
     656       39419 :   common.clear();
     657       39419 :   common.assign(unique_elements.begin(), unique_elements.end());
     658       39419 : }
     659             : 
     660             : /**
     661             :  * Taken from https://stackoverflow.com/a/257382
     662             :  * Evaluating constexpr (Has_size<T>::value) in a templated method over class T will
     663             :  * return whether T is a standard container or a singleton
     664             :  */
     665             : template <typename T>
     666             : class Has_size
     667             : {
     668             :   using Yes = char;
     669             :   struct No
     670             :   {
     671             :     char x[2];
     672             :   };
     673             : 
     674             :   template <typename C>
     675             :   static Yes test(decltype(&C::size));
     676             :   template <typename C>
     677             :   static No test(...);
     678             : 
     679             : public:
     680             :   static constexpr bool value = sizeof(test<T>(0)) == sizeof(Yes);
     681             : };
     682             : 
     683             : /**
     684             :  * @param value The quantity to test for zero-ness
     685             :  * @param tolerance The tolerance for testing zero-ness. The default is 1e-18 for double precision
     686             :  * configurations of libMesh/MOOSE
     687             :  * @return whether the L_infty norm of the value is (close enough to) zero
     688             :  */
     689             : template <typename T>
     690             : bool
     691          20 : isZero(const T & value, const Real tolerance = TOLERANCE * TOLERANCE * TOLERANCE)
     692             : {
     693             :   if constexpr (Has_size<T>::value)
     694             :   {
     695           6 :     for (const auto & element : value)
     696           4 :       if (!isZero(element, tolerance))
     697           2 :         return false;
     698             : 
     699           2 :     return true;
     700             :   }
     701             :   else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 0)
     702           8 :     return MooseUtils::absoluteFuzzyEqual(MetaPhysicL::raw_value(value), 0, tolerance);
     703             :   else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 1)
     704             :   {
     705          10 :     for (const auto i : make_range(Moose::dim))
     706           8 :       if (!MooseUtils::absoluteFuzzyEqual(MetaPhysicL::raw_value(value(i)), 0, tolerance))
     707           2 :         return false;
     708             : 
     709           2 :     return true;
     710             :   }
     711             :   else if constexpr (libMesh::TensorTools::TensorTraits<T>::rank == 2)
     712             :   {
     713          10 :     for (const auto i : make_range(Moose::dim))
     714          26 :       for (const auto j : make_range(Moose::dim))
     715          20 :         if (!MooseUtils::absoluteFuzzyEqual(MetaPhysicL::raw_value(value(i, j)), 0, tolerance))
     716           2 :           return false;
     717             : 
     718           2 :     return true;
     719             :   }
     720             : }
     721             : 
     722             : /**
     723             :  * Function to dump the contents of MaterialPropertyStorage for debugging purposes
     724             :  * @param props The storage item to dump, this should be
     725             :  * MaterialPropertyStorage.props(state)
     726             :  *
     727             :  * Currently this only words for scalar material properties. Something to do as needed would be to
     728             :  * create a method in MaterialProperty
     729             :  * that may be overloaded to dump the type using template specialization.
     730             :  */
     731             : void MaterialPropertyStorageDump(
     732             :     const HashMap<const libMesh::Elem *, HashMap<unsigned int, MaterialProperties>> & props);
     733             : 
     734             : /**
     735             :  * Indents the supplied message given the prefix and color
     736             :  * @param prefix The prefix to use for indenting
     737             :  * @param message The message that will be indented
     738             :  * @param color The color to apply to the prefix (default CYAN)
     739             :  * @param indent_first_line If true this will indent the first line too (default)
     740             :  * @param post_prefix A string to append right after the prefix, defaults to a column and a space
     741             :  *
     742             :  * Takes a message like the following and indents it with another color code (see below)
     743             :  *
     744             :  * Input message:
     745             :  * COLOR_YELLOW
     746             :  * *** Warning ***
     747             :  * Something bad has happened and we want to draw attention to it with color
     748             :  * COLOR_DEFAULT
     749             :  *
     750             :  * Output message:
     751             :  * COLOR_CYAN sub_app: COLOR_YELLOW
     752             :  * COLOR_CYAN sub_app: COLOR_YELLOW *** Warning ***
     753             :  * COLOR_CYAN sub_app: COLOR_YELLOW Something bad has happened and we want to draw attention to it
     754             :  * with color
     755             :  * COLOR_DEFAULT
     756             :  *
     757             :  * Also handles single line color codes
     758             :  * COLOR_CYAN sub_app: 0 Nonlinear |R| = COLOR_GREEN 1.0e-10 COLOR_DEFAULT
     759             :  *
     760             :  * Not indenting the first line is useful in the case where the first line is actually finishing
     761             :  * the line before it.
     762             :  */
     763             : void indentMessage(const std::string & prefix,
     764             :                    std::string & message,
     765             :                    const char * color = COLOR_CYAN,
     766             :                    bool dont_indent_first_line = true,
     767             :                    const std::string & post_prefix = ": ");
     768             : 
     769             : /**
     770             :  * remove ANSI escape sequences for terminal color from msg
     771             :  */
     772             : std::string & removeColor(std::string & msg);
     773             : 
     774             : std::list<std::string> listDir(const std::string path, bool files_only = false);
     775             : 
     776             : bool pathExists(const std::string & path);
     777             : 
     778             : /**
     779             :  * Retrieves the names of all of the files contained within the list of directories passed into
     780             :  * the routine. The names returned will be the paths to the files relative to the current
     781             :  * directory.
     782             :  * @param directory_list The list of directories to retrieve files from.
     783             :  * @param file_only Whether or not to list only files
     784             :  */
     785             : std::list<std::string> getFilesInDirs(const std::list<std::string> & directory_list,
     786             :                                       const bool files_only = true);
     787             : 
     788             : /**
     789             :  * Returns the most recent checkpoint prefix (the four numbers at the beginning)
     790             :  * If a suitable file isn't found the empty string is returned
     791             :  * @param checkpoint_files the list of files to analyze
     792             :  */
     793             : std::string getLatestCheckpointFilePrefix(const std::list<std::string> & checkpoint_files);
     794             : 
     795             : /*
     796             :  * Checks to see if a string matches a search string
     797             :  * @param name The name to check
     798             :  * @param search_string The search string to check name against
     799             :  */
     800             : bool wildCardMatch(std::string name, std::string search_string);
     801             : 
     802             : /*
     803             :  * Checks to see if a candidate string matches a pattern string, permitting glob
     804             :  * wildcards (* and ?) anywhere in the pattern.
     805             :  * @param candidate The name to check
     806             :  * @param pattern The search string to check name candidate
     807             :  */
     808             : bool globCompare(const std::string & candidate,
     809             :                  const std::string & pattern,
     810             :                  std::size_t c = 0,
     811             :                  std::size_t p = 0);
     812             : 
     813             : template <typename T>
     814             : void
     815          24 : expandAllMatches(const std::vector<T> & candidates, std::vector<T> & patterns)
     816             : {
     817          24 :   std::set<T> expanded;
     818          72 :   for (const auto & p : patterns)
     819             :   {
     820          48 :     unsigned int found = 0;
     821         240 :     for (const auto & c : candidates)
     822         192 :       if (globCompare(c, p))
     823             :       {
     824          48 :         expanded.insert(c);
     825          48 :         found++;
     826             :       }
     827          48 :     if (!found)
     828           0 :       throw std::invalid_argument(p);
     829             :   }
     830          24 :   patterns.assign(expanded.begin(), expanded.end());
     831          24 : }
     832             : 
     833             : /**
     834             :  * convert takes a string representation of a number type and converts it to the number.
     835             :  * This method is here to get around deficiencies in the STL stoi and stod methods where they
     836             :  * might successfully convert part of a string to a number when we'd like to throw an error.
     837             :  */
     838             : template <typename T>
     839             : T
     840        6713 : convert(const std::string & str, bool throw_on_failure = false)
     841             : {
     842        6713 :   std::stringstream ss(str);
     843        1720 :   T val;
     844        6713 :   if ((ss >> val).fail() || !ss.eof())
     845             :   {
     846          13 :     std::string msg = std::string("Unable to convert '") + str + "' to type " +
     847             :                       libMesh::demangle(typeid(T).name());
     848             : 
     849          13 :     if (throw_on_failure)
     850          13 :       throw std::invalid_argument(msg);
     851             :     else
     852           0 :       mooseError(msg);
     853          13 :   }
     854             : 
     855        8420 :   return val;
     856        6713 : }
     857             : 
     858             : template <>
     859             : short int convert<short int>(const std::string & str, bool throw_on_failure);
     860             : 
     861             : template <>
     862             : unsigned short int convert<unsigned short int>(const std::string & str, bool throw_on_failure);
     863             : 
     864             : template <>
     865             : int convert<int>(const std::string & str, bool throw_on_failure);
     866             : 
     867             : template <>
     868             : unsigned int convert<unsigned int>(const std::string & str, bool throw_on_failure);
     869             : 
     870             : template <>
     871             : long int convert<long int>(const std::string & str, bool throw_on_failure);
     872             : 
     873             : template <>
     874             : unsigned long int convert<unsigned long int>(const std::string & str, bool throw_on_failure);
     875             : 
     876             : template <>
     877             : long long int convert<long long int>(const std::string & str, bool throw_on_failure);
     878             : 
     879             : template <>
     880             : unsigned long long int convert<unsigned long long int>(const std::string & str,
     881             :                                                        bool throw_on_failure);
     882             : 
     883             : /**
     884             :  * Create a symbolic link, if the link already exists it is replaced.
     885             :  */
     886             : void createSymlink(const std::string & target, const std::string & link);
     887             : 
     888             : /**
     889             :  * Remove a symbolic link, if the given filename is a link.
     890             :  */
     891             : void clearSymlink(const std::string & link);
     892             : 
     893             : /**
     894             :  * Returns a container that contains the content of second passed in container
     895             :  * inserted into the first passed in container (set or map union).
     896             :  */
     897             : template <typename T>
     898             : T
     899             : concatenate(T c1, const T & c2)
     900             : {
     901             :   c1.insert(c2.begin(), c2.end());
     902             :   return c1;
     903             : }
     904             : 
     905             : /**
     906             :  * Returns a vector that contains is the concatenation of the two passed in vectors.
     907             :  */
     908             : template <typename T>
     909             : std::vector<T>
     910             : concatenate(std::vector<T> c1, const std::vector<T> & c2)
     911             : {
     912             :   c1.insert(c1.end(), c2.begin(), c2.end());
     913             :   return c1;
     914             : }
     915             : 
     916             : /**
     917             :  * Returns the passed in vector with the item appended to it.
     918             :  */
     919             : template <typename T>
     920             : std::vector<T>
     921          33 : concatenate(std::vector<T> c1, const T & item)
     922             : {
     923          33 :   c1.push_back(item);
     924          33 :   return c1;
     925             : }
     926             : 
     927             : /**
     928             :  * Concatenates \p value into a single string separated by \p separator
     929             :  */
     930             : std::string stringJoin(const std::vector<std::string> & values,
     931             :                        const std::string & separator = " ");
     932             : 
     933             : /**
     934             :  * @return Whether or not \p value begins with \p begin_value
     935             :  */
     936             : bool beginsWith(const std::string & value, const std::string & begin_value);
     937             : 
     938             : /**
     939             :  * Return the number of digits for a number.
     940             :  *
     941             :  * This can foster quite a large discussion:
     942             :  * https://stackoverflow.com/questions/1489830/efficient-way-to-determine-number-of-digits-in-an-integer
     943             :  *
     944             :  * For our purposes I like the following algorithm.
     945             :  */
     946             : template <typename T>
     947             : int
     948        1747 : numDigits(const T & num)
     949             : {
     950        1747 :   return num > 9 ? static_cast<int>(std::log10(static_cast<double>(num))) + 1 : 1;
     951             : }
     952             : 
     953             : /**
     954             :  * Return the default ExecFlagEnum for MOOSE.
     955             :  */
     956             : ExecFlagEnum getDefaultExecFlagEnum();
     957             : 
     958             : /**
     959             :  * Robust string to integer conversion that fails for cases such at "1foo".
     960             :  * @param input The string to convert.
     961             :  * @param throw_on_failure Throw an invalid_argument exception instead of mooseError.
     962             :  */
     963             : int stringToInteger(const std::string & input, bool throw_on_failure = false);
     964             : 
     965             : /**
     966             :  * Linearly partition a number of items
     967             :  *
     968             :  * @param num_items The number of items to partition
     969             :  * @param num_chunks The number of chunks to partition into
     970             :  * @param chunk_id The ID of the chunk you are trying to get information about (typically the
     971             :  * current MPI rank)
     972             :  * @param num_local_items Output: The number of items for this chunk_id
     973             :  * @param local_items_begin Output: The first item for this chunk_id
     974             :  * @param local_items_end Output: One past the final item for this chunk_id
     975             :  */
     976             : void linearPartitionItems(dof_id_type num_items,
     977             :                           dof_id_type num_chunks,
     978             :                           dof_id_type chunk_id,
     979             :                           dof_id_type & num_local_items,
     980             :                           dof_id_type & local_items_begin,
     981             :                           dof_id_type & local_items_end);
     982             : 
     983             : /**
     984             :  * Return the chunk_id that is assigned to handle item_id
     985             :  *
     986             :  * @param num_items Global number of items to partition
     987             :  * @param num_chunks Total number of chunks to split into
     988             :  * @param item_id The item to find the chunk_id for
     989             :  * @return The chunk_id of the chunk that contains item_id
     990             :  */
     991             : processor_id_type
     992             : linearPartitionChunk(dof_id_type num_items, dof_id_type num_chunks, dof_id_type item_id);
     993             : 
     994             : /**
     995             :  * Wrapper around PetscGetRealPath, which is a cross-platform replacement for realpath
     996             :  */
     997             : std::string realpath(const std::string & path);
     998             : 
     999             : /**
    1000             :  * Custom type trait that has a ::value of true for types that cam be use interchangeably
    1001             :  * with Real. Most notably it is false for complex numbers, which do not have a
    1002             :  * strict ordering (and therefore no <,>,<=,>= operators).
    1003             :  */
    1004             : template <typename T>
    1005             : struct IsLikeReal
    1006             : {
    1007             :   static constexpr bool value = false;
    1008             : };
    1009             : template <>
    1010             : struct IsLikeReal<Real>
    1011             : {
    1012             :   static constexpr bool value = true;
    1013             : };
    1014             : template <>
    1015             : struct IsLikeReal<ADReal>
    1016             : {
    1017             :   static constexpr bool value = true;
    1018             : };
    1019             : 
    1020             : /**
    1021             :  * Custom type trait that has a ::value of true for types that can be broadcasted
    1022             :  */
    1023             : template <typename T>
    1024             : struct canBroadcast
    1025             : {
    1026             :   static constexpr bool value = std::is_base_of<TIMPI::DataType, TIMPI::StandardType<T>>::value ||
    1027             :                                 TIMPI::Has_buffer_type<TIMPI::Packing<T>>::value;
    1028             : };
    1029             : 
    1030             : ///@{ Comparison helpers that support the MooseUtils::Any wildcard which will match any value
    1031             : const static struct AnyType
    1032             : {
    1033             : } Any;
    1034             : 
    1035             : template <typename T1, typename T2>
    1036             : bool
    1037       43769 : wildcardEqual(const T1 & a, const T2 & b)
    1038             : {
    1039       43769 :   return a == b;
    1040             : }
    1041             : 
    1042             : template <typename T>
    1043             : bool
    1044             : wildcardEqual(const T &, AnyType)
    1045             : {
    1046             :   return true;
    1047             : }
    1048             : template <typename T>
    1049             : bool
    1050        5072 : wildcardEqual(AnyType, const T &)
    1051             : {
    1052        5072 :   return true;
    1053             : }
    1054             : ///@}
    1055             : 
    1056             : /**
    1057             :  * Find a specific pair in a container matching on first, second or both pair components
    1058             :  */
    1059             : template <typename C, typename It, typename M1, typename M2>
    1060             : auto
    1061       53411 : findPair(C & container, It start_iterator, const M1 & first, const M2 & second)
    1062             : {
    1063       53411 :   return std::find_if(start_iterator,
    1064             :                       container.end(),
    1065       48729 :                       [&](auto & item) {
    1066       48841 :                         return wildcardEqual(first, item.first) &&
    1067       48841 :                                wildcardEqual(second, item.second);
    1068       53411 :                       });
    1069             : }
    1070             : 
    1071             : /**
    1072             :  * Construct a valid bounding box from 2 arbitrary points
    1073             :  *
    1074             :  * If you have 2 points in space and you wish to construct a bounding box, you should use
    1075             :  * this method to avoid unexpected behavior of the underlying BoundingBox class in libMesh.
    1076             :  * BoundingBox class expect 2 points whose coordinates are "sorted" (i.e., x-, y- and -z
    1077             :  * coordinates of the first point are smaller then the corresponding coordinates of the second
    1078             :  * point). If this "sorting" is not present, the BoundingBox class will build an empty box and
    1079             :  * any further testing of points inside the box will fail. This method will allow you to obtain
    1080             :  * the correct bounding box for any valid combination of 2 corner points of a box.
    1081             :  *
    1082             :  * @param p1 First corner of the constructed bounding box
    1083             :  * @param p2 Second corner of the constructed bounding box
    1084             :  * @return Valid bounding box
    1085             :  */
    1086             : libMesh::BoundingBox buildBoundingBox(const Point & p1, const Point & p2);
    1087             : 
    1088             : /**
    1089             :  * Utility class template for a semidynamic vector with a maximum size N
    1090             :  * and a chosen dynamic size. This container avoids heap allocation and
    1091             :  * is meant as a replacement for small local std::vector variables.
    1092             :  * By default this class uses `value initialization`. This can be disabled
    1093             :  * using the third template parameter if uninitialized storage is acceptable,
    1094             :  */
    1095             : template <typename T, std::size_t N, bool value_init = true>
    1096             : class SemidynamicVector : public MetaPhysicL::DynamicStdArrayWrapper<T, MetaPhysicL::NWrapper<N>>
    1097             : {
    1098             :   typedef MetaPhysicL::DynamicStdArrayWrapper<T, MetaPhysicL::NWrapper<N>> Parent;
    1099             : 
    1100             : public:
    1101    19232003 :   SemidynamicVector(std::size_t size) : Parent()
    1102             :   {
    1103     4808003 :     Parent::resize(size);
    1104             :     if constexpr (value_init)
    1105    19201934 :       for (const auto i : make_range(size))
    1106    14393932 :         _data[i] = T{};
    1107     4808003 :   }
    1108             : 
    1109           1 :   void resize(std::size_t new_size)
    1110             :   {
    1111           1 :     [[maybe_unused]] const auto old_dynamic_n = Parent::size();
    1112             : 
    1113           1 :     Parent::resize(new_size);
    1114             : 
    1115             :     if constexpr (value_init)
    1116             :       for (const auto i : make_range(old_dynamic_n, _dynamic_n))
    1117             :         _data[i] = T{};
    1118           1 :   }
    1119             : 
    1120           1 :   void push_back(const T & v)
    1121             :   {
    1122           1 :     const auto old_dynamic_n = Parent::size();
    1123           1 :     Parent::resize(old_dynamic_n + 1);
    1124           1 :     _data[old_dynamic_n] = v;
    1125           1 :   }
    1126             : 
    1127             :   template <typename... Args>
    1128           1 :   void emplace_back(Args &&... args)
    1129             :   {
    1130           1 :     const auto old_dynamic_n = Parent::size();
    1131           1 :     Parent::resize(old_dynamic_n + 1);
    1132           1 :     (::new (&_data[old_dynamic_n]) T(std::forward<Args>(args)...));
    1133           1 :   }
    1134             : 
    1135           1 :   std::size_t max_size() const { return N; }
    1136             : 
    1137             :   using Parent::_data;
    1138             :   using Parent::_dynamic_n;
    1139             : };
    1140             : 
    1141             : /**
    1142             :  * The MooseUtils::get() specializations are used to support making
    1143             :  * forwards-compatible code changes from dumb pointers to smart pointers.
    1144             :  * The same line of code, e.g.
    1145             :  *
    1146             :  * libMesh::Parameters::Value * value = MooseUtils::get(map_iter->second);
    1147             :  *
    1148             :  * will then work regardless of whether map_iter->second is a dumb pointer
    1149             :  * or a smart pointer. Note that the smart pointer get() functions are const
    1150             :  * so they can be (ab)used to get a non-const pointer to the underlying
    1151             :  * resource. We are simply following this convention here.
    1152             :  */
    1153             : template <typename T>
    1154             : T *
    1155   684436052 : get(const std::unique_ptr<T> & u)
    1156             : {
    1157   684436052 :   return u.get();
    1158             : }
    1159             : 
    1160             : template <typename T>
    1161             : T *
    1162             : get(T * p)
    1163             : {
    1164             :   return p;
    1165             : }
    1166             : 
    1167             : template <typename T>
    1168             : T *
    1169             : get(const std::shared_ptr<T> & s)
    1170             : {
    1171             :   return s.get();
    1172             : }
    1173             : 
    1174             : /**
    1175             :  * This method detects whether two sets intersect without building a result set.
    1176             :  * It exits as soon as any intersection is detected.
    1177             :  */
    1178             : template <class InputIterator>
    1179             : bool
    1180          35 : setsIntersect(InputIterator first1, InputIterator last1, InputIterator first2, InputIterator last2)
    1181             : {
    1182          48 :   while (first1 != last1 && first2 != last2)
    1183             :   {
    1184          17 :     if (*first1 == *first2)
    1185           4 :       return true;
    1186             : 
    1187          13 :     if (*first1 < *first2)
    1188           0 :       ++first1;
    1189          13 :     else if (*first1 > *first2)
    1190          13 :       ++first2;
    1191             :   }
    1192          31 :   return false;
    1193             : }
    1194             : 
    1195             : template <class T>
    1196             : bool
    1197          35 : setsIntersect(const T & s1, const T & s2)
    1198             : {
    1199          35 :   return setsIntersect(s1.begin(), s1.end(), s2.begin(), s2.end());
    1200             : }
    1201             : 
    1202             : /**
    1203             :  * Courtesy https://stackoverflow.com/a/8889045 and
    1204             :  * https://en.cppreference.com/w/cpp/string/byte/isdigit
    1205             :  * @return Whether every character in the string is a digit
    1206             :  */
    1207             : inline bool
    1208     1786580 : isDigits(const std::string & str)
    1209             : {
    1210     4082627 :   return std::all_of(str.begin(), str.end(), [](unsigned char c) { return std::isdigit(c); });
    1211             : }
    1212             : 
    1213             : /**
    1214             :  * Courtesy https://stackoverflow.com/a/57163016 and
    1215             :  * https://stackoverflow.com/questions/447206/c-isfloat-function
    1216             :  * @return Whether the string is convertible to a float
    1217             :  */
    1218             : inline bool
    1219          16 : isFloat(const std::string & str)
    1220             : {
    1221          16 :   if (str.empty())
    1222           0 :     return false;
    1223             :   char * ptr;
    1224          16 :   strtof(str.c_str(), &ptr);
    1225          16 :   return (*ptr) == '\0';
    1226             : }
    1227             : 
    1228             : /**
    1229             :  * Gets the canonical path of the given path
    1230             :  */
    1231             : std::string canonicalPath(const std::string & path);
    1232             : 
    1233             : /**
    1234             :  * @returns Whether the \p string1 starts with \p string2
    1235             :  */
    1236             : bool startsWith(const std::string & string1, const std::string & string2);
    1237             : 
    1238             : /**
    1239             :  * Replace the starting string \p string2 of \p string1 with \p string3. A user should have checked
    1240             :  * that \p string1 \p startsWith \p string2
    1241             :  */
    1242             : void replaceStart(std::string & string1, const std::string & string2, const std::string & string3);
    1243             : 
    1244             : /**
    1245             :  * @returns whether every alphabetic character in a string is lower-case
    1246             :  */
    1247             : bool isAllLowercase(const std::string & str);
    1248             : } // MooseUtils namespace
    1249             : 
    1250             : namespace Moose
    1251             : {
    1252             : template <typename T>
    1253             : struct ADType;
    1254             : 
    1255             : template <typename T, std::size_t N, bool value_init>
    1256             : struct ADType<MooseUtils::SemidynamicVector<T, N, value_init>>
    1257             : {
    1258             :   typedef MooseUtils::SemidynamicVector<typename ADType<T>::type, N, value_init> type;
    1259             : };
    1260             : }
    1261             : 
    1262             : /**
    1263             :  * find, erase, length algorithm for removing a substring from a string
    1264             :  */
    1265             : void removeSubstring(std::string & main, const std::string & sub);
    1266             : 
    1267             : /**
    1268             :  * find, erase, length algorithm for removing a substring from a copy of a string
    1269             :  */
    1270             : std::string removeSubstring(const std::string & main, const std::string & sub);

Generated by: LCOV version 1.14