Merge pull request #5302 from bska/more-infostep-cnv

Report CNV Violation Pore-Volume Fraction to INFOITER
This commit is contained in:
Atgeirr Flø Rasmussen 2024-05-06 14:13:21 +02:00 committed by GitHub
commit ae7307d2c3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 190 additions and 61 deletions

View File

@ -897,7 +897,8 @@ namespace Opm {
Vector R_sum(numComp, 0.0 ); Vector R_sum(numComp, 0.0 );
Vector maxCoeff(numComp, std::numeric_limits< Scalar >::lowest() ); Vector maxCoeff(numComp, std::numeric_limits< Scalar >::lowest() );
std::vector<int> maxCoeffCell(numComp, -1); std::vector<int> maxCoeffCell(numComp, -1);
const auto [ pvSumLocal, numAquiferPvSumLocal] = localConvergenceData(R_sum, maxCoeff, B_avg, maxCoeffCell); const auto [ pvSumLocal, numAquiferPvSumLocal] =
this->localConvergenceData(R_sum, maxCoeff, B_avg, maxCoeffCell);
// compute global sum and max of quantities // compute global sum and max of quantities
const auto [ pvSum, numAquiferPvSum ] = const auto [ pvSum, numAquiferPvSum ] =
@ -905,9 +906,9 @@ namespace Opm {
numAquiferPvSumLocal, numAquiferPvSumLocal,
R_sum, maxCoeff, B_avg); R_sum, maxCoeff, B_avg);
auto cnvErrorPvFraction = computeCnvErrorPv(B_avg, dt); const auto cnvErrorPvFraction =
cnvErrorPvFraction /= (pvSum - numAquiferPvSum); computeCnvErrorPv(B_avg, dt)
/ (pvSum - numAquiferPvSum);
// For each iteration, we need to determine whether to use the relaxed tolerances. // For each iteration, we need to determine whether to use the relaxed tolerances.
// To disable the usage of relaxed tolerances, you can set the relaxed tolerances as the strict tolerances. // To disable the usage of relaxed tolerances, you can set the relaxed tolerances as the strict tolerances.
@ -944,7 +945,7 @@ namespace Opm {
// Finish computation // Finish computation
std::vector<Scalar> CNV(numComp); std::vector<Scalar> CNV(numComp);
std::vector<Scalar> mass_balance_residual(numComp); std::vector<Scalar> mass_balance_residual(numComp);
for ( int compIdx = 0; compIdx < numComp; ++compIdx ) for (int compIdx = 0; compIdx < numComp; ++compIdx)
{ {
CNV[compIdx] = B_avg[compIdx] * dt * maxCoeff[compIdx]; CNV[compIdx] = B_avg[compIdx] * dt * maxCoeff[compIdx];
mass_balance_residual[compIdx] = std::abs(B_avg[compIdx]*R_sum[compIdx]) * dt / pvSum; mass_balance_residual[compIdx] = std::abs(B_avg[compIdx]*R_sum[compIdx]) * dt / pvSum;
@ -953,12 +954,15 @@ namespace Opm {
// Create convergence report. // Create convergence report.
ConvergenceReport report{reportTime}; ConvergenceReport report{reportTime};
report.setPoreVolCnvViolationFraction(cnvErrorPvFraction, pvSum - numAquiferPvSum);
using CR = ConvergenceReport; using CR = ConvergenceReport;
for (int compIdx = 0; compIdx < numComp; ++compIdx) { for (int compIdx = 0; compIdx < numComp; ++compIdx) {
double res[2] = { mass_balance_residual[compIdx], CNV[compIdx] }; const double res[2] = { mass_balance_residual[compIdx], CNV[compIdx] };
CR::ReservoirFailure::Type types[2] = { CR::ReservoirFailure::Type::MassBalance, const CR::ReservoirFailure::Type types[2] = { CR::ReservoirFailure::Type::MassBalance,
CR::ReservoirFailure::Type::Cnv }; CR::ReservoirFailure::Type::Cnv };
double tol[2] = { tol_mb, tol_cnv }; const double tol[2] = { tol_mb, tol_cnv };
for (int ii : {0, 1}) { for (int ii : {0, 1}) {
if (std::isnan(res[ii])) { if (std::isnan(res[ii])) {
report.setReservoirFailed({types[ii], CR::Severity::NotANumber, compIdx}); report.setReservoirFailed({types[ii], CR::Severity::NotANumber, compIdx});

View File

@ -656,6 +656,7 @@ private:
} else if (res[ii] > tol[ii]) { } else if (res[ii] > tol[ii]) {
report.setReservoirFailed({types[ii], CR::Severity::Normal, compIdx}); report.setReservoirFailed({types[ii], CR::Severity::Normal, compIdx});
} }
report.setReservoirConvergenceMetric(types[ii], compIdx, res[ii]); report.setReservoirConvergenceMetric(types[ii], compIdx, res[ii]);
} }
} }

View File

@ -24,6 +24,7 @@
#include <opm/simulators/timestepping/ConvergenceReport.hpp> #include <opm/simulators/timestepping/ConvergenceReport.hpp>
#include <algorithm> #include <algorithm>
#include <array>
#include <cassert> #include <cassert>
#include <condition_variable> #include <condition_variable>
#include <cstddef> #include <cstddef>
@ -40,12 +41,44 @@
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <tuple>
#include <type_traits>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector> #include <vector>
namespace { namespace {
auto fixedHeaders() noexcept
{
using namespace std::literals::string_literals;
return std::array {
"ReportStep"s,
"TimeStep"s,
"Time"s,
"CnvErrPvFrac"s,
"Iteration"s,
};
}
template <typename HeaderSequence>
auto maxHeaderSize(const HeaderSequence& headers)
{
using sz_t = std::remove_cv_t<std::remove_reference_t<
decltype(std::declval<HeaderSequence>().front().size())>>;
if (headers.empty()) {
return sz_t{0};
}
return std::accumulate(headers.begin(), headers.end(), sz_t{1},
[](const auto m, const auto& header)
{
return std::max(m, header.size() + 1);
});
}
std::string std::string
formatMetricColumn(const Opm::ConvergenceOutputThread::ComponentToPhaseName& getPhaseName, formatMetricColumn(const Opm::ConvergenceOutputThread::ComponentToPhaseName& getPhaseName,
const Opm::ConvergenceReport::ReservoirConvergenceMetric& metric) const Opm::ConvergenceReport::ReservoirConvergenceMetric& metric)
@ -65,45 +98,49 @@ namespace {
[&getPhaseName](const std::string::size_type maxChar, [&getPhaseName](const std::string::size_type maxChar,
const Opm::ConvergenceReport::ReservoirConvergenceMetric& metric) const Opm::ConvergenceReport::ReservoirConvergenceMetric& metric)
{ {
return std::max(maxChar, formatMetricColumn(getPhaseName, metric).size()); return std::max(maxChar, formatMetricColumn(getPhaseName, metric).size() + 1);
}); });
} }
std::string::size_type std::pair<std::string::size_type, std::string::size_type>
writeConvergenceHeader(std::ostream& os, writeConvergenceHeader(std::ostream& os,
const Opm::ConvergenceOutputThread::ComponentToPhaseName& getPhaseName, const Opm::ConvergenceOutputThread::ComponentToPhaseName& getPhaseName,
const Opm::ConvergenceReportQueue::OutputRequest& firstRequest) const Opm::ConvergenceReportQueue::OutputRequest& firstRequest)
{ {
const auto minColSize = std::string::size_type{11}; const auto initial_headers = fixedHeaders();
const auto minColSize = maxHeaderSize(initial_headers);
os << std::right << std::setw(minColSize) << "ReportStep" << ' ' {
<< std::right << std::setw(minColSize) << "TimeStep" << ' ' auto leadingSpace = false;
<< std::right << std::setw(minColSize) << "Time" << ' '
<< std::right << std::setw(minColSize) << "Iteration"; for (const auto& columnHeader : initial_headers) {
if (leadingSpace) { os << ' '; }
os << std::right << std::setw(minColSize) << columnHeader;
leadingSpace = true;
}
}
const auto& metrics = firstRequest.reports.front().reservoirConvergence(); const auto& metrics = firstRequest.reports.front().reservoirConvergence();
const auto maxChar = maxColHeaderSize(minColSize, getPhaseName, metrics); const auto headerSize = maxColHeaderSize(minColSize, getPhaseName, metrics);
for (const auto& metric : metrics) { for (const auto& metric : metrics) {
os << std::right << std::setw(maxChar + 1) os << std::right << std::setw(headerSize)
<< formatMetricColumn(getPhaseName, metric); << formatMetricColumn(getPhaseName, metric);
} }
// Note: Newline character intentionally placed in separate output // Note: Newline character intentionally placed in separate output
// request to not influence right-justification of column header. // request to not influence right-justification of column header.
os << std::right << std::setw(maxChar + 1) << "WellStatus" << '\n'; os << std::right << std::setw(headerSize) << "WellStatus" << '\n';
return maxChar; return { minColSize, headerSize };
} }
void writeConvergenceRequest(std::ostream& os, void writeConvergenceRequest(std::ostream& os,
const Opm::ConvergenceOutputThread::ConvertToTimeUnits& convertTime, const Opm::ConvergenceOutputThread::ConvertToTimeUnits& convertTime,
std::string::size_type colSize, const std::string::size_type firstColSize,
const std::string::size_type colSize,
const Opm::ConvergenceReportQueue::OutputRequest& request) const Opm::ConvergenceReportQueue::OutputRequest& request)
{ {
const auto firstColSize = std::string::size_type{11};
os.setf(std::ios_base::scientific); os.setf(std::ios_base::scientific);
auto iter = 0; auto iter = 0;
@ -112,19 +149,23 @@ namespace {
<< std::setw(firstColSize) << request.currentStep << ' ' << std::setw(firstColSize) << request.currentStep << ' '
<< std::setprecision(4) << std::setw(firstColSize) << std::setprecision(4) << std::setw(firstColSize)
<< convertTime(report.reportTime()) << ' ' << convertTime(report.reportTime()) << ' '
<< std::setprecision(4) << std::setw(firstColSize)
<< report.cnvViolatedPvFraction() << ' '
<< std::setw(firstColSize) << iter; << std::setw(firstColSize) << iter;
for (const auto& metric : report.reservoirConvergence()) { for (const auto& metric : report.reservoirConvergence()) {
os << std::setprecision(4) << std::setw(colSize + 1) << metric.value(); os << std::setprecision(4) << std::setw(colSize) << metric.value();
} }
os << std::right << std::setw(colSize + 1) os << std::right << std::setw(colSize)
<< (report.wellFailed() ? "FAIL" : "CONV"); << (report.wellFailed() ? "FAIL" : "CONV");
if (report.wellFailed()) { if (report.wellFailed()) {
for (const auto& wf : report.wellFailures()) { for (const auto& wf : report.wellFailures()) {
os << " " << to_string(wf); os << ' ' << to_string(wf);
} }
} }
os << '\n'; os << '\n';
++iter; ++iter;
@ -160,6 +201,7 @@ private:
ComponentToPhaseName getPhaseName_{}; ComponentToPhaseName getPhaseName_{};
ConvertToTimeUnits convertTime_{}; ConvertToTimeUnits convertTime_{};
std::optional<std::ofstream> infoIter_{}; std::optional<std::ofstream> infoIter_{};
std::string::size_type firstColSize_{0};
std::string::size_type colSize_{0}; std::string::size_type colSize_{0};
bool haveOutputIterHeader_{false}; bool haveOutputIterHeader_{false};
bool finalRequestWritten_{false}; bool finalRequestWritten_{false};
@ -203,7 +245,7 @@ writeIterInfo(const std::vector<ConvergenceReportQueue::OutputRequest>& requests
} }
if (! this->haveOutputIterHeader_) { if (! this->haveOutputIterHeader_) {
this->colSize_ = std::tie(this->firstColSize_, this->colSize_) =
writeConvergenceHeader(this->infoIter_.value(), writeConvergenceHeader(this->infoIter_.value(),
this->getPhaseName_, this->getPhaseName_,
requests.front()); requests.front());
@ -213,6 +255,7 @@ writeIterInfo(const std::vector<ConvergenceReportQueue::OutputRequest>& requests
for (const auto& request : requests) { for (const auto& request : requests) {
writeConvergenceRequest(this->infoIter_.value(), writeConvergenceRequest(this->infoIter_.value(),
this->convertTime_, this->convertTime_,
this->firstColSize_,
this->colSize_, this->colSize_,
request); request);

View File

@ -363,13 +363,16 @@ public:
+ schedule().seconds(timer.currentStepNum()), + schedule().seconds(timer.currentStepNum()),
timer.currentStepLength()); timer.currentStepLength());
simulator_.setEpisodeIndex(timer.currentStepNum()); simulator_.setEpisodeIndex(timer.currentStepNum());
if (serializer_.shouldLoad()) { if (serializer_.shouldLoad()) {
wellModel_().prepareDeserialize(serializer_.loadStep() - 1); wellModel_().prepareDeserialize(serializer_.loadStep() - 1);
serializer_.loadState(); serializer_.loadState();
simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0); simulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0);
} }
solver_->model().beginReportStep();
bool enableTUNING = Parameters::get<TypeTag, Properties::EnableTuning>(); this->solver_->model().beginReportStep();
const bool enableTUNING = Parameters::get<TypeTag, Properties::EnableTuning>();
// If sub stepping is enabled allow the solver to sub cycle // If sub stepping is enabled allow the solver to sub cycle
// in case the report steps are too large for the solver to converge // in case the report steps are too large for the solver to converge
@ -442,10 +445,17 @@ public:
report_.success.solver_time += solverTimer_->secsSinceStart(); report_.success.solver_time += solverTimer_->secsSinceStart();
if (this->grid().comm().rank() == 0) { if (this->grid().comm().rank() == 0) {
// Grab the step convergence reports that are new since last we were here. // Grab the step convergence reports that are new since last we
const auto& reps = solver_->model().stepReports(); // were here.
this->writeConvergenceOutput(std::vector<StepReport>{reps.begin() + already_reported_steps_, reps.end()}); const auto& reps = this->solver_->model().stepReports();
already_reported_steps_ = reps.size();
auto reports = std::vector<StepReport> {
reps.begin() + this->already_reported_steps_, reps.end()
};
this->writeConvergenceOutput(std::move(reports));
this->already_reported_steps_ = reps.size();
} }
// Increment timer, remember well state. // Increment timer, remember well state.

View File

@ -40,56 +40,78 @@ namespace Opm
// ----------- Types ----------- // ----------- Types -----------
enum Status { AllGood = 0, enum Status {
AllGood = 0,
ReservoirFailed = 1 << 0, ReservoirFailed = 1 << 0,
WellFailed = 1 << 1 }; WellFailed = 1 << 1,
enum struct Severity { None = 0, };
enum struct Severity {
None = 0,
Normal = 1, Normal = 1,
TooLarge = 2, TooLarge = 2,
NotANumber = 3 }; NotANumber = 3,
};
class ReservoirFailure class ReservoirFailure
{ {
public: public:
enum struct Type { Invalid, MassBalance, Cnv }; enum struct Type { Invalid, MassBalance, Cnv };
ReservoirFailure(Type t, Severity s, int phase) ReservoirFailure(Type t, Severity s, int phase)
: type_(t), severity_(s), phase_(phase) : type_(t), severity_(s), phase_(phase)
{ {}
}
Type type() const { return type_; } Type type() const { return type_; }
Severity severity() const { return severity_; } Severity severity() const { return severity_; }
int phase() const { return phase_; } int phase() const { return phase_; }
private: private:
Type type_; Type type_;
Severity severity_; Severity severity_;
int phase_; int phase_;
}; };
class ReservoirConvergenceMetric class ReservoirConvergenceMetric
{ {
public: public:
ReservoirConvergenceMetric(ReservoirFailure::Type t, int phase, double value) ReservoirConvergenceMetric(ReservoirFailure::Type t, int phase, double value)
: type_(t), phase_(phase), value_(value) : type_(t), phase_(phase), value_(value)
{ {}
}
ReservoirFailure::Type type() const { return type_; } ReservoirFailure::Type type() const { return type_; }
int phase() const { return phase_; } int phase() const { return phase_; }
double value() const { return value_; } double value() const { return value_; }
private: private:
ReservoirFailure::Type type_; ReservoirFailure::Type type_;
int phase_; int phase_;
double value_; double value_;
}; };
class WellFailure class WellFailure
{ {
public: public:
enum struct Type { Invalid, MassBalance, Pressure, ControlBHP, ControlTHP, ControlRate, Unsolvable, WrongFlowDirection }; enum struct Type {
Invalid,
MassBalance,
Pressure,
ControlBHP,
ControlTHP,
ControlRate,
Unsolvable,
WrongFlowDirection,
};
WellFailure(Type t, Severity s, int phase, const std::string& well_name) WellFailure(Type t, Severity s, int phase, const std::string& well_name)
: type_(t), severity_(s), phase_(phase), well_name_(well_name) : type_(t), severity_(s), phase_(phase), well_name_(well_name)
{ {}
}
Type type() const { return type_; } Type type() const { return type_; }
Severity severity() const { return severity_; } Severity severity() const { return severity_; }
int phase() const { return phase_; } int phase() const { return phase_; }
const std::string& wellName() const { return well_name_; } const std::string& wellName() const { return well_name_; }
private: private:
Type type_; Type type_;
Severity severity_; Severity severity_;
@ -101,8 +123,7 @@ namespace Opm
ConvergenceReport() ConvergenceReport()
: ConvergenceReport{0.0} : ConvergenceReport{0.0}
{ {}
}
explicit ConvergenceReport(const double reportTime) explicit ConvergenceReport(const double reportTime)
: reportTime_{reportTime} : reportTime_{reportTime}
@ -110,8 +131,7 @@ namespace Opm
, res_failures_{} , res_failures_{}
, well_failures_{} , well_failures_{}
, wellGroupTargetsViolated_(false) , wellGroupTargetsViolated_(false)
{ {}
}
void clear() void clear()
{ {
@ -144,6 +164,13 @@ namespace Opm
wellGroupTargetsViolated_ = wellGroupTargetsViolated; wellGroupTargetsViolated_ = wellGroupTargetsViolated;
} }
void setPoreVolCnvViolationFraction(const double cnvErrorPvFraction,
const double cnvErrorPvFractionDenom)
{
this->pvFracCnvViol_ = cnvErrorPvFraction;
this->pvFracCnvViolDenom_ = cnvErrorPvFractionDenom;
}
ConvergenceReport& operator+=(const ConvergenceReport& other) ConvergenceReport& operator+=(const ConvergenceReport& other)
{ {
reportTime_ = std::max(reportTime_, other.reportTime_); reportTime_ = std::max(reportTime_, other.reportTime_);
@ -154,6 +181,21 @@ namespace Opm
assert(reservoirFailed() != res_failures_.empty()); assert(reservoirFailed() != res_failures_.empty());
assert(wellFailed() != well_failures_.empty()); assert(wellFailed() != well_failures_.empty());
wellGroupTargetsViolated_ = (wellGroupTargetsViolated_ || other.wellGroupTargetsViolated_); wellGroupTargetsViolated_ = (wellGroupTargetsViolated_ || other.wellGroupTargetsViolated_);
if ((this->pvFracCnvViolDenom_ > 0.0) ||
(other.pvFracCnvViolDenom_ > 0.0))
{
this->pvFracCnvViol_ = (this->pvFracCnvViol_ * this->pvFracCnvViolDenom_ +
other.pvFracCnvViol_ * other.pvFracCnvViolDenom_)
/ (this->pvFracCnvViolDenom_ + other.pvFracCnvViolDenom_);
this->pvFracCnvViolDenom_ += other.pvFracCnvViolDenom_;
}
else {
this->pvFracCnvViol_ = 0.0;
this->pvFracCnvViolDenom_ = 0.0;
}
return *this; return *this;
} }
@ -164,6 +206,16 @@ namespace Opm
return reportTime_; return reportTime_;
} }
double cnvViolatedPvFraction() const
{
return this->pvFracCnvViol_;
}
std::pair<double, double> cnvViolatedPvFractionPack() const
{
return { this->pvFracCnvViol_, this->pvFracCnvViolDenom_ };
}
bool converged() const bool converged() const
{ {
return (status_ == AllGood) && !wellGroupTargetsViolated_; return (status_ == AllGood) && !wellGroupTargetsViolated_;
@ -211,7 +263,6 @@ namespace Opm
} }
private: private:
// ----------- Member variables ----------- // ----------- Member variables -----------
double reportTime_; double reportTime_;
Status status_; Status status_;
@ -219,6 +270,8 @@ namespace Opm
std::vector<WellFailure> well_failures_; std::vector<WellFailure> well_failures_;
std::vector<ReservoirConvergenceMetric> res_convergence_; std::vector<ReservoirConvergenceMetric> res_convergence_;
bool wellGroupTargetsViolated_; bool wellGroupTargetsViolated_;
double pvFracCnvViol_{};
double pvFracCnvViolDenom_{};
}; };
struct StepReport struct StepReport
@ -228,7 +281,6 @@ namespace Opm
std::vector<ConvergenceReport> report; std::vector<ConvergenceReport> report;
}; };
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t); std::string to_string(const ConvergenceReport::ReservoirFailure::Type t);
std::string to_string(const ConvergenceReport::Severity s); std::string to_string(const ConvergenceReport::Severity s);

View File

@ -22,6 +22,8 @@
#include <opm/simulators/timestepping/gatherConvergenceReport.hpp> #include <opm/simulators/timestepping/gatherConvergenceReport.hpp>
#include <utility>
#if HAVE_MPI #if HAVE_MPI
#include <mpi.h> #include <mpi.h>
@ -76,15 +78,24 @@ namespace
{ {
// Pack the data. // Pack the data.
// Status will not be packed, it is possible to deduce from the other data. // Status will not be packed, it is possible to deduce from the other data.
// Reservoir failures.
double reportTime = local_report.reportTime(); double reportTime = local_report.reportTime();
MPI_Pack(&reportTime, 1, MPI_DOUBLE, buf.data(), buf.size(), &offset, mpi_communicator); MPI_Pack(&reportTime, 1, MPI_DOUBLE, buf.data(), buf.size(), &offset, mpi_communicator);
{
const auto cnvPvFrac = local_report.cnvViolatedPvFractionPack();
MPI_Pack(&cnvPvFrac.first , 1, MPI_DOUBLE, buf.data(), buf.size(), &offset, mpi_communicator);
MPI_Pack(&cnvPvFrac.second, 1, MPI_DOUBLE, buf.data(), buf.size(), &offset, mpi_communicator);
}
// Reservoir failures.
const auto rf = local_report.reservoirFailures(); const auto rf = local_report.reservoirFailures();
int num_rf = rf.size(); int num_rf = rf.size();
MPI_Pack(&num_rf, 1, MPI_INT, buf.data(), buf.size(), &offset, mpi_communicator); MPI_Pack(&num_rf, 1, MPI_INT, buf.data(), buf.size(), &offset, mpi_communicator);
for (const auto& f : rf) { for (const auto& f : rf) {
packReservoirFailure(f, buf, offset, mpi_communicator); packReservoirFailure(f, buf, offset, mpi_communicator);
} }
// Reservoir convergence metrics. // Reservoir convergence metrics.
const auto rm = local_report.reservoirConvergence(); const auto rm = local_report.reservoirConvergence();
int num_rm = rm.size(); int num_rm = rm.size();
@ -92,6 +103,7 @@ namespace
for (const auto& m : rm) { for (const auto& m : rm) {
packReservoirConvergenceMetric(m, buf, offset, mpi_communicator); packReservoirConvergenceMetric(m, buf, offset, mpi_communicator);
} }
// Well failures. // Well failures.
const auto wf = local_report.wellFailures(); const auto wf = local_report.wellFailures();
int num_wf = wf.size(); int num_wf = wf.size();
@ -114,7 +126,7 @@ namespace
for (const auto& f : local_report.wellFailures()) { for (const auto& f : local_report.wellFailures()) {
wellnames_length += (f.wellName().size() + 1); wellnames_length += (f.wellName().size() + 1);
} }
return (3 + 3*num_rf + 2*num_rm + 4*num_wf)*int_pack_size + (1 + 1*num_rm)*double_pack_size + wellnames_length; return (3 + 3*num_rf + 2*num_rm + 4*num_wf)*int_pack_size + (3 + 1*num_rm)*double_pack_size + wellnames_length;
} }
ConvergenceReport::ReservoirFailure unpackReservoirFailure(const std::vector<char>& recv_buffer, int& offset, MPI_Comm mpi_communicator) ConvergenceReport::ReservoirFailure unpackReservoirFailure(const std::vector<char>& recv_buffer, int& offset, MPI_Comm mpi_communicator)
@ -169,7 +181,15 @@ namespace
auto* data = const_cast<char*>(recv_buffer.data()); auto* data = const_cast<char*>(recv_buffer.data());
double reportTime{0.0}; double reportTime{0.0};
MPI_Unpack(data, recv_buffer.size(), &offset, &reportTime, 1, MPI_DOUBLE, mpi_communicator); MPI_Unpack(data, recv_buffer.size(), &offset, &reportTime, 1, MPI_DOUBLE, mpi_communicator);
ConvergenceReport cr{reportTime}; ConvergenceReport cr{reportTime};
auto cnvPvFrac = std::pair { 0.0, 0.0 };
MPI_Unpack(data, recv_buffer.size(), &offset, &cnvPvFrac.first , 1, MPI_DOUBLE, mpi_communicator);
MPI_Unpack(data, recv_buffer.size(), &offset, &cnvPvFrac.second, 1, MPI_DOUBLE, mpi_communicator);
cr.setPoreVolCnvViolationFraction(cnvPvFrac.first, cnvPvFrac.second);
int num_rf = -1; int num_rf = -1;
MPI_Unpack(data, recv_buffer.size(), &offset, &num_rf, 1, MPI_INT, mpi_communicator); MPI_Unpack(data, recv_buffer.size(), &offset, &num_rf, 1, MPI_INT, mpi_communicator);
for (int rf = 0; rf < num_rf; ++rf) { for (int rf = 0; rf < num_rf; ++rf) {

View File

@ -149,9 +149,8 @@ BOOST_AUTO_TEST_CASE(CheckMassBalanceWithinXXXMBE)
BOOST_TEST_MESSAGE("---------------------------------------------------------------------------"); BOOST_TEST_MESSAGE("---------------------------------------------------------------------------");
BOOST_CHECK( max_mb[0] < 1.0e-6 ); BOOST_CHECK_MESSAGE( max_mb[0] < 1.0e-6, "max_mb[0] (= " << max_mb[0] << ") is not strictly less than 1.0e-6" );
BOOST_CHECK( max_mb[1] < 1.0e-8 ); BOOST_CHECK_MESSAGE( max_mb[1] < 1.0e-8, "max_mb[1] (= " << max_mb[1] << ") is not strictly less than 1.0e-8" );
BOOST_CHECK( max_mb[2] < 1.0e-10 ); BOOST_CHECK_MESSAGE( max_mb[2] < 1.0e-10, "max_mb[2] (= " << max_mb[1] << ") is not strictly less than 1.0e-10" );
} }