// -*- 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 . 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace { template void logUniqueFailedCells(const std::string& messageTag, std::string_view prefix, const std::size_t maxNumCellsFaillog, const std::vector& cells, IJKString&& ijkString) { if (cells.empty()) { return; } std::vector sorted(cells); std::sort(sorted.begin(), sorted.end()); auto u = std::unique(sorted.begin(), sorted.end()); const auto numFailed = static_cast (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()); } std::string injectorCModeToString(const Opm::WellInjectorCMode cmode) { auto cmodeStr = std::string{}; // CMODE_UNDEFINED => "" if (cmode != Opm::WellInjectorCMode::CMODE_UNDEFINED) { cmodeStr = Opm::WellInjectorCMode2String(cmode); } return cmodeStr; } std::string producerCModeToString(const Opm::WellProducerCMode cmode) { auto cmodeStr = std::string{}; // NONE && CMODE_UNDEFINED => "" if ((cmode != Opm::WellProducerCMode::NONE) && (cmode != Opm::WellProducerCMode::CMODE_UNDEFINED)) { cmodeStr = Opm::WellProducerCMode2String(cmode); } return cmodeStr; } } // Namespace anonymous namespace Opm { template LogOutputHelper::LogOutputHelper(const EclipseState& eclState, const Schedule& schedule, const SummaryState& summaryState, const std::string& moduleVersionName) : eclState_(eclState) , schedule_(schedule) , summaryState_(summaryState) , flowVersionName_(moduleVersionName) {} template void LogOutputHelper:: cumulative(const std::size_t reportStepNum) const { this->beginCumulativeReport_(); using Ix = typename WellCumDataType::WCId; const auto& st = summaryState_; for (const auto& gname : this->schedule_.groupNames()) { std::vector values(WellCumDataType::numWCValues); std::vector names(WellCumDataType::numWCNames); names[Ix::WellName] = gname; const auto isField = gname == "FIELD"; values[Ix::OilProd] = isField ? st.get("FOPT", 0.0) : st.get_group_var(gname, "GOPT", 0.0); values[Ix::WaterProd] = isField ? st.get("FWPT", 0.0) : st.get_group_var(gname, "GWPT", 0.0); values[Ix::GasProd] = isField ? st.get("FGPT", 0.0) : st.get_group_var(gname, "GGPT", 0.0); values[Ix::FluidResVolProd] = isField ? st.get("FVPT", 0.0) : st.get_group_var(gname, "GVPT", 0.0); values[Ix::OilInj] = isField ? st.get("FOIT", 0.0) : st.get_group_var(gname, "GOIT", 0.0); values[Ix::WaterInj] = isField ? st.get("FWIT", 0.0) : st.get_group_var(gname, "GWIT", 0.0); values[Ix::GasInj] = isField ? st.get("FGIT", 0.0) : st.get_group_var(gname, "GGIT", 0.0); values[Ix::FluidResVolInj] = isField ? st.get("FVIT", 0.0) : st.get_group_var(gname, "GVIT", 0.0); this->outputCumulativeReportRecord_(values, names); } for (const auto& wname : this->schedule_.wellNames(reportStepNum)) { const auto& well = this->schedule_.getWell(wname, reportStepNum); std::vector values(WellCumDataType::numWCValues); std::vector names(WellCumDataType::numWCNames); names[Ix::WellName] = wname; if (well.isInjector()) { const auto& controls = well.injectionControls(st); const auto ctlMode = controls.cmode; names[Ix::WellType] = "INJ"; if (ctlMode != Well::InjectorCMode::RATE) { names[Ix::WellCTRL] = injectorCModeToString(ctlMode); } else { const auto injType = controls.injector_type; if (injType == InjectorType::OIL) { names[Ix::WellCTRL] = "ORAT"; } else if (injType == InjectorType::WATER) { names[Ix::WellCTRL] = "WRAT"; } else if (injType == InjectorType::GAS) { names[Ix::WellCTRL] = "GRAT"; } } } else if (well.isProducer()) { const auto cmode = well.productionControls(st).cmode; names[Ix::WellType] = "PROD"; names[Ix::WellCTRL] = producerCModeToString(cmode); } values[Ix::WellLocationi] = well.getHeadI() + 1; values[Ix::WellLocationj] = well.getHeadJ() + 1; values[Ix::OilProd] = st.get_well_var(wname, "WOPT", 0.0); values[Ix::WaterProd] = st.get_well_var(wname, "WWPT", 0.0); values[Ix::GasProd] = st.get_well_var(wname, "WGPT", 0.0); values[Ix::FluidResVolProd] = st.get_well_var(wname, "WVPT", 0.0); values[Ix::OilInj] = st.get_well_var(wname, "WOIT", 0.0); values[Ix::WaterInj] = st.get_well_var(wname, "WWIT", 0.0); values[Ix::GasInj] = st.get_well_var(wname, "WGIT", 0.0); values[Ix::FluidResVolInj] = st.get_well_var(wname, "WVIT", 0.0); this->outputCumulativeReportRecord_(values, names); } this->endCumulativeReport_(); } template void LogOutputHelper:: error(const std::vector& failedCellsPbub, const std::vector& 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(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 void LogOutputHelper:: fip(const Inplace& inplace, const Inplace& initialInplace, const std::string& name) const { auto iget = [&name](const Inplace& ip, Inplace::Phase phase, std::size_t idx) { if (name.empty()) { return ip.get(phase); } return ip.get(name, phase, idx); }; for (std::size_t reg = 1; reg <= (name.empty() ? 1 : inplace.max_region(name)); ++reg) { std::unordered_map initial_values; std::unordered_map current_values; for (const auto& phase : Inplace::phases()) { initial_values[phase] = iget(initialInplace, phase, reg); current_values[phase] = iget(inplace, phase, reg); } current_values[Inplace::Phase::DynamicPoreVolume] = iget(inplace, Inplace::Phase::DynamicPoreVolume, reg); this->fipUnitConvert_(initial_values); this->fipUnitConvert_(current_values); Scalar regHydroCarbonPoreVolumeAveragedPressure = detail::pressureAverage(iget(inplace, Inplace::Phase::PressureHydroCarbonPV, reg), iget(inplace, Inplace::Phase::HydroCarbonPV, reg), iget(inplace, Inplace::Phase::PressurePV, reg), iget(inplace, Inplace::Phase::DynamicPoreVolume, reg), true); this->pressureUnitConvert_(regHydroCarbonPoreVolumeAveragedPressure); this->outputRegionFluidInPlace_(std::move(initial_values), std::move(current_values), regHydroCarbonPoreVolumeAveragedPressure, name, name.empty() ? 0 : reg); } } template void LogOutputHelper:: fipResv(const Inplace& inplace, const std::string& name) const { { std::unordered_map current_values; for (const auto& phase : Inplace::phases()) current_values[phase] = inplace.get(phase); Scalar field_dyn_pv = 0.0; for (auto nreg = inplace.max_region(name), reg = 0*nreg + 1; reg <= nreg; ++reg) field_dyn_pv = field_dyn_pv + inplace.get(name, Inplace::Phase::DynamicPoreVolume, reg); current_values[Inplace::Phase::DynamicPoreVolume] = field_dyn_pv; this->fipUnitConvert_(current_values); this->outputResvFluidInPlace_(current_values, 0); } for (auto nreg = inplace.max_region(), reg = 0*nreg + 1; reg <= nreg; ++reg) { std::unordered_map current_values; for (const auto& phase : Inplace::phases()) { if (reg <= inplace.max_region(name)) current_values[phase] = inplace.get(name, phase, reg); else current_values[phase] = 0.0; } if (reg <= inplace.max_region(name)) current_values[Inplace::Phase::DynamicPoreVolume] = inplace.get(name, Inplace::Phase::DynamicPoreVolume, reg); else current_values[Inplace::Phase::DynamicPoreVolume] = 0.0; this->fipUnitConvert_(current_values); this->outputResvFluidInPlace_(current_values, reg); } std::ostringstream ss; ss << " ==========================================================================================="; OpmLog::note(ss.str()); } template void LogOutputHelper:: timeStamp(const std::string& lbl, double elapsed, int rstep, boost::posix_time::ptime currentDate) const { std::ostringstream ss; boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%d %b %Y"); ss.imbue(std::locale(std::locale::classic(), facet)); ss << "\n **************************************************************************\n" << " " << std::left << std::setw(9) << lbl << "AT" << std::right << std::setw(10) << (double)unit::convert::to(elapsed, unit::day) << " DAYS" << " *" << std::setw(30) << eclState_.getTitle() << " *\n" << " REPORT " << std::setw(4) << rstep << " " << currentDate << " * Flow version " << std::setw(11) << flowVersionName_ << " *\n" << " **************************************************************************\n"; OpmLog::note(ss.str()); } template void LogOutputHelper:: injection(const std::size_t reportStepNum) const { this->beginInjectionReport_(); using Ix = typename WellInjDataType::WIId; const auto& st = this->summaryState_; for (const auto& gname : this->schedule_.groupNames()) { std::vector values(WellInjDataType::numWIValues); std::vector names(WellInjDataType::numWINames); names[Ix::WellName] = gname; const auto isField = gname == "FIELD"; values[Ix::OilRate] = isField ? st.get("FOIR", 0.0) : st.get_group_var(gname, "GOIR", 0.0); values[Ix::WaterRate] = isField ? st.get("FWIR", 0.0) : st.get_group_var(gname, "GWIR", 0.0); values[Ix::GasRate] = isField ? st.get("FGIR", 0.0) : st.get_group_var(gname, "GGIR", 0.0); values[Ix::FluidResVol] = isField ? st.get("FVIR", 0.0) : st.get_group_var(gname, "GVIR", 0.0); this->outputInjectionReportRecord_(values, names); } for (const auto& wname : this->schedule_.wellNames(reportStepNum)) { const auto& well = this->schedule_.getWell(wname, reportStepNum); // Ignore production wells for the injection report. if (well.isProducer()) { continue; } std::vector values(WellInjDataType::numWIValues); std::vector names(WellInjDataType::numWINames); names[Ix::WellName] = wname; const auto& controls = well.injectionControls(st); const auto ctlMode = controls.cmode; const auto injType = controls.injector_type; const auto isRate = ctlMode == Well::InjectorCMode::RATE; if (injType == InjectorType::OIL) { names[Ix::CTRLModeOil] = isRate ? "ORAT" : injectorCModeToString(ctlMode); } else if (injType == InjectorType::WATER) { names[Ix::CTRLModeWat] = isRate ? "WRAT" : injectorCModeToString(ctlMode); } else if (injType == InjectorType::GAS) { names[Ix::CTRLModeGas] = isRate ? "GRAT" : injectorCModeToString(ctlMode); } values[Ix::WellLocationi] = well.getHeadI() + 1; values[Ix::WellLocationj] = well.getHeadJ() + 1; values[Ix::OilRate] = st.get_well_var(wname, "WOIR", 0.0); values[Ix::WaterRate] = st.get_well_var(wname, "WWIR", 0.0); values[Ix::GasRate] = st.get_well_var(wname, "WGIR", 0.0); values[Ix::FluidResVol] = st.get_well_var(wname, "WVIR", 0.0); values[Ix::BHP] = st.get_well_var(wname, "WBHP", 0.0); values[Ix::THP] = st.get_well_var(wname, "WTHP", 0.0); // values[Ix::SteadyStateII] = 0; this->outputInjectionReportRecord_(values, names); } this->endInjectionReport_(); } template void LogOutputHelper:: production(const std::size_t reportStepNum) const { this->beginProductionReport_(); using Ix = typename WellProdDataType::WPId; const auto& st = this->summaryState_; for (const auto& gname : this->schedule_.groupNames()) { std::vector values(WellProdDataType::numWPValues); std::vector names(WellProdDataType::numWPNames); names[0] = gname; const auto isField = gname == "FIELD"; values[Ix::OilRate] = isField ? st.get("FOPR", 0.0) : st.get_group_var(gname, "GOPR", 0.0); values[Ix::WaterRate] = isField ? st.get("FWPR", 0.0) : st.get_group_var(gname, "GWPR", 0.0); values[Ix::GasRate] = isField ? st.get("FGPR", 0.0) : st.get_group_var(gname, "GGPR", 0.0); values[Ix::FluidResVol] = isField ? st.get("FVPR", 0.0) : st.get_group_var(gname, "GVPR", 0.0); values[Ix::WaterCut] = isField ? st.get("FWCT", 0.0) : st.get_group_var(gname, "GWCT", 0.0); values[Ix::GasOilRatio] = isField ? st.get("FGOR", 0.0) : st.get_group_var(gname, "GGOR", 0.0); if (values[Ix::WaterRate] == 0.0) { values[Ix::WatGasRatio] = 0; } else { values[Ix::WatGasRatio] = values[Ix::WaterRate] / values[Ix::GasRate]; } if (std::isnan(values[Ix::WatGasRatio])) { values[Ix::WatGasRatio] = 0.0; } this->outputProductionReportRecord_(values, names); } for (const auto& wname : this->schedule_.wellNames(reportStepNum)) { const auto& well = this->schedule_.getWell(wname, reportStepNum); // Ignore injection wells for the production report. if (well.isInjector()) { continue; } std::vector values(WellProdDataType::numWPValues); std::vector names(WellProdDataType::numWPNames); names[Ix::WellName] = wname; names[Ix::CTRLMode] = producerCModeToString(well.productionControls(st).cmode); values[Ix::WellLocationi] = well.getHeadI() + 1; values[Ix::WellLocationj] = well.getHeadJ() + 1; values[Ix::OilRate] = st.get_well_var(wname, "WOPR", 0.0); values[Ix::WaterRate] = st.get_well_var(wname, "WWPR", 0.0); values[Ix::GasRate] = st.get_well_var(wname, "WGPR", 0.0); values[Ix::FluidResVol] = st.get_well_var(wname, "WVPR", 0.0); values[Ix::WaterCut] = st.get_well_var(wname, "WWCT", 0.0); values[Ix::GasOilRatio] = st.get_well_var(wname, "WGOR", 0.0); values[Ix::BHP] = st.get_well_var(wname, "WBHP", 0.0); values[Ix::THP] = st.get_well_var(wname, "WTHP", 0.0); // values[Ix::SteadyStatePI] = 0; if (values[Ix::WaterRate] == 0.0) { values[Ix::WatGasRatio] = 0.0; } else { values[Ix::WatGasRatio] = values[Ix::WaterRate] / values[Ix::GasRate]; } if (std::isnan(values[Ix::WatGasRatio])) { values[Ix::WatGasRatio] = 0.0; } this->outputProductionReportRecord_(values, names); } this->endProductionReport_(); } template void LogOutputHelper::beginCumulativeReport_() const { const auto unitType = this->eclState_.getUnits().getType(); std::ostringstream ss; ss << "\n=================================================== CUMULATIVE PRODUCTION/INJECTION REPORT =========================================\n" << ": WELL : LOCATION : WELL :CTRL: OIL : WATER : GAS : Prod : OIL : WATER : GAS : INJ :\n" << ": NAME : (I,J,K) : TYPE :MODE: PROD : PROD : PROD : RES.VOL. : INJ : INJ : INJ : RES.VOL. :\n"; if (unitType == UnitSystem::UnitType::UNIT_TYPE_METRIC) { ss << ": : : : : MSCM : MSCM : MMSCM : MRCM : MSCM : MSCM : MMSCM : MRCM :\n"; } else if (unitType == UnitSystem::UnitType::UNIT_TYPE_FIELD) { ss << ": : : : : MSTB : MSTB : MMSCF : MRB : MSTB : MSTB : MMSCF : MRB :\n"; } else if (unitType == UnitSystem::UnitType::UNIT_TYPE_LAB) { ss << ": : : : : MSCC : MSCC : MMSCC : MRCC : MSCC : MSCC : MMSCC : MRCC :\n"; } ss << "===================================================================================================================================="; OpmLog::note(ss.str()); } template void LogOutputHelper::endCumulativeReport_() const { const auto ss = std::string { ":--------:-----------:--------:----:-----------:-----------:-----------:-----------:-----------:-----------:-----------:-----------:" }; OpmLog::note(ss); } template void LogOutputHelper:: outputCumulativeReportRecord_(const std::vector& wellCum, const std::vector& wellCumNames) const { std::ostringstream ss; ss << std::right << std::fixed << std::setprecision(0) << ':' << std::setw(8) << wellCumNames[WellCumDataType::WellName] << ':'; if (wellCum[WellCumDataType::WellLocationi] < 1) { ss << std::setw(11) << "" << ':'; } else { ss << std::setw( 5) << wellCum[WellCumDataType::WellLocationi] << ',' << std::setw( 5) << wellCum[WellCumDataType::WellLocationj] << ':'; } auto scaledValue = [&wellCum](const typename WellCumDataType::WCId quantity) { // Unit M* return wellCum[quantity] / 1000.0; }; auto scaledGasValue = [&wellCum](const typename WellCumDataType::WCId quantity) { // Unit MM* return wellCum[quantity] / (1000.0 * 1000.0); }; ss << std::setw( 8) << wellCumNames[WellCumDataType::WCId::WellType] << ':' << std::setw( 4) << wellCumNames[WellCumDataType::WCId::WellCTRL] << ':' << std::setprecision(1) << std::setw(11) << scaledValue(WellCumDataType::WCId::OilProd) << ':' << std::setw(11) << scaledValue(WellCumDataType::WCId::WaterProd) << ':' << std::setw(11) << scaledGasValue(WellCumDataType::WCId::GasProd) << ':' << std::setw(11) << scaledValue(WellCumDataType::WCId::FluidResVolProd) << ':' << std::setw(11) << scaledValue(WellCumDataType::WCId::OilInj) << ':' << std::setw(11) << scaledValue(WellCumDataType::WCId::WaterInj) << ':' << std::setw(11) << scaledGasValue(WellCumDataType::WCId::GasInj) << ':' << std::setw(11) << scaledValue(WellCumDataType::WCId::FluidResVolInj) << ':'; OpmLog::note(ss.str()); } template void LogOutputHelper::beginInjectionReport_() const { const auto unitType = this->eclState_.getUnits().getType(); std::ostringstream ss; ss << "\n=================================================== INJECTION REPORT ========================================\n"//===================== \n" << ": WELL : LOCATION : CTRL : CTRL : CTRL : OIL : WATER : GAS : FLUID : BHP OR : THP OR :\n"// STEADY-ST II :\n" << ": NAME : (I,J,K) : MODE : MODE : MODE : RATE : RATE : RATE : RES.VOL. : CON.PR.: BLK.PR.:\n";// OR POTENTIAL :\n"; if (unitType == UnitSystem::UnitType::UNIT_TYPE_METRIC) { ss << ": : : OIL : WAT : GAS : SCM/DAY : SCM/DAY : SCM/DAY : RCM/DAY : BARSA : BARSA :\n";// :\n"; } else if (unitType == UnitSystem::UnitType::UNIT_TYPE_FIELD) { ss << ": : : OIL : WAT : GAS : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : PSIA : PSIA :\n";// :\n"; } else if (unitType == UnitSystem::UnitType::UNIT_TYPE_LAB) { ss << ": : : OIL : WAT : GAS : SCC/HR : SCC/HR : SCC/HR : RCC/HR : ATMA : ATMA :\n";// :\n"; } ss << "=============================================================================================================";//====================="; OpmLog::note(ss.str()); } template void LogOutputHelper::endInjectionReport_() const { const auto ss = std::string { ":--------:-----------:------:------:------:-----------:-----------:-----------:-----------:--------:--------:" }; OpmLog::note(ss); } template void LogOutputHelper:: outputInjectionReportRecord_(const std::vector& wellInj, const std::vector& wellInjNames) const { const auto isWellRecord = wellInj[WellProdDataType::WellLocationi] >= 1; std::ostringstream ss; ss << fmt::format(":{:<8}:", wellInjNames[WellInjDataType::WellName]); ss << std::right << std::fixed << std::setprecision(0) << std::setw(8); if (! isWellRecord) { ss << std::setw(11) << "" << ':'; } else { ss << std::setw( 5) << wellInj[WellInjDataType::WellLocationi] << ',' << std::setw( 5) << wellInj[WellInjDataType::WellLocationj] << ':'; } ss << std::setw( 6) << wellInjNames[WellInjDataType::CTRLModeOil] << ':' << std::setw( 6) << wellInjNames[WellInjDataType::CTRLModeWat] << ':' << std::setw( 6) << wellInjNames[WellInjDataType::CTRLModeGas] << ':' << std::setprecision(1) << std::setw(11) << wellInj[WellInjDataType::OilRate] << ':' << std::setw(11) << wellInj[WellInjDataType::WaterRate] << ':' << std::setw(11) << wellInj[WellInjDataType::GasRate] << ':' << std::setw(11) << wellInj[WellInjDataType::FluidResVol] << ':'; if (! isWellRecord) { ss << std::setw(8) << "" << ':' << std::setw(8) << "" << ':'; //wellInj[WellInjDataType::SteadyStateII] << std::setw(10) << "\n" } else { ss << std::setw(8) << wellInj[WellInjDataType::BHP] << ':' << std::setw(8) << wellInj[WellInjDataType::THP] << ':'; //wellInj[WellInjDataType::SteadyStateII] << std::setw(10) << "\n" } OpmLog::note(ss.str()); } template void LogOutputHelper::beginProductionReport_() const { const auto unitType = this->eclState_.getUnits().getType(); std::ostringstream ss; ss << "\n======================================================= PRODUCTION REPORT =======================================================\n"//=================== \n" << ": WELL : LOCATION :CTRL: OIL : WATER : GAS : FLUID : WATER : GAS/OIL : WAT/GAS : BHP OR : THP OR :\n"// STEADY-ST PI :\n" << ": NAME : (I,J,K) :MODE: RATE : RATE : RATE : RES.VOL. : CUT : RATIO : RATIO : CON.PR.: BLK.PR.:\n";// OR POTN OF PREF. PH:\n"; if (unitType == UnitSystem::UnitType::UNIT_TYPE_METRIC) { ss << ": : : : SCM/DAY : SCM/DAY : SCM/DAY : RCM/DAY : SCM/SCM : SCM/SCM : SCM/SCM : BARSA : BARSA :\n";// :\n"; } else if (unitType == UnitSystem::UnitType::UNIT_TYPE_FIELD) { ss << ": : : : STB/DAY : STB/DAY : MSCF/DAY : RB/DAY : : MSCF/STB : STB/MSCF : PSIA : PSIA :\n";// :\n"; } else if (unitType == UnitSystem::UnitType::UNIT_TYPE_LAB) { ss << ": : : : SCC/HR : SCC/HR : SCC/HR : RCC : SCC/SCC : SCC/SCC : SCC/SCC : ATMA : ATMA :\n";// :\n"; } ss << "=================================================================================================================================";//==================="; OpmLog::note(ss.str()); } template void LogOutputHelper::endProductionReport_() const { std::ostringstream ss; ss << ':' << std::setfill ('-') << std::setw (9) << ':' << std::setfill ('-') << std::setw (12) << ':' << std::setfill ('-') << std::setw ( 5) << ':' << std::setfill ('-') << std::setw (12) << ':' << std::setfill ('-') << std::setw (12) << ':' << std::setfill ('-') << std::setw (12) << ':' << std::setfill ('-') << std::setw (12) << ':' << std::setfill ('-') << std::setw (12) << ':' << std::setfill ('-') << std::setw (11) << ':' << std::setfill ('-') << std::setw (13) << ':' << std::setfill ('-') << std::setw ( 9) << ':' << std::setfill ('-') << std::setw ( 9) << ':'; OpmLog::note(ss.str()); } template void LogOutputHelper:: outputProductionReportRecord_(const std::vector& wellProd, const std::vector& wellProdNames) const { const auto isWellRecord = wellProd[WellProdDataType::WellLocationi] >= 1; std::ostringstream ss; ss << std::right << std::fixed << ':' << std::setw(8) << wellProdNames[WellProdDataType::WellName] << ':'; if (! isWellRecord) { ss << std::setprecision(0) << std::setw(11) << "" << ':'; } else { ss << std::setprecision(0) << std::setw(5) << wellProd[WellProdDataType::WellLocationi] << ',' << std::setw(5) << wellProd[WellProdDataType::WellLocationj] << ':'; } ss << std::setw( 4) << wellProdNames[WellProdDataType::CTRLMode] << ':' << std::setprecision(1) << std::setw(11) << wellProd[WellProdDataType::OilRate] << ':' << std::setw(11) << wellProd[WellProdDataType::WaterRate] << ':' << std::setw(11) << wellProd[WellProdDataType::GasRate] << ':' << std::setw(11) << wellProd[WellProdDataType::FluidResVol] << ':' << std::setprecision(3) << std::setw(11) << wellProd[WellProdDataType::WaterCut] << ':' << std::setprecision(2) << std::setw(10) << wellProd[WellProdDataType::GasOilRatio] << ':' << std::setprecision(4) << std::setw(12) << wellProd[WellProdDataType::WatGasRatio] << ':' << std::setprecision(1); if (! isWellRecord) { ss << std::setw(8) << "" << ':' << std::setw(8) << "" << ':'; } else { ss << std::setw(8) << wellProd[WellProdDataType::BHP] << ':' << std::setw(8) << wellProd[WellProdDataType::THP] << ':'; } OpmLog::note(ss.str()); } template void LogOutputHelper:: outputRegionFluidInPlace_(std::unordered_map oip, std::unordered_map cip, const Scalar pav, const std::string& name, const int reg) const { // don't output FIPNUM report if the region has no porv. if (! (cip[Inplace::Phase::PoreVolume] > Scalar{0})) { return; } const UnitSystem& units = eclState_.getUnits(); std::ostringstream ss; ss << '\n'; if (reg == 0) { ss << " ==================================================\n" << " : FIELD TOTALS :\n"; } else { ss << " ==================================================\n" << " : " << name << " REPORT REGION " << std::setw(8 - name.size()) << reg << " :\n"; } if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) { ss << " : PAV = " << std::setw(14) << pav << " BARSA :\n" << std::fixed << std::setprecision(0) << " : PORV= " << std::setw(14) << cip[Inplace::Phase::PoreVolume] << " RM3 :\n"; if (!reg) { ss << " : Pressure is weighted by hydrocarbon pore volume:\n" << " : Porv volumes are taken at reference conditions :\n"; } ss << " :--------------- OIL SM3 ----------------:-- WAT SM3 --:--------------- GAS SM3 ---------------:\n"; } else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) { ss << std::fixed << std::setprecision(0) << " : PAV =" << std::setw(14) << pav << " PSIA :\n" << std::fixed << std::setprecision(0) << " : PORV=" << std::setw(14) << cip[Inplace::Phase::PoreVolume] << " RB :\n"; if (!reg) { ss << " : Pressure is weighted by hydrocarbon pore volume:\n" << " : Pore volumes are taken at reference conditions :\n"; } ss << " :--------------- OIL STB ----------------:-- WAT STB --:--------------- GAS MSCF ----------------:\n"; } ss << " : LIQUID VAPOUR TOTAL : TOTAL : FREE DISSOLVED TOTAL :" << "\n" << " :-------------------------:-------------------------------------------:----------------:-------------------------------------------:" << "\n" << " :CURRENTLY IN PLACE :" << std::setw(14) << cip[Inplace::Phase::OilInLiquidPhase] << std::setw(14) << cip[Inplace::Phase::OilInGasPhase] << std::setw(15) << cip[Inplace::Phase::OIL] << ":" << std::setw(14) << cip[Inplace::Phase::WATER] << " :" << std::setw(14) << (cip[Inplace::Phase::GasInGasPhase]) << std::setw(14) << cip[Inplace::Phase::GasInLiquidPhase] << std::setw(15) << cip[Inplace::Phase::GAS] << ":\n" << " :-------------------------:-------------------------------------------:----------------:-------------------------------------------:\n" << " :ORIGINALLY IN PLACE :" << std::setw(14) << oip[Inplace::Phase::OilInLiquidPhase] << std::setw(14) << oip[Inplace::Phase::OilInGasPhase] << std::setw(15) << oip[Inplace::Phase::OIL] << ":" << std::setw(14) << oip[Inplace::Phase::WATER] << " :" << std::setw(14) << oip[Inplace::Phase::GasInGasPhase] << std::setw(14) << oip[Inplace::Phase::GasInLiquidPhase] << std::setw(15) << oip[Inplace::Phase::GAS] << ":\n"; if (reg == 0){ ss << " ====================================================================================================================================\n\n"; } else { ss << " :-------------------------:-------------------------------------------:----------------:-------------------------------------------:\n"; ss << " ====================================================================================================================================\n\n"; } OpmLog::note(ss.str()); } template void LogOutputHelper:: outputResvFluidInPlace_(std::unordered_map cipr, const int reg) const { const UnitSystem& units = eclState_.getUnits(); std::ostringstream ss; if (reg == 0) { ss << "\n ===================================\n"; if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_METRIC) { ss << " : RESERVOIR VOLUMES RM3 :\n"; } else if (units.getType() == UnitSystem::UnitType::UNIT_TYPE_FIELD) { ss << " : RESERVOIR VOLUMES RB :\n"; } ss << " :---------:---------------:---------------:---------------:---------------:---------------:\n" << " : REGION : TOTAL PORE : PORE VOLUME : PORE VOLUME : PORE VOLUME : PORE VOLUME :\n" << " : : VOLUME : CONTAINING : CONTAINING : CONTAINING : CONTAINING :\n" << " : : : OIL : WATER : GAS : HYDRO-CARBON :\n" << " :---------:---------------:---------------:---------------:---------------:---------------\n"; ss << std::right << std::fixed << std::setprecision(0) << " :" << std::setw (8) << "FIELD" << " :"; } else { ss << std::right << std::fixed << std::setprecision(0) << " :" << std::setw (8) << reg << " :"; } ss << std::setw(15) << cipr[Inplace::Phase::DynamicPoreVolume] << ":" << std::setw(15) << cipr[Inplace::Phase::OilResVolume] << ":" << std::setw(15) << cipr[Inplace::Phase::WaterResVolume] << ":" << std::setw(15) << cipr[Inplace::Phase::GasResVolume] << ":" << std::setw(15) << cipr[Inplace::Phase::OilResVolume] + cipr[Inplace::Phase::GasResVolume] << ":"; OpmLog::note(ss.str()); } template void LogOutputHelper:: fipUnitConvert_(std::unordered_map& fip) const { const UnitSystem& units = eclState_.getUnits(); using M = UnitSystem::measure; const auto unit_map = std::unordered_map { {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::CO2InGasPhaseInMobKrg, M::moles}, {Inplace::Phase::CO2InGasPhaseMobKrg, M::moles}, {Inplace::Phase::WaterInWaterPhase, M::liquid_surface_volume}, {Inplace::Phase::WaterInGasPhase, M::liquid_surface_volume}, {Inplace::Phase::CO2Mass, M::mass}, {Inplace::Phase::CO2MassInWaterPhase, M::mass}, {Inplace::Phase::CO2MassInGasPhase, M::mass}, {Inplace::Phase::CO2MassInGasPhaseInMob, M::mass}, {Inplace::Phase::CO2MassInGasPhaseMob, M::mass}, {Inplace::Phase::CO2MassInGasPhaseInMobKrg, M::mass}, {Inplace::Phase::CO2MassInGasPhaseMobKrg, M::mass}, {Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped, M::mass}, {Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped, M::mass}, {Inplace::Phase::CO2MassInGasPhaseMaximumTrapped, M::mass}, {Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped, M::mass}, }; for (auto& [phase, value] : fip) { auto unitPos = unit_map.find(phase); if (unitPos != unit_map.end()) { value = units.from_si(unitPos->second, value); } } } template void LogOutputHelper:: pressureUnitConvert_(Scalar& pav) const { pav = eclState_.getUnits() .from_si(UnitSystem::measure::pressure, pav); } template class LogOutputHelper; #if FLOW_INSTANTIATE_FLOAT template class LogOutputHelper; #endif } // namespace Opm