mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
We accomplish that by passing the module version as a string to the constructors of LogOutputHelper and EclGenericOutputBlackoilModel instead of calling moduleVersionName() in LogOutputHelper. That way moduleVersionName is not needed by libopmsimulators anymore and compilation works again for people requesting shared libraries via CMake's BUILD_SHARED_LIBS variable.
995 lines
43 KiB
C++
995 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/utils/moduleVersion.hpp>
|
|
#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 <opm/input/eclipse/Units/Units.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,
|
|
const std::string& moduleVersionName)
|
|
: eclState_(eclState)
|
|
, schedule_(schedule)
|
|
, summaryState_(summaryState)
|
|
, flowVersionName_(moduleVersionName)
|
|
{}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
cumulative(const std::size_t reportStepNum) const
|
|
{
|
|
this->beginCumulativeReport_();
|
|
|
|
std::vector<Scalar> tmp_values(WellCumDataType::numWCValues, 0.0);
|
|
std::vector<std::string> tmp_names(WellCumDataType::numWCNames, "");
|
|
|
|
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->outputCumulativeReportRecord_(tmp_values, tmp_names);
|
|
}
|
|
|
|
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
|
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->outputCumulativeReportRecord_(tmp_values, tmp_names);
|
|
}
|
|
|
|
this->endCumulativeReport_();
|
|
}
|
|
|
|
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 std::string& name) const
|
|
{
|
|
auto iget = [&name](const Inplace& ip,
|
|
Inplace::Phase phase,
|
|
std::size_t idx)
|
|
{
|
|
if (name.empty()) {
|
|
return ip.get(phase);
|
|
}
|
|
|
|
return ip.get(name, phase, idx);
|
|
};
|
|
|
|
for (std::size_t reg = 1; reg <= (name.empty() ? 1 : inplace.max_region(name)); ++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] = iget(initialInplace, phase, reg);
|
|
current_values[phase] = iget(inplace, phase, reg);
|
|
}
|
|
|
|
current_values[Inplace::Phase::DynamicPoreVolume] =
|
|
iget(inplace, Inplace::Phase::DynamicPoreVolume, reg);
|
|
|
|
this->fipUnitConvert_(initial_values);
|
|
this->fipUnitConvert_(current_values);
|
|
|
|
Scalar regHydroCarbonPoreVolumeAveragedPressure =
|
|
detail::pressureAverage(iget(inplace, Inplace::Phase::PressureHydroCarbonPV, reg),
|
|
iget(inplace, Inplace::Phase::HydroCarbonPV, reg),
|
|
iget(inplace, Inplace::Phase::PressurePV, reg),
|
|
iget(inplace, Inplace::Phase::DynamicPoreVolume, reg),
|
|
true);
|
|
this->pressureUnitConvert_(regHydroCarbonPoreVolumeAveragedPressure);
|
|
this->outputRegionFluidInPlace_(std::move(initial_values),
|
|
std::move(current_values),
|
|
regHydroCarbonPoreVolumeAveragedPressure,
|
|
name,
|
|
name.empty() ? 0 : reg);
|
|
}
|
|
}
|
|
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
fipResv(const Inplace& inplace, const std::string& name) const
|
|
{
|
|
{
|
|
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
|
|
|
for (const auto& phase : Inplace::phases())
|
|
current_values[phase] = inplace.get(phase);
|
|
|
|
Scalar field_dyn_pv = 0.0;
|
|
|
|
|
|
for (auto nreg = inplace.max_region(name), reg = 0*nreg + 1; reg <= nreg; ++reg)
|
|
field_dyn_pv = field_dyn_pv + inplace.get(name, Inplace::Phase::DynamicPoreVolume, reg);
|
|
|
|
current_values[Inplace::Phase::DynamicPoreVolume] = field_dyn_pv;
|
|
|
|
this->fipUnitConvert_(current_values);
|
|
this->outputResvFluidInPlace_(current_values, 0);
|
|
}
|
|
|
|
for (auto nreg = inplace.max_region(), reg = 0*nreg + 1; reg <= nreg; ++reg) {
|
|
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
|
|
|
for (const auto& phase : Inplace::phases()) {
|
|
if (reg <= inplace.max_region(name))
|
|
current_values[phase] = inplace.get(name, phase, reg);
|
|
else
|
|
current_values[phase] = 0.0;
|
|
}
|
|
|
|
if (reg <= inplace.max_region(name))
|
|
current_values[Inplace::Phase::DynamicPoreVolume] =
|
|
inplace.get(name, Inplace::Phase::DynamicPoreVolume, reg);
|
|
else
|
|
current_values[Inplace::Phase::DynamicPoreVolume] = 0.0;
|
|
|
|
this->fipUnitConvert_(current_values);
|
|
this->outputResvFluidInPlace_(current_values, reg);
|
|
}
|
|
|
|
std::ostringstream ss;
|
|
ss << " ===========================================================================================";
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
timeStamp(const std::string& lbl, double elapsed, int rstep, boost::posix_time::ptime currentDate) const
|
|
{
|
|
|
|
std::ostringstream ss;
|
|
boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d %b %Y");
|
|
ss.imbue(std::locale(std::locale::classic(), facet));
|
|
|
|
ss << "\n **************************************************************************\n"
|
|
<< " " << std::left << std::setw(9) << lbl << "AT" << std::right << std::setw(10)
|
|
<< (double)unit::convert::to(elapsed, unit::day) << " DAYS" << " *" << std::setw(30) << eclState_.getTitle() << " *\n"
|
|
<< " REPORT " << std::setw(4) << rstep << " " << currentDate
|
|
<< " * Flow version " << std::setw(11) << flowVersionName_ << " *\n"
|
|
<< " **************************************************************************\n";
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
injection(const std::size_t reportStepNum) const
|
|
{
|
|
this->beginInjectionReport_();
|
|
|
|
std::vector<Scalar> tmp_values(WellInjDataType::numWIValues, 0.0);
|
|
std::vector<std::string> tmp_names(WellInjDataType::numWINames, "");
|
|
|
|
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->outputInjectionReportRecord_(tmp_values, tmp_names);
|
|
}
|
|
|
|
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
|
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->outputInjectionReportRecord_(tmp_values, tmp_names);
|
|
}
|
|
|
|
this->endInjectionReport_();
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
production(const std::size_t reportStepNum) const
|
|
{
|
|
this->beginProductionReport_();
|
|
|
|
std::vector<Scalar> tmp_values(WellProdDataType::numWPValues, 0.0);
|
|
std::vector<std::string> tmp_names(WellProdDataType::numWPNames, "");
|
|
|
|
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->outputProductionReportRecord_(tmp_values, tmp_names);
|
|
}
|
|
|
|
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
|
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->outputProductionReportRecord_(tmp_values, tmp_names);
|
|
}
|
|
|
|
this->endProductionReport_();
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void LogOutputHelper<Scalar>::beginCumulativeReport_() const
|
|
{
|
|
const auto unitType = this->eclState_.getUnits().getType();
|
|
|
|
std::ostringstream ss;
|
|
|
|
ss << "\n=================================================== 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 (unitType == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << ": : : : : MSCM : MSCM : MMSCM : MRCM : MSCM : MSCM : MMSCM : MRCM :\n";
|
|
} else if (unitType == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << ": : : : : MSTB : MSTB : MMSCF : MRB : MSTB : MSTB : MMSCF : MRB :\n";
|
|
} else if (unitType == UnitSystem::UnitType::UNIT_TYPE_LAB) {
|
|
ss << ": : : : : MSCC : MSCC : MMSCC : MRCC : MSCC : MSCC : MMSCC : MRCC :\n";
|
|
}
|
|
|
|
ss << "====================================================================================================================================";
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void LogOutputHelper<Scalar>::endCumulativeReport_() const
|
|
{
|
|
const auto ss = std::string { ":--------:-----------:--------:----:-----------:-----------:-----------:-----------:-----------:-----------:-----------:-----------:" };
|
|
|
|
OpmLog::note(ss);
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputCumulativeReportRecord_(const std::vector<Scalar>& wellCum,
|
|
const std::vector<std::string>& wellCumNames) const
|
|
{
|
|
std::ostringstream ss;
|
|
|
|
ss << std::right << std::fixed << std::setprecision(0) << ':'
|
|
<< std::setw(8) << wellCumNames[WellCumDataType::WellName] << ':';
|
|
|
|
if (wellCum[WellCumDataType::WellLocationi] < 1) {
|
|
ss << std::setw(11) << "" << ':';
|
|
} else {
|
|
ss << std::setw( 5) << wellCum[WellCumDataType::WellLocationi] << ','
|
|
<< std::setw( 5) << wellCum[WellCumDataType::WellLocationj] << ':';
|
|
}
|
|
|
|
auto scaledValue = [&wellCum](const typename WellCumDataType::WCId quantity)
|
|
{
|
|
// Unit M*
|
|
return wellCum[quantity] / 1000.0;
|
|
};
|
|
|
|
auto scaledGasValue = [&wellCum](const typename WellCumDataType::WCId quantity)
|
|
{
|
|
// Unit MM*
|
|
return wellCum[quantity] / (1000.0 * 1000.0);
|
|
};
|
|
|
|
ss << std::setw( 8) << wellCumNames[WellCumDataType::WCId::WellType] << ':'
|
|
<< std::setw( 4) << wellCumNames[WellCumDataType::WCId::WellCTRL] << ':' << std::setprecision(1)
|
|
<< std::setw(11) << scaledValue(WellCumDataType::WCId::OilProd) << ':'
|
|
<< std::setw(11) << scaledValue(WellCumDataType::WCId::WaterProd) << ':'
|
|
<< std::setw(11) << scaledGasValue(WellCumDataType::WCId::GasProd) << ':'
|
|
<< std::setw(11) << scaledValue(WellCumDataType::WCId::FluidResVolProd) << ':'
|
|
<< std::setw(11) << scaledValue(WellCumDataType::WCId::OilInj) << ':'
|
|
<< std::setw(11) << scaledValue(WellCumDataType::WCId::WaterInj) << ':'
|
|
<< std::setw(11) << scaledGasValue(WellCumDataType::WCId::GasInj) << ':'
|
|
<< std::setw(11) << scaledValue(WellCumDataType::WCId::FluidResVolInj) << ':';
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void LogOutputHelper<Scalar>::beginInjectionReport_() const
|
|
{
|
|
const auto unitType = this->eclState_.getUnits().getType();
|
|
|
|
std::ostringstream ss;
|
|
ss << "\n=================================================== 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 (unitType == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << ": : : OIL : WAT : GAS : SCM/DAY : SCM/DAY : SCM/DAY : RCM/DAY : BARSA : BARSA :\n";// :\n";
|
|
} else if (unitType == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << ": : : OIL : WAT : GAS : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : PSIA : PSIA :\n";// :\n";
|
|
} else if (unitType == UnitSystem::UnitType::UNIT_TYPE_LAB) {
|
|
ss << ": : : OIL : WAT : GAS : SCC/HR : SCC/HR : SCC/HR : RCC/HR : ATMA : ATMA :\n";// :\n";
|
|
}
|
|
|
|
ss << "=============================================================================================================";//=====================";
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void LogOutputHelper<Scalar>::endInjectionReport_() const
|
|
{
|
|
const auto ss = std::string { ":--------:-----------:------:------:------:-----------:-----------:-----------:-----------:--------:--------:" };
|
|
|
|
OpmLog::note(ss);
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputInjectionReportRecord_(const std::vector<Scalar>& wellInj,
|
|
const std::vector<std::string>& wellInjNames) const
|
|
{
|
|
const auto isWellRecord =
|
|
wellInj[WellProdDataType::WellLocationi] >= 1;
|
|
|
|
std::ostringstream ss;
|
|
|
|
ss << std::right << std::fixed << std::setprecision(0) << ':'
|
|
<< std::setw(8) << wellInjNames[WellInjDataType::WellName] << ':';
|
|
|
|
if (! isWellRecord) {
|
|
ss << std::setw(11) << "" << ':';
|
|
} else {
|
|
ss << std::setw( 5) << wellInj[WellInjDataType::WellLocationi] << ','
|
|
<< std::setw( 5) << wellInj[WellInjDataType::WellLocationj] << ':';
|
|
}
|
|
|
|
ss << 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] << ':';
|
|
|
|
if (! isWellRecord) {
|
|
ss << std::setw(8) << "" << ':' << std::setw(8) << "" << ':'; //wellInj[WellInjDataType::SteadyStateII] << std::setw(10) << "\n"
|
|
} else {
|
|
ss << std::setw(8) << wellInj[WellInjDataType::BHP] << ':'
|
|
<< std::setw(8) << wellInj[WellInjDataType::THP] << ':'; //wellInj[WellInjDataType::SteadyStateII] << std::setw(10) << "\n"
|
|
}
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void LogOutputHelper<Scalar>::beginProductionReport_() const
|
|
{
|
|
const auto unitType = this->eclState_.getUnits().getType();
|
|
|
|
std::ostringstream ss;
|
|
ss << "\n======================================================= 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 (unitType == 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 (unitType == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
|
ss << ": : : : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : : MSCF/STB : STB/MSCF : PSIA : PSIA :\n";// :\n";
|
|
} else if (unitType == UnitSystem::UnitType::UNIT_TYPE_LAB) {
|
|
ss << ": : : : SCC/HR : SCC/HR : SCC/HR : RCC : SCC/SCC : SCC/SCC : SCC/SCC : ATMA : ATMA :\n";// :\n";
|
|
}
|
|
|
|
ss << "=================================================================================================================================";//===================";
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template <typename Scalar>
|
|
void LogOutputHelper<Scalar>::endProductionReport_() const
|
|
{
|
|
std::ostringstream ss;
|
|
|
|
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) << ':';
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputProductionReportRecord_(const std::vector<Scalar>& wellProd,
|
|
const std::vector<std::string>& wellProdNames) const
|
|
{
|
|
const auto isWellRecord =
|
|
wellProd[WellProdDataType::WellLocationi] >= 1;
|
|
|
|
std::ostringstream ss;
|
|
|
|
ss << std::right << std::fixed << ':'
|
|
<< std::setw(8) << wellProdNames[WellProdDataType::WellName] << ':';
|
|
|
|
if (! isWellRecord) {
|
|
ss << std::setprecision(0) << std::setw(11) << "" << ':';
|
|
} else {
|
|
ss << std::setprecision(0)
|
|
<< std::setw(5) << wellProd[WellProdDataType::WellLocationi] << ','
|
|
<< std::setw(5) << wellProd[WellProdDataType::WellLocationj] << ':';
|
|
}
|
|
|
|
ss << 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);
|
|
|
|
if (! isWellRecord) {
|
|
ss << std::setw(8) << "" << ':' << std::setw(8) << "" << ':';
|
|
} else {
|
|
ss << std::setw(8) << wellProd[WellProdDataType::BHP] << ':'
|
|
<< std::setw(8) << wellProd[WellProdDataType::THP] << ':';
|
|
}
|
|
|
|
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 std::string& name,
|
|
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 << " ==================================================\n"
|
|
<< " : FIELD TOTALS :\n";
|
|
}
|
|
else {
|
|
ss << " ==================================================\n"
|
|
<< " : " << name << " REPORT REGION "
|
|
<< std::setw(8 - name.size()) << 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 << std::fixed << std::setprecision(0)
|
|
<< " : 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(15) << cip[Inplace::Phase::OIL] << ":"
|
|
<< std::setw(14) << cip[Inplace::Phase::WATER] << " :"
|
|
<< std::setw(14) << (cip[Inplace::Phase::GasInGasPhase])
|
|
<< std::setw(14) << cip[Inplace::Phase::GasInLiquidPhase]
|
|
<< std::setw(15) << 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(15) << oip[Inplace::Phase::OIL] << ":"
|
|
<< std::setw(14) << oip[Inplace::Phase::WATER] << " :"
|
|
<< std::setw(14) << oip[Inplace::Phase::GasInGasPhase]
|
|
<< std::setw(14) << oip[Inplace::Phase::GasInLiquidPhase]
|
|
<< std::setw(15) << oip[Inplace::Phase::GAS] << ":\n";
|
|
|
|
if (reg == 0){
|
|
ss << " ====================================================================================================================================\n\n";
|
|
|
|
} else {
|
|
ss << " :-------------------------:-------------------------------------------:----------------:-------------------------------------------:\n";
|
|
ss << " ====================================================================================================================================\n\n";
|
|
}
|
|
|
|
OpmLog::note(ss.str());
|
|
}
|
|
|
|
template<class Scalar>
|
|
void LogOutputHelper<Scalar>::
|
|
outputResvFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> cipr,
|
|
const int reg) const
|
|
{
|
|
const UnitSystem& units = eclState_.getUnits();
|
|
std::ostringstream ss;
|
|
|
|
if (reg == 0) {
|
|
ss << "\n ===================================\n";
|
|
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) {
|
|
ss << " : RESERVOIR VOLUMES RM3 :\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";
|
|
|
|
ss << std::right << std::fixed << std::setprecision(0) << " :"
|
|
<< std::setw (8) << "FIELD" << " :";
|
|
|
|
} else {
|
|
ss << std::right << std::fixed << std::setprecision(0) << " :"
|
|
<< std::setw (8) << reg << " :";
|
|
}
|
|
|
|
ss << 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] << ":";
|
|
|
|
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},
|
|
{Inplace::Phase::CO2Mass, M::mass},
|
|
{Inplace::Phase::CO2MassInWaterPhase, M::mass},
|
|
{Inplace::Phase::CO2MassInGasPhase, M::mass},
|
|
{Inplace::Phase::CO2MassInGasPhaseInMob,M::mass},
|
|
{Inplace::Phase::CO2MassInGasPhaseMob, M::mass},
|
|
};
|
|
|
|
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
|