mirror of
https://github.com/OPM/opm-simulators.git
synced 2024-11-24 10:10:18 -06:00
Merge pull request #4775 from akva2/logoutput_separate_class
Add dedicated class for output of logs
This commit is contained in:
commit
f806e7668b
@ -48,6 +48,7 @@ list (APPEND MAIN_SOURCE_FILES
|
||||
opm/simulators/flow/ExtraConvergenceOutputThread.cpp
|
||||
opm/simulators/flow/FlowMainEbos.cpp
|
||||
opm/simulators/flow/KeywordValidation.cpp
|
||||
opm/simulators/flow/LogOutputHelper.cpp
|
||||
opm/simulators/flow/Main.cpp
|
||||
opm/simulators/flow/NonlinearSolverEbos.cpp
|
||||
opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.cpp
|
||||
@ -84,6 +85,7 @@ list (APPEND MAIN_SOURCE_FILES
|
||||
opm/simulators/utils/ParallelFileMerger.cpp
|
||||
opm/simulators/utils/ParallelRestart.cpp
|
||||
opm/simulators/utils/PartiallySupportedFlowKeywords.cpp
|
||||
opm/simulators/utils/PressureAverage.cpp
|
||||
opm/simulators/utils/readDeck.cpp
|
||||
opm/simulators/utils/SerializationPackers.cpp
|
||||
opm/simulators/utils/UnsupportedFlowKeywords.cpp
|
||||
@ -252,6 +254,7 @@ list (APPEND TEST_SOURCE_FILES
|
||||
tests/test_GroupState.cpp
|
||||
tests/test_invert.cpp
|
||||
tests/test_keyword_validator.cpp
|
||||
tests/test_LogOutputHelper.cpp
|
||||
tests/test_milu.cpp
|
||||
tests/test_multmatrixtransposed.cpp
|
||||
tests/test_norne_pvt.cpp
|
||||
@ -425,6 +428,7 @@ list (APPEND PUBLIC_HEADER_FILES
|
||||
opm/simulators/flow/NonlinearSolverEbos.hpp
|
||||
opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp
|
||||
opm/simulators/flow/KeywordValidation.hpp
|
||||
opm/simulators/flow/LogOutputHelper.hpp
|
||||
opm/simulators/flow/ValidationFunctions.hpp
|
||||
opm/simulators/flow/partitionCells.hpp
|
||||
opm/simulators/flow/SubDomain.hpp
|
||||
@ -512,6 +516,7 @@ list (APPEND PUBLIC_HEADER_FILES
|
||||
opm/simulators/utils/PropsCentroidsDataHandle.hpp
|
||||
opm/simulators/utils/SerializationPackers.hpp
|
||||
opm/simulators/utils/VectorVectorDataHandle.hpp
|
||||
opm/simulators/utils/PressureAverage.hpp
|
||||
opm/simulators/utils/readDeck.hpp
|
||||
opm/simulators/wells/ALQState.hpp
|
||||
opm/simulators/wells/BlackoilWellModel.hpp
|
||||
|
@ -39,6 +39,8 @@
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/input/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/simulators/utils/PressureAverage.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
@ -161,6 +163,7 @@ EclGenericOutputBlackoilModule(const EclipseState& eclState,
|
||||
, summaryConfig_(summaryConfig)
|
||||
, summaryState_(summaryState)
|
||||
, interRegionFlows_(numCells(eclState), defineInterRegionFlowArrays(eclState, summaryConfig))
|
||||
, logOutput_(eclState, schedule, summaryState)
|
||||
, enableEnergy_(enableEnergy)
|
||||
, enableTemperature_(enableTemperature)
|
||||
, enableSolvent_(enableSolvent)
|
||||
@ -222,160 +225,10 @@ template<class FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputCumLog(size_t reportStepNum, const bool substep, bool forceDisableCumOutput)
|
||||
{
|
||||
if (!substep) {
|
||||
ScalarBuffer tmp_values(WellCumDataType::numWCValues, 0.0);
|
||||
StringBuffer tmp_names(WellCumDataType::numWCNames, "");
|
||||
outputCumulativeReport_(tmp_values, tmp_names, forceDisableCumOutput);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
outputCumulativeReport_(tmp_values, tmp_names, forceDisableCumOutput);
|
||||
}
|
||||
|
||||
for (const auto& wname : schedule_.wellNames(reportStepNum)) {
|
||||
|
||||
// don't bother with wells not on this process
|
||||
if (isDefunctParallelWell(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
|
||||
|
||||
outputCumulativeReport_(tmp_values, tmp_names, forceDisableCumOutput);
|
||||
|
||||
}
|
||||
if (!substep && !forceDisableCumOutput) {
|
||||
logOutput_.cumulative(reportStepNum,
|
||||
[this](const std::string& name)
|
||||
{ return this->isDefunctParallelWell(name); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -385,117 +238,10 @@ outputProdLog(size_t reportStepNum,
|
||||
const bool substep,
|
||||
bool forceDisableProdOutput)
|
||||
{
|
||||
if (!substep) {
|
||||
ScalarBuffer tmp_values(WellProdDataType::numWPValues, 0.0);
|
||||
StringBuffer tmp_names(WellProdDataType::numWPNames, "");
|
||||
outputProductionReport_(tmp_values, tmp_names, forceDisableProdOutput);
|
||||
|
||||
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 (isnan(tmp_values[8])){
|
||||
tmp_values[8] = 0.0;
|
||||
}
|
||||
|
||||
outputProductionReport_(tmp_values, tmp_names, forceDisableProdOutput);
|
||||
}
|
||||
|
||||
for (const auto& wname: schedule_.wellNames(reportStepNum)) {
|
||||
|
||||
// don't bother with wells not on this process
|
||||
if (isDefunctParallelWell(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 (isnan(tmp_values[8])){
|
||||
tmp_values[8] = 0.0;
|
||||
}
|
||||
|
||||
outputProductionReport_(tmp_values, tmp_names, forceDisableProdOutput);
|
||||
}
|
||||
if (!substep && !forceDisableProdOutput) {
|
||||
logOutput_.production(reportStepNum,
|
||||
[this](const std::string& name)
|
||||
{ return this->isDefunctParallelWell(name); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -503,129 +249,10 @@ template<class FluidSystem,class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputInjLog(size_t reportStepNum, const bool substep, bool forceDisableInjOutput)
|
||||
{
|
||||
if (!substep) {
|
||||
ScalarBuffer tmp_values(WellInjDataType::numWIValues, 0.0);
|
||||
StringBuffer tmp_names(WellInjDataType::numWINames, "");
|
||||
outputInjectionReport_(tmp_values, tmp_names, forceDisableInjOutput);
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
outputInjectionReport_(tmp_values, tmp_names, forceDisableInjOutput);
|
||||
}
|
||||
|
||||
for (const auto& wname: schedule_.wellNames(reportStepNum)) {
|
||||
|
||||
// don't bother with wells not on this process
|
||||
if (isDefunctParallelWell(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
|
||||
|
||||
outputInjectionReport_(tmp_values, tmp_names, forceDisableInjOutput);
|
||||
}
|
||||
if (!substep && !forceDisableInjOutput) {
|
||||
logOutput_.injection(reportStepNum,
|
||||
[this](const std::string& name)
|
||||
{ return this->isDefunctParallelWell(name); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -644,8 +271,9 @@ outputFipLog(std::map<std::string, double>& miscSummaryData,
|
||||
miscSummaryData,
|
||||
regionData);
|
||||
|
||||
if (!substep)
|
||||
outputFipLogImpl(inplace);
|
||||
if (!substep && !forceDisableFipOutput_) {
|
||||
logOutput_.fip(inplace, this->initialInplace());
|
||||
}
|
||||
|
||||
return inplace;
|
||||
}
|
||||
@ -665,8 +293,9 @@ outputFipresvLog(std::map<std::string, double>& miscSummaryData,
|
||||
miscSummaryData,
|
||||
regionData);
|
||||
|
||||
if (!substep)
|
||||
outputFipresvLogImpl(inplace);
|
||||
if (!substep && !forceDisableFipresvOutput_) {
|
||||
logOutput_.fipResv(inplace);
|
||||
}
|
||||
|
||||
return inplace;
|
||||
}
|
||||
@ -1415,266 +1044,6 @@ doAllocBuffers(unsigned bufferSize,
|
||||
}
|
||||
}
|
||||
|
||||
template<class FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,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 FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
pressureUnitConvert_(Scalar& pav) const
|
||||
{
|
||||
pav = this->eclState_.getUnits()
|
||||
.from_si(UnitSystem::measure::pressure, pav);
|
||||
}
|
||||
|
||||
template<class FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputRegionFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> oip,
|
||||
std::unordered_map<Inplace::Phase, Scalar> cip,
|
||||
const Scalar& pav, const int reg) const
|
||||
{
|
||||
if (forceDisableFipOutput_)
|
||||
return;
|
||||
|
||||
// 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";
|
||||
}
|
||||
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 FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputResvFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> cipr, const int reg) const
|
||||
{
|
||||
if (forceDisableFipresvOutput_)
|
||||
return;
|
||||
|
||||
// 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";
|
||||
}
|
||||
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 FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputProductionReport_(const ScalarBuffer& wellProd,
|
||||
const StringBuffer& wellProdNames,
|
||||
const bool forceDisableProdOutput)
|
||||
{
|
||||
if (forceDisableProdOutput)
|
||||
return;
|
||||
|
||||
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";
|
||||
}
|
||||
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";
|
||||
}
|
||||
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 FluidSystem, class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputInjectionReport_(const ScalarBuffer& wellInj,
|
||||
const StringBuffer& wellInjNames,
|
||||
const bool forceDisableInjOutput)
|
||||
{
|
||||
if (forceDisableInjOutput)
|
||||
return;
|
||||
|
||||
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";
|
||||
}
|
||||
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
||||
ss << ": : : OIL : WAT : GAS : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : PSIA : PSIA :\n";// :\n";
|
||||
}
|
||||
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 FluidSystem,class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputCumulativeReport_(const ScalarBuffer& wellCum,
|
||||
const StringBuffer& wellCumNames,
|
||||
const bool forceDisableCumOutput)
|
||||
{
|
||||
if (forceDisableCumOutput)
|
||||
return;
|
||||
|
||||
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";
|
||||
}
|
||||
if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) {
|
||||
ss << ": : : : : MSTB : MSTB : MMSCF : MRB : MSTB : MSTB : MMSCF : MRB :\n";
|
||||
}
|
||||
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 << ":" << std::setw(11) << wellCum[WellCumDataType::WaterProd]/1000 << ":" << std::setw(11)<< wellCum[WellCumDataType::GasProd]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::FluidResVolProd]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::OilInj]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::WaterInj]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::GasInj]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::FluidResVolInj]/1000 << ": \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 << ":" << std::setw(11) << wellCum[WellCumDataType::WaterProd]/1000 << ":" << std::setw(11)<< wellCum[WellCumDataType::GasProd]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::FluidResVolProd]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::OilInj]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::WaterInj]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::GasInj]/1000 << ":" << std::setw(11) << wellCum[WellCumDataType::FluidResVolInj]/1000 << ": \n";
|
||||
}
|
||||
ss << ":--------:-----------:--------:----:------------:----------:-----------:-----------:------------:----------:-----------:-----------: \n";
|
||||
}
|
||||
OpmLog::note(ss.str());
|
||||
}
|
||||
|
||||
template<class FluidSystem,class Scalar>
|
||||
bool EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
isOutputCreationDirective_(const std::string& keyword)
|
||||
@ -1684,84 +1053,6 @@ isOutputCreationDirective_(const std::string& keyword)
|
||||
|| (keyword == "SAVE") || (keyword == "SFREQ"); // Not really supported
|
||||
}
|
||||
|
||||
template<class FluidSystem, class Scalar>
|
||||
Scalar EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
pressureAverage_(const Scalar& pressurePvHydrocarbon,
|
||||
const Scalar& pvHydrocarbon,
|
||||
const Scalar& pressurePv,
|
||||
const Scalar& pv,
|
||||
const bool hydrocarbon)
|
||||
{
|
||||
if (hydrocarbon && (pvHydrocarbon > 1e-10))
|
||||
return pressurePvHydrocarbon / pvHydrocarbon;
|
||||
|
||||
return pressurePv / pv;
|
||||
}
|
||||
|
||||
template<class FluidSystem,class Scalar>
|
||||
typename EclGenericOutputBlackoilModule<FluidSystem,Scalar>::ScalarBuffer
|
||||
EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
pressureAverage_(const ScalarBuffer& pressurePvHydrocarbon,
|
||||
const ScalarBuffer& pvHydrocarbon,
|
||||
const ScalarBuffer& pressurePv,
|
||||
const ScalarBuffer& pv,
|
||||
const bool hydrocarbon)
|
||||
{
|
||||
const std::size_t size = pressurePvHydrocarbon.size();
|
||||
assert(pvHydrocarbon.size() == size);
|
||||
assert(pressurePv.size() == size);
|
||||
assert(pv.size() == size);
|
||||
|
||||
ScalarBuffer fraction(size, 0.0);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
fraction[i] = pressureAverage_(pressurePvHydrocarbon[i],
|
||||
pvHydrocarbon[i],
|
||||
pressurePv[i],
|
||||
pv[i],
|
||||
hydrocarbon);
|
||||
}
|
||||
|
||||
return fraction;
|
||||
}
|
||||
|
||||
namespace {
|
||||
template <typename IndexVector, typename IJKString>
|
||||
void logUniqueFailedCells(const std::string& messageTag,
|
||||
std::string_view prefix,
|
||||
const std::size_t maxNumCellsFaillog,
|
||||
IndexVector&& cells,
|
||||
IJKString&& ijkString)
|
||||
{
|
||||
if (cells.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::sort(cells.begin(), cells.end());
|
||||
auto u = std::unique(cells.begin(), cells.end());
|
||||
|
||||
const auto numFailed = static_cast<std::size_t>
|
||||
(std::distance(cells.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 << ']';
|
||||
|
||||
OpmLog::warning(messageTag, errlog.str());
|
||||
}
|
||||
} // Namespace anonymous
|
||||
|
||||
template<class FluidSystem,class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputErrorLog(const Parallel::Communication& comm) const
|
||||
@ -1776,113 +1067,8 @@ outputErrorLog(const Parallel::Communication& comm) const
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
};
|
||||
|
||||
const auto maxNumCellsFaillog = static_cast<std::size_t>(20);
|
||||
|
||||
logUniqueFailedCells("Bubble point numerical problem",
|
||||
"Finding the bubble point pressure",
|
||||
maxNumCellsFaillog,
|
||||
std::get<0>(std::move(globalFailedCellsPbub)),
|
||||
ijkString);
|
||||
|
||||
logUniqueFailedCells("Dew point numerical problem",
|
||||
"Finding the dew point pressure",
|
||||
maxNumCellsFaillog,
|
||||
std::get<0>(std::move(globalFailedCellsPdew)),
|
||||
ijkString);
|
||||
}
|
||||
|
||||
template<class FluidSystem,class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputFipLogImpl(const Inplace& inplace) const
|
||||
{
|
||||
{
|
||||
Scalar fieldHydroCarbonPoreVolumeAveragedPressure = 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] = this->initialInplace_->get(phase);
|
||||
current_values[phase] = inplace.get(phase);
|
||||
}
|
||||
|
||||
current_values[Inplace::Phase::DynamicPoreVolume] =
|
||||
inplace.get(Inplace::Phase::DynamicPoreVolume);
|
||||
|
||||
fipUnitConvert_(initial_values);
|
||||
fipUnitConvert_(current_values);
|
||||
|
||||
pressureUnitConvert_(fieldHydroCarbonPoreVolumeAveragedPressure);
|
||||
outputRegionFluidInPlace_(std::move(initial_values),
|
||||
std::move(current_values),
|
||||
fieldHydroCarbonPoreVolumeAveragedPressure);
|
||||
}
|
||||
|
||||
for (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] = this->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);
|
||||
|
||||
fipUnitConvert_(initial_values);
|
||||
fipUnitConvert_(current_values);
|
||||
|
||||
Scalar regHydroCarbonPoreVolumeAveragedPressure
|
||||
= 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);
|
||||
pressureUnitConvert_(regHydroCarbonPoreVolumeAveragedPressure);
|
||||
outputRegionFluidInPlace_(std::move(initial_values),
|
||||
std::move(current_values),
|
||||
regHydroCarbonPoreVolumeAveragedPressure, reg);
|
||||
}
|
||||
}
|
||||
|
||||
template<class FluidSystem,class Scalar>
|
||||
void EclGenericOutputBlackoilModule<FluidSystem,Scalar>::
|
||||
outputFipresvLogImpl(const Inplace& inplace) const
|
||||
{
|
||||
{
|
||||
std::unordered_map<Inplace::Phase, Scalar> current_values;
|
||||
|
||||
for (const auto& phase : Inplace::phases()) {
|
||||
current_values[phase] = inplace.get(phase);
|
||||
}
|
||||
fipUnitConvert_(current_values);
|
||||
outputResvFluidInPlace_(current_values);
|
||||
}
|
||||
|
||||
for (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);
|
||||
|
||||
fipUnitConvert_(current_values);
|
||||
outputResvFluidInPlace_(current_values, reg);
|
||||
}
|
||||
logOutput_.error(std::get<0>(globalFailedCellsPbub),
|
||||
std::get<0>(globalFailedCellsPdew));
|
||||
}
|
||||
|
||||
template<class FluidSystem,class Scalar>
|
||||
@ -2003,22 +1189,21 @@ updateSummaryRegionValues(const Inplace& inplace,
|
||||
|
||||
if (this->summaryConfig_.hasKeyword("FPR")) {
|
||||
miscSummaryData["FPR"] =
|
||||
pressureAverage_(inplace.get(Inplace::Phase::PressureHydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::HydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::PressurePV),
|
||||
inplace.get(Inplace::Phase::DynamicPoreVolume),
|
||||
true);
|
||||
detail::pressureAverage(inplace.get(Inplace::Phase::PressureHydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::HydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::PressurePV),
|
||||
inplace.get(Inplace::Phase::DynamicPoreVolume),
|
||||
true);
|
||||
}
|
||||
|
||||
if (this->summaryConfig_.hasKeyword("FPRP")) {
|
||||
miscSummaryData["FPRP"] =
|
||||
pressureAverage_(inplace.get(Inplace::Phase::PressureHydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::HydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::PressurePV),
|
||||
inplace.get(Inplace::Phase::DynamicPoreVolume),
|
||||
false);
|
||||
detail::pressureAverage(inplace.get(Inplace::Phase::PressureHydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::HydroCarbonPV),
|
||||
inplace.get(Inplace::Phase::PressurePV),
|
||||
inplace.get(Inplace::Phase::DynamicPoreVolume),
|
||||
false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The region summary vectors should loop through the FIPxxx regions to
|
||||
@ -2038,20 +1223,20 @@ updateSummaryRegionValues(const Inplace& inplace,
|
||||
|
||||
for (const auto& node : this->RPRNodes_) {
|
||||
regionData[node.keyword()] =
|
||||
pressureAverage_(get_vector(node, Inplace::Phase::PressureHydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::HydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::PressurePV),
|
||||
get_vector(node, Inplace::Phase::DynamicPoreVolume),
|
||||
true);
|
||||
detail::pressureAverage(get_vector(node, Inplace::Phase::PressureHydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::HydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::PressurePV),
|
||||
get_vector(node, Inplace::Phase::DynamicPoreVolume),
|
||||
true);
|
||||
}
|
||||
|
||||
for (const auto& node : this->RPRPNodes_) {
|
||||
regionData[node.keyword()] =
|
||||
pressureAverage_(get_vector(node, Inplace::Phase::PressureHydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::HydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::PressurePV),
|
||||
get_vector(node, Inplace::Phase::DynamicPoreVolume),
|
||||
false);
|
||||
detail::pressureAverage(get_vector(node, Inplace::Phase::PressureHydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::HydroCarbonPV),
|
||||
get_vector(node, Inplace::Phase::PressurePV),
|
||||
get_vector(node, Inplace::Phase::DynamicPoreVolume),
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <opm/output/data/Wells.hpp>
|
||||
#include <opm/output/eclipse/Inplace.hpp>
|
||||
|
||||
#include <opm/simulators/flow/LogOutputHelper.hpp>
|
||||
#include <opm/simulators/utils/ParallelCommunication.hpp>
|
||||
|
||||
#include <array>
|
||||
@ -293,74 +294,6 @@ protected:
|
||||
bool enableExtbo,
|
||||
bool enableMICP);
|
||||
|
||||
struct WellProdDataType
|
||||
{
|
||||
enum WPId
|
||||
{
|
||||
WellLocationi = 0, //WLi
|
||||
WellLocationj = 1, //WLj
|
||||
OilRate = 2, //OR
|
||||
WaterRate = 3, //WR
|
||||
GasRate = 4, //GR
|
||||
FluidResVol = 5, //FRV
|
||||
WaterCut = 6, //WC
|
||||
GasOilRatio = 7, //GOR
|
||||
WatGasRatio = 8, //WGR
|
||||
BHP = 9, //BHP
|
||||
THP = 10, //THP
|
||||
SteadyStatePI = 11, //SteadyStatePI
|
||||
WellName = 0, //WName
|
||||
CTRLMode = 1, //CTRL
|
||||
};
|
||||
|
||||
static constexpr int numWPValues = 12;
|
||||
static constexpr int numWPNames = 2;
|
||||
};
|
||||
|
||||
struct WellInjDataType
|
||||
{
|
||||
enum WIId
|
||||
{
|
||||
WellLocationi = 0, //WLi
|
||||
WellLocationj = 1, //WLj
|
||||
OilRate = 2, //OR
|
||||
WaterRate = 3, //WR
|
||||
GasRate = 4, //GR
|
||||
FluidResVol = 5, //FRV
|
||||
BHP = 6, //BHP
|
||||
THP = 7, //THP
|
||||
SteadyStateII = 8, //SteadyStateII
|
||||
WellName = 0, //WName
|
||||
CTRLModeOil = 1, //CTRLo
|
||||
CTRLModeWat = 2, //CTRLw
|
||||
CTRLModeGas = 3, //CTRLg
|
||||
};
|
||||
static constexpr int numWIValues = 9;
|
||||
static constexpr int numWINames = 4;
|
||||
};
|
||||
|
||||
struct WellCumDataType
|
||||
{
|
||||
enum WCId
|
||||
{
|
||||
WellLocationi = 0, //WLi
|
||||
WellLocationj = 1, //WLj
|
||||
OilProd = 2, //OP
|
||||
WaterProd = 3, //WP
|
||||
GasProd = 4, //GP
|
||||
FluidResVolProd = 5, //FRVP
|
||||
OilInj = 6, //OI
|
||||
WaterInj = 7, //WI
|
||||
GasInj = 8, //GI
|
||||
FluidResVolInj = 9, //FRVI
|
||||
WellName = 0, //WName
|
||||
WellType = 1, //WType
|
||||
WellCTRL = 2, //WCTRL
|
||||
};
|
||||
static constexpr int numWCValues = 10;
|
||||
static constexpr int numWCNames = 3;
|
||||
};
|
||||
|
||||
void doAllocBuffers(unsigned bufferSize,
|
||||
unsigned reportStepNum,
|
||||
const bool substep,
|
||||
@ -371,29 +304,6 @@ protected:
|
||||
unsigned numTracers,
|
||||
unsigned numOutputNnc);
|
||||
|
||||
void fipUnitConvert_(std::unordered_map<Inplace::Phase, Scalar>& fip) const;
|
||||
|
||||
void pressureUnitConvert_(Scalar& pav) const;
|
||||
|
||||
void outputRegionFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> oip,
|
||||
std::unordered_map<Inplace::Phase, Scalar> cip,
|
||||
const Scalar& pav, const int reg = 0) const;
|
||||
void outputResvFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> cipr,
|
||||
const int reg = 0) const;
|
||||
void outputProductionReport_(const ScalarBuffer& wellProd,
|
||||
const StringBuffer& wellProdNames,
|
||||
const bool forceDisableProdOutput);
|
||||
void outputInjectionReport_(const ScalarBuffer& wellInj,
|
||||
const StringBuffer& wellInjNames,
|
||||
const bool forceDisableInjOutput);
|
||||
void outputCumulativeReport_(const ScalarBuffer& wellCum,
|
||||
const StringBuffer& wellCumNames,
|
||||
const bool forceDisableCumOutput);
|
||||
|
||||
void outputFipLogImpl(const Inplace& inplace) const;
|
||||
|
||||
void outputFipresvLogImpl(const Inplace& inplace) const;
|
||||
|
||||
void makeRegionSum(Inplace& inplace,
|
||||
const std::string& region_name,
|
||||
const Parallel::Communication& comm) const;
|
||||
@ -406,17 +316,6 @@ protected:
|
||||
|
||||
static bool isOutputCreationDirective_(const std::string& keyword);
|
||||
|
||||
static Scalar pressureAverage_(const Scalar& pressurePvHydrocarbon,
|
||||
const Scalar& pvHydrocarbon,
|
||||
const Scalar& pressurePv,
|
||||
const Scalar& pv,
|
||||
bool hydrocarbon);
|
||||
|
||||
static ScalarBuffer pressureAverage_(const ScalarBuffer& pressurePvHydrocarbon,
|
||||
const ScalarBuffer& pvHydrocarbon,
|
||||
const ScalarBuffer& pressurePv,
|
||||
const ScalarBuffer& pv,
|
||||
bool hydrocarbon);
|
||||
// Sum Fip values over regions.
|
||||
static ScalarBuffer regionSum(const ScalarBuffer& property,
|
||||
const std::vector<int>& regionId,
|
||||
@ -444,6 +343,7 @@ protected:
|
||||
const SummaryState& summaryState_;
|
||||
|
||||
EclInterRegFlowMap interRegionFlows_;
|
||||
LogOutputHelper<Scalar> logOutput_;
|
||||
|
||||
bool enableEnergy_;
|
||||
bool enableTemperature_;
|
||||
|
912
opm/simulators/flow/LogOutputHelper.cpp
Normal file
912
opm/simulators/flow/LogOutputHelper.cpp
Normal file
@ -0,0 +1,912 @@
|
||||
// -*- 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 (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
|
166
opm/simulators/flow/LogOutputHelper.hpp
Normal file
166
opm/simulators/flow/LogOutputHelper.hpp
Normal file
@ -0,0 +1,166 @@
|
||||
// -*- 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.
|
||||
*/
|
||||
/*!
|
||||
* \file
|
||||
*/
|
||||
#ifndef LOG_OUTPUT_HELPER_HPP
|
||||
#define LOG_OUTPUT_HELPER_HPP
|
||||
|
||||
#include <opm/output/eclipse/Inplace.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class EclipseState;
|
||||
class Inplace;
|
||||
class Schedule;
|
||||
class SummaryState;
|
||||
|
||||
template<class Scalar>
|
||||
class LogOutputHelper {
|
||||
public:
|
||||
LogOutputHelper(const EclipseState& eclState,
|
||||
const Schedule& schedule,
|
||||
const SummaryState& st);
|
||||
|
||||
//! \brief Write cumulative production and injection reports to output.
|
||||
void cumulative(const std::size_t reportStepNum,
|
||||
std::function<bool(const std::string&)> isDefunct) const;
|
||||
|
||||
//! \brief Write error report to output.
|
||||
void error(const std::vector<int>& failedCellsPbub,
|
||||
const std::vector<int>& failedCellsPdew) const;
|
||||
|
||||
//! \brief Write fluid-in-place reports to output.
|
||||
void fip(const Inplace& inplace,
|
||||
const Inplace& initialInplace) const;
|
||||
|
||||
//! \brief Write fluid-in-place reservoir reports to output.
|
||||
void fipResv(const Inplace& inplace) const;
|
||||
|
||||
//! \brief Write injection report to output.
|
||||
void injection(const std::size_t reportStepNum,
|
||||
std::function<bool(const std::string&)> isDefunct) const;
|
||||
|
||||
//! \brief Write production report to output.
|
||||
void production(const std::size_t reportStepNum,
|
||||
std::function<bool(const std::string&)> isDefunct) const;
|
||||
|
||||
private:
|
||||
void outputCumulativeReport_(const std::vector<Scalar>& wellCum,
|
||||
const std::vector<std::string>& wellCumNames) const;
|
||||
|
||||
void outputRegionFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> oip,
|
||||
std::unordered_map<Inplace::Phase, Scalar> cip,
|
||||
const Scalar pav,
|
||||
const int reg) const;
|
||||
|
||||
void outputResvFluidInPlace_(std::unordered_map<Inplace::Phase, Scalar> cipr,
|
||||
const int reg) const;
|
||||
|
||||
void outputInjectionReport_(const std::vector<Scalar>& wellInj,
|
||||
const std::vector<std::string>& wellInjNames) const;
|
||||
|
||||
void outputProductionReport_(const std::vector<Scalar>& wellProd,
|
||||
const std::vector<std::string>& wellProdNames) const;
|
||||
|
||||
void fipUnitConvert_(std::unordered_map<Inplace::Phase, Scalar>& fip) const;
|
||||
void pressureUnitConvert_(Scalar& pav) const;
|
||||
|
||||
struct WellCumDataType
|
||||
{
|
||||
enum WCId
|
||||
{
|
||||
WellLocationi = 0, // WLi
|
||||
WellLocationj = 1, // WLj
|
||||
OilProd = 2, // OP
|
||||
WaterProd = 3, // WP
|
||||
GasProd = 4, // GP
|
||||
FluidResVolProd = 5, // FRVP
|
||||
OilInj = 6, // OI
|
||||
WaterInj = 7, // WI
|
||||
GasInj = 8, // GI
|
||||
FluidResVolInj = 9, // FRVI
|
||||
WellName = 0, // WName
|
||||
WellType = 1, // WType
|
||||
WellCTRL = 2, // WCTRL
|
||||
};
|
||||
static constexpr int numWCValues = 10;
|
||||
static constexpr int numWCNames = 3;
|
||||
};
|
||||
|
||||
struct WellInjDataType
|
||||
{
|
||||
enum WIId
|
||||
{
|
||||
WellLocationi = 0, // WLi
|
||||
WellLocationj = 1, // WLj
|
||||
OilRate = 2, // OR
|
||||
WaterRate = 3, // WR
|
||||
GasRate = 4, // GR
|
||||
FluidResVol = 5, // FRV
|
||||
BHP = 6, // BHP
|
||||
THP = 7, // THP
|
||||
SteadyStateII = 8, // SteadyStateII
|
||||
WellName = 0, // WName
|
||||
CTRLModeOil = 1, // CTRLo
|
||||
CTRLModeWat = 2, // CTRLw
|
||||
CTRLModeGas = 3, // CTRLg
|
||||
};
|
||||
static constexpr int numWIValues = 9;
|
||||
static constexpr int numWINames = 4;
|
||||
};
|
||||
|
||||
struct WellProdDataType
|
||||
{
|
||||
enum WPId
|
||||
{
|
||||
WellLocationi = 0, // WLi
|
||||
WellLocationj = 1, // WLj
|
||||
OilRate = 2, // OR
|
||||
WaterRate = 3, // WR
|
||||
GasRate = 4, // GR
|
||||
FluidResVol = 5, // FRV
|
||||
WaterCut = 6, // WC
|
||||
GasOilRatio = 7, // GOR
|
||||
WatGasRatio = 8, // WGR
|
||||
BHP = 9, // BHP
|
||||
THP = 10, // THP
|
||||
SteadyStatePI = 11, // SteadyStatePI
|
||||
WellName = 0, // WName
|
||||
CTRLMode = 1, // CTRL
|
||||
};
|
||||
|
||||
static constexpr int numWPValues = 12;
|
||||
static constexpr int numWPNames = 2;
|
||||
};
|
||||
|
||||
const EclipseState& eclState_;
|
||||
const Schedule& schedule_;
|
||||
const SummaryState& summaryState_;
|
||||
};
|
||||
|
||||
} // namespace Opm
|
||||
|
||||
#endif // LOG_OUTPUT_HELPER_HPP
|
81
opm/simulators/utils/PressureAverage.cpp
Normal file
81
opm/simulators/utils/PressureAverage.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
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/PressureAverage.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
|
||||
namespace Opm {
|
||||
namespace detail {
|
||||
|
||||
template<class Scalar>
|
||||
Scalar
|
||||
pressureAverage(const Scalar pressurePvHydrocarbon,
|
||||
const Scalar pvHydrocarbon,
|
||||
const Scalar pressurePv,
|
||||
const Scalar pv,
|
||||
const bool hydrocarbon)
|
||||
{
|
||||
if (hydrocarbon && (pvHydrocarbon > 1e-10))
|
||||
return pressurePvHydrocarbon / pvHydrocarbon;
|
||||
|
||||
return pressurePv / pv;
|
||||
}
|
||||
|
||||
template<class Scalar>
|
||||
std::vector<Scalar>
|
||||
pressureAverage(const std::vector<Scalar>& pressurePvHydrocarbon,
|
||||
const std::vector<Scalar>& pvHydrocarbon,
|
||||
const std::vector<Scalar>& pressurePv,
|
||||
const std::vector<Scalar>& pv,
|
||||
const bool hydrocarbon)
|
||||
{
|
||||
const std::size_t size = pressurePvHydrocarbon.size();
|
||||
assert(pvHydrocarbon.size() == size);
|
||||
assert(pressurePv.size() == size);
|
||||
assert(pv.size() == size);
|
||||
|
||||
std::vector<Scalar> fraction(size, 0.0);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
fraction[i] = pressureAverage(pressurePvHydrocarbon[i],
|
||||
pvHydrocarbon[i],
|
||||
pressurePv[i],
|
||||
pv[i],
|
||||
hydrocarbon);
|
||||
}
|
||||
|
||||
return fraction;
|
||||
}
|
||||
|
||||
template double
|
||||
pressureAverage<double>(const double,
|
||||
const double,
|
||||
const double,
|
||||
const double,
|
||||
const bool);
|
||||
|
||||
template std::vector<double>
|
||||
pressureAverage<double>(const std::vector<double>&,
|
||||
const std::vector<double>&,
|
||||
const std::vector<double>&,
|
||||
const std::vector<double>&,
|
||||
const bool);
|
||||
|
||||
} // namespace detail
|
||||
} // namespace Opm
|
46
opm/simulators/utils/PressureAverage.hpp
Normal file
46
opm/simulators/utils/PressureAverage.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifndef PRESSURE_AVERAGE_HPP
|
||||
#define PRESSURE_AVERAGE_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Opm {
|
||||
namespace detail {
|
||||
|
||||
//! \brief Calculates average pressure value.
|
||||
template<class Scalar>
|
||||
Scalar pressureAverage(const Scalar pressurePvHydrocarbon,
|
||||
const Scalar pvHydrocarbon,
|
||||
const Scalar pressurePv,
|
||||
const Scalar pv,
|
||||
const bool hydrocarbon);
|
||||
|
||||
//! \brief Calculates average pressure value for a vector.
|
||||
template<class Scalar>
|
||||
std::vector<Scalar>
|
||||
pressureAverage(const std::vector<Scalar>& pressurePvHydrocarbon,
|
||||
const std::vector<Scalar>& pvHydrocarbon,
|
||||
const std::vector<Scalar>& pressurePv,
|
||||
const std::vector<Scalar>& pv,
|
||||
const bool hydrocarbon);
|
||||
|
||||
} // namespace detail
|
||||
} // namespace Opm
|
||||
|
||||
#endif // PRESSURE_AVERAGE_HPP
|
443
tests/test_LogOutputHelper.cpp
Normal file
443
tests/test_LogOutputHelper.cpp
Normal file
@ -0,0 +1,443 @@
|
||||
/*
|
||||
Copyright 2018 SINTEF Digital, Mathematics and Cybernetics.
|
||||
Copyright 2018 Equinor.
|
||||
|
||||
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 3 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/>.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#define BOOST_TEST_MODULE TestLogOutputHelper
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/common/OpmLog/OpmLog.hpp>
|
||||
#include <opm/common/OpmLog/StreamLog.hpp>
|
||||
#include <opm/common/utility/String.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/input/eclipse/Python/Python.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
|
||||
#include <opm/simulators/flow/LogOutputHelper.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
const std::string input = R"(
|
||||
RUNSPEC
|
||||
FIELD
|
||||
DIMENS
|
||||
10 10 3 /
|
||||
DX
|
||||
300*1000 /
|
||||
DY
|
||||
300*1000 /
|
||||
DZ
|
||||
100*20 100*30 100*50 /
|
||||
TOPS
|
||||
100*8325 /
|
||||
START -- 0
|
||||
31 AUG 1993 /
|
||||
SCHEDULE
|
||||
WELSPECS
|
||||
-- Item #: 1 2 3 4 5 6
|
||||
'PROD' 'G1' 10 10 8400 'OIL' /
|
||||
'INJ' 'G1' 1 1 8335 'GAS' /
|
||||
/
|
||||
WCONPROD
|
||||
-- Item #:1 2 3 4 5 9
|
||||
'PROD' 'OPEN' 'ORAT' 20000 4* 1000 /
|
||||
/
|
||||
WCONINJE
|
||||
-- Item #:1 2 3 4 5 6 7
|
||||
'INJ' 'GAS' 'OPEN' 'RATE' 100000 1* 9014 /
|
||||
/)";
|
||||
|
||||
std::string trimStream(std::stringstream& str)
|
||||
{
|
||||
char buffer[1024];
|
||||
std::string data;
|
||||
do {
|
||||
str.getline(buffer, 1024, '\n');
|
||||
std::string tmp(buffer);
|
||||
if (!tmp.empty()) {
|
||||
tmp = Opm::trim_copy(tmp);
|
||||
data += tmp;
|
||||
data += '\n';
|
||||
}
|
||||
} while (!str.eof());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Cumulative)
|
||||
{
|
||||
const std::string reference = R"(=================================================== CUMULATIVE PRODUCTION/INJECTION REPORT =========================================
|
||||
: WELL : LOCATION : WELL :CTRL: OIL : WATER : GAS : Prod : OIL : WATER : GAS : INJ :
|
||||
: NAME : (I,J,K) : TYPE :MODE: PROD : PROD : PROD : RES.VOL. : INJ : INJ : INJ : RES.VOL. :
|
||||
: : : : : MSTB : MSTB : MMSCF : MRB : MSTB : MSTB : MMSCF : MRB :
|
||||
====================================================================================================================================
|
||||
: FIELD: : : : 1.0: 2.0: 3.0: 4.0: 5.0: 6.0: 7.0: 8.0:
|
||||
:--------:-----------:--------:----:------------:----------:-----------:-----------:------------:----------:-----------:-----------:
|
||||
: G1: : : : 9.0: 10.0: 11.0: 12.0: 13.0: 14.0: 15.0: 15.0:
|
||||
:--------:-----------:--------:----:------------:----------:-----------:-----------:------------:----------:-----------:-----------:
|
||||
: PROD: 10, 10: PROD:ORAT: 16.0: 17.0: 18.0: 19.0: 20.0: 21.0: 22.0: 23.0:
|
||||
:--------:-----------:--------:----:------------:----------:-----------:-----------:------------:----------:-----------:-----------:
|
||||
: INJ: 1, 1: INJ:GRAT: 24.0: 25.0: 26.0: 27.0: 28.0: 29.0: 30.0: 31.0:
|
||||
:--------:-----------:--------:----:------------:----------:-----------:-----------:------------:----------:-----------:-----------:
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto python = std::make_shared<Opm::Python>();
|
||||
auto deck = parser.parseString(input);
|
||||
Opm::EclipseGrid grid(10,10,3);
|
||||
Opm::TableManager table ( deck );
|
||||
Opm::FieldPropsManager fp( deck, Opm::Phases{true, true, true}, grid, table);
|
||||
Opm::Runspec runspec (deck );
|
||||
Opm::Schedule schedule(deck, grid, fp, runspec, python);
|
||||
|
||||
Opm::EclipseState eclState(deck);
|
||||
Opm::SummaryState st;
|
||||
constexpr auto fields = std::array {
|
||||
std::pair{"FOPT", 1.0},
|
||||
std::pair{"FWPT", 2.0},
|
||||
std::pair{"FGPT", 3.0},
|
||||
std::pair{"FVPT", 4.0},
|
||||
std::pair{"FOIT", 5.0},
|
||||
std::pair{"FWIT", 6.0},
|
||||
std::pair{"FGIT", 7.0},
|
||||
std::pair{"FVIT", 8.0},
|
||||
std::pair{"GOPT:G1", 9.0},
|
||||
std::pair{"GWPT:G1", 10.0},
|
||||
std::pair{"GGPT:G1", 11.0},
|
||||
std::pair{"GVPT:G1", 12.0},
|
||||
std::pair{"GOIT:G1", 13.0},
|
||||
std::pair{"GWIT:G1", 14.0},
|
||||
std::pair{"GGIT:G1", 15.0},
|
||||
std::pair{"GVIT:G1", 15.0},
|
||||
std::pair{"WOPT:PROD", 16.0},
|
||||
std::pair{"WWPT:PROD", 17.0},
|
||||
std::pair{"WGPT:PROD", 18.0},
|
||||
std::pair{"WVPT:PROD", 19.0},
|
||||
std::pair{"WOIT:PROD", 20.0},
|
||||
std::pair{"WWIT:PROD", 21.0},
|
||||
std::pair{"WGIT:PROD", 22.0},
|
||||
std::pair{"WVIT:PROD", 23.0},
|
||||
std::pair{"WOPT:INJ", 24.0},
|
||||
std::pair{"WWPT:INJ", 25.0},
|
||||
std::pair{"WGPT:INJ", 26.0},
|
||||
std::pair{"WVPT:INJ", 27.0},
|
||||
std::pair{"WOIT:INJ", 28.0},
|
||||
std::pair{"WWIT:INJ", 29.0},
|
||||
std::pair{"WGIT:INJ", 30.0},
|
||||
std::pair{"WVIT:INJ", 31.0},
|
||||
};
|
||||
for (const auto& p : fields) {
|
||||
st.set(p.first, p.second * 1e3);
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
Opm::OpmLog::addBackend("stream",
|
||||
std::make_shared<Opm::StreamLog>(str, Opm::Log::MessageType::Note));
|
||||
|
||||
Opm::LogOutputHelper<double> helper(eclState, schedule, st);
|
||||
helper.cumulative(0, [](const std::string&) { return false; });
|
||||
std::string data = trimStream(str);
|
||||
BOOST_CHECK_EQUAL(data, reference);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Error)
|
||||
{
|
||||
const std::string reference = R"(Finding the bubble point pressure failed for 3 cells [(2,1,1), (1,3,1), (1,4,1)]
|
||||
Finding the dew point pressure failed for 3 cells [(5,1,1), (6,1,1), (7,1,1)]
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto python = std::make_shared<Opm::Python>();
|
||||
auto deck = parser.parseString(input);
|
||||
Opm::EclipseGrid grid(10,10,3);
|
||||
Opm::TableManager table ( deck );
|
||||
Opm::FieldPropsManager fp( deck, Opm::Phases{true, true, true}, grid, table);
|
||||
Opm::Runspec runspec (deck );
|
||||
Opm::Schedule schedule(deck, grid, fp, runspec, python);
|
||||
Opm::EclipseState eclState(deck);
|
||||
|
||||
std::stringstream str;
|
||||
Opm::OpmLog::addBackend("stream",
|
||||
std::make_shared<Opm::StreamLog>(str, Opm::Log::MessageType::Warning));
|
||||
|
||||
Opm::SummaryState st;
|
||||
Opm::LogOutputHelper<double> helper(eclState, schedule, st);
|
||||
|
||||
helper.error({1,20,30}, {4,5,6});
|
||||
std::string data = trimStream(str);
|
||||
BOOST_CHECK_EQUAL(data, reference);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Fip)
|
||||
{
|
||||
const std::string reference = R"(Field total pressure dependent pore volume = 50 RB
|
||||
===================================================
|
||||
: Field Totals :
|
||||
: PAV = 0 PSIA :
|
||||
: PORV = 157 RB :
|
||||
: Pressure is weighted by hydrocarbon pore volume :
|
||||
: Pore volumes are taken at reference conditions :
|
||||
:--------------- Oil STB ---------------:-- Wat STB --:--------------- Gas MSCF ---------------:
|
||||
: Liquid Vapour Total : Total : Free Dissolved Total :
|
||||
:------------------------:------------------------------------------:----------------:------------------------------------------:
|
||||
:Currently in place : 132 138 120: 113 : 1 1 1:
|
||||
:------------------------:------------------------------------------:----------------:------------------------------------------:
|
||||
:Originally in place : 25 31 13: 6 : 0 0 0:
|
||||
:========================:==========================================:================:==========================================:
|
||||
FIPNUM report region 1 pressure dependent pore volume = 50 RB
|
||||
===================================================
|
||||
: FIPNUM report region 1 :
|
||||
: PAV = 0 PSIA :
|
||||
: PORV = 371 RB :
|
||||
:--------------- Oil STB ---------------:-- Wat STB --:--------------- Gas MSCF ---------------:
|
||||
: Liquid Vapour Total : Total : Free Dissolved Total :
|
||||
:------------------------:------------------------------------------:----------------:------------------------------------------:
|
||||
:Currently in place : 346 352 333: 327 : 2 2 2:
|
||||
:------------------------:------------------------------------------:----------------:------------------------------------------:
|
||||
:Originally in place : 239 245 226: 220 : 1 1 1:
|
||||
:========================:==========================================:================:==========================================:
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto python = std::make_shared<Opm::Python>();
|
||||
auto deck = parser.parseString(input);
|
||||
Opm::EclipseGrid grid(10,10,3);
|
||||
Opm::TableManager table ( deck );
|
||||
Opm::FieldPropsManager fp( deck, Opm::Phases{true, true, true}, grid, table);
|
||||
Opm::Runspec runspec (deck );
|
||||
Opm::Schedule schedule(deck, grid, fp, runspec, python);
|
||||
|
||||
Opm::EclipseState eclState(deck);
|
||||
Opm::SummaryState st;
|
||||
|
||||
std::stringstream str;
|
||||
Opm::OpmLog::addBackend("stream",
|
||||
std::make_shared<Opm::StreamLog>(str, Opm::Log::MessageType::Note));
|
||||
|
||||
Opm::LogOutputHelper<double> helper(eclState, schedule, st);
|
||||
Opm::Inplace initial, current;
|
||||
const auto& phases = current.phases();
|
||||
double j = 1.0;
|
||||
for (const auto& phase : phases) {
|
||||
initial.add(phase, j);
|
||||
initial.add("FIPNUM", phase, 0, j + 2*phases.size());
|
||||
initial.add("FIPNUM", phase, 1, j + 2*phases.size());
|
||||
current.add(phase, j + phases.size());
|
||||
current.add("FIPNUM", phase, 0, j + 3*phases.size());
|
||||
current.add("FIPNUM", phase, 1, j + 3*phases.size());
|
||||
++j;
|
||||
}
|
||||
|
||||
initial.add(Opm::Inplace::Phase::PressureHydroCarbonPV, 1.0);
|
||||
initial.add(Opm::Inplace::Phase::HydroCarbonPV, 2.0);
|
||||
initial.add(Opm::Inplace::Phase::PressurePV, 3.0);
|
||||
initial.add(Opm::Inplace::Phase::DynamicPoreVolume, 4.0);
|
||||
|
||||
current.add(Opm::Inplace::Phase::PressureHydroCarbonPV, 2.0);
|
||||
current.add(Opm::Inplace::Phase::HydroCarbonPV, 4.0);
|
||||
current.add(Opm::Inplace::Phase::PressurePV, 6.0);
|
||||
current.add(Opm::Inplace::Phase::DynamicPoreVolume, 8.0);
|
||||
current.add("FIPNUM", Opm::Inplace::Phase::PressureHydroCarbonPV, 1, 2.0);
|
||||
current.add("FIPNUM", Opm::Inplace::Phase::HydroCarbonPV, 1, 4.0);
|
||||
current.add("FIPNUM", Opm::Inplace::Phase::PressurePV, 1, 6.0);
|
||||
current.add("FIPNUM", Opm::Inplace::Phase::DynamicPoreVolume, 1, 8.0);
|
||||
|
||||
helper.fip(current, initial);
|
||||
std::string data = trimStream(str);
|
||||
BOOST_CHECK_EQUAL(data, reference);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(FipResv)
|
||||
{
|
||||
const std::string reference = R"(===================================
|
||||
: RESERVOIR VOLUMES RB :
|
||||
:---------:---------------:---------------:---------------:---------------:---------------:
|
||||
: REGION : TOTAL PORE : PORE VOLUME : PORE VOLUME : PORE VOLUME : PORE VOLUME :
|
||||
: : VOLUME : CONTAINING : CONTAINING : CONTAINING : CONTAINING :
|
||||
: : : OIL : WATER : GAS : HYDRO-CARBON :
|
||||
:---------:---------------:---------------:---------------:---------------:---------------
|
||||
: 1: 176: 170: 164: 176: 346:
|
||||
:---------:---------------:---------------:---------------:---------------:---------------:
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto python = std::make_shared<Opm::Python>();
|
||||
auto deck = parser.parseString(input);
|
||||
Opm::EclipseGrid grid(10,10,3);
|
||||
Opm::TableManager table ( deck );
|
||||
Opm::FieldPropsManager fp( deck, Opm::Phases{true, true, true}, grid, table);
|
||||
Opm::Runspec runspec (deck );
|
||||
Opm::Schedule schedule(deck, grid, fp, runspec, python);
|
||||
|
||||
Opm::EclipseState eclState(deck);
|
||||
Opm::SummaryState st;
|
||||
|
||||
std::stringstream str;
|
||||
Opm::OpmLog::addBackend("stream",
|
||||
std::make_shared<Opm::StreamLog>(str, Opm::Log::MessageType::Note));
|
||||
|
||||
Opm::LogOutputHelper<double> helper(eclState, schedule, st);
|
||||
Opm::Inplace current;
|
||||
const auto& phases = current.phases();
|
||||
double j = 1.0;
|
||||
for (const auto& phase : phases) {
|
||||
current.add(phase, phases.size());
|
||||
current.add("FIPNUM", phase, 1, j + phases.size());
|
||||
++j;
|
||||
}
|
||||
|
||||
current.add(Opm::Inplace::Phase::DynamicPoreVolume, 1.0);
|
||||
current.add(Opm::Inplace::Phase::OilResVolume, 2.0);
|
||||
current.add(Opm::Inplace::Phase::WaterResVolume, 3.0);
|
||||
current.add(Opm::Inplace::Phase::GasResVolume, 4.0);
|
||||
current.add("FIPNUM", Opm::Inplace::Phase::DynamicPoreVolume, 1, 11.0 + phases.size());
|
||||
|
||||
helper.fipResv(current);
|
||||
std::string data = trimStream(str);
|
||||
BOOST_CHECK_EQUAL(data, reference);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Injection)
|
||||
{
|
||||
const std::string reference = R"(=================================================== INJECTION REPORT ========================================
|
||||
: WELL : LOCATION : CTRL : CTRL : CTRL : OIL : WATER : GAS : FLUID : BHP OR : THP OR :
|
||||
: NAME : (I,J,K) : MODE : MODE : MODE : RATE : RATE : RATE : RES.VOL. : CON.PR.: BLK.PR.:
|
||||
: : : OIL : WAT : GAS : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : PSIA : PSIA :
|
||||
==============================================================================================================
|
||||
: FIELD: : : : : 1.0: 2.0: 3.0: 4.0: : :
|
||||
:--------:-----------:------:------:------:------------:----------:-----------:-----------:--------:--------:
|
||||
: G1: : : : : 5.0: 6.0: 7.0: 8.0: : :
|
||||
:--------:-----------:------:------:------:------------:----------:-----------:-----------:--------:--------:
|
||||
: INJ: 1, 1: : : GRAT: 9.0: 10.0: 11.0: 12.0: 13.0: 14.0:
|
||||
:--------:-----------:------:------:------:------------:----------:-----------:-----------:--------:--------:
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto python = std::make_shared<Opm::Python>();
|
||||
auto deck = parser.parseString(input);
|
||||
Opm::EclipseGrid grid(10,10,3);
|
||||
Opm::TableManager table ( deck );
|
||||
Opm::FieldPropsManager fp( deck, Opm::Phases{true, true, true}, grid, table);
|
||||
Opm::Runspec runspec (deck );
|
||||
Opm::Schedule schedule(deck, grid, fp, runspec, python);
|
||||
|
||||
Opm::EclipseState eclState(deck);
|
||||
Opm::SummaryState st;
|
||||
constexpr auto fields = std::array {
|
||||
std::pair{"FOIR", 1.0},
|
||||
std::pair{"FWIR", 2.0},
|
||||
std::pair{"FGIR", 3.0},
|
||||
std::pair{"FVIR", 4.0},
|
||||
std::pair{"GOIR:G1", 5.0},
|
||||
std::pair{"GWIR:G1", 6.0},
|
||||
std::pair{"GGIR:G1", 7.0},
|
||||
std::pair{"GVIR:G1", 8.0},
|
||||
std::pair{"WOIR:INJ", 9.0},
|
||||
std::pair{"WWIR:INJ", 10.0},
|
||||
std::pair{"WGIR:INJ", 11.0},
|
||||
std::pair{"WVIR:INJ", 12.0},
|
||||
std::pair{"WBHP:INJ", 13.0},
|
||||
std::pair{"WTHP:INJ", 14.0},
|
||||
};
|
||||
for (const auto& p : fields) {
|
||||
st.set(p.first, p.second);
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
Opm::OpmLog::addBackend("stream",
|
||||
std::make_shared<Opm::StreamLog>(str, Opm::Log::MessageType::Note));
|
||||
|
||||
Opm::LogOutputHelper<double> helper(eclState, schedule, st);
|
||||
helper.injection(0, [](const std::string&) { return false; });
|
||||
std::string data = trimStream(str);
|
||||
BOOST_CHECK_EQUAL(data, reference);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Production)
|
||||
{
|
||||
const std::string reference = R"(======================================================= PRODUCTION REPORT =======================================================
|
||||
: WELL : LOCATION :CTRL: OIL : WATER : GAS : FLUID : WATER : GAS/OIL : WAT/GAS : BHP OR : THP OR :
|
||||
: NAME : (I,J,K) :MODE: RATE : RATE : RATE : RES.VOL. : CUT : RATIO : RATIO : CON.PR.: BLK.PR.:
|
||||
: : : : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : : MSCF/STB : STB/MSCF : PSIA : PSIA :
|
||||
=================================================================================================================================
|
||||
: FIELD: : : 1.0: 2.0: 3.0: 4.0: 5.000: 6.00: 0.6667: : :
|
||||
:--------:-----------:----:-----------:-----------:-----------:-----------:-----------:----------:------------:--------:--------:
|
||||
: G1: : : 7.0: 8.0: 9.0: 10.0: 11.000: 12.00: 0.8889: : :
|
||||
:--------:-----------:----:-----------:-----------:-----------:-----------:-----------:----------:------------:--------:--------:
|
||||
: PROD: 10, 10:ORAT: 13.0: 14.0: 15.0: 16.0: 17.000: 18.00: 0.9333: 19.0: 20.0:
|
||||
:--------:-----------:----:-----------:-----------:-----------:-----------:-----------:----------:------------:--------:--------:
|
||||
)";
|
||||
|
||||
Opm::Parser parser;
|
||||
auto python = std::make_shared<Opm::Python>();
|
||||
auto deck = parser.parseString(input);
|
||||
Opm::EclipseGrid grid(10,10,3);
|
||||
Opm::TableManager table ( deck );
|
||||
Opm::FieldPropsManager fp( deck, Opm::Phases{true, true, true}, grid, table);
|
||||
Opm::Runspec runspec (deck );
|
||||
Opm::Schedule schedule(deck, grid, fp, runspec, python);
|
||||
|
||||
Opm::EclipseState eclState(deck);
|
||||
Opm::SummaryState st;
|
||||
constexpr auto fields = std::array {
|
||||
std::pair{"FOPR", 1.0},
|
||||
std::pair{"FWPR", 2.0},
|
||||
std::pair{"FGPR", 3.0},
|
||||
std::pair{"FVPR", 4.0},
|
||||
std::pair{"FWCT", 5.0},
|
||||
std::pair{"FGOR", 6.0},
|
||||
std::pair{"GOPR:G1", 7.0},
|
||||
std::pair{"GWPR:G1", 8.0},
|
||||
std::pair{"GGPR:G1", 9.0},
|
||||
std::pair{"GVPR:G1", 10.0},
|
||||
std::pair{"GWCT:G1", 11.0},
|
||||
std::pair{"GGOR:G1", 12.0},
|
||||
std::pair{"WOPR:PROD", 13.0},
|
||||
std::pair{"WWPR:PROD", 14.0},
|
||||
std::pair{"WGPR:PROD", 15.0},
|
||||
std::pair{"WVPR:PROD", 16.0},
|
||||
std::pair{"WWCT:PROD", 17.0},
|
||||
std::pair{"WGOR:PROD", 18.0},
|
||||
std::pair{"WBHP:PROD", 19.0},
|
||||
std::pair{"WTHP:PROD", 20.0},
|
||||
};
|
||||
for (const auto& p : fields) {
|
||||
st.set(p.first, p.second);
|
||||
}
|
||||
|
||||
std::stringstream str;
|
||||
Opm::OpmLog::addBackend("stream",
|
||||
std::make_shared<Opm::StreamLog>(str, Opm::Log::MessageType::Note));
|
||||
|
||||
Opm::LogOutputHelper<double> helper(eclState, schedule, st);
|
||||
helper.production(0, [](const std::string&) { return false; });
|
||||
std::string data = trimStream(str);
|
||||
BOOST_CHECK_EQUAL(data, reference);
|
||||
}
|
Loading…
Reference in New Issue
Block a user