diff --git a/opm/input/eclipse/Schedule/Well/Connection.hpp b/opm/input/eclipse/Schedule/Well/Connection.hpp index 16e6682fc..ac2da506e 100644 --- a/opm/input/eclipse/Schedule/Well/Connection.hpp +++ b/opm/input/eclipse/Schedule/Well/Connection.hpp @@ -180,6 +180,7 @@ namespace RestartIO { serializer(m_defaultSatTabId); serializer(segment_number); serializer(m_subject_to_welpi); + serializer(m_filter_cake); } private: diff --git a/opm/input/eclipse/Schedule/Well/FilterCake.hpp b/opm/input/eclipse/Schedule/Well/FilterCake.hpp index 77c060372..cf3e133e8 100644 --- a/opm/input/eclipse/Schedule/Well/FilterCake.hpp +++ b/opm/input/eclipse/Schedule/Well/FilterCake.hpp @@ -37,6 +37,7 @@ namespace Opm { }; static FilterCakeGeometry filterCakeGeometryFromString(const std::string& str, const KeywordLocation& location); + static std::string filterCakeGeometryToString(const FilterCakeGeometry& geometry); FilterCakeGeometry geometry{FilterCakeGeometry::NONE}; double perm{0.}; @@ -61,11 +62,13 @@ namespace Opm { serializer(sf_multiplier); } + static FilterCake serializationTestObject(); + bool operator==(const FilterCake& other) const; - bool active() const; - void applyCleanMultiplier(const double factor); + + static std::string filterCakeToString(const FilterCake& fc); }; } diff --git a/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp b/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp index 7e2b1c99f..15b504bbf 100644 --- a/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp +++ b/src/opm/input/eclipse/Schedule/KeywordHandlers.cpp @@ -1973,7 +1973,6 @@ Well{0} entered with 'FIELD' parent group: for (const auto& record : handlerContext.keyword) { const std::string& wellNamePattern = record.getItem().getTrimmedString(0); const auto well_names = this->wellNames(wellNamePattern, handlerContext); - // TODO: will check whether we should put all the filter cake related to a separate property for (const auto& well_name: well_names) { auto well = this->snapshots.back().wells(well_name); well.handleWINJCLN(record, handlerContext.keyword.location()); @@ -1996,14 +1995,13 @@ Well{0} entered with 'FIELD' parent group: } } - void Schedule::handleWINJFCNC(Schedule::HandlerContext& handlerContext) { + void Schedule::handleWINJFCNC(HandlerContext& handlerContext) { for (const auto& record : handlerContext.keyword) { const std::string& wellNamePattern = record.getItem().getTrimmedString(0); const auto well_names = this->wellNames(wellNamePattern, handlerContext); - // TODO: will check whether we should put all the filter cake related to a separate property for (const auto& well_name: well_names) { auto well = this->snapshots.back().wells(well_name); - const auto filter_conc = record.getItem().get(0).get(); + const auto filter_conc = record.getItem().get(0); // the unit is ppm_vol well.setFilterConc(filter_conc/1.e6); this->snapshots.back().wells.update(std::move(well)); diff --git a/src/opm/input/eclipse/Schedule/Well/Connection.cpp b/src/opm/input/eclipse/Schedule/Well/Connection.cpp index df77a866c..c214055ee 100644 --- a/src/opm/input/eclipse/Schedule/Well/Connection.cpp +++ b/src/opm/input/eclipse/Schedule/Well/Connection.cpp @@ -137,6 +137,7 @@ Connection::Connection(const RestartIO::RstConnection& rst_connection, const Sch result.m_defaultSatTabId = true; result.segment_number = 16; result.m_subject_to_welpi = true; + result.m_filter_cake = FilterCake::serializationTestObject(); return result; } @@ -302,6 +303,9 @@ const std::optional>& Connection::perf_range() const { if (this->m_injmult.has_value()) { ss << "INJMULT " << InjMult::InjMultToString(this->m_injmult.value()) << std::endl; } + if (this->m_filter_cake.has_value()) { + ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << std::endl; + } return ss.str(); } diff --git a/src/opm/input/eclipse/Schedule/Well/FilterCake.cpp b/src/opm/input/eclipse/Schedule/Well/FilterCake.cpp index 7c72fd23a..07754fa17 100644 --- a/src/opm/input/eclipse/Schedule/Well/FilterCake.cpp +++ b/src/opm/input/eclipse/Schedule/Well/FilterCake.cpp @@ -34,7 +34,20 @@ namespace Opm { else if (str == "RADIAL") return FilterCakeGeometry::RADIAL; else - throw OpmInputError(fmt::format("Unknown mode {} is specified in WINJDAM keyword", str), location); + throw OpmInputError(fmt::format("Unknown geometry type {} is specified in WINJDAM keyword", str), location); + } + + std::string FilterCake::filterCakeGeometryToString(const Opm::FilterCake::FilterCakeGeometry& geometry) { + switch (geometry) { + case FilterCakeGeometry::LINEAR: + return "LINEAR"; + case FilterCakeGeometry::RADIAL: + return "RADIAL"; + case FilterCakeGeometry::NONE: + return "NONE"; + default: + return "unknown FileterCakeGeometry type"; + } } @@ -64,12 +77,39 @@ namespace Opm { && sf_multiplier == other.sf_multiplier; } - bool FilterCake::active() const { - return this->geometry != FilterCakeGeometry::NONE; - } - void FilterCake::applyCleanMultiplier(const double factor) { this->sf_multiplier *= factor; } + + FilterCake FilterCake::serializationTestObject() { + FilterCake filter_cake; + filter_cake.geometry = FilterCakeGeometry::LINEAR; + filter_cake.perm = 1.e-8; + filter_cake.poro = 0.2; + filter_cake.radius = 0.1; + filter_cake.flow_area = 20.; + filter_cake.sf_multiplier = 0.2; + + return filter_cake; + } + + std::string FilterCake::filterCakeToString(const FilterCake& fc) { + std::string str = fmt::format("geometry type {}, perm {}, poro {}", + filterCakeGeometryToString(fc.geometry), fc.perm, fc.poro); + if (fc.radius.has_value()) { + fmt::format_to(std::back_inserter(str), ", radius {}", fc.radius.value()); + } else { + fmt::format_to(std::back_inserter(str), ", radius DEFAULT"); + } + + if (fc.flow_area.has_value()) { + fmt::format_to(std::back_inserter(str), ", flow_area {}", fc.flow_area.value()); + } else { + fmt::format_to(std::back_inserter(str), ", flow_area DEFAULT"); + } + + fmt::format_to(std::back_inserter(str), ", sf_multiplier {}.", fc.sf_multiplier); + return str; + } } // end of Opm namespace diff --git a/src/opm/input/eclipse/Schedule/Well/Well.cpp b/src/opm/input/eclipse/Schedule/Well/Well.cpp index 188dd02bf..508f709d4 100644 --- a/src/opm/input/eclipse/Schedule/Well/Well.cpp +++ b/src/opm/input/eclipse/Schedule/Well/Well.cpp @@ -536,6 +536,7 @@ Well Well::serializationTestObject() result.m_pavg = PAvg(); result.well_temperature = 10.0; result.well_inj_mult = InjMult::serializationTestObject(); + result.m_filter_concentration = 0.1; return result; } diff --git a/src/opm/input/eclipse/share/keywords/900_OPM/W/WINJFCNC b/src/opm/input/eclipse/share/keywords/900_OPM/W/WINJFCNC index c2c1e85fa..067233a41 100644 --- a/src/opm/input/eclipse/share/keywords/900_OPM/W/WINJFCNC +++ b/src/opm/input/eclipse/share/keywords/900_OPM/W/WINJFCNC @@ -10,7 +10,7 @@ }, { "name": "VOL_CONCENTRATION", - "value_type": "UDA", + "value_type": "DOUBLE", "dimension": "1", "default" : 0 } diff --git a/tests/test_Serialization.cpp b/tests/test_Serialization.cpp index 4fc995bb4..d98b6484a 100644 --- a/tests/test_Serialization.cpp +++ b/tests/test_Serialization.cpp @@ -75,6 +75,7 @@ #include #include #include +#include #include #include #include @@ -229,6 +230,7 @@ TEST_FOR_TYPE(Equil) TEST_FOR_TYPE(TLMixpar) TEST_FOR_TYPE(Ppcwmax) TEST_FOR_TYPE(Events) +TEST_FOR_TYPE(FilterCake) TEST_FOR_TYPE(Fault) TEST_FOR_TYPE(FaultCollection) TEST_FOR_TYPE(FaultFace)