aboutsummaryrefslogtreecommitdiff
path: root/Source/ablastr/warn_manager/WarnManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/ablastr/warn_manager/WarnManager.cpp')
-rw-r--r--Source/ablastr/warn_manager/WarnManager.cpp312
1 files changed, 312 insertions, 0 deletions
diff --git a/Source/ablastr/warn_manager/WarnManager.cpp b/Source/ablastr/warn_manager/WarnManager.cpp
new file mode 100644
index 000000000..cd440615d
--- /dev/null
+++ b/Source/ablastr/warn_manager/WarnManager.cpp
@@ -0,0 +1,312 @@
+/* Copyright 2022 Luca Fedeli
+ *
+ * This file is part of WarpX.
+ *
+ * License: BSD-3-Clause-LBNL
+ */
+
+#include "WarnManager.H"
+
+#include "ablastr/utils/msg_logger/MsgLogger.H"
+#include "ablastr/utils/TextMsg.H"
+
+#include <AMReX_ParallelDescriptor.H>
+
+#include <algorithm>
+#include <sstream>
+
+namespace abl_msg_logger = ablastr::utils::msg_logger;
+using namespace ablastr::warn_manager;
+
+namespace
+{
+ WarnPriority MapPriorityToWarnPriority (
+ const abl_msg_logger::Priority& priority)
+ {
+ using namespace abl_msg_logger;
+ if (priority == Priority::low)
+ return WarnPriority::low;
+ else if (priority == Priority::medium)
+ return WarnPriority::medium;
+ else if (priority == Priority::high)
+ return WarnPriority::high;
+ else
+ ablastr::utils::TextMsg::Err(
+ "Parsing Priority to WarnPriority has failed");
+
+ return WarnPriority::high;
+ }
+}
+
+WarnManager& WarnManager::GetInstance() {
+ static auto warn_manager = WarnManager{};
+ return warn_manager;
+}
+
+WarnManager::WarnManager():
+ m_rank{amrex::ParallelDescriptor::MyProc()},
+ m_p_logger{std::make_unique<abl_msg_logger::Logger>()}
+{}
+
+void WarnManager::RecordWarning(
+ std::string topic,
+ std::string text,
+ WarnPriority priority)
+{
+ auto msg_priority = abl_msg_logger::Priority::high;
+ if(priority == WarnPriority::low)
+ msg_priority = abl_msg_logger::Priority::low;
+ else if(priority == WarnPriority::medium)
+ msg_priority = abl_msg_logger::Priority::medium;
+
+ if(m_always_warn_immediately){
+
+ amrex::Warning(
+ ablastr::utils::TextMsg::Warn(
+ "["
+ + std::string(abl_msg_logger::PriorityToString(msg_priority))
+ + "]["
+ + topic
+ + "] "
+ + text));
+ }
+
+#ifdef AMREX_USE_OMP
+ #pragma omp critical
+#endif
+ {
+ m_p_logger->record_msg(abl_msg_logger::Msg{topic, text, msg_priority});
+ }
+
+ if(m_abort_on_warning_threshold){
+
+ auto abort_priority = abl_msg_logger::Priority::high;
+ if(m_abort_on_warning_threshold == WarnPriority::low)
+ abort_priority = abl_msg_logger::Priority::low;
+ else if(m_abort_on_warning_threshold == WarnPriority::medium)
+ abort_priority = abl_msg_logger::Priority::medium;
+
+ ABLASTR_ALWAYS_ASSERT_WITH_MESSAGE(
+ msg_priority < abort_priority,
+ "A warning with priority '"
+ + abl_msg_logger::PriorityToString(msg_priority)
+ + "' has been raised."
+ );
+ }
+}
+
+std::string WarnManager::PrintLocalWarnings(const std::string& when) const
+{
+ auto all_warnings = m_p_logger->get_msgs_with_counter();
+ std::sort(all_warnings.begin(), all_warnings.end(),
+ [](const auto& a, const auto& b){return a.msg < b.msg;});
+
+ std::stringstream ss;
+
+ ss << "\n" << WarnManager::GetHeader(when, warn_line_size, false);
+
+ if(all_warnings.empty()){
+ ss << "* No recorded warnings.\n";
+ }
+ else{
+ for(const auto& warn_msg : all_warnings){
+ ss << PrintWarnMsg(warn_msg);
+ ss << "*\n";
+ }
+ }
+
+ ss << std::string(warn_line_size, '*') << "\n\n" ;
+
+ return ss.str();
+}
+
+std::string WarnManager::PrintGlobalWarnings(const std::string& when) const
+{
+ auto all_warnings =
+ m_p_logger->collective_gather_msgs_with_counter_and_ranks();
+
+ if(m_rank != amrex::ParallelDescriptor::IOProcessorNumber())
+ return "[see I/O rank message]";
+
+ std::sort(all_warnings.begin(), all_warnings.end(),
+ [](const auto& a, const auto& b){
+ return a.msg_with_counter.msg < b.msg_with_counter.msg;});
+
+ std::stringstream ss;
+
+ ss << "\n" << WarnManager::GetHeader(when, warn_line_size, true);
+
+ if(all_warnings.empty()){
+ ss << "* No recorded warnings.\n";
+ }
+ else{
+ for(const auto& warn_msg : all_warnings){
+ ss << PrintWarnMsg(warn_msg);
+ ss << "*\n";
+ }
+ }
+
+ ss << std::string(warn_line_size, '*') << "\n\n" ;
+
+ return ss.str();
+}
+
+void WarnManager::SetAlwaysWarnImmediately(bool always_warn_immediately)
+{
+ m_always_warn_immediately = always_warn_immediately;
+}
+
+bool WarnManager::GetAlwaysWarnImmediatelyFlag() const
+{
+ return m_always_warn_immediately;
+}
+
+void WarnManager::SetAbortThreshold(std::optional<WarnPriority> abort_threshold)
+{
+ m_abort_on_warning_threshold = abort_threshold;
+}
+
+std::optional<WarnPriority> WarnManager::GetAbortThreshold() const
+{
+ return m_abort_on_warning_threshold;
+}
+
+void WarnManager::debug_read_warnings_from_input(amrex::ParmParse& params)
+{
+ std::vector<std::string> warnings;
+ params.queryarr("test_warnings", warnings);
+
+ for (const auto& warn : warnings){
+ amrex::ParmParse pp_warn(warn);
+
+ std::string topic;
+ pp_warn.query("topic", topic);
+
+ std::string msg;
+ pp_warn.query("msg", msg);
+
+ std::string spriority;
+ pp_warn.query("priority", spriority);
+ const auto wpriority = MapPriorityToWarnPriority(
+ abl_msg_logger::StringToPriority(spriority));
+
+ int all_involved = 0;
+ pp_warn.query("all_involved", all_involved);
+ if(all_involved != 0){
+ this->RecordWarning(topic, msg, wpriority);
+ }
+ else{
+ std::vector<int> who_involved;
+ pp_warn.queryarr("who_involved", who_involved);
+ if(std::find (who_involved.begin(), who_involved.end(), m_rank)
+ != who_involved.end()){
+ this->RecordWarning(topic, msg, wpriority);
+ }
+ }
+ }
+
+}
+
+std::string WarnManager::PrintWarnMsg(
+ const abl_msg_logger::MsgWithCounter& msg_with_counter) const
+{
+ std::stringstream ss;
+ ss << "* --> ";
+ if (msg_with_counter.msg.priority == abl_msg_logger::Priority::high)
+ ss << "[!!!]";
+ else if (msg_with_counter.msg.priority == abl_msg_logger::Priority::medium)
+ ss << "[!! ]";
+ else if (msg_with_counter.msg.priority == abl_msg_logger::Priority::low)
+ ss << "[! ]";
+ else
+ ss << "[???]";
+
+ ss << " [" + msg_with_counter.msg.topic << "] ";
+
+ if(msg_with_counter.counter == 2)
+ ss << "[raised twice]\n";
+ else if(msg_with_counter.counter == 1)
+ ss << "[raised once]\n";
+ else
+ ss << "[raised " << msg_with_counter.counter << " times]\n";
+
+ ss << MsgFormatter(msg_with_counter.msg.text, warn_line_size, warn_tab_size);
+
+ return ss.str();
+}
+
+std::string WarnManager::PrintWarnMsg(
+ const abl_msg_logger::MsgWithCounterAndRanks& msg_with_counter_and_ranks) const
+{
+ std::stringstream ss;
+ ss << this->PrintWarnMsg(msg_with_counter_and_ranks.msg_with_counter);
+
+ std::string raised_by = "@ Raised by: ";
+ if (!msg_with_counter_and_ranks.all_ranks){
+ for (const auto rr : msg_with_counter_and_ranks.ranks)
+ raised_by += " " + std::to_string(rr);
+ }
+ else{
+ raised_by += "ALL\n";
+ }
+ ss << WarnManager::MsgFormatter(raised_by, warn_line_size, warn_tab_size);
+
+ return ss.str();
+}
+
+std::string WarnManager::GetHeader(
+ const std::string& when,
+ const int line_size,
+ const bool is_global)
+{
+ const std::string warn_header{"**** WARNINGS "};
+
+ std::stringstream ss;
+
+ ss << warn_header <<
+ std::string(line_size - static_cast<int>(warn_header.length()), '*') << "\n" ;
+
+ if(is_global){
+ ss << "* GLOBAL warning list after " << " [ " << when << " ]\n*\n";
+ }
+ else{
+ auto const mpi_rank = amrex::ParallelDescriptor::MyProc();
+ ss << "* LOCAL" << " ( rank # " << mpi_rank << " ) "
+ << " warning list after " << when << "\n*\n";
+ }
+
+ return ss.str();
+}
+
+std::string
+WarnManager::MsgFormatter(
+ const std::string& msg,
+ const int line_size,
+ const int tab_size)
+{
+ const auto prefix = "*" + std::string(tab_size, ' ');
+ const auto prefix_length = static_cast<int>(prefix.length());
+
+ const auto wrapped_text = ablastr::utils::automatic_text_wrap(
+ msg, line_size-prefix_length);
+
+ std::stringstream ss_out;
+ for (const auto& line : wrapped_text)
+ ss_out << prefix << line << "\n";
+
+ return ss_out.str();
+}
+
+WarnManager& ablastr::warn_manager::GetWMInstance()
+{
+ return WarnManager::GetInstance();
+}
+
+void ablastr::warn_manager::WMRecordWarning(
+ std::string topic,
+ std::string text,
+ WarnPriority priority)
+{
+ WarnManager::GetInstance().RecordWarning(
+ topic, text, priority);
+}