From a98246d8366e496e13512988ded316882f3c4022 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 3 Nov 2023 17:48:46 -0600 Subject: [PATCH 01/24] update micm interface for atm physics --- .dockerignore | 3 + .github/workflows/test.yml | 14 ++++ Dockerfile.fortran-ubuntu | 69 +++++++++++++++++++ musica-fortran/src/micm/CMakeLists.txt | 2 +- .../src/micm/{micm_mod.F90 => micm_core.F90} | 41 +++++++---- musica-fortran/test/test_musica_api.F90 | 18 ++--- 6 files changed, 126 insertions(+), 21 deletions(-) create mode 100644 Dockerfile.fortran-ubuntu rename musica-fortran/src/micm/{micm_mod.F90 => micm_core.F90} (72%) diff --git a/.dockerignore b/.dockerignore index b35cbab0..97befec2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,8 +4,11 @@ # add things to copy !CMakeLists.txt !Dockerfile +!Dockerfile.fortran +!Dockerfile.fortran-ubuntu !Dockerfile.mpi !Dockerfile.mpi_openmp +!Dockerfile.no_micm !Dockerfile.openmp !musica !musica-fortran diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f80a606b..58ec7910 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -72,3 +72,17 @@ jobs: 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-ubuntu: + 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-ubuntu -f Dockerfile.fortran-ubuntu . + - name: run tests in container + run: docker run --name test-container -t musica-fortran-ubuntu bash -c 'make test' \ No newline at end of file diff --git a/Dockerfile.fortran-ubuntu b/Dockerfile.fortran-ubuntu new file mode 100644 index 00000000..a5e65faa --- /dev/null +++ b/Dockerfile.fortran-ubuntu @@ -0,0 +1,69 @@ +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 + +# Install json-fortran for intel version +RUN cd json-fortran-8.2.0 \ + && mkdir build-intel \ + && cd build-intel \ + && cmake -D SKIP_DOC_GEN:BOOL=TRUE .. \ + && make install + + +RUN cd musica/musica-fortran/test \ + && mkdir build && cd build \ + && cmake .. \ + && make + +RUN cd musica/musica-fortran/test \ + && cp -r micm_config ./build/micm_config + +WORKDIR musica/musica-fortran/test/build \ No newline at end of file diff --git a/musica-fortran/src/micm/CMakeLists.txt b/musica-fortran/src/micm/CMakeLists.txt index a6fc43b4..39634b78 100644 --- a/musica-fortran/src/micm/CMakeLists.txt +++ b/musica-fortran/src/micm/CMakeLists.txt @@ -1,4 +1,4 @@ target_sources(musica-fortran PUBLIC - micm_mod.F90 + micm_core.F90 ) \ No newline at end of file diff --git a/musica-fortran/src/micm/micm_mod.F90 b/musica-fortran/src/micm/micm_core.F90 similarity index 72% rename from musica-fortran/src/micm/micm_mod.F90 rename to musica-fortran/src/micm/micm_core.F90 index fbed7551..e8c9e742 100644 --- a/musica-fortran/src/micm/micm_mod.F90 +++ b/musica-fortran/src/micm/micm_core.F90 @@ -1,5 +1,8 @@ -module micm +module micm_core + ! Top-level MICM interface + use iso_c_binding + implicit none private @@ -7,22 +10,30 @@ module micm include "micm_c_def.F90" - type micm_t + type :: micm_t + ! The micm_t class defines the API private type(c_ptr) :: ptr contains + ! Creates solver from configure file procedure :: create_solver => micm_create_solver + ! Solves chemical system procedure :: solve => micm_solve - final :: delete_micm - end type + ! Deallocates micm instance + final :: finalize + end type micm_t interface micm_t procedure create_micm - end interface + end interface micm_t contains + function create_micm(config_path) + ! Constructor of micm objects + 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 @@ -35,17 +46,22 @@ function create_micm(config_path) c_config_path(N + 1) = C_NULL_CHAR create_micm%ptr = create_micm_c(c_config_path) - end function + + return - subroutine delete_micm(this) - type(micm_t) :: this + end function create_micm + + subroutine finalize(this) + type(micm_t), intent(inout) :: this call delete_micm_c(this%ptr) - end subroutine + + end subroutine finalize integer function micm_create_solver(this) class(micm_t), intent(in) :: this micm_create_solver = micm_create_solver_c(this%ptr) - end function + + end function micm_create_solver subroutine micm_solve(this, temperature, pressure, time_step, concentrations, num_concentrations) class(micm_t), intent(in) :: this @@ -55,6 +71,7 @@ subroutine micm_solve(this, temperature, pressure, time_step, concentrations, nu 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 subroutine micm_solve -end module \ No newline at end of file +end module micm_core \ 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 8ee59b26..d78e7fa3 100644 --- a/musica-fortran/test/test_musica_api.F90 +++ b/musica-fortran/test/test_musica_api.F90 @@ -1,8 +1,10 @@ program test use iso_c_binding - use micm + use micm_core + implicit none - type(micm_t) :: m + + type(micm_t) :: micm real(c_double) :: temperature real(c_double) :: pressure @@ -17,10 +19,10 @@ program test num_concentrations = 10 write(*,*) " * [Fortran] Creating MICM" - m = micm_t("micm_config") + micm = micm_t("micm_config") write(*,*) " * [Fortran] Creating solver" - write(*,*) " * [Fortran] Solver creating status indicates ", m%create_solver(), " (1 is success, else failure) " + write(*,*) " * [Fortran] Solver creating status indicates ", micm%create_solver(), " (1 is success, else failure) " write(*,*) " * [Fortran] Initial temp", temperature write(*,*) " * [Fortran] Initial pressure", pressure @@ -28,11 +30,11 @@ program test write(*,*) " * [Fortran] Initial concentrations", concentrations write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations - write(*,*) " * [Fortran] Starting to solve" - call m%solve(temperature, pressure, time_step, concentrations, num_concentrations) + write(*,*) " * [Fortran] Solving starts.." + call micm%solve(temperature, pressure, time_step, concentrations, num_concentrations) + write(*,*) " * [Fortran] After solving, concentrations", concentrations - write(*,*) " * [Fortran] Calling destructor for MICM" - call m%delete + write(*,*) " * [Fortran] Exiting..." end program \ No newline at end of file From 430f27b7fe79016e7d7791353fb2d2ba2126073a Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 3 Nov 2023 17:58:54 -0600 Subject: [PATCH 02/24] update the tag --- musica-fortran/test/CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt index eb67929e..ad02d537 100644 --- a/musica-fortran/test/CMakeLists.txt +++ b/musica-fortran/test/CMakeLists.txt @@ -16,11 +16,16 @@ set(ENABLE_TUVX OFF) FetchContent_Declare(musica GIT_REPOSITORY https://github.com/NCAR/musica.git - GIT_TAG bad9756 # TODO(jiwon) - update the tag + GIT_TAG a98246d # TODO(jiwon) - update the tag ) FetchContent_MakeAvailable(musica) +# TODO(jiwon) - testing for dev +# add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/musica) +# message(${CMAKE_CURRENT_SOURCE_DIR}/../..) +# message(${CMAKE_CURRENT_BINARY_DIR}/musica) + ################################################################################ # Tests add_executable(test_musica_api test_musica_api.F90) From 602672061a73ff1343c560c15b2a5736d86673e6 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 3 Nov 2023 18:09:25 -0600 Subject: [PATCH 03/24] remove newline --- Dockerfile.fortran-ubuntu | 2 -- 1 file changed, 2 deletions(-) diff --git a/Dockerfile.fortran-ubuntu b/Dockerfile.fortran-ubuntu index a5e65faa..919e1362 100644 --- a/Dockerfile.fortran-ubuntu +++ b/Dockerfile.fortran-ubuntu @@ -21,7 +21,6 @@ RUN apt update \ g++ \ && apt clean - # Set environment variables to install MUSICA using gcc ENV FC=gfortran ENV FFLAGS="-I/usr/include/" @@ -57,7 +56,6 @@ RUN cd json-fortran-8.2.0 \ && cmake -D SKIP_DOC_GEN:BOOL=TRUE .. \ && make install - RUN cd musica/musica-fortran/test \ && mkdir build && cd build \ && cmake .. \ From 059433073a164eeb08feddc28c6e6d071371d4e6 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 17 Nov 2023 15:13:22 -0700 Subject: [PATCH 04/24] comment musica-fortra-intel --- .github/workflows/test.yml | 26 +++++++++---------- ...erfile.fortran => Dockerfile.fortran-intel | 0 2 files changed, 13 insertions(+), 13 deletions(-) rename Dockerfile.fortran => Dockerfile.fortran-intel (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 58ec7910..3f95ae65 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -58,20 +58,20 @@ 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: - 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 + # build_test_connections_musica-fortran-intel: + # 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' + # - uses: actions/checkout@v2 + # with: + # submodules: recursive + # - name: build Docker image + # run: docker build -t musica-fortran -f Dockerfile.fortran-intel . + # - name: run tests in container + # run: docker run --name test-container -t musica-fortran bash -c 'make test' build_test_connections_musica-fortran-ubuntu: 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 diff --git a/Dockerfile.fortran b/Dockerfile.fortran-intel similarity index 100% rename from Dockerfile.fortran rename to Dockerfile.fortran-intel From bfcd0b39bee3ae18264e12c7aa3a5ff03f5b5a4b Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Mon, 20 Nov 2023 18:29:46 -0700 Subject: [PATCH 05/24] remove unncessary install command --- Dockerfile.fortran-ubuntu | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Dockerfile.fortran-ubuntu b/Dockerfile.fortran-ubuntu index 919e1362..a3e297c6 100644 --- a/Dockerfile.fortran-ubuntu +++ b/Dockerfile.fortran-ubuntu @@ -49,13 +49,6 @@ RUN cd musica \ && cd build \ && make install -j 8 -# Install json-fortran for intel version -RUN cd json-fortran-8.2.0 \ - && mkdir build-intel \ - && cd build-intel \ - && cmake -D SKIP_DOC_GEN:BOOL=TRUE .. \ - && make install - RUN cd musica/musica-fortran/test \ && mkdir build && cd build \ && cmake .. \ From d833a187ca6b69b7ad53e0ef3ddd5b52aa41f6e0 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 21 Nov 2023 17:43:57 -0700 Subject: [PATCH 06/24] set up errorcode in creating solver for cam-sima --- musica-fortran/test/CMakeLists.txt | 38 ++++++++++++---- musica-fortran/test/test_musica_api.F90 | 27 ++++++----- .../test/test_musica_api_invalid_config.F90 | 45 +++++++++++++++++++ musica/src/micm/micm.cpp | 18 ++++---- 4 files changed, 98 insertions(+), 30 deletions(-) create mode 100644 musica-fortran/test/test_musica_api_invalid_config.F90 diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt index ad02d537..8a964656 100644 --- a/musica-fortran/test/CMakeLists.txt +++ b/musica-fortran/test/CMakeLists.txt @@ -14,20 +14,21 @@ 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 a98246d # TODO(jiwon) - update the tag -) +# TODO(jiwon) - original +# FetchContent_Declare(musica +# GIT_REPOSITORY https://github.com/NCAR/musica.git +# GIT_TAG a98246d # TODO(jiwon) - update the tag +# ) -FetchContent_MakeAvailable(musica) +# FetchContent_MakeAvailable(musica) # TODO(jiwon) - testing for dev -# add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/musica) -# message(${CMAKE_CURRENT_SOURCE_DIR}/../..) -# message(${CMAKE_CURRENT_BINARY_DIR}/musica) +add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/musica) +message(${CMAKE_CURRENT_SOURCE_DIR}/../..) +message(${CMAKE_CURRENT_BINARY_DIR}/musica) ################################################################################ -# Tests +# Test MUSICA API add_executable(test_musica_api test_musica_api.F90) target_link_libraries(test_musica_api @@ -44,4 +45,23 @@ enable_testing() add_test( NAME test_musica_api COMMAND $ +) + +# Test MUSICA API with invalid configuration files +add_executable(test_invalid_config test_musica_api_invalid_config.F90) + +target_link_libraries(test_invalid_config + PUBLIC + musica::musica-fortran +) + +set_target_properties(test_invalid_config +PROPERTIES +LINKER_LANGUAGE Fortran) + +enable_testing() + +add_test( + NAME test_invalid_config + COMMAND $ ) \ 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 d78e7fa3..a5117944 100644 --- a/musica-fortran/test/test_musica_api.F90 +++ b/musica-fortran/test/test_musica_api.F90 @@ -11,6 +11,7 @@ program test real(c_double) :: time_step real(c_double), dimension(10) :: concentrations integer(c_size_t) :: num_concentrations + integer :: errcode temperature = 10d0 pressure = 20d0 @@ -18,22 +19,26 @@ program test concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) num_concentrations = 10 - write(*,*) " * [Fortran] Creating MICM" + write(*,*) " * [Fortran] Creating MICM..." micm = micm_t("micm_config") - write(*,*) " * [Fortran] Creating solver" - write(*,*) " * [Fortran] Solver creating status indicates ", micm%create_solver(), " (1 is success, else failure) " + write(*,*) " * [Fortran] Creating solver..." + errcode = micm%create_solver() - write(*,*) " * [Fortran] Initial temp", temperature - write(*,*) " * [Fortran] Initial pressure", pressure - write(*,*) " * [Fortran] Initial time_step", time_step - write(*,*) " * [Fortran] Initial concentrations", concentrations - write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations + if (errcode == 1) then + write(*,*) " * [Fortran] Failed in creating solver" + else + write(*,*) " * [Fortran] Initial temp", temperature + write(*,*) " * [Fortran] Initial pressure", pressure + write(*,*) " * [Fortran] Initial time_step", time_step + write(*,*) " * [Fortran] Initial concentrations", concentrations + write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations - write(*,*) " * [Fortran] Solving starts.." - call micm%solve(temperature, pressure, time_step, concentrations, num_concentrations) + write(*,*) " * [Fortran] Solving starts..." + call micm%solve(temperature, pressure, time_step, concentrations, num_concentrations) - write(*,*) " * [Fortran] After solving, concentrations", concentrations + write(*,*) " * [Fortran] After solving, concentrations", concentrations + endif write(*,*) " * [Fortran] Exiting..." diff --git a/musica-fortran/test/test_musica_api_invalid_config.F90 b/musica-fortran/test/test_musica_api_invalid_config.F90 new file mode 100644 index 00000000..98e63ab5 --- /dev/null +++ b/musica-fortran/test/test_musica_api_invalid_config.F90 @@ -0,0 +1,45 @@ +program test + use iso_c_binding + use micm_core + + implicit none + + type(micm_t) :: micm + + real(c_double) :: temperature + real(c_double) :: pressure + real(c_double) :: time_step + real(c_double), dimension(10) :: concentrations + integer(c_size_t) :: num_concentrations + integer :: errcode + + temperature = 10d0 + pressure = 20d0 + time_step = 1d0 + concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) + num_concentrations = 10 + + write(*,*) " * [Fortran] Creating MICM..." + micm = micm_t("invalid_config") + + write(*,*) " * [Fortran] Creating solver..." + errcode = micm%create_solver() + + if (errcode == 1) then + write(*,*) " * [Fortran] Failed in creating solver" + else + write(*,*) " * [Fortran] Initial temp", temperature + write(*,*) " * [Fortran] Initial pressure", pressure + write(*,*) " * [Fortran] Initial time_step", time_step + write(*,*) " * [Fortran] Initial concentrations", concentrations + write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations + + write(*,*) " * [Fortran] Solving starts..." + call micm%solve(temperature, pressure, time_step, concentrations, num_concentrations) + + write(*,*) " * [Fortran] After solving, concentrations", concentrations + endif + + write(*,*) " * [Fortran] Exiting..." + +end program \ No newline at end of file diff --git a/musica/src/micm/micm.cpp b/musica/src/micm/micm.cpp index 4f391d68..1451f79b 100644 --- a/musica/src/micm/micm.cpp +++ b/musica/src/micm/micm.cpp @@ -1,4 +1,4 @@ -#include +#include #include "../../include/micm/micm.hpp" // TODO(jiwon) relative include path? #include @@ -10,34 +10,32 @@ MICM::MICM(const std::string& config_path) {} MICM::~MICM() -{ +{ delete solver_; } int MICM::create_solver() { - bool success = 1; // TODO(jiwon): can we specifiy error type with int? + int errcode = 0; // 0 means no error // 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) { + micm::SolverParameters solver_params = solver_config.GetSolverParams(); 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}; + params}; } - else + else { - std::cout << " * [C++] Failed creating solver" << std::endl; - success = 0; + errcode = 1; // 1 means that error occured } - - return success; + return errcode; } void MICM::solve(double temperature, double pressure, double time_step, double*& concentrations, size_t num_concentrations) From 5f4f4201895fefcfb1943b5a5c7b9d0029c1b99c Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Tue, 21 Nov 2023 18:02:56 -0700 Subject: [PATCH 07/24] update the tag --- musica-fortran/src/micm/micm_c_def.F90 | 2 +- musica-fortran/test/CMakeLists.txt | 17 ++++++++--------- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/musica-fortran/src/micm/micm_c_def.F90 b/musica-fortran/src/micm/micm_c_def.F90 index 107ddfe4..94e3762f 100644 --- a/musica-fortran/src/micm/micm_c_def.F90 +++ b/musica-fortran/src/micm/micm_c_def.F90 @@ -15,7 +15,7 @@ subroutine delete_micm_c(micm_t) bind(C, name="delete_micm") 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? + integer(c_int) :: micm_create_solver_c type(c_ptr), intent(in), value :: micm_t end function diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt index 8a964656..aca81666 100644 --- a/musica-fortran/test/CMakeLists.txt +++ b/musica-fortran/test/CMakeLists.txt @@ -14,18 +14,17 @@ set(USE_MUSICA OFF) set(USE_MUSICA_FORTRAN ON) set(ENABLE_TUVX OFF) -# TODO(jiwon) - original -# FetchContent_Declare(musica -# GIT_REPOSITORY https://github.com/NCAR/musica.git -# GIT_TAG a98246d # TODO(jiwon) - update the tag -# ) +FetchContent_Declare(musica + GIT_REPOSITORY https://github.com/NCAR/musica.git + GIT_TAG d833a18 # TODO(jiwon) - update the tag +) -# FetchContent_MakeAvailable(musica) +FetchContent_MakeAvailable(musica) # TODO(jiwon) - testing for dev -add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/musica) -message(${CMAKE_CURRENT_SOURCE_DIR}/../..) -message(${CMAKE_CURRENT_BINARY_DIR}/musica) +# add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/musica) +# message(${CMAKE_CURRENT_SOURCE_DIR}/../..) +# message(${CMAKE_CURRENT_BINARY_DIR}/musica) ################################################################################ # Test MUSICA API From c7c9afddc11ba7404ef0f896e9907008062874e1 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 15 Dec 2023 16:33:42 -0700 Subject: [PATCH 08/24] update for cam-sima --- Dockerfile => docker/Dockerfile | 0 .../Dockerfile.fortran-intel | 0 .../Dockerfile.fortran-ubuntu | 0 Dockerfile.mpi => docker/Dockerfile.mpi | 0 .../Dockerfile.mpi_openmp | 0 .../Dockerfile.no_micm | 0 Dockerfile.openmp => docker/Dockerfile.openmp | 0 musica-fortran/src/micm/micm_c_def.F90 | 32 -------- musica-fortran/src/micm/micm_core.F90 | 75 ++++++++++++------- musica-fortran/test/test_musica_api.F90 | 21 +++--- .../test/test_musica_api_invalid_config.F90 | 21 +++--- musica/include/micm/micm.hpp | 22 ++++-- musica/include/micm/micm_c.h | 7 +- musica/src/micm/micm.cpp | 7 +- musica/src/micm/micm_c_api.cpp | 9 +-- 15 files changed, 97 insertions(+), 97 deletions(-) rename Dockerfile => docker/Dockerfile (100%) rename Dockerfile.fortran-intel => docker/Dockerfile.fortran-intel (100%) rename Dockerfile.fortran-ubuntu => docker/Dockerfile.fortran-ubuntu (100%) rename Dockerfile.mpi => docker/Dockerfile.mpi (100%) rename Dockerfile.mpi_openmp => docker/Dockerfile.mpi_openmp (100%) rename Dockerfile.no_micm => docker/Dockerfile.no_micm (100%) rename Dockerfile.openmp => docker/Dockerfile.openmp (100%) delete mode 100644 musica-fortran/src/micm/micm_c_def.F90 diff --git a/Dockerfile b/docker/Dockerfile similarity index 100% rename from Dockerfile rename to docker/Dockerfile diff --git a/Dockerfile.fortran-intel b/docker/Dockerfile.fortran-intel similarity index 100% rename from Dockerfile.fortran-intel rename to docker/Dockerfile.fortran-intel diff --git a/Dockerfile.fortran-ubuntu b/docker/Dockerfile.fortran-ubuntu similarity index 100% rename from Dockerfile.fortran-ubuntu rename to docker/Dockerfile.fortran-ubuntu diff --git a/Dockerfile.mpi b/docker/Dockerfile.mpi similarity index 100% rename from Dockerfile.mpi rename to docker/Dockerfile.mpi diff --git a/Dockerfile.mpi_openmp b/docker/Dockerfile.mpi_openmp similarity index 100% rename from Dockerfile.mpi_openmp rename to docker/Dockerfile.mpi_openmp diff --git a/Dockerfile.no_micm b/docker/Dockerfile.no_micm similarity index 100% rename from Dockerfile.no_micm rename to docker/Dockerfile.no_micm diff --git a/Dockerfile.openmp b/docker/Dockerfile.openmp similarity index 100% rename from Dockerfile.openmp rename to docker/Dockerfile.openmp diff --git a/musica-fortran/src/micm/micm_c_def.F90 b/musica-fortran/src/micm/micm_c_def.F90 deleted file mode 100644 index 94e3762f..00000000 --- a/musica-fortran/src/micm/micm_c_def.F90 +++ /dev/null @@ -1,32 +0,0 @@ -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 - 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_core.F90 b/musica-fortran/src/micm/micm_core.F90 index e8c9e742..faf64bfa 100644 --- a/musica-fortran/src/micm/micm_core.F90 +++ b/musica-fortran/src/micm/micm_core.F90 @@ -8,18 +8,48 @@ module micm_core private public :: micm_t - include "micm_c_def.F90" + 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 + type(c_ptr), intent(in), value :: micm_t + end function + + subroutine micm_solve_c(micm_t, temperature, pressure, time_step, num_concentrations, 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 + integer, value, intent(in) :: num_concentrations + real(c_double), dimension(*), intent(inout) :: concentrations + end subroutine + end interface type :: micm_t - ! The micm_t class defines the API private type(c_ptr) :: ptr contains - ! Creates solver from configure file + ! Create a solver from configure file procedure :: create_solver => micm_create_solver - ! Solves chemical system + ! Solve the chemical system procedure :: solve => micm_solve - ! Deallocates micm instance + ! Deallocate the micm instance final :: finalize end type micm_t @@ -32,13 +62,12 @@ module micm_core function create_micm(config_path) ! Constructor of micm objects - 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 + 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 + ! Convert Fortran string to C string N = len_trim(config_path) do i = 1, N c_config_path(i) = config_path(i:i) @@ -48,30 +77,26 @@ function create_micm(config_path) create_micm%ptr = create_micm_c(c_config_path) return - end function create_micm subroutine finalize(this) - type(micm_t), intent(inout) :: this + type(micm_t), intent(inout) :: this call delete_micm_c(this%ptr) - end subroutine finalize integer function micm_create_solver(this) - class(micm_t), intent(in) :: this + class(micm_t), intent(in) :: this micm_create_solver = micm_create_solver_c(this%ptr) - end function micm_create_solver - 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) - + subroutine micm_solve(this, temperature, pressure, time_step, num_concentrations, 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 + integer, intent(in) :: num_concentrations + real(c_double), dimension(*), intent(inout) :: concentrations + call micm_solve_c(this%ptr, temperature, pressure, time_step, num_concentrations, concentrations) end subroutine micm_solve end module micm_core \ 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 a5117944..53d70650 100644 --- a/musica-fortran/test/test_musica_api.F90 +++ b/musica-fortran/test/test_musica_api.F90 @@ -4,20 +4,19 @@ program test implicit none - type(micm_t) :: micm - - real(c_double) :: temperature - real(c_double) :: pressure - real(c_double) :: time_step - real(c_double), dimension(10) :: concentrations - integer(c_size_t) :: num_concentrations - integer :: errcode + type(micm_t) :: micm + real(c_double) :: temperature + real(c_double) :: pressure + real(c_double) :: time_step + integer :: num_concentrations + real(c_double), dimension(10) :: concentrations + integer :: errcode temperature = 10d0 pressure = 20d0 time_step = 1d0 - concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) num_concentrations = 10 + concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) write(*,*) " * [Fortran] Creating MICM..." micm = micm_t("micm_config") @@ -31,11 +30,11 @@ program test write(*,*) " * [Fortran] Initial temp", temperature write(*,*) " * [Fortran] Initial pressure", pressure write(*,*) " * [Fortran] Initial time_step", time_step - write(*,*) " * [Fortran] Initial concentrations", concentrations write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations + write(*,*) " * [Fortran] Initial concentrations", concentrations write(*,*) " * [Fortran] Solving starts..." - call micm%solve(temperature, pressure, time_step, concentrations, num_concentrations) + call micm%solve(temperature, pressure, time_step, num_concentrations, concentrations) write(*,*) " * [Fortran] After solving, concentrations", concentrations endif diff --git a/musica-fortran/test/test_musica_api_invalid_config.F90 b/musica-fortran/test/test_musica_api_invalid_config.F90 index 98e63ab5..69796432 100644 --- a/musica-fortran/test/test_musica_api_invalid_config.F90 +++ b/musica-fortran/test/test_musica_api_invalid_config.F90 @@ -4,20 +4,19 @@ program test implicit none - type(micm_t) :: micm - - real(c_double) :: temperature - real(c_double) :: pressure - real(c_double) :: time_step - real(c_double), dimension(10) :: concentrations - integer(c_size_t) :: num_concentrations - integer :: errcode + type(micm_t) :: micm + real(c_double) :: temperature + real(c_double) :: pressure + real(c_double) :: time_step + integer :: num_concentrations + real(c_double), dimension(10) :: concentrations + integer :: errcode temperature = 10d0 pressure = 20d0 time_step = 1d0 - concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) num_concentrations = 10 + concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) write(*,*) " * [Fortran] Creating MICM..." micm = micm_t("invalid_config") @@ -31,11 +30,11 @@ program test write(*,*) " * [Fortran] Initial temp", temperature write(*,*) " * [Fortran] Initial pressure", pressure write(*,*) " * [Fortran] Initial time_step", time_step - write(*,*) " * [Fortran] Initial concentrations", concentrations write(*,*) " * [Fortran] Initial number of concentrations", num_concentrations + write(*,*) " * [Fortran] Initial concentrations", concentrations write(*,*) " * [Fortran] Solving starts..." - call micm%solve(temperature, pressure, time_step, concentrations, num_concentrations) + call micm%solve(temperature, pressure, time_step, num_concentrations, concentrations) write(*,*) " * [Fortran] After solving, concentrations", concentrations endif diff --git a/musica/include/micm/micm.hpp b/musica/include/micm/micm.hpp index cf55cbde..86a6d65f 100644 --- a/musica/include/micm/micm.hpp +++ b/musica/include/micm/micm.hpp @@ -9,15 +9,28 @@ #include -class MICM +class MICM { public: + /// @brief Constructor + /// @param config_path Path to the configuration file or the directory containing the configuration files MICM(const std::string& config_path); + + /// @brief Destructor ~MICM(); - // TODO(jiwon): can return type indicate error? + /// @brief Create a solver + /// @return Status of solver creation related to parsing configuration files. + /// The return value represents the error code for CAM-SIMA int create_solver(); - void solve(double temperature, double pressure, double time_step, double*& concentrations, size_t num_concentrations); + + /// @brief Solve the system + /// @param temperature Temperature [K] + /// @param pressure Pressure [Pa-1] + /// @param time_step Time [s] to advance the state by + /// @param num_concentrations The number of species' concentrations + /// @param concentrations Species's concentrations + void solve(double temperature, double pressure, double time_step, int num_concentrations, double*& concentrations); private: static constexpr size_t NUM_GRID_CELLS = 1; // TODO(jiwon) @@ -34,5 +47,4 @@ class MICM using Vector1SparseMatrixParam = micm::SparseMatrix>; typedef micm::RosenbrockSolver VectorRosenbrockSolver; VectorRosenbrockSolver* solver_; -}; - +}; \ No newline at end of file diff --git a/musica/include/micm/micm_c.h b/musica/include/micm/micm_c.h index d0c7c213..c13fb4ca 100644 --- a/musica/include/micm/micm_c.h +++ b/musica/include/micm/micm_c.h @@ -9,10 +9,9 @@ extern "C" { 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); +void micm_solve(Micm* micm, double temperature, double pressure, double time_step, int num_concentrations, + double* concentrations); #ifdef __cplusplus } -#endif - +#endif \ No newline at end of file diff --git a/musica/src/micm/micm.cpp b/musica/src/micm/micm.cpp index 1451f79b..3ae86f2e 100644 --- a/musica/src/micm/micm.cpp +++ b/musica/src/micm/micm.cpp @@ -1,9 +1,8 @@ #include -#include "../../include/micm/micm.hpp" // TODO(jiwon) relative include path? +#include #include - MICM::MICM(const std::string& config_path) : config_path_(config_path), solver_(nullptr) @@ -18,7 +17,6 @@ int MICM::create_solver() { int errcode = 0; // 0 means no error - // read and parse the config micm::SolverConfig solver_config; micm::ConfigParseStatus status = solver_config.ReadAndParse(config_path_); @@ -35,10 +33,11 @@ int MICM::create_solver() { errcode = 1; // 1 means that error occured } + return errcode; } -void MICM::solve(double temperature, double pressure, double time_step, double*& concentrations, size_t num_concentrations) +void MICM::solve(double temperature, double pressure, double time_step, int num_concentrations, double*& concentrations) { v_concentrations_.assign(concentrations, concentrations + num_concentrations); diff --git a/musica/src/micm/micm_c_api.cpp b/musica/src/micm/micm_c_api.cpp index caf3f84e..51c61a85 100644 --- a/musica/src/micm/micm_c_api.cpp +++ b/musica/src/micm/micm_c_api.cpp @@ -1,6 +1,5 @@ -#include "../../include/micm/micm_c.h" // TODO(jiwon) - relative path? -#include "../../include/micm/micm.hpp" - +#include +#include Micm* create_micm(const char* config_path) { @@ -17,7 +16,7 @@ int micm_create_solver(Micm* micm) return micm->create_solver(); } -void micm_solve(Micm* micm, double temperature, double pressure, double time_step, double* concentrations, size_t num_concentrations) +void micm_solve(Micm* micm, double temperature, double pressure, double time_step, int num_concentrations, double* concentrations) { - micm->solve(temperature, pressure, time_step, concentrations, num_concentrations); + micm->solve(temperature, pressure, time_step, num_concentrations, concentrations); } \ No newline at end of file From 033a63a3f59bbd2f211d6c52477a7707efb75250 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 15 Dec 2023 18:35:20 -0700 Subject: [PATCH 09/24] update cmake and github action --- .github/workflows/test.yml | 28 ++++++++++++++-------------- CMakeLists.txt | 25 ++++++++++++++++++------- musica-fortran/CMakeLists.txt | 10 +++------- musica/CMakeLists.txt | 25 +++++++++---------------- musica/packaging/CMakeLists.txt | 12 +++++++++++- 5 files changed, 55 insertions(+), 45 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3f95ae65..a2e22a14 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,55 +7,55 @@ jobs: 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 + - uses: actions/checkout@v3 with: submodules: recursive - name: build Docker image - run: docker build -t musica . + run: docker build -t musica -f docker/Dockerfile . - 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 + - uses: actions/checkout@v3 with: submodules: recursive - name: build Docker image - run: docker build -t musica -f Dockerfile.no_micm . + run: docker build -t musica -f docker/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 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - name: build Docker image - run: docker build -t musica-openmp -f Dockerfile.openmp . + run: docker build -t musica-openmp -f docker/Dockerfile.openmp . - name: run tests in container run: docker run --name test-container -t musica-openmp bash -c 'make test' build_test_connections_with_mpi: 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 + - uses: actions/checkout@v3 with: submodules: recursive - name: build Docker image - run: docker build -t musica-mpi -f Dockerfile.mpi . + run: docker build -t musica-mpi -f docker/Dockerfile.mpi . - name: run tests in container run: docker run --name test-container -t musica-mpi bash -c 'make test' build_test_connections_with_mpi_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 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - name: build Docker image - run: docker build -t musica-mpi-openmp -f Dockerfile.mpi_openmp . + run: docker build -t musica-mpi-openmp -f docker/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-intel: @@ -65,11 +65,11 @@ jobs: # - name: delete unnessary tools to free up space # run: rm -rf /opt/hostedtoolcache - # - uses: actions/checkout@v2 + # - uses: actions/checkout@v3 # with: # submodules: recursive # - name: build Docker image - # run: docker build -t musica-fortran -f Dockerfile.fortran-intel . + # run: docker build -t musica-fortran -f docker/Dockerfile.fortran-intel . # - name: run tests in container # run: docker run --name test-container -t musica-fortran bash -c 'make test' build_test_connections_musica-fortran-ubuntu: @@ -79,10 +79,10 @@ jobs: - name: delete unnessary tools to free up space run: rm -rf /opt/hostedtoolcache - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: recursive - name: build Docker image - run: docker build -t musica-fortran-ubuntu -f Dockerfile.fortran-ubuntu . + run: docker build -t musica-fortran-ubuntu -f docker/Dockerfile.fortran-ubuntu . - name: run tests in container run: docker run --name test-container -t musica-fortran-ubuntu bash -c 'make test' \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 02442d2d..d7f2c1cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,21 @@ project( LANGUAGES Fortran CXX C ) -set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}/cmake") -set(CMAKE_USER_MAKE_RULES_OVERRIDE "${CMAKE_MODULE_PATH}/SetDefaults.cmake") +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}/cmake) +set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_MODULE_PATH}/SetDefaults.cmake) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +include(GNUInstallDirs) + +set(INSTALL_PREFIX ${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}) +set(INSTALL_INCLUDE_DIR ${INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) +set(INSTALL_LIB_DIR ${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) + +set(MUSICA_MOD_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}) +set(MUSICA_LIB_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) + +set(MUSICA_FORTRAN_SRC_DIR ${CMAKE_SOURCE_DIR}/musica-fortran/src/micm) + ################################################################################ include(CMakeDependentOption) @@ -17,9 +28,12 @@ include(CMakeDependentOption) option(USE_MUSICA "Use MUSICA" ON) message(STATUS "Building MUSICA sources into a library : ${USE_MUSICA}") -option(USE_MUSICA_FORTRAN "Use MUSICA Fortran interface" OFF) +option(USE_MUSICA_FORTRAN "Use MUSICA-Fortran interface" OFF) message(STATUS "Building MUSICA-Fortran sources into a library : ${USE_MUSICA_FORTRAN}") +option(MAKE_MUSICA_FORTRAN_INSTALLABLE "Make MUSICA-Fortran installable" ON) +message(STATUS "Making MUSICA-Fortran sources installable by the CAM-SIMA framework : ${MAKE_MUSICA_FORTRAN_INSTALLABLE}") + ################################################################################ # Projet wide setup options cmake_dependent_option( @@ -50,14 +64,11 @@ if(CREATE_ENVIRONMENT_MODULE) set(INSTALL_MODULE_FILE_PATH "" CACHE STRING "This is the path of the modulefiles location that the Lmod files should be installed to.") endif() -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() diff --git a/musica-fortran/CMakeLists.txt b/musica-fortran/CMakeLists.txt index 3d71e3b7..9724a1ee 100644 --- a/musica-fortran/CMakeLists.txt +++ b/musica-fortran/CMakeLists.txt @@ -6,14 +6,10 @@ project( LANGUAGES Fortran C CXX ) -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - -# Options -message(STATUS "Build tests for MUSICA : ${ENABLE_TESTS}") - # Set up include and lib directories -set(MUSICA_FORTRAN_MOD_DIR "${PROJECT_BINARY_DIR}/include") -set(MUSICA_FORTRAN_LIB_DIR "${PROJECT_BINARY_DIR}/libs") +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) +set(MUSICA_FORTRAN_MOD_DIR ${PROJECT_BINARY_DIR}/include) +set(MUSICA_FORTRAN_LIB_DIR ${PROJECT_BINARY_DIR}/libs) add_library(musica-fortran STATIC) add_library(musica::musica-fortran ALIAS musica-fortran) diff --git a/musica/CMakeLists.txt b/musica/CMakeLists.txt index e0823902..a1eb7a81 100644 --- a/musica/CMakeLists.txt +++ b/musica/CMakeLists.txt @@ -1,10 +1,6 @@ ################################################################################ # Preamble -# Set up include and lib directories -set(MUSICA_MOD_DIR "${PROJECT_BINARY_DIR}/include") -set(MUSICA_LIB_DIR "${PROJECT_BINARY_DIR}/libs") - if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." @@ -49,13 +45,13 @@ target_link_libraries(musica target_include_directories(musica PUBLIC $ - $ + $ ) target_include_directories(musica - PUBLIC + PUBLIC $ - $ + $ ) #################### @@ -73,7 +69,7 @@ set_target_properties(musicacore_object PROPERTIES target_include_directories(musicacore_object PUBLIC $ - $ + $ ) target_link_libraries(musicacore_object @@ -92,8 +88,6 @@ add_subdirectory(${PROJECT_SOURCE_DIR}/lib/musica-core/src ${MUSICA_LIB_DIR}/mus #################### # TUV-x if (ENABLE_TUVX) - add_definitions(-DMUSICA_USE_TUVX) - set(TUVX_MOD_DIR ${MUSICA_MOD_DIR}) set(TUVX_LIB_DIR ${MUSICA_LIB_DIR}) @@ -107,7 +101,7 @@ if (ENABLE_TUVX) target_include_directories(tuvx_object PUBLIC $ - $ + $ ) target_link_libraries(tuvx_object @@ -125,23 +119,22 @@ endif() #################### # MICM if (ENABLE_MICM) - add_definitions(-DMUSICA_USE_MICM) target_compile_features(musica PUBLIC cxx_std_20) target_include_directories(musica PUBLIC $ - $ + $ ) install( DIRECTORY - ${PROJECT_SOURCE_DIR}/lib/micm/include + ${PROJECT_SOURCE_DIR}/lib/micm/include/ DESTINATION - ${INSTALL_MOD_DIR} + ${INSTALL_INCLUDE_DIR} ) endif() ################################################################################ # Packaging -add_subdirectory(packaging) +add_subdirectory(packaging) \ No newline at end of file diff --git a/musica/packaging/CMakeLists.txt b/musica/packaging/CMakeLists.txt index 08b272ca..49134722 100644 --- a/musica/packaging/CMakeLists.txt +++ b/musica/packaging/CMakeLists.txt @@ -14,10 +14,20 @@ install( DIRECTORY ${MUSICA_MOD_DIR}/ DESTINATION - ${INSTALL_MOD_DIR} + ${INSTALL_INCLUDE_DIR} FILES_MATCHING PATTERN "*.mod" ) +if(MAKE_MUSICA_FORTRAN_INSTALLABLE) + install( + DIRECTORY + ${MUSICA_FORTRAN_SRC_DIR}/ + DESTINATION + ${INSTALL_PREFIX}/fortran_include/ + FILES_MATCHING PATTERN "*.F90" + ) +endif() + # install the cmake config files set(cmake_config_install_location ${INSTALL_PREFIX}/cmake) From 50dec5d3b8b27e3159ccb1f1f56e4091594dcef7 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 15 Dec 2023 18:43:32 -0700 Subject: [PATCH 10/24] fixed line truncated error --- musica-fortran/src/micm/micm_core.F90 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/musica-fortran/src/micm/micm_core.F90 b/musica-fortran/src/micm/micm_core.F90 index faf64bfa..bb3fc1de 100644 --- a/musica-fortran/src/micm/micm_core.F90 +++ b/musica-fortran/src/micm/micm_core.F90 @@ -29,7 +29,8 @@ function micm_create_solver_c(micm_t) bind(C, name="micm_create_solver") type(c_ptr), intent(in), value :: micm_t end function - subroutine micm_solve_c(micm_t, temperature, pressure, time_step, num_concentrations, concentrations) bind(C, name="micm_solve") + subroutine micm_solve_c(micm_t, temperature, pressure, time_step, num_concentrations, concentrations) & + bind(C, name="micm_solve") use iso_c_binding implicit none type(c_ptr), intent(in), value :: micm_t From 72f38d28fa80e4eae8fe60d12f2503193fb0dcbc Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Fri, 15 Dec 2023 18:51:06 -0700 Subject: [PATCH 11/24] update the git tag --- musica-fortran/test/CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt index aca81666..0bdfd85c 100644 --- a/musica-fortran/test/CMakeLists.txt +++ b/musica-fortran/test/CMakeLists.txt @@ -16,16 +16,11 @@ set(ENABLE_TUVX OFF) FetchContent_Declare(musica GIT_REPOSITORY https://github.com/NCAR/musica.git - GIT_TAG d833a18 # TODO(jiwon) - update the tag + GIT_TAG 50dec5d # TODO(jiwon) - update the tag ) FetchContent_MakeAvailable(musica) -# TODO(jiwon) - testing for dev -# add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../.. ${CMAKE_CURRENT_BINARY_DIR}/musica) -# message(${CMAKE_CURRENT_SOURCE_DIR}/../..) -# message(${CMAKE_CURRENT_BINARY_DIR}/musica) - ################################################################################ # Test MUSICA API add_executable(test_musica_api test_musica_api.F90) From f8bcac7802949676e638ebba3d42193390951598 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Mon, 18 Dec 2023 10:19:43 -0800 Subject: [PATCH 12/24] update dockerignore --- .dockerignore | 23 ++++++++--------------- musica/src/micm/micm.cpp | 2 -- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/.dockerignore b/.dockerignore index 97befec2..4ad08a8d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,19 +3,12 @@ # add things to copy !CMakeLists.txt -!Dockerfile -!Dockerfile.fortran -!Dockerfile.fortran-ubuntu -!Dockerfile.mpi -!Dockerfile.mpi_openmp -!Dockerfile.no_micm -!Dockerfile.openmp -!musica -!musica-fortran -!docs -!cmake -!lib -!src -!test +!musica/ +!musica-fortran/ +!docs/ +!cmake/ +!lib/ +!src/ +!test/ !.gitmodules -!.git \ No newline at end of file +!.git/ \ No newline at end of file diff --git a/musica/src/micm/micm.cpp b/musica/src/micm/micm.cpp index 3ae86f2e..55938042 100644 --- a/musica/src/micm/micm.cpp +++ b/musica/src/micm/micm.cpp @@ -1,5 +1,3 @@ -#include - #include #include From fd57b7417733ff45c2cbe2519da944f38c86c527 Mon Sep 17 00:00:00 2001 From: Jiwon Gim <55209567+boulderdaze@users.noreply.github.com> Date: Wed, 3 Jan 2024 13:32:57 -0700 Subject: [PATCH 13/24] Make sure the MUSICA library and interfaces are usable in any host application Co-authored-by: Matt Dawson --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7f2c1cf..f23838d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,7 +32,7 @@ option(USE_MUSICA_FORTRAN "Use MUSICA-Fortran interface" OFF) message(STATUS "Building MUSICA-Fortran sources into a library : ${USE_MUSICA_FORTRAN}") option(MAKE_MUSICA_FORTRAN_INSTALLABLE "Make MUSICA-Fortran installable" ON) -message(STATUS "Making MUSICA-Fortran sources installable by the CAM-SIMA framework : ${MAKE_MUSICA_FORTRAN_INSTALLABLE}") +message(STATUS "Making MUSICA-Fortran sources installable : ${MAKE_MUSICA_FORTRAN_INSTALLABLE}") ################################################################################ # Projet wide setup options From 147829327c36a860353785abe377552d53e914a6 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 4 Jan 2024 15:25:02 -0700 Subject: [PATCH 14/24] add stop to the block that catches failures creating the solver --- musica-fortran/test/test_musica_api.F90 | 1 + musica-fortran/test/test_musica_api_invalid_config.F90 | 1 + 2 files changed, 2 insertions(+) diff --git a/musica-fortran/test/test_musica_api.F90 b/musica-fortran/test/test_musica_api.F90 index 53d70650..cf4bd31d 100644 --- a/musica-fortran/test/test_musica_api.F90 +++ b/musica-fortran/test/test_musica_api.F90 @@ -26,6 +26,7 @@ program test if (errcode == 1) then write(*,*) " * [Fortran] Failed in creating solver" + stop errcode else write(*,*) " * [Fortran] Initial temp", temperature write(*,*) " * [Fortran] Initial pressure", pressure diff --git a/musica-fortran/test/test_musica_api_invalid_config.F90 b/musica-fortran/test/test_musica_api_invalid_config.F90 index 69796432..3c09e96f 100644 --- a/musica-fortran/test/test_musica_api_invalid_config.F90 +++ b/musica-fortran/test/test_musica_api_invalid_config.F90 @@ -26,6 +26,7 @@ program test if (errcode == 1) then write(*,*) " * [Fortran] Failed in creating solver" + stop errcode else write(*,*) " * [Fortran] Initial temp", temperature write(*,*) " * [Fortran] Initial pressure", pressure From 96fd5a708f73fbc39c2f4ab0971c2839e58bfaf6 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 4 Jan 2024 16:03:03 -0700 Subject: [PATCH 15/24] fix the stop code usage --- musica-fortran/test/test_musica_api.F90 | 4 +--- .../test/test_musica_api_invalid_config.F90 | 17 ++++------------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/musica-fortran/test/test_musica_api.F90 b/musica-fortran/test/test_musica_api.F90 index cf4bd31d..189128ff 100644 --- a/musica-fortran/test/test_musica_api.F90 +++ b/musica-fortran/test/test_musica_api.F90 @@ -26,7 +26,7 @@ program test if (errcode == 1) then write(*,*) " * [Fortran] Failed in creating solver" - stop errcode + stop 3 else write(*,*) " * [Fortran] Initial temp", temperature write(*,*) " * [Fortran] Initial pressure", pressure @@ -40,6 +40,4 @@ program test write(*,*) " * [Fortran] After solving, concentrations", concentrations endif - write(*,*) " * [Fortran] Exiting..." - end program \ No newline at end of file diff --git a/musica-fortran/test/test_musica_api_invalid_config.F90 b/musica-fortran/test/test_musica_api_invalid_config.F90 index 3c09e96f..cee482b9 100644 --- a/musica-fortran/test/test_musica_api_invalid_config.F90 +++ b/musica-fortran/test/test_musica_api_invalid_config.F90 @@ -26,20 +26,11 @@ program test if (errcode == 1) then write(*,*) " * [Fortran] Failed in creating solver" - stop errcode + write(*,*) " * [Fortran] Expected failure. Error code: ", errcode + stop 0 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 micm%solve(temperature, pressure, time_step, num_concentrations, concentrations) - - write(*,*) " * [Fortran] After solving, concentrations", concentrations + write(*,*) " * [Fortran] Unexpected error code: ", errcode + stop 3 endif - write(*,*) " * [Fortran] Exiting..." - end program \ No newline at end of file From af3b00af13c0c1045e463dc24ea0c6ce3e2015bb Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 10 Jan 2024 11:31:10 -0700 Subject: [PATCH 16/24] update the submodule --- lib/micm | 2 +- lib/musica-core | 2 +- lib/tuv-x | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/micm b/lib/micm index 48d3ed14..a94cc96e 160000 --- a/lib/micm +++ b/lib/micm @@ -1 +1 @@ -Subproject commit 48d3ed14927e65314e5028590a049d6bb4074591 +Subproject commit a94cc96e7bd8dbba6c9eb88d73ade6e5437703b6 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 16e7e8a4..daba6579 160000 --- a/lib/tuv-x +++ b/lib/tuv-x @@ -1 +1 @@ -Subproject commit 16e7e8a4b10dc387311530c7591cebb5b609a60c +Subproject commit daba657958baa3a499ae7fa470f3df0073655c67 From 22ca8942c0dc99688a011b879c1e15ff18253170 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Wed, 10 Jan 2024 13:00:05 -0700 Subject: [PATCH 17/24] update the tag --- musica-fortran/test/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt index 3ce71b0d..365f4c25 100644 --- a/musica-fortran/test/CMakeLists.txt +++ b/musica-fortran/test/CMakeLists.txt @@ -16,7 +16,7 @@ set(ENABLE_TUVX OFF) FetchContent_Declare(musica GIT_REPOSITORY https://github.com/NCAR/musica.git - GIT_TAG 264396b # TODO(jiwon) - update the tag + GIT_TAG c3dff0f # TODO(jiwon) - update the tag ) FetchContent_MakeAvailable(musica) From 66176ba6a0d36950254962f92f022eb0cd939e0e Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Thu, 14 Mar 2024 15:02:12 -0500 Subject: [PATCH 18/24] Reorganize (#67) * add musica c test * add temp directory for the review * make musica fortran shared lib * musica fortran working version for the intel compilers * clean up musica * clean up musica-fortran * reorganizing the cmake files, using MUSICA prefix * renaming directory * investingating cross-compiler library usage * things build and link, but segfault happens * trying a different interface * sigh... * c null char * intent * intent * printing things * calling the constructor... * differnt constructor * syntax * removing prints * comment out prints * trying raw pointer * uhhhh.... * return type * trying to make the interface smaller * fixing type * adding pointer * correcting thing * wish I could read * removing import * yes, i do * commenting out print * pass by value * thing * removing value * uncommenting thing * trying a thing * adding it back * adding invalid * new interface * adding failure test * trying to fix paths * more paths * thing * reordering includes, giving up on trying to remove installed directories * updating tuv branch * going back to that version * smaller interface * getting the test to work * moving fortran things to the fortran side * removing musica_core, updating tuvx branch * removing old tuvx git stuff * what is happening * including tuvx that can be built with gcc 13 * different actions * more actions * not looking for fortran stuff when we don't need it * installing dependencies * removing unused dependency * trying to set compiler * wait maybe it was right * fix clang linking bad c++ version * trying to add multiple clang versions on ubuntu * removing duplicate build * removing unused header * correcting build * seeing if 13 and 14 work * not specifying clang version * adding readme ci badges * updating doi badge * only installing micm_core.F90 * removing json fortran deps * better openmp find interface * huh, another seg fault * trying a thing * undoing one thing, keeping a thing * okay so it needs it * trying different standard library * that didn't work * adding gcc test to github * commenting out writes * pointer assignment * yeah, pointer assignment * removing reference to json fortran in module * adding module message * adding fortran install instructions * some changes * verbose * actual verbose * something different * trying to remove a thing * trying different ubuntu version * trying a different thing * maybe here * maybe this * trying a different interface * trying to pass the pointer by value * passing by value * catching a bad allocation * comments * updating install stuff * windows builds? * adding c compiler for clang * adding nvhpc dockerfile * Update src/component_versions.c Co-authored-by: Matt Dawson * including memcheck build * removing gfortran dependencies for builds that don't need them --------- Co-authored-by: Jiwon Gim Co-authored-by: Matt Dawson --- .dockerignore | 14 +- .github/workflows/docker.yml | 56 +++++++ .github/workflows/mac.yml | 63 ++++++++ .github/workflows/test.yml | 88 ----------- .github/workflows/ubuntu.yml | 65 ++++++++ .github/workflows/windows.yml | 131 ++++++++++++++++ .gitmodules | 9 +- CMakeLists.txt | 132 +++++++---------- README.md | 7 +- cmake/cmake_uninstall.cmake.in | 23 +-- cmake/dependencies.cmake | 53 ++++--- cmake/musica_util.cmake | 4 +- cmake/test_util.cmake | 18 +-- .../configs => configs}/chapman/config.json | 0 .../chapman/reactions.json | 0 .../configs => configs}/chapman/species.json | 0 docker/Dockerfile | 16 +- docker/Dockerfile.fortran-gcc | 49 ++++++ docker/Dockerfile.fortran-intel | 54 ++----- docker/Dockerfile.fortran-nvhpc | 58 ++++++++ docker/Dockerfile.fortran-ubuntu | 60 -------- docker/Dockerfile.memcheck | 27 ++++ docker/Dockerfile.mpi | 12 -- docker/Dockerfile.mpi_openmp | 12 -- docker/Dockerfile.no_micm | 41 ----- docker/Dockerfile.openmp | 12 -- fortran/CMakeLists.txt | 92 ++++++++++++ fortran/micm_core.F90 | 86 +++++++++++ fortran/packaging/CMakelists.txt | 65 ++++++++ fortran/test/CMakeLists.txt | 1 + .../fetch_content_integration/CMakeLists.txt | 57 +++++++ .../test_micm_fort_api.F90 | 48 ++++++ .../test_micm_fort_api_invalid.F90 | 38 +++++ fortran/test/unit/CMakeLists.txt | 11 ++ .../test/unit}/tuvx.F90 | 0 .../test/unit}/tuvx_mpi.F90 | 0 .../test/unit}/tuvx_openmp.F90 | 0 include/musica/component_versions.h | 17 +++ include/musica/micm.hpp | 57 +++++++ {musica/include => include}/musica/version.h | 6 + lib/musica-core | 1 - lib/tuv-x | 2 +- musica-fortran/CMakeLists.txt | 40 ----- musica-fortran/src/CMakeLists.txt | 1 - musica-fortran/src/micm/CMakeLists.txt | 4 - musica-fortran/src/micm/micm_core.F90 | 103 ------------- musica-fortran/test/CMakeLists.txt | 61 -------- musica-fortran/test/test_musica_api.F90 | 43 ------ .../test/test_musica_api_invalid_config.F90 | 35 ----- musica/CMakeLists.txt | 140 ------------------ musica/include/micm/micm.hpp | 50 ------- musica/include/micm/micm_c.h | 17 --- musica/include/musica/component_versions.h | 11 -- musica/src/CMakeLists.txt | 12 -- musica/src/micm/micm.cpp | 58 -------- musica/src/micm/micm_c_api.cpp | 22 --- musica/test/connections/CMakeLists.txt | 25 ---- musica/test/connections/musica_core.F90 | 19 --- musica/test/connections/musica_core_mpi.F90 | 37 ----- .../test/connections/musica_core_openmp.F90 | 34 ----- src/CMakeLists.txt | 89 +++++++++++ {musica/src => src}/component_versions.c | 7 + {musica/src => src}/micm/CMakeLists.txt | 1 - src/micm/micm.cpp | 86 +++++++++++ {musica => src}/packaging/CMakeLists.txt | 52 ++++--- {musica => src}/packaging/modulefile.lua.in | 8 +- {musica => src}/test/CMakeLists.txt | 0 src/test/connections/CMakeLists.txt | 12 ++ {musica => src}/test/connections/micm.cpp | 2 + src/test/connections/micm_c_api.cpp | 44 ++++++ {musica => src}/test/unit/CMakeLists.txt | 0 .../test/unit/component_versions.cpp | 0 {musica/src => src}/version.c.in | 0 73 files changed, 1339 insertions(+), 1159 deletions(-) create mode 100644 .github/workflows/docker.yml create mode 100644 .github/workflows/mac.yml delete mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/ubuntu.yml create mode 100644 .github/workflows/windows.yml rename {musica-fortran/test/configs => configs}/chapman/config.json (100%) rename {musica-fortran/test/configs => configs}/chapman/reactions.json (100%) rename {musica-fortran/test/configs => configs}/chapman/species.json (100%) create mode 100644 docker/Dockerfile.fortran-gcc create mode 100644 docker/Dockerfile.fortran-nvhpc delete mode 100644 docker/Dockerfile.fortran-ubuntu create mode 100644 docker/Dockerfile.memcheck delete mode 100644 docker/Dockerfile.no_micm create mode 100644 fortran/CMakeLists.txt create mode 100644 fortran/micm_core.F90 create mode 100644 fortran/packaging/CMakelists.txt create mode 100644 fortran/test/CMakeLists.txt create mode 100644 fortran/test/fetch_content_integration/CMakeLists.txt create mode 100644 fortran/test/fetch_content_integration/test_micm_fort_api.F90 create mode 100644 fortran/test/fetch_content_integration/test_micm_fort_api_invalid.F90 create mode 100644 fortran/test/unit/CMakeLists.txt rename {musica/test/connections => fortran/test/unit}/tuvx.F90 (100%) rename {musica/test/connections => fortran/test/unit}/tuvx_mpi.F90 (100%) rename {musica/test/connections => fortran/test/unit}/tuvx_openmp.F90 (100%) create mode 100644 include/musica/component_versions.h create mode 100644 include/musica/micm.hpp rename {musica/include => include}/musica/version.h (52%) delete mode 160000 lib/musica-core delete mode 100644 musica-fortran/CMakeLists.txt delete mode 100644 musica-fortran/src/CMakeLists.txt delete mode 100644 musica-fortran/src/micm/CMakeLists.txt delete mode 100644 musica-fortran/src/micm/micm_core.F90 delete mode 100644 musica-fortran/test/CMakeLists.txt delete mode 100644 musica-fortran/test/test_musica_api.F90 delete mode 100644 musica-fortran/test/test_musica_api_invalid_config.F90 delete mode 100644 musica/CMakeLists.txt delete mode 100644 musica/include/micm/micm.hpp delete mode 100644 musica/include/micm/micm_c.h delete mode 100644 musica/include/musica/component_versions.h delete mode 100644 musica/src/CMakeLists.txt delete mode 100644 musica/src/micm/micm.cpp delete mode 100644 musica/src/micm/micm_c_api.cpp delete mode 100644 musica/test/connections/CMakeLists.txt delete mode 100644 musica/test/connections/musica_core.F90 delete mode 100644 musica/test/connections/musica_core_mpi.F90 delete mode 100644 musica/test/connections/musica_core_openmp.F90 create mode 100644 src/CMakeLists.txt rename {musica/src => src}/component_versions.c (78%) rename {musica/src => src}/micm/CMakeLists.txt (70%) create mode 100644 src/micm/micm.cpp rename {musica => src}/packaging/CMakeLists.txt (74%) rename {musica => src}/packaging/modulefile.lua.in (73%) rename {musica => src}/test/CMakeLists.txt (100%) create mode 100644 src/test/connections/CMakeLists.txt rename {musica => src}/test/connections/micm.cpp (70%) create mode 100644 src/test/connections/micm_c_api.cpp rename {musica => src}/test/unit/CMakeLists.txt (100%) rename {musica => src}/test/unit/component_versions.cpp (100%) rename {musica/src => src}/version.c.in (100%) diff --git a/.dockerignore b/.dockerignore index 4ad08a8d..62f2cbcc 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,13 +2,13 @@ * # add things to copy +!.git/ +!.gitmodules !CMakeLists.txt -!musica/ -!musica-fortran/ -!docs/ !cmake/ +!configs +!docs/ +!fortran/ +!include/ !lib/ -!src/ -!test/ -!.gitmodules -!.git/ \ No newline at end of file +!src/ \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 00000000..e424a5c8 --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,56 @@ +name: Docker + +on: [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + docker-build-and-test: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + name: Build and Test - ${{ matrix.dockerfile }} + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + dockerfile: + - Dockerfile + - Dockerfile.memcheck + - Dockerfile.fortran-intel + - Dockerfile.fortran-gcc + - Dockerfile.fortran-nvhpc + - Dockerfile.openmp + - Dockerfile.mpi + - Dockerfile.mpi_openmp + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Delete huge unnecessary tools folder + run: rm -rf /opt/hostedtoolcache + + - name: Build Docker image + run: docker build -t tuvx -f docker/${{ matrix.dockerfile }} . + + - name: Run tests in container + if: matrix.dockerfile != 'Dockerfile.coverage' + run: docker run --name test-container -t tuvx bash -c 'make test ARGS="--rerun-failed --output-on-failure -j8"' + + - name: Run coverage tests in container + if: matrix.dockerfile == 'Dockerfile.coverage' + run: docker run --name test-container -t tuvx bash -c 'make coverage ARGS="--rerun-failed --output-on-failure -j8"' + + - name: Copy coverage from container + if: matrix.dockerfile == 'Dockerfile.coverage' + run: docker cp test-container:build/coverage.info . + + - name: Upload coverage report + if: matrix.dockerfile == 'Dockerfile.coverage' + uses: codecov/codecov-action@v3 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage.info \ No newline at end of file diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml new file mode 100644 index 00000000..54130b99 --- /dev/null +++ b/.github/workflows/mac.yml @@ -0,0 +1,63 @@ +name: Mac + +on: [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + c_cxx: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: macos-latest + strategy: + matrix: + compiler: + - { cpp: g++-11, c: gcc-11} + - { cpp: g++-12, c: gcc-12} + - { cpp: g++-13, c: gcc-13} + - { cpp: clang++, c: clang} + build_type: [Debug, Release] + env: + CC: ${{ matrix.compiler.c }} + CXX: ${{ matrix.compiler.cpp }} + + steps: + - uses: actions/checkout@v3 + + - name: Run Cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} + + - name: Build + run: cmake --build build --parallel 10 + + - name: Run tests + run: | + cd build + ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure . --verbose -j 10 + fortran: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: macos-latest + strategy: + matrix: + gcc_version: [11, 12, 13] + build_type: [Debug, Release] + env: + FC: gfortran-${{ matrix.gcc_version }} + + steps: + - uses: actions/checkout@v3 + + - name: Install dependencies + run: brew install netcdf netcdf-fortran + + - name: Run Cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MUSICA_BUILD_FORTRAN_INTERFACE=ON + + - name: Build + run: cmake --build build --parallel 10 + + - name: Run tests + run: | + cd build + ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure . --verbose -j 10 \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 55f8f3cf..00000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: build - -on: [push, pull_request] - -jobs: - build_test_connections: - 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@v3 - with: - submodules: recursive - - name: build Docker image - run: docker build -t musica -f docker/Dockerfile . - - 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@v3 - with: - submodules: recursive - - name: build Docker image - run: docker build -t musica -f docker/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 - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - name: build Docker image - run: docker build -t musica-openmp -f docker/Dockerfile.openmp . - - name: run tests in container - run: docker run --name test-container -t musica-openmp bash -c 'make test' - build_test_connections_with_mpi: - 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@v3 - with: - submodules: recursive - - name: build Docker image - run: docker build -t musica-mpi -f docker/Dockerfile.mpi . - - name: run tests in container - run: docker run --name test-container -t musica-mpi bash -c 'make test' - build_test_connections_with_mpi_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 - steps: - - uses: actions/checkout@v3 - with: - submodules: recursive - - name: build Docker image - run: docker build -t musica-mpi-openmp -f docker/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-intel: - # 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@v3 - # with: - # submodules: recursive - # - name: build Docker image - # run: docker build -t musica-fortran -f docker/Dockerfile.fortran-intel . - # - name: run tests in container - # run: docker run --name test-container -t musica-fortran bash -c 'make test' - build_test_connections_musica-fortran-ubuntu: - 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@v3 - with: - submodules: recursive - - name: build Docker image - run: docker build -t musica-fortran-ubuntu -f docker/Dockerfile.fortran-ubuntu . - - name: run tests in container - run: docker run --name test-container -t musica-fortran-ubuntu bash -c 'make test' diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml new file mode 100644 index 00000000..973e7cec --- /dev/null +++ b/.github/workflows/ubuntu.yml @@ -0,0 +1,65 @@ +name: Ubuntu + +on: [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + c_cxx: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + strategy: + matrix: + compiler: + - { cpp: g++-11, c: gcc-11} + - { cpp: g++-12, c: gcc-12} + - { cpp: g++-13, c: gcc-13} + - { cpp: clang++, c: clang} + build_type: [Debug, Release] + env: + CC: ${{ matrix.compiler.c }} + CXX: ${{ matrix.compiler.cpp }} + + steps: + - uses: actions/checkout@v3 + + - name: Run Cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} + + - name: Build + run: cmake --build build --verbose + + - name: Run tests + run: | + cd build + ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure . --verbose -j 10 + fortran: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: ubuntu-latest + strategy: + matrix: + gcc_version: [11, 12, 13] + build_type: [Debug, Release] + env: + FC: gfortran-${{ matrix.gcc_version }} + + steps: + - uses: actions/checkout@v3 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libnetcdf-dev netcdf-bin libnetcdff-dev + + - name: Run Cmake + run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MUSICA_BUILD_FORTRAN_INTERFACE=ON + + - name: Build + run: cmake --build build --parallel 10 + + - name: Run tests + run: | + cd build + ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure . --verbose -j 10 \ No newline at end of file diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 00000000..50f44a3d --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,131 @@ +name: Windows + +on: [push, pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref || github.run_id }} + cancel-in-progress: true + +jobs: + mingw: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2019 + strategy: + matrix: + architecture: [x64] + + steps: + - uses: actions/checkout@v3 + - name: Set up MinGW + uses: egor-tensin/setup-mingw@v2 + with: + platform: ${{ matrix.architecture }} + version: 12.2.0 # https://github.com/egor-tensin/setup-mingw/issues/14 + + - name: Run Cmake + run: cmake -S . -B build -G "MinGW Makefiles" + + - name: Build + run: cmake --build build --parallel 10 + + - name: Run tests + run: | + cd build + ctest -C Debug --rerun-failed --output-on-failure . --verbose + + msvc2019: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2019 + strategy: + matrix: + build_type: [Debug, Release] + architecture: [Win32, x64] + + steps: + - uses: actions/checkout@v3 + + - name: Run CMake + run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + + - name: Build + run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 + + - name: Test + run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure + + msvc2019_latest: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2019 + + steps: + - uses: actions/checkout@v3 + - name: Run CMake + run: cmake -S . -B build -G "Visual Studio 16 2019" + - name: Build + run: cmake --build build --config Release --parallel 10 + - name: Test + run: cd build ; ctest -j 10 -C Release --output-on-failure + + msvc2022: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2022 + strategy: + matrix: + build_type: [Debug, Release] + architecture: [Win32, x64] + + steps: + - uses: actions/checkout@v3 + - name: Run CMake + run: cmake -S . -B build -G "Visual Studio 17 2022" -A ${{ matrix.architecture }} -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} + - name: Build + run: cmake --build build --config ${{ matrix.build_type }} --parallel 10 + - name: Test + run: cd build ; ctest -j 10 -C ${{ matrix.build_type }} --output-on-failure + + msvc2022_latest: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2022 + + steps: + - uses: actions/checkout@v3 + - name: Run CMake + run: cmake -S . -B build -G "Visual Studio 17 2022" + - name: Build + run: cmake --build build --config Release --parallel 10 + - name: Test + run: cd build ; ctest -j 10 -C Release --output-on-failure + + clang: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2019 + strategy: + matrix: + version: [11, 12, 13, 14, 15] + + steps: + - uses: actions/checkout@v3 + - name: Install Clang + run: curl -fsSL -o LLVM${{ matrix.version }}.exe https://github.com/llvm/llvm-project/releases/download/llvmorg-${{ matrix.version }}.0.0/LLVM-${{ matrix.version }}.0.0-win64.exe ; 7z x LLVM${{ matrix.version }}.exe -y -o"C:/Program Files/LLVM" + - name: Run CMake + run: cmake -S . -B build -DCMAKE_CXX_COMPILER="C:/Program Files/LLVM/bin/clang++.exe" -DCMAKE_C_COMPILER="C:/Program Files/LLVM/bin/clang.exe" -G"MinGW Makefiles" -DCMAKE_BUILD_TYPE=Debug + - name: Build + run: cmake --build build --parallel 10 + - name: Test + run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure + + clang-cl-11: + if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name != github.event.pull_request.base.repo.full_name + runs-on: windows-2019 + strategy: + matrix: + architecture: [Win32, x64] + + steps: + - uses: actions/checkout@v3 + - name: Run CMake + run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -T ClangCL + - name: Build + run: cmake --build build --config Debug --parallel 10 + - name: Test + run: cd build ; ctest -j 10 -C Debug --exclude-regex "test-unicode" --output-on-failure \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index f52ce418..cf939edf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ -[submodule "lib/tuv-x"] - path = lib/tuv-x - url = https://github.com/NCAR/tuv-x.git -[submodule "lib/musica-core"] - path = lib/musica-core - url = https://github.com/NCAR/musica-core.git [submodule "lib/micm"] path = lib/micm url = https://github.com/NCAR/micm.git +[submodule "lib/tuv-x"] + path = lib/tuv-x + url = https://github.com/NCAR/tuv-x diff --git a/CMakeLists.txt b/CMakeLists.txt index 0df69e45..d8feaf55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,94 +1,57 @@ cmake_minimum_required(VERSION 3.21) project( - musica - VERSION 0.5.0 - LANGUAGES Fortran CXX C + musica-distribution + VERSION 0.6.0 ) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}/cmake) set(CMAKE_USER_MAKE_RULES_OVERRIDE ${CMAKE_MODULE_PATH}/SetDefaults.cmake) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -include(GNUInstallDirs) - -set(INSTALL_PREFIX ${CMAKE_PROJECT_NAME}-${PROJECT_VERSION}) -set(INSTALL_INCLUDE_DIR ${INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) -set(INSTALL_LIB_DIR ${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) - -set(MUSICA_MOD_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}) -set(MUSICA_LIB_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE) +endif(NOT CMAKE_BUILD_TYPE) -set(MUSICA_FORTRAN_SRC_DIR ${CMAKE_SOURCE_DIR}/musica-fortran/src/micm) +include(GNUInstallDirs) ################################################################################ -include(CMakeDependentOption) - # Library options to build -option(USE_MUSICA "Use MUSICA" ON) -message(STATUS "Building MUSICA sources into a library : ${USE_MUSICA}") - -option(USE_MUSICA_FORTRAN "Use MUSICA-Fortran interface" OFF) -message(STATUS "Building MUSICA-Fortran sources into a library : ${USE_MUSICA_FORTRAN}") - -option(MAKE_MUSICA_FORTRAN_INSTALLABLE "Make MUSICA-Fortran installable" ON) -message(STATUS "Making MUSICA-Fortran sources installable : ${MAKE_MUSICA_FORTRAN_INSTALLABLE}") - -################################################################################ -# Projet wide setup options -cmake_dependent_option( - ENABLE_TESTS "Builds tests that ensures each enabled MUSICA component can be used" ON "USE_MUSICA" OFF) -message(STATUS "Build tests for MUSICA : ${ENABLE_TESTS}") - -cmake_dependent_option( - ENABLE_TUVX "Builds TUV-x, a photolysis calculator library" ON "USE_MUSICA" OFF) -message(STATUS "Build TUV-x : ${ENABLE_TUVX}") +include(CMakeDependentOption) -cmake_dependent_option( - ENABLE_MICM "Adds MICM, a model independent chemical mechanism solver" ON "USE_MUSICA" OFF) -message(STATUS "Build MICM : ${ENABLE_MICM}") +option(MUSICA_BUILD_C_CXX_INTERFACE "Use MUSICA" ON) +option(MUSICA_BUILD_FORTRAN_INTERFACE "Use MUSICA-Fortran interface" OFF) +option(MUSICA_ENABLE_INSTALL "Install the musica library" ON) +option(MUSICA_ENABLE_TESTS "Builds tests that ensures each enabled MUSICA component can be used" ON) +option(MUSICA_ENABLE_MPI "Enable MPI parallel support" OFF) +option(MUSICA_ENABLE_OPENMP "Enable OpemMP support" OFF) +option(MUSICA_ENABLE_MEMCHECK "Enable memory checking" OFF) cmake_dependent_option( - ENABLE_MPI "Enable MPI parallel support" OFF "USE_MUSICA" OFF) -message(STATUS "Enable MPI parallel support : ${ENABLE_MPI}") + MUSICA_ENABLE_TUVX "Builds TUV-x, a photolysis calculator library" ON "MUSICA_BUILD_FORTRAN_INTERFACE" OFF) cmake_dependent_option( - ENABLE_OPENMP "Enable OpemMP support" OFF "USE_MUSICA" OFF) -message(STATUS "Enable OpemMP support : ${ENABLE_OPENMP}") + MUSICA_ENABLE_MICM "Adds MICM, a model independent chemical mechanism solver" ON "MUSICA_BUILD_C_CXX_INTERFACE" OFF) cmake_dependent_option( - CREATE_ENVIRONMENT_MODULE "Creates an Lmod environment module file that can be installed on the same machine this library is installed to." OFF "USE_MUSICA" OFF) -message(STATUS "Creates an Lmod environment module : ${CREATE_ENVIRONMENT_MODULE}") - -if(CREATE_ENVIRONMENT_MODULE) - set(INSTALL_MODULE_FILE_PATH "" CACHE STRING "This is the path of the modulefiles location that the Lmod files should be installed to.") -endif() - -# MUSICA library components -if(ENABLE_TUVX) - add_definitions(-DMUSICA_USE_TUVX) -endif() - -if(ENABLE_MICM) - add_definitions(-DMUSICA_USE_MICM) -endif() + MUSICA_CREATE_ENVIRONMENT_MODULE "Creates an Lmod environment module file that can be installed on the same machine this library is installed to." OFF "MUSICA_BUILD_C_CXX_INTERFACE" OFF) -# MPI -if(ENABLE_MPI) - add_definitions(-DMUSICA_USE_MPI) -endif() - -# OpenMP -if(ENABLE_OPENMP) - find_package(OpenMP) - if(OpenMP_Fortran_FOUND) - message(STATUS "Compiling with OpenMP support") - add_definitions(-DMUSICA_USE_OPENMP) - else() - message(FATAL_ERROR "OpenMP package not found") +if(MUSICA_CREATE_ENVIRONMENT_MODULE) + set(MUSICA_INSTALL_MODULE_FILE_PATH "" CACHE STRING "This is the path of the modulefiles location that the Lmod files should be installed to.") + if(MUSICA_INSTALL_MODULE_FILE_PATH STREQUAL "") + message(FATAL_ERROR "MUSICA_INSTALL_MODULE_FILE_PATH is required but not set") endif() endif() +################################################################################ +# Projet wide setup variables +set(MUSICA_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) +set(MUSICA_MOD_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR}) +set(MUSICA_LIB_DIR ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +set(MUSICA_FORTRAN_SRC_DIR ${CMAKE_SOURCE_DIR}/fortran) + # Add flags for various compilers if(${CMAKE_Fortran_COMPILER_ID} MATCHES "Intel") add_definitions(-DMUSICA_USING_INTEL) @@ -98,20 +61,35 @@ elseif(${CMAKE_Fortran_COMPILER_ID} MATCHES "PGI") add_definitions(-DMUSICA_USING_PGI) endif() -################################################################################ -# MUSICA -if(USE_MUSICA) - add_subdirectory(musica) -endif() +if(MUSICA_BUILD_C_CXX_INTERFACE) + # on ubuntu with clang, an incorrect version of the c++ standard library was being linked + if (${CMAKE_HOST_SYSTEM_NAME} MATCHES "Linux" AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + # If the compiler is Clang, use libc++ + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + endif() -# MUSICA-Fortran -if(USE_MUSICA_FORTRAN) - add_subdirectory(musica-fortran) + set(CMAKE_CXX_STANDARD 20) endif() +################################################################################ +# Dependencies + +include(dependencies) + ################################################################################ # Tests -if(ENABLE_TESTS) +if(MUSICA_ENABLE_TESTS) enable_testing() - add_subdirectory(musica/test) +endif() + +################################################################################ +# MUSICA +if(MUSICA_BUILD_C_CXX_INTERFACE) + add_subdirectory(src) +endif() + +################################################################################ +# MUSICA-Fortran +if(MUSICA_BUILD_FORTRAN_INTERFACE) + add_subdirectory(fortran) endif() diff --git a/README.md b/README.md index 4fcc82f2..bed50ba8 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ # 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) - +[![docker](https://github.com/NCAR/musica/actions/workflows/docker.yml/badge.svg)](https://github.com/NCAR/musica/actions/workflows/docker.yml) +[![macOS](https://github.com/NCAR/musica/actions/workflows/mac.yml/badge.svg)](https://github.com/NCAR/musica/actions/workflows/mac.yml) +[![ubuntu](https://github.com/NCAR/musica/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/NCAR/musica/actions/workflows/ubuntu.yml) +[![windows](https://github.com/NCAR/musica/actions/workflows/windows.yml/badge.svg)](https://github.com/NCAR/musica/actions/workflows/windows.yml) +[![DOI](https://zenodo.org/badge/550370528.svg)](https://zenodo.org/doi/10.5281/zenodo.7458559) Multi-Scale Infrastructure for Chemistry and Aerosols diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in index 66e6b1d2..b9ce0db7 100644 --- a/cmake/cmake_uninstall.cmake.in +++ b/cmake/cmake_uninstall.cmake.in @@ -9,29 +9,16 @@ string(REGEX REPLACE "\n" ";" files "${files}") foreach(file ${files}) message(STATUS "Uninstalling $ENV{DESTDIR}${file}") if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") - exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + execute_process( + COMMAND "@CMAKE_COMMAND@" "-E" "rm" "$ENV{DESTDIR}${file}" OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) + RESULT_VARIABLE rm_retval + # COMMAND_ECHO STDOUT + ) if(NOT "${rm_retval}" STREQUAL 0) message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") endif() else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File $ENV{DESTDIR}${file} does not exist.") endif() -endforeach() - -set(uninstall_dirs "@INSTALL_PREFIX@;@cmake_config_install_location@") - -foreach(dir IN LISTS uninstall_dirs) - message(STATUS "Uninstalling ${dir}") - exec_program( - "@CMAKE_COMMAND@" ARGS "-E remove_directory ${dir}" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - if(NOT "${rm_retval}" STREQUAL 0) - message(FATAL_ERROR "Problem when removing ${dir}") - endif() endforeach() \ No newline at end of file diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 684de281..10bb0032 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -1,30 +1,14 @@ find_package(PkgConfig REQUIRED) -################################################################################ -# json-fortran library -find_path(JSON_INCLUDE_DIR json_module.mod - DOC "json-fortran include directory (must include json_*.mod files)" - PATHS - $ENV{JSON_FORTRAN_HOME}/lib - /opt/local/lib - /usr/local/lib - /usr/local/lib64) -find_library(JSON_LIB jsonfortran - DOC "json-fortran library" - PATHS - $ENV{JSON_FORTRAN_HOME}/lib - /opt/local/lib - /usr/local/lib - /usr/local/lib64) -include_directories(${JSON_INCLUDE_DIR}) - ################################################################################ # NetCDF library -pkg_check_modules(netcdff IMPORTED_TARGET REQUIRED netcdf-fortran) +if (MUSICA_BUILD_FORTRAN_INTERFACE) + pkg_check_modules(netcdff IMPORTED_TARGET REQUIRED netcdf-fortran) +endif() ################################################################################ # google test -if(ENABLE_TESTS) +if(MUSICA_ENABLE_TESTS) include(FetchContent) FetchContent_Declare(googletest GIT_REPOSITORY https://github.com/google/googletest.git @@ -35,4 +19,33 @@ if(ENABLE_TESTS) set(BUILD_GMOCK OFF CACHE BOOL "" FORCE) FetchContent_MakeAvailable(googletest) +endif() + +################################################################################ +# OpenMP +if(MUSICA_ENABLE_OPENMP) + find_package(OpenMP REQUIRED) +endif() + +################################################################################ +# MICM + +if (MUSICA_ENABLE_MICM) + FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.11.2 + ) + FetchContent_MakeAvailable(json) +endif() + +################################################################################ +# TUV-x + +if (MUSICA_ENABLE_TUVX) + FetchContent_Declare( + yaml-cpp + GIT_REPOSITORY https://github.com/jbeder/yaml-cpp/ + GIT_TAG 0.8.0 + ) + FetchContent_MakeAvailable(yaml-cpp) endif() \ No newline at end of file diff --git a/cmake/musica_util.cmake b/cmake/musica_util.cmake index fde0c037..4d879455 100644 --- a/cmake/musica_util.cmake +++ b/cmake/musica_util.cmake @@ -1,6 +1,6 @@ function(checkout_submodules) - find_package(Git QUIET) - if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") + find_package(Git) + if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") # Update submodules as needed option(GIT_SUBMODULE "Check submodules during build" ON) if(GIT_SUBMODULE) diff --git a/cmake/test_util.cmake b/cmake/test_util.cmake index a588456e..17a1194e 100644 --- a/cmake/test_util.cmake +++ b/cmake/test_util.cmake @@ -1,14 +1,14 @@ ################################################################################ # Utility functions for creating tests -if(ENABLE_MEMCHECK) +if(MUSICA_ENABLE_MEMCHECK) find_program(MEMORYCHECK_COMMAND "valgrind") endif() ################################################################################ # build and add a standard test linked to musica -function(create_standard_test) +function(create_standard_test_fortran) set(prefix TEST) set(singleValues NAME WORKING_DIRECTORY) set(multiValues SOURCES LIBRARIES) @@ -16,14 +16,14 @@ function(create_standard_test) cmake_parse_arguments(${prefix} " " "${singleValues}" "${multiValues}" ${ARGN}) add_executable(test_${TEST_NAME} ${TEST_SOURCES}) - target_link_libraries(test_${TEST_NAME} PUBLIC musica::musica) + target_link_libraries(test_${TEST_NAME} PUBLIC musica::musica-fortran) # link additional libraries foreach(library ${TEST_LIBRARIES}) target_link_libraries(test_${TEST_NAME} PUBLIC ${library}) endforeach() - if(ENABLE_OPENMP) + if(MUSICA_ENABLE_OPENMP) target_link_libraries(test_${TEST_NAME} PUBLIC OpenMP::OpenMP_Fortran) endif() @@ -32,7 +32,7 @@ function(create_standard_test) endif() add_musica_test(${TEST_NAME} test_${TEST_NAME} "" ${TEST_WORKING_DIRECTORY}) -endfunction(create_standard_test) +endfunction(create_standard_test_fortran) function(create_standard_test_cxx) set(prefix TEST) @@ -42,7 +42,7 @@ function(create_standard_test_cxx) cmake_parse_arguments(${prefix} " " "${singleValues}" "${multiValues}" ${ARGN}) add_executable(test_${TEST_NAME} ${TEST_SOURCES}) target_link_libraries(test_${TEST_NAME} PUBLIC musica::musica GTest::gtest_main) - if(ENABLE_OPENMP) + if(MUSICA_ENABLE_OPENMP) target_link_libraries(test_${TEST_NAME} PUBLIC OpenMP::OpenMP_CXX OpenMP::OpenMP_Fortran) endif() if(NOT DEFINED TEST_WORKING_DIRECTORY) @@ -55,7 +55,7 @@ endfunction(create_standard_test_cxx) # Add a test function(add_musica_test test_name test_binary test_args working_dir) - if(ENABLE_MPI) + if(MUSICA_ENABLE_MPI) add_test(NAME ${test_name} COMMAND mpirun -v -np 2 ${CMAKE_BINARY_DIR}/${test_binary} ${test_args} WORKING_DIRECTORY ${working_dir}) @@ -67,7 +67,7 @@ function(add_musica_test test_name test_binary test_args working_dir) set(MEMORYCHECK_COMMAND_OPTIONS "--error-exitcode=1 --trace-children=yes --leak-check=full --gen-suppressions=all ${MEMCHECK_SUPPRESS}") set(memcheck "${MEMORYCHECK_COMMAND} ${MEMORYCHECK_COMMAND_OPTIONS}") separate_arguments(memcheck) - if(ENABLE_MPI AND MEMORYCHECK_COMMAND AND ENABLE_MEMCHECK) + if(MUSICA_ENABLE_MPI AND MEMORYCHECK_COMMAND AND MUSICA_ENABLE_MEMCHECK) add_test(NAME memcheck_${test_name} COMMAND mpirun -v -np 2 ${memcheck} ${CMAKE_BINARY_DIR}/${test_binary} ${test_args} WORKING_DIRECTORY ${working_dir}) @@ -76,7 +76,7 @@ function(add_musica_test test_name test_binary test_args working_dir) # https://stackoverflow.com/a/66931930/5217293 set_tests_properties(${test_name} PROPERTIES FIXTURES_SETUP f_${test_name}) set_tests_properties(memcheck_${test_name} PROPERTIES FIXTURES_REQUIRED f_${test_name}) - elseif(MEMORYCHECK_COMMAND AND ENABLE_MEMCHECK) + elseif(MEMORYCHECK_COMMAND AND MUSICA_ENABLE_MEMCHECK) add_test(NAME memcheck_${test_name} COMMAND ${memcheck} ${CMAKE_BINARY_DIR}/${test_binary} ${test_args} WORKING_DIRECTORY ${working_dir}) diff --git a/musica-fortran/test/configs/chapman/config.json b/configs/chapman/config.json similarity index 100% rename from musica-fortran/test/configs/chapman/config.json rename to configs/chapman/config.json diff --git a/musica-fortran/test/configs/chapman/reactions.json b/configs/chapman/reactions.json similarity index 100% rename from musica-fortran/test/configs/chapman/reactions.json rename to configs/chapman/reactions.json diff --git a/musica-fortran/test/configs/chapman/species.json b/configs/chapman/species.json similarity index 100% rename from musica-fortran/test/configs/chapman/species.json rename to configs/chapman/species.json diff --git a/docker/Dockerfile b/docker/Dockerfile index 67bc8b20..e6104d97 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -4,7 +4,7 @@ RUN dnf -y update \ && dnf -y install \ cmake \ gcc-c++ \ - gcc-gfortran \ + gdb \ git \ lcov \ make \ @@ -13,19 +13,6 @@ RUN dnf -y update \ 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 @@ -33,7 +20,6 @@ COPY . musica RUN cd musica \ && cmake -S . \ -B build \ - -D ENABLE_TESTS=ON \ && cd build \ && make install -j 8 diff --git a/docker/Dockerfile.fortran-gcc b/docker/Dockerfile.fortran-gcc new file mode 100644 index 00000000..fe096268 --- /dev/null +++ b/docker/Dockerfile.fortran-gcc @@ -0,0 +1,49 @@ +FROM fedora:35 + +RUN dnf -y update \ + && dnf -y install \ + cmake \ + curl \ + gcc \ + gcc-c++ \ + gdb \ + gcc-gfortran \ + git \ + lcov \ + libcurl-devel \ + hdf5-devel \ + netcdf-fortran-devel \ + m4 \ + make \ + json-c-devel \ + valgrind \ + vim \ + zlib-devel \ + && dnf clean all + +# Set environment variables to install MUSICA using gcc +ENV FC=gfortran +ENV CXX=g++ +ENV CC=gcc +ENV FFLAGS="-I/usr/include/" + +# Copy the musica code +COPY . musica + +# Build and install MUSICA +RUN cd musica \ + && cmake -S . \ + -B build \ + -D CMAKE_BUILD_TYPE=Debug \ + && cd build \ + && make install + +RUN cd musica/fortran/test/fetch_content_integration \ + && mkdir build && cd build \ + && cmake .. \ + -D CMAKE_BUILD_TYPE=Debug \ + && make + +RUN cp -r /musica/configs/chapman musica/fortran/test/fetch_content_integration/build + +WORKDIR musica/fortran/test/fetch_content_integration/build \ No newline at end of file diff --git a/docker/Dockerfile.fortran-intel b/docker/Dockerfile.fortran-intel index fd4f23b0..8e90f135 100644 --- a/docker/Dockerfile.fortran-intel +++ b/docker/Dockerfile.fortran-intel @@ -4,72 +4,50 @@ FROM intel/oneapi-hpckit:latest RUN apt update \ && apt -y install \ cmake \ - cmake-curses-gui \ curl \ + gcc \ + gfortran \ + git \ + lcov \ libcurl4-openssl-dev \ libhdf5-dev \ + libnetcdff-dev \ m4 \ + make \ nlohmann-json3-dev \ + valgrind \ vim \ zlib1g-dev \ - git \ - lcov \ - make \ - libnetcdff-dev \ - valgrind \ - gcc \ - gfortran \ && 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 \ + -D MUSICA_ENABLE_TESTS=ON \ + -D MUSICA_ENABLE_TUVX=OFF \ + -D CMAKE_BUILD_TYPE=Debug \ && cd build \ - && make install -j 8 + && make install # Set environment variables to build MUSICA-Fortran using intel compilers ENV CC=icx ENV CXX=icpx -ENV FC=ifort - -# Install json-fortran for intel version -RUN cd json-fortran-8.2.0 \ - && mkdir build-intel \ - && cd build-intel \ - && cmake -D SKIP_DOC_GEN:BOOL=TRUE .. \ - && make install - -# Set json-fortran variable to build MUSICA-Fortran using intel -ENV JSON_FORTRAN_HOME="/usr/local/jsonfortran-intel-8.2.0" +ENV FC=ifx -RUN cd musica/musica-fortran/test \ +RUN cd musica/fortran/test/fetch_content_integration \ && mkdir build && cd build \ && cmake .. \ + -D CMAKE_BUILD_TYPE=Debug \ && make -RUN cd musica/musica-fortran/test \ - && cp -r configs/chapman ./build/chapman +RUN cp -r /musica/configs/chapman musica/fortran/test/fetch_content_integration/build -WORKDIR musica/musica-fortran/test/build \ No newline at end of file +WORKDIR musica/fortran/test/fetch_content_integration/build \ No newline at end of file diff --git a/docker/Dockerfile.fortran-nvhpc b/docker/Dockerfile.fortran-nvhpc new file mode 100644 index 00000000..9c21239a --- /dev/null +++ b/docker/Dockerfile.fortran-nvhpc @@ -0,0 +1,58 @@ +# nvidia rate limits requests. You can get around this by restarting docker if for +# some reason you have to build this image many times +# https://stackoverflow.com/a/75757516/5217293 +# +# Container versions, and sizes, can be found at https://catalog.ngc.nvidia.com/orgs/nvidia/containers/nvhpc/tags +# +FROM nvcr.io/nvidia/nvhpc:23.7-devel-cuda12.2-ubuntu22.04 + +RUN apt update \ + && apt -y install \ + cmake \ + curl \ + gcc \ + gfortran \ + git \ + lcov \ + libcurl4-openssl-dev \ + libhdf5-dev \ + libnetcdff-dev \ + m4 \ + make \ + nlohmann-json3-dev \ + valgrind \ + vim \ + zlib1g-dev \ + && apt clean + +# Set environment variables to install MUSICA using gcc +ENV FC=gfortran +ENV FFLAGS="-I/usr/include/" + +# Copy the musica code +COPY . musica + +# Build and install MUSICA +RUN cd musica \ + && cmake -S . \ + -B build \ + -D MUSICA_ENABLE_TESTS=ON \ + -D MUSICA_ENABLE_TUVX=OFF \ + -D CMAKE_BUILD_TYPE=Debug \ + && cd build \ + && make install + +# Set environment variables to build MUSICA-Fortran using intel compilers +ENV CXX=nvc++ +ENV CC=nvc +ENV FC=nvfortran + +RUN cd musica/fortran/test/fetch_content_integration \ + && mkdir build && cd build \ + && cmake .. \ + -D CMAKE_BUILD_TYPE=Debug \ + && make + +RUN cp -r /musica/configs/chapman musica/fortran/test/fetch_content_integration/build + +WORKDIR musica/fortran/test/fetch_content_integration/build \ No newline at end of file diff --git a/docker/Dockerfile.fortran-ubuntu b/docker/Dockerfile.fortran-ubuntu deleted file mode 100644 index 3c4f6b00..00000000 --- a/docker/Dockerfile.fortran-ubuntu +++ /dev/null @@ -1,60 +0,0 @@ -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/docker/Dockerfile.memcheck b/docker/Dockerfile.memcheck new file mode 100644 index 00000000..0c1aca9f --- /dev/null +++ b/docker/Dockerfile.memcheck @@ -0,0 +1,27 @@ +FROM fedora:35 + +RUN dnf -y update \ + && dnf -y install \ + cmake \ + gcc-c++ \ + gdb \ + git \ + lcov \ + make \ + netcdf-fortran-devel \ + json-devel \ + valgrind \ + && dnf clean all + +# Copy the musica code +COPY . musica + +# Build +RUN cd musica \ + && cmake -S . \ + -B build \ + -D MUSICA_ENABLE_MEMCHECK=ON \ + && cd build \ + && make install -j 8 + +WORKDIR musica/build diff --git a/docker/Dockerfile.mpi b/docker/Dockerfile.mpi index 8590801a..b5e4d7e0 100644 --- a/docker/Dockerfile.mpi +++ b/docker/Dockerfile.mpi @@ -12,7 +12,6 @@ WORKDIR /home/test_user RUN sudo dnf -y install \ cmake \ gcc-c++ \ - gcc-gfortran \ git \ lcov \ make \ @@ -22,21 +21,10 @@ RUN sudo dnf -y install \ valgrind-openmpi \ && 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 .. \ - && sudo make install - # Set environment variables ENV PATH="${PATH}:/usr/lib64/openmpi/bin/" ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib64/openmpi/lib" ENV OMP_NUM_THREADS=3 -ENV FC=gfortran -ENV JSON_FORTRAN_HOME="/usr/local/jsonfortran-gnu-8.2.0" # Copy the musica code COPY . musica/ diff --git a/docker/Dockerfile.mpi_openmp b/docker/Dockerfile.mpi_openmp index 875f0d4f..a06f1f03 100644 --- a/docker/Dockerfile.mpi_openmp +++ b/docker/Dockerfile.mpi_openmp @@ -12,7 +12,6 @@ WORKDIR /home/test_user RUN sudo dnf -y install \ cmake \ gcc-c++ \ - gcc-gfortran \ git \ lcov \ make \ @@ -22,21 +21,10 @@ RUN sudo dnf -y install \ valgrind-openmpi \ && 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 .. \ - && sudo make install - # Set environment variables ENV PATH="${PATH}:/usr/lib64/openmpi/bin/" ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib64/openmpi/lib" ENV OMP_NUM_THREADS=3 -ENV FC=gfortran -ENV JSON_FORTRAN_HOME="/usr/local/jsonfortran-gnu-8.2.0" # copy the MusicBox code COPY . musica/ diff --git a/docker/Dockerfile.no_micm b/docker/Dockerfile.no_micm deleted file mode 100644 index e8a98cc9..00000000 --- a/docker/Dockerfile.no_micm +++ /dev/null @@ -1,41 +0,0 @@ -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/docker/Dockerfile.openmp b/docker/Dockerfile.openmp index cb21aca2..7c48052a 100644 --- a/docker/Dockerfile.openmp +++ b/docker/Dockerfile.openmp @@ -12,7 +12,6 @@ WORKDIR /home/test_user RUN sudo dnf -y install \ cmake \ gcc-c++ \ - gcc-gfortran \ git \ lcov \ make \ @@ -22,20 +21,9 @@ RUN sudo dnf -y install \ valgrind-openmpi \ && 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 .. \ - && sudo make install - # Set environment variables ENV PATH="${PATH}:/usr/lib64/openmpi/bin/" ENV OMP_NUM_THREADS=3 -ENV FC=gfortran -ENV JSON_FORTRAN_HOME="/usr/local/jsonfortran-gnu-8.2.0" # copy the MusicBox code COPY . musica/ diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt new file mode 100644 index 00000000..15d04347 --- /dev/null +++ b/fortran/CMakeLists.txt @@ -0,0 +1,92 @@ +cmake_minimum_required(VERSION 3.21) + +project( + musica-fortran + VERSION ${PROJECT_VERSION} + LANGUAGES Fortran +) + +message (STATUS "CMake build configuration for ${PROJECT_NAME} (${CMAKE_BUILD_TYPE}) ${PROJECT_VERSION}") + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(netcdff IMPORTED_TARGET REQUIRED netcdf-fortran) + +if(NOT TARGET musica) + find_package(musica REQUIRED) +endif() + +add_library(musica-fortran) +add_library(musica::musica-fortran ALIAS musica-fortran) + +set_target_properties(musica-fortran + PROPERTIES + LIBRARY_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR} + Fortran_MODULE_DIRECTORY ${MUSICA_MOD_DIR} + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +target_include_directories(musica-fortran + PUBLIC + $ + $ +) + +target_link_libraries(musica-fortran + PUBLIC + musica +) + +target_sources(musica-fortran + PUBLIC + micm_core.F90 +) + +#################### +# TUV-x +if (MUSICA_ENABLE_TUVX) + set(TUVX_MOD_DIR ${MUSICA_MOD_DIR}) + set(TUVX_LIB_DIR ${MUSICA_LIB_DIR}) + + add_subdirectory(${CMAKE_SOURCE_DIR}/lib/tuv-x/src ${MUSICA_LIB_DIR}/tuv-x/src) + + # for yaml-cpp + target_compile_features(tuvx_object PRIVATE cxx_std_20) + + set_target_properties(tuvx_object PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR} + Fortran_MODULE_DIRECTORY ${MUSICA_MOD_DIR} + ) + + target_include_directories(tuvx_object + PUBLIC + $ + $ + ) + + target_link_libraries(tuvx_object + PUBLIC + musicacore_object + ) + + target_link_libraries(musica-fortran + PUBLIC + yaml-cpp::yaml-cpp + ) + + # add the sources to musica + target_sources(musica-fortran + PRIVATE + $ + ) +endif() + + +################################################################################ +# testing + +if(MUSICA_ENABLE_TESTS) + add_subdirectory(test) +endif() \ No newline at end of file diff --git a/fortran/micm_core.F90 b/fortran/micm_core.F90 new file mode 100644 index 00000000..27b2f564 --- /dev/null +++ b/fortran/micm_core.F90 @@ -0,0 +1,86 @@ +module micm_core + + use iso_c_binding, only: c_ptr, c_char, c_int, c_double, c_null_char + implicit none + + public :: micm_t + private + + interface + function create_micm_c(config_path, error_code) bind(C, name="create_micm") + import c_ptr, c_int, c_char + character(kind=c_char), intent(in) :: config_path(*) + integer(kind=c_int), intent(out) :: error_code + type(c_ptr) :: create_micm_c + end function create_micm_c + + subroutine delete_micm_c(micm) bind(C, name="delete_micm") + import c_ptr + type(c_ptr), intent(in) :: micm + end subroutine delete_micm_c + + subroutine micm_solve_c(micm, time_step, temperature, pressure, num_concentrations, concentrations) bind(C, name="micm_solve") + import c_ptr, c_double, c_int + type(c_ptr), value, intent(in) :: micm + real(kind=c_double), value, intent(in) :: time_step + real(kind=c_double), value, intent(in) :: temperature + real(kind=c_double), value, intent(in) :: pressure + integer(kind=c_int), value, intent(in) :: num_concentrations + real(kind=c_double), intent(inout) :: concentrations(num_concentrations) + end subroutine micm_solve_c + end interface + + type :: micm_t + private + type(c_ptr) :: ptr + contains + ! Solve the chemical system + procedure :: solve + ! Deallocate the micm instance + final :: finalize + end type micm_t + + interface micm_t + procedure constructor + end interface micm_t + +contains + + function constructor(config_path, errcode) result( this ) + type(micm_t), pointer :: this + character(len=*), intent(in) :: config_path + integer, intent(out) :: errcode + character(len=1, kind=c_char) :: c_config_path(len_trim(config_path)+1) + integer :: n, i + + allocate( this ) + + 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 + + this%ptr = create_micm_c(c_config_path, errcode) + + if (errcode /= 0) then + return + end if + end function constructor + + subroutine solve(this, time_step, temperature, pressure, num_concentrations, concentrations) + class(micm_t) :: this + real(c_double), intent(in) :: time_step + real(c_double), intent(in) :: temperature + real(c_double), intent(in) :: pressure + integer(c_int), intent(in) :: num_concentrations + real(c_double), intent(inout) :: concentrations(*) + call micm_solve_c(this%ptr, time_step, temperature, pressure, num_concentrations, concentrations) + end subroutine solve + + subroutine finalize(this) + type(micm_t), intent(inout) :: this + call delete_micm_c(this%ptr) + end subroutine finalize + +end module micm_core diff --git a/fortran/packaging/CMakelists.txt b/fortran/packaging/CMakelists.txt new file mode 100644 index 00000000..ed4eccd5 --- /dev/null +++ b/fortran/packaging/CMakelists.txt @@ -0,0 +1,65 @@ +include(CMakePackageConfigHelpers) + +install( + TARGETS + musica-fortran + EXPORT + musica_fortran_Exports + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} +) + +# install the mod files +install( + DIRECTORY + ${MUSICA_MOD_DIR}/ + DESTINATION + ${MUSICA_INSTALL_INCLUDE_DIR}/musica/fortran + FILES_MATCHING PATTERN "*.mod" +) + +# install the cmake config files +set(cmake_config_install_location "${CMAKE_INSTALL_LIBDIR}/cmake/musica") + +install( + EXPORT + musica_fortran_Exports + DESTINATION + ${cmake_config_install_location} + NAMESPACE musica:: +) + +configure_package_config_file( + "${CMAKE_SOURCE_DIR}/cmake/musicaConfig.cmake.in" + "${PROJECT_BINARY_DIR}/musica_fortranConfig.cmake" + INSTALL_DESTINATION + ${cmake_config_install_location} +) + +write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/musica_fortranConfigVersion.cmake" + VERSION ${PROJECT_VERSION} + COMPATIBILITY SameMajorVersion +) + +install( + FILES + ${PROJECT_BINARY_DIR}/musica_fortranConfig.cmake + ${PROJECT_BINARY_DIR}/musica_fortranConfigVersion.cmake + DESTINATION + ${cmake_config_install_location} +) + +###################################################################### +# uninstall target + +# https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif() \ No newline at end of file diff --git a/fortran/test/CMakeLists.txt b/fortran/test/CMakeLists.txt new file mode 100644 index 00000000..059f2a25 --- /dev/null +++ b/fortran/test/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(unit) \ No newline at end of file diff --git a/fortran/test/fetch_content_integration/CMakeLists.txt b/fortran/test/fetch_content_integration/CMakeLists.txt new file mode 100644 index 00000000..f85e8e06 --- /dev/null +++ b/fortran/test/fetch_content_integration/CMakeLists.txt @@ -0,0 +1,57 @@ +cmake_minimum_required(VERSION 3.21) + +project( + test_musica_fortran + LANGUAGES Fortran C CXX +) + +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) + +include(FetchContent) + +FetchContent_Declare(musica-fortran + GIT_REPOSITORY https://github.com/NCAR/musica.git + GIT_TAG reorganize +) + +set(MUSICA_BUILD_C_CXX_INTERFACE OFF) +set(MUSICA_BUILD_FORTRAN_INTERFACE ON) +set(MUSICA_ENABLE_MICM ON) +set(MUSICA_ENABLE_TUVX OFF) +set(MUSICA_ENABLE_TESTS OFF) + +FetchContent_MakeAvailable(musica-fortran) + +find_package(PkgConfig REQUIRED) +pkg_check_modules(netcdff IMPORTED_TARGET REQUIRED netcdf-fortran) + +enable_testing() + +# API Test +add_executable(test_micm_fort_api test_micm_fort_api.F90) + +target_link_libraries(test_micm_fort_api + PRIVATE + musica::musica-fortran + stdc++ +) + +add_test( + NAME test_micm_fort_api + COMMAND $ + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} +) + +add_executable(test_micm_fort_api_invalid test_micm_fort_api_invalid.F90) + +target_link_libraries(test_micm_fort_api_invalid + PRIVATE + musica::musica-fortran + stdc++ +) + +add_test( + NAME test_micm_fort_api_invalid + COMMAND $ + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} +) \ No newline at end of file diff --git a/fortran/test/fetch_content_integration/test_micm_fort_api.F90 b/fortran/test/fetch_content_integration/test_micm_fort_api.F90 new file mode 100644 index 00000000..d8cf8fe9 --- /dev/null +++ b/fortran/test/fetch_content_integration/test_micm_fort_api.F90 @@ -0,0 +1,48 @@ +program test_micm_fort_api + use iso_c_binding + use micm_core, only: micm_t + + implicit none + + type(micm_t), pointer :: micm + real(c_double) :: time_step + real(c_double) :: temperature + real(c_double) :: pressure + integer(c_int) :: num_concentrations + real(c_double), dimension(5) :: concentrations + integer :: errcode + character(len=7) :: config_path + + time_step = 200 + temperature = 272.5 + pressure = 101253.3 + num_concentrations = 5 + concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) + config_path = "chapman" + + write(*,*) "[test micm fort api] Creating MICM solver..." + micm => micm_t(config_path, errcode) + + if (errcode /= 0) then + write(*,*) "[test micm fort api] Failed in creating solver." + stop 3 + endif + + write(*,*) "[test micm fort api] Initial concentrations", concentrations + + write(*,*) "[test micm fort api] Solving starts..." + call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations) + + write(*,*) "[test micm fort api] After solving, concentrations", concentrations + + call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations) + + write(*,*) "[test micm fort api] After solving, concentrations222", concentrations + + call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations) + + write(*,*) "[test micm fort api] After solving, concentrations333", concentrations + + write(*,*) "[test micm fort api] Finished." + +end program diff --git a/fortran/test/fetch_content_integration/test_micm_fort_api_invalid.F90 b/fortran/test/fetch_content_integration/test_micm_fort_api_invalid.F90 new file mode 100644 index 00000000..71adbd27 --- /dev/null +++ b/fortran/test/fetch_content_integration/test_micm_fort_api_invalid.F90 @@ -0,0 +1,38 @@ +subroutine test_micm_fort_api_invalid() + use iso_c_binding + use micm_core, only: micm_t + + implicit none + + type(micm_t), pointer :: micm + real(c_double) :: time_step + real(c_double) :: temperature + real(c_double) :: pressure + integer(c_int) :: num_concentrations + real(c_double), dimension(5) :: concentrations + integer :: errcode + character(len=7) :: config_path + + time_step = 200 + temperature = 272.5 + pressure = 101253.3 + num_concentrations = 5 + concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) + config_path = "invalid_config" + + write(*,*) "[test micm fort api] Creating MICM solver..." + micm => micm_t(config_path, errcode) + + if (errcode /= 0) then + write(*,*) "[test micm fort api] Failed in creating solver. Expected failure. Error code: ", errcode + stop 0 + else + write(*,*) "[test micm fort api] Unexpected error code: ", errcode + stop 3 + endif + +end subroutine + +program test_micm_api + call test_micm_fort_api_invalid() +end program diff --git a/fortran/test/unit/CMakeLists.txt b/fortran/test/unit/CMakeLists.txt new file mode 100644 index 00000000..f67af53f --- /dev/null +++ b/fortran/test/unit/CMakeLists.txt @@ -0,0 +1,11 @@ +include(test_util) + +if (MUSICA_ENABLE_TUVX) + create_standard_test_fortran(NAME connect_to_tuvx SOURCES tuvx.F90) + 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() +endif() \ No newline at end of file diff --git a/musica/test/connections/tuvx.F90 b/fortran/test/unit/tuvx.F90 similarity index 100% rename from musica/test/connections/tuvx.F90 rename to fortran/test/unit/tuvx.F90 diff --git a/musica/test/connections/tuvx_mpi.F90 b/fortran/test/unit/tuvx_mpi.F90 similarity index 100% rename from musica/test/connections/tuvx_mpi.F90 rename to fortran/test/unit/tuvx_mpi.F90 diff --git a/musica/test/connections/tuvx_openmp.F90 b/fortran/test/unit/tuvx_openmp.F90 similarity index 100% rename from musica/test/connections/tuvx_openmp.F90 rename to fortran/test/unit/tuvx_openmp.F90 diff --git a/include/musica/component_versions.h b/include/musica/component_versions.h new file mode 100644 index 00000000..d77f5149 --- /dev/null +++ b/include/musica/component_versions.h @@ -0,0 +1,17 @@ +/** + * This file contains the version information for the different project modules + * Copyright (C) 2023-2024 National Center for Atmospheric Research, + * + * SPDX-License-Identifier: Apache-2.0* creating solvers, and solving the model. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +char* getAllComponentVersions(); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp new file mode 100644 index 00000000..4a680363 --- /dev/null +++ b/include/musica/micm.hpp @@ -0,0 +1,57 @@ +/** + * This file contains the defintion of the MICM class, which represents a multi-component + * reactive transport model. It also includes functions for creating and deleting MICM instances with c binding + * Copyright (C) 2023-2024 National Center for Atmospheric Research, + * + * SPDX-License-Identifier: Apache-2.0* creating solvers, and solving the model. + */ +#pragma once + +#include + +#include +#include +#include + +class MICM; + +#ifdef __cplusplus +extern "C" { +#endif + +MICM* create_micm(const char* config_path, int* error_code); +void delete_micm(const MICM* micm); +void micm_solve(MICM* micm, double time_step, double temperature, double pressure, int num_concentrations, double* concentrations); + +#ifdef __cplusplus +} +#endif + +class MICM +{ +public: + /// @brief Constructor + MICM(); + + /// @brief Destructor + ~MICM(); + + /// @brief Create a solver by reading and parsing configuration file + /// @param config_path Path to configuration file or directory containing configuration file + /// @return 0 on success, 1 on failure in parsing configuration file + int create_solver(const std::string& config_path); + + /// @brief Solve the system + /// @param time_step Time [s] to advance the state by + /// @para/ @briefm temperature Temperature [K] + /// @param pressure Pressure/ [P@brief C@param num_concentrations The number oconfiguration file + /// @param config_path Path to configuration file or directory containing configuration file + /// @return 0 on success, 1 on failure in parsing species' concentrations + /// @param concentrations Species's concentrations + void solve(double time_step, double temperature, double pressure, int num_concentrations, double* concentrations); + + static constexpr size_t NUM_GRID_CELLS = 1; + +private: + std::unique_ptr> solver_; +}; \ No newline at end of file diff --git a/musica/include/musica/version.h b/include/musica/version.h similarity index 52% rename from musica/include/musica/version.h rename to include/musica/version.h index caa53615..d94b5572 100644 --- a/musica/include/musica/version.h +++ b/include/musica/version.h @@ -1,3 +1,9 @@ +/** + * This file contains the version information for the project + * Copyright (C) 2023-2024 National Center for Atmospheric Research, + * + * SPDX-License-Identifier: Apache-2.0* creating solvers, and solving the model. + */ #pragma once #ifdef __cplusplus diff --git a/lib/musica-core b/lib/musica-core deleted file mode 160000 index d5bdc303..00000000 --- a/lib/musica-core +++ /dev/null @@ -1 +0,0 @@ -Subproject commit d5bdc303fe9afbae8f7585a11bcb660534b97f23 diff --git a/lib/tuv-x b/lib/tuv-x index daba6579..a5c71420 160000 --- a/lib/tuv-x +++ b/lib/tuv-x @@ -1 +1 @@ -Subproject commit daba657958baa3a499ae7fa470f3df0073655c67 +Subproject commit a5c71420b5e72bf24570b34f28d43656772d1e76 diff --git a/musica-fortran/CMakeLists.txt b/musica-fortran/CMakeLists.txt deleted file mode 100644 index b8e2e651..00000000 --- a/musica-fortran/CMakeLists.txt +++ /dev/null @@ -1,40 +0,0 @@ -cmake_minimum_required(VERSION 3.21) - -project( - musica-fortran - VERSION 0.0.0 - LANGUAGES Fortran C CXX -) - -# Set up include and lib directories -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) -set(MUSICA_FORTRAN_MOD_DIR ${PROJECT_BINARY_DIR}/include) -set(MUSICA_FORTRAN_LIB_DIR ${PROJECT_BINARY_DIR}/libs) - -add_library(musica-fortran STATIC) -add_library(musica::musica-fortran ALIAS musica-fortran) - -set_target_properties(musica-fortran -PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_FORTRAN_LIB_DIR} - Fortran_MODULE_DIRECTORY ${MUSICA_FORTRAN_MOD_DIR} -) - -find_package(PkgConfig REQUIRED) -pkg_check_modules(netcdff IMPORTED_TARGET REQUIRED netcdf-fortran) - -# Find MUSICA package -find_package(musica 0.5.0 REQUIRED) - -target_link_libraries(musica-fortran - PUBLIC - musica::musica) - -target_include_directories(musica-fortran - PUBLIC - $ - $ -) - -# Add sources -add_subdirectory(src) \ No newline at end of file diff --git a/musica-fortran/src/CMakeLists.txt b/musica-fortran/src/CMakeLists.txt deleted file mode 100644 index d3a7ab7d..00000000 --- a/musica-fortran/src/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(micm) \ No newline at end of file diff --git a/musica-fortran/src/micm/CMakeLists.txt b/musica-fortran/src/micm/CMakeLists.txt deleted file mode 100644 index 39634b78..00000000 --- a/musica-fortran/src/micm/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -target_sources(musica-fortran - PUBLIC - micm_core.F90 -) \ No newline at end of file diff --git a/musica-fortran/src/micm/micm_core.F90 b/musica-fortran/src/micm/micm_core.F90 deleted file mode 100644 index bb3fc1de..00000000 --- a/musica-fortran/src/micm/micm_core.F90 +++ /dev/null @@ -1,103 +0,0 @@ -module micm_core - ! Top-level MICM interface - - use iso_c_binding - - implicit none - - private - public :: micm_t - - 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 - type(c_ptr), intent(in), value :: micm_t - end function - - subroutine micm_solve_c(micm_t, temperature, pressure, time_step, num_concentrations, 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 - integer, value, intent(in) :: num_concentrations - real(c_double), dimension(*), intent(inout) :: concentrations - end subroutine - end interface - - type :: micm_t - private - type(c_ptr) :: ptr - contains - ! Create a solver from configure file - procedure :: create_solver => micm_create_solver - ! Solve the chemical system - procedure :: solve => micm_solve - ! Deallocate the micm instance - final :: finalize - end type micm_t - - interface micm_t - procedure create_micm - end interface micm_t - -contains - - function create_micm(config_path) - ! Constructor of micm objects - - 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 - - ! Convert 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) - - return - end function create_micm - - subroutine finalize(this) - type(micm_t), intent(inout) :: this - call delete_micm_c(this%ptr) - end subroutine finalize - - integer function micm_create_solver(this) - class(micm_t), intent(in) :: this - micm_create_solver = micm_create_solver_c(this%ptr) - end function micm_create_solver - - subroutine micm_solve(this, temperature, pressure, time_step, num_concentrations, 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 - integer, intent(in) :: num_concentrations - real(c_double), dimension(*), intent(inout) :: concentrations - call micm_solve_c(this%ptr, temperature, pressure, time_step, num_concentrations, concentrations) - end subroutine micm_solve - -end module micm_core \ No newline at end of file diff --git a/musica-fortran/test/CMakeLists.txt b/musica-fortran/test/CMakeLists.txt deleted file mode 100644 index 365f4c25..00000000 --- a/musica-fortran/test/CMakeLists.txt +++ /dev/null @@ -1,61 +0,0 @@ -cmake_minimum_required(VERSION 3.21) - -project( - test_musica_fortran_wrapper - VERSION 0.0.0 - LANGUAGES Fortran C CXX -) - -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) - -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 c3dff0f # TODO(jiwon) - update the tag -) - -FetchContent_MakeAvailable(musica) - -################################################################################ -# Test MUSICA API -add_executable(test_musica_api test_musica_api.F90) - -target_link_libraries(test_musica_api - PUBLIC - musica::musica-fortran -) - -set_target_properties(test_musica_api -PROPERTIES -LINKER_LANGUAGE Fortran) - -enable_testing() - -add_test( - NAME test_musica_api - COMMAND $ -) - -# Test MUSICA API with invalid configuration files -add_executable(test_invalid_config test_musica_api_invalid_config.F90) - -target_link_libraries(test_invalid_config - PUBLIC - musica::musica-fortran -) - -set_target_properties(test_invalid_config -PROPERTIES -LINKER_LANGUAGE Fortran) - -enable_testing() - -add_test( - NAME test_invalid_config - COMMAND $ -) \ No newline at end of file diff --git a/musica-fortran/test/test_musica_api.F90 b/musica-fortran/test/test_musica_api.F90 deleted file mode 100644 index 8e20490d..00000000 --- a/musica-fortran/test/test_musica_api.F90 +++ /dev/null @@ -1,43 +0,0 @@ -program test - use iso_c_binding - use micm_core - - implicit none - - type(micm_t) :: micm - real(c_double) :: temperature - real(c_double) :: pressure - real(c_double) :: time_step - integer :: num_concentrations - real(c_double), dimension(5) :: concentrations - integer :: errcode - - temperature = 10d0 - pressure = 20d0 - time_step = 1d0 - num_concentrations = 5 - concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) - - write(*,*) " * [Fortran] Creating MICM..." - micm = micm_t("chapman") - - write(*,*) " * [Fortran] Creating solver..." - errcode = micm%create_solver() - - if (errcode == 0) then - 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 micm%solve(temperature, pressure, time_step, num_concentrations, concentrations) - - write(*,*) " * [Fortran] After solving, concentrations", concentrations - else - write(*,*) " * [Fortran] Failed in creating solver" - stop 3 - endif - -end program \ No newline at end of file diff --git a/musica-fortran/test/test_musica_api_invalid_config.F90 b/musica-fortran/test/test_musica_api_invalid_config.F90 deleted file mode 100644 index 1e72a46b..00000000 --- a/musica-fortran/test/test_musica_api_invalid_config.F90 +++ /dev/null @@ -1,35 +0,0 @@ -program test - use iso_c_binding - use micm_core - - implicit none - - type(micm_t) :: micm - real(c_double) :: temperature - real(c_double) :: pressure - real(c_double) :: time_step - integer :: num_concentrations - real(c_double), dimension(10) :: concentrations - integer :: errcode - - temperature = 10d0 - pressure = 20d0 - time_step = 1d0 - num_concentrations = 10 - concentrations = (/ 1d0, 2d0, 3d0, 4d0, 5d0, 6d0, 7d0, 8d0, 9d0, 10d0 /) - - write(*,*) " * [Fortran] Creating MICM..." - micm = micm_t("invalid_config") - - write(*,*) " * [Fortran] Creating solver..." - errcode = micm%create_solver() - - if (errcode == 1) then - write(*,*) " * [Fortran] Failed in creating solver. Expected failure. Error code: ", errcode - stop 0 - else - write(*,*) " * [Fortran] Unexpected error code: ", errcode - stop 3 - endif - -end program \ No newline at end of file diff --git a/musica/CMakeLists.txt b/musica/CMakeLists.txt deleted file mode 100644 index a1eb7a81..00000000 --- a/musica/CMakeLists.txt +++ /dev/null @@ -1,140 +0,0 @@ -################################################################################ -# Preamble - -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "Release" CACHE STRING - "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif(NOT CMAKE_BUILD_TYPE) - -message (STATUS "CMake build configuration for musica(${CMAKE_BUILD_TYPE}) ${PROJECT_VERSION}") - -include(musica_util) - -# Add submodules -checkout_submodules() - -################################################################################ -# Dependencies - -include(dependencies) - -############################################################################## -# MUSICA targets - -#################### -# MUSICA -add_library(musica STATIC) -add_library(musica::musica ALIAS musica) - -add_subdirectory(src) - -set_target_properties(musica PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR} - Fortran_MODULE_DIRECTORY ${MUSICA_MOD_DIR} - VERSION ${PROJECT_VERSION} - SOVERSION ${PROJECT_VERSION_MAJOR} -) - -target_link_libraries(musica - PRIVATE - PkgConfig::netcdff - ${JSON_LIB} -) - -target_include_directories(musica - PUBLIC - $ - $ -) - -target_include_directories(musica - PUBLIC - $ - $ -) - -#################### -# MUSICA-core -add_library(musicacore_object) -add_library(musica::musicacore ALIAS musicacore_object) - -set(ENABLE_UTIL_ONLY ON) - -set_target_properties(musicacore_object PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR} - Fortran_MODULE_DIRECTORY ${MUSICA_MOD_DIR} -) - -target_include_directories(musicacore_object - PUBLIC - $ - $ -) - -target_link_libraries(musicacore_object - PRIVATE - PkgConfig::netcdff -) - -# add the sources to musica -target_sources(musica - PRIVATE - $ -) - -add_subdirectory(${PROJECT_SOURCE_DIR}/lib/musica-core/src ${MUSICA_LIB_DIR}/musica-core/src) - -#################### -# TUV-x -if (ENABLE_TUVX) - set(TUVX_MOD_DIR ${MUSICA_MOD_DIR}) - set(TUVX_LIB_DIR ${MUSICA_LIB_DIR}) - - add_subdirectory(${PROJECT_SOURCE_DIR}/lib/tuv-x/src ${MUSICA_LIB_DIR}/tuv-x/src) - - set_target_properties(tuvx_object PROPERTIES - ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR} - Fortran_MODULE_DIRECTORY ${MUSICA_MOD_DIR} - ) - - target_include_directories(tuvx_object - PUBLIC - $ - $ - ) - - target_link_libraries(tuvx_object - PUBLIC - musicacore_object - ) - - # add the sources to musica - target_sources(musica - PRIVATE - $ - ) -endif() - -#################### -# MICM -if (ENABLE_MICM) - target_compile_features(musica PUBLIC cxx_std_20) - - target_include_directories(musica - PUBLIC - $ - $ - ) - - install( - DIRECTORY - ${PROJECT_SOURCE_DIR}/lib/micm/include/ - DESTINATION - ${INSTALL_INCLUDE_DIR} - ) -endif() - -################################################################################ -# Packaging -add_subdirectory(packaging) \ No newline at end of file diff --git a/musica/include/micm/micm.hpp b/musica/include/micm/micm.hpp deleted file mode 100644 index 86a6d65f..00000000 --- a/musica/include/micm/micm.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include -#include -#include - -#include -#include -#include - - -class MICM -{ -public: - /// @brief Constructor - /// @param config_path Path to the configuration file or the directory containing the configuration files - MICM(const std::string& config_path); - - /// @brief Destructor - ~MICM(); - - /// @brief Create a solver - /// @return Status of solver creation related to parsing configuration files. - /// The return value represents the error code for CAM-SIMA - int create_solver(); - - /// @brief Solve the system - /// @param temperature Temperature [K] - /// @param pressure Pressure [Pa-1] - /// @param time_step Time [s] to advance the state by - /// @param num_concentrations The number of species' concentrations - /// @param concentrations Species's concentrations - void solve(double temperature, double pressure, double time_step, int num_concentrations, double*& 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_; -}; \ No newline at end of file diff --git a/musica/include/micm/micm_c.h b/musica/include/micm/micm_c.h deleted file mode 100644 index c13fb4ca..00000000 --- a/musica/include/micm/micm_c.h +++ /dev/null @@ -1,17 +0,0 @@ -#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, int num_concentrations, - double* concentrations); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/musica/include/musica/component_versions.h b/musica/include/musica/component_versions.h deleted file mode 100644 index 119f5dba..00000000 --- a/musica/include/musica/component_versions.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -char* getAllComponentVersions(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/musica/src/CMakeLists.txt b/musica/src/CMakeLists.txt deleted file mode 100644 index 585b6731..00000000 --- a/musica/src/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -# version -configure_file(version.c.in ${CMAKE_BINARY_DIR}/version.c @ONLY) - -target_sources(musica - PRIVATE - component_versions.c - ${CMAKE_BINARY_DIR}/version.c -) - -if(ENABLE_MICM) - add_subdirectory(micm) -endif() \ No newline at end of file diff --git a/musica/src/micm/micm.cpp b/musica/src/micm/micm.cpp deleted file mode 100644 index 3a7155c3..00000000 --- a/musica/src/micm/micm.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include - -#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; - - micm::SolverConfig solver_config; - micm::ConfigParseStatus status = solver_config.ReadAndParse(config_path_); - - if (status == micm::ConfigParseStatus::Success) - { - micm::SolverParameters solver_params = solver_config.GetSolverParams(); - 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 - { - faliure = 1; - } - - return faliure; -} - -void MICM::solve(double temperature, double pressure, double time_step, int num_concentrations, double*& 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; i -#include - -Micm* create_micm(const char* config_path) -{ - return new MICM(std::string(config_path)); -} - -void delete_micm(const Micm* micm) -{ - delete micm; -} - -int micm_create_solver(Micm* micm) -{ - return micm->create_solver(); -} - -void micm_solve(Micm* micm, double temperature, double pressure, double time_step, int num_concentrations, double* concentrations) -{ - micm->solve(temperature, pressure, time_step, num_concentrations, concentrations); -} \ No newline at end of file diff --git a/musica/test/connections/CMakeLists.txt b/musica/test/connections/CMakeLists.txt deleted file mode 100644 index a13cc463..00000000 --- a/musica/test/connections/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -include(test_util) - -create_standard_test(NAME connect_to_musica_core SOURCES musica_core.F90) - -if (ENABLE_OPENMP) - create_standard_test(NAME connect_to_musica_core_openmp SOURCES musica_core_openmp.F90) -endif() - -if (ENABLE_MPI) - create_standard_test(NAME connect_to_musica_core_mpi SOURCES musica_core_mpi.F90) -endif() - -if (ENABLE_TUVX) - create_standard_test(NAME connect_to_tuvx SOURCES tuvx.F90) - if (ENABLE_OPENMP) - create_standard_test(NAME connect_to_tuvx_openmp SOURCES tuvx_openmp.F90) - endif() - if (ENABLE_MPI) - create_standard_test(NAME connect_to_tuvx_mpi SOURCES tuvx_mpi.F90) - endif() -endif() - -if (ENABLE_MICM) - create_standard_test_cxx(NAME connect_to_micm SOURCES micm.cpp) -endif() \ No newline at end of file diff --git a/musica/test/connections/musica_core.F90 b/musica/test/connections/musica_core.F90 deleted file mode 100644 index 31545505..00000000 --- a/musica/test/connections/musica_core.F90 +++ /dev/null @@ -1,19 +0,0 @@ -! Copyright (C) 2022 National Center for Atmospheric Research -! SPDX-License-Identifier: Apache-2.0 -! -!> \file -!> Tests for that we can connect to tuvx using the monolith static library for musica - -!> Test module for the tuvx connection -program test_musica_connection - use musica_assert - - implicit none - - call assert(1234312, 1 == 1) - -contains - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -end program test_musica_connection diff --git a/musica/test/connections/musica_core_mpi.F90 b/musica/test/connections/musica_core_mpi.F90 deleted file mode 100644 index 70bc11e7..00000000 --- a/musica/test/connections/musica_core_mpi.F90 +++ /dev/null @@ -1,37 +0,0 @@ -! Copyright (C) 2022 National Center for Atmospheric Research -! SPDX-License-Identifier: Apache-2.0 -! -!> \file -!> Tests for that we can connect to tuvx using the monolith static library for musica - -!> Test module for the tuvx connection -program test_musica_connection - use musica_assert - use musica_mpi - - implicit none - - call musica_mpi_init( ) - call test_musicacore( ) - call musica_mpi_finalize( ) - -contains - - subroutine test_musicacore() - integer, parameter :: comm = MPI_COMM_WORLD - integer :: send_integer, recv_integer - - call assert( 357761664, musica_mpi_support( ) ) - call assert( 455191678, musica_mpi_size( comm ) > 1 ) - - call musica_mpi_barrier( comm ) - - send_integer = 0 - if( musica_mpi_rank( comm ) == 0 ) send_integer = 42 - call musica_mpi_bcast( send_integer, comm ) - call assert( 353714667, send_integer == 42 ) - end subroutine test_musicacore - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -end program test_musica_connection diff --git a/musica/test/connections/musica_core_openmp.F90 b/musica/test/connections/musica_core_openmp.F90 deleted file mode 100644 index 5a81cb39..00000000 --- a/musica/test/connections/musica_core_openmp.F90 +++ /dev/null @@ -1,34 +0,0 @@ -! Copyright (C) 2022 National Center for Atmospheric Research -! SPDX-License-Identifier: Apache-2.0 -! -!> \file -!> Tests for that we can connect to tuvx using the monolith static library for musica - -!> Test module for the tuvx connection -program test_musica_connection - use musica_assert -#ifdef MUSICA_USE_OPENMP - use omp_lib -#endif - - implicit none - -#ifdef MUSICA_USE_OPENMP - write(*,*) "Testing with ", omp_get_max_threads( ), " threads" -#else - write(*,*) "Testing without OpenMP support" -#endif - - !$omp parallel - call test_musicacore( ) - !$omp end parallel - -contains - - subroutine test_musicacore() - call assert(1234312, 1 == 1) - end subroutine test_musicacore - -!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -end program test_musica_connection diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 00000000..7e64cc37 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,89 @@ +################################################################################ +# Preamble + +project( + musica + VERSION ${PROJECT_VERSION} + LANGUAGES C CXX +) + +message (STATUS "CMake build configuration for ${PROJECT_NAME} (${CMAKE_BUILD_TYPE}) ${PROJECT_VERSION}") + +include(musica_util) + +# Add submodules +checkout_submodules() + +############################################################################## +# MUSICA targets + +#################### +# MUSICA +add_library(musica) +add_library(musica::musica ALIAS musica) + +set(MUSICA_COMPILE_DEFINITIONS) + +if(MUSICA_ENABLE_MICM) + list(APPEND MUSICA_COMPILE_DEFINITIONS -DMUSICA_USE_MICM) +endif() + +if(MUSICA_ENABLE_MPI) + list(APPEND MUSICA_COMPILE_DEFINITIONS -DMUSICA_USE_MPI) +endif() + +if(MUSICA_ENABLE_OPENMP) + list(APPEND MUSICA_COMPILE_DEFINITIONS -DMUSICA_USE_OPENMP) +endif() + +target_compile_definitions(musica PRIVATE ${MUSICA_COMPILE_DEFINITIONS}) + +set_target_properties(musica PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY ${MUSICA_LIB_DIR} + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) + +target_include_directories(musica + PUBLIC + $ + $ +) + +# version +configure_file(version.c.in ${CMAKE_BINARY_DIR}/version.c @ONLY) + +target_sources(musica + PRIVATE + component_versions.c + ${CMAKE_BINARY_DIR}/version.c +) + +#################### +# MICM +if(MUSICA_ENABLE_MICM) + target_compile_features(musica PUBLIC cxx_std_20) + + target_include_directories(musica + PUBLIC + $ + $ + ) + + target_link_libraries(musica PRIVATE nlohmann_json::nlohmann_json) + + add_subdirectory(micm) +endif() + +################################################################################ +# testing + +if(MUSICA_ENABLE_TESTS) + add_subdirectory(test) +endif() + +################################################################################ +# Packaging +if(MUSICA_ENABLE_INSTALL) + add_subdirectory(packaging) +endif() \ No newline at end of file diff --git a/musica/src/component_versions.c b/src/component_versions.c similarity index 78% rename from musica/src/component_versions.c rename to src/component_versions.c index 1bc3cbc8..5f0989b6 100644 --- a/musica/src/component_versions.c +++ b/src/component_versions.c @@ -1,3 +1,10 @@ +/** + * This file defines functions to manage and retrieve versions of components in a software system. + * It provides functionality to compare versions, check compatibility, and retrieve version information. + * Copyright (C) 2023-2024 National Center for Atmospheric Research, + * + * SPDX-License-Identifier: Apache-2.0* creating solvers, and solving the model. + */ #include #include #include diff --git a/musica/src/micm/CMakeLists.txt b/src/micm/CMakeLists.txt similarity index 70% rename from musica/src/micm/CMakeLists.txt rename to src/micm/CMakeLists.txt index bf1ab6d6..57442af7 100644 --- a/musica/src/micm/CMakeLists.txt +++ b/src/micm/CMakeLists.txt @@ -1,5 +1,4 @@ target_sources(musica PRIVATE - micm_c_api.cpp micm.cpp ) \ No newline at end of file diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp new file mode 100644 index 00000000..4ae1ce98 --- /dev/null +++ b/src/micm/micm.cpp @@ -0,0 +1,86 @@ +/** + * This file contains the implementation of the MICM class, which represents a multi-component + * reactive transport model. It also includes functions for creating and deleting MICM instances, + * Copyright (C) 2023-2024 National Center for Atmospheric Research, + * + * SPDX-License-Identifier: Apache-2.0* creating solvers, and solving the model. + */ +#include +#include + +#include +#include +#include + +MICM* create_micm(const char* config_path, int* error_code) +{ + try { + MICM* micm = new MICM(); + *error_code = micm->create_solver(std::string(config_path)); + return micm; + } + catch (const std::bad_alloc& e) { + *error_code = 1; + return nullptr; + } +} + +void delete_micm(const MICM* micm) +{ + delete micm; +} + +void micm_solve(MICM* micm, double time_step, double temperature, double pressure, int num_concentrations, double* concentrations) +{ + micm->solve(time_step, temperature, pressure, num_concentrations, concentrations); +} + +MICM::MICM() : solver_(nullptr) {} + +MICM::~MICM() +{ + std::cout << "MICM destructor called" << std::endl; +} + +int MICM::create_solver(const std::string &config_path) +{ + int parsing_status = 0; // 0 on success, 1 on failure + + micm::SolverConfig<> solver_config; + micm::ConfigParseStatus status = solver_config.ReadAndParse(std::filesystem::path(config_path)); + + if (status == micm::ConfigParseStatus::Success) + { + micm::SolverParameters solver_params = solver_config.GetSolverParams(); + auto params = micm::RosenbrockSolverParameters::three_stage_rosenbrock_parameters(NUM_GRID_CELLS); + solver_ = std::make_unique>(solver_params.system_, + solver_params.processes_, + params); + } + else + { + parsing_status = 1; + } + + return parsing_status; +} + +void MICM::solve(double time_step, double temperature, double pressure, int num_concentrations, double *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; + } + + state.variables_.AsVector().assign(concentrations, concentrations + num_concentrations); + + auto result = solver_->Solve(time_step, state); + + for (int i = 0; i < result.result_.AsVector().size(); i++) + { + concentrations[i] = result.result_.AsVector()[i]; + } +} \ No newline at end of file diff --git a/musica/packaging/CMakeLists.txt b/src/packaging/CMakeLists.txt similarity index 74% rename from musica/packaging/CMakeLists.txt rename to src/packaging/CMakeLists.txt index 49134722..331b72ab 100644 --- a/musica/packaging/CMakeLists.txt +++ b/src/packaging/CMakeLists.txt @@ -1,46 +1,52 @@ include(CMakePackageConfigHelpers) install( - TARGETS - musica musicacore_object - EXPORT + TARGETS + musica + nlohmann_json + EXPORT musica_Exports - LIBRARY DESTINATION ${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) -# install the mod files +# install the musica header files install( - DIRECTORY - ${MUSICA_MOD_DIR}/ + DIRECTORY + ${CMAKE_SOURCE_DIR}/include/ + DESTINATION + ${MUSICA_INSTALL_INCLUDE_DIR} +) + +install( + FILES + ${MUSICA_FORTRAN_SRC_DIR}/micm_core.F90 DESTINATION - ${INSTALL_INCLUDE_DIR} - FILES_MATCHING PATTERN "*.mod" + ${MUSICA_INSTALL_INCLUDE_DIR}/musica/fortran ) -if(MAKE_MUSICA_FORTRAN_INSTALLABLE) +if (MUSICA_ENABLE_MICM) install( - DIRECTORY - ${MUSICA_FORTRAN_SRC_DIR}/ + DIRECTORY + ${CMAKE_SOURCE_DIR}/lib/micm/include/ DESTINATION - ${INSTALL_PREFIX}/fortran_include/ - FILES_MATCHING PATTERN "*.F90" + ${MUSICA_INSTALL_INCLUDE_DIR}/musica ) endif() # install the cmake config files -set(cmake_config_install_location ${INSTALL_PREFIX}/cmake) +set(cmake_config_install_location "${CMAKE_INSTALL_LIBDIR}/cmake/musica") install( - EXPORT - musica_Exports - DESTINATION + EXPORT + musica_Exports + DESTINATION ${cmake_config_install_location} NAMESPACE musica:: ) configure_package_config_file( - "${PROJECT_SOURCE_DIR}/cmake/musicaConfig.cmake.in" + "${CMAKE_SOURCE_DIR}/cmake/musicaConfig.cmake.in" "${PROJECT_BINARY_DIR}/musicaConfig.cmake" INSTALL_DESTINATION ${cmake_config_install_location} @@ -66,7 +72,7 @@ install( # https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake if(NOT TARGET uninstall) configure_file( - "${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) @@ -77,7 +83,7 @@ endif() ###################################################################### # Environment module -if (CREATE_ENVIRONMENT_MODULE) +if (MUSICA_CREATE_ENVIRONMENT_MODULE) # Define the paths and environment variables for the module set(MODULE_NAME ${PROJECT_VERSION}.lua) set(MODULE_FILE_PATH ${CMAKE_BINARY_DIR}/modulefiles/${PROJECT_NAME}/${MODULE_NAME}) @@ -91,7 +97,7 @@ if (CREATE_ENVIRONMENT_MODULE) ${MODULE_FILE_PATH} @ONLY) - if(INSTALL_MODULE_FILE_PATH) + if(MUSICA_INSTALL_MODULE_FILE_PATH) # Create a custom target for installing the module file add_custom_target(install_lmod_module COMMAND ${CMAKE_COMMAND} -E copy diff --git a/musica/packaging/modulefile.lua.in b/src/packaging/modulefile.lua.in similarity index 73% rename from musica/packaging/modulefile.lua.in rename to src/packaging/modulefile.lua.in index 1fa6e11a..62e33aa9 100644 --- a/musica/packaging/modulefile.lua.in +++ b/src/packaging/modulefile.lua.in @@ -4,7 +4,11 @@ whatis("@PROJECT_NAME@ v@PROJECT_VERSION@") -- The message printed by the module help command help([[ MUSICA: Mulitscale Interface for Chemistry and Aerosols -For more information, visit https://github.com/NCAR/musica +For more information, visit https://github.com/NCAR/musica. + +This module represnts modules that support the MUSICA project. Please note +that this software library is not the same as MUSICAv0, which is a configuration +of CESM. Example usage of `find_package` in a CMakeLists.txt file: @@ -17,7 +21,7 @@ local base = "@MODULE_INSTALL_PATH@" local libpath = pathJoin(base, "/lib") -- libraries local incpath = pathJoin(base, "/include") -- include files -always_load("cmake/3.22.0", "json-fortran/8.3.0") +always_load("cmake/3.22.0") -- Set variables to use with cmake setenv("musica_ROOT", base) diff --git a/musica/test/CMakeLists.txt b/src/test/CMakeLists.txt similarity index 100% rename from musica/test/CMakeLists.txt rename to src/test/CMakeLists.txt diff --git a/src/test/connections/CMakeLists.txt b/src/test/connections/CMakeLists.txt new file mode 100644 index 00000000..22007dff --- /dev/null +++ b/src/test/connections/CMakeLists.txt @@ -0,0 +1,12 @@ +include(test_util) + +if (MUSICA_ENABLE_MICM) + create_standard_test_cxx(NAME connect_to_micm SOURCES micm.cpp) + create_standard_test_cxx(NAME micm_c_api SOURCES micm_c_api.cpp) + + ################################################################################ + # Copy test data + + add_custom_target(copy_unit_test_configs ALL ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_SOURCE_DIR}/configs ${CMAKE_BINARY_DIR}/configs) +endif() \ No newline at end of file diff --git a/musica/test/connections/micm.cpp b/src/test/connections/micm.cpp similarity index 70% rename from musica/test/connections/micm.cpp rename to src/test/connections/micm.cpp index abd65c47..848d2026 100644 --- a/musica/test/connections/micm.cpp +++ b/src/test/connections/micm.cpp @@ -1,7 +1,9 @@ #include +#include #include TEST(ConnectToMICM, Version) { std::string version = micm::getMicmVersion(); + std::cout << version << std::endl; } \ No newline at end of file diff --git a/src/test/connections/micm_c_api.cpp b/src/test/connections/micm_c_api.cpp new file mode 100644 index 00000000..c7ee270c --- /dev/null +++ b/src/test/connections/micm_c_api.cpp @@ -0,0 +1,44 @@ +#include +#include + +// Test fixture for the MICM C API +class MicmCApiTest : public ::testing::Test { +protected: + MICM* micm; + int error_code; + const char* config_path = "configs/chapman"; + + void SetUp() override { + micm = nullptr; + error_code = 0; + micm = create_micm(config_path, &error_code); + } + + void TearDown() override { + delete_micm(micm); + } +}; + +// Test case for creating the MICM instance +TEST_F(MicmCApiTest, CreateMicmInstance) { + ASSERT_EQ(error_code, 0); + ASSERT_NE(micm, nullptr); +} + +// Test case for solving the MICM instance +TEST_F(MicmCApiTest, SolveMicmInstance) { + double time_step = 200.0; + double temperature = 272.5; + double pressure = 101253.3; + int num_concentrations = 5; + double concentrations[] = {0.75, 0.4, 0.8, 0.01, 0.02}; + + micm_solve(micm, time_step, temperature, pressure, num_concentrations, concentrations); + + // Add assertions to check the solved concentrations + ASSERT_EQ(concentrations[0], 0.75); + ASSERT_NE(concentrations[1], 0.4); + ASSERT_NE(concentrations[2], 0.8); + ASSERT_NE(concentrations[3], 0.01); + ASSERT_NE(concentrations[4], 0.02); +} \ No newline at end of file diff --git a/musica/test/unit/CMakeLists.txt b/src/test/unit/CMakeLists.txt similarity index 100% rename from musica/test/unit/CMakeLists.txt rename to src/test/unit/CMakeLists.txt diff --git a/musica/test/unit/component_versions.cpp b/src/test/unit/component_versions.cpp similarity index 100% rename from musica/test/unit/component_versions.cpp rename to src/test/unit/component_versions.cpp diff --git a/musica/src/version.c.in b/src/version.c.in similarity index 100% rename from musica/src/version.c.in rename to src/version.c.in From 3417f1e14466431c3cf7779f4f86e931cfd3dbd0 Mon Sep 17 00:00:00 2001 From: Jiwon Gim Date: Thu, 14 Mar 2024 15:45:11 -0600 Subject: [PATCH 19/24] removed test code for debugging and formatted spacing --- fortran/micm_core.F90 | 24 +++++++++---------- .../fetch_content_integration/CMakeLists.txt | 2 +- .../test_micm_fort_api.F90 | 8 ------- 3 files changed, 13 insertions(+), 21 deletions(-) diff --git a/fortran/micm_core.F90 b/fortran/micm_core.F90 index 27b2f564..80d3cc18 100644 --- a/fortran/micm_core.F90 +++ b/fortran/micm_core.F90 @@ -10,8 +10,8 @@ module micm_core function create_micm_c(config_path, error_code) bind(C, name="create_micm") import c_ptr, c_int, c_char character(kind=c_char), intent(in) :: config_path(*) - integer(kind=c_int), intent(out) :: error_code - type(c_ptr) :: create_micm_c + integer(kind=c_int), intent(out) :: error_code + type(c_ptr) :: create_micm_c end function create_micm_c subroutine delete_micm_c(micm) bind(C, name="delete_micm") @@ -21,12 +21,12 @@ end subroutine delete_micm_c subroutine micm_solve_c(micm, time_step, temperature, pressure, num_concentrations, concentrations) bind(C, name="micm_solve") import c_ptr, c_double, c_int - type(c_ptr), value, intent(in) :: micm + type(c_ptr), value, intent(in) :: micm real(kind=c_double), value, intent(in) :: time_step real(kind=c_double), value, intent(in) :: temperature real(kind=c_double), value, intent(in) :: pressure integer(kind=c_int), value, intent(in) :: num_concentrations - real(kind=c_double), intent(inout) :: concentrations(num_concentrations) + real(kind=c_double), intent(inout) :: concentrations(num_concentrations) end subroutine micm_solve_c end interface @@ -47,7 +47,7 @@ end subroutine micm_solve_c contains function constructor(config_path, errcode) result( this ) - type(micm_t), pointer :: this + type(micm_t), pointer :: this character(len=*), intent(in) :: config_path integer, intent(out) :: errcode character(len=1, kind=c_char) :: c_config_path(len_trim(config_path)+1) @@ -69,17 +69,17 @@ function constructor(config_path, errcode) result( this ) end function constructor subroutine solve(this, time_step, temperature, pressure, num_concentrations, concentrations) - class(micm_t) :: this - real(c_double), intent(in) :: time_step - real(c_double), intent(in) :: temperature - real(c_double), intent(in) :: pressure - integer(c_int), intent(in) :: num_concentrations - real(c_double), intent(inout) :: concentrations(*) + class(micm_t) :: this + real(c_double), intent(in) :: time_step + real(c_double), intent(in) :: temperature + real(c_double), intent(in) :: pressure + integer(c_int), intent(in) :: num_concentrations + real(c_double), intent(inout) :: concentrations(*) call micm_solve_c(this%ptr, time_step, temperature, pressure, num_concentrations, concentrations) end subroutine solve subroutine finalize(this) - type(micm_t), intent(inout) :: this + type(micm_t), intent(inout) :: this call delete_micm_c(this%ptr) end subroutine finalize diff --git a/fortran/test/fetch_content_integration/CMakeLists.txt b/fortran/test/fetch_content_integration/CMakeLists.txt index f85e8e06..8ca09407 100644 --- a/fortran/test/fetch_content_integration/CMakeLists.txt +++ b/fortran/test/fetch_content_integration/CMakeLists.txt @@ -11,7 +11,7 @@ include(FetchContent) FetchContent_Declare(musica-fortran GIT_REPOSITORY https://github.com/NCAR/musica.git - GIT_TAG reorganize + GIT_TAG main ) set(MUSICA_BUILD_C_CXX_INTERFACE OFF) diff --git a/fortran/test/fetch_content_integration/test_micm_fort_api.F90 b/fortran/test/fetch_content_integration/test_micm_fort_api.F90 index d8cf8fe9..2dc1cf89 100644 --- a/fortran/test/fetch_content_integration/test_micm_fort_api.F90 +++ b/fortran/test/fetch_content_integration/test_micm_fort_api.F90 @@ -35,14 +35,6 @@ program test_micm_fort_api write(*,*) "[test micm fort api] After solving, concentrations", concentrations - call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations) - - write(*,*) "[test micm fort api] After solving, concentrations222", concentrations - - call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations) - - write(*,*) "[test micm fort api] After solving, concentrations333", concentrations - write(*,*) "[test micm fort api] Finished." end program From 3362575907fb7055c635e5ed7d6157b30cf69063 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Thu, 14 Mar 2024 16:52:26 -0500 Subject: [PATCH 20/24] putting fetchcontent at top level --- cmake/dependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake index 10bb0032..a8600f8c 100644 --- a/cmake/dependencies.cmake +++ b/cmake/dependencies.cmake @@ -1,4 +1,5 @@ find_package(PkgConfig REQUIRED) +include(FetchContent) ################################################################################ # NetCDF library @@ -9,7 +10,6 @@ endif() ################################################################################ # google test if(MUSICA_ENABLE_TESTS) - include(FetchContent) FetchContent_Declare(googletest GIT_REPOSITORY https://github.com/google/googletest.git GIT_TAG be03d00f5f0cc3a997d1a368bee8a1fe93651f48 From 82cf0aa2c401457ee8fec3b19bfec41c568849cd Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Mon, 18 Mar 2024 17:15:59 -0500 Subject: [PATCH 21/24] adding citation file (#71) * adding citation file * making tests pass --- CITATION.cff | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 CITATION.cff diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 00000000..76eee6b3 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,66 @@ +cff-version: 1.2.0 +message: "This Citation File Format (CFF) record describes a software paper." +authors: + - family-names: Pfister + given-names: Gabriele G. + - family-names: Eastham + given-names: Sebastian D. + - family-names: Arellano + given-names: Avelino F. + - family-names: Aumont + given-names: Bernard + - family-names: Barsanti + given-names: Kelley C. + - family-names: Barth + given-names: Mary C. + - family-names: Conley + given-names: Andrew + - family-names: Davis + given-names: Nicholas A. + - family-names: Emmons + given-names: Louisa K. + - family-names: Fast + given-names: Jerome D. + - family-names: Fiore + given-names: Arlene M. + - family-names: Gaubert + given-names: Benjamin + - family-names: Goldhaber + given-names: Steve + - family-names: Granier + given-names: Claire + - family-names: Grell + given-names: Georg A. + - family-names: Guevara + given-names: Marc + - family-names: Henze + given-names: Daven K. + - family-names: Hodzic + given-names: Alma + - family-names: Liu + given-names: Xiaohong + - family-names: Marsh + given-names: Daniel R. + - family-names: Orlando + given-names: John J. + - family-names: Plane + given-names: John M. C. + - family-names: Polvani + given-names: Lorenzo M. + - family-names: Rosenlof + given-names: Karen H. + - family-names: Steiner + given-names: Allison L. + - family-names: Jacob + given-names: Daniel J. + - family-names: Brasseur + given-names: Guy P. +title: "The Multi-Scale Infrastructure for Chemistry and Aerosols (MUSICA)" +journal: "Bulletin of the American Meteorological Society" +year: 2020 +publisher: "American Meteorological Society" +volume: 101 +number: 10 +page: "E1743 - E1760" +doi: "10.1175/BAMS-D-19-0331.1" +url: "https://journals.ametsoc.org/view/journals/bams/101/10/bamsD190331.xml" From 68183a0c45e20058ae06cfba5f7b5db2fe071f34 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Wed, 20 Mar 2024 14:51:35 -0500 Subject: [PATCH 22/24] updating version --- CITATION.cff | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index 76eee6b3..e93959e7 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -1,5 +1,5 @@ cff-version: 1.2.0 -message: "This Citation File Format (CFF) record describes a software paper." +message: "This Citation File Format (CFF) record describes how to cite MUSICA software." authors: - family-names: Pfister given-names: Gabriele G. @@ -64,3 +64,4 @@ number: 10 page: "E1743 - E1760" doi: "10.1175/BAMS-D-19-0331.1" url: "https://journals.ametsoc.org/view/journals/bams/101/10/bamsD190331.xml" +version: 0.6.0 \ No newline at end of file From 57778e3d3b90eb3d3c668bf973f9e99332ab6ec1 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Wed, 20 Mar 2024 14:53:59 -0500 Subject: [PATCH 23/24] updating micm version --- lib/micm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/micm b/lib/micm index a94cc96e..4a9149db 160000 --- a/lib/micm +++ b/lib/micm @@ -1 +1 @@ -Subproject commit a94cc96e7bd8dbba6c9eb88d73ade6e5437703b6 +Subproject commit 4a9149db80f4f5adfb4cb751b70b0f7818f23616 From 288231892dd79431668b0795bdd81e184a205a35 Mon Sep 17 00:00:00 2001 From: Kyle Shores Date: Thu, 21 Mar 2024 09:34:34 -0500 Subject: [PATCH 24/24] updating tuvx version --- lib/tuv-x | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/tuv-x b/lib/tuv-x index a5c71420..d43b16d2 160000 --- a/lib/tuv-x +++ b/lib/tuv-x @@ -1 +1 @@ -Subproject commit a5c71420b5e72bf24570b34f28d43656772d1e76 +Subproject commit d43b16d29e26ee1b29085b3c0b6f5d56ec122751