diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b61d9b4d..fe0e68845 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,21 @@ option(USE_DAMARIS_LIB "Use the Damaris library for asynchronous I/O?" OFF) option(USE_BDA_BRIDGE "Enable the BDA bridge (GPU/AMGCL solvers)" ON) option(USE_TRACY_PROFILER "Enable tracy profiling" OFF) option(CONVERT_CUDA_TO_HIP "Convert CUDA code to HIP (to run on AMD cards)" OFF) +set(OPM_COMPILE_COMPONENTS "2;3;4;5;6;7" CACHE STRING "The components to compile support for") +# Check that OPM_COMPILE_COMPONENTS is a subset of 2,3,4,5,6,7 +set(valid_components "2;3;4;5;6;7") +foreach(component IN LISTS OPM_COMPILE_COMPONENTS) + list(FIND valid_components ${component} index) + if(index EQUAL -1) + message(FATAL_ERROR "Invalid component ${component} in OPM_COMPILE_COMPONENTS. Valid components are: ${valid_components}") + endif() +endforeach() +# Check for duplicates in OPM_COMPILE_COMPONENTS +list(REMOVE_DUPLICATES OPM_COMPILE_COMPONENTS) +# Make a string we can use in the code +# this will be used in a template argument pack. +string(REPLACE ";" "," OPM_COMPILE_COMPONENTS_TEMPLATE_LIST "${OPM_COMPILE_COMPONENTS}") + # HIP requires cmake version 3.21 if (CONVERT_CUDA_TO_HIP AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.21") @@ -561,6 +576,12 @@ opm_add_test(flowexp_blackoil $ ) +# We now specify the files we actually want to compile +set(FLOWEXP_COMPONENTS_SOURCES) +foreach(component IN LISTS OPM_COMPILE_COMPONENTS) + list(APPEND FLOWEXP_COMPONENTS_SOURCES flowexperimental/comp/flowexp_comp${component}.cpp) +endforeach() + opm_add_test(flowexp_comp ONLY_COMPILE ALWAYS_ENABLE @@ -568,12 +589,7 @@ opm_add_test(flowexp_comp LIBRARIES opmsimulators SOURCES flowexperimental/comp/flowexp_comp.cpp - flowexperimental/comp/flowexp_comp2.cpp - flowexperimental/comp/flowexp_comp3.cpp - flowexperimental/comp/flowexp_comp4.cpp - flowexperimental/comp/flowexp_comp5.cpp - flowexperimental/comp/flowexp_comp6.cpp - flowexperimental/comp/flowexp_comp7.cpp + ${FLOWEXP_COMPONENTS_SOURCES} $ ) diff --git a/flowexperimental/comp/flowexp_comp.cpp b/flowexperimental/comp/flowexp_comp.cpp index 526f682fa..1bc9efe15 100644 --- a/flowexperimental/comp/flowexp_comp.cpp +++ b/flowexperimental/comp/flowexp_comp.cpp @@ -19,8 +19,8 @@ #include "config.h" #include -#include #include +#include #include @@ -28,9 +28,49 @@ #include +#include + #include "flowexp_comp.hpp" -int main(int argc, char** argv) +template +std::tuple +runComponent(int runtimeComponent, int argc, char** argv) +{ + if (runtimeComponent == compileTimeComponent) { + return std::make_tuple(true, Opm::dispatchFlowExpComp(argc, argv)); + } + return std::make_tuple(false, EXIT_FAILURE); +} + + +/** + * @brief Runs a specified runtime component. + * + * This function checks if the provided runtime component matches the current compile-time component. + * If they match, it dispatches the simulator for the number of components and returns + * a tuple where the second element is the result of the execution. + * + * Otherwise, it recursively calls itself with the next component in the list. + * + * @param runtimecomponent The runtime component identifier to be executed. + * @param argc The number of command-line arguments. + * @param argv The array of command-line arguments. + * @return A tuple containing a boolean indicating if the component was executed and an integer result of the execution. + * + * @note We have two non-variadic templates to be able to properly overload for the base case. + */ +template +std::tuple +runComponent(int runtimecomponent, int argc, char** argv) +{ + if (currentCompileTimeComponent == runtimecomponent) { + return std::make_tuple(true, Opm::dispatchFlowExpComp(argc, argv)); + } + return runComponent(runtimecomponent, argc, argv); +} + +int +main(int argc, char** argv) { using TypeTag = Opm::Properties::TTag::FlowExpCompProblem<0>; Opm::registerEclTimeSteppingParameters(); @@ -44,23 +84,20 @@ int main(int argc, char** argv) = Opm::FlowGenericVanguard::canonicalDeckPath(Opm::Parameters::Get()); // Only read the RUNSPEC section of the deck - const auto deck = Opm::Parser{}.parseFile(inputFilename, - Opm::ParseContext{}, - std::vector { Opm::Ecl::SectionType::RUNSPEC }); + const auto deck + = Opm::Parser {}.parseFile(inputFilename, Opm::ParseContext {}, std::vector {Opm::Ecl::SectionType::RUNSPEC}); const auto runspec = Opm::Runspec(deck); const auto numComps = runspec.numComps(); - OPM_ERROR_IF(numComps < 2 || numComps > 7, - fmt::format("Deck has {} components, not supported. We support a maximum of 7 components, " - "and a minimum of 2.", numComps) ); + auto [componentSupported, executionSatus] + = runComponent(numComps, argc, argv); - switch (numComps) { - case 2: return Opm::dispatchFlowExpComp<2>(argc, argv); - case 3: return Opm::dispatchFlowExpComp<3>(argc, argv); - case 4: return Opm::dispatchFlowExpComp<4>(argc, argv); - case 5: return Opm::dispatchFlowExpComp<5>(argc, argv); - case 6: return Opm::dispatchFlowExpComp<6>(argc, argv); - case 7: return Opm::dispatchFlowExpComp<7>(argc, argv); + if (!componentSupported) { + fmt::println("Deck has {} components, not supported. In this build of the simulator, we support the " + "following number of components:\n\t{}. Note that the supported components can be changed " + "when configuring CMake through the OPM_COMPILE_COMPONENTS options. Exiting.", + numComps, + fmt::join(std::vector {OPM_COMPILE_COMPONENTS_TEMPLATE_LIST}, ", ")); } + return executionSatus; } - diff --git a/opm-simulators-prereqs.cmake b/opm-simulators-prereqs.cmake index 21db38c4c..e1de38275 100644 --- a/opm-simulators-prereqs.cmake +++ b/opm-simulators-prereqs.cmake @@ -27,6 +27,7 @@ set (opm-simulators_CONFIG_VAR USE_TRACY FLOW_INSTANTIATE_FLOAT HAVE_FLOATING_POINT_FROM_CHARS + OPM_COMPILE_COMPONENTS_TEMPLATE_LIST ) # dependencies