Deferred logger will throw "correct" exception

This commit is contained in:
Joakim Hove 2021-03-18 08:29:23 +01:00
parent 984ea28d6f
commit 634f0d61d8
3 changed files with 142 additions and 35 deletions

View File

@ -33,6 +33,25 @@ namespace Opm
* 2) a call to logMessages adds the messages to OpmLog backends * 2) a call to logMessages adds the messages to OpmLog backends
* */ * */
namespace ExceptionType
{
/*
If an exception has been raised on more than processor simultaneously the
highest number type will be thrown in the subsequent global rethrow.
*/
enum ExcEnum {
NONE = 0,
RUNTIME_ERROR = 1,
INVALID_ARGUMENT = 2,
LOGIC_ERROR = 3,
DEFAULT = 4, // will throw std::logic_error()
};
}
class DeferredLogger class DeferredLogger
{ {
public: public:

View File

@ -49,15 +49,40 @@
throw Exception(oss__.str()); \ throw Exception(oss__.str()); \
} while (false) } while (false)
inline void checkForExceptionsAndThrow(int exception_thrown, const std::string& message) namespace {
{
void _throw(Opm::ExceptionType::ExcEnum exc_type, const std::string& message) {
const auto& cc = Dune::MPIHelper::getCollectiveCommunication(); const auto& cc = Dune::MPIHelper::getCollectiveCommunication();
if (cc.max(exception_thrown) == 1) { auto global_exc = cc.max(exc_type);
switch (global_exc) {
case Opm::ExceptionType::NONE:
break;
case Opm::ExceptionType::RUNTIME_ERROR:
throw std::runtime_error(message); throw std::runtime_error(message);
break;
case Opm::ExceptionType::INVALID_ARGUMENT:
throw std::invalid_argument(message);
break;
case Opm::ExceptionType::DEFAULT:
case Opm::ExceptionType::LOGIC_ERROR:
throw std::logic_error(message);
break;
default:
throw std::logic_error(message);
} }
} }
inline void logAndCheckForExceptionsAndThrow(Opm::DeferredLogger& deferred_logger, int exception_thrown, const std::string& message, const bool terminal_output) }
inline void checkForExceptionsAndThrow(Opm::ExceptionType::ExcEnum exc_type, const std::string& message)
{
_throw(exc_type, message);
}
inline void logAndCheckForExceptionsAndThrow(Opm::DeferredLogger& deferred_logger, Opm::ExceptionType::ExcEnum exc_type , const std::string& message, const bool terminal_output)
{ {
Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(deferred_logger); Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(deferred_logger);
if (terminal_output) { if (terminal_output) {
@ -67,10 +92,7 @@ inline void logAndCheckForExceptionsAndThrow(Opm::DeferredLogger& deferred_logge
// cleared from the global logger, but we must also clear them // cleared from the global logger, but we must also clear them
// from the local logger. // from the local logger.
deferred_logger.clearMessages(); deferred_logger.clearMessages();
const auto& cc = Dune::MPIHelper::getCollectiveCommunication(); _throw(exc_type, message);
if (cc.max(exception_thrown) == 1) {
throw std::runtime_error(message);
}
} }
#endif // OPM_DEFERREDLOGGINGERRORHELPERS_HPP #endif // OPM_DEFERREDLOGGINGERRORHELPERS_HPP

View File

@ -309,7 +309,8 @@ namespace Opm {
updateAndCommunicateGroupData(local_deferredLogger); updateAndCommunicateGroupData(local_deferredLogger);
const int reportStepIdx = ebosSimulator_.episodeIndex(); const int reportStepIdx = ebosSimulator_.episodeIndex();
const double simulationTime = ebosSimulator_.time(); const double simulationTime = ebosSimulator_.time();
int exception_thrown = 0; std::string exc_msg;
auto exc_type = ExceptionType::NONE;
try { try {
// test wells // test wells
wellTesting(reportStepIdx, simulationTime, local_deferredLogger); wellTesting(reportStepIdx, simulationTime, local_deferredLogger);
@ -342,11 +343,21 @@ namespace Opm {
setRepRadiusPerfLength(); setRepRadiusPerfLength();
} }
} }
} catch (std::exception& e) { } catch (const std::runtime_error& e) {
exception_thrown = 1; exc_type = ExceptionType::RUNTIME_ERROR;
exc_msg = e.what();
} catch (const std::invalid_argument& e) {
exc_type = ExceptionType::INVALID_ARGUMENT;
exc_msg = e.what();
} catch (const std::logic_error& e) {
exc_type = ExceptionType::LOGIC_ERROR;
exc_msg = e.what();
} catch (const std::exception& e) {
exc_type = ExceptionType::DEFAULT;
exc_msg = e.what();
} }
logAndCheckForExceptionsAndThrow(local_deferredLogger, exception_thrown, "beginTimeStep() failed.", terminal_output_); logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "beginTimeStep() failed: " + exc_msg, terminal_output_);
for (auto& well : well_container_) { for (auto& well : well_container_) {
well->setVFPProperties(vfp_properties_.get()); well->setVFPProperties(vfp_properties_.get());
@ -395,19 +406,33 @@ namespace Opm {
try { try {
well->calculateExplicitQuantities(ebosSimulator_, well_state_, local_deferredLogger); well->calculateExplicitQuantities(ebosSimulator_, well_state_, local_deferredLogger);
well->solveWellEquation(ebosSimulator_, well_state_, local_deferredLogger); well->solveWellEquation(ebosSimulator_, well_state_, local_deferredLogger);
} catch (std::exception& e) { } catch (const std::exception& e) {
const std::string msg = "Compute initial well solution for new well " + well->name() + " failed. Continue with zero initial rates"; const std::string msg = "Compute initial well solution for new well " + well->name() + " failed. Continue with zero initial rates";
local_deferredLogger.warning("WELL_INITIAL_SOLVE_FAILED", msg); local_deferredLogger.warning("WELL_INITIAL_SOLVE_FAILED", msg);
} }
} }
} }
} catch (std::exception& e) { } catch (const std::runtime_error& e) {
exc_type = ExceptionType::RUNTIME_ERROR;
exc_msg = e.what();
} catch (const std::invalid_argument& e) {
exc_type = ExceptionType::INVALID_ARGUMENT;
exc_msg = e.what();
} catch (const std::logic_error& e) {
exc_type = ExceptionType::LOGIC_ERROR;
exc_msg = e.what();
} catch (const std::exception& e) {
exc_type = ExceptionType::DEFAULT;
exc_msg = e.what();
}
if (exc_type != ExceptionType::NONE) {
const std::string msg = "Compute initial well solution for new wells failed. Continue with zero initial rates"; const std::string msg = "Compute initial well solution for new wells failed. Continue with zero initial rates";
local_deferredLogger.warning("WELL_INITIAL_SOLVE_FAILED", msg); local_deferredLogger.warning("WELL_INITIAL_SOLVE_FAILED", msg);
} }
logAndCheckForExceptionsAndThrow(local_deferredLogger, logAndCheckForExceptionsAndThrow(local_deferredLogger,
exception_thrown, "beginTimeStep() failed.", terminal_output_); exc_type, "beginTimeStep() failed: " + exc_msg, terminal_output_);
} }
@ -986,7 +1011,8 @@ namespace Opm {
updatePerforationIntensiveQuantities(); updatePerforationIntensiveQuantities();
int exception_thrown = 0; auto exc_type = ExceptionType::NONE;
std::string exc_msg;
try { try {
if (iterationIdx == 0) { if (iterationIdx == 0) {
calculateExplicitQuantities(local_deferredLogger); calculateExplicitQuantities(local_deferredLogger);
@ -1011,12 +1037,21 @@ namespace Opm {
well_state_.enableGliftOptimization(); well_state_.enableGliftOptimization();
assembleWellEq(B_avg, dt, local_deferredLogger); assembleWellEq(B_avg, dt, local_deferredLogger);
well_state_.disableGliftOptimization(); well_state_.disableGliftOptimization();
} catch (const std::runtime_error& e) {
} catch (std::exception& e) { exc_type = ExceptionType::RUNTIME_ERROR;
exception_thrown = 1; exc_msg = e.what();
} catch (const std::invalid_argument& e) {
exc_type = ExceptionType::INVALID_ARGUMENT;
exc_msg = e.what();
} catch (const std::logic_error& e) {
exc_type = ExceptionType::LOGIC_ERROR;
exc_msg = e.what();
} catch (const std::exception& e) {
exc_type = ExceptionType::DEFAULT;
exc_msg = e.what();
} }
logAndCheckForExceptionsAndThrow(local_deferredLogger, exception_thrown, "assemble() failed.", terminal_output_);
logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "assemble() failed: " + exc_msg, terminal_output_);
last_report_.converged = true; last_report_.converged = true;
last_report_.assemble_time_well += perfTimer.stop(); last_report_.assemble_time_well += perfTimer.stop();
} }
@ -1135,18 +1170,28 @@ namespace Opm {
recoverWellSolutionAndUpdateWellState(const BVector& x) recoverWellSolutionAndUpdateWellState(const BVector& x)
{ {
Opm::DeferredLogger local_deferredLogger; Opm::DeferredLogger local_deferredLogger;
auto exc_type = ExceptionType::NONE;
int exception_thrown = 0; std::string exc_msg;
try { try {
if (localWellsActive()) { if (localWellsActive()) {
for (auto& well : well_container_) { for (auto& well : well_container_) {
well->recoverWellSolutionAndUpdateWellState(x, well_state_, local_deferredLogger); well->recoverWellSolutionAndUpdateWellState(x, well_state_, local_deferredLogger);
} }
} }
} catch (std::exception& e) { } catch (const std::runtime_error& e) {
exception_thrown = 1; exc_type = ExceptionType::RUNTIME_ERROR;
exc_msg = e.what();
} catch (const std::invalid_argument& e) {
exc_type = ExceptionType::INVALID_ARGUMENT;
exc_msg = e.what();
} catch (const std::logic_error& e) {
exc_type = ExceptionType::LOGIC_ERROR;
exc_msg = e.what();
} catch (const std::exception& e) {
exc_type = ExceptionType::DEFAULT;
exc_msg = e.what();
} }
logAndCheckForExceptionsAndThrow(local_deferredLogger, exception_thrown, "recoverWellSolutionAndUpdateWellState() failed.", terminal_output_); logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "recoverWellSolutionAndUpdateWellState() failed: " + exc_msg, terminal_output_);
} }
@ -1455,7 +1500,8 @@ namespace Opm {
const Opm::SummaryConfig& summaryConfig = ebosSimulator_.vanguard().summaryConfig(); const Opm::SummaryConfig& summaryConfig = ebosSimulator_.vanguard().summaryConfig();
const bool write_restart_file = ebosSimulator_.vanguard().schedule().write_rst_file(reportStepIdx); const bool write_restart_file = ebosSimulator_.vanguard().schedule().write_rst_file(reportStepIdx);
int exception_thrown = 0; auto exc_type = ExceptionType::NONE;
std::string exc_msg;
for (const auto& well : well_container_) { for (const auto& well : well_container_) {
const bool needed_for_summary = ((summaryConfig.hasSummaryKey( "WWPI:" + well->name()) || const bool needed_for_summary = ((summaryConfig.hasSummaryKey( "WWPI:" + well->name()) ||
summaryConfig.hasSummaryKey( "WOPI:" + well->name()) || summaryConfig.hasSummaryKey( "WOPI:" + well->name()) ||
@ -1474,14 +1520,23 @@ namespace Opm {
for (int p = 0; p < np; ++p) { for (int p = 0; p < np; ++p) {
well_potentials[well->indexOfWell() * np + p] = std::abs(potentials[p]); well_potentials[well->indexOfWell() * np + p] = std::abs(potentials[p]);
} }
} catch (std::exception& e) { } catch (const std::runtime_error& e) {
exception_thrown = 1; exc_type = ExceptionType::RUNTIME_ERROR;
exc_msg = e.what();
} catch (const std::invalid_argument& e) {
exc_type = ExceptionType::INVALID_ARGUMENT;
exc_msg = e.what();
} catch (const std::logic_error& e) {
exc_type = ExceptionType::LOGIC_ERROR;
exc_msg = e.what();
} catch (const std::exception& e) {
exc_type = ExceptionType::DEFAULT;
exc_msg = e.what();
} }
} }
} }
logAndCheckForExceptionsAndThrow(deferred_logger, exc_type,
logAndCheckForExceptionsAndThrow(deferred_logger, exception_thrown, "computeWellPotentials() failed: " + exc_msg,
"computeWellPotentials() failed.",
terminal_output_); terminal_output_);
// Store it in the well state // Store it in the well state
@ -1520,7 +1575,8 @@ namespace Opm {
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
prepareTimeStep(Opm::DeferredLogger& deferred_logger) prepareTimeStep(Opm::DeferredLogger& deferred_logger)
{ {
int exception_thrown = 0; auto exc_type = ExceptionType::NONE;
std::string exc_msg;
try { try {
for (const auto& well : well_container_) { for (const auto& well : well_container_) {
well->checkWellOperability(ebosSimulator_, well_state_, deferred_logger); well->checkWellOperability(ebosSimulator_, well_state_, deferred_logger);
@ -1545,10 +1601,20 @@ namespace Opm {
} }
} // end of for (const auto& well : well_container_) } // end of for (const auto& well : well_container_)
updatePrimaryVariables(deferred_logger); updatePrimaryVariables(deferred_logger);
} catch (std::exception& e) { } catch (const std::runtime_error& e) {
exception_thrown = 1; exc_type = ExceptionType::RUNTIME_ERROR;
exc_msg = e.what();
} catch (const std::invalid_argument& e) {
exc_type = ExceptionType::INVALID_ARGUMENT;
exc_msg = e.what();
} catch (const std::logic_error& e) {
exc_type = ExceptionType::LOGIC_ERROR;
exc_msg = e.what();
} catch (const std::exception& e) {
exc_type = ExceptionType::DEFAULT;
exc_msg = e.what();
} }
logAndCheckForExceptionsAndThrow(deferred_logger, exception_thrown, "prepareTimestep() failed.", terminal_output_); logAndCheckForExceptionsAndThrow(deferred_logger, exc_type, "prepareTimestep() failed: " + exc_msg, terminal_output_);
} }