Unify parallel try-catch clauses with Macros and catch everything.

Not a big fan of Macros but here at least they seem ot be the only
option. The problem is that the catch clauses must all catch the same
exceptions that have a entry in ExceptionType, because they might be
nested. In addition we did not have a catch all clause, which is added
now and is needed in case a called method throws an unexpected exception.
This commit is contained in:
Markus Blatt 2021-09-20 10:56:11 +02:00
parent 1dc3832966
commit a927f8e23b
2 changed files with 82 additions and 112 deletions

View File

@ -100,4 +100,60 @@ inline void logAndCheckForExceptionsAndThrow(Opm::DeferredLogger& deferred_logge
_throw(exc_type, message); _throw(exc_type, message);
} }
/// \brief Macro to setup the try of a parallel try-catch
///
/// Use OPM_END_PARALLEL_TRY_CATCH or OPM_END_PARALLEL_TRY_CATCH_LOG
/// fot the catch part.
#define OPM_BEGIN_PARALLEL_TRY_CATCH() \
std::string obptc_exc_msg; \
auto obptc_exc_type = Opm::ExceptionType::NONE; \
try {
/// \brief Inserts catch classes for the parallel try-catch
///
/// There is a clause that will catch anything
#define OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, \
obptc_exc_msg) \
catch (const Opm::NumericalIssue& e){ \
obptc_exc_type = Opm::ExceptionType::NUMERICAL_ISSUE; \
obptc_exc_msg = e.what(); \
} catch (const std::runtime_error& e) { \
obptc_exc_type = Opm::ExceptionType::RUNTIME_ERROR; \
obptc_exc_msg = e.what(); \
} catch (const std::invalid_argument& e) { \
obptc_exc_type = Opm::ExceptionType::INVALID_ARGUMENT; \
obptc_exc_msg = e.what(); \
} catch (const std::logic_error& e) { \
obptc_exc_type = Opm::ExceptionType::LOGIC_ERROR; \
obptc_exc_msg = e.what(); \
} catch (const std::exception& e) { \
obptc_exc_type = Opm::ExceptionType::DEFAULT; \
obptc_exc_msg = e.what(); \
} catch (...) { \
obptc_exc_type = Opm::ExceptionType::DEFAULT; \
obptc_exc_msg = "Unknown exception was thrown"; \
}
/// \brief Catch exception and throw in a parallel try-catch clause
///
/// Assumes that OPM_BEGIN_PARALLEL_TRY_CATCH() was called to initiate
/// the try-catch clause
#define OPM_END_PARALLEL_TRY_CATCH(prefix) \
} \
OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, obptc_exc_msg);\
checkForExceptionsAndThrow(obptc_exc_type, \
prefix + obptc_exc_msg);
/// \brief Catch exception, log, and throw in a parallel try-catch clause
///
/// Assumes that OPM_BEGIN_PARALLEL_TRY_CATCH() was called to initiate
/// the try-catch clause
#define OPM_END_PARALLEL_TRY_CATCH_LOG(obptc_logger, \
obptc_prefix, \
obptc_output) \
} \
OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, obptc_exc_msg); \
logAndCheckForExceptionsAndThrow(obptc_logger, obptc_exc_type, \
obptc_prefix + obptc_exc_msg, obptc_output);
#endif // OPM_DEFERREDLOGGINGERRORHELPERS_HPP #endif // OPM_DEFERREDLOGGINGERRORHELPERS_HPP

View File

@ -177,8 +177,6 @@ namespace Opm {
{ {
DeferredLogger local_deferredLogger; DeferredLogger local_deferredLogger;
std::string exc_msg;
auto exc_type = ExceptionType::NONE;
report_step_starts_ = true; report_step_starts_ = true;
const Grid& grid = ebosSimulator_.vanguard().grid(); const Grid& grid = ebosSimulator_.vanguard().grid();
@ -190,7 +188,7 @@ namespace Opm {
// at least initializeWellState might be throw // at least initializeWellState might be throw
// exception in opm-material (UniformTabulated2DFunction.hpp) // exception in opm-material (UniformTabulated2DFunction.hpp)
// playing it safe by extending the scope a bit. // playing it safe by extending the scope a bit.
try OPM_BEGIN_PARALLEL_TRY_CATCH();
{ {
// The well state initialize bhp with the cell pressure in the top cell. // The well state initialize bhp with the cell pressure in the top cell.
@ -233,24 +231,8 @@ namespace Opm {
} }
} }
} }
catch (const Opm::NumericalIssue& e){ OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "beginReportStep() failed: ",
exc_type = ExceptionType::NUMERICAL_ISSUE; terminal_output_);
exc_msg = e.what();
} 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();
}
logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "beginReportStep() failed: " + exc_msg, terminal_output_);
// Store the current well state, to be able to recover in the case of failed iterations // Store the current well state, to be able to recover in the case of failed iterations
this->commitWGState(); this->commitWGState();
} }
@ -273,9 +255,8 @@ namespace Opm {
ebosSimulator_.model().newtonMethod().numIterations()); ebosSimulator_.model().newtonMethod().numIterations());
this->wellState().gliftTimeStepInit(); this->wellState().gliftTimeStepInit();
const double simulationTime = ebosSimulator_.time(); const double simulationTime = ebosSimulator_.time();
std::string exc_msg; OPM_BEGIN_PARALLEL_TRY_CATCH();
auto exc_type = ExceptionType::NONE; {
try {
// test wells // test wells
wellTesting(reportStepIdx, simulationTime, local_deferredLogger); wellTesting(reportStepIdx, simulationTime, local_deferredLogger);
@ -302,21 +283,9 @@ namespace Opm {
setRepRadiusPerfLength(); setRepRadiusPerfLength();
} }
} }
} 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();
} }
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "beginTimeStep() failed: ",
logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "beginTimeStep() failed: " + exc_msg, terminal_output_); terminal_output_);
for (auto& well : well_container_) { for (auto& well : well_container_) {
well->setVFPProperties(vfp_properties_.get()); well->setVFPProperties(vfp_properties_.get());
@ -358,8 +327,8 @@ namespace Opm {
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx); const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime, WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime,
this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger); this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger);
std::string exc_msg;
auto exc_type = ExceptionType::NONE;
// update gpmaint targets // update gpmaint targets
if (schedule_[reportStepIdx].has_gpmaint()) { if (schedule_[reportStepIdx].has_gpmaint()) {
regionalAveragePressureCalculator_->template defineState<ElementContext>(ebosSimulator_); regionalAveragePressureCalculator_->template defineState<ElementContext>(ebosSimulator_);
@ -391,19 +360,9 @@ namespace Opm {
} }
} }
} }
} 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();
} }
// Catch clauses for all errors setting exc_type and exc_msg
OPM_PARALLEL_CATCH_CLAUSE(exc_type, exc_msg);
if (exc_type != ExceptionType::NONE) { 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";
@ -849,9 +808,8 @@ namespace Opm {
updatePerforationIntensiveQuantities(); updatePerforationIntensiveQuantities();
auto exc_type = ExceptionType::NONE; OPM_BEGIN_PARALLEL_TRY_CATCH();
std::string exc_msg; {
try {
if (iterationIdx == 0) { if (iterationIdx == 0) {
calculateExplicitQuantities(local_deferredLogger); calculateExplicitQuantities(local_deferredLogger);
prepareTimeStep(local_deferredLogger); prepareTimeStep(local_deferredLogger);
@ -863,20 +821,9 @@ namespace Opm {
maybeDoGasLiftOptimize(local_deferredLogger); maybeDoGasLiftOptimize(local_deferredLogger);
assembleWellEq(dt, local_deferredLogger); assembleWellEq(dt, local_deferredLogger);
} 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();
} }
logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "assemble() failed: " + exc_msg, terminal_output_); OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "assemble() failed: ",
terminal_output_);
last_report_.converged = true; last_report_.converged = true;
last_report_.assemble_time_well += perfTimer.stop(); last_report_.assemble_time_well += perfTimer.stop();
} }
@ -1160,28 +1107,17 @@ namespace Opm {
recoverWellSolutionAndUpdateWellState(const BVector& x) recoverWellSolutionAndUpdateWellState(const BVector& x)
{ {
DeferredLogger local_deferredLogger; DeferredLogger local_deferredLogger;
auto exc_type = ExceptionType::NONE; OPM_BEGIN_PARALLEL_TRY_CATCH();
std::string exc_msg; {
try {
if (localWellsActive()) { if (localWellsActive()) {
for (auto& well : well_container_) { for (auto& well : well_container_) {
well->recoverWellSolutionAndUpdateWellState(x, this->wellState(), local_deferredLogger); well->recoverWellSolutionAndUpdateWellState(x, this->wellState(), local_deferredLogger);
} }
} }
} 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();
} }
logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "recoverWellSolutionAndUpdateWellState() failed: " + exc_msg, terminal_output_); OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger,
"recoverWellSolutionAndUpdateWellState() failed: ",
terminal_output_);
} }
@ -1386,19 +1322,9 @@ namespace Opm {
const auto& well= well_container_[widx]; const auto& well= well_container_[widx];
try { try {
well->computeWellPotentials(ebosSimulator_, well_state_copy, potentials, deferred_logger); well->computeWellPotentials(ebosSimulator_, well_state_copy, potentials, deferred_logger);
} 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();
} }
// catch all possible exception and store type and message.
OPM_PARALLEL_CATCH_CLAUSE(exc_type, exc_msg);
// Store it in the well state // Store it in the well state
// potentials is resized and set to zero in the beginning of well->ComputeWellPotentials // potentials is resized and set to zero in the beginning of well->ComputeWellPotentials
// and updated only if sucessfull. i.e. the potentials are zero for exceptions // and updated only if sucessfull. i.e. the potentials are zero for exceptions
@ -1476,9 +1402,8 @@ namespace Opm {
BlackoilWellModel<TypeTag>:: BlackoilWellModel<TypeTag>::
prepareTimeStep(DeferredLogger& deferred_logger) prepareTimeStep(DeferredLogger& deferred_logger)
{ {
auto exc_type = ExceptionType::NONE; OPM_BEGIN_PARALLEL_TRY_CATCH();
std::string exc_msg; {
try {
for (const auto& well : well_container_) { for (const auto& well : well_container_) {
const bool old_well_operable = well->isOperable(); const bool old_well_operable = well->isOperable();
well->checkWellOperability(ebosSimulator_, this->wellState(), deferred_logger); well->checkWellOperability(ebosSimulator_, this->wellState(), deferred_logger);
@ -1516,20 +1441,9 @@ 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 (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();
} }
logAndCheckForExceptionsAndThrow(deferred_logger, exc_type, "prepareTimestep() failed: " + exc_msg, terminal_output_); OPM_END_PARALLEL_TRY_CATCH_LOG(deferred_logger, "prepareTimestep() failed: ",
terminal_output_);
} }