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 "MooseError.h" 15 : #include "SolutionInvalidityRegistry.h" 16 : #include "ConsoleStream.h" 17 : #include "ConsoleStreamInterface.h" 18 : 19 : // System Includes 20 : #include <array> 21 : #include <atomic> 22 : #include <thread> 23 : #include <future> 24 : #include <mutex> 25 : 26 : // libMesh Includes 27 : #include "libmesh/parallel_object.h" 28 : 29 : // Forward Declarations 30 : template <class... Ts> 31 : class VariadicTable; 32 : 33 : /** 34 : * The SolutionInvalidity will contain all the information about the occurrence(s) of solution 35 : * invalidity 36 : */ 37 : class SolutionInvalidity : protected ConsoleStreamInterface, public libMesh::ParallelObject 38 : { 39 : public: 40 : using SolutionInvalidityRegistry = moose::internal::SolutionInvalidityRegistry; 41 : 42 : /** 43 : * Create a new SolutionInvalidity 44 : */ 45 : SolutionInvalidity(MooseApp & app); 46 : 47 : /// Increments solution invalid occurrences for each solution id 48 : void flagInvalidSolutionInternal(const InvalidSolutionID _invalid_solution_id); 49 : 50 : /** 51 : * Whether or not an invalid solution was encountered that was a warning. 52 : * 53 : * This must be called after a sync. 54 : */ 55 : bool hasInvalidSolutionWarning() const; 56 : 57 : /** 58 : * Whether or not an invalid solution was encountered that was an error. 59 : * 60 : * This must be called after a sync. 61 : */ 62 : bool hasInvalidSolutionError() const; 63 : 64 : /** 65 : * Whether or not any invalid solution was encountered (error or warning). 66 : * 67 : * This must be called after a sync. 68 : */ 69 : bool hasInvalidSolution() const; 70 : 71 : /** 72 : * Whether or not any warning or invalid solution has ever been encountered during the simulation 73 : * 74 : * This must be called after a sync. 75 : */ 76 : bool hasEverHadSolutionIssue() const; 77 : 78 : /// Reset the number of solution invalid occurrences back to zero for the current time step 79 : void resetTimeStepOccurences(); 80 : 81 : /// Reset the number of solution invalid occurrences back to zero 82 : void resetIterationOccurences(); 83 : 84 : /// Pass the number of solution invalid occurrences from current iteration to cumulative counters 85 : void accumulateIterationIntoTimeStepOccurences(); 86 : 87 : /// Pass the number of solution invalid occurrences from current timestep to cumulative timestep counter (e.g. the total) 88 : void accumulateTimeStepIntoTotalOccurences(const unsigned int timestep_index); 89 : 90 : /// Struct used in InvalidCounts for storing the time history of invalid occurrences 91 : struct TimestepCounts 92 : { 93 186 : TimestepCounts() : timestep_index(std::numeric_limits<unsigned int>::max()) {} 94 1877 : TimestepCounts(unsigned int timestep_index) : timestep_index(timestep_index) {} 95 : unsigned int timestep_index; 96 : unsigned int counts = 0; 97 : }; 98 : 99 : /// Struct used in _counts for storing warning and invalid-solution occurrences 100 : struct InvalidCounts 101 : { 102 : /// Counts for the current iteration (depends on the count, but usually linear iteration) 103 : unsigned int current_counts = 0; 104 : /// Counts for the current time step 105 : unsigned int current_timestep_counts = 0; 106 : /// Total counts across the entire simulation 107 : unsigned int total_counts = 0; 108 : /// Keep track of the occurences across all time steps 109 : std::vector<TimestepCounts> timestep_counts; 110 : }; 111 : 112 : /// Access the private solution invalidity counts 113 166 : const std::vector<InvalidCounts> & counts() const { return _counts; } 114 : 115 : /** 116 : * Print the summary table of Solution Invalid warnings 117 : * @param console The output stream to output to 118 : */ 119 : void print(const ConsoleStream & console) const; 120 : 121 : /** 122 : * Print the time history table of Solution Invalid warnings 123 : * @param console The output stream to output to 124 : */ 125 : void printHistory(const ConsoleStream & console, unsigned int & timestep_interval_size) const; 126 : 127 : /** 128 : * Immediately print the section and message for debug purpose 129 : */ 130 : void printDebug(InvalidSolutionID _invalid_solution_id) const; 131 : 132 : /** 133 : * Sync iteration counts to main processor 134 : * Sum across all processors 135 : */ 136 : void syncIteration(); 137 : 138 : /// Whether the solution invalidity has synchronized iteration counts across MPI processes 139 308629 : bool hasSynced() const { return _has_synced; } 140 : 141 : friend void dataStore(std::ostream &, SolutionInvalidity &, void *); 142 : friend void dataLoad(std::istream &, SolutionInvalidity &, void *); 143 : 144 : private: 145 : /// Mutex for locking access to the invalid counts 146 : /// TODO: These can be changed to shared_mutexes 147 : mutable std::mutex _invalid_mutex; 148 : 149 : typedef VariadicTable<std::string, 150 : unsigned long int, 151 : unsigned long int, 152 : unsigned long int, 153 : std::string> 154 : FullTable; 155 : 156 : /// Build a VariadicTable for solution invalidity 157 : FullTable summaryTable() const; 158 : 159 : typedef VariadicTable<std::string, std::string, unsigned long int, unsigned long int> TimeTable; 160 : 161 : /// Build a VariadicTable for solution invalidity history 162 : TimeTable transientTable(unsigned int & time_interval) const; 163 : 164 : /// Create a registry to keep track of the names and occurrences of the solution invalidity 165 : SolutionInvalidityRegistry & _solution_invalidity_registry; 166 : 167 : /// Store the solution invalidity counts 168 : std::vector<InvalidCounts> _counts; 169 : 170 : /// Whether or not we've synced (can check counts/existance of warnings or errors) 171 : bool _has_synced; 172 : /// Whether or not we have a warning (only after a sync) 173 : bool _has_solution_warning; 174 : /// Whether or not we have an invalid solution (only after a sync) 175 : bool _has_solution_error; 176 : /// Whether or not we have ever had any warning or solution issue during the simulation 177 : bool _has_recorded_issue; 178 : }; 179 : 180 : // datastore and dataload for recover 181 : void dataStore(std::ostream & stream, 182 : SolutionInvalidity::TimestepCounts & timestep_counts, 183 : void * context); 184 : void dataLoad(std::istream & stream, 185 : SolutionInvalidity::TimestepCounts & timestep_counts, 186 : void * context); 187 : void dataStore(std::ostream & stream, SolutionInvalidity & solution_invalidity, void * context); 188 : void dataLoad(std::istream & stream, SolutionInvalidity & solution_invalidity, void * context);