mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
913 lines
43 KiB
C++
913 lines
43 KiB
C++
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
// vi: set et ts=4 sw=4 sts=4:
|
|
/*
|
|
This file is part of the Open Porous Media project (OPM).
|
|
OPM is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 2 of the License, or
|
|
(at your option) any later version.
|
|
OPM is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
You should have received a copy of the GNU General Public License
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
Consult the COPYING file in the top-level source directory of this
|
|
module for the precise wording of the license and the list of
|
|
copyright holders.
|
|
*/
|
|
|
|
#include <config.h>
|
|
#include <opm/simulators/flow/LogOutputHelper.hpp>
|
|
|
|
#include <opm/common/OpmLog/OpmLog.hpp>
|
|
|
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
|
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
|
|
|
#include <opm/simulators/utils/PressureAverage.hpp>
|
|
|
|
#include <fmt/format.h>
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
#include <vector>
|
|
|
|
namespace {
|
|
|
|
template <typename IJKString>
|
|
void logUniqueFailedCells(const std::string& messageTag,
|
|
std::string_view prefix,
|
|
const std::size_t maxNumCellsFaillog,
|
|
const std::vector<int>& cells,
|
|
IJKString&& ijkString)
|
|
{
|
|
if (cells.empty()) {
|
|
return;
|
|
}
|
|
|
|
std::vector<int> sorted(cells);
|
|
std::sort(sorted.begin(), sorted.end());
|
|
auto u = std::unique(sorted.begin(), sorted.end());
|
|
|
|
const auto numFailed = static_cast<std::size_t>
|
|
(std::distance(sorted.begin(), u));
|
|
|
|
std::ostringstream errlog;
|
|
errlog << prefix << " failed for " << numFailed << " cell"
|
|
<< ((numFailed != std::size_t{1}) ? "s" : "")
|
|
<< " [" << ijkString(cells[0]);
|
|
|
|
const auto maxElems = std::min(maxNumCellsFaillog, numFailed);
|
|
for (auto i = 1 + 0*maxElems; i < maxElems; ++i) {
|
|
errlog << ", " << ijkString(cells[i]);
|
|
}
|
|
|
|
if (numFailed > maxNumCellsFaillog) {
|
|
errlog << ", ...";
|
|
}
|
|
|
|
errlog << ']';
|
|
|
|
Opm::OpmLog::warning(messageTag, errlog.str());
|
|
}
|
|
|
|
} // Namespace anonymous
|
|
|
|
namespace Opm {
|
|
|
|
template<class Scalar>
|
|
LogOutputHelper<Scalar>::LogOutputHelper(const EclipseState& eclState,
|
|
const Schedule& schedule,
|
|
const SummaryState& summaryState)
|
|
: eclState_(eclState)
|
|
, schedule_(schedule)
|
|
, summaryState_(summaryState)
|
|
{}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
cumulative(const std::size_t reportStepNum,
|
|
std::function<bool(const std::string&)> isDefunct) const
|
|
{
|
|
std::vector<Scalar> tmp_values(WellCumDataType::numWCValues, 0.0);
|
|
std::vector<std::string> tmp_names(WellCumDataType::numWCNames, "");
|
|
this->outputCumulativeReport_(tmp_values, tmp_names);
|
|
|
|
const auto& st = summaryState_;
|
|
for (const auto& gname : schedule_.groupNames()) {
|
|
auto gName = static_cast<std::string>(gname);
|
|
auto get = [&st, &gName](const std::string& vector)
|
|
{
|
|
const auto key = vector + ':' + gName;
|
|
return st.has(key) ? st.get(key) : 0.0;
|
|
};
|
|
|
|
tmp_names[0] = gname;
|
|
|
|
if (tmp_names[0] == "FIELD") {
|
|
tmp_values[2] = st.get("FOPT", 0.0); // WellCumDataType::OilProd
|
|
tmp_values[3] = st.get("FWPT", 0.0); // WellCumDataType::WaterProd
|
|
tmp_values[4] = st.get("FGPT", 0.0); // WellCumDataType::GasProd
|
|
tmp_values[5] = st.get("FVPT", 0.0); // WellCumDataType::FluidResVolProd
|
|
tmp_values[6] = st.get("FOIT", 0.0); // WellCumDataType::OilInj
|
|
tmp_values[7] = st.get("FWIT", 0.0); // WellCumDataType::WaterInj
|
|
tmp_values[8] = st.get("FGIT", 0.0); // WellCumDataType::GasInj
|
|
tmp_values[9] = st.get("FVIT", 0.0); // WellCumDataType::FluidResVolInj
|
|
} else {
|
|
tmp_values[2] = get("GOPT"); // WellCumDataType::OilProd
|
|
tmp_values[3] = get("GWPT"); // WellCumDataType::WaterProd
|
|
tmp_values[4] = get("GGPT"); // WellCumDataType::GasProd
|
|
tmp_values[5] = get("GVPT"); // WellCumDataType::FluidResVolProd
|
|
tmp_values[6] = get("GOIT"); // WellCumDataType::OilInj
|
|
tmp_values[7] = get("GWIT"); // WellCumDataType::WaterInj
|
|
tmp_values[8] = get("GGIT"); // WellCumDataType::GasInj
|
|
tmp_values[9] = get("GVIT"); // WellCumDataType::FluidResVolInj
|
|
}
|
|
|
|
this->outputCumulativeReport_(tmp_values, tmp_names);
|
|
}
|
|
|
|
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
|
// don't bother with wells not on this process
|
|
if (isDefunct(wname)) {
|
|
continue;
|
|
}
|
|
|
|
const auto& well = schedule_.getWell(wname, reportStepNum);
|
|
tmp_names[0] = wname; // WellCumDataType::WellName
|
|
auto wName = static_cast<std::string>(wname);
|
|
auto get = [&st, &wName](const std::string& vector)
|
|
{
|
|
const auto key = vector + ':' + wName;
|
|
return st.has(key) ? st.get(key) : 0.0;
|
|
};
|
|
|
|
if (well.isInjector()) {
|
|
const auto& controls = well.injectionControls(st);
|
|
const auto ctlMode = controls.cmode;
|
|
const auto injType = controls.injector_type;
|
|
using CMode = ::Opm::Well::InjectorCMode;
|
|
using WType = ::Opm::InjectorType;
|
|
|
|
auto ftype = [](const auto wtype) -> std::string
|
|
{
|
|
switch (wtype) {
|
|
case WType::OIL: return "Oil";
|
|
case WType::WATER: return "Wat";
|
|
case WType::GAS: return "Gas";
|
|
case WType::MULTI: return "Multi";
|
|
default: return "";
|
|
}
|
|
};
|
|
|
|
auto fctl = [](const auto wmctl) -> std::string
|
|
{
|
|
switch (wmctl) {
|
|
case CMode::RATE: return "RATE";
|
|
case CMode::RESV: return "RESV";
|
|
case CMode::THP: return "THP";
|
|
case CMode::BHP: return "BHP";
|
|
case CMode::GRUP: return "GRUP";
|
|
default: return "";
|
|
}
|
|
};
|
|
|
|
tmp_names[1] = "INJ"; // WellCumDataType::WellType
|
|
const auto flowctl = fctl(ctlMode);
|
|
if (flowctl == "RATE") { // WellCumDataType::WellCTRL
|
|
const auto flowtype = ftype(injType);
|
|
if (flowtype == "Oil") {
|
|
tmp_names[2] = "ORAT";
|
|
} else if (flowtype == "Wat") {
|
|
tmp_names[2] = "WRAT";
|
|
} else if (flowtype == "Gas") {
|
|
tmp_names[2] = "GRAT";
|
|
}
|
|
} else {
|
|
tmp_names[2] = flowctl;
|
|
}
|
|
} else if (well.isProducer()) {
|
|
const auto& controls = well.productionControls(st);
|
|
using CMode = ::Opm::Well::ProducerCMode;
|
|
|
|
auto fctl = [](const auto wmctl) -> std::string
|
|
{
|
|
switch (wmctl) {
|
|
case CMode::ORAT: return "ORAT";
|
|
case CMode::WRAT: return "WRAT";
|
|
case CMode::GRAT: return "GRAT";
|
|
case CMode::LRAT: return "LRAT";
|
|
case CMode::RESV: return "RESV";
|
|
case CMode::THP: return "THP";
|
|
case CMode::BHP: return "BHP";
|
|
case CMode::CRAT: return "CRAT";
|
|
case CMode::GRUP: return "GRUP";
|
|
default: return "none";
|
|
}
|
|
};
|
|
tmp_names[1] = "PROD"; // WellProdDataType::CTRLMode
|
|
tmp_names[2] = fctl(controls.cmode); // WellProdDataType::CTRLMode
|
|
}
|
|
|
|
tmp_values[0] = well.getHeadI() + 1; // WellCumDataType::wellLocationi
|
|
tmp_values[1] = well.getHeadJ() + 1; // WellCumDataType::wellLocationj
|
|
tmp_values[2] = get("WOPT"); // WellCumDataType::OilProd
|
|
tmp_values[3] = get("WWPT"); // WellCumDataType::WaterProd
|
|
tmp_values[4] = get("WGPT"); // WellCumDataType::GasProd
|
|
tmp_values[5] = get("WVPT"); // WellCumDataType::FluidResVolProd
|
|
tmp_values[6] = get("WOIT"); // WellCumDataType::OilInj
|
|
tmp_values[7] = get("WWIT"); // WellCumDataType::WaterInj
|
|
tmp_values[8] = get("WGIT"); // WellCumDataType::GasInj
|
|
tmp_values[9] = get("WVIT"); // WellCumDataType::FluidResVolInj
|
|
|
|
this->outputCumulativeReport_(tmp_values, tmp_names);
|
|
}
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
error(const std::vector<int>& failedCellsPbub,
|
|
const std::vector<int>& failedCellsPdew) const
|
|
{
|
|
auto ijkString = [this](const std::size_t globalIndex)
|
|
{
|
|
const auto ijk = this->eclState_.gridDims().getIJK(globalIndex);
|
|
|
|
return fmt::format("({},{},{})", ijk[0] + 1, ijk[1] + 1, ijk[2] + 1);
|
|
};
|
|
|
|
constexpr auto maxNumCellsFaillog = static_cast<std::size_t>(20);
|
|
|
|
logUniqueFailedCells("Bubble point numerical problem",
|
|
"Finding the bubble point pressure",
|
|
maxNumCellsFaillog,
|
|
failedCellsPbub,
|
|
ijkString);
|
|
|
|
logUniqueFailedCells("Dew point numerical problem",
|
|
"Finding the dew point pressure",
|
|
maxNumCellsFaillog,
|
|
failedCellsPdew,
|
|
ijkString);
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
fip(const Inplace& inplace,
|
|
const Inplace& initialInplace) const
|
|
{
|
|
{
|
|
Scalar fieldHydroCarbonPoreVolumeAveragedPressure =
|
|
detail::pressureAverage(inplace.get(Inplace::Phase::PressureHydroCarbonPV),
|
|
inplace.get(Inplace::Phase::HydroCarbonPV),
|
|
inplace.get(Inplace::Phase::PressurePV),
|
|
inplace.get(Inplace::Phase::DynamicPoreVolume),
|
|
true);
|
|
|
|
std::unordered_map<Inplace::Phase, Scalar> initial_values;
|
|
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
|
|
|
for (const auto& phase : Inplace::phases()) {
|
|
initial_values[phase] = initialInplace.get(phase);
|
|
current_values[phase] = inplace.get(phase);
|
|
}
|
|
|
|
current_values[Inplace::Phase::DynamicPoreVolume] =
|
|
inplace.get(Inplace::Phase::DynamicPoreVolume);
|
|
|
|
this->fipUnitConvert_(initial_values);
|
|
this->fipUnitConvert_(current_values);
|
|
|
|
this->pressureUnitConvert_(fieldHydroCarbonPoreVolumeAveragedPressure);
|
|
this->outputRegionFluidInPlace_(std::move(initial_values),
|
|
std::move(current_values),
|
|
fieldHydroCarbonPoreVolumeAveragedPressure, 0);
|
|
}
|
|
|
|
for (std::size_t reg = 1; reg <= inplace.max_region("FIPNUM"); ++reg) {
|
|
std::unordered_map<Inplace::Phase, Scalar> initial_values;
|
|
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
|
|
|
for (const auto& phase : Inplace::phases()) {
|
|
initial_values[phase] = initialInplace.get("FIPNUM", phase, reg);
|
|
current_values[phase] = inplace.get("FIPNUM", phase, reg);
|
|
}
|
|
|
|
current_values[Inplace::Phase::DynamicPoreVolume] =
|
|
inplace.get("FIPNUM", Inplace::Phase::DynamicPoreVolume, reg);
|
|
|
|
this->fipUnitConvert_(initial_values);
|
|
this->fipUnitConvert_(current_values);
|
|
|
|
Scalar regHydroCarbonPoreVolumeAveragedPressure =
|
|
detail::pressureAverage(inplace.get("FIPNUM", Inplace::Phase::PressureHydroCarbonPV, reg),
|
|
inplace.get("FIPNUM", Inplace::Phase::HydroCarbonPV, reg),
|
|
inplace.get("FIPNUM", Inplace::Phase::PressurePV, reg),
|
|
inplace.get("FIPNUM", Inplace::Phase::DynamicPoreVolume, reg),
|
|
true);
|
|
this->pressureUnitConvert_(regHydroCarbonPoreVolumeAveragedPressure);
|
|
this->outputRegionFluidInPlace_(std::move(initial_values),
|
|
std::move(current_values),
|
|
regHydroCarbonPoreVolumeAveragedPressure, reg);
|
|
}
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
fipResv(const Inplace& inplace) const
|
|
{
|
|
{
|
|
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
|
|
|
for (const auto& phase : Inplace::phases()) {
|
|
current_values[phase] = inplace.get(phase);
|
|
}
|
|
this->fipUnitConvert_(current_values);
|
|
this->outputResvFluidInPlace_(current_values, 0);
|
|
}
|
|
|
|
for (std::size_t reg = 1; reg <= inplace.max_region("FIPNUM"); ++reg) {
|
|
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
|
|
|
for (const auto& phase : Inplace::phases()) {
|
|
current_values[phase] = inplace.get("FIPNUM", phase, reg);
|
|
}
|
|
current_values[Inplace::Phase::DynamicPoreVolume] =
|
|
inplace.get("FIPNUM", Inplace::Phase::DynamicPoreVolume, reg);
|
|
|
|
this->fipUnitConvert_(current_values);
|
|
this->outputResvFluidInPlace_(current_values, reg);
|
|
}
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
injection(const std::size_t reportStepNum,
|
|
std::function<bool(const std::string&)> isDefunct) const
|
|
{
|
|
std::vector<Scalar> tmp_values(WellInjDataType::numWIValues, 0.0);
|
|
std::vector<std::string> tmp_names(WellInjDataType::numWINames, "");
|
|
this->outputInjectionReport_(tmp_values, tmp_names);
|
|
|
|
const auto& st = summaryState_;
|
|
for (const auto& gname : schedule_.groupNames()) {
|
|
auto gName = static_cast<std::string>(gname);
|
|
auto get = [&st, &gName](const std::string& vector)
|
|
{
|
|
const auto key = vector + ':' + gName;
|
|
return st.has(key) ? st.get(key) : 0.0;
|
|
};
|
|
|
|
tmp_names[0] = gname;
|
|
if (tmp_names[0] == "FIELD") {
|
|
tmp_values[2] = st.get("FOIR", 0.0); // WellInjDataType::OilRate
|
|
tmp_values[3] = st.get("FWIR", 0.0); // WellInjDataType::WaterRate
|
|
tmp_values[4] = st.get("FGIR", 0.0); // WellInjDataType::GasRate
|
|
tmp_values[5] = st.get("FVIR", 0.0); // WellInjDataType::FluidResVol
|
|
} else {
|
|
tmp_values[2] = get("GOIR"); // WellInjDataType::OilRate
|
|
tmp_values[3] = get("GWIR"); // WellInjDataType::WaterRate
|
|
tmp_values[4] = get("GGIR"); // WellInjDataType::GasRate
|
|
tmp_values[5] = get("GVIR"); // WellInjDataType::FluidResVol
|
|
}
|
|
|
|
this->outputInjectionReport_(tmp_values, tmp_names);
|
|
}
|
|
|
|
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
|
// don't bother with wells not on this process
|
|
if (isDefunct(wname)) {
|
|
continue;
|
|
}
|
|
|
|
const auto& well = schedule_.getWell(wname, reportStepNum);
|
|
|
|
// Ignore Producer wells
|
|
if (well.isProducer()) {
|
|
continue;
|
|
}
|
|
|
|
tmp_names[0] = wname; // WellInjDataType::WellName
|
|
auto wName = static_cast<std::string>(wname);
|
|
auto get = [&st, &wName](const std::string& vector)
|
|
{
|
|
const auto key = vector + ':' + wName;
|
|
return st.has(key) ? st.get(key) : 0.0;
|
|
};
|
|
|
|
const auto& controls = well.injectionControls(st);
|
|
const auto ctlMode = controls.cmode;
|
|
const auto injType = controls.injector_type;
|
|
using CMode = Well::InjectorCMode;
|
|
using WType = InjectorType;
|
|
|
|
auto ftype = [](const auto wtype) -> std::string
|
|
{
|
|
switch (wtype) {
|
|
case WType::OIL: return "Oil";
|
|
case WType::WATER: return "Wat";
|
|
case WType::GAS: return "Gas";
|
|
case WType::MULTI: return "Multi";
|
|
default: return "";
|
|
}
|
|
};
|
|
|
|
auto fctl = [](const auto wmctl) -> std::string
|
|
{
|
|
switch (wmctl) {
|
|
case CMode::RATE: return "RATE";
|
|
case CMode::RESV: return "RESV";
|
|
case CMode::THP: return "THP";
|
|
case CMode::BHP: return "BHP";
|
|
case CMode::GRUP: return "GRUP";
|
|
default: return "";
|
|
}
|
|
};
|
|
|
|
const auto flowtype = ftype(injType);
|
|
const auto flowctl = fctl(ctlMode);
|
|
if (flowtype == "Oil") { // WellInjDataType::CTRLModeOil
|
|
if (flowctl == "RATE") {
|
|
tmp_names[1] = "ORAT";
|
|
} else {
|
|
tmp_names[1] = flowctl;
|
|
}
|
|
}
|
|
else if (flowtype == "Wat") { // WellInjDataType::CTRLModeWat
|
|
if (flowctl == "RATE") {
|
|
tmp_names[3] = "WRAT";
|
|
} else {
|
|
tmp_names[2] = flowctl;
|
|
}
|
|
}
|
|
else if (flowtype == "Gas") // WellInjDataType::CTRLModeGas
|
|
{
|
|
if (flowctl == "RATE") {
|
|
tmp_names[3] = "GRAT";
|
|
} else {
|
|
tmp_names[3] = flowctl;
|
|
}
|
|
}
|
|
|
|
tmp_values[0] = well.getHeadI() + 1; // WellInjDataType::wellLocationi
|
|
tmp_values[1] = well.getHeadJ() + 1; // WellInjDataType::wellLocationj
|
|
tmp_values[2] = get("WOIR"); // WellInjDataType::OilRate
|
|
tmp_values[3] = get("WWIR"); // WellInjDataType::WaterRate
|
|
tmp_values[4] = get("WGIR"); // WellInjDataType::GasRate
|
|
tmp_values[5] = get("WVIR");// WellInjDataType::FluidResVol
|
|
tmp_values[6] = get("WBHP"); // WellInjDataType::BHP
|
|
tmp_values[7] = get("WTHP"); // WellInjDataType::THP
|
|
//tmp_values[8] = 0; // WellInjDataType::SteadyStateII
|
|
|
|
this->outputInjectionReport_(tmp_values, tmp_names);
|
|
}
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
production(const std::size_t reportStepNum,
|
|
std::function<bool(const std::string&)> isDefunct) const
|
|
{
|
|
std::vector<Scalar> tmp_values(WellProdDataType::numWPValues, 0.0);
|
|
std::vector<std::string> tmp_names(WellProdDataType::numWPNames, "");
|
|
this->outputProductionReport_(tmp_values, tmp_names);
|
|
|
|
const auto& st = summaryState_;
|
|
for (const auto& gname : schedule_.groupNames()) {
|
|
auto gName = static_cast<std::string>(gname);
|
|
auto get = [&st, &gName](const std::string& vector)
|
|
{
|
|
const auto key = vector + ':' + gName;
|
|
return st.has(key) ? st.get(key) : 0.0;
|
|
};
|
|
|
|
tmp_names[0] = gname;
|
|
if (tmp_names[0] == "FIELD") {
|
|
tmp_values[2] = st.get("FOPR", 0.0); // WellProdDataType::OilRate
|
|
tmp_values[3] = st.get("FWPR", 0.0); // WellProdDataType::WaterRate
|
|
tmp_values[4] = st.get("FGPR", 0.0); // WellProdDataType::GasRate
|
|
tmp_values[5] = st.get("FVPR", 0.0); // WellProdDataType::FluidResVol
|
|
tmp_values[6] = st.get("FWCT", 0.0); // WellProdDataType::WaterCut
|
|
tmp_values[7] = st.get("FGOR", 0.0); // WellProdDataType::GasOilRatio
|
|
} else {
|
|
tmp_values[2] = get("GOPR"); // WellProdDataType::OilRate
|
|
tmp_values[3] = get("GWPR"); // WellProdDataType::WaterRate
|
|
tmp_values[4] = get("GGPR"); // WellProdDataType::GasRate
|
|
tmp_values[5] = get("GVPR"); // WellProdDataType::FluidResVol
|
|
tmp_values[6] = get("GWCT"); // WellProdDataType::WaterCut
|
|
tmp_values[7] = get("GGOR"); // WellProdDataType::GasOilRatio
|
|
}
|
|
|
|
tmp_values[8] = tmp_values[3] / tmp_values[4]; // WellProdDataType::WaterGasRatio
|
|
if (std::isnan(tmp_values[8])) {
|
|
tmp_values[8] = 0.0;
|
|
}
|
|
|
|
this->outputProductionReport_(tmp_values, tmp_names);
|
|
}
|
|
|
|
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
|
|
|
// don't bother with wells not on this process
|
|
if (isDefunct(wname)) {
|
|
continue;
|
|
}
|
|
|
|
const auto& well = schedule_.getWell(wname, reportStepNum);
|
|
|
|
// Ignore injector wells
|
|
if (well.isInjector()) {
|
|
continue;
|
|
}
|
|
|
|
tmp_names[0] = wname; // WellProdDataType::WellName
|
|
|
|
|
|
auto wName = static_cast<std::string>(wname);
|
|
auto get = [&st, &wName](const std::string& vector)
|
|
{
|
|
const auto key = vector + ':' + wName;
|
|
return st.has(key) ? st.get(key) : 0.0;
|
|
};
|
|
|
|
const auto& controls = well.productionControls(st);
|
|
using CMode = Well::ProducerCMode;
|
|
|
|
auto fctl = [](const auto wmctl) -> std::string
|
|
{
|
|
switch (wmctl) {
|
|
case CMode::ORAT: return "ORAT";
|
|
case CMode::WRAT: return "WRAT";
|
|
case CMode::GRAT: return "GRAT";
|
|
case CMode::LRAT: return "LRAT";
|
|
case CMode::RESV: return "RESV";
|
|
case CMode::THP: return "THP";
|
|
case CMode::BHP: return "BHP";
|
|
case CMode::CRAT: return "CRate";
|
|
case CMode::GRUP: return "GRUP";
|
|
default: return "none";
|
|
}
|
|
};
|
|
|
|
tmp_names[1] = fctl(controls.cmode); // WellProdDataType::CTRLMode
|
|
|
|
tmp_values[0] = well.getHeadI() + 1; // WellProdDataType::WellLocationi
|
|
tmp_values[1] = well.getHeadJ() + 1; // WellProdDataType::WellLocationj
|
|
tmp_values[2] = get("WOPR"); // WellProdDataType::OilRate
|
|
tmp_values[3] = get("WWPR"); // WellProdDataType::WaterRate
|
|
tmp_values[4] = get("WGPR"); // WellProdDataType::GasRate
|
|
tmp_values[5] = get("WVPR"); // WellProdDataType::FluidResVol
|
|
tmp_values[6] = get("WWCT"); // WellProdDataType::WaterCut
|
|
tmp_values[7] = get("WGOR"); // WellProdDataType::GasOilRatio
|
|
tmp_values[9] = get("WBHP"); // WellProdDataType::BHP
|
|
tmp_values[10] = get("WTHP"); // WellProdDataType::THP
|
|
//tmp_values[11] = 0; //WellProdDataType::SteadyStatePI //
|
|
|
|
tmp_values[8] = tmp_values[3] / tmp_values[4]; // WellProdDataType::WaterGasRatio
|
|
if (std::isnan(tmp_values[8])) {
|
|
tmp_values[8] = 0.0;
|
|
}
|
|
|
|
this->outputProductionReport_(tmp_values, tmp_names);
|
|
}
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputCumulativeReport_(const std::vector<Scalar>& wellCum,
|
|
const std::vector<std::string>& wellCumNames) const
|
|
{
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
std::ostringstream ss;
|
|
if (wellCumNames[WellCumDataType::WellName].empty()) {
|
|
ss << "=================================================== CUMULATIVE PRODUCTION/INJECTION REPORT =========================================\n"
|
|
<< ": WELL : LOCATION : WELL :CTRL: OIL : WATER : GAS : Prod : OIL : WATER : GAS : INJ :\n"
|
|
<< ": NAME : (I,J,K) : TYPE :MODE: PROD : PROD : PROD : RES.VOL. : INJ : INJ : INJ : RES.VOL. :\n";
|
|
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << ": : : : : MSCM : MSCM : MMSCM : MRCM : MSCM : MSCM : MMSCM : MRCM :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << ": : : : : MSTB : MSTB : MMSCF : MRB : MSTB : MSTB : MMSCF : MRB :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_LAB) {
|
|
ss << ": : : : : MSCC : MSCC : MMSCC : MRCC : MSCC : MSCC : MMSCC : MRCC :\n";
|
|
}
|
|
ss << "====================================================================================================================================\n";
|
|
} else {
|
|
if (wellCum[WellCumDataType::WellLocationi] < 1) {
|
|
ss << std::right << std::fixed << std::setprecision(0) << ":" << std::setw (8)
|
|
<< wellCumNames[WellCumDataType::WellName] << ":"
|
|
<< std::setw(11) << "" << ":"
|
|
<< std::setw(8) << wellCumNames[WellCumDataType::WellType] << ":"
|
|
<< std::setw(4) << wellCumNames[WellCumDataType::WellCTRL] << ":"
|
|
<< std::setprecision(1) << std::setw(11) << wellCum[WellCumDataType::OilProd] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::WaterProd] / 1000.0 << ":"
|
|
<< std::setw(11)<< wellCum[WellCumDataType::GasProd] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::FluidResVolProd] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::OilInj] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::WaterInj] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::GasInj] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::FluidResVolInj] / 1000.0 << ": \n";
|
|
} else {
|
|
ss << std::right << std::fixed << std::setprecision(0) << ":"
|
|
<< std::setw (8) << wellCumNames[WellCumDataType::WellName] << ":"
|
|
<< std::setw(5) << wellCum[WellCumDataType::WellLocationi] << ","
|
|
<< std::setw(5) << wellCum[WellCumDataType::WellLocationj] << ":"
|
|
<< std::setw(8) << wellCumNames[WellCumDataType::WellType] << ":"
|
|
<< std::setw(4) << wellCumNames[WellCumDataType::WellCTRL] << ":"
|
|
<< std::setprecision(1) << std::setw(11) << wellCum[WellCumDataType::OilProd] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::WaterProd] / 1000.0 << ":"
|
|
<< std::setw(11)<< wellCum[WellCumDataType::GasProd] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::FluidResVolProd] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::OilInj] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::WaterInj] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::GasInj] / 1000.0 << ":"
|
|
<< std::setw(11) << wellCum[WellCumDataType::FluidResVolInj] / 1000.0 << ": \n";
|
|
}
|
|
ss << ":--------:-----------:--------:----:------------:----------:-----------:-----------:------------:----------:-----------:-----------: \n";
|
|
}
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputInjectionReport_(const std::vector<Scalar>& wellInj,
|
|
const std::vector<std::string>& wellInjNames) const
|
|
{
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
std::ostringstream ss;
|
|
if (wellInjNames[WellInjDataType::WellName].empty()) {
|
|
ss << "=================================================== INJECTION REPORT ========================================\n"//===================== \n"
|
|
<< ": WELL : LOCATION : CTRL : CTRL : CTRL : OIL : WATER : GAS : FLUID : BHP OR : THP OR :\n"// STEADY-ST II :\n"
|
|
<< ": NAME : (I,J,K) : MODE : MODE : MODE : RATE : RATE : RATE : RES.VOL. : CON.PR.: BLK.PR.:\n";// OR POTENTIAL :\n";
|
|
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << ": : : OIL : WAT : GAS : SCM/DAY : SCM/DAY : SCM/DAY : RCM/DAY : BARSA : BARSA :\n";// :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << ": : : OIL : WAT : GAS : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : PSIA : PSIA :\n";// :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_LAB) {
|
|
ss << ": : : OIL : WAT : GAS : SCC/HR : SCC/HR : SCC/HR : RCC/HR : ATMA : ATMA :\n";// :\n";
|
|
}
|
|
ss << "==============================================================================================================\n";//===================== \n";
|
|
} else {
|
|
if (wellInj[WellInjDataType::WellLocationi] < 1) {
|
|
ss << std::right << std::fixed << std::setprecision(0) << ":"
|
|
<< std::setw (8) << wellInjNames[WellInjDataType::WellName] << ":"
|
|
<< std::setw(11) << "" << ":"
|
|
<< std::setw(6) << wellInjNames[WellInjDataType::CTRLModeOil] << ":"
|
|
<< std::setw(6) << wellInjNames[WellInjDataType::CTRLModeWat] << ":"
|
|
<< std::setw(6) << wellInjNames[WellInjDataType::CTRLModeGas] << ":"
|
|
<< std::setprecision(1) << std::setw(11) << wellInj[WellInjDataType::OilRate] << ":"
|
|
<< std::setw(11) << wellInj[WellInjDataType::WaterRate] << ":"
|
|
<< std::setw(11)<< wellInj[WellInjDataType::GasRate] << ":"
|
|
<< std::setw(11) << wellInj[WellInjDataType::FluidResVol] << ":"
|
|
<< std::setw(8)<< "" << ":" << std::setw(8)<< "" << ": \n";//wellInj[WellInjDataType::SteadyStateII] << std::setw(10) << "\n"
|
|
} else {
|
|
ss << std::right << std::fixed << std::setprecision(0) << ":"
|
|
<< std::setw (8) << wellInjNames[WellInjDataType::WellName] << ":"
|
|
<< std::setw(5) << wellInj[WellInjDataType::WellLocationi] << ","
|
|
<< std::setw(5) << wellInj[WellInjDataType::WellLocationj] << ":"
|
|
<< std::setw(6) << wellInjNames[WellInjDataType::CTRLModeOil] << ":"
|
|
<< std::setw(6) << wellInjNames[WellInjDataType::CTRLModeWat] << ":"
|
|
<< std::setw(6) << wellInjNames[WellInjDataType::CTRLModeGas] << ":"
|
|
<< std::setprecision(1) << std::setw(11) << wellInj[WellInjDataType::OilRate] << ":"
|
|
<< std::setw(11) << wellInj[WellInjDataType::WaterRate] << ":"
|
|
<< std::setw(11) << wellInj[WellInjDataType::GasRate] << ":"
|
|
<< std::setw(11) << wellInj[WellInjDataType::FluidResVol] << ":"
|
|
<< std::setw(8) << wellInj[WellInjDataType::BHP] << ":"
|
|
<< std::setw(8)<< wellInj[WellInjDataType::THP] << ": \n";//wellInj[WellInjDataType::SteadyStateII] << std::setw(10) << "\n"
|
|
}
|
|
ss << ":--------:-----------:------:------:------:------------:----------:-----------:-----------:--------:--------: \n";//--------------------:\n";
|
|
}
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputProductionReport_(const std::vector<Scalar>& wellProd,
|
|
const std::vector<std::string>& wellProdNames) const
|
|
{
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
std::ostringstream ss;
|
|
if (wellProdNames[WellProdDataType::WellName].empty()) {
|
|
ss << "======================================================= PRODUCTION REPORT =======================================================\n"//=================== \n"
|
|
<< ": WELL : LOCATION :CTRL: OIL : WATER : GAS : FLUID : WATER : GAS/OIL : WAT/GAS : BHP OR : THP OR :\n"// STEADY-ST PI :\n"
|
|
<< ": NAME : (I,J,K) :MODE: RATE : RATE : RATE : RES.VOL. : CUT : RATIO : RATIO : CON.PR.: BLK.PR.:\n";// OR POTN OF PREF. PH:\n";
|
|
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << ": : : : SCM/DAY : SCM/DAY : SCM/DAY : RCM/DAY : SCM/SCM : SCM/SCM : SCM/SCM : BARSA : BARSA :\n";// :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << ": : : : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : : MSCF/STB : STB/MSCF : PSIA : PSIA :\n";// :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_LAB) {
|
|
ss << ": : : : SCC/HR : SCC/HR : SCC/HR : RCC : SCC/SCC : SCC/SCC : SCC/SCC : ATMA : ATMA :\n";// :\n";
|
|
}
|
|
ss << "=================================================================================================================================\n";//=================== \n";
|
|
} else {
|
|
if (wellProd[WellProdDataType::WellLocationi] < 1) {
|
|
ss << std::right << std::fixed << ":"
|
|
<< std::setw(8) << wellProdNames[WellProdDataType::WellName] << ":"
|
|
<< std::setprecision(0) << std::setw(11) << "" << ":"
|
|
<< std::setw(4) << wellProdNames[WellProdDataType::CTRLMode] << ":"
|
|
<< std::setprecision(1) << std::setw(11) << wellProd[WellProdDataType::OilRate] << ":"
|
|
<< std::setw(11) << wellProd[WellProdDataType::WaterRate] << ":"
|
|
<< std::setw(11)<< wellProd[WellProdDataType::GasRate] << ":"
|
|
<< std::setw(11) << wellProd[WellProdDataType::FluidResVol] << std::setprecision(3) << ":"
|
|
<< std::setw(11) << wellProd[WellProdDataType::WaterCut] << std::setprecision(2) << ":"
|
|
<< std::setw(10) << wellProd[WellProdDataType::GasOilRatio] << std::setprecision(4) << ":"
|
|
<< std::setw(12) << wellProd[WellProdDataType::WatGasRatio] << std::setprecision(1) << ":"
|
|
<< std::setw(8) << "" << ":" << std::setw(8) << "" << ": \n";
|
|
} else {
|
|
ss << std::right << std::fixed << ":"
|
|
<< std::setw (8) << wellProdNames[WellProdDataType::WellName] << ":"
|
|
<< std::setprecision(0) << std::setw(5) << wellProd[WellProdDataType::WellLocationi] << ","
|
|
<< std::setw(5) << wellProd[WellProdDataType::WellLocationj] << ":"
|
|
<< std::setw(4) << wellProdNames[WellProdDataType::CTRLMode] << ":"
|
|
<< std::setprecision(1) << std::setw(11) << wellProd[WellProdDataType::OilRate] << ":"
|
|
<< std::setw(11) << wellProd[WellProdDataType::WaterRate] << ":"
|
|
<< std::setw(11)<< wellProd[WellProdDataType::GasRate] << ":"
|
|
<< std::setw(11) << wellProd[WellProdDataType::FluidResVol] << std::setprecision(3) << ":"
|
|
<< std::setw(11) << wellProd[WellProdDataType::WaterCut] << std::setprecision(2) << ":"
|
|
<< std::setw(10) << wellProd[WellProdDataType::GasOilRatio] << std::setprecision(4) << ":"
|
|
<< std::setw(12) << wellProd[WellProdDataType::WatGasRatio] << std::setprecision(1) << ":"
|
|
<< std::setw(8) << wellProd[WellProdDataType::BHP] << ":"
|
|
<< std::setw(8) << wellProd[WellProdDataType::THP] << ": \n";
|
|
}
|
|
ss << ":"<< std::setfill ('-') << std::setw (9) << ":"
|
|
<< std::setfill ('-') << std::setw (12) << ":"
|
|
<< std::setfill ('-') << std::setw (5) << ":"
|
|
<< std::setfill ('-') << std::setw (12) << ":"
|
|
<< std::setfill ('-') << std::setw (12) << ":"
|
|
<< std::setfill ('-') << std::setw (12) << ":"
|
|
<< std::setfill ('-') << std::setw (12) << ":"
|
|
<< std::setfill ('-') << std::setw (12) << ":"
|
|
<< std::setfill ('-') << std::setw (11) << ":"
|
|
<< std::setfill ('-') << std::setw (13) << ":"
|
|
<< std::setfill ('-') << std::setw (9) << ":"
|
|
<< std::setfill ('-') << std::setw (9) << ":" << "\n";
|
|
}
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputRegionFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> oip,
|
|
std::unordered_map<Inplace::Phase, Scalar> cip,
|
|
const Scalar pav,
|
|
const int reg) const
|
|
{
|
|
// don't output FIPNUM report if the region has no porv.
|
|
if (! (cip[Inplace::Phase::PoreVolume] > Scalar{0})) {
|
|
return;
|
|
}
|
|
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
std::ostringstream ss;
|
|
|
|
ss << '\n';
|
|
if (reg == 0) {
|
|
ss << "Field total";
|
|
} else {
|
|
ss << "FIPNUM report region " << reg;
|
|
}
|
|
|
|
ss << " pressure dependent pore volume = "
|
|
<< std::fixed << std::setprecision(0)
|
|
<< cip[Inplace::Phase::DynamicPoreVolume] << ' '
|
|
<< units.name(UnitSystem::measure::volume) << "\n\n";
|
|
|
|
if (reg == 0) {
|
|
ss << " ===================================================\n"
|
|
<< " : Field Totals :\n";
|
|
}
|
|
else {
|
|
ss << " ===================================================\n"
|
|
<< " : FIPNUM report region "
|
|
<< std::setw(2) << reg << " :\n";
|
|
}
|
|
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << " : PAV =" << std::setw(14) << pav << " BARSA :\n"
|
|
<< std::fixed << std::setprecision(0)
|
|
<< " : PORV =" << std::setw(14) << cip[Inplace::Phase::PoreVolume] << " RM3 :\n";
|
|
if (!reg) {
|
|
ss << " : Pressure is weighted by hydrocarbon pore volume :\n"
|
|
<< " : Porv volumes are taken at reference conditions :\n";
|
|
}
|
|
ss << " :--------------- Oil SM3 ---------------:-- Wat SM3 --:--------------- Gas SM3 ---------------:\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << " : PAV =" << std::setw(14) << pav << " PSIA :\n"
|
|
<< std::fixed << std::setprecision(0)
|
|
<< " : PORV =" << std::setw(14) << cip[Inplace::Phase::PoreVolume] << " RB :\n";
|
|
if (!reg) {
|
|
ss << " : Pressure is weighted by hydrocarbon pore volume :\n"
|
|
<< " : Pore volumes are taken at reference conditions :\n";
|
|
}
|
|
ss << " :--------------- Oil STB ---------------:-- Wat STB --:--------------- Gas MSCF ---------------:\n";
|
|
}
|
|
ss << " : Liquid Vapour Total : Total : Free Dissolved Total :" << "\n"
|
|
<< ":------------------------:------------------------------------------:----------------:------------------------------------------:" << "\n"
|
|
<< ":Currently in place :" << std::setw(14) << cip[Inplace::Phase::OilInLiquidPhase]
|
|
<< std::setw(14) << cip[Inplace::Phase::OilInGasPhase]
|
|
<< std::setw(14) << cip[Inplace::Phase::OIL] << ":"
|
|
<< std::setw(13) << cip[Inplace::Phase::WATER] << " :"
|
|
<< std::setw(14) << (cip[Inplace::Phase::GasInGasPhase])
|
|
<< std::setw(14) << cip[Inplace::Phase::GasInLiquidPhase]
|
|
<< std::setw(14) << cip[Inplace::Phase::GAS] << ":\n"
|
|
<< ":------------------------:------------------------------------------:----------------:------------------------------------------:\n"
|
|
<< ":Originally in place :" << std::setw(14) << oip[Inplace::Phase::OilInLiquidPhase]
|
|
<< std::setw(14) << oip[Inplace::Phase::OilInGasPhase]
|
|
<< std::setw(14) << oip[Inplace::Phase::OIL] << ":"
|
|
<< std::setw(13) << oip[Inplace::Phase::WATER] << " :"
|
|
<< std::setw(14) << oip[Inplace::Phase::GasInGasPhase]
|
|
<< std::setw(14) << oip[Inplace::Phase::GasInLiquidPhase]
|
|
<< std::setw(14) << oip[Inplace::Phase::GAS] << ":\n"
|
|
<< ":========================:==========================================:================:==========================================:\n";
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputResvFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> cipr,
|
|
const int reg) const
|
|
{
|
|
// don't output FIPNUM report if the region has no porv.
|
|
if (cipr[Inplace::Phase::PoreVolume] == 0) {
|
|
return;
|
|
}
|
|
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
std::ostringstream ss;
|
|
if (reg == 0) {
|
|
ss << " ===================================\n";
|
|
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << " : RESERVOIR VOLUMES M3 :\n";
|
|
} else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << " : RESERVOIR VOLUMES RB :\n";
|
|
}
|
|
ss << ":---------:---------------:---------------:---------------:---------------:---------------:\n"
|
|
<< ": REGION : TOTAL PORE : PORE VOLUME : PORE VOLUME : PORE VOLUME : PORE VOLUME :\n"
|
|
<< ": : VOLUME : CONTAINING : CONTAINING : CONTAINING : CONTAINING :\n"
|
|
<< ": : : OIL : WATER : GAS : HYDRO-CARBON :\n"
|
|
<< ":---------:---------------:---------------:---------------:---------------:---------------\n";
|
|
}
|
|
else {
|
|
ss << std::right << std::fixed << std::setprecision(0) << ":"
|
|
<< std::setw (9) << reg << ":"
|
|
<< std::setw(15) << cipr[Inplace::Phase::DynamicPoreVolume] << ":"
|
|
<< std::setw(15) << cipr[Inplace::Phase::OilResVolume] << ":"
|
|
<< std::setw(15) << cipr[Inplace::Phase::WaterResVolume] << ":"
|
|
<< std::setw(15) << cipr[Inplace::Phase::GasResVolume] << ":"
|
|
<< std::setw(15) << cipr[Inplace::Phase::OilResVolume] +
|
|
cipr[Inplace::Phase::GasResVolume] << ":\n"
|
|
<< ":---------:---------------:---------------:---------------:---------------:---------------:\n";
|
|
}
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
fipUnitConvert_(std::unordered_map<Inplace::Phase, Scalar>& fip) const
|
|
{
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
using M = UnitSystem::measure;
|
|
const auto unit_map = std::unordered_map<Inplace::Phase, M> {
|
|
{Inplace::Phase::WATER, M::liquid_surface_volume},
|
|
{Inplace::Phase::OIL, M::liquid_surface_volume},
|
|
{Inplace::Phase::OilInLiquidPhase, M::liquid_surface_volume},
|
|
{Inplace::Phase::OilInGasPhase, M::liquid_surface_volume},
|
|
{Inplace::Phase::GAS, M::gas_surface_volume},
|
|
{Inplace::Phase::GasInLiquidPhase, M::gas_surface_volume},
|
|
{Inplace::Phase::GasInGasPhase, M::gas_surface_volume},
|
|
{Inplace::Phase::PoreVolume, M::volume},
|
|
{Inplace::Phase::DynamicPoreVolume, M::volume},
|
|
{Inplace::Phase::WaterResVolume, M::volume},
|
|
{Inplace::Phase::OilResVolume, M::volume},
|
|
{Inplace::Phase::GasResVolume, M::volume},
|
|
{Inplace::Phase::SALT, M::mass},
|
|
{Inplace::Phase::CO2InWaterPhase, M::moles},
|
|
{Inplace::Phase::CO2InGasPhaseInMob,M::moles},
|
|
{Inplace::Phase::CO2InGasPhaseMob, M::moles},
|
|
{Inplace::Phase::WaterInWaterPhase, M::liquid_surface_volume},
|
|
{Inplace::Phase::WaterInGasPhase, M::liquid_surface_volume},
|
|
};
|
|
|
|
for (auto& [phase, value] : fip) {
|
|
auto unitPos = unit_map.find(phase);
|
|
if (unitPos != unit_map.end()) {
|
|
value = units.from_si(unitPos->second, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
pressureUnitConvert_(Scalar& pav) const
|
|
{
|
|
pav = eclState_.getUnits()
|
|
.from_si(UnitSystem::measure::pressure, pav);
|
|
}
|
|
|
|
template class LogOutputHelper<double>;
|
|
|
|
} // namespace Opm
|