From 093b346426a4f46f9165bc8131152962951a4e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 18 Dec 2023 14:26:51 +0100 Subject: [PATCH 1/3] Avoid modifying outputDir, leave empty if defaulted. Handle this case for Damaris, which needs to be told the output dir before this is available from the IOConfig. --- opm/simulators/flow/Main.hpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/opm/simulators/flow/Main.hpp b/opm/simulators/flow/Main.hpp index cd39a4076..9b0487376 100644 --- a/opm/simulators/flow/Main.hpp +++ b/opm/simulators/flow/Main.hpp @@ -78,6 +78,7 @@ #include #include +#include #include #include #include @@ -327,10 +328,6 @@ private: deckFilename = EWOMS_GET_PARAM(PreTypeTag, std::string, EclDeckFileName); outputDir = EWOMS_GET_PARAM(PreTypeTag, std::string, OutputDir); } - - if (outputDir.empty()) { - outputDir = "."; - } #if HAVE_DAMARIS enableDamarisOutput_ = EWOMS_GET_PARAM(PreTypeTag, bool, EnableDamarisOutput); @@ -344,7 +341,18 @@ private: } if (enableDamarisOutput_) { - this->setupDamaris(outputDir); // Damaris server ranks will block here until damaris_stop() is called by client ranks + // Deal with empty (defaulted) output dir, should be deck dir + auto damarisOutputDir = outputDir; + if (outputDir.empty()) { + auto odir = std::filesystem::path{deckFilename}.parent_path(); + if (odir.empty()) { + damarisOutputDir = "."; + } else { + damarisOutputDir = odir.generic_string(); + } + } + // Damaris server ranks will block here until damaris_stop() is called by client ranks + this->setupDamaris(damarisOutputDir); } #endif // HAVE_DAMARIS From c95cd5b147b7a7028b02584c77216441078bdec8 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Tue, 19 Dec 2023 10:34:24 +0100 Subject: [PATCH 2/3] added: bool param to flag that Main.hpp should not initialize/finalize MPI needed for tests --- opm/simulators/flow/Main.cpp | 16 +++++++++++----- opm/simulators/flow/Main.hpp | 3 ++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/opm/simulators/flow/Main.cpp b/opm/simulators/flow/Main.cpp index c75fef642..a9de12950 100644 --- a/opm/simulators/flow/Main.cpp +++ b/opm/simulators/flow/Main.cpp @@ -40,10 +40,12 @@ namespace Opm { -Main::Main(int argc, char** argv) - : argc_(argc), argv_(argv) +Main::Main(int argc, char** argv, bool ownMPI) + : argc_(argc), argv_(argv), ownMPI_(ownMPI) { - initMPI(); + if (ownMPI_) { + initMPI(); + } } Main::Main(const std::string& filename) @@ -83,7 +85,9 @@ Main::~Main() } #endif // HAVE_MPI - EclGenericVanguard::setCommunication(nullptr); + if (ownMPI_) { + EclGenericVanguard::setCommunication(nullptr); + } #if HAVE_DAMARIS if (enableDamarisOutput_) { @@ -102,7 +106,9 @@ Main::~Main() #endif // HAVE_DAMARIS #if HAVE_MPI && !HAVE_DUNE_FEM - MPI_Finalize(); + if (ownMPI_) { + MPI_Finalize(); + } #endif } diff --git a/opm/simulators/flow/Main.hpp b/opm/simulators/flow/Main.hpp index 9b0487376..13125825d 100644 --- a/opm/simulators/flow/Main.hpp +++ b/opm/simulators/flow/Main.hpp @@ -127,7 +127,7 @@ int flowEbosMain(int argc, char** argv, bool outputCout, bool outputFiles) class Main { public: - Main(int argc, char** argv); + Main(int argc, char** argv, bool ownMPI = true); // This constructor can be called from Python Main(const std::string& filename); @@ -727,6 +727,7 @@ private: int argc_{0}; char** argv_{nullptr}; + bool ownMPI_{true}; //!< True if we "own" MPI and should init / finalize bool outputCout_{false}; bool outputFiles_{false}; double setupTime_{0.0}; From de9c3ddfda5f6849a8df371e5912f33f5d478013 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Tue, 19 Dec 2023 10:34:59 +0100 Subject: [PATCH 3/3] added: test for outputdir --- CMakeLists.txt | 2 + CMakeLists_files.cmake | 1 + opm/simulators/flow/Main.hpp | 8 ++ tests/test_outputdir.cpp | 165 +++++++++++++++++++++++++++++++++++ 4 files changed, 176 insertions(+) create mode 100644 tests/test_outputdir.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index d8fd5b65c..b37211142 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -349,6 +349,8 @@ if (HAVE_OPM_TESTS) include (${CMAKE_CURRENT_SOURCE_DIR}/compareECLFiles.cmake) endif() +target_sources(test_outputdir PRIVATE $) + opm_set_test_driver(${CMAKE_CURRENT_SOURCE_DIR}/tests/run-parallel-unitTest.sh "") opm_add_test(test_gatherconvergencereport diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index 472d9e5a6..fa06b12ff 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -268,6 +268,7 @@ list (APPEND TEST_SOURCE_FILES tests/test_milu.cpp tests/test_multmatrixtransposed.cpp tests/test_norne_pvt.cpp + tests/test_outputdir.cpp tests/test_parallel_wbp_sourcevalues.cpp tests/test_parallelwellinfo.cpp tests/test_partitionCells.cpp diff --git a/opm/simulators/flow/Main.hpp b/opm/simulators/flow/Main.hpp index 13125825d..96821dcd8 100644 --- a/opm/simulators/flow/Main.hpp +++ b/opm/simulators/flow/Main.hpp @@ -190,6 +190,14 @@ public: } } + //! \brief Used for test_outputdir. + int justInitialize() + { + int exitCode = EXIT_SUCCESS; + initialize_(exitCode); + return exitCode; + } + private: int dispatchDynamic_() { diff --git a/tests/test_outputdir.cpp b/tests/test_outputdir.cpp new file mode 100644 index 000000000..3ee6d7f4f --- /dev/null +++ b/tests/test_outputdir.cpp @@ -0,0 +1,165 @@ +/* + Copyright 2023 SINTEF Digital, Mathematics and Cybernetics. + + 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 3 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 . +*/ + +#include + +#define BOOST_TEST_MODULE TestOutputDir +#define BOOST_TEST_NO_MAIN +#include + +#include + +#include +#include +#include + +namespace { + +struct Fixture { + Fixture() + { + const std::string deck = R"(RUNSPEC +DIMENS + 10 10 3 / +START + 8 OCT 2020 / +GRID +DXV + 10*100.0 / +DYV + 10*100.0 / +DZV + 3*10.0 / +DEPTHZ + 121*2000.0 / +PERMX + 300*100.0 / +PERMY + 300*100.0 / +PERMZ + 300*10.0 / +PORO + 300*0.3 / +PROPS +SOLUTION +SCHEDULE + +TSTEP + 10 +/ +END +)"; + + input_path = std::filesystem::temp_directory_path() / "outputdir_test/"; + + std::filesystem::remove_all(input_path); + std::filesystem::create_directories(input_path / "subdir" / "subdir"); + + for (const auto& file_path : {input_path / "INPUT.DATA", + input_path / "subdir" / "INPUT.DATA", + input_path / "subdir" / "subdir" / "INPUT.DATA"}) { + std::ofstream of(file_path); + of << deck; + } + } + + ~Fixture() + { + std::filesystem::remove_all(input_path); + } + + std::filesystem::path input_path; +}; + +} + +BOOST_FIXTURE_TEST_CASE(WithOutputDir, Fixture) +{ + std::filesystem::current_path(input_path); + + using PathPair = std::pair; + + for (const auto& Case : {PathPair{input_path, input_path / "output1"}, + PathPair{input_path / "subdir", input_path / "output2"}, + PathPair{input_path / "subdir" / "subdir", input_path / "output3"}}) { + const std::string output_path = "--output-dir=" + Case.second.string(); + const std::string input_file_path = (Case.first / "INPUT.DATA"); + const char* no_param[] = {"test_outputdir", input_file_path.c_str(), + output_path.c_str(), nullptr}; + + using ParamsMeta = Opm::GetProp; + ParamsMeta::clear(); + + Opm::Main main(3, const_cast(no_param), false); + + BOOST_CHECK_EQUAL(main.justInitialize(), EXIT_SUCCESS); + BOOST_CHECK(!std::filesystem::exists(input_path / "INPUT.PRT")); + BOOST_CHECK(!std::filesystem::exists(input_path / "INPUT.DBG")); + BOOST_CHECK(!std::filesystem::exists(Case.first / "INPUT.PRT")); + BOOST_CHECK(!std::filesystem::exists(Case.first / "INPUT.DBG")); + BOOST_CHECK(std::filesystem::exists(Case.second / "INPUT.PRT")); + BOOST_CHECK(std::filesystem::exists(Case.second / "INPUT.DBG")); + } +} + +BOOST_FIXTURE_TEST_CASE(NoOutputDir, Fixture) +{ + std::filesystem::current_path(input_path); + + for (const auto& Case : {input_path / "subdir" / "subdir", + input_path / "subdir"}) { + const std::string input_file_path = (Case / "INPUT.DATA"); + const char* no_param[] = {"test_outputdir", input_file_path.c_str(), nullptr}; + + using ParamsMeta = Opm::GetProp; + ParamsMeta::clear(); + + Opm::Main main(2, const_cast(no_param), false); + + BOOST_CHECK_EQUAL(main.justInitialize(), EXIT_SUCCESS); + BOOST_CHECK(!std::filesystem::exists(input_path / "INPUT.PRT")); + BOOST_CHECK(!std::filesystem::exists(input_path / "INPUT.DBG")); + BOOST_CHECK(std::filesystem::exists(Case/ "INPUT.PRT")); + BOOST_CHECK(std::filesystem::exists(Case/ "INPUT.DBG")); + } +} + +bool init_unit_test_func() +{ + return true; +} + +int main(int argc, char** argv) +{ + // MPI setup. + int argcDummy = 1; + const char *tmp[] = {"test_outputdir"}; + char **argvDummy = const_cast(tmp); +#if HAVE_DUNE_FEM + Dune::Fem::MPIManager::initialize(argcDummy, argvDummy); +#else + Dune::MPIHelper::instance(argcDummy, argvDummy); +#endif + + Opm::EclGenericVanguard::setCommunication(std::make_unique()); + + return boost::unit_test::unit_test_main(&init_unit_test_func, argc, argv); +}