diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp index 052dce9b5..272d15c96 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.hpp @@ -21,10 +21,11 @@ #ifndef UDQ_DEFINE_HPP #define UDQ_DEFINE_HPP -#include -#include +#include #include +#include #include +#include #include #include @@ -101,7 +102,7 @@ private: KeywordLocation m_location; std::size_t m_report_step; UDQUpdate m_update_status; - std::string string_data; + mutable std::optional string_data; }; } diff --git a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp index feb26812d..279f9b125 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.hpp @@ -187,6 +187,9 @@ namespace UDQ { bool scalarFunc(UDQTokenType token_type); bool cmpFunc(UDQTokenType token_type); bool setFunc(UDQTokenType token_type); + bool trailingSpace(UDQTokenType token_type); + bool leadingSpace(UDQTokenType token_type); + std::string typeName(UDQVarType var_type); UDAKeyword keyword(UDAControl control); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp index 57f0b0493..750f96490 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQDefine.cpp @@ -198,12 +198,6 @@ UDQDefine::UDQDefine(const UDQParams& udq_params, } this->m_tokens = make_tokens(string_tokens); this->ast = std::make_shared( UDQParser::parse(udq_params, this->m_var_type, this->m_keyword, this->m_location, this->m_tokens, parseContext, errors) ); - this->string_data = ""; - for (std::size_t index = 0; index < deck_data.size(); index++) { - this->string_data += deck_data[index]; - if (index != deck_data.size() - 1) - this->string_data += " "; - } } void UDQDefine::update_status(UDQUpdate update, std::size_t report_step) { @@ -328,7 +322,33 @@ const std::string& UDQDefine::keyword() const { } const std::string& UDQDefine::input_string() const { - return this->string_data; + if (!this->string_data.has_value()) { + std::string s; + /* + A string representation equivalent to the input string is assembled by + joining tokens and sprinkle with ' ' at semi random locations. The + main use of this function is to output the definition string in form + usable for the restart file. + */ + + for (std::size_t token_index = 0; token_index < this->m_tokens.size(); token_index++) { + const auto& token = this->m_tokens[token_index]; + if (UDQ::leadingSpace(token.type())) + s += " "; + + s += token.str(); + if (token_index == (this->m_tokens.size() - 1)) + continue; + + if (UDQ::trailingSpace(token.type())) { + s += " "; + continue; + } + } + this->string_data = s; + + } + return this->string_data.value(); } std::set UDQDefine::func_tokens() const { diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp index bb266a8ff..d1045ff5c 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQEnums.cpp @@ -372,6 +372,26 @@ std::string typeName(UDQVarType var_type) { } } +bool trailingSpace(UDQTokenType token_type) { + if (binaryFunc(token_type)) + return true; + + if (cmpFunc(token_type)) + return true; + + return false; +} + +bool leadingSpace(UDQTokenType token_type) { + if (binaryFunc(token_type)) + return true; + + if (cmpFunc(token_type)) + return true; + + return false; +} + namespace { template Value lookup_control_map_value(const std::map& map, const UDAControl control) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQToken.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQToken.cpp index a940d2b6a..a4cd3812d 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQToken.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQToken.cpp @@ -16,12 +16,21 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ +#include #include #include namespace Opm { +namespace { +std::string format_double(double d) { + return fmt::format("{:g}", d); +} +} + + + UDQToken::UDQToken(const std::string& string_token, UDQTokenType token_type_) : token_type(token_type_) { @@ -56,10 +65,13 @@ std::string UDQToken::str() const { if (this->m_selector.empty()) return std::get(this->m_value); - return std::get(this->m_value) + std::string{" "} + std::accumulate(this->m_selector.begin(), this->m_selector.end(), std::string{}, - [](const std::string& s1, const std::string& s2) { return s1 + " " + s2; }); + std::string quoted_selector; + for (const auto& s : this->m_selector) + quoted_selector += " '" + s + "'"; + + return std::get(this->m_value) + quoted_selector; } else - return std::to_string(std::get(this->m_value)); + return format_double(std::get(this->m_value)); } diff --git a/tests/parser/UDQTests.cpp b/tests/parser/UDQTests.cpp index 8d19ffed7..5a23d151f 100644 --- a/tests/parser/UDQTests.cpp +++ b/tests/parser/UDQTests.cpp @@ -1272,10 +1272,10 @@ BOOST_AUTO_TEST_CASE(UDQPARSE_TEST1) { KeywordLocation location; UDQParams udqp; UDQDefine def1(udqp, "WUBHP",0, location, {"1/(WWCT", "'W1*')"}); - BOOST_CHECK_EQUAL( def1.input_string() , "1/(WWCT 'W1*')"); + BOOST_CHECK_EQUAL( def1.input_string() , "1 / (WWCT 'W1*')"); - UDQDefine def2(udqp, "WUBHP",0, location, {"2*(1", "+" , "WBHP)"}); - BOOST_CHECK_EQUAL( def2.input_string() , "2*(1 + WBHP)"); + UDQDefine def2(udqp, "WUBHP",0, location, {"2 * (1", "+" , "WBHP)"}); + BOOST_CHECK_EQUAL( def2.input_string() , "2 * (1 + WBHP)"); } diff --git a/tests/test_AggregateUDQData.cpp b/tests/test_AggregateUDQData.cpp index d7a061a7f..e90f2e8da 100644 --- a/tests/test_AggregateUDQData.cpp +++ b/tests/test_AggregateUDQData.cpp @@ -646,22 +646,22 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) const auto& zUdl = udqData.getZUDL(); auto start = 0*udqDims[5]; - BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WOPR PR"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "OD1 - 17"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.6"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WOPR 'P"); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "ROD1' - "); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "170) * 0"); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , ".6 "); // udq NO. 1 start = 3*udqDims[5]; - BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(GOPR GR"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "P1 - 449"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , ") * 0.77"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , " "); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(GOPR 'G"); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "RP1' - 4"); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "49) * 0."); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "77 "); // udq NO. 1 start = 4*udqDims[5]; - BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WLPR PR"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "OD2 - 30"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "0) * 0.8"); // udq NO. 1 - BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , "0 "); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(WLPR 'P"); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 1].c_str() , "ROD2' - "); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 2].c_str() , "300) * 0"); // udq NO. 1 + BOOST_CHECK_EQUAL(zUdl[start + 3].c_str() , ".8 "); // udq NO. 1 start = 5*udqDims[5]; BOOST_CHECK_EQUAL(zUdl[start + 0].c_str() , "(FLPR - "); // udq NO. 1 @@ -761,9 +761,6 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) } - BOOST_CHECK_EQUAL(rst_state.udqs[0].expression(), "(WOPR PROD1 - 170) * 0.60"); - - const auto& udq_params = es.runspec().udqParams(); const auto& input_config = sched[1].udq(); Opm::UDQConfig rst_config(udq_params, rst_state); @@ -779,7 +776,6 @@ BOOST_AUTO_TEST_CASE (Declared_UDQ_data) rst_udq_state.load_rst(rst_state); for (const auto& input_def : input_config.definitions()) { const auto& rst_def = rst_config.define( input_def.keyword() ); - auto input_eval = input_def.eval(input_context); auto rst_eval = rst_def.eval(rst_context);