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);
}
/// \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

View File

@ -177,8 +177,6 @@ namespace Opm {
{
DeferredLogger local_deferredLogger;
std::string exc_msg;
auto exc_type = ExceptionType::NONE;
report_step_starts_ = true;
const Grid& grid = ebosSimulator_.vanguard().grid();
@ -190,7 +188,7 @@ namespace Opm {
// at least initializeWellState might be throw
// exception in opm-material (UniformTabulated2DFunction.hpp)
// 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.
@ -233,24 +231,8 @@ namespace Opm {
}
}
}
catch (const Opm::NumericalIssue& e){
exc_type = ExceptionType::NUMERICAL_ISSUE;
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_);
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "beginReportStep() failed: ",
terminal_output_);
// Store the current well state, to be able to recover in the case of failed iterations
this->commitWGState();
}
@ -273,9 +255,8 @@ namespace Opm {
ebosSimulator_.model().newtonMethod().numIterations());
this->wellState().gliftTimeStepInit();
const double simulationTime = ebosSimulator_.time();
std::string exc_msg;
auto exc_type = ExceptionType::NONE;
try {
OPM_BEGIN_PARALLEL_TRY_CATCH();
{
// test wells
wellTesting(reportStepIdx, simulationTime, local_deferredLogger);
@ -302,21 +283,9 @@ namespace Opm {
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();
}
logAndCheckForExceptionsAndThrow(local_deferredLogger, exc_type, "beginTimeStep() failed: " + exc_msg, terminal_output_);
OPM_END_PARALLEL_TRY_CATCH_LOG(local_deferredLogger, "beginTimeStep() failed: ",
terminal_output_);
for (auto& well : well_container_) {
well->setVFPProperties(vfp_properties_.get());
@ -358,8 +327,8 @@ namespace Opm {
const Group& fieldGroup = schedule().getGroup("FIELD", reportStepIdx);
WellGroupHelpers::updateGuideRates(fieldGroup, schedule(), summaryState, this->phase_usage_, reportStepIdx, simulationTime,
this->wellState(), this->groupState(), comm, &this->guideRate_, pot, local_deferredLogger);
std::string exc_msg;
auto exc_type = ExceptionType::NONE;
// update gpmaint targets
if (schedule_[reportStepIdx].has_gpmaint()) {
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) {
const std::string msg = "Compute initial well solution for new wells failed. Continue with zero initial rates";
@ -849,9 +808,8 @@ namespace Opm {
updatePerforationIntensiveQuantities();
auto exc_type = ExceptionType::NONE;
std::string exc_msg;
try {
OPM_BEGIN_PARALLEL_TRY_CATCH();
{
if (iterationIdx == 0) {
calculateExplicitQuantities(local_deferredLogger);
prepareTimeStep(local_deferredLogger);
@ -863,20 +821,9 @@ namespace Opm {
maybeDoGasLiftOptimize(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_.assemble_time_well += perfTimer.stop();
}
@ -1160,28 +1107,17 @@ namespace Opm {
recoverWellSolutionAndUpdateWellState(const BVector& x)
{
DeferredLogger local_deferredLogger;
auto exc_type = ExceptionType::NONE;
std::string exc_msg;
try {
OPM_BEGIN_PARALLEL_TRY_CATCH();
{
if (localWellsActive()) {
for (auto& well : well_container_) {
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];
try {
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
// 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
@ -1476,9 +1402,8 @@ namespace Opm {
BlackoilWellModel<TypeTag>::
prepareTimeStep(DeferredLogger& deferred_logger)
{
auto exc_type = ExceptionType::NONE;
std::string exc_msg;
try {
OPM_BEGIN_PARALLEL_TRY_CATCH();
{
for (const auto& well : well_container_) {
const bool old_well_operable = well->isOperable();
well->checkWellOperability(ebosSimulator_, this->wellState(), deferred_logger);
@ -1516,20 +1441,9 @@ namespace Opm {
} // end of for (const auto& well : well_container_)
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_);
}