diff --git a/docker/Dockerfile.fortran-gcc b/docker/Dockerfile.fortran-gcc index fe096268..bfb18695 100644 --- a/docker/Dockerfile.fortran-gcc +++ b/docker/Dockerfile.fortran-gcc @@ -44,6 +44,6 @@ RUN cd musica/fortran/test/fetch_content_integration \ -D CMAKE_BUILD_TYPE=Debug \ && make -RUN cp -r /musica/configs/chapman musica/fortran/test/fetch_content_integration/build +RUN cp -r /musica/configs 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 e3bd63d7..c8bd569b 100644 --- a/docker/Dockerfile.fortran-intel +++ b/docker/Dockerfile.fortran-intel @@ -48,6 +48,6 @@ RUN cd musica/fortran/test/fetch_content_integration \ -D CMAKE_BUILD_TYPE=Release \ && make -RUN cp -r /musica/configs/chapman musica/fortran/test/fetch_content_integration/build +RUN cp -r /musica/configs 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-nvhpc b/docker/Dockerfile.fortran-nvhpc index b86296b8..4c7053e4 100644 --- a/docker/Dockerfile.fortran-nvhpc +++ b/docker/Dockerfile.fortran-nvhpc @@ -53,6 +53,6 @@ RUN cd musica/fortran/test/fetch_content_integration \ -D CMAKE_BUILD_TYPE=Release \ && make -RUN cp -r /musica/configs/chapman musica/fortran/test/fetch_content_integration/build +RUN cp -r /musica/configs musica/fortran/test/fetch_content_integration/build WORKDIR musica/fortran/test/fetch_content_integration/build \ No newline at end of file diff --git a/fortran/CMakeLists.txt b/fortran/CMakeLists.txt index 69974314..926ed66d 100644 --- a/fortran/CMakeLists.txt +++ b/fortran/CMakeLists.txt @@ -40,7 +40,7 @@ target_link_libraries(musica-fortran ) target_sources(musica-fortran - PUBLIC + PRIVATE micm_core.F90 ) diff --git a/fortran/micm_core.F90 b/fortran/micm_core.F90 index 35760999..86ea59a1 100644 --- a/fortran/micm_core.F90 +++ b/fortran/micm_core.F90 @@ -3,13 +3,14 @@ module micm_core use iso_c_binding, only: c_ptr, c_char, c_int, c_double, c_null_char, c_size_t, c_f_pointer implicit none - public :: micm_t + public :: micm_t, mapping_t private - type, bind(c) :: Mapping + type, bind(c) :: mapping_t character(kind=c_char, len=1) :: name(256) integer(c_size_t) :: index - end type Mapping + integer(c_size_t) :: string_length + end type mapping_t interface function create_micm_c(config_path, error_code) bind(C, name="create_micm") @@ -24,7 +25,8 @@ subroutine delete_micm_c(micm) bind(C, name="delete_micm") 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") + subroutine micm_solve_c(micm, time_step, temperature, pressure, num_concentrations, concentrations, & + num_user_defined_reaction_rates, user_defined_reaction_rates) 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 @@ -32,6 +34,8 @@ subroutine micm_solve_c(micm, time_step, temperature, pressure, num_concentratio 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) + integer(kind=c_int), value, intent(in) :: num_user_defined_reaction_rates + real(kind=c_double), intent(inout) :: user_defined_reaction_rates(num_user_defined_reaction_rates) end subroutine micm_solve_c function get_species_ordering(micm, array_size) bind(c, name="get_species_ordering") @@ -50,8 +54,8 @@ end function get_user_defined_reaction_rates_ordering end interface type :: micm_t - type(Mapping), pointer :: species_ordering(:), reaction_rates_ordering(:) - integer(kind=c_size_t) :: species_ordering_length, reaction_rates_ordering_length + type(mapping_t), pointer :: species_ordering(:), user_defined_reaction_rates(:) + integer(kind=c_size_t) :: species_ordering_length, user_defined_reaction_rates_length type(c_ptr), private :: ptr contains ! Solve the chemical system @@ -76,7 +80,6 @@ function constructor(config_path, errcode) result( this ) allocate( this ) - print *, "Config Path:", config_path n = len_trim(config_path) do i = 1, n c_config_path(i) = config_path(i:i) @@ -92,21 +95,23 @@ function constructor(config_path, errcode) result( this ) mappings_ptr = get_species_ordering(this%ptr, this%species_ordering_length) call c_f_pointer(mappings_ptr, this%species_ordering, [this%species_ordering_length]) - ! this%reaction_rates_ordering = get_user_defined_reaction_rates_ordering(this%ptr, this%reaction_rates_ordering_length) - ! do i = 1, this%reaction_rates_ordering_length - ! print *, "Reaction Rate Name:", this%reaction_rates_ordering(i)%name, ", Index:", this%reaction_rates_ordering(i)%index - ! end do + mappings_ptr = get_user_defined_reaction_rates_ordering(this%ptr, this%user_defined_reaction_rates_length) + call c_f_pointer(mappings_ptr, this%user_defined_reaction_rates, [this%user_defined_reaction_rates_length]) end function constructor - subroutine solve(this, time_step, temperature, pressure, num_concentrations, concentrations) + subroutine solve(this, time_step, temperature, pressure, num_concentrations, concentrations, & + num_user_defined_reaction_rates, user_defined_reaction_rates) 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) + integer(c_int), intent(in) :: num_user_defined_reaction_rates + real(c_double), intent(inout) :: user_defined_reaction_rates(*) + call micm_solve_c(this%ptr, time_step, temperature, pressure, num_concentrations, concentrations, & + num_user_defined_reaction_rates, user_defined_reaction_rates) end subroutine solve subroutine finalize(this) diff --git a/fortran/micm_core.mod b/fortran/micm_core.mod new file mode 100644 index 00000000..4dc67a6f Binary files /dev/null and b/fortran/micm_core.mod differ 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 2dc1cf89..54bcc9c7 100644 --- a/fortran/test/fetch_content_integration/test_micm_fort_api.F90 +++ b/fortran/test/fetch_content_integration/test_micm_fort_api.F90 @@ -1,6 +1,6 @@ program test_micm_fort_api use iso_c_binding - use micm_core, only: micm_t + use micm_core, only: micm_t, mapping_t implicit none @@ -8,21 +8,35 @@ program test_micm_fort_api 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 + integer(c_int) :: num_concentrations, num_user_defined_reaction_rates + real(c_double), dimension(5) :: concentrations + real(c_double), dimension(3) :: user_defined_reaction_rates + integer :: errcode, i + character(len=256) :: config_path + type(mapping_t) :: the_mapping time_step = 200 temperature = 272.5 - pressure = 101253.3 + pressure = 101253.4 num_concentrations = 5 concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) - config_path = "chapman" + config_path = "configs/chapman" + num_user_defined_reaction_rates = 3 + user_defined_reaction_rates = (/ 0.1, 0.2, 0.3 /) + write(*,*) "[test micm fort api] Creating MICM solver..." micm => micm_t(config_path, errcode) + do i = 1, micm%species_ordering_length + the_mapping = micm%species_ordering(i) + print *, "Species Name:", the_mapping%name(:the_mapping%string_length), ", Index:", the_mapping%index + end do + do i = 1, micm%user_defined_reaction_rates_length + the_mapping = micm%user_defined_reaction_rates(i) + print *, "User Defined Reaction Rate Name:", the_mapping%name(:the_mapping%string_length), ", Index:", the_mapping%index + end do + if (errcode /= 0) then write(*,*) "[test micm fort api] Failed in creating solver." stop 3 @@ -31,7 +45,8 @@ program test_micm_fort_api 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) + call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations, & + num_user_defined_reaction_rates, user_defined_reaction_rates) write(*,*) "[test micm fort api] After solving, concentrations", concentrations 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 index 71adbd27..93ef7fae 100644 --- a/fortran/test/fetch_content_integration/test_micm_fort_api_invalid.F90 +++ b/fortran/test/fetch_content_integration/test_micm_fort_api_invalid.F90 @@ -5,19 +5,9 @@ subroutine test_micm_fort_api_invalid() 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..." diff --git a/fortran/test/unit/test_musica_fortran_interface.F90 b/fortran/test/unit/test_musica_fortran_interface.F90 index f7d6ca2e..7fc6fd41 100644 --- a/fortran/test/unit/test_musica_fortran_interface.F90 +++ b/fortran/test/unit/test_musica_fortran_interface.F90 @@ -1,6 +1,6 @@ program test_micm_fort_api use iso_c_binding - use micm_core, only: micm_t + use micm_core, only: micm_t, mapping_t implicit none @@ -8,21 +8,35 @@ program test_micm_fort_api 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 + integer(c_int) :: num_concentrations, num_user_defined_reaction_rates + real(c_double), dimension(5) :: concentrations + real(c_double), dimension(3) :: user_defined_reaction_rates + integer :: errcode, i + character(len=256) :: config_path + type(mapping_t) :: the_mapping time_step = 200 temperature = 272.5 - pressure = 101253.3 + pressure = 101253.4 num_concentrations = 5 concentrations = (/ 0.75, 0.4, 0.8, 0.01, 0.02 /) config_path = "configs/chapman" + num_user_defined_reaction_rates = 3 + user_defined_reaction_rates = (/ 0.1, 0.2, 0.3 /) + write(*,*) "[test micm fort api] Creating MICM solver..." micm => micm_t(config_path, errcode) + do i = 1, micm%species_ordering_length + the_mapping = micm%species_ordering(i) + print *, "Species Name:", the_mapping%name(:the_mapping%string_length), ", Index:", the_mapping%index + end do + do i = 1, micm%user_defined_reaction_rates_length + the_mapping = micm%user_defined_reaction_rates(i) + print *, "User Defined Reaction Rate Name:", the_mapping%name(:the_mapping%string_length), ", Index:", the_mapping%index + end do + if (errcode /= 0) then write(*,*) "[test micm fort api] Failed in creating solver." stop 3 @@ -31,7 +45,8 @@ program test_micm_fort_api 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) + call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations, & + num_user_defined_reaction_rates, user_defined_reaction_rates) write(*,*) "[test micm fort api] After solving, concentrations", concentrations diff --git a/include/musica/micm.hpp b/include/musica/micm.hpp index e4418df9..a9e9c82e 100644 --- a/include/musica/micm.hpp +++ b/include/musica/micm.hpp @@ -17,8 +17,9 @@ class MICM; struct Mapping { - char *name; + char name[256]; size_t index; + size_t string_length; }; #ifdef __cplusplus @@ -39,12 +40,6 @@ extern "C" 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 diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 8dded4cc..e8ea0232 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -40,22 +40,22 @@ void micm_solve(MICM *micm, double time_step, double temperature, double pressur Mapping *get_species_ordering(MICM *micm, size_t *array_size) { auto map = micm->get_species_ordering(); - Mapping *reactionRates = new Mapping[map.size()]; + Mapping *species_ordering = new Mapping[map.size()]; // Copy data from the map to the array of structs size_t i = 0; for (const auto &entry : map) { - reactionRates[i].name = new char[entry.first.size() + 1]; // +1 for null terminator - std::strcpy(reactionRates[i].name, entry.first.c_str()); - reactionRates[i].index = entry.second; + std::strcpy(species_ordering[i].name, entry.first.c_str()); + species_ordering[i].index = entry.second; + species_ordering[i].string_length = entry.first.size(); ++i; } // Set the size of the array *array_size = map.size(); - return reactionRates; + return species_ordering; } Mapping *get_user_defined_reaction_rates_ordering(MICM *micm, size_t *array_size) @@ -67,9 +67,9 @@ Mapping *get_user_defined_reaction_rates_ordering(MICM *micm, size_t *array_size size_t i = 0; for (const auto &entry : map) { - reactionRates[i].name = new char[entry.first.size() + 1]; // +1 for null terminator std::strcpy(reactionRates[i].name, entry.first.c_str()); reactionRates[i].index = entry.second; + reactionRates[i].string_length = entry.first.size(); ++i; } @@ -79,12 +79,6 @@ Mapping *get_user_defined_reaction_rates_ordering(MICM *micm, size_t *array_size return reactionRates; } -MICM::MICM() : solver_(nullptr) {} - -MICM::~MICM() -{ -} - int MICM::create_solver(const std::string &config_path) { int parsing_status = 0; // 0 on success, 1 on failure