mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
Merge pull request #5302 from bska/more-infostep-cnv
Report CNV Violation Pore-Volume Fraction to INFOITER
This commit is contained in:
commit
ae7307d2c3
@ -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.
|
||||||
@ -927,7 +928,7 @@ namespace Opm {
|
|||||||
const bool relax_pv_fraction_cnv = cnvErrorPvFraction < param_.relaxed_max_pv_fraction_;
|
const bool relax_pv_fraction_cnv = cnvErrorPvFraction < param_.relaxed_max_pv_fraction_;
|
||||||
const bool use_relaxed_cnv = relax_final_iteration_cnv || relax_pv_fraction_cnv || relax_iter_cnv;
|
const bool use_relaxed_cnv = relax_final_iteration_cnv || relax_pv_fraction_cnv || relax_iter_cnv;
|
||||||
|
|
||||||
if (relax_final_iteration_mb || relax_final_iteration_cnv) {
|
if (relax_final_iteration_mb || relax_final_iteration_cnv) {
|
||||||
if ( terminal_output_ ) {
|
if ( terminal_output_ ) {
|
||||||
std::string message = "Number of newton iterations reached its maximum try to continue with relaxed tolerances:";
|
std::string message = "Number of newton iterations reached its maximum try to continue with relaxed tolerances:";
|
||||||
if (relax_final_iteration_mb)
|
if (relax_final_iteration_mb)
|
||||||
@ -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});
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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";
|
|
||||||
|
|
||||||
const auto& metrics = firstRequest.reports.front().reservoirConvergence();
|
for (const auto& columnHeader : initial_headers) {
|
||||||
const auto maxChar = maxColHeaderSize(minColSize, getPhaseName, metrics);
|
if (leadingSpace) { os << ' '; }
|
||||||
|
os << std::right << std::setw(minColSize) << columnHeader;
|
||||||
|
leadingSpace = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& metrics = firstRequest.reports.front().reservoirConvergence();
|
||||||
|
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);
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -40,56 +40,78 @@ namespace Opm
|
|||||||
|
|
||||||
// ----------- Types -----------
|
// ----------- Types -----------
|
||||||
|
|
||||||
enum Status { AllGood = 0,
|
enum Status {
|
||||||
ReservoirFailed = 1 << 0,
|
AllGood = 0,
|
||||||
WellFailed = 1 << 1 };
|
ReservoirFailed = 1 << 0,
|
||||||
enum struct Severity { None = 0,
|
WellFailed = 1 << 1,
|
||||||
Normal = 1,
|
};
|
||||||
TooLarge = 2,
|
|
||||||
NotANumber = 3 };
|
enum struct Severity {
|
||||||
|
None = 0,
|
||||||
|
Normal = 1,
|
||||||
|
TooLarge = 2,
|
||||||
|
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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user