From 4ac0fab7a499be6c0fa5c2df743bc70735d81f9b Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Mon, 24 Jun 2024 14:31:47 -0600 Subject: [PATCH 01/31] update cmake options --- docker/Dockerfile.fortran-gcc | 2 +- docker/Dockerfile.fortran-intel | 2 +- docker/Dockerfile.memcheck | 4 +++- docker/Dockerfile.mpi | 8 +++++--- docker/Dockerfile.mpi_openmp | 10 ++++++---- docker/Dockerfile.openmp | 4 +++- docker/Dockerfile.python | 4 +++- 7 files changed, 22 insertions(+), 12 deletions(-) diff --git a/docker/Dockerfile.fortran-gcc b/docker/Dockerfile.fortran-gcc index 7e6410c9..d21acb7e 100644 --- a/docker/Dockerfile.fortran-gcc +++ b/docker/Dockerfile.fortran-gcc @@ -1,6 +1,6 @@ FROM fedora:35 -ARG BUILD_TYPE=release +ARG BUILD_TYPE=Release RUN dnf -y update \ && dnf -y install \ diff --git a/docker/Dockerfile.fortran-intel b/docker/Dockerfile.fortran-intel index d6f2fe61..1a724f4a 100644 --- a/docker/Dockerfile.fortran-intel +++ b/docker/Dockerfile.fortran-intel @@ -50,7 +50,7 @@ COPY . musica RUN cd musica \ && cmake -S . \ -B build \ - -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ && cd build \ && make install -j diff --git a/docker/Dockerfile.memcheck b/docker/Dockerfile.memcheck index 25c61637..70ff8934 100644 --- a/docker/Dockerfile.memcheck +++ b/docker/Dockerfile.memcheck @@ -1,5 +1,7 @@ FROM fedora:35 +ARG BUILD_TYPE=Release + RUN dnf -y update \ && dnf -y install \ cmake \ @@ -22,7 +24,7 @@ COPY . musica RUN cd musica \ && cmake -S . \ -B build \ - -D CMAKE_BUILD_TYPE=Debug \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ -D MUSICA_ENABLE_MEMCHECK=ON \ && cd build \ && make install -j 8 diff --git a/docker/Dockerfile.mpi b/docker/Dockerfile.mpi index 91acf76e..6d220bd2 100644 --- a/docker/Dockerfile.mpi +++ b/docker/Dockerfile.mpi @@ -1,5 +1,7 @@ FROM fedora:35 +ARG BUILD_TYPE=Release + RUN dnf -y update \ && dnf install -y sudo \ && adduser test_user \ @@ -38,9 +40,9 @@ RUN sudo chown -R test_user.test_user musica RUN cd musica \ && cmake -S . \ -B build \ - -D CMAKE_BUILD_TYPE=debug \ - -D ENABLE_TESTS=ON \ - -D ENABLE_MPI=ON \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -D MUSICA_ENABLE_TESTS=ON \ + -D MUSICA_ENABLE_MPI=ON \ -D CMAKE_Fortran_COMPILER=/usr/lib64/openmpi/bin/mpif90 \ -D CMAKE_C_COMPILER=/usr/lib64/openmpi/bin/mpicc \ -D CMAKE_CXX_COMPILER=/usr/lib64/openmpi/bin/mpicxx \ diff --git a/docker/Dockerfile.mpi_openmp b/docker/Dockerfile.mpi_openmp index a9147545..07f11249 100644 --- a/docker/Dockerfile.mpi_openmp +++ b/docker/Dockerfile.mpi_openmp @@ -1,5 +1,7 @@ FROM fedora:35 +ARG BUILD_TYPE=Release + RUN dnf -y update \ && dnf install -y sudo \ && adduser test_user \ @@ -38,10 +40,10 @@ RUN sudo chown -R test_user.test_user musica RUN cd musica \ && cmake -S . \ -B build \ - -D CMAKE_BUILD_TYPE=debug \ - -D ENABLE_MPI=ON \ - -D ENABLE_OPENMP=ON \ - -D ENABLE_TESTS=ON \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ + -D MUSICA_ENABLE_MPI=ON \ + -D MUSICA_ENABLE_OPENMP=ON \ + -D MUSICA_ENABLE_TESTS=ON \ -D CMAKE_Fortran_COMPILER=/usr/lib64/openmpi/bin/mpif90 \ -D CMAKE_C_COMPILER=/usr/lib64/openmpi/bin/mpicc \ -D CMAKE_CXX_COMPILER=/usr/lib64/openmpi/bin/mpicxx \ diff --git a/docker/Dockerfile.openmp b/docker/Dockerfile.openmp index 7ad2c7af..8c9ef4ac 100644 --- a/docker/Dockerfile.openmp +++ b/docker/Dockerfile.openmp @@ -1,5 +1,7 @@ FROM fedora:35 +ARG BUILD_TYPE=Release + RUN dnf -y update \ && dnf install -y sudo \ && adduser test_user \ @@ -37,7 +39,7 @@ RUN sudo chown -R test_user.test_user musica RUN cd musica \ && cmake -S . \ -B build \ - -D CMAKE_BUILD_TYPE=debug \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ -D ENABLE_OPENMP:BOOL=TRUE \ -D ENABLE_TESTS=ON \ -D CMAKE_Fortran_COMPILER=/usr/lib64/openmpi/bin/mpif90 \ diff --git a/docker/Dockerfile.python b/docker/Dockerfile.python index 1648d612..a75dfec6 100644 --- a/docker/Dockerfile.python +++ b/docker/Dockerfile.python @@ -1,5 +1,7 @@ FROM fedora:35 +ARG BUILD_TYPE=Release + RUN dnf -y update \ && dnf -y install \ cmake \ @@ -23,7 +25,7 @@ RUN pip install -r musica/python/requirements.txt RUN cd musica \ && cmake -S . \ -B build \ - -D CMAKE_BUILD_TYPE=Release \ + -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ -D MUSICA_ENABLE_PYTHON_LIBRARY=ON \ -D MUSICA_ENABLE_TUVX=OFF \ && cd build \ From e27634b5eae0a668b05844a26f2896140206692c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Mon, 24 Jun 2024 17:23:11 -0600 Subject: [PATCH 02/31] set vector matrix dimension --- CMakeLists.txt | 1 + cmake/dependencies.cmake | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 817051b0..1673fe56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option(MUSICA_ENABLE_MEMCHECK "Enable memory checking" OFF) option(MUSICA_BUILD_DOCS "Build the documentation" OFF) option(MUSICA_ENABLE_MICM "Enable MICM" ON) option(MUSICA_ENABLE_TUVX "Enable TUV-x" ON) +set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "4" CACHE STRING "Set MICM vector-ordered matrix dimension") cmake_dependent_option( MUSICA_ENABLE_PYTHON_LIBRARY "Adds pybind11, a lightweight header-only library that exposes C++ types in Python and vice versa" OFF "MUSICA_BUILD_C_CXX_INTERFACE" OFF) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 8ec51940..13969b29 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -60,6 +60,8 @@ if (MUSICA_ENABLE_MICM AND MUSICA_BUILD_C_CXX_INTERFACE) ) set(MICM_ENABLE_TESTS OFF) set(MICM_ENABLE_EXAMPLES OFF) + set(MICM_DEFAULT_VECTOR_MATRIX_SIZE ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) + message(STATUS "MICM vector-ordered matrix dimension: ${MICM_DEFAULT_VECTOR_MATRIX_SIZE}") FetchContent_MakeAvailable(micm) endif() From d114885e9ae611da05f69f519246846ce01395d7 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 2 Jul 2024 22:15:28 -0600 Subject: [PATCH 03/31] compilation flag for grid cells, vector matrix dimension --- CMakeLists.txt | 11 +++++++++-- src/CMakeLists.txt | 3 +++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1673fe56..7ae15f9b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,8 +30,15 @@ option(MUSICA_ENABLE_OPENMP "Enable OpemMP support" OFF) option(MUSICA_ENABLE_MEMCHECK "Enable memory checking" OFF) option(MUSICA_BUILD_DOCS "Build the documentation" OFF) option(MUSICA_ENABLE_MICM "Enable MICM" ON) -option(MUSICA_ENABLE_TUVX "Enable TUV-x" ON) -set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "4" CACHE STRING "Set MICM vector-ordered matrix dimension") +option(MUSICA_ENABLE_TUVX "Enable TUV-x" OFF) + +set(MUSICA_SET_MICM_NUM_GRID_CELLS "1" CACHE STRING "Set the number of grid cells for MICM Solver") +set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "2" CACHE STRING "Set MICM vector-ordered matrix dimension") + +if(${MUSICA_SET_MICM_NUM_GRID_CELLS} LESS ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) + set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE ${MUSICA_SET_MICM_NUM_GRID_CELLS}) + message(STATUS "MICM vector matrix dimension must be less than or equal to the number of grid cells") +endif() cmake_dependent_option( MUSICA_ENABLE_PYTHON_LIBRARY "Adds pybind11, a lightweight header-only library that exposes C++ types in Python and vice versa" OFF "MUSICA_BUILD_C_CXX_INTERFACE" OFF) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e8c7a849..18fce6a1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,6 +17,9 @@ message (STATUS "CMake build configuration for ${PROJECT_NAME} (${CMAKE_BUILD_TY add_library(musica) add_library(musica::musica ALIAS musica) +target_compile_definitions(musica PUBLIC MICM_NUM_GRID_CELLS=${MUSICA_SET_MICM_NUM_GRID_CELLS}) +target_compile_definitions(musica PUBLIC MICM_VECTOR_MATRIX_SIZE=${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) + # set the c++ standard for musica target_compile_features(musica PUBLIC cxx_std_20) From 6d2bc7d533432ca3dc838bd35c116793346cc27f Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 3 Jul 2024 13:56:12 -0600 Subject: [PATCH 04/31] c api for vector ordered matrix --- CMakeLists.txt | 1 + cmake/dependencies.cmake | 3 +- include/musica/micm.hpp | 177 +++++++++++++++++++++++-- src/micm/micm.cpp | 210 +++++++++++++++--------------- src/test/unit/micm/micm_c_api.cpp | 19 +-- 5 files changed, 282 insertions(+), 128 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ae15f9b..6c6aba0b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,7 @@ set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "2" CACHE STRING "Set MICM vector-ordered if(${MUSICA_SET_MICM_NUM_GRID_CELLS} LESS ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE ${MUSICA_SET_MICM_NUM_GRID_CELLS}) message(STATUS "MICM vector matrix dimension must be less than or equal to the number of grid cells") + message(STATUS "MICM vector matrix dimension: " ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) endif() cmake_dependent_option( diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 13969b29..53a3285a 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -51,7 +51,8 @@ endif() if (MUSICA_ENABLE_MICM AND MUSICA_BUILD_C_CXX_INTERFACE) set_git_default(MICM_GIT_REPOSITORY https://github.com/NCAR/micm.git) - set_git_default(MICM_GIT_TAG 401add1bb3d0db9cd13464ed0566dc2599f02ca9) + # set_git_default(MICM_GIT_TAG 401add1bb3d0db9cd13464ed0566dc2599f02ca9) + set_git_default(MICM_GIT_TAG musica-vector-ordered-rosenbrock) FetchContent_Declare(micm GIT_REPOSITORY ${MICM_GIT_REPOSITORY} diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index c4b10075..78f533ee 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -12,13 +12,23 @@ #include #include #include +#include #include +#include +#include #include #include #include #include +#ifndef MICM_NUM_GRID_CELLS + #define MICM_NUM_GRID_CELLS 1 +#endif +#ifndef MICM_VECTOR_MATRIX_SIZE + #define MICM_VECTOR_MATRIX_SIZE 1 +#endif + namespace musica { @@ -28,6 +38,11 @@ namespace musica extern "C" { #endif + enum MICMSolver + { + Rosenbrock = 1, + RosenbrockStandardOrder, + }; struct SolverResultStats { @@ -87,7 +102,13 @@ namespace musica } }; - MICM *CreateMicm(const char *config_path, Error *error); + /// @brief Create a MICM object by specifying the solver type to use + /// @param config_path Path to configuration file or directory containing configuration file + /// @param solver_type Integer value representing solver type + /// 1 : Vector-ordered Rosenbrock solver + /// 2 : Standard-ordered Rosenbrock solver + /// @param error Error struct to indicate success or failure + MICM *CreateMicm(const char *config_path, short solver_type, Error *error); void DeleteMicm(const MICM *micm, Error *error); void MicmSolve( MICM *micm, @@ -116,12 +137,18 @@ namespace musica class MICM { public: - /// @brief Create a solver by reading and parsing configuration file + /// @brief Create a Rosenbrock solver of vector-ordered matrix type by reading and parsing configuration file /// @param config_path Path to configuration file or directory containing configuration file /// @param error Error struct to indicate success or failure - void Create(const std::string &config_path, Error *error); + void CreateRosenbrock(const std::string &config_path, Error *error); + + /// @brief Create a Rosenbrock solver of standard-ordered matrix type by reading and parsing configuration file + /// @param config_path Path to configuration file or directory containing configuration file + /// @param error Error struct to indicate success or failure + void CreateRosenbrockStandard(const std::string &config_path, Error *error); /// @brief Solve the system + /// @param solver Pointer to solver /// @param time_step Time [s] to advance the state by /// @param temperature Temperature [K] /// @param pressure Pressure [Pa] @@ -131,7 +158,9 @@ namespace musica /// @param num_custom_rate_parameters The size of the custom_rate_parameters array /// @param custom_rate_parameters Array of custom rate parameters /// @param error Error struct to indicate success or failure + template void Solve( + std::unique_ptr &solver, double time_step, double temperature, double pressure, @@ -144,15 +173,26 @@ namespace musica SolverResultStats *solver_stats, Error *error); + /// @brief Set solver type + /// @param solver_type Integer value representing solver type + void SetSolverType(short solver_type) + { + solver_type_ = solver_type; + } + /// @brief Get the ordering of species + /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of species names to their indices - std::map GetSpeciesOrdering(Error *error); + template + std::map GetSpeciesOrdering(std::unique_ptr &solver, Error *error); /// @brief Get the ordering of user-defined reaction rates + /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of reaction rate names to their indices - std::map GetUserDefinedReactionRatesOrdering(Error *error); + template + std::map GetUserDefinedReactionRatesOrdering(std::unique_ptr &solver, Error *error); /// @brief Get a property for a chemical species /// @param species_name Name of the species @@ -162,20 +202,129 @@ namespace musica template T GetSpeciesProperty(const std::string &species_name, const std::string &property_name, Error *error); - static constexpr std::size_t NUM_GRID_CELLS = 1; + public: + short solver_type_; - private: - using DenseMatrixPolicy = micm::Matrix; - using SparseMatrixPolicy = micm::SparseMatrix; - using SolverPolicy = typename micm::RosenbrockSolverParameters:: - template SolverType>; - using Rosenbrock = micm::Solver>; + /// @brief Vector-ordered Rosenbrock solver type + using DenseMatrixVector = micm::VectorMatrix; + using SparseMatrixVector = micm::SparseMatrix>; + using RosenbrockVectorType = typename micm::RosenbrockSolverParameters:: + template SolverType>; + using Rosenbrock = micm::Solver>; + std::unique_ptr rosenbrock_; - std::unique_ptr solver_; + /// @brief Standard-ordered Rosenbrock solver type + using DenseMatrixStandard = micm::Matrix; + using SparseMatrixStandard = micm::SparseMatrix; + using RosenbrockStandardType = typename micm::RosenbrockSolverParameters:: + template SolverType>; + using RosenbrockStandard = micm::Solver>; + std::unique_ptr rosenbrock_standard_; + private: std::unique_ptr solver_parameters_; }; + template + inline void MICM::Solve( + std::unique_ptr &solver, + double time_step, + double temperature, + double pressure, + double air_density, + int num_concentrations, + double *concentrations, + int num_custom_rate_parameters, + double *custom_rate_parameters, + String *solver_state, + SolverResultStats *solver_stats, + Error *error) + { + try + { + micm::State state = solver->GetState(); + + for (std::size_t i{}; i < MICM_NUM_GRID_CELLS; i++) + { + state.conditions_[i].temperature_ = temperature; + state.conditions_[i].pressure_ = pressure; + state.conditions_[i].air_density_ = air_density; + } + + // + // TODO(jiwon) - set concentrations for vector matrix for more than 1 grid cells + // + state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); + state.custom_rate_parameters_.AsVector().assign( + custom_rate_parameters, custom_rate_parameters + num_custom_rate_parameters); + + solver->CalculateRateConstants(state); + auto result = solver->Solve(time_step, state); + + *solver_state = CreateString(micm::SolverStateToString(result.state_).c_str()); + + *solver_stats = SolverResultStats( + result.stats_.function_calls_, + result.stats_.jacobian_updates_, + result.stats_.number_of_steps_, + result.stats_.accepted_, + result.stats_.rejected_, + result.stats_.decompositions_, + result.stats_.solves_, + result.stats_.singular_, + result.final_time_); + + for (int i = 0; i < state.variables_.AsVector().size(); i++) + { + concentrations[i] = state.variables_.AsVector()[i]; + } + + DeleteError(error); + *error = NoError(); + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + } + } + + template + inline std::map MICM::GetSpeciesOrdering(std::unique_ptr &solver, Error *error) + { + try + { + micm::State state = solver->GetState(); + DeleteError(error); + *error = NoError(); + return state.variable_map_; + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + return std::map(); + } + } + + template + std::map MICM::GetUserDefinedReactionRatesOrdering(std::unique_ptr &solver, Error *error) + { + try + { + micm::State state = solver->GetState(); + DeleteError(error); + *error = NoError(); + return state.custom_rate_parameter_map_; + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + return std::map(); + } + } + template inline T MICM::GetSpeciesProperty(const std::string &species_name, const std::string &property_name, Error *error) { @@ -201,4 +350,4 @@ namespace musica *error = ToError(MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SPECIES_NOT_FOUND, msg.c_str()); return T(); } -} // namespace musica +} // namespace musica \ No newline at end of file diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 7d03038e..aa714519 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -14,20 +14,37 @@ #include #include #include -#include +#include namespace musica { - MICM *CreateMicm(const char *config_path, Error *error) + + MICM *CreateMicm(const char *config_path, short solver_type, Error *error) { DeleteError(error); + if ((solver_type != 1) && (solver_type != 2)) + { + // TODO(jiwon) error msg? + return nullptr; + } + MICM *micm = new MICM(); - micm->Create(std::string(config_path), error); + if (solver_type == 1) + { + micm->SetSolverType(1); + micm->CreateRosenbrock(std::string(config_path), error); + } + else if (solver_type == 2) + { + micm->SetSolverType(2); + micm->CreateRosenbrockStandard(std::string(config_path), error); + } if (!IsSuccess(*error)) { delete micm; return nullptr; } + return micm; } @@ -65,19 +82,40 @@ namespace musica Error *error) { DeleteError(error); - micm->Solve( - time_step, - temperature, - pressure, - air_density, - num_concentrations, - concentrations, - num_custom_rate_parameters, - custom_rate_parameters, - solver_state, - solver_stats, - error); - } + + if (micm->solver_type_ == MICMSolver::Rosenbrock) + { + micm->Solve( + micm->rosenbrock_, + time_step, + temperature, + pressure, + air_density, + num_concentrations, + concentrations, + num_custom_rate_parameters, + custom_rate_parameters, + solver_state, + solver_stats, + error); + } + else if (micm->solver_type_ == MICMSolver::RosenbrockStandardOrder) + { + micm->Solve( + micm->rosenbrock_standard_, + time_step, + temperature, + pressure, + air_density, + num_concentrations, + concentrations, + num_custom_rate_parameters, + custom_rate_parameters, + solver_state, + solver_stats, + error); + } + }; String MicmVersion() { @@ -87,11 +125,22 @@ namespace musica Mapping *GetSpeciesOrdering(MICM *micm, std::size_t *array_size, Error *error) { DeleteError(error); - auto map = micm->GetSpeciesOrdering(error); + + std::map map; + + if (micm->solver_type_ == MICMSolver::Rosenbrock) + { + map = micm->GetSpeciesOrdering(micm->rosenbrock_, error); + } + else if (micm->solver_type_ == MICMSolver::RosenbrockStandardOrder) + { + map = micm->GetSpeciesOrdering(micm->rosenbrock_standard_, error); + } if (!IsSuccess(*error)) { return nullptr; } + Mapping *species_ordering = new Mapping[map.size()]; // Copy data from the map to the array of structs @@ -110,11 +159,22 @@ namespace musica Mapping *GetUserDefinedReactionRatesOrdering(MICM *micm, std::size_t *array_size, Error *error) { DeleteError(error); - auto map = micm->GetUserDefinedReactionRatesOrdering(error); + + std::map map; + + if (micm->solver_type_ == MICMSolver::Rosenbrock) + { + map = micm->GetUserDefinedReactionRatesOrdering(micm->rosenbrock_, error); + } + else if (micm->solver_type_ == MICMSolver::RosenbrockStandardOrder) + { + map = micm->GetUserDefinedReactionRatesOrdering(micm->rosenbrock_standard_, error); + } if (!IsSuccess(*error)) { return nullptr; } + Mapping *reactionRates = new Mapping[map.size()]; // Copy data from the map to the array of structs @@ -167,7 +227,7 @@ namespace musica return micm->GetSpeciesProperty(species_name_str, property_name_str, error); } - void MICM::Create(const std::string &config_path, Error *error) + void MICM::CreateRosenbrock(const std::string &config_path, Error *error) { try { @@ -175,13 +235,20 @@ namespace musica solver_config.ReadAndParse(std::filesystem::path(config_path)); solver_parameters_ = std::make_unique(solver_config.GetSolverParams()); - solver_ = std::make_unique(micm::CpuSolverBuilder( - micm::RosenbrockSolverParameters::ThreeStageRosenbrockParameters()) - .SetSystem(solver_parameters_->system_) - .SetReactions(solver_parameters_->processes_) - .SetNumberOfGridCells(NUM_GRID_CELLS) - .SetIgnoreUnusedSpecies(true) - .Build()); + rosenbrock_ = std::make_unique( + micm::SolverBuilder< + micm::RosenbrockSolverParameters, + micm::VectorMatrix, + micm::SparseMatrix>, + micm::ProcessSet, + micm::LinearSolver< + micm::SparseMatrix>, + micm::LuDecomposition>>(micm::RosenbrockSolverParameters::ThreeStageRosenbrockParameters()) + .SetSystem(solver_parameters_->system_) + .SetReactions(solver_parameters_->processes_) + .SetNumberOfGridCells(MICM_NUM_GRID_CELLS) + .SetIgnoreUnusedSpecies(true) + .Build()); DeleteError(error); *error = NoError(); @@ -193,97 +260,30 @@ namespace musica } } - void MICM::Solve( - double time_step, - double temperature, - double pressure, - double air_density, - int num_concentrations, - double *concentrations, - int num_custom_rate_parameters, - double *custom_rate_parameters, - String *solver_state, - SolverResultStats *solver_stats, - Error *error) + void MICM::CreateRosenbrockStandard(const std::string &config_path, Error *error) { try { - micm::State state = solver_->GetState(); - - for (std::size_t i{}; i < NUM_GRID_CELLS; i++) - { - state.conditions_[i].temperature_ = temperature; - state.conditions_[i].pressure_ = pressure; - state.conditions_[i].air_density_ = air_density; - } - - state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); - - state.custom_rate_parameters_.AsVector().assign( - custom_rate_parameters, custom_rate_parameters + num_custom_rate_parameters); - - solver_->CalculateRateConstants(state); - auto result = solver_->Solve(time_step, state); - - *solver_state = CreateString(micm::SolverStateToString(result.state_).c_str()); - - *solver_stats = SolverResultStats( - result.stats_.function_calls_, - result.stats_.jacobian_updates_, - result.stats_.number_of_steps_, - result.stats_.accepted_, - result.stats_.rejected_, - result.stats_.decompositions_, - result.stats_.solves_, - result.stats_.singular_, - result.final_time_); - - for (int i = 0; i < state.variables_.AsVector().size(); i++) - { - concentrations[i] = state.variables_.AsVector()[i]; - } - - DeleteError(error); - *error = NoError(); - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - } - } + micm::SolverConfig<> solver_config; + solver_config.ReadAndParse(std::filesystem::path(config_path)); + solver_parameters_ = std::make_unique(solver_config.GetSolverParams()); - std::map MICM::GetSpeciesOrdering(Error *error) - { - try - { - micm::State state = solver_->GetState(); - DeleteError(error); - *error = NoError(); - return state.variable_map_; - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - return std::map(); - } - } + rosenbrock_standard_ = + std::make_unique(micm::CpuSolverBuilder( + micm::RosenbrockSolverParameters::ThreeStageRosenbrockParameters()) + .SetSystem(solver_parameters_->system_) + .SetReactions(solver_parameters_->processes_) + .SetNumberOfGridCells(MICM_NUM_GRID_CELLS) + .SetIgnoreUnusedSpecies(true) + .Build()); - std::map MICM::GetUserDefinedReactionRatesOrdering(Error *error) - { - try - { - micm::State state = solver_->GetState(); DeleteError(error); *error = NoError(); - return state.custom_rate_parameter_map_; } catch (const std::system_error &e) { DeleteError(error); *error = ToError(e); - return std::map(); } } diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 3821ceb8..2dbd6e3d 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -18,9 +18,10 @@ class MicmCApiTest : public ::testing::Test void SetUp() override { + short solver_type = 1; micm = nullptr; Error error; - micm = CreateMicm(config_path, &error); + micm = CreateMicm(config_path, solver_type, &error); ASSERT_TRUE(IsSuccess(error)); DeleteError(&error); @@ -38,8 +39,9 @@ class MicmCApiTest : public ::testing::Test // Test case for bad configuration file path TEST_F(MicmCApiTest, BadConfigurationFilePath) { + short solver_type = 1; Error error = NoError(); - auto micm_bad_config = CreateMicm("bad config path", &error); + auto micm_bad_config = CreateMicm("bad config path", solver_type, &error); ASSERT_EQ(micm_bad_config, nullptr); ASSERT_TRUE(IsError(error, MICM_ERROR_CATEGORY_CONFIGURATION, MICM_CONFIGURATION_ERROR_CODE_INVALID_FILE_PATH)); DeleteError(&error); @@ -189,18 +191,19 @@ TEST_F(MicmCApiTest, SolveMicmInstance) double air_density = pressure / (GAS_CONSTANT * temperature); int num_concentrations = 5; double concentrations[] = { 0.75, 0.4, 0.8, 0.01, 0.02 }; + std::size_t num_user_defined_reaction_rates = 3; + double user_defined_reaction_rates[] = { 0.1, 0.2, 0.3 }; String solver_state; SolverResultStats solver_stats; Error error; - auto ordering = micm->GetUserDefinedReactionRatesOrdering(&error); + Mapping* ordering = GetUserDefinedReactionRatesOrdering(micm, &num_user_defined_reaction_rates, &error); ASSERT_TRUE(IsSuccess(error)); - int num_custom_rate_parameters = ordering.size(); - std::vector custom_rate_parameters(num_custom_rate_parameters, 0.0); - for (auto& entry : ordering) + std::vector custom_rate_parameters(num_user_defined_reaction_rates, 0.0); + for (std::size_t i=0; i Date: Wed, 3 Jul 2024 14:37:15 -0600 Subject: [PATCH 05/31] add vector matrix test --- src/test/unit/micm/micm_c_api.cpp | 78 ++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 2dbd6e3d..4509d959 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -18,6 +18,7 @@ class MicmCApiTest : public ::testing::Test void SetUp() override { + // if 1, Vector-ordered Rosenbrock solver, else if 2, Standard-ordered Rosenbrock solver short solver_type = 1; micm = nullptr; Error error; @@ -47,6 +48,15 @@ TEST_F(MicmCApiTest, BadConfigurationFilePath) DeleteError(&error); } +// Test case for bad configuration file path +TEST_F(MicmCApiTest, BadSolverType) +{ + short solver_type = 999; + Error error = NoError(); + auto micm_bad_solver_type = CreateMicm("configs/chapman", solver_type, &error); + ASSERT_EQ(micm_bad_solver_type, nullptr); +} + // Test case for missing species property TEST_F(MicmCApiTest, MissingSpeciesProperty) { @@ -182,7 +192,7 @@ TEST_F(MicmCApiTest, GetUserDefinedReactionRatesOrdering) } // Test case for solving the MICM instance -TEST_F(MicmCApiTest, SolveMicmInstance) +TEST_F(MicmCApiTest, SolveMicmVectorMatrixInstance) { double time_step = 200.0; double temperature = 272.5; @@ -243,6 +253,72 @@ TEST_F(MicmCApiTest, SolveMicmInstance) DeleteError(&error); } +// Test case for solving the MICM instance +TEST_F(MicmCApiTest, SolveMicmStandardVectorInstance) +{ + short solver_type = 2; + micm = nullptr; + Error error; + micm = CreateMicm(config_path, solver_type, &error); + + double time_step = 200.0; + double temperature = 272.5; + double pressure = 101253.3; + constexpr double GAS_CONSTANT = 8.31446261815324; // J mol-1 K-1 + double air_density = pressure / (GAS_CONSTANT * temperature); + int num_concentrations = 5; + double concentrations[] = { 0.75, 0.4, 0.8, 0.01, 0.02 }; + std::size_t num_user_defined_reaction_rates = 3; + double user_defined_reaction_rates[] = { 0.1, 0.2, 0.3 }; + String solver_state; + SolverResultStats solver_stats; + + Mapping* ordering = GetUserDefinedReactionRatesOrdering(micm, &num_user_defined_reaction_rates, &error); + ASSERT_TRUE(IsSuccess(error)); + + std::vector custom_rate_parameters(num_user_defined_reaction_rates, 0.0); + for (std::size_t i=0; i Date: Wed, 3 Jul 2024 14:49:37 -0600 Subject: [PATCH 06/31] update fortran api --- fortran/test/fetch_content_integration/test_micm_api.F90 | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fortran/test/fetch_content_integration/test_micm_api.F90 b/fortran/test/fetch_content_integration/test_micm_api.F90 index c98eca9d..8d6baa11 100644 --- a/fortran/test/fetch_content_integration/test_micm_api.F90 +++ b/fortran/test/fetch_content_integration/test_micm_api.F90 @@ -42,13 +42,14 @@ subroutine test_api() real(c_double), parameter :: GAS_CONSTANT = 8.31446261815324_c_double ! J mol-1 K-1 integer :: i + config_path = "configs/chapman" + solver_type = 1 time_step = 200 temperature = 272.5 pressure = 101253.4 air_density = pressure / ( GAS_CONSTANT * temperature ) num_concentrations = 5 concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) - config_path = "configs/chapman" num_user_defined_reaction_rates = 3 user_defined_reaction_rates = (/ 0.1, 0.2, 0.3 /) @@ -56,7 +57,7 @@ subroutine test_api() print *, "[test micm fort api] MICM version ", micm_version%get_char_array() write(*,*) "[test micm fort api] Creating MICM solver..." - micm => micm_t(config_path, error) + micm => micm_t(config_path, solver_type, error) ASSERT( error%is_success() ) do i = 1, size( micm%species_ordering ) From 4546e4ae0a7c461ca294a7a0042f6c666193d104 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 3 Jul 2024 15:06:59 -0600 Subject: [PATCH 07/31] chage the build type --- cmake/dependencies.cmake | 4 +--- docker/Dockerfile.memcheck | 2 +- docker/Dockerfile.mpi | 2 +- docker/Dockerfile.mpi_openmp | 2 +- docker/Dockerfile.openmp | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index a03f30a3..0384870c 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -51,8 +51,7 @@ endif() if (MUSICA_ENABLE_MICM AND MUSICA_BUILD_C_CXX_INTERFACE) set_git_default(MICM_GIT_REPOSITORY https://github.com/NCAR/micm.git) - # set_git_default(MICM_GIT_TAG 401add1bb3d0db9cd13464ed0566dc2599f02ca9) - set_git_default(MICM_GIT_TAG musica-vector-ordered-rosenbrock) + set_git_default(MICM_GIT_TAG musica-vector-ordered-rosenbrock) #TODO(jiwon) need to update this FetchContent_Declare(micm GIT_REPOSITORY ${MICM_GIT_REPOSITORY} @@ -62,7 +61,6 @@ if (MUSICA_ENABLE_MICM AND MUSICA_BUILD_C_CXX_INTERFACE) set(MICM_ENABLE_TESTS OFF) set(MICM_ENABLE_EXAMPLES OFF) set(MICM_DEFAULT_VECTOR_MATRIX_SIZE ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) - message(STATUS "MICM vector-ordered matrix dimension: ${MICM_DEFAULT_VECTOR_MATRIX_SIZE}") FetchContent_MakeAvailable(micm) endif() diff --git a/docker/Dockerfile.memcheck b/docker/Dockerfile.memcheck index 70ff8934..cd943615 100644 --- a/docker/Dockerfile.memcheck +++ b/docker/Dockerfile.memcheck @@ -1,6 +1,6 @@ FROM fedora:35 -ARG BUILD_TYPE=Release +ARG BUILD_TYPE=Debug RUN dnf -y update \ && dnf -y install \ diff --git a/docker/Dockerfile.mpi b/docker/Dockerfile.mpi index 6d220bd2..fa85b48f 100644 --- a/docker/Dockerfile.mpi +++ b/docker/Dockerfile.mpi @@ -1,6 +1,6 @@ FROM fedora:35 -ARG BUILD_TYPE=Release +ARG BUILD_TYPE=Debug RUN dnf -y update \ && dnf install -y sudo \ diff --git a/docker/Dockerfile.mpi_openmp b/docker/Dockerfile.mpi_openmp index 07f11249..f48a4605 100644 --- a/docker/Dockerfile.mpi_openmp +++ b/docker/Dockerfile.mpi_openmp @@ -1,6 +1,6 @@ FROM fedora:35 -ARG BUILD_TYPE=Release +ARG BUILD_TYPE=Debug RUN dnf -y update \ && dnf install -y sudo \ diff --git a/docker/Dockerfile.openmp b/docker/Dockerfile.openmp index 8c9ef4ac..db379ebd 100644 --- a/docker/Dockerfile.openmp +++ b/docker/Dockerfile.openmp @@ -1,6 +1,6 @@ FROM fedora:35 -ARG BUILD_TYPE=Release +ARG BUILD_TYPE=Debug RUN dnf -y update \ && dnf install -y sudo \ From fa8248605f388f49e891d0f0866ce73884433c74 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 10:50:03 -0600 Subject: [PATCH 08/31] update python wrapper --- python/test/test_analytical.py | 3 ++- python/test/test_chapman.py | 3 ++- python/wrapper.cpp | 32 ++++++++++++++++++++++++++------ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/python/test/test_analytical.py b/python/test/test_analytical.py index 6f973847..2e1257f1 100644 --- a/python/test/test_analytical.py +++ b/python/test/test_analytical.py @@ -11,7 +11,8 @@ def test_simulation(self): GAS_CONSTANT = 8.31446261815324 air_density = pressure / (GAS_CONSTANT * temperature) - solver = musica.create_solver("configs/analytical") + solver_type = 1 + solver = musica.create_solver("configs/analytical", solver_type) rates = musica.user_defined_reaction_rates(solver) ordering = musica.species_ordering(solver) diff --git a/python/test/test_chapman.py b/python/test/test_chapman.py index 90e93acf..8a3204d0 100644 --- a/python/test/test_chapman.py +++ b/python/test/test_chapman.py @@ -11,7 +11,8 @@ def test_micm_solve(self): air_density = pressure / (GAS_CONSTANT * temperature) concentrations = [0.75, 0.4, 0.8, 0.01, 0.02] - solver = musica.create_solver("configs/chapman") + solver_type = 1 + solver = musica.create_solver("configs/chapman", solver_type) rate_constant_ordering = musica.user_defined_reaction_rates(solver) ordering = musica.species_ordering(solver) diff --git a/python/wrapper.cpp b/python/wrapper.cpp index 7310baf9..b938adc8 100644 --- a/python/wrapper.cpp +++ b/python/wrapper.cpp @@ -12,16 +12,14 @@ PYBIND11_MODULE(musica, m) { py::class_(m, "MICM") .def(py::init<>()) - .def("create", &musica::MICM::Create) - .def("solve", &musica::MICM::Solve) .def("__del__", [](musica::MICM &micm) {}); m.def( "create_solver", - [](const char *config_path) + [](const char *config_path, short solver_type) { musica::Error error; - musica::MICM *micm = musica::CreateMicm(config_path, &error); + musica::MICM *micm = musica::CreateMicm(config_path, solver_type, &error); if (!musica::IsSuccess(error)) { std::string message = "Error creating solver: " + std::string(error.message_.value_); @@ -90,7 +88,18 @@ PYBIND11_MODULE(musica, m) [](musica::MICM *micm) { musica::Error error; - return micm->GetSpeciesOrdering(&error); + std::map map; + + if (micm->solver_type_ == musica::MICMSolver::Rosenbrock) + { + map = micm->GetSpeciesOrdering(micm->rosenbrock_, &error); + } + else if (micm->solver_type_ == musica::MICMSolver::RosenbrockStandardOrder) + { + map = micm->GetSpeciesOrdering(micm->rosenbrock_standard_, &error); + } + + return map; }, "Return map of get_species_ordering rates"); @@ -99,7 +108,18 @@ PYBIND11_MODULE(musica, m) [](musica::MICM *micm) { musica::Error error; - return micm->GetUserDefinedReactionRatesOrdering(&error); + std::map map; + + if (micm->solver_type_ == musica::MICMSolver::Rosenbrock) + { + map = micm->GetUserDefinedReactionRatesOrdering(micm->rosenbrock_, &error); + } + else if (micm->solver_type_ == musica::MICMSolver::RosenbrockStandardOrder) + { + map = micm->GetUserDefinedReactionRatesOrdering(micm->rosenbrock_standard_, &error); + } + + return map; }, "Return map of reaction rates"); } \ No newline at end of file From 54ec3e7fcad5c888c94428b54f3ea7069c182c78 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 13:03:44 -0600 Subject: [PATCH 09/31] resolve memory leak --- fortran/micm.F90 | 14 ++++++++------ .../fetch_content_integration/test_micm_api.F90 | 3 ++- .../test_micm_box_model.F90 | 4 +++- src/test/unit/micm/micm_c_api.cpp | 15 +++++++++------ 4 files changed, 22 insertions(+), 14 deletions(-) diff --git a/fortran/micm.F90 b/fortran/micm.F90 index 854a4db8..d6dcdc9c 100644 --- a/fortran/micm.F90 +++ b/fortran/micm.F90 @@ -26,12 +26,13 @@ module musica_micm end type solver_stats_t_c interface - function create_micm_c(config_path, error) bind(C, name="CreateMicm") + function create_micm_c(config_path, solver_type, error) bind(C, name="CreateMicm") use musica_util, only: error_t_c import c_ptr, c_int, c_char - character(kind=c_char), intent(in) :: config_path(*) - type(error_t_c), intent(inout) :: error - type(c_ptr) :: create_micm_c + character(kind=c_char), intent(in) :: config_path(*) + integer(kind=c_int), value, intent(in) :: solver_type + type(error_t_c), intent(inout) :: error + type(c_ptr) :: create_micm_c end function create_micm_c subroutine delete_micm_c(micm, error) bind(C, name="DeleteMicm") @@ -182,10 +183,11 @@ function get_micm_version() result(value) value = string_t(string_c) end function get_micm_version - function constructor(config_path, error) result( this ) + function constructor(config_path, solver_type, error) result( this ) use musica_util, only: error_t_c, error_t, copy_mappings type(micm_t), pointer :: this character(len=*), intent(in) :: config_path + integer(c_int), intent(in) :: solver_type type(error_t), intent(inout) :: error character(len=1, kind=c_char) :: c_config_path(len_trim(config_path)+1) integer :: n, i @@ -201,7 +203,7 @@ function constructor(config_path, error) result( this ) end do c_config_path(n+1) = c_null_char - this%ptr = create_micm_c(c_config_path, error_c) + this%ptr = create_micm_c(c_config_path, solver_type, error_c) error = error_t(error_c) if (.not. error%is_success()) then deallocate(this) diff --git a/fortran/test/fetch_content_integration/test_micm_api.F90 b/fortran/test/fetch_content_integration/test_micm_api.F90 index 8d6baa11..c27de787 100644 --- a/fortran/test/fetch_content_integration/test_micm_api.F90 +++ b/fortran/test/fetch_content_integration/test_micm_api.F90 @@ -32,6 +32,7 @@ subroutine test_api() real(c_double), dimension(5) :: concentrations real(c_double), dimension(3) :: user_defined_reaction_rates character(len=256) :: config_path + integer(c_int) :: solver_type character(len=:), allocatable :: string_value real(c_double) :: double_value integer(c_int) :: int_value @@ -117,7 +118,7 @@ subroutine test_api() ASSERT( error%is_error( MICM_ERROR_CATEGORY_SPECIES, \ MICM_SPECIES_ERROR_CODE_PROPERTY_NOT_FOUND ) ) deallocate( micm ) - micm => micm_t( "configs/invalid", error ) + micm => micm_t( "configs/invalid", solver_type, error ) ASSERT( error%is_error( MICM_ERROR_CATEGORY_CONFIGURATION, \ MICM_CONFIGURATION_ERROR_CODE_INVALID_FILE_PATH ) ) ASSERT( .not. associated( micm ) ) diff --git a/fortran/test/fetch_content_integration/test_micm_box_model.F90 b/fortran/test/fetch_content_integration/test_micm_box_model.F90 index dfdc5aab..0552b7c8 100644 --- a/fortran/test/fetch_content_integration/test_micm_box_model.F90 +++ b/fortran/test/fetch_content_integration/test_micm_box_model.F90 @@ -15,6 +15,7 @@ program test_micm_box_model subroutine box_model() character(len=256) :: config_path + integer(c_int) :: solver_type real(c_double), parameter :: GAS_CONSTANT = 8.31446261815324_c_double ! J mol-1 K-1 @@ -38,6 +39,7 @@ subroutine box_model() integer :: i config_path = "configs/analytical" + solver_type = 2 time_step = 200 temperature = 273.0 @@ -47,7 +49,7 @@ subroutine box_model() concentrations = (/ 1.0, 1.0, 1.0 /) write(*,*) "Creating MICM solver..." - micm => micm_t(config_path, error) + micm => micm_t(config_path, solver_type, error) do i = 1, size( micm%species_ordering ) associate(the_mapping => micm%species_ordering(i)) diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 4509d959..67a97a67 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -18,8 +18,7 @@ class MicmCApiTest : public ::testing::Test void SetUp() override { - // if 1, Vector-ordered Rosenbrock solver, else if 2, Standard-ordered Rosenbrock solver - short solver_type = 1; + short solver_type = MICMSolver::Rosenbrock; micm = nullptr; Error error; micm = CreateMicm(config_path, solver_type, &error); @@ -249,17 +248,18 @@ TEST_F(MicmCApiTest, SolveMicmVectorMatrixInstance) std::cout << "Singular: " << solver_stats.singular_ << std::endl; std::cout << "Final time: " << solver_stats.final_time_ << std::endl; + DeleteMappings(ordering, num_user_defined_reaction_rates); DeleteString(&solver_state); DeleteError(&error); } // Test case for solving the MICM instance -TEST_F(MicmCApiTest, SolveMicmStandardVectorInstance) +TEST(RosenbrockStandardOrder, SolveMicmStandardOrderInstance) { - short solver_type = 2; - micm = nullptr; Error error; - micm = CreateMicm(config_path, solver_type, &error); + const char* config_path = "configs/chapman"; + short solver_type = MICMSolver::RosenbrockStandardOrder; + MICM* micm = CreateMicm(config_path, solver_type, &error); double time_step = 200.0; double temperature = 272.5; @@ -315,7 +315,10 @@ TEST_F(MicmCApiTest, SolveMicmStandardVectorInstance) std::cout << "Singular: " << solver_stats.singular_ << std::endl; std::cout << "Final time: " << solver_stats.final_time_ << std::endl; + DeleteMappings(ordering, num_user_defined_reaction_rates); DeleteString(&solver_state); + DeleteMicm(micm, &error); + ASSERT_TRUE(IsSuccess(error)); DeleteError(&error); } From b36233056f794c01b52255a9d21571e72b55bd49 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 14:15:49 -0600 Subject: [PATCH 10/31] fix intel docker --- docker/Dockerfile.fortran-intel | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docker/Dockerfile.fortran-intel b/docker/Dockerfile.fortran-intel index 1a724f4a..48e28a64 100644 --- a/docker/Dockerfile.fortran-intel +++ b/docker/Dockerfile.fortran-intel @@ -67,6 +67,4 @@ RUN cd musica/fortran/test/fetch_content_integration \ -D MUSICA_GIT_TAG=${MUSICA_GIT_TAG} \ && make -j -WORKDIR musica/fortran/test/fetch_content_integration/build -RUN cp -r /musica/build/_deps/tuvx-src/examples/ . -RUN cp -r /musica/build/_deps/tuvx-src/data/ . \ No newline at end of file +WORKDIR musica/fortran/test/fetch_content_integration/build \ No newline at end of file From 30bfafcf25811dad4df31e34f38a351dd59fa337 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 14:27:57 -0600 Subject: [PATCH 11/31] tuvx on --- CMakeLists.txt | 2 +- include/musica/micm.hpp | 4 ++-- src/micm/micm.cpp | 4 ++-- src/test/unit/micm/micm_c_api.cpp | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a73933d..c7d2aa50 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ option(MUSICA_ENABLE_OPENMP "Enable OpemMP support" OFF) option(MUSICA_ENABLE_MEMCHECK "Enable memory checking" OFF) option(MUSICA_BUILD_DOCS "Build the documentation" OFF) option(MUSICA_ENABLE_MICM "Enable MICM" ON) -option(MUSICA_ENABLE_TUVX "Enable TUV-x" OFF) +option(MUSICA_ENABLE_TUVX "Enable TUV-x" ON) set(MUSICA_SET_MICM_NUM_GRID_CELLS "1" CACHE STRING "Set the number of grid cells for MICM Solver") set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "2" CACHE STRING "Set MICM vector-ordered matrix dimension") diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index 78f533ee..99f1eda7 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -102,7 +102,7 @@ namespace musica } }; - /// @brief Create a MICM object by specifying the solver type to use + /// @brief Create a MICM object by specifying solver type to use /// @param config_path Path to configuration file or directory containing configuration file /// @param solver_type Integer value representing solver type /// 1 : Vector-ordered Rosenbrock solver @@ -145,7 +145,7 @@ namespace musica /// @brief Create a Rosenbrock solver of standard-ordered matrix type by reading and parsing configuration file /// @param config_path Path to configuration file or directory containing configuration file /// @param error Error struct to indicate success or failure - void CreateRosenbrockStandard(const std::string &config_path, Error *error); + void CreateRosenbrockStandardOrder(const std::string &config_path, Error *error); /// @brief Solve the system /// @param solver Pointer to solver diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index aa714519..f21cfce7 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -37,7 +37,7 @@ namespace musica else if (solver_type == 2) { micm->SetSolverType(2); - micm->CreateRosenbrockStandard(std::string(config_path), error); + micm->CreateRosenbrockStandardOrder(std::string(config_path), error); } if (!IsSuccess(*error)) { @@ -260,7 +260,7 @@ namespace musica } } - void MICM::CreateRosenbrockStandard(const std::string &config_path, Error *error) + void MICM::CreateRosenbrockStandardOrder(const std::string &config_path, Error *error) { try { diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 67a97a67..22a9c3ab 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -210,7 +210,7 @@ TEST_F(MicmCApiTest, SolveMicmVectorMatrixInstance) ASSERT_TRUE(IsSuccess(error)); std::vector custom_rate_parameters(num_user_defined_reaction_rates, 0.0); - for (std::size_t i=0; i custom_rate_parameters(num_user_defined_reaction_rates, 0.0); - for (std::size_t i=0; i Date: Fri, 5 Jul 2024 14:37:11 -0600 Subject: [PATCH 12/31] micm git tag --- cmake/dependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 0384870c..e2dc2eb4 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -51,7 +51,7 @@ endif() if (MUSICA_ENABLE_MICM AND MUSICA_BUILD_C_CXX_INTERFACE) set_git_default(MICM_GIT_REPOSITORY https://github.com/NCAR/micm.git) - set_git_default(MICM_GIT_TAG musica-vector-ordered-rosenbrock) #TODO(jiwon) need to update this + set_git_default(MICM_GIT_TAG v3.5.0) FetchContent_Declare(micm GIT_REPOSITORY ${MICM_GIT_REPOSITORY} From b484cfefe276827e64b9284ce7ae3e1a984d8164 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 15:31:17 -0600 Subject: [PATCH 13/31] edit erorr --- include/musica/micm.hpp | 3 --- include/musica/util.hpp | 5 +++-- src/micm/micm.cpp | 7 +++++-- src/test/unit/micm/micm_c_api.cpp | 12 +++++++----- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index 99f1eda7..fe7bc1d6 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -251,9 +251,6 @@ namespace musica state.conditions_[i].air_density_ = air_density; } - // - // TODO(jiwon) - set concentrations for vector matrix for more than 1 grid cells - // state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); state.custom_rate_parameters_.AsVector().assign( custom_rate_parameters, custom_rate_parameters + num_custom_rate_parameters); diff --git a/include/musica/util.hpp b/include/musica/util.hpp index e6f3f0c6..aaca47b0 100644 --- a/include/musica/util.hpp +++ b/include/musica/util.hpp @@ -4,8 +4,9 @@ #include -#define MUSICA_ERROR_CATEGORY "MUSICA Error" -#define MUSICA_ERROR_CODE_SPECIES_NOT_FOUND 1 +#define MUSICA_ERROR_CATEGORY "MUSICA Error" +#define MUSICA_ERROR_CODE_SPECIES_NOT_FOUND 1 +#define MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND 2 #ifdef __cplusplus #include diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index f21cfce7..d43260bc 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -5,6 +5,7 @@ // multi-component reactive transport model. It also includes functions for // creating and deleting MICM instances, creating solvers, and solving the model. #include +#include #include #include @@ -14,6 +15,7 @@ #include #include #include +#include #include namespace musica @@ -22,9 +24,10 @@ namespace musica MICM *CreateMicm(const char *config_path, short solver_type, Error *error) { DeleteError(error); - if ((solver_type != 1) && (solver_type != 2)) + if ((solver_type != MICMSolver::Rosenbrock) && (solver_type != MICMSolver::RosenbrockStandardOrder)) { - // TODO(jiwon) error msg? + std::string msg = "Solver type '" + std::to_string(solver_type) + "' not found"; + *error = ToError(MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND, msg.c_str()); return nullptr; } diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 22a9c3ab..271aa83d 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -47,13 +47,15 @@ TEST_F(MicmCApiTest, BadConfigurationFilePath) DeleteError(&error); } -// Test case for bad configuration file path +// Test case for bad input for solver type TEST_F(MicmCApiTest, BadSolverType) { short solver_type = 999; Error error = NoError(); auto micm_bad_solver_type = CreateMicm("configs/chapman", solver_type, &error); ASSERT_EQ(micm_bad_solver_type, nullptr); + ASSERT_TRUE(IsError(error, MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND)); + DeleteError(&error); } // Test case for missing species property @@ -190,8 +192,8 @@ TEST_F(MicmCApiTest, GetUserDefinedReactionRatesOrdering) DeleteMappings(reaction_rates_ordering, array_size); } -// Test case for solving the MICM instance -TEST_F(MicmCApiTest, SolveMicmVectorMatrixInstance) +// Test case for solving system with vector-ordered Rosenbrock solver +TEST_F(MicmCApiTest, SolveUsingVectorOrderedRosenbrock) { double time_step = 200.0; double temperature = 272.5; @@ -253,8 +255,8 @@ TEST_F(MicmCApiTest, SolveMicmVectorMatrixInstance) DeleteError(&error); } -// Test case for solving the MICM instance -TEST(RosenbrockStandardOrder, SolveMicmStandardOrderInstance) +// Test case for solving system with standard-ordered Rosenbrock solver +TEST(RosenbrockStandardOrder, SolveUsingStandardOrderedRosenbrock) { Error error; const char* config_path = "configs/chapman"; From 2d503773c6c71272a97ec7b9ae006174ffee6e56 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 15:58:31 -0600 Subject: [PATCH 14/31] opdate the option name for open mp --- docker/Dockerfile.openmp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile.openmp b/docker/Dockerfile.openmp index db379ebd..efc433b8 100644 --- a/docker/Dockerfile.openmp +++ b/docker/Dockerfile.openmp @@ -40,8 +40,8 @@ RUN cd musica \ && cmake -S . \ -B build \ -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ - -D ENABLE_OPENMP:BOOL=TRUE \ - -D ENABLE_TESTS=ON \ + -D MUSICA_ENABLE_OPENMP=ON \ + -D MUSICA_ENABLE_TESTS=ON \ -D CMAKE_Fortran_COMPILER=/usr/lib64/openmpi/bin/mpif90 \ -D CMAKE_C_COMPILER=/usr/lib64/openmpi/bin/mpicc \ -D CMAKE_CXX_COMPILER=/usr/lib64/openmpi/bin/mpic++ \ From f4f65263cbdcea77ceeeee479cf7d6e7aad73e6f Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 16:26:53 -0600 Subject: [PATCH 15/31] remove open mp fortran in c tests --- cmake/test_util.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/test_util.cmake b/cmake/test_util.cmake index 074f01d5..39cafea1 100644 --- a/cmake/test_util.cmake +++ b/cmake/test_util.cmake @@ -43,7 +43,7 @@ function(create_standard_test_cxx) add_executable(test_${TEST_NAME} ${TEST_SOURCES}) target_link_libraries(test_${TEST_NAME} PUBLIC musica::musica GTest::gtest_main) if(MUSICA_ENABLE_OPENMP) - target_link_libraries(test_${TEST_NAME} PUBLIC OpenMP::OpenMP_CXX OpenMP::OpenMP_Fortran) + target_link_libraries(test_${TEST_NAME} PUBLIC OpenMP::OpenMP_CXX) endif() if(NOT DEFINED TEST_WORKING_DIRECTORY) set(TEST_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") From b8481f6739e63c2b5e1ab17010e6596381fa954c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 5 Jul 2024 16:38:04 -0600 Subject: [PATCH 16/31] edit comment --- src/test/unit/micm/micm_c_api.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 271aa83d..d3f735ff 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -192,7 +192,7 @@ TEST_F(MicmCApiTest, GetUserDefinedReactionRatesOrdering) DeleteMappings(reaction_rates_ordering, array_size); } -// Test case for solving system with vector-ordered Rosenbrock solver +// Test case for solving system using vector-ordered Rosenbrock solver TEST_F(MicmCApiTest, SolveUsingVectorOrderedRosenbrock) { double time_step = 200.0; @@ -255,7 +255,7 @@ TEST_F(MicmCApiTest, SolveUsingVectorOrderedRosenbrock) DeleteError(&error); } -// Test case for solving system with standard-ordered Rosenbrock solver +// Test case for solving system using standard-ordered Rosenbrock solver TEST(RosenbrockStandardOrder, SolveUsingStandardOrderedRosenbrock) { Error error; From 5a67815162668db282c96492cdc65d78d9303c17 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Mon, 8 Jul 2024 16:03:56 -0600 Subject: [PATCH 17/31] replace unique ptr T to T --- include/musica/micm.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index fe7bc1d6..9ecaba34 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -160,7 +160,7 @@ namespace musica /// @param error Error struct to indicate success or failure template void Solve( - std::unique_ptr &solver, + T &solver, double time_step, double temperature, double pressure, @@ -185,14 +185,14 @@ namespace musica /// @param error Error struct to indicate success or failure /// @return Map of species names to their indices template - std::map GetSpeciesOrdering(std::unique_ptr &solver, Error *error); + std::map GetSpeciesOrdering(T &solver, Error *error); /// @brief Get the ordering of user-defined reaction rates /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of reaction rate names to their indices template - std::map GetUserDefinedReactionRatesOrdering(std::unique_ptr &solver, Error *error); + std::map GetUserDefinedReactionRatesOrdering(T &solver, Error *error); /// @brief Get a property for a chemical species /// @param species_name Name of the species @@ -227,7 +227,7 @@ namespace musica template inline void MICM::Solve( - std::unique_ptr &solver, + T &solver, double time_step, double temperature, double pressure, @@ -287,7 +287,7 @@ namespace musica } template - inline std::map MICM::GetSpeciesOrdering(std::unique_ptr &solver, Error *error) + inline std::map MICM::GetSpeciesOrdering(T &solver, Error *error) { try { @@ -305,7 +305,7 @@ namespace musica } template - std::map MICM::GetUserDefinedReactionRatesOrdering(std::unique_ptr &solver, Error *error) + std::map MICM::GetUserDefinedReactionRatesOrdering(T &solver, Error *error) { try { From 983a510125493d2df26988d071c20acea796f40c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Mon, 8 Jul 2024 16:25:38 -0600 Subject: [PATCH 18/31] replace tempalte with auto --- include/musica/micm.hpp | 106 ++-------------------------------------- src/micm/micm.cpp | 94 +++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 103 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index 9ecaba34..cd355bb4 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -158,9 +158,8 @@ namespace musica /// @param num_custom_rate_parameters The size of the custom_rate_parameters array /// @param custom_rate_parameters Array of custom rate parameters /// @param error Error struct to indicate success or failure - template void Solve( - T &solver, + auto &solver, double time_step, double temperature, double pressure, @@ -184,15 +183,13 @@ namespace musica /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of species names to their indices - template - std::map GetSpeciesOrdering(T &solver, Error *error); + std::map GetSpeciesOrdering(auto &solver, Error *error); /// @brief Get the ordering of user-defined reaction rates /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of reaction rate names to their indices - template - std::map GetUserDefinedReactionRatesOrdering(T &solver, Error *error); + std::map GetUserDefinedReactionRatesOrdering(auto &solver, Error *error); /// @brief Get a property for a chemical species /// @param species_name Name of the species @@ -225,103 +222,6 @@ namespace musica std::unique_ptr solver_parameters_; }; - template - inline void MICM::Solve( - T &solver, - double time_step, - double temperature, - double pressure, - double air_density, - int num_concentrations, - double *concentrations, - int num_custom_rate_parameters, - double *custom_rate_parameters, - String *solver_state, - SolverResultStats *solver_stats, - Error *error) - { - try - { - micm::State state = solver->GetState(); - - for (std::size_t i{}; i < MICM_NUM_GRID_CELLS; i++) - { - state.conditions_[i].temperature_ = temperature; - state.conditions_[i].pressure_ = pressure; - state.conditions_[i].air_density_ = air_density; - } - - state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); - state.custom_rate_parameters_.AsVector().assign( - custom_rate_parameters, custom_rate_parameters + num_custom_rate_parameters); - - solver->CalculateRateConstants(state); - auto result = solver->Solve(time_step, state); - - *solver_state = CreateString(micm::SolverStateToString(result.state_).c_str()); - - *solver_stats = SolverResultStats( - result.stats_.function_calls_, - result.stats_.jacobian_updates_, - result.stats_.number_of_steps_, - result.stats_.accepted_, - result.stats_.rejected_, - result.stats_.decompositions_, - result.stats_.solves_, - result.stats_.singular_, - result.final_time_); - - for (int i = 0; i < state.variables_.AsVector().size(); i++) - { - concentrations[i] = state.variables_.AsVector()[i]; - } - - DeleteError(error); - *error = NoError(); - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - } - } - - template - inline std::map MICM::GetSpeciesOrdering(T &solver, Error *error) - { - try - { - micm::State state = solver->GetState(); - DeleteError(error); - *error = NoError(); - return state.variable_map_; - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - return std::map(); - } - } - - template - std::map MICM::GetUserDefinedReactionRatesOrdering(T &solver, Error *error) - { - try - { - micm::State state = solver->GetState(); - DeleteError(error); - *error = NoError(); - return state.custom_rate_parameter_map_; - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - return std::map(); - } - } - template inline T MICM::GetSpeciesProperty(const std::string &species_name, const std::string &property_name, Error *error) { diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index d43260bc..a33b7f2b 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -290,4 +290,98 @@ namespace musica } } + void MICM::Solve( + auto &solver, + double time_step, + double temperature, + double pressure, + double air_density, + int num_concentrations, + double *concentrations, + int num_custom_rate_parameters, + double *custom_rate_parameters, + String *solver_state, + SolverResultStats *solver_stats, + Error *error) + { + try + { + micm::State state = solver->GetState(); + + for (std::size_t i{}; i < MICM_NUM_GRID_CELLS; i++) + { + state.conditions_[i].temperature_ = temperature; + state.conditions_[i].pressure_ = pressure; + state.conditions_[i].air_density_ = air_density; + } + + state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); + state.custom_rate_parameters_.AsVector().assign( + custom_rate_parameters, custom_rate_parameters + num_custom_rate_parameters); + + solver->CalculateRateConstants(state); + auto result = solver->Solve(time_step, state); + + *solver_state = CreateString(micm::SolverStateToString(result.state_).c_str()); + + *solver_stats = SolverResultStats( + result.stats_.function_calls_, + result.stats_.jacobian_updates_, + result.stats_.number_of_steps_, + result.stats_.accepted_, + result.stats_.rejected_, + result.stats_.decompositions_, + result.stats_.solves_, + result.stats_.singular_, + result.final_time_); + + for (int i = 0; i < state.variables_.AsVector().size(); i++) + { + concentrations[i] = state.variables_.AsVector()[i]; + } + + DeleteError(error); + *error = NoError(); + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + } + } + + std::map MICM::GetSpeciesOrdering(auto &solver, Error *error) + { + try + { + micm::State state = solver->GetState(); + DeleteError(error); + *error = NoError(); + return state.variable_map_; + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + return std::map(); + } + } + + std::map MICM::GetUserDefinedReactionRatesOrdering(auto &solver, Error *error) + { + try + { + micm::State state = solver->GetState(); + DeleteError(error); + *error = NoError(); + return state.custom_rate_parameter_map_; + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + return std::map(); + } + } + } // namespace musica From 997038bf17590bedd2cc4d156bfe5981e9da82aa Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 14:15:27 -0600 Subject: [PATCH 19/31] add map header --- include/musica/micm.hpp | 1 + src/micm/micm.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index cd355bb4..d3522995 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index a33b7f2b..26907ff4 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -32,14 +32,14 @@ namespace musica } MICM *micm = new MICM(); - if (solver_type == 1) + if (solver_type == MICMSolver::Rosenbrock) { - micm->SetSolverType(1); + micm->SetSolverType(MICMSolver::Rosenbrock); micm->CreateRosenbrock(std::string(config_path), error); } - else if (solver_type == 2) + else if (solver_type == MICMSolver::RosenbrockStandardOrder) { - micm->SetSolverType(2); + micm->SetSolverType(MICMSolver::RosenbrockStandardOrder); micm->CreateRosenbrockStandardOrder(std::string(config_path), error); } if (!IsSuccess(*error)) From 80a0f667befd905b2918efbd0ede9d02cdd5f74b Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 15:17:49 -0600 Subject: [PATCH 20/31] expose solver type enum to python --- python/test/test_analytical.py | 4 +--- python/test/test_chapman.py | 3 +-- python/wrapper.cpp | 6 +++++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/python/test/test_analytical.py b/python/test/test_analytical.py index 2e1257f1..92230a16 100644 --- a/python/test/test_analytical.py +++ b/python/test/test_analytical.py @@ -11,9 +11,7 @@ def test_simulation(self): GAS_CONSTANT = 8.31446261815324 air_density = pressure / (GAS_CONSTANT * temperature) - solver_type = 1 - solver = musica.create_solver("configs/analytical", solver_type) - + solver = musica.create_solver("configs/analytical", musica.micmsolver.rosenbrock) rates = musica.user_defined_reaction_rates(solver) ordering = musica.species_ordering(solver) diff --git a/python/test/test_chapman.py b/python/test/test_chapman.py index 8a3204d0..7d11eaef 100644 --- a/python/test/test_chapman.py +++ b/python/test/test_chapman.py @@ -11,8 +11,7 @@ def test_micm_solve(self): air_density = pressure / (GAS_CONSTANT * temperature) concentrations = [0.75, 0.4, 0.8, 0.01, 0.02] - solver_type = 1 - solver = musica.create_solver("configs/chapman", solver_type) + solver = musica.create_solver("configs/chapman", musica.micmsolver.rosenbrock) rate_constant_ordering = musica.user_defined_reaction_rates(solver) ordering = musica.species_ordering(solver) diff --git a/python/wrapper.cpp b/python/wrapper.cpp index b938adc8..fb6cccbb 100644 --- a/python/wrapper.cpp +++ b/python/wrapper.cpp @@ -10,10 +10,14 @@ namespace py = pybind11; // Wraps micm.cpp PYBIND11_MODULE(musica, m) { - py::class_(m, "MICM") + py::class_(m, "micm") .def(py::init<>()) .def("__del__", [](musica::MICM &micm) {}); + py::enum_(m, "micmsolver") + .value("rosenbrock", musica::MICMSolver::Rosenbrock) + .value("rosenbrock_standard_order", musica::MICMSolver::RosenbrockStandardOrder); + m.def( "create_solver", [](const char *config_path, short solver_type) From 23889c3231b7d852f2dc1ba523eb036d2c3ef038 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 16:28:14 -0600 Subject: [PATCH 21/31] back to template --- include/musica/micm.hpp | 22 +++++++++++++++++++++- python/wrapper.cpp | 2 +- src/micm/micm.cpp | 32 ++++++++++++++++---------------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index d3522995..a36b0bf7 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -184,7 +184,9 @@ namespace musica /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of species names to their indices - std::map GetSpeciesOrdering(auto &solver, Error *error); + // std::map GetSpeciesOrdering(auto &solver, Error *error); + template + std::map GetSpeciesOrdering(T &solver, Error *error); /// @brief Get the ordering of user-defined reaction rates /// @param solver Pointer to solver @@ -223,6 +225,24 @@ namespace musica std::unique_ptr solver_parameters_; }; + template + inline std::map MICM::GetSpeciesOrdering(T &solver, Error *error) + { + try + { + micm::State state = solver->GetState(); + DeleteError(error); + *error = NoError(); + return state.variable_map_; + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + return std::map(); + } + } + template inline T MICM::GetSpeciesProperty(const std::string &species_name, const std::string &property_name, Error *error) { diff --git a/python/wrapper.cpp b/python/wrapper.cpp index fb6cccbb..6a9608ad 100644 --- a/python/wrapper.cpp +++ b/python/wrapper.cpp @@ -20,7 +20,7 @@ PYBIND11_MODULE(musica, m) m.def( "create_solver", - [](const char *config_path, short solver_type) + [](const char *config_path, musica::MICMSolver solver_type) { musica::Error error; musica::MICM *micm = musica::CreateMicm(config_path, solver_type, &error); diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 26907ff4..133b0cf0 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -350,22 +350,22 @@ namespace musica } } - std::map MICM::GetSpeciesOrdering(auto &solver, Error *error) - { - try - { - micm::State state = solver->GetState(); - DeleteError(error); - *error = NoError(); - return state.variable_map_; - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - return std::map(); - } - } + // std::map MICM::GetSpeciesOrdering(auto &solver, Error *error) + // { + // try + // { + // micm::State state = solver->GetState(); + // DeleteError(error); + // *error = NoError(); + // return state.variable_map_; + // } + // catch (const std::system_error &e) + // { + // DeleteError(error); + // *error = ToError(e); + // return std::map(); + // } + // } std::map MICM::GetUserDefinedReactionRatesOrdering(auto &solver, Error *error) { From 276bc8f523ff9839dc642b4b295aaaba1a51bdeb Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 16:36:36 -0600 Subject: [PATCH 22/31] back to template --- include/musica/micm.hpp | 21 ++++++++++++++++++++- src/micm/micm.cpp | 34 ---------------------------------- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index a36b0bf7..63318a68 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -192,7 +192,8 @@ namespace musica /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure /// @return Map of reaction rate names to their indices - std::map GetUserDefinedReactionRatesOrdering(auto &solver, Error *error); + template + std::map GetUserDefinedReactionRatesOrdering(T &solver, Error *error); /// @brief Get a property for a chemical species /// @param species_name Name of the species @@ -243,6 +244,24 @@ namespace musica } } + template + inline std::map MICM::GetUserDefinedReactionRatesOrdering(T &solver, Error *error) + { + try + { + micm::State state = solver->GetState(); + DeleteError(error); + *error = NoError(); + return state.custom_rate_parameter_map_; + } + catch (const std::system_error &e) + { + DeleteError(error); + *error = ToError(e); + return std::map(); + } + } + template inline T MICM::GetSpeciesProperty(const std::string &species_name, const std::string &property_name, Error *error) { diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 133b0cf0..512cb9ef 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -350,38 +350,4 @@ namespace musica } } - // std::map MICM::GetSpeciesOrdering(auto &solver, Error *error) - // { - // try - // { - // micm::State state = solver->GetState(); - // DeleteError(error); - // *error = NoError(); - // return state.variable_map_; - // } - // catch (const std::system_error &e) - // { - // DeleteError(error); - // *error = ToError(e); - // return std::map(); - // } - // } - - std::map MICM::GetUserDefinedReactionRatesOrdering(auto &solver, Error *error) - { - try - { - micm::State state = solver->GetState(); - DeleteError(error); - *error = NoError(); - return state.custom_rate_parameter_map_; - } - catch (const std::system_error &e) - { - DeleteError(error); - *error = ToError(e); - return std::map(); - } - } - } // namespace musica From 2812b211a1056e5604691ffcc4ce346a788fda93 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 18:23:39 -0600 Subject: [PATCH 23/31] enum for solver type --- include/musica/micm.hpp | 15 +++++++-------- src/micm/micm.cpp | 2 +- src/test/unit/micm/micm_c_api.cpp | 11 ++++------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index 63318a68..c19fb08f 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -39,10 +39,11 @@ namespace musica extern "C" { #endif + /// @brief Types of MICM solver enum MICMSolver { - Rosenbrock = 1, - RosenbrockStandardOrder, + Rosenbrock = 1, // Vector-ordered Rosenbrock solver + RosenbrockStandardOrder, // Standard-ordered Rosenbrock solver }; struct SolverResultStats @@ -105,11 +106,9 @@ namespace musica /// @brief Create a MICM object by specifying solver type to use /// @param config_path Path to configuration file or directory containing configuration file - /// @param solver_type Integer value representing solver type - /// 1 : Vector-ordered Rosenbrock solver - /// 2 : Standard-ordered Rosenbrock solver + /// @param solver_type Type of MICMSolver /// @param error Error struct to indicate success or failure - MICM *CreateMicm(const char *config_path, short solver_type, Error *error); + MICM *CreateMicm(const char *config_path, MICMSolver solver_type, Error *error); void DeleteMicm(const MICM *micm, Error *error); void MicmSolve( MICM *micm, @@ -174,8 +173,8 @@ namespace musica Error *error); /// @brief Set solver type - /// @param solver_type Integer value representing solver type - void SetSolverType(short solver_type) + /// @param MICMSolver Type of MICMSolver + void SetSolverType(MICMSolver solver_type) { solver_type_ = solver_type; } diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 512cb9ef..eb852b0f 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -21,7 +21,7 @@ namespace musica { - MICM *CreateMicm(const char *config_path, short solver_type, Error *error) + MICM *CreateMicm(const char *config_path, MICMSolver solver_type, Error *error) { DeleteError(error); if ((solver_type != MICMSolver::Rosenbrock) && (solver_type != MICMSolver::RosenbrockStandardOrder)) diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index d3f735ff..7a342ddd 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -18,10 +18,9 @@ class MicmCApiTest : public ::testing::Test void SetUp() override { - short solver_type = MICMSolver::Rosenbrock; micm = nullptr; Error error; - micm = CreateMicm(config_path, solver_type, &error); + micm = CreateMicm(config_path, MICMSolver::Rosenbrock, &error); ASSERT_TRUE(IsSuccess(error)); DeleteError(&error); @@ -39,9 +38,8 @@ class MicmCApiTest : public ::testing::Test // Test case for bad configuration file path TEST_F(MicmCApiTest, BadConfigurationFilePath) { - short solver_type = 1; Error error = NoError(); - auto micm_bad_config = CreateMicm("bad config path", solver_type, &error); + auto micm_bad_config = CreateMicm("bad config path", MICMSolver::Rosenbrock, &error); ASSERT_EQ(micm_bad_config, nullptr); ASSERT_TRUE(IsError(error, MICM_ERROR_CATEGORY_CONFIGURATION, MICM_CONFIGURATION_ERROR_CODE_INVALID_FILE_PATH)); DeleteError(&error); @@ -52,7 +50,7 @@ TEST_F(MicmCApiTest, BadSolverType) { short solver_type = 999; Error error = NoError(); - auto micm_bad_solver_type = CreateMicm("configs/chapman", solver_type, &error); + auto micm_bad_solver_type = CreateMicm("configs/chapman", static_cast(solver_type), &error); ASSERT_EQ(micm_bad_solver_type, nullptr); ASSERT_TRUE(IsError(error, MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND)); DeleteError(&error); @@ -260,8 +258,7 @@ TEST(RosenbrockStandardOrder, SolveUsingStandardOrderedRosenbrock) { Error error; const char* config_path = "configs/chapman"; - short solver_type = MICMSolver::RosenbrockStandardOrder; - MICM* micm = CreateMicm(config_path, solver_type, &error); + MICM* micm = CreateMicm(config_path, MICMSolver::RosenbrockStandardOrder, &error); double time_step = 200.0; double temperature = 272.5; From 09bf9b88dbaeb3f84931a92c89c060bc1969ddd7 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 19:27:06 -0600 Subject: [PATCH 24/31] enum solver type for fortran --- fortran/micm.F90 | 6 ++++++ .../fetch_content_integration/test_micm_api.F90 | 3 ++- include/musica/micm.hpp | 2 +- src/micm/micm.cpp | 15 ++++++++------- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/fortran/micm.F90 b/fortran/micm.F90 index d6dcdc9c..973b2e50 100644 --- a/fortran/micm.F90 +++ b/fortran/micm.F90 @@ -10,6 +10,7 @@ module musica_micm implicit none public :: micm_t, solver_stats_t, get_micm_version + public :: Rosenbrock, RosenbrockStandardOrder private !> Wrapper for c solver stats @@ -25,6 +26,11 @@ module musica_micm real(c_double) :: final_time_ = 0._c_double end type solver_stats_t_c + enum, bind(c) + enumerator :: Rosenbrock = 1, & + RosenbrockStandardOrder = 2 + end enum + interface function create_micm_c(config_path, solver_type, error) bind(C, name="CreateMicm") use musica_util, only: error_t_c diff --git a/fortran/test/fetch_content_integration/test_micm_api.F90 b/fortran/test/fetch_content_integration/test_micm_api.F90 index c27de787..f03bb61a 100644 --- a/fortran/test/fetch_content_integration/test_micm_api.F90 +++ b/fortran/test/fetch_content_integration/test_micm_api.F90 @@ -6,6 +6,7 @@ program test_micm_api use, intrinsic :: iso_c_binding use, intrinsic :: ieee_arithmetic use musica_micm, only: micm_t, solver_stats_t, get_micm_version + use musica_micm, only: Rosenbrock, RosenbrockStandardOrder use musica_util, only: assert, error_t, mapping_t, string_t #include "micm/util/error.hpp" @@ -44,7 +45,7 @@ subroutine test_api() integer :: i config_path = "configs/chapman" - solver_type = 1 + solver_type = Rosenbrock time_step = 200 temperature = 272.5 pressure = 101253.4 diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index c19fb08f..79184836 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -203,7 +203,7 @@ namespace musica T GetSpeciesProperty(const std::string &species_name, const std::string &property_name, Error *error); public: - short solver_type_; + MICMSolver solver_type_; /// @brief Vector-ordered Rosenbrock solver type using DenseMatrixVector = micm::VectorMatrix; diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index eb852b0f..6b002d4c 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -24,14 +24,8 @@ namespace musica MICM *CreateMicm(const char *config_path, MICMSolver solver_type, Error *error) { DeleteError(error); - if ((solver_type != MICMSolver::Rosenbrock) && (solver_type != MICMSolver::RosenbrockStandardOrder)) - { - std::string msg = "Solver type '" + std::to_string(solver_type) + "' not found"; - *error = ToError(MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND, msg.c_str()); - return nullptr; - } - MICM *micm = new MICM(); + if (solver_type == MICMSolver::Rosenbrock) { micm->SetSolverType(MICMSolver::Rosenbrock); @@ -42,6 +36,13 @@ namespace musica micm->SetSolverType(MICMSolver::RosenbrockStandardOrder); micm->CreateRosenbrockStandardOrder(std::string(config_path), error); } + else + { + std::string msg = "Solver type '" + std::to_string(solver_type) + "' not found"; + *error = ToError(MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND, msg.c_str()); + delete micm; + return nullptr; + } if (!IsSuccess(*error)) { delete micm; From 680a2cb950c7497998e26520b95cf16ad060d341 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 9 Jul 2024 19:30:18 -0600 Subject: [PATCH 25/31] add fortran 2023 feature comment --- fortran/micm.F90 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fortran/micm.F90 b/fortran/micm.F90 index 973b2e50..72add656 100644 --- a/fortran/micm.F90 +++ b/fortran/micm.F90 @@ -26,6 +26,8 @@ module musica_micm real(c_double) :: final_time_ = 0._c_double end type solver_stats_t_c + ! We could use Fortran 2023 enum type feature if Fortran 2023 is supported + ! https://fortran-lang.discourse.group/t/enumerator-type-in-bind-c-derived-type-best-practice/5947/2 enum, bind(c) enumerator :: Rosenbrock = 1, & RosenbrockStandardOrder = 2 From 61c87df0cf8c83a101cbc050e515a9ef2db25b1c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 10 Jul 2024 14:47:12 -0600 Subject: [PATCH 26/31] pass num grid cells to constructor --- CMakeLists.txt | 9 +-------- fortran/micm.F90 | 12 +++++++----- .../test_micm_api.F90 | 6 ++++-- .../test_micm_box_model.F90 | 7 +++++-- include/musica/micm.hpp | 11 ++++++++++- python/test/test_analytical.py | 3 ++- python/test/test_chapman.py | 3 ++- python/wrapper.cpp | 4 ++-- src/micm/micm.cpp | 18 ++++++++++-------- src/test/unit/micm/micm_c_api.cpp | 14 +++++++++----- 10 files changed, 52 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c7d2aa50..175f4b8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,14 +30,7 @@ option(MUSICA_BUILD_DOCS "Build the documentation" OFF) option(MUSICA_ENABLE_MICM "Enable MICM" ON) option(MUSICA_ENABLE_TUVX "Enable TUV-x" ON) -set(MUSICA_SET_MICM_NUM_GRID_CELLS "1" CACHE STRING "Set the number of grid cells for MICM Solver") -set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "2" CACHE STRING "Set MICM vector-ordered matrix dimension") - -if(${MUSICA_SET_MICM_NUM_GRID_CELLS} LESS ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) - set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE ${MUSICA_SET_MICM_NUM_GRID_CELLS}) - message(STATUS "MICM vector matrix dimension must be less than or equal to the number of grid cells") - message(STATUS "MICM vector matrix dimension: " ${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) -endif() +set(MUSICA_SET_MICM_VECTOR_MATRIX_SIZE "1" CACHE STRING "Set MICM vector-ordered matrix dimension") cmake_dependent_option( MUSICA_ENABLE_PYTHON_LIBRARY "Adds pybind11, a lightweight header-only library that exposes C++ types in Python and vice versa" OFF "MUSICA_BUILD_C_CXX_INTERFACE" OFF) diff --git a/fortran/micm.F90 b/fortran/micm.F90 index 72add656..db1ab198 100644 --- a/fortran/micm.F90 +++ b/fortran/micm.F90 @@ -29,16 +29,17 @@ module musica_micm ! We could use Fortran 2023 enum type feature if Fortran 2023 is supported ! https://fortran-lang.discourse.group/t/enumerator-type-in-bind-c-derived-type-best-practice/5947/2 enum, bind(c) - enumerator :: Rosenbrock = 1, & - RosenbrockStandardOrder = 2 + enumerator :: Rosenbrock = 1 + enumerator :: RosenbrockStandardOrder = 2 end enum interface - function create_micm_c(config_path, solver_type, error) bind(C, name="CreateMicm") + function create_micm_c(config_path, solver_type, num_grid_cells, error) bind(C, name="CreateMicm") use musica_util, only: error_t_c import c_ptr, c_int, c_char character(kind=c_char), intent(in) :: config_path(*) integer(kind=c_int), value, intent(in) :: solver_type + integer(kind=c_int), value, intent(in) :: num_grid_cells type(error_t_c), intent(inout) :: error type(c_ptr) :: create_micm_c end function create_micm_c @@ -191,11 +192,12 @@ function get_micm_version() result(value) value = string_t(string_c) end function get_micm_version - function constructor(config_path, solver_type, error) result( this ) + function constructor(config_path, solver_type, num_grid_cells, error) result( this ) use musica_util, only: error_t_c, error_t, copy_mappings type(micm_t), pointer :: this character(len=*), intent(in) :: config_path integer(c_int), intent(in) :: solver_type + integer(c_int), intent(in) :: num_grid_cells type(error_t), intent(inout) :: error character(len=1, kind=c_char) :: c_config_path(len_trim(config_path)+1) integer :: n, i @@ -211,7 +213,7 @@ function constructor(config_path, solver_type, error) result( this ) end do c_config_path(n+1) = c_null_char - this%ptr = create_micm_c(c_config_path, solver_type, error_c) + this%ptr = create_micm_c(c_config_path, solver_type, num_grid_cells, error_c) error = error_t(error_c) if (.not. error%is_success()) then deallocate(this) diff --git a/fortran/test/fetch_content_integration/test_micm_api.F90 b/fortran/test/fetch_content_integration/test_micm_api.F90 index f03bb61a..24d9d31c 100644 --- a/fortran/test/fetch_content_integration/test_micm_api.F90 +++ b/fortran/test/fetch_content_integration/test_micm_api.F90 @@ -34,6 +34,7 @@ subroutine test_api() real(c_double), dimension(3) :: user_defined_reaction_rates character(len=256) :: config_path integer(c_int) :: solver_type + integer(c_int) :: num_grid_cells character(len=:), allocatable :: string_value real(c_double) :: double_value integer(c_int) :: int_value @@ -46,6 +47,7 @@ subroutine test_api() config_path = "configs/chapman" solver_type = Rosenbrock + num_grid_cells = 1 time_step = 200 temperature = 272.5 pressure = 101253.4 @@ -59,7 +61,7 @@ subroutine test_api() print *, "[test micm fort api] MICM version ", micm_version%get_char_array() write(*,*) "[test micm fort api] Creating MICM solver..." - micm => micm_t(config_path, solver_type, error) + micm => micm_t(config_path, solver_type, num_grid_cells, error) ASSERT( error%is_success() ) do i = 1, size( micm%species_ordering ) @@ -119,7 +121,7 @@ subroutine test_api() ASSERT( error%is_error( MICM_ERROR_CATEGORY_SPECIES, \ MICM_SPECIES_ERROR_CODE_PROPERTY_NOT_FOUND ) ) deallocate( micm ) - micm => micm_t( "configs/invalid", solver_type, error ) + micm => micm_t( "configs/invalid", solver_type, num_grid_cells, error ) ASSERT( error%is_error( MICM_ERROR_CATEGORY_CONFIGURATION, \ MICM_CONFIGURATION_ERROR_CODE_INVALID_FILE_PATH ) ) ASSERT( .not. associated( micm ) ) diff --git a/fortran/test/fetch_content_integration/test_micm_box_model.F90 b/fortran/test/fetch_content_integration/test_micm_box_model.F90 index 0552b7c8..b80a4af1 100644 --- a/fortran/test/fetch_content_integration/test_micm_box_model.F90 +++ b/fortran/test/fetch_content_integration/test_micm_box_model.F90 @@ -5,6 +5,7 @@ program test_micm_box_model use musica_util, only: error_t, string_t, mapping_t use musica_micm, only: micm_t, solver_stats_t + use musica_micm, only: Rosenbrock, RosenbrockStandardOrder implicit none @@ -16,6 +17,7 @@ subroutine box_model() character(len=256) :: config_path integer(c_int) :: solver_type + integer(c_int) :: num_grid_cells real(c_double), parameter :: GAS_CONSTANT = 8.31446261815324_c_double ! J mol-1 K-1 @@ -39,7 +41,8 @@ subroutine box_model() integer :: i config_path = "configs/analytical" - solver_type = 2 + solver_type = RosenbrockStandardOrder + num_grid_cells = 1 time_step = 200 temperature = 273.0 @@ -49,7 +52,7 @@ subroutine box_model() concentrations = (/ 1.0, 1.0, 1.0 /) write(*,*) "Creating MICM solver..." - micm => micm_t(config_path, solver_type, error) + micm => micm_t(config_path, solver_type, num_grid_cells, error) do i = 1, size( micm%species_ordering ) associate(the_mapping => micm%species_ordering(i)) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index 79184836..0613dce2 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -107,8 +107,9 @@ namespace musica /// @brief Create a MICM object by specifying solver type to use /// @param config_path Path to configuration file or directory containing configuration file /// @param solver_type Type of MICMSolver + /// @param num_grid_cells Number of grid cells /// @param error Error struct to indicate success or failure - MICM *CreateMicm(const char *config_path, MICMSolver solver_type, Error *error); + MICM *CreateMicm(const char *config_path, MICMSolver solver_type, int num_grid_cells, Error *error); void DeleteMicm(const MICM *micm, Error *error); void MicmSolve( MICM *micm, @@ -179,6 +180,13 @@ namespace musica solver_type_ = solver_type; } + /// @brief Set number of grid cells + /// @param num_grid_cells Number of grid cells + void SetNumGridCells(int num_grid_cells) + { + num_grid_cells_ = num_grid_cells; + } + /// @brief Get the ordering of species /// @param solver Pointer to solver /// @param error Error struct to indicate success or failure @@ -222,6 +230,7 @@ namespace musica std::unique_ptr rosenbrock_standard_; private: + int num_grid_cells_; std::unique_ptr solver_parameters_; }; diff --git a/python/test/test_analytical.py b/python/test/test_analytical.py index 92230a16..d446447f 100644 --- a/python/test/test_analytical.py +++ b/python/test/test_analytical.py @@ -5,13 +5,14 @@ class TestAnalyticalSimulation(unittest.TestCase): def test_simulation(self): + num_grid_cells = 1 time_step = 200.0 temperature = 272.5 pressure = 101253.3 GAS_CONSTANT = 8.31446261815324 air_density = pressure / (GAS_CONSTANT * temperature) - solver = musica.create_solver("configs/analytical", musica.micmsolver.rosenbrock) + solver = musica.create_solver("configs/analytical", musica.micmsolver.rosenbrock, num_grid_cells) rates = musica.user_defined_reaction_rates(solver) ordering = musica.species_ordering(solver) diff --git a/python/test/test_chapman.py b/python/test/test_chapman.py index 7d11eaef..fdfd2745 100644 --- a/python/test/test_chapman.py +++ b/python/test/test_chapman.py @@ -4,6 +4,7 @@ class TestChapman(unittest.TestCase): def test_micm_solve(self): + num_grid_cells = 1 time_step = 200.0 temperature = 272.5 pressure = 101253.3 @@ -11,7 +12,7 @@ def test_micm_solve(self): air_density = pressure / (GAS_CONSTANT * temperature) concentrations = [0.75, 0.4, 0.8, 0.01, 0.02] - solver = musica.create_solver("configs/chapman", musica.micmsolver.rosenbrock) + solver = musica.create_solver("configs/chapman", musica.micmsolver.rosenbrock, num_grid_cells) rate_constant_ordering = musica.user_defined_reaction_rates(solver) ordering = musica.species_ordering(solver) diff --git a/python/wrapper.cpp b/python/wrapper.cpp index 6a9608ad..8f828f19 100644 --- a/python/wrapper.cpp +++ b/python/wrapper.cpp @@ -20,10 +20,10 @@ PYBIND11_MODULE(musica, m) m.def( "create_solver", - [](const char *config_path, musica::MICMSolver solver_type) + [](const char *config_path, musica::MICMSolver solver_type, int num_grid_cells) { musica::Error error; - musica::MICM *micm = musica::CreateMicm(config_path, solver_type, &error); + musica::MICM *micm = musica::CreateMicm(config_path, solver_type, num_grid_cells, &error); if (!musica::IsSuccess(error)) { std::string message = "Error creating solver: " + std::string(error.message_.value_); diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 6b002d4c..ff278e29 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -21,10 +21,11 @@ namespace musica { - MICM *CreateMicm(const char *config_path, MICMSolver solver_type, Error *error) + MICM *CreateMicm(const char *config_path, MICMSolver solver_type, int num_grid_cells, Error *error) { DeleteError(error); MICM *micm = new MICM(); + micm->SetNumGridCells(num_grid_cells); if (solver_type == MICMSolver::Rosenbrock) { @@ -250,7 +251,7 @@ namespace musica micm::LuDecomposition>>(micm::RosenbrockSolverParameters::ThreeStageRosenbrockParameters()) .SetSystem(solver_parameters_->system_) .SetReactions(solver_parameters_->processes_) - .SetNumberOfGridCells(MICM_NUM_GRID_CELLS) + .SetNumberOfGridCells(num_grid_cells_) .SetIgnoreUnusedSpecies(true) .Build()); @@ -277,7 +278,7 @@ namespace musica micm::RosenbrockSolverParameters::ThreeStageRosenbrockParameters()) .SetSystem(solver_parameters_->system_) .SetReactions(solver_parameters_->processes_) - .SetNumberOfGridCells(MICM_NUM_GRID_CELLS) + .SetNumberOfGridCells(num_grid_cells_) .SetIgnoreUnusedSpecies(true) .Build()); @@ -309,14 +310,15 @@ namespace musica { micm::State state = solver->GetState(); - for (std::size_t i{}; i < MICM_NUM_GRID_CELLS; i++) + for (int cell{}; cell < num_grid_cells_; cell++) { - state.conditions_[i].temperature_ = temperature; - state.conditions_[i].pressure_ = pressure; - state.conditions_[i].air_density_ = air_density; + state.conditions_[cell].temperature_ = temperature; + state.conditions_[cell].pressure_ = pressure; + state.conditions_[cell].air_density_ = air_density; } - + state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); + state.custom_rate_parameters_.AsVector().assign( custom_rate_parameters, custom_rate_parameters + num_custom_rate_parameters); diff --git a/src/test/unit/micm/micm_c_api.cpp b/src/test/unit/micm/micm_c_api.cpp index 7a342ddd..638b7742 100644 --- a/src/test/unit/micm/micm_c_api.cpp +++ b/src/test/unit/micm/micm_c_api.cpp @@ -15,12 +15,13 @@ class MicmCApiTest : public ::testing::Test protected: MICM* micm; const char* config_path = "configs/chapman"; + int num_grid_cells = 1; void SetUp() override { micm = nullptr; Error error; - micm = CreateMicm(config_path, MICMSolver::Rosenbrock, &error); + micm = CreateMicm(config_path, MICMSolver::Rosenbrock, num_grid_cells, &error); ASSERT_TRUE(IsSuccess(error)); DeleteError(&error); @@ -38,8 +39,9 @@ class MicmCApiTest : public ::testing::Test // Test case for bad configuration file path TEST_F(MicmCApiTest, BadConfigurationFilePath) { + int num_grid_cells = 1; Error error = NoError(); - auto micm_bad_config = CreateMicm("bad config path", MICMSolver::Rosenbrock, &error); + auto micm_bad_config = CreateMicm("bad config path", MICMSolver::Rosenbrock, num_grid_cells, &error); ASSERT_EQ(micm_bad_config, nullptr); ASSERT_TRUE(IsError(error, MICM_ERROR_CATEGORY_CONFIGURATION, MICM_CONFIGURATION_ERROR_CODE_INVALID_FILE_PATH)); DeleteError(&error); @@ -49,8 +51,9 @@ TEST_F(MicmCApiTest, BadConfigurationFilePath) TEST_F(MicmCApiTest, BadSolverType) { short solver_type = 999; + int num_grid_cells = 1; Error error = NoError(); - auto micm_bad_solver_type = CreateMicm("configs/chapman", static_cast(solver_type), &error); + auto micm_bad_solver_type = CreateMicm("configs/chapman", static_cast(solver_type), num_grid_cells, &error); ASSERT_EQ(micm_bad_solver_type, nullptr); ASSERT_TRUE(IsError(error, MUSICA_ERROR_CATEGORY, MUSICA_ERROR_CODE_SOLVER_TYPE_NOT_FOUND)); DeleteError(&error); @@ -256,9 +259,10 @@ TEST_F(MicmCApiTest, SolveUsingVectorOrderedRosenbrock) // Test case for solving system using standard-ordered Rosenbrock solver TEST(RosenbrockStandardOrder, SolveUsingStandardOrderedRosenbrock) { - Error error; const char* config_path = "configs/chapman"; - MICM* micm = CreateMicm(config_path, MICMSolver::RosenbrockStandardOrder, &error); + int num_grid_cells = 1; + Error error; + MICM* micm = CreateMicm(config_path, MICMSolver::RosenbrockStandardOrder, num_grid_cells, &error); double time_step = 200.0; double temperature = 272.5; From 63bf31967982b278b784063e7ee4bbdd5ad9b5d0 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 10 Jul 2024 14:56:11 -0600 Subject: [PATCH 27/31] code clean up --- include/musica/micm.hpp | 3 --- src/CMakeLists.txt | 1 - src/micm/micm.cpp | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index 0613dce2..a7356f6e 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -23,9 +23,6 @@ #include #include -#ifndef MICM_NUM_GRID_CELLS - #define MICM_NUM_GRID_CELLS 1 -#endif #ifndef MICM_VECTOR_MATRIX_SIZE #define MICM_VECTOR_MATRIX_SIZE 1 #endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 18fce6a1..54a5f60f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,7 +17,6 @@ message (STATUS "CMake build configuration for ${PROJECT_NAME} (${CMAKE_BUILD_TY add_library(musica) add_library(musica::musica ALIAS musica) -target_compile_definitions(musica PUBLIC MICM_NUM_GRID_CELLS=${MUSICA_SET_MICM_NUM_GRID_CELLS}) target_compile_definitions(musica PUBLIC MICM_VECTOR_MATRIX_SIZE=${MUSICA_SET_MICM_VECTOR_MATRIX_SIZE}) # set the c++ standard for musica diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index ff278e29..dd5b804a 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -316,7 +316,7 @@ namespace musica state.conditions_[cell].pressure_ = pressure; state.conditions_[cell].air_density_ = air_density; } - + state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); state.custom_rate_parameters_.AsVector().assign( From 15ae98873dd828bf60c9f0b6ea2f826a8d90c39d Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 11 Jul 2024 13:36:10 -0600 Subject: [PATCH 28/31] specify enabled languages in top level cmake --- CMakeLists.txt | 2 +- cmake/dependencies.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 175f4b8b..7741ceee 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.21) # must be on the same line so that pyproject.toml can correctly identify the version -project(musica-distribution VERSION 0.7.0) +project(musica-distribution VERSION 0.7.0 LANGUAGES C CXX Fortran) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake) set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_MODULE_PATH}/SetDefaults.cmake) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index df84a956..0e614583 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -42,7 +42,7 @@ endif() ################################################################################ # OpenMP if(MUSICA_ENABLE_OPENMP) - find_package(OpenMP REQUIRED) + find_package(OpenMP REQUIRED COMPONENTS C CXX Fortran) endif() ################################################################################ From e53faf221a6d43bd1d64c5f59e2d3081842c7117 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 11 Jul 2024 14:20:51 -0600 Subject: [PATCH 29/31] comment out the tuvx openmp tests --- CMakeLists.txt | 1 + fortran/test/unit/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7741ceee..1e1fad9c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,7 @@ cmake_minimum_required(VERSION 3.21) # must be on the same line so that pyproject.toml can correctly identify the version +# project(musica-distribution VERSION 0.7.0) project(musica-distribution VERSION 0.7.0 LANGUAGES C CXX Fortran) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake) diff --git a/fortran/test/unit/CMakeLists.txt b/fortran/test/unit/CMakeLists.txt index 27b0de76..3674dd88 100644 --- a/fortran/test/unit/CMakeLists.txt +++ b/fortran/test/unit/CMakeLists.txt @@ -12,9 +12,9 @@ if (MUSICA_ENABLE_TUVX) create_standard_test_fortran(NAME connect_to_tuvx SOURCES tuvx.F90) create_standard_test_fortran(NAME tuvx_fortran_api SOURCES ../fetch_content_integration/test_tuvx_api.F90) - if (MUSICA_ENABLE_OPENMP) - create_standard_test_fortran(NAME connect_to_tuvx_openmp SOURCES tuvx_openmp.F90) - endif() + # if (MUSICA_ENABLE_OPENMP) + # create_standard_test_fortran(NAME connect_to_tuvx_openmp SOURCES tuvx_openmp.F90) + # endif() if (MUSICA_ENABLE_MPI) create_standard_test_fortran(NAME connect_to_tuvx_mpi SOURCES tuvx_mpi.F90) endif() From 1f548debde37b017ced9b760dc5d34c19418a26c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 11 Jul 2024 14:27:23 -0600 Subject: [PATCH 30/31] revert back --- CMakeLists.txt | 3 +-- fortran/test/unit/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e1fad9c..175f4b8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,7 @@ cmake_minimum_required(VERSION 3.21) # must be on the same line so that pyproject.toml can correctly identify the version -# project(musica-distribution VERSION 0.7.0) -project(musica-distribution VERSION 0.7.0 LANGUAGES C CXX Fortran) +project(musica-distribution VERSION 0.7.0) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake) set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_MODULE_PATH}/SetDefaults.cmake) diff --git a/fortran/test/unit/CMakeLists.txt b/fortran/test/unit/CMakeLists.txt index 3674dd88..27b0de76 100644 --- a/fortran/test/unit/CMakeLists.txt +++ b/fortran/test/unit/CMakeLists.txt @@ -12,9 +12,9 @@ if (MUSICA_ENABLE_TUVX) create_standard_test_fortran(NAME connect_to_tuvx SOURCES tuvx.F90) create_standard_test_fortran(NAME tuvx_fortran_api SOURCES ../fetch_content_integration/test_tuvx_api.F90) - # if (MUSICA_ENABLE_OPENMP) - # create_standard_test_fortran(NAME connect_to_tuvx_openmp SOURCES tuvx_openmp.F90) - # endif() + if (MUSICA_ENABLE_OPENMP) + create_standard_test_fortran(NAME connect_to_tuvx_openmp SOURCES tuvx_openmp.F90) + endif() if (MUSICA_ENABLE_MPI) create_standard_test_fortran(NAME connect_to_tuvx_mpi SOURCES tuvx_mpi.F90) endif() From 830b4266447db5b1d4393351cd25dca7b45b3717 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 11 Jul 2024 14:35:53 -0600 Subject: [PATCH 31/31] revert back --- cmake/dependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 0e614583..df84a956 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -42,7 +42,7 @@ endif() ################################################################################ # OpenMP if(MUSICA_ENABLE_OPENMP) - find_package(OpenMP REQUIRED COMPONENTS C CXX Fortran) + find_package(OpenMP REQUIRED) endif() ################################################################################