From fa7a56f1e22d19340b3de890fb2f6d528d1f4fdd Mon Sep 17 00:00:00 2001 From: Kristian Bendiksen Date: Fri, 24 Nov 2023 11:42:31 +0100 Subject: [PATCH] #10861 Add import/export for grid calculations --- .gitmodules | 3 + ...xportGridCalculationExpressionsFeature.cpp | 49 +++++++---- ...mportGridCalculationExpressionsFeature.cpp | 49 +++++++---- .../FileInterface/CMakeLists_files.cmake | 5 ++ .../FileInterface/RifGridCalculation.h | 40 +++++++++ .../RifGridCalculationExporter.cpp | 72 +++++++++++++++++ .../RifGridCalculationExporter.h | 34 ++++++++ .../RifGridCalculationImporter.cpp | 81 +++++++++++++++++++ .../RifGridCalculationImporter.h | 34 ++++++++ .../ProjectDataModel/RimGridCalculation.h | 5 +- .../RimUserDefinedCalculation.cpp | 8 ++ .../RimUserDefinedCalculation.h | 11 +-- .../RimUserDefinedCalculationCollection.cpp | 13 +-- .../RimUserDefinedCalculationCollection.h | 2 +- .../UnitTests/CMakeLists_files.cmake | 1 + .../UnitTests/RifGridCalculationIO-Test.cpp | 67 +++++++++++++++ CMakeLists.txt | 7 ++ ThirdParty/tomlplusplus | 1 + 18 files changed, 440 insertions(+), 42 deletions(-) create mode 100644 ApplicationLibCode/FileInterface/RifGridCalculation.h create mode 100644 ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp create mode 100644 ApplicationLibCode/FileInterface/RifGridCalculationExporter.h create mode 100644 ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp create mode 100644 ApplicationLibCode/FileInterface/RifGridCalculationImporter.h create mode 100644 ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp create mode 160000 ThirdParty/tomlplusplus diff --git a/.gitmodules b/.gitmodules index 7b1c4f9349..da885ca10b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -22,3 +22,6 @@ [submodule "ThirdParty/regression-analysis"] path = ThirdParty/regression-analysis url = https://github.com/CeetronSolutions/regression-analysis.git +[submodule "ThirdParty/tomlplusplus"] + path = ThirdParty/tomlplusplus + url = https://github.com/marzer/tomlplusplus.git diff --git a/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp b/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp index 5825744e9a..27e789750e 100644 --- a/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp +++ b/ApplicationLibCode/Commands/RicExportGridCalculationExpressionsFeature.cpp @@ -22,9 +22,13 @@ #include "RiaLogging.h" #include "RiaPreferences.h" +#include "RifGridCalculation.h" +#include "RifGridCalculationExporter.h" #include "RimGridCalculationCollection.h" +#include "RimGridCalculationVariable.h" #include "RimProject.h" +#include "Riu3DMainWindowTools.h" #include "RiuFileDialogTools.h" #include @@ -51,9 +55,6 @@ void RicExportGridCalculationExpressionsFeature::onActionTriggered( bool isCheck if ( calcColl->calculations().empty() ) return; - auto objectAsText = calcColl->writeObjectToXmlString(); - if ( objectAsText.isEmpty() ) return; - QString fallbackPath = RiaPreferences::current()->gridCalculationExpressionFolder(); auto app = RiaGuiApplication::instance(); QString startPath = @@ -62,23 +63,41 @@ void RicExportGridCalculationExpressionsFeature::onActionTriggered( bool isCheck QString fileName = RiuFileDialogTools::getSaveFileName( nullptr, "Select File for Grid Calculation Expression Export", startPath, - "Xml File(*.xml);;All files(*.*)" ); + "Toml File(*.toml);;All files(*.*)" ); if ( fileName.isEmpty() ) return; - QFile exportFile( fileName ); - if ( !exportFile.open( QIODevice::WriteOnly | QIODevice::Text ) ) - { - RiaLogging::errorInMessageBox( nullptr, - "Export Grid Calculation Expressions", - QString( "Could not save to the file: %1" ).arg( fileName ) ); - return; - } - QString absPath = QFileInfo( fileName ).absolutePath(); app->setLastUsedDialogDirectory( RicExportGridCalculationExpressionsFeature::gridCalculationExpressionId(), absPath ); - QTextStream stream( &exportFile ); - stream << objectAsText; + + std::vector calculations; + for ( auto calculation : calcColl->calculations() ) + { + RifGridCalculation calc; + calc.description = calculation->description().toStdString(); + calc.expression = calculation->expression().toStdString(); + for ( auto variable : calculation->allVariables() ) + { + if ( auto gridVariable = dynamic_cast( variable ) ) + { + RifGridCalculationVariable var; + var.resultVariable = gridVariable->resultVariable().toStdString(); + var.resultType = caf::AppEnum::text( gridVariable->resultCategoryType() ).toStdString(); + var.name = gridVariable->name().toStdString(); + calc.variables.push_back( var ); + } + } + + calculations.push_back( calc ); + } + + auto [isOk, errorMessage] = RifGridCalculationExporter::writeToFile( calculations, fileName.toStdString() ); + if ( !isOk ) + { + RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), + "Grid Calculation Export Error", + QString::fromStdString( errorMessage ) ); + } } //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp b/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp index 88aeb264a8..f761dcdb33 100644 --- a/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp +++ b/ApplicationLibCode/Commands/RicImportGridCalculationExpressionsFeature.cpp @@ -24,11 +24,16 @@ #include "RiaPreferences.h" #include "RimEclipseCaseTools.h" +#include "RimEclipseResultAddress.h" #include "RimGridCalculationCollection.h" +#include "RimGridCalculationVariable.h" #include "RimProject.h" +#include "Riu3DMainWindowTools.h" #include "RiuFileDialogTools.h" +#include "RifGridCalculationImporter.h" + #include "cafPdmDefaultObjectFactory.h" #include "cafPdmXmlObjectHandle.h" @@ -50,20 +55,18 @@ void RicImportGridCalculationExpressionsFeature::onActionTriggered( bool isCheck RiaPreferences::current()->gridCalculationExpressionFolder() ); QString fileName = - RiuFileDialogTools::getOpenFileName( nullptr, "Import Grid Calculation Expressions", defaultDir, "Xml File(*.xml);;All files(*.*)" ); - + RiuFileDialogTools::getOpenFileName( nullptr, "Import Grid Calculation Expressions", defaultDir, "Toml File(*.toml);;All files(*.*)" ); if ( fileName.isEmpty() ) return; - QFile importFile( fileName ); - if ( !importFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + auto [calculations, errorMessage] = RifGridCalculationImporter::readFromFile( fileName.toStdString() ); + if ( !errorMessage.empty() ) { - RiaLogging::error( QString( "Import Grid Calculation Expressions : Could not open the file: %1" ).arg( fileName ) ); + RiaLogging::errorInMessageBox( Riu3DMainWindowTools::mainWindowWidget(), + "Grid Calculation Import Error", + QString::fromStdString( errorMessage ) ); return; } - QTextStream stream( &importFile ); - QString objectAsText = stream.readAll(); - auto proj = RimProject::current(); auto calcColl = proj->gridCalculationCollection(); @@ -71,14 +74,32 @@ void RicImportGridCalculationExpressionsFeature::onActionTriggered( bool isCheck auto eclCases = RimEclipseCaseTools::allEclipseGridCases(); if ( !eclCases.empty() ) firstCase = eclCases.front(); - RimGridCalculationCollection tmp; - tmp.xmlCapability()->readObjectFromXmlString( objectAsText, caf::PdmDefaultObjectFactory::instance() ); - for ( auto calc : tmp.calculations() ) + for ( auto calc : calculations ) { - auto gridCalculation = dynamic_cast( calcColl->addCalculationCopy( calc ) ); - if ( gridCalculation && firstCase ) + bool addDefaultExpression = false; + auto gridCalculation = dynamic_cast( calcColl->addCalculation( addDefaultExpression ) ); + if ( gridCalculation ) { - gridCalculation->assignEclipseCaseForNullPointers( firstCase ); + gridCalculation->setExpression( QString::fromStdString( calc.expression ) ); + gridCalculation->setDescription( QString::fromStdString( calc.description ) ); + gridCalculation->setUnit( QString::fromStdString( calc.unit ) ); + for ( auto var : calc.variables ) + { + auto variable = dynamic_cast( gridCalculation->addVariable( QString::fromStdString( var.name ) ) ); + RimEclipseResultAddress address; + + RiaDefines::ResultCatType myEnum = + caf::AppEnum::fromText( QString::fromStdString( var.resultType ) ); + address.setEclipseCase( firstCase ); + address.setResultName( QString::fromStdString( var.resultVariable ) ); + address.setResultType( myEnum ); + variable->setEclipseResultAddress( address ); + } + + if ( firstCase ) + { + gridCalculation->assignEclipseCaseForNullPointers( firstCase ); + } } } diff --git a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake index c2d4e79bf6..582fccf6ca 100644 --- a/ApplicationLibCode/FileInterface/CMakeLists_files.cmake +++ b/ApplicationLibCode/FileInterface/CMakeLists_files.cmake @@ -89,6 +89,9 @@ set(SOURCE_GROUP_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/RifFaultReactivationModelExporter.h ${CMAKE_CURRENT_LIST_DIR}/RifThermalToStimPlanFractureXmlOutput.h ${CMAKE_CURRENT_LIST_DIR}/RifEclipseSummaryAddressDefines.h + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculation.h + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationImporter.h + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationExporter.h ) set(SOURCE_GROUP_SOURCE_FILES @@ -179,6 +182,8 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RifFaultReactivationModelExporter.cpp ${CMAKE_CURRENT_LIST_DIR}/RifThermalToStimPlanFractureXmlOutput.cpp ${CMAKE_CURRENT_LIST_DIR}/RifEclipseSummaryAddressDefines.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationImporter.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationExporter.cpp ) list(APPEND CODE_HEADER_FILES ${SOURCE_GROUP_HEADER_FILES}) diff --git a/ApplicationLibCode/FileInterface/RifGridCalculation.h b/ApplicationLibCode/FileInterface/RifGridCalculation.h new file mode 100644 index 0000000000..5efa8ef0fe --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculation.h @@ -0,0 +1,40 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include +#include + +//================================================================================================== +// +//================================================================================================== +struct RifGridCalculationVariable +{ + std::string name; + std::string resultType; + std::string resultVariable; +}; + +struct RifGridCalculation +{ + std::string description; + std::string expression; + std::string unit; + std::vector variables; +}; diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp new file mode 100644 index 0000000000..ac9788cc63 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.cpp @@ -0,0 +1,72 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifGridCalculationExporter.h" + +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifGridCalculationExporter::writeToFile( const std::vector& calculations, + const std::string& filePath ) +{ + std::ofstream stream( filePath ); + if ( !stream.good() ) return { false, "Unable to open file: " + filePath }; + + return writeToStream( calculations, stream ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair RifGridCalculationExporter::writeToStream( const std::vector& calculations, + std::ostream& stream ) +{ + auto calculationsVector = toml::array(); + + for ( auto calculation : calculations ) + { + auto variablesVector = toml::array{}; + for ( auto variable : calculation.variables ) + { + variablesVector.push_back( toml::table{ + { "name", variable.name }, + { "variable", variable.resultVariable }, + { "type", variable.resultType }, + } ); + } + + calculationsVector.push_back( toml::table{ + { "description", calculation.description }, + { "expression", calculation.expression }, + { "unit", calculation.unit }, + { "variables", variablesVector }, + } ); + } + + auto tbl = toml::table{ + { "grid-calculation", calculationsVector }, + }; + + stream << tbl; + + return { stream.good(), "" }; +} diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationExporter.h b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.h new file mode 100644 index 0000000000..d19c6a98de --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationExporter.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RifGridCalculation.h" + +#include +#include + +//================================================================================================== +// +//================================================================================================== +class RifGridCalculationExporter +{ +public: + static std::pair writeToFile( const std::vector& calculations, const std::string& filePath ); + static std::pair writeToStream( const std::vector& calculations, std::ostream& stream ); +}; diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp new file mode 100644 index 0000000000..e12a4b2966 --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.cpp @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "RifGridCalculationImporter.h" + +#include + +#include + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair, std::string> RifGridCalculationImporter::readFromFile( const std::string& filePath ) +{ + std::ifstream stream( filePath ); + if ( !stream.good() ) return { {}, "Unable to open file: " + filePath }; + + return readFromStream( stream ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::pair, std::string> RifGridCalculationImporter::readFromStream( std::istream& stream ) +{ + toml::table tbl = toml::parse( stream ); + + auto calculationsVector = tbl["grid-calculation"]; + + std::vector calculations; + + if ( toml::array* arr = calculationsVector.as_array() ) + { + for ( auto&& a : *arr ) + { + RifGridCalculation calculation; + if ( toml::table* calc = a.as_table() ) + { + calculation.description = calc->at_path( "description" ).as_string()->value_or( "" ); + calculation.expression = calc->at_path( "expression" ).as_string()->value_or( "" ); + calculation.unit = calc->at_path( "unit" ).as_string()->value_or( "" ); + + if ( toml::array* vars = calc->at_path( "variables" ).as_array() ) + { + std::vector variables; + for ( auto&& v : *vars ) + { + if ( toml::table* var = v.as_table() ) + { + RifGridCalculationVariable variable; + variable.name = var->at_path( "name" ).as_string()->value_or( "" ); + variable.resultType = var->at_path( "type" ).as_string()->value_or( "" ); + variable.resultVariable = var->at_path( "variable" ).as_string()->value_or( "" ); + variables.push_back( variable ); + } + } + calculation.variables = variables; + } + + calculations.push_back( calculation ); + } + } + } + + return { calculations, "" }; +} diff --git a/ApplicationLibCode/FileInterface/RifGridCalculationImporter.h b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.h new file mode 100644 index 0000000000..5a636d550b --- /dev/null +++ b/ApplicationLibCode/FileInterface/RifGridCalculationImporter.h @@ -0,0 +1,34 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2023- Equinor ASA +// +// ResInsight 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. +// +// ResInsight 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 at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#pragma once + +#include "RifGridCalculation.h" + +#include +#include + +//================================================================================================== +// +//================================================================================================== +class RifGridCalculationImporter +{ +public: + static std::pair, std::string> readFromFile( const std::string& filePath ); + static std::pair, std::string> readFromStream( std::istream& stream ); +}; diff --git a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h index e322ac1719..58ea477441 100644 --- a/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h +++ b/ApplicationLibCode/ProjectDataModel/RimGridCalculation.h @@ -64,11 +64,12 @@ public: std::vector inputCases() const; + RimGridCalculationVariable* createVariable() override; + protected: void onChildrenUpdated( caf::PdmChildArrayFieldHandle* childArray, std::vector& updatedObjects ) override; - RimGridCalculationVariable* createVariable() override; - std::pair validateVariables(); + std::pair validateVariables(); std::vector getInputVectorForVariable( RimGridCalculationVariable* v, size_t tsId, diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp index 9303591244..6601ac4588 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.cpp @@ -178,6 +178,14 @@ QString RimUserDefinedCalculation::unitName() const return m_unit; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void RimUserDefinedCalculation::setUnit( const QString& unit ) +{ + m_unit = unit; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h index 563c991485..f8a229bce9 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculation.h @@ -54,10 +54,10 @@ public: std::vector allVariables() const; - void setExpression( const QString& expr ); - QString expression() const; - QString unitName() const; - + void setExpression( const QString& expr ); + QString expression() const; + void setUnit( const QString& unit ); + QString unitName() const; bool parseExpression(); virtual bool preCalculate() const; virtual bool calculate() = 0; @@ -71,6 +71,8 @@ public: QString shortName() const; + RimUserDefinedCalculationVariable* addVariable( const QString& name ); + protected: virtual RimUserDefinedCalculationVariable* createVariable() = 0; @@ -79,7 +81,6 @@ protected: void defineEditorAttribute( const caf::PdmFieldHandle* field, QString uiConfigName, caf::PdmUiEditorAttribute* attribute ) override; RimUserDefinedCalculationVariable* findByName( const QString& name ) const; - RimUserDefinedCalculationVariable* addVariable( const QString& name ); void deleteVariable( RimUserDefinedCalculationVariable* calcVariable ); virtual QString buildCalculationName() const; diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp index ec9f9e66fc..b30dcf0ec4 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.cpp @@ -40,15 +40,18 @@ RimUserDefinedCalculationCollection::RimUserDefinedCalculationCollection() //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -RimUserDefinedCalculation* RimUserDefinedCalculationCollection::addCalculation() +RimUserDefinedCalculation* RimUserDefinedCalculationCollection::addCalculation( bool addDefaultExpression ) { RimUserDefinedCalculation* calculation = createCalculation(); assignCalculationIdToCalculation( calculation ); - QString varName = QString( "Calculation_%1" ).arg( calculation->id() ); - calculation->setDescription( varName ); - calculation->setExpression( varName + " := x + y" ); - calculation->parseExpression(); + if ( addDefaultExpression ) + { + QString varName = QString( "Calculation_%1" ).arg( calculation->id() ); + calculation->setDescription( varName ); + calculation->setExpression( varName + " := x + y" ); + calculation->parseExpression(); + } m_calculations.push_back( calculation ); diff --git a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h index 66698e9f24..7f6fc22122 100644 --- a/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h +++ b/ApplicationLibCode/ProjectDataModel/RimUserDefinedCalculationCollection.h @@ -37,7 +37,7 @@ class RimUserDefinedCalculationCollection : public caf::PdmObject public: RimUserDefinedCalculationCollection(); - RimUserDefinedCalculation* addCalculation(); + RimUserDefinedCalculation* addCalculation( bool addDefaultExpression = true ); RimUserDefinedCalculation* addCalculationCopy( const RimUserDefinedCalculation* sourceCalculation ); void deleteCalculation( RimUserDefinedCalculation* calculation ); std::vector calculations() const; diff --git a/ApplicationLibCode/UnitTests/CMakeLists_files.cmake b/ApplicationLibCode/UnitTests/CMakeLists_files.cmake index 1b9033cf39..9590f662f2 100644 --- a/ApplicationLibCode/UnitTests/CMakeLists_files.cmake +++ b/ApplicationLibCode/UnitTests/CMakeLists_files.cmake @@ -98,6 +98,7 @@ set(SOURCE_GROUP_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/RiaNumericalTools-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/opm-import-well-data-Test.cpp ${CMAKE_CURRENT_LIST_DIR}/RifInpExportTools-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RifGridCalculationIO-Test.cpp ) if(RESINSIGHT_ENABLE_GRPC) diff --git a/ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp b/ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp new file mode 100644 index 0000000000..c5cf719591 --- /dev/null +++ b/ApplicationLibCode/UnitTests/RifGridCalculationIO-Test.cpp @@ -0,0 +1,67 @@ +#include "gtest/gtest.h" + +#include "RiaTestDataDirectory.h" + +#include "RifGridCalculation.h" +#include "RifGridCalculationExporter.h" +#include "RifGridCalculationImporter.h" + +static const std::string GRID_CALCULATION_DIR = std::string( TEST_DATA_DIR ) + std::string( "/RifGridCalculationIO/" ); + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +TEST( RifGridCalculationIO, importAndExport ) +{ + std::string fileName = GRID_CALCULATION_DIR + "calculations.toml"; + + RifGridCalculation calc1; + calc1.description = "My first calculation"; + calc1.expression = "answer = a + b"; + calc1.unit = "meter"; + RifGridCalculationVariable variable1; + variable1.name = "a"; + variable1.resultVariable = "PRESSURE"; + variable1.resultType = "DYNAMIC_NATIVE"; + RifGridCalculationVariable variable2; + variable2.name = "b"; + variable2.resultVariable = "PORO"; + variable2.resultType = "STATIC_NATIVE"; + calc1.variables = { variable1, variable2 }; + + RifGridCalculation calc2; + calc2.description = "My second calculation"; + calc2.expression = "answer = x + y"; + calc2.unit = "meter"; + RifGridCalculationVariable variable3; + variable3.name = "x"; + variable3.resultVariable = "PRESSURE"; + variable3.resultType = "DYNAMIC_NATIVE"; + RifGridCalculationVariable variable4; + variable4.name = "y"; + variable4.resultVariable = "PORO"; + variable4.resultType = "STATIC_NATIVE"; + calc2.variables = { variable3, variable4 }; + + std::vector calculations = { calc1, calc2 }; + + std::stringstream stream; + auto [isOk, errorMessage] = RifGridCalculationExporter::writeToStream( calculations, stream ); + EXPECT_TRUE( isOk ); + EXPECT_TRUE( errorMessage.empty() ); + + auto [importedCalculations, importErrorMessage] = RifGridCalculationImporter::readFromStream( stream ); + ASSERT_EQ( calculations.size(), importedCalculations.size() ); + + ASSERT_EQ( calculations[0].description, importedCalculations[0].description ); + ASSERT_EQ( calculations[0].expression, importedCalculations[0].expression ); + ASSERT_EQ( calculations[0].unit, importedCalculations[0].unit ); + ASSERT_EQ( calculations[0].variables.size(), importedCalculations[0].variables.size() ); + + for ( size_t v = 0; v < calculations[0].variables.size(); v++ ) + { + ASSERT_EQ( calculations[0].variables[v].name, importedCalculations[0].variables[v].name ); + ASSERT_EQ( calculations[0].variables[v].resultType, importedCalculations[0].variables[v].resultType ); + ASSERT_EQ( calculations[0].variables[v].resultVariable, importedCalculations[0].variables[v].resultVariable ); + } +} diff --git a/CMakeLists.txt b/CMakeLists.txt index 57936de2a9..645ff5b01d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,7 @@ if(RESINSIGHT_VCPKG_AUTO_INSTALL) endif() set(CMAKE_CXX_STANDARD 20) + set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) @@ -614,6 +615,12 @@ set_property( "Thirdparty" ) +# ############################################################################## +# toml++ +# ############################################################################## + +add_subdirectory(ThirdParty/tomlplusplus) + # ############################################################################## # Thirdparty libraries are put in ThirdParty solution folder # ############################################################################## diff --git a/ThirdParty/tomlplusplus b/ThirdParty/tomlplusplus new file mode 160000 index 0000000000..d8fa9a1fdd --- /dev/null +++ b/ThirdParty/tomlplusplus @@ -0,0 +1 @@ +Subproject commit d8fa9a1fddc90254cac2366dde23f0b613bc1280