diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c70d6ee4..2de74426 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,6 +14,17 @@ jobs: run: docker build -t musica . - name: run tests in container run: docker run --name test-container -t musica bash -c 'make test' + build_test_connections_without_micm: + runs-on: ubuntu-latest + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: build Docker image + run: docker build -t musica -f Dockerfile.no_micm . + - name: run tests in container + run: docker run --name test-container -t musica bash -c 'make test' build_test_connections_with_openmp: runs-on: ubuntu-latest if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name @@ -47,7 +58,21 @@ jobs: run: docker build -t musica-mpi-openmp -f Dockerfile.mpi_openmp . - name: run tests in container run: docker run --name test-container -t musica-mpi-openmp bash -c 'make test' - build_test_connections_musica-fortran: + # build_test_connections_musica-fortran: + # runs-on: ubuntu-latest + # if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + # steps: + # - name: delete unnessary tools to free up space + # run: rm -rf /opt/hostedtoolcache + + # - uses: actions/checkout@v2 + # with: + # submodules: recursive + # - name: build Docker image + # run: docker build -t musica-fortran -f Dockerfile.fortran . + # - name: run tests in container + # run: docker run --name test-container -t musica-fortran bash -c 'make test' + build_test_connections_musica-fortran-same-compiler: runs-on: ubuntu-latest if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name steps: @@ -58,6 +83,6 @@ jobs: with: submodules: recursive - name: build Docker image - run: docker build -t musica-fortran -f Dockerfile.fortran . + run: docker build -t musica-fortran-ubuntu -f Dockerfile.fortran-ubuntu . - name: run tests in container - run: docker run --name test-container -t musica-fortran bash -c 'make test' + run: docker run --name test-container -t musica-fortran-ubuntu bash -c 'make test' diff --git a/CMakeLists.txt b/CMakeLists.txt index b4184e79..def7209a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.21) project( musica - VERSION 0.4.0 + VERSION 0.5.0 LANGUAGES Fortran CXX C ) @@ -54,6 +54,14 @@ include(GNUInstallDirs) set(INSTALL_PREFIX "musica-${PROJECT_VERSION}") set(INSTALL_MOD_DIR "${INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}") +# MUSICA library components +if(ENABLE_TUVX) + add_definitions(-DMUSICA_USE_TUVX) +endif() +if(ENABLE_MICM) + add_definitions(-DMUSICA_USE_MICM) +endif() + # MPI if(ENABLE_MPI) add_definitions(-DMUSICA_USE_MPI) diff --git a/Dockerfile b/Dockerfile index 7879439b..67bc8b20 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,6 +9,7 @@ RUN dnf -y update \ lcov \ make \ netcdf-fortran-devel \ + json-devel \ valgrind \ && dnf clean all @@ -35,5 +36,5 @@ RUN cd musica \ -D ENABLE_TESTS=ON \ && cd build \ && make install -j 8 - + WORKDIR musica/build diff --git a/Dockerfile.fortran b/Dockerfile.fortran index 73b196cd..fd4f23b0 100644 --- a/Dockerfile.fortran +++ b/Dockerfile.fortran @@ -9,6 +9,7 @@ RUN apt update \ libcurl4-openssl-dev \ libhdf5-dev \ m4 \ + nlohmann-json3-dev \ vim \ zlib1g-dev \ git \ @@ -44,6 +45,7 @@ RUN cd musica \ && cmake -S . \ -B build \ -D ENABLE_TESTS=ON \ + -D ENABLE_TUVX=OFF \ && cd build \ && make install -j 8 @@ -67,4 +69,7 @@ RUN cd musica/musica-fortran/test \ && cmake .. \ && make +RUN cd musica/musica-fortran/test \ + && cp -r configs/chapman ./build/chapman + WORKDIR musica/musica-fortran/test/build \ No newline at end of file diff --git a/Dockerfile.fortran-ubuntu b/Dockerfile.fortran-ubuntu new file mode 100644 index 00000000..3c4f6b00 --- /dev/null +++ b/Dockerfile.fortran-ubuntu @@ -0,0 +1,60 @@ +FROM ubuntu:22.04 + +RUN apt update \ + && apt -y install \ + cmake \ + cmake-curses-gui \ + curl \ + libcurl4-openssl-dev \ + libhdf5-dev \ + m4 \ + nlohmann-json3-dev \ + vim \ + zlib1g-dev \ + git \ + lcov \ + make \ + libnetcdff-dev \ + valgrind \ + gcc \ + gfortran \ + g++ \ + && apt clean + +# Set environment variables to install MUSICA using gcc +ENV FC=gfortran +ENV FFLAGS="-I/usr/include/" + +# Install json-fortran for gnu version +RUN curl -LO https://github.com/jacobwilliams/json-fortran/archive/8.2.0.tar.gz \ + && tar -zxvf 8.2.0.tar.gz \ + && cd json-fortran-8.2.0 \ + && mkdir build \ + && cd build \ + && cmake -D SKIP_DOC_GEN:BOOL=TRUE .. \ + && make install + +# Copy the musica code +COPY . musica + +# Set json-fortran variable to install MUSICA using gcc +ENV JSON_FORTRAN_HOME="/usr/local/jsonfortran-gnu-8.2.0" + +# Build and install MUSICA +RUN cd musica \ + && cmake -S . \ + -B build \ + -D ENABLE_TESTS=ON \ + -D ENABLE_TUVX=OFF \ + && cd build \ + && make install -j 8 + +RUN cd musica/musica-fortran/test \ + && mkdir build && cd build \ + && cmake .. \ + && make + +RUN cd musica/musica-fortran/test \ + && cp -r configs/chapman ./build/chapman + +WORKDIR musica/musica-fortran/test/build \ No newline at end of file diff --git a/Dockerfile.mpi b/Dockerfile.mpi index bccbf9ae..8590801a 100644 --- a/Dockerfile.mpi +++ b/Dockerfile.mpi @@ -18,6 +18,7 @@ RUN sudo dnf -y install \ make \ netcdf-fortran-devel \ openmpi-devel \ + json-devel \ valgrind-openmpi \ && dnf clean all diff --git a/Dockerfile.mpi_openmp b/Dockerfile.mpi_openmp index a751b1cd..875f0d4f 100644 --- a/Dockerfile.mpi_openmp +++ b/Dockerfile.mpi_openmp @@ -17,6 +17,7 @@ RUN sudo dnf -y install \ lcov \ make \ netcdf-fortran-devel \ + json-devel \ openmpi-devel \ valgrind-openmpi \ && dnf clean all diff --git a/Dockerfile.no_micm b/Dockerfile.no_micm new file mode 100644 index 00000000..e8a98cc9 --- /dev/null +++ b/Dockerfile.no_micm @@ -0,0 +1,41 @@ +FROM fedora:35 + +RUN dnf -y update \ + && dnf -y install \ + cmake \ + gcc-c++ \ + gcc-gfortran \ + git \ + lcov \ + make \ + netcdf-fortran-devel \ + valgrind \ + && dnf clean all + +# Install json-fortran +RUN curl -LO https://github.com/jacobwilliams/json-fortran/archive/8.2.0.tar.gz \ + && tar -zxvf 8.2.0.tar.gz \ + && cd json-fortran-8.2.0 \ + && mkdir build \ + && cd build \ + && cmake -D SKIP_DOC_GEN:BOOL=TRUE .. \ + && make install + +# Set environment variables +ENV FC=gfortran +ENV JSON_FORTRAN_HOME="/usr/local/jsonfortran-gnu-8.2.0" + +# Copy the musica code +COPY . musica + +# Build +RUN cd musica \ + && cmake -S . \ + -B build \ + -D ENABLE_TESTS=ON \ + -D ENABLE_TUVX=ON \ + -D ENABLE_MICM=OFF \ + && cd build \ + && make install -j 8 + +WORKDIR musica/build diff --git a/Dockerfile.openmp b/Dockerfile.openmp index b73afd2e..cb21aca2 100644 --- a/Dockerfile.openmp +++ b/Dockerfile.openmp @@ -17,6 +17,7 @@ RUN sudo dnf -y install \ lcov \ make \ netcdf-fortran-devel \ + json-devel \ openmpi-devel \ valgrind-openmpi \ && dnf clean all diff --git a/README.md b/README.md index 378815e6..4fcc82f2 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # MUSICA +[![GitHub Releases](https://img.shields.io/github/release/NCAR/musica.svg)](https://github.com/NCAR/musica/releases) [![License](https://img.shields.io/github/license/NCAR/musica.svg)](https://github.com/NCAR/musica/blob/main/LICENSE) [![CI Status](https://github.com/NCAR/musica/actions/workflows/test.yml/badge.svg)](https://github.com/NCAR/musica/actions/workflows/test.yml) @@ -60,4 +61,4 @@ MUSICAv0 description and evaluation: eprint = {https://agupubs.onlinelibrary.wiley.com/doi/pdf/10.1029/2021MS002889}, year = {2022} } -``` \ No newline at end of file +``` diff --git a/lib/micm b/lib/micm index 48d3ed14..b36c5f8c 160000 --- a/lib/micm +++ b/lib/micm @@ -1 +1 @@ -Subproject commit 48d3ed14927e65314e5028590a049d6bb4074591 +Subproject commit b36c5f8c94d8e3db7fa93f8690935fffb1466f6e diff --git a/lib/musica-core b/lib/musica-core index a0b2da06..d5bdc303 160000 --- a/lib/musica-core +++ b/lib/musica-core @@ -1 +1 @@ -Subproject commit a0b2da0681a5f7f24721bf7b9997e297cd88f5be +Subproject commit d5bdc303fe9afbae8f7585a11bcb660534b97f23 diff --git a/lib/tuv-x b/lib/tuv-x index aa1fef55..daba6579 160000 --- a/lib/tuv-x +++ b/lib/tuv-x @@ -1 +1 @@ -Subproject commit aa1fef550320e2fb3fbd480c11cd473d97cbc02a +Subproject commit daba657958baa3a499ae7fa470f3df0073655c67 diff --git a/musica-fortran/CMakeLists.txt b/musica-fortran/CMakeLists.txt index 1c7c7a92..a6f94c6e 100644 --- a/musica-fortran/CMakeLists.txt +++ b/musica-fortran/CMakeLists.txt @@ -28,7 +28,7 @@ find_package(PkgConfig REQUIRED) pkg_check_modules(netcdff IMPORTED_TARGET REQUIRED netcdf-fortran) # Find MUSICA package -find_package(musica 0.3.0 REQUIRED) +find_package(musica 0.5.0 REQUIRED) target_link_libraries(musica-fortran PUBLIC diff --git a/musica-fortran/src/micm/CMakeLists.txt b/musica-fortran/src/micm/CMakeLists.txt index 7e743d8f..a6fc43b4 100644 --- a/musica-fortran/src/micm/CMakeLists.txt +++ b/musica-fortran/src/micm/CMakeLists.txt @@ -1,4 +1,4 @@ target_sources(musica-fortran PUBLIC - interface.F90 + micm_mod.F90 ) \ No newline at end of file diff --git a/musica-fortran/src/micm/interface.F90 b/musica-fortran/src/micm/interface.F90 deleted file mode 100644 index 355f69c9..00000000 --- a/musica-fortran/src/micm/interface.F90 +++ /dev/null @@ -1,22 +0,0 @@ -module micm - use iso_c_binding - - implicit none - - interface - - type(c_funptr) function get_solver(filepath) bind(c) - import :: c_char, c_funptr - character(len=*, kind=c_char), dimension(*), intent(in) :: filepath - end function get_solver - - subroutine solver(state, state_size, time_step) bind(c) - import :: c_ptr, c_double, c_int64_t - real(c_double), dimension(*) :: state - integer(c_int64_t), value :: state_size - integer(c_int64_t), value :: time_step - end subroutine - - end interface - -end module micm \ No newline at end of file diff --git a/musica-fortran/src/micm/micm_c_def.F90 b/musica-fortran/src/micm/micm_c_def.F90 new file mode 100644 index 00000000..107ddfe4 --- /dev/null +++ b/musica-fortran/src/micm/micm_c_def.F90 @@ -0,0 +1,32 @@ +interface + function create_micm_c(config_path) bind(C, name="create_micm") + use iso_c_binding + implicit none + type(c_ptr) :: create_micm_c + character(len=1, kind=C_CHAR), intent(in) :: config_path(*) + end function + + subroutine delete_micm_c(micm_t) bind(C, name="delete_micm") + use iso_c_binding + implicit none + type(c_ptr), value :: micm_t + end subroutine + + function micm_create_solver_c(micm_t) bind(C, name="micm_create_solver") + use iso_c_binding + implicit none + integer(c_int) :: micm_create_solver_c ! TODO(jiwon) return value? + type(c_ptr), intent(in), value :: micm_t + end function + + subroutine micm_solve_c(micm_t, temperature, pressure, time_step, concentrations, num_concentrations) bind(C, name="micm_solve") + use iso_c_binding + implicit none + type(c_ptr), intent(in), value :: micm_t + real(c_double), value :: temperature + real(c_double), value :: pressure + real(c_double), value :: time_step + real(c_double), dimension(*), intent(inout) :: concentrations + integer(c_size_t), value, intent(in) :: num_concentrations + end subroutine +end interface diff --git a/musica-fortran/src/micm/micm_mod.F90 b/musica-fortran/src/micm/micm_mod.F90 new file mode 100644 index 00000000..6484b22d --- /dev/null +++ b/musica-fortran/src/micm/micm_mod.F90 @@ -0,0 +1,60 @@ +module micm_mod + use iso_c_binding + implicit none + + private + public :: micm_t + + include "micm_c_def.F90" + + type micm_t + private + type(c_ptr) :: ptr + contains + procedure :: create_solver => micm_create_solver + procedure :: solve => micm_solve + final :: delete_micm + end type + + interface micm_t + procedure create_micm + end interface + +contains + function create_micm(config_path) + type(micm_t) :: create_micm + character(len=*), intent(in) :: config_path + character(len=1, kind=C_CHAR) :: c_config_path(len_trim(config_path) + 1) + integer :: N, i + + ! Converting Fortran string to C string + N = len_trim(config_path) + do i = 1, N + c_config_path(i) = config_path(i:i) + end do + c_config_path(N + 1) = C_NULL_CHAR + + create_micm%ptr = create_micm_c(c_config_path) + end function + + subroutine delete_micm(this) + type(micm_t) :: this + call delete_micm_c(this%ptr) + end subroutine + + integer function micm_create_solver(this) + class(micm_t), intent(in) :: this + micm_create_solver = micm_create_solver_c(this%ptr) + end function + + subroutine micm_solve(this, temperature, pressure, time_step, concentrations, num_concentrations) + class(micm_t), intent(in) :: this + real(c_double), intent(in) :: temperature + real(c_double), intent(in) :: pressure + real(c_double), intent(in) :: time_step + real(c_double), dimension(*), intent(inout) :: concentrations + integer(c_size_t), intent(in) :: num_concentrations + call micm_solve_c(this%ptr, temperature, pressure, time_step, concentrations, num_concentrations) + end subroutine + +end module \ No newline at end of file diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt index 088216ef..d62e1234 100644 --- a/musica-fortran/test/CMakeLists.txt +++ b/musica-fortran/test/CMakeLists.txt @@ -12,10 +12,11 @@ include(FetchContent) set(USE_MUSICA OFF) set(USE_MUSICA_FORTRAN ON) +set(ENABLE_TUVX OFF) FetchContent_Declare(musica GIT_REPOSITORY https://github.com/NCAR/musica.git - GIT_TAG bf1b77b ## todo: jiwon update this + GIT_TAG 264396b # TODO(jiwon) - update the tag ) FetchContent_MakeAvailable(musica) diff --git a/musica-fortran/test/configs/chapman/config.json b/musica-fortran/test/configs/chapman/config.json new file mode 100644 index 00000000..04d0ef28 --- /dev/null +++ b/musica-fortran/test/configs/chapman/config.json @@ -0,0 +1,6 @@ +{ + "camp-files": [ + "species.json", + "reactions.json" + ] +} diff --git a/musica-fortran/test/configs/chapman/reactions.json b/musica-fortran/test/configs/chapman/reactions.json new file mode 100644 index 00000000..679593f9 --- /dev/null +++ b/musica-fortran/test/configs/chapman/reactions.json @@ -0,0 +1,97 @@ +{ + "camp-data": [ + { + "name": "Chapman", + "type": "MECHANISM", + "reactions": [ + { + "type": "PHOTOLYSIS", + "reactants": { + "O2": {} + }, + "products": { + "O": { + "yield": 2.0 + } + }, + "MUSICA name": "R1" + }, + { + "type": "ARRHENIUS", + "A": 8.018e-17, + "reactants": { + "O": {}, + "O2": {} + }, + "products": { + "O3": {} + }, + "MUSICA name": "R2" + }, + { + "type": "PHOTOLYSIS", + "reactants": { + "O3": {} + }, + "products": { + "O": {}, + "O2": {} + }, + "MUSICA name": "R3" + }, + { + "type": "ARRHENIUS", + "A": 1.576e-15, + "reactants": { + "O": {}, + "O3": {} + }, + "products": { + "O2": { + "yield": 2.0 + } + }, + "MUSICA name": "R4" + }, + { + "type": "PHOTOLYSIS", + "reactants": { + "O3": {} + }, + "products": { + "O1D": {}, + "O2": {} + }, + "MUSICA name": "R5" + }, + { + "type": "ARRHENIUS", + "A": 7.11e-11, + "reactants": { + "O1D": {}, + "M": {} + }, + "products": { + "O": {}, + "M": {} + }, + "MUSICA name": "R6" + }, + { + "type": "ARRHENIUS", + "A": 1.2e-10, + "reactants": { + "O1D": {}, + "O3": {} + }, + "products": { + "O2": { + "yield": 2.0 + } + }, + "MUSICA name": "R7" + } + ] + } + ] +} \ No newline at end of file diff --git a/musica-fortran/test/configs/chapman/species.json b/musica-fortran/test/configs/chapman/species.json new file mode 100644 index 00000000..c962907f --- /dev/null +++ b/musica-fortran/test/configs/chapman/species.json @@ -0,0 +1,29 @@ +{ + "camp-data": [ + { + "name": "M", + "type": "CHEM_SPEC", + "tracer type": "CONSTANT" + }, + { + "name": "O2", + "type": "CHEM_SPEC", + "tracer type": "CONSTANT" + }, + { + "name": "O", + "type": "CHEM_SPEC", + "absolute tolerance": 1e-12 + }, + { + "name": "O1D", + "type": "CHEM_SPEC", + "absolute tolerance": 1e-12 + }, + { + "name": "O3", + "type": "CHEM_SPEC", + "absolute tolerance": 1e-12 + } + ] +} \ No newline at end of file diff --git a/musica-fortran/test/test_musica_api.F90 b/musica-fortran/test/test_musica_api.F90 index 8ec61ac8..5cbc562a 100644 --- a/musica-fortran/test/test_musica_api.F90 +++ b/musica-fortran/test/test_musica_api.F90 @@ -1,10 +1,42 @@ -program test_musica_api - use iso_c_binding - use micm +program test + use iso_c_binding + use micm_mod + implicit none + type(micm_t) :: m - character(len=5, kind=c_char) :: c_filepath - type(c_funptr) :: csolver_func_pointer - c_filepath = 'asdf' - csolver_func_pointer = get_solver(c_filepath) + real(c_double) :: temperature + real(c_double) :: pressure + real(c_double) :: time_step + real(c_double), dimension(5) :: concentrations + integer(c_size_t) :: num_concentrations + integer :: errcode -end program test_musica_api + temperature = 10d0 + pressure = 20d0 + time_step = 1d0 + concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) + num_concentrations = 5 + + write(*,*) " * [Fortran] Creating MICM" + m = micm_t("chapman") + + write(*,*) " * [Fortran] Creating solver" + errcode = m%create_solver() + + if (errcode == 1) then + write(*,*) " * [Fortran] Failed in creating solver" + stop 3 + else + write(*,*) " * [Fortran] Initial temp", temperature + write(*,*) " * [Fortran] Initial pressure", pressure + write(*,*) " * [Fortran] Initial time_step", time_step + write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations + write(*,*) " * [Fortran] Initial concentrations", concentrations + + write(*,*) " * [Fortran] Solving starts..." + call m%solve(temperature, pressure, time_step, concentrations, num_concentrations) + + write(*,*) " * [Fortran] After solving, concentrations", concentrations + endif + +end program \ No newline at end of file diff --git a/musica/CMakeLists.txt b/musica/CMakeLists.txt index cb556df0..e0823902 100644 --- a/musica/CMakeLists.txt +++ b/musica/CMakeLists.txt @@ -89,7 +89,7 @@ target_sources(musica add_subdirectory(${PROJECT_SOURCE_DIR}/lib/musica-core/src ${MUSICA_LIB_DIR}/musica-core/src) -# #################### +#################### # TUV-x if (ENABLE_TUVX) add_definitions(-DMUSICA_USE_TUVX) @@ -122,7 +122,7 @@ if (ENABLE_TUVX) ) endif() -# #################### +#################### # MICM if (ENABLE_MICM) add_definitions(-DMUSICA_USE_MICM) @@ -136,7 +136,7 @@ if (ENABLE_MICM) install( DIRECTORY - ${PROJECT_SOURCE_DIR}/lib/micm/include/micm + ${PROJECT_SOURCE_DIR}/lib/micm/include DESTINATION ${INSTALL_MOD_DIR} ) diff --git a/musica/include/micm/interface.hpp b/musica/include/micm/interface.hpp deleted file mode 100644 index 74c9bd40..00000000 --- a/musica/include/micm/interface.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#include - -#include -#include -#include - -class MICM { - public: - micm::RosenbrockSolver* solver_; -}; - -#ifdef __cplusplus - extern "C" - { -#endif - - typedef void (*FuncPtr)(double[], int64_t, int64_t); - - FuncPtr get_solver(char filepath[]); - -#ifdef __cplusplus - } // extern "C" -#endif - diff --git a/musica/include/micm/micm.hpp b/musica/include/micm/micm.hpp new file mode 100644 index 00000000..cf55cbde --- /dev/null +++ b/musica/include/micm/micm.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include +#include +#include + + +class MICM +{ +public: + MICM(const std::string& config_path); + ~MICM(); + + // TODO(jiwon): can return type indicate error? + int create_solver(); + void solve(double temperature, double pressure, double time_step, double*& concentrations, size_t num_concentrations); + +private: + static constexpr size_t NUM_GRID_CELLS = 1; // TODO(jiwon) + + std::string config_path_; + + // TODO(jiwon) - currently hard coded + std::vector v_concentrations_; + + // TODO(jiwon) - currently hard coded + template + using Vector1MatrixParam = micm::VectorMatrix; + template + using Vector1SparseMatrixParam = micm::SparseMatrix>; + typedef micm::RosenbrockSolver VectorRosenbrockSolver; + VectorRosenbrockSolver* solver_; +}; + diff --git a/musica/include/micm/micm_c.h b/musica/include/micm/micm_c.h new file mode 100644 index 00000000..d0c7c213 --- /dev/null +++ b/musica/include/micm/micm_c.h @@ -0,0 +1,18 @@ +#include + +#ifdef __cplusplus +extern "C" { + class MICM; + typedef MICM Micm; +#endif + +Micm* create_micm(const char* config_path); +void delete_micm(const Micm* micm); +int micm_create_solver(Micm* micm); +void micm_solve(Micm* micm, double temperature, double pressure, double time_step, + double* concentrations, size_t num_concentrations); + +#ifdef __cplusplus +} +#endif + diff --git a/musica/src/CMakeLists.txt b/musica/src/CMakeLists.txt index 752e230b..585b6731 100644 --- a/musica/src/CMakeLists.txt +++ b/musica/src/CMakeLists.txt @@ -7,4 +7,6 @@ target_sources(musica ${CMAKE_BINARY_DIR}/version.c ) -add_subdirectory(micm) \ No newline at end of file +if(ENABLE_MICM) + add_subdirectory(micm) +endif() \ No newline at end of file diff --git a/musica/src/micm/CMakeLists.txt b/musica/src/micm/CMakeLists.txt index 964ff510..bf1ab6d6 100644 --- a/musica/src/micm/CMakeLists.txt +++ b/musica/src/micm/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(musica PRIVATE - interface.cpp + micm_c_api.cpp + micm.cpp ) \ No newline at end of file diff --git a/musica/src/micm/interface.cpp b/musica/src/micm/interface.cpp deleted file mode 100644 index 4ec80500..00000000 --- a/musica/src/micm/interface.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include - -#include - -// assumes that photo_rates, matches order in c++ already -void fortran_solve(void *micm_address, double time_start, double time_end, double *concentrations, double temperature, double pressure, double *photo_rates) -{ - // MICM *micm = static_cast(micm_address); - // micm::State state = micm->solver_->GetState(); - - // for (auto param : state.custom_rate_parameters_[0]) - // { - // param = *(photo_rates++); - // } - // state.conditions_[0].pressure_ = pressure; - // state.conditions_[0].temperature_ = temperature; - - // auto result = micm->solver_->Solve(time_start, time_end, state); -} - -void solver( - double state[], // NOLINT(misc-unused-parameters,cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) - int64_t state_size, - int64_t - timestep) -{ - std::cout << "state size: " << state_size << std::endl; - std::cout << "timestep: " << timestep << std::endl; - - for (int64_t i{}; i < state_size; ++i) - { - std::cout << "state[" << i << "] = " << state[i] << std::endl; - } -} - -FuncPtr get_solver( - char filepath[]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) -{ - std::cout << "file path: " << filepath << "\n"; - return &solver; -} \ No newline at end of file diff --git a/musica/src/micm/micm.cpp b/musica/src/micm/micm.cpp new file mode 100644 index 00000000..838948d8 --- /dev/null +++ b/musica/src/micm/micm.cpp @@ -0,0 +1,62 @@ +#include + +#include "../../include/micm/micm.hpp" // TODO(jiwon) relative include path? +#include + + +MICM::MICM(const std::string& config_path) + : config_path_(config_path), + solver_(nullptr) + {} + +MICM::~MICM() +{ + delete solver_; +} + +int MICM::create_solver() +{ + int faliure = 0; // TODO(jiwon): can we specifiy error type with int? + + // read and parse the config + micm::SolverConfig solver_config; + micm::ConfigParseStatus status = solver_config.ReadAndParse(config_path_); + micm::SolverParameters solver_params = solver_config.GetSolverParams(); + + if (status == micm::ConfigParseStatus::Success) + { + auto params = micm::RosenbrockSolverParameters::three_stage_rosenbrock_parameters(NUM_GRID_CELLS); + params.reorder_state_ = false; + solver_ = new VectorRosenbrockSolver{solver_params.system_, + solver_params.processes_, + params}; + } + else + { + std::cout << " * [C++] Failed creating solver" << std::endl; + faliure = 1; + } + + return faliure; +} + +void MICM::solve(double temperature, double pressure, double time_step, double*& concentrations, size_t num_concentrations) +{ + micm::State state = solver_->GetState(); + + for(size_t i{}; i < NUM_GRID_CELLS; ++i) { + state.conditions_[i].temperature_ = temperature; + state.conditions_[i].pressure_ = pressure; + } + + v_concentrations_.assign(concentrations, concentrations + num_concentrations); + state.variables_[0] = v_concentrations_; + + auto result = solver_->Solve(time_step, state); + + v_concentrations_ = result.result_.AsVector(); + for (int i=0; icreate_solver(); +} + +void micm_solve(Micm* micm, double temperature, double pressure, double time_step, double* concentrations, size_t num_concentrations) +{ + micm->solve(temperature, pressure, time_step, concentrations, num_concentrations); +} \ No newline at end of file