diff --git a/opm/input/eclipse/Schedule/BCProp.hpp b/opm/input/eclipse/Schedule/BCProp.hpp index 0363a3d8c..89d32c79e 100644 --- a/opm/input/eclipse/Schedule/BCProp.hpp +++ b/opm/input/eclipse/Schedule/BCProp.hpp @@ -28,7 +28,6 @@ #include #include - namespace Opm { class Deck; @@ -43,6 +42,12 @@ enum class BCType { NONE }; +enum class BCMECHType { + FREE, + FIXED, + NONE +}; + enum class BCComponent { OIL, GAS, @@ -52,6 +57,33 @@ enum class BCComponent { NONE }; +struct MechBCValue { + std::array disp{}; + std::array stress{}; + std::array fixeddir{}; + + static MechBCValue serializationTestObject() + { + return MechBCValue{{1.0, 2.0, 3.0}, + {3.0, 4.0, 5.0, 6.0, 7.0, 8.0}, + {true, false, true}}; + } + + template + void serializeOp(Serializer& serializer) + { + serializer(disp); + serializer(stress); + serializer(fixeddir); + } + + bool operator==(const MechBCValue& other) const + { + return disp == other.disp && + stress == other.stress && + fixeddir == other.fixeddir; + } +}; class BCProp { public: @@ -59,11 +91,14 @@ public: struct BCFace { int index; BCType bctype; + BCMECHType bcmechtype; BCComponent component; double rate; std::optional pressure; std::optional temperature; + std::optional mechbcvalue; + BCFace() = default; explicit BCFace(const DeckRecord& record); @@ -76,10 +111,12 @@ public: { serializer(index); serializer(bctype); + serializer(bcmechtype); serializer(component); serializer(rate); serializer(pressure); serializer(temperature); + serializer(mechbcvalue); } }; @@ -108,6 +145,4 @@ private: } //namespace Opm - - #endif diff --git a/src/opm/input/eclipse/Schedule/BCProp.cpp b/src/opm/input/eclipse/Schedule/BCProp.cpp index e48c1451a..374a2ad71 100644 --- a/src/opm/input/eclipse/Schedule/BCProp.cpp +++ b/src/opm/input/eclipse/Schedule/BCProp.cpp @@ -45,9 +45,24 @@ BCType bctype(const std::string& s) { if (s == "CLOSED") return BCType::CLOSED; + if (s == "NONE") + return BCType::NONE; + throw std::invalid_argument("Not recognized boundary condition type: " + s); } +BCMECHType bcmechtype(const std::string& s) { + if (s == "FREE") + return BCMECHType::FREE; + + if (s == "FIXED") + return BCMECHType::FIXED; + + if (s == "NONE") + return BCMECHType::NONE; + + throw std::invalid_argument("Not recognized boundary condition type: " + s); +} BCComponent component(const std::string& s) { if (s == "OIL") @@ -78,6 +93,7 @@ using BCKEY = ParserKeywords::BCPROP; BCProp::BCFace::BCFace(const DeckRecord& record) : index(record.getItem().get(0)), bctype(fromstring::bctype(record.getItem().get(0))), + bcmechtype(fromstring::bcmechtype(record.getItem().get(0))), component(fromstring::component(record.getItem().get(0))), rate(record.getItem().getSIDouble(0)) { @@ -87,6 +103,51 @@ BCProp::BCFace::BCFace(const DeckRecord& record) : if (const auto& T = record.getItem(); ! T.defaultApplied(0)) { temperature = T.getSIDouble(0); } + + MechBCValue mechbcvaluetmp; + bool allDefault = true; + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.stress[0] = P.getSIDouble(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.stress[1] = P.getSIDouble(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.stress[2] = P.getSIDouble(0); + allDefault = false; + } + mechbcvaluetmp.stress[3] = 0; + mechbcvaluetmp.stress[4] = 0; + mechbcvaluetmp.stress[5] = 0; + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.disp[0] = P.getSIDouble(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.disp[1] = P.getSIDouble(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.disp[2] = P.getSIDouble(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.fixeddir[0] = P.get(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.fixeddir[1] = P.get(0); + allDefault = false; + } + if (const auto& P = record.getItem(); ! P.defaultApplied(0)) { + mechbcvaluetmp.fixeddir[2] = P.get(0); + allDefault = false; + } + if (!allDefault) { + mechbcvalue = mechbcvaluetmp; + } } BCProp::BCFace BCProp::BCFace::serializationTestObject() @@ -94,11 +155,12 @@ BCProp::BCFace BCProp::BCFace::serializationTestObject() BCFace result; result.index = 100; result.bctype = BCType::RATE; + result.bcmechtype = BCMECHType::FIXED; result.component = BCComponent::GAS; result.rate = 101.0; result.pressure = 102.0; result.temperature = 103.0; - + result.mechbcvalue = MechBCValue::serializationTestObject(); return result; } @@ -106,10 +168,12 @@ BCProp::BCFace BCProp::BCFace::serializationTestObject() bool BCProp::BCFace::operator==(const BCProp::BCFace& other) const { return this->index == other.index && this->bctype == other.bctype && + this->bcmechtype == other.bcmechtype && this->component == other.component && this->rate == other.rate && this->pressure == other.pressure && - this->temperature == other.temperature; + this->temperature == other.temperature && + this->mechbcvalue == other.mechbcvalue; } @@ -123,7 +187,7 @@ void BCProp::updateBCProp(const DeckRecord& record) { return; } } - this->m_faces.emplace_back( bcnew ); + this->m_faces.emplace_back( bcnew ); } @@ -166,4 +230,3 @@ bool BCProp::operator==(const BCProp& other) const { } //namespace Opm - diff --git a/src/opm/input/eclipse/share/keywords/900_OPM/B/BCPROP b/src/opm/input/eclipse/share/keywords/900_OPM/B/BCPROP index 2f0ffd28b..ee32309ab 100644 --- a/src/opm/input/eclipse/share/keywords/900_OPM/B/BCPROP +++ b/src/opm/input/eclipse/share/keywords/900_OPM/B/BCPROP @@ -33,6 +33,62 @@ "name": "TEMPERATURE", "value_type": "DOUBLE", "dimension": "Temperature" + }, + { + "name": "MECHTYPE", + "value_type": "STRING", + "default": "NONE" + }, + { + "name": "FIXEDX", + "value_type": "INT", + "default": 1 + }, + { + "name": "FIXEDY", + "value_type": "INT", + "default": 1 + }, + { + "name": "FIXEDZ", + "value_type": "INT", + "default": 1 + }, + { + "name": "STRESSXX", + "value_type": "DOUBLE", + "default": 0, + "dimension": "Pressure" + }, + { + "name": "STRESSYY", + "value_type": "DOUBLE", + "default": 0, + "dimension": "Pressure" + }, + { + "name": "STRESSZZ", + "value_type": "DOUBLE", + "default": 0, + "dimension": "Pressure" + }, + { + "name": "DISPX", + "value_type": "DOUBLE", + "default": 0, + "dimension": "Length" + }, + { + "name": "DISPY", + "value_type": "DOUBLE", + "default": 0, + "dimension": "Length" + }, + { + "name": "DISPZ", + "value_type": "DOUBLE", + "default": 0, + "dimension": "Length" } ] } diff --git a/tests/parser/BCConfigTests.cpp b/tests/parser/BCConfigTests.cpp index 58f44000a..2377638ad 100644 --- a/tests/parser/BCConfigTests.cpp +++ b/tests/parser/BCConfigTests.cpp @@ -189,3 +189,121 @@ BCPROP BOOST_CHECK_EQUAL(deck.getActiveUnitSystem().to_si(measure::pressure, 279.0), *prop[2].pressure); } + +BOOST_AUTO_TEST_CASE(Mech) +{ + const std::string input = R"( +RUNSPEC + +DIMENS + 10 10 3 / +OIL +GAS +WATER +LAB +START + 1 'JAN' 2015 / +GRID +DX + 300*1000 / +DY + 300*1000 / +DZ + 300*1000 / +TOPS + 100*8325 / +BCCON + 1 1* * 1 5 1 10 Y- / + 2 20 20 4* Y / + 3 10 15 1 10 4 7 Z / +/ +SCHEDULE +BCPROP + 1 NONE * * * * FIXED 1 0 0 1.0 * * 2.0 * * / + 2 NONE * * * * FIXED 0 1 0 * 3.0 * / + 3 NONE * * * * FREE 0 0 1 * * 4.0 * * 5.0 / +/ +)"; + + auto deck = createDeck(input); + Opm::BCConfig config(deck); + const auto& kw = deck.get(); + Opm::BCProp prop; + for (const auto& record : kw.back()) { + prop.updateBCProp(record); + } + + BOOST_CHECK_EQUAL(config.size(), 3U); + + BOOST_CHECK_EQUAL(prop.size(), 3U); + BOOST_CHECK(prop[1].bctype == Opm::BCType::NONE); + BOOST_CHECK(prop[1].component == Opm::BCComponent::NONE); + using measure = Opm::UnitSystem::measure; + BOOST_CHECK_EQUAL(0.0, + prop[1].rate); + BOOST_CHECK(!prop[1].pressure.has_value()); + BOOST_CHECK(!prop[1].temperature.has_value()); + BOOST_CHECK(prop[1].bcmechtype == Opm::BCMECHType::FIXED); + BOOST_CHECK(prop[1].mechbcvalue.has_value()); + BOOST_CHECK_EQUAL(prop[1].mechbcvalue->fixeddir[0], 1); + BOOST_CHECK_EQUAL(prop[1].mechbcvalue->fixeddir[1], 0); + BOOST_CHECK_EQUAL(prop[1].mechbcvalue->fixeddir[2], 0); + BOOST_CHECK_EQUAL(deck.getActiveUnitSystem().to_si(measure::pressure, 1.0), + prop[1].mechbcvalue->stress[0]); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->stress[1], 1e-12); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->stress[2], 1e-12); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->stress[3], 1e-12); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->stress[4], 1e-12); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->stress[5], 1e-12); + BOOST_CHECK_EQUAL(deck.getActiveUnitSystem().to_si(measure::length, 2.0), + prop[1].mechbcvalue->disp[0]); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->disp[1], 1e-12); + BOOST_CHECK_SMALL(prop[1].mechbcvalue->disp[2], 1e-12); + + BOOST_CHECK(prop[2].bctype == Opm::BCType::NONE); + BOOST_CHECK(prop[2].component == Opm::BCComponent::NONE); + using measure = Opm::UnitSystem::measure; + BOOST_CHECK_EQUAL(0.0, + prop[2].rate); + BOOST_CHECK(!prop[2].pressure.has_value()); + BOOST_CHECK(!prop[2].temperature.has_value()); + BOOST_CHECK(prop[2].bcmechtype == Opm::BCMECHType::FIXED); + BOOST_CHECK(prop[2].mechbcvalue.has_value()); + BOOST_CHECK_EQUAL(prop[2].mechbcvalue->fixeddir[0], 0); + BOOST_CHECK_EQUAL(prop[2].mechbcvalue->fixeddir[1], 1); + BOOST_CHECK_EQUAL(prop[2].mechbcvalue->fixeddir[2], 0); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->stress[0], 1e-12); + BOOST_CHECK_EQUAL(deck.getActiveUnitSystem().to_si(measure::pressure, 3.0), + prop[2].mechbcvalue->stress[1]); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->stress[2], 1e-12); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->stress[3], 1e-12); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->stress[4], 1e-12); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->stress[5], 1e-12); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->disp[0], 1e-12); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->disp[1], 1e-12); + BOOST_CHECK_SMALL(prop[2].mechbcvalue->disp[2], 1e-12); + + BOOST_CHECK(prop[3].bctype == Opm::BCType::NONE); + BOOST_CHECK(prop[3].component == Opm::BCComponent::NONE); + using measure = Opm::UnitSystem::measure; + BOOST_CHECK_EQUAL(0.0, + prop[3].rate); + BOOST_CHECK(!prop[3].pressure.has_value()); + BOOST_CHECK(!prop[3].temperature.has_value()); + BOOST_CHECK(prop[3].bcmechtype == Opm::BCMECHType::FREE); + BOOST_CHECK(prop[3].mechbcvalue.has_value()); + BOOST_CHECK_EQUAL(prop[3].mechbcvalue->fixeddir[0], 0); + BOOST_CHECK_EQUAL(prop[3].mechbcvalue->fixeddir[1], 0); + BOOST_CHECK_EQUAL(prop[3].mechbcvalue->fixeddir[2], 1); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->stress[0], 1e-12); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->stress[1], 1e-12); + BOOST_CHECK_EQUAL(deck.getActiveUnitSystem().to_si(measure::pressure, 4.0), + prop[3].mechbcvalue->stress[2]); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->stress[3], 1e-12); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->stress[4], 1e-12); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->stress[5], 1e-12); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->disp[0], 1e-12); + BOOST_CHECK_SMALL(prop[3].mechbcvalue->disp[1], 1e-12); + BOOST_CHECK_EQUAL(deck.getActiveUnitSystem().to_si(measure::length, 5.0), + prop[3].mechbcvalue->disp[2]); +}