24#include "libmesh/parallel_algebra.h"
25#include "libmesh/parallel_sync.h"
29 ParallelObject(app.comm()),
30 _solution_invalidity_registry(
moose::internal::getSolutionInvalidityRegistry()),
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>>>
142 for (
const auto id : index_range(
_counts))
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);
211 _console << info.object_type <<
": " << info.message <<
"\n" << std::flush;
219 FullTable vtable({
"Object",
"Converged",
"Timestep",
"Total",
"Message"}, 4);
229 vtable.setColumnPrecision({
239 for (
const auto id : index_range(
_counts))
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({
281 for (
const auto id : index_range(
_counts))
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();
366 for (
const auto id : index_range(solution_invalidity.
_counts))
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);
unsigned int InvalidSolutionID
void dataStore(std::ostream &stream, SolutionInvalidity::TimestepCounts ×tep_counts, void *context)
void dataLoad(std::istream &stream, SolutionInvalidity::TimestepCounts ×tep_counts, void *context)
An inteface for the _console for outputting to the Console object.
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
A helper class for re-directing output streams to Console output objects form MooseObjects.
bool keyExists(const Key &key) const
std::size_t id(const Key &key) const
const Item & item(const std::size_t id) const
Base class for MOOSE-based applications.
The SolutionInvalidity will contain all the information about the occurrence(s) of solution invalidit...
SolutionInvalidityRegistry & _solution_invalidity_registry
Create a registry to keep track of the names and occurrences of the solution invalidity.
void printDebug(InvalidSolutionID _invalid_solution_id) const
Immediately print the section and message for debug purpose.
void flagInvalidSolutionInternal(const InvalidSolutionID _invalid_solution_id)
Increments solution invalid occurrences for each solution id.
SolutionInvalidity(MooseApp &app)
Create a new SolutionInvalidity.
const std::vector< InvalidCounts > & counts() const
Access the private solution invalidity counts.
bool _has_solution_error
Whether or not we have an invalid solution (only after a sync)
std::vector< InvalidCounts > _counts
Store the solution invalidity counts.
bool _has_recorded_issue
Whether or not we have ever had any warning or solution issue during the simulation.
bool hasInvalidSolutionError() const
Whether or not an invalid solution was encountered that was an error.
void accumulateIterationIntoTimeStepOccurences()
Pass the number of solution invalid occurrences from current iteration to cumulative counters.
TimeTable transientTable(unsigned int &time_interval) const
Build a VariadicTable for solution invalidity history.
void resetTimeStepOccurences()
Reset the number of solution invalid occurrences back to zero for the current time step.
void resetIterationOccurences()
Reset the number of solution invalid occurrences back to zero.
void print(const ConsoleStream &console) const
Print the summary table of Solution Invalid warnings.
void accumulateTimeStepIntoTotalOccurences(const unsigned int timestep_index)
Pass the number of solution invalid occurrences from current timestep to cumulative timestep counter ...
void syncIteration()
Sync iteration counts to main processor Sum across all processors.
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.
bool hasEverHadSolutionIssue() const
Whether or not any warning or invalid solution has ever been encountered during the simulation.
bool _has_solution_warning
Whether or not we have a warning (only after a sync)
bool _has_synced
Whether or not we've synced (can check counts/existance of warnings or errors)
bool hasInvalidSolution() const
Whether or not any invalid solution was encountered (error or warning).
FullTable summaryTable() const
Build a VariadicTable for solution invalidity.
void printHistory(const ConsoleStream &console, unsigned int ×tep_interval_size) const
Print the time history table of Solution Invalid warnings.
void max(const T &r, T &o, Request &req) const
A class for "pretty printing" a table of data.
void print(StreamType &stream)
Pretty print the table of data.
void setColumnFormat(const std::vector< VariadicTableColumnFormat > &column_format)
Set how to format numbers for each column.
processor_id_type processor_id() const
const Parallel::Communicator & comm() const
Helper class that stores the name associated with an invalid solution.
InvalidSolutionID registerInvalidity(const std::string &object_type, const std::string &message, const bool warning)
Call to register an invalid calculation.
void push_parallel_vector_data(const Communicator &comm, MapToVectors &&data, const ActionFunctor &act_on_data)
SolutionInvalidityRegistry & getSolutionInvalidityRegistry()
Get the global SolutionInvalidityRegistry singleton.
Struct used in InvalidCounts for storing the time history of invalid occurrences.
unsigned int timestep_index