diff --git a/docs/source/tutorial/chapter2.rst b/docs/source/tutorial/chapter2.rst new file mode 100644 index 00000000..519ffa20 --- /dev/null +++ b/docs/source/tutorial/chapter2.rst @@ -0,0 +1,65 @@ +Chapter 2 +========= + +An MICM Box Model Fortran Example +--------------------------------- + +In this next MUSICA Fortran example, +we will setup a MICM solver, starting with a set of MICM configuration files, +and run the solver for a single integration time step. + +The MICM configuration is specified in a top-level ``config.json`` file, +which simply lists the chemical species configuration file followed by +the reactions configuration file. + + .. literalinclude:: ../../../configs/analytical/config.json + :language: json + +For this example, we will have a system of three chemical species +`A`, `B`, and `C`, defined in the JSON file ``species.json`` as follows: + + .. literalinclude:: ../../../configs/analytical/species.json + :language: json + +The ``reactions.json`` specifies a mechanism, or a set of reactions for the system. +Here, we will introduce two Arrhenius type reactions, the first +with `B` evolving to `C`, and specifying all five reaction parameters, +and the second reaction with `A` evolving to `B` and using only two reaction parameters. +The mechanism configuration might then be set up as: + + .. literalinclude:: ../../../configs/analytical/reactions.json + :language: json + +More information on MICM configurations and reactions can be found in the MICM documentation +at `https://ncar.github.io/micm/user_guide/`_ + +The Fortran example code is shown below in full: + + .. literalinclude:: ../../../fortran/test/fetch_content_integration/test_micm_box_model.F90 + :language: f90 + +From the ``musica_util`` module we need the Fortran types +``error_t``, ``string_t``, and ``mapping_t``. +A pointer to a ``musica_micm::micm_t`` will serve as the interface to the MICM solver +(in the example the pointer name is ``micm``). +Note that the ``config_path`` in the code sample has been set to ``configs/analytical``, +so that subdir should be created relative to the main program and contain +the MICM JSON configuration files, +or otherwise the ``config_path`` should be modified appropriately. +The initial species concentrations are initialized in the ``concentrations`` array, +which is an argument to the MICM solver. + +Finally, a single time step solution is obtained through a call to ``micm%solve``, +after which the updated concentrations may be displayed. + +.. code-block:: bash + + $ ./test_micm_box_model + Creating MICM solver... + Species Name:A, Index: 1 + Species Name:B, Index: 2 + Species Name:C, Index: 3 + Solving starts... + After solving, concentrations 0.38 1.61E-009 2.62 + $ + diff --git a/docs/source/tutorial/tutorial.rst b/docs/source/tutorial/tutorial.rst index e4206e3d..7d22728a 100644 --- a/docs/source/tutorial/tutorial.rst +++ b/docs/source/tutorial/tutorial.rst @@ -7,3 +7,4 @@ Tutorial :caption: Contents: chapter1.rst + chapter2.rst diff --git a/fortran/test/fetch_content_integration/CMakeLists.txt b/fortran/test/fetch_content_integration/CMakeLists.txt index 603b7f86..3b978644 100644 --- a/fortran/test/fetch_content_integration/CMakeLists.txt +++ b/fortran/test/fetch_content_integration/CMakeLists.txt @@ -36,6 +36,7 @@ enable_testing() if (MUSICA_ENABLE_MICM) add_executable(test_micm_fortran_api test_micm_api.F90) add_executable(test_get_micm_version test_get_micm_version.F90) + add_executable(test_micm_box_model test_micm_box_model.F90) target_link_libraries(test_micm_fortran_api PRIVATE @@ -68,6 +69,22 @@ if (MUSICA_ENABLE_MICM) COMMAND $ WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} ) + + target_link_libraries(test_micm_box_model + PRIVATE + musica::musica-fortran + ) + + set_target_properties(test_micm_box_model + PROPERTIES + LINKER_LANGUAGE Fortran + ) + + add_test( + NAME test_micm_box_model + COMMAND $ + WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + ) endif() # API Test diff --git a/fortran/test/fetch_content_integration/test_micm_box_model.F90 b/fortran/test/fetch_content_integration/test_micm_box_model.F90 new file mode 100644 index 00000000..dfdc5aab --- /dev/null +++ b/fortran/test/fetch_content_integration/test_micm_box_model.F90 @@ -0,0 +1,69 @@ +program test_micm_box_model + + use, intrinsic :: iso_c_binding + use, intrinsic :: ieee_arithmetic + + use musica_util, only: error_t, string_t, mapping_t + use musica_micm, only: micm_t, solver_stats_t + + implicit none + + call box_model() + +contains + + subroutine box_model() + + character(len=256) :: config_path + + real(c_double), parameter :: GAS_CONSTANT = 8.31446261815324_c_double ! J mol-1 K-1 + + real(c_double) :: time_step + real(c_double) :: temperature + real(c_double) :: pressure + real(c_double) :: air_density + + integer(c_int) :: num_concentrations = 3 + real(c_double), dimension(3) :: concentrations + + integer(c_int) :: num_user_defined_reaction_rates = 0 + real(c_double), dimension(:), allocatable :: user_defined_reaction_rates + + type(string_t) :: solver_state + type(solver_stats_t) :: solver_stats + type(error_t) :: error + + type(micm_t), pointer :: micm + + integer :: i + + config_path = "configs/analytical" + + time_step = 200 + temperature = 273.0 + pressure = 1.0e5 + air_density = pressure / (GAS_CONSTANT * temperature) + + concentrations = (/ 1.0, 1.0, 1.0 /) + + write(*,*) "Creating MICM solver..." + micm => micm_t(config_path, error) + + do i = 1, size( micm%species_ordering ) + associate(the_mapping => micm%species_ordering(i)) + print *, "Species Name:", the_mapping%name(), ", Index:", the_mapping%index() + end associate + end do + + write(*,*) "Solving starts..." + ! call micm%solve(time_step, temperature, pressure, num_concentrations, concentrations, & + ! num_user_defined_reaction_rates, user_defined_reaction_rates, error) + call micm%solve(time_step, temperature, pressure, air_density, num_concentrations, concentrations, & + num_user_defined_reaction_rates, user_defined_reaction_rates, solver_state, solver_stats, error) + write(*,*) "After solving, concentrations", concentrations + + deallocate( micm ) + + end subroutine box_model + +end program test_micm_box_model diff --git a/fortran/test/unit/CMakeLists.txt b/fortran/test/unit/CMakeLists.txt index 2d5e274a..27b0de76 100644 --- a/fortran/test/unit/CMakeLists.txt +++ b/fortran/test/unit/CMakeLists.txt @@ -5,6 +5,7 @@ create_standard_test_fortran(NAME fortran_util SOURCES util.F90) if (MUSICA_ENABLE_MICM) create_standard_test_fortran(NAME micm_fortran_api SOURCES ../fetch_content_integration/test_micm_api.F90) create_standard_test_fortran(NAME get_micm_version SOURCES ../fetch_content_integration/test_get_micm_version.F90) + create_standard_test_fortran(NAME micm_box_model SOURCES ../fetch_content_integration/test_micm_box_model.F90) endif() if (MUSICA_ENABLE_TUVX) diff --git a/src/micm/micm.cpp b/src/micm/micm.cpp index 7d03038e..af8cfc55 100644 --- a/src/micm/micm.cpp +++ b/src/micm/micm.cpp @@ -6,6 +6,7 @@ // creating and deleting MICM instances, creating solvers, and solving the model. #include +#include #include #include #include