24 #include "libmesh/parallel_algebra.h" 25 #include "libmesh/parallel_sync.h" 29 ParallelObject(app.comm()),
32 _has_solution_warning(false),
33 _has_solution_error(false),
34 _has_recorded_issue(false)
42 if (
_counts.size() <= _invalid_solution_id)
43 _counts.resize(_invalid_solution_id + 1);
45 ++
_counts[_invalid_solution_id].current_counts;
80 entry.current_counts = 0;
90 entry.current_timestep_counts = 0;
97 entry.current_timestep_counts += entry.current_counts;
104 if (entry.current_timestep_counts)
106 if (entry.timestep_counts.empty() ||
107 entry.timestep_counts.back().timestep_index != timestep_index)
108 entry.timestep_counts.emplace_back(timestep_index);
109 entry.timestep_counts.back().counts = entry.current_timestep_counts;
110 entry.total_counts += entry.current_timestep_counts;
117 console <<
"\nSolution Invalid Warnings:\n";
123 unsigned int & timestep_interval_size)
const 126 console <<
"\nSolution Invalid History:\n";
128 console <<
"\nWarnings History:\n";
135 std::map<processor_id_type, std::vector<std::tuple<std::string, std::string, int, unsigned int>>>
145 if (entry.current_counts)
148 data_to_send[0].emplace_back(
149 info.object_type,
info.message,
info.warning, entry.current_counts);
150 entry.current_counts = 0;
154 const auto receive_data = [
this](
const processor_id_type libmesh_dbg_var(pid),
const auto & data)
156 mooseAssert(
processor_id() == 0,
"Should only receive on processor 0");
158 for (
const auto & [object_type, message, warning_int,
counts] : data)
160 mooseAssert(
counts,
"Should not send data without counts");
164 const bool warning = warning_int;
172 "Inconsistent registration of invalidity warning and error");
176 mooseAssert(pid != 0,
"Should only hit on other processors");
178 object_type, message, warning);
219 FullTable vtable({
"Object",
"Converged",
"Timestep",
"Total",
"Message"}, 4);
229 vtable.setColumnPrecision({
241 const auto & entry =
_counts[id];
242 if (entry.current_counts)
245 vtable.addRow(
info.object_type,
246 entry.current_counts,
247 entry.current_timestep_counts,
263 TimeTable vtable({
"Object",
"Step",
"Interval Count",
"Total Count"}, 4);
272 vtable.setColumnPrecision({
283 const auto & entry =
_counts[id];
285 std::vector<unsigned int> interval_counts;
286 std::vector<unsigned int> total_counts;
288 if (!entry.timestep_counts.empty())
291 for (
unsigned int timestep = 0; timestep <= entry.timestep_counts.back().timestep_index;
292 timestep += step_interval)
295 auto start_it = timestep;
296 auto end_it = (timestep + step_interval < entry.timestep_counts.back().timestep_index)
297 ? start_it + step_interval
298 : entry.timestep_counts.back().timestep_index;
300 int interval_sum = 0;
301 for (
auto ts_count : entry.timestep_counts)
304 if (ts_count.timestep_index >= start_it &&
305 (ts_count.timestep_index < end_it || start_it == end_it))
306 interval_sum += ts_count.counts;
309 interval_counts.push_back(interval_sum);
313 unsigned int interval_sum = 0;
314 for (
unsigned int interval_index :
index_range(interval_counts))
316 std::string interval_index_str =
317 (step_interval > 1) ? std::to_string(interval_index) +
"-" +
318 std::to_string(interval_index + step_interval - 1)
319 : std::to_string(interval_index);
321 interval_sum += interval_counts[interval_index];
322 vtable.addRow(
info.object_type +
" : " +
info.message,
324 interval_counts[interval_index],
363 std::size_t size = solution_invalidity.
_counts.size();
368 auto & entry = solution_invalidity.
_counts[id];
370 std::string type =
info.object_type;
371 std::string message =
info.message;
372 bool warning =
info.warning;
376 dataStore(stream, entry.current_counts, context);
377 dataStore(stream, entry.current_timestep_counts, context);
378 dataStore(stream, entry.timestep_counts, context);
379 dataStore(stream, entry.total_counts, context);
389 std::size_t num_counts;
391 dataLoad(stream, num_counts, context);
393 std::string object_type, message;
398 for (
size_t i = 0; i < num_counts; i++)
400 dataLoad(stream, object_type, context);
409 object_type, message, warning);
411 if (solution_invalidity.
_counts.size() <= id)
412 solution_invalidity.
_counts.resize(
id + 1);
414 auto & entry = solution_invalidity.
_counts[id];
415 dataLoad(stream, entry.current_counts, context);
416 dataLoad(stream, entry.current_timestep_counts, context);
417 dataLoad(stream, entry.timestep_counts, context);
418 dataLoad(stream, entry.total_counts, context);
std::string name(const ElemQuality q)
bool hasInvalidSolutionError() const
Whether or not an invalid solution was encountered that was an error.
bool hasEverHadSolutionIssue() const
Whether or not any warning or invalid solution has ever been encountered during the simulation...
A helper class for re-directing output streams to Console output objects form MooseObjects.
void dataStore(std::ostream &stream, SolutionInvalidity::TimestepCounts ×tep_counts, void *context)
void accumulateTimeStepIntoTotalOccurences(const unsigned int timestep_index)
Pass the number of solution invalid occurrences from current timestep to cumulative timestep counter ...
bool _has_recorded_issue
Whether or not we have ever had any warning or solution issue during the simulation.
bool hasInvalidSolutionWarning() const
Whether or not an invalid solution was encountered that was a warning.
std::mutex _invalid_mutex
Mutex for locking access to the invalid counts TODO: These can be changed to shared_mutexes.
const std::vector< InvalidCounts > & counts() const
Access the private solution invalidity counts.
void print(StreamType &stream)
Pretty print the table of data.
unsigned int InvalidSolutionID
void accumulateIterationIntoTimeStepOccurences()
Pass the number of solution invalid occurrences from current iteration to cumulative counters...
std::vector< InvalidCounts > _counts
Store the solution invalidity counts.
void dataLoad(std::istream &stream, SolutionInvalidity::TimestepCounts ×tep_counts, void *context)
SolutionInvalidity(MooseApp &app)
Create a new SolutionInvalidity.
bool _has_synced
Whether or not we've synced (can check counts/existance of warnings or errors)
A class for "pretty printing" a table of data.
void printDebug(InvalidSolutionID _invalid_solution_id) const
Immediately print the section and message for debug purpose.
Base class for MOOSE-based applications.
SolutionInvalidityRegistry & _solution_invalidity_registry
Create a registry to keep track of the names and occurrences of the solution invalidity.
const Parallel::Communicator & comm() const
InvalidSolutionID registerInvalidity(const std::string &object_type, const std::string &message, const bool warning)
Call to register an invalid calculation.
void resetIterationOccurences()
Reset the number of solution invalid occurrences back to zero.
TimeTable transientTable(unsigned int &time_interval) const
Build a VariadicTable for solution invalidity history.
unsigned int timestep_index
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
uint8_t processor_id_type
void syncIteration()
Sync iteration counts to main processor Sum across all processors.
std::size_t id(const Key &key) const
bool _has_solution_warning
Whether or not we have a warning (only after a sync)
const Item & item(const std::size_t id) const
An inteface for the _console for outputting to the Console object.
bool hasInvalidSolution() const
Whether or not any invalid solution was encountered (error or warning).
Helper class that stores the name associated with an invalid solution.
void flagInvalidSolutionInternal(const InvalidSolutionID _invalid_solution_id)
Increments solution invalid occurrences for each solution id.
void setColumnFormat(const std::vector< VariadicTableColumnFormat > &column_format)
Set how to format numbers for each column.
bool _has_solution_error
Whether or not we have an invalid solution (only after a sync)
The SolutionInvalidity will contain all the information about the occurrence(s) of solution invalidit...
Struct used in InvalidCounts for storing the time history of invalid occurrences. ...
SolutionInvalidityRegistry & getSolutionInvalidityRegistry()
Get the global SolutionInvalidityRegistry singleton.
void max(const T &r, T &o, Request &req) const
void print(const ConsoleStream &console) const
Print the summary table of Solution Invalid warnings.
bool keyExists(const Key &key) const
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
void resetTimeStepOccurences()
Reset the number of solution invalid occurrences back to zero for the current time step...
void printHistory(const ConsoleStream &console, unsigned int ×tep_interval_size) const
Print the time history table of Solution Invalid warnings.
processor_id_type processor_id() const
auto index_range(const T &sizable)
FullTable summaryTable() const
Build a VariadicTable for solution invalidity.