Skip to content

Commit

Permalink
278 add tutorial for use with openmp (#280)
Browse files Browse the repository at this point in the history
* adding more build instructions

* adding test for openmp

* adding cmake stuff to detect libomp installed with homebrew

* stubbed openmp tutorial
  • Loading branch information
K20shores authored Oct 4, 2023
1 parent dcb77b6 commit 1a8e7d2
Show file tree
Hide file tree
Showing 16 changed files with 489 additions and 10 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ option(BUILD_DOCS "Build the documentation" OFF)
option(ENABLE_CUDA "Build with Cuda support" OFF)
option(ENABLE_OPENACC "Build with OpenACC Support" OFF)
option(ENABLE_LLVM "Build with LLVM support for JIT-compiling" OFF)
option(ENABLE_TESTS "Build the tests" ON)

include(CMakeDependentOption)
# Option to collect custom OpenACC flags
Expand Down Expand Up @@ -68,7 +69,7 @@ endif()
################################################################################
# Tests

if(PROJECT_IS_TOP_LEVEL)
if(PROJECT_IS_TOP_LEVEL AND ENABLE_TESTS)
# Test code coverage
if(ENABLE_COVERAGE)
include(CodeCoverage)
Expand Down
1 change: 1 addition & 0 deletions Dockerfile.openmp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ RUN mkdir /build \
&& cmake \
-D ENABLE_CLANG_TIDY:BOOL=FALSE \
-D ENABLE_OPENMP:BOOL=TRUE \
-D ENABLE_JSON:BOOL=TRUE \
../micm \
&& make install -j 8

Expand Down
35 changes: 35 additions & 0 deletions cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,41 @@ endif()
# OpenMP

if(ENABLE_OPENMP)
if(APPLE)
# Apple clang by default doesn't include support for openmp
# but if omp was installed with `brew install libomp`, support can be configured
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# Set the C flags
set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp")
set(OpenMP_C_LIB_NAMES "omp")
set(OpenMP_omp_LIBRARY omp)

# Set the CXX flags
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp")
set(OpenMP_CXX_LIB_NAMES "omp")
set(OpenMP_omp_LIBRARY omp)

# Assume that libomp is instaleld on mac with brew when using apple clang
# Get the path to libomp from Homebrew
execute_process(
COMMAND brew --prefix libomp
OUTPUT_VARIABLE LIBOMP_PREFIX
OUTPUT_STRIP_TRAILING_WHITESPACE
)

# Set the full path to the libomp library
set(OpenMP_omp_LIBRARY "${LIBOMP_PREFIX}/lib/libomp.dylib")

# Set the include directory
set(LIBOMP_INCLUDE_DIR "${LIBOMP_PREFIX}/include")

include_directories(
${LIBOMP_INCLUDE_DIR}
)
endif()

endif()

find_package(OpenMP REQUIRED)
message(STATUS "Compiling with OpenMP support")
endif()
Expand Down
Binary file added docs/source/_static/tutorials/robertson.zip
Binary file not shown.
30 changes: 21 additions & 9 deletions docs/source/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ CPU
~~~
To build and install MICM locally, you must have the following libraries installed:

- [sphinx](https://github.com/sphinx-doc/sphinx)
- [sphinx-book-theme](https://github.com/executablebooks/sphinx-book-theme)
- [sphinx-design](https://github.com/executablebooks/sphinx-design)
- [breathe](https://github.com/breathe-doc/breathe)
- `CMake <https://cmake.org/>`_
- `installation <https://cmake.org/download/>`_

You must also have CMake installed on your machine.

Open a terminal window, navigate to a folder where you would like the MICM files to exist,
and run the following commands::
Then, it's enough for you to configure and install micm on your computer. Because micm is header-only library, the install
step will simply copy the header files into the normal location required by your system.

.. code-block:: console
$ git clone https://github.com/NCAR/micm.git
$ cd micm
$ mkdir build
Expand All @@ -30,6 +28,20 @@ and run the following commands::
CMake will allow for setting options such as the installation directory
with CMAKE_INSTALL_PREFIX, or various build flags such as BUILD_DOCS, ENABLE_CUDA, etc.

MICM can optionally include support for json configuration reading, OpenMP,
JIT-compiled chemistry functions, and GPUs. Each of these requires an additional library.
Some of these libraries can be included automatically with cmake build options,
others require that you have libraries installed on your system.

- JSON configuration support
- When building micm, you need to enable the JSON option. This will download and configure the `nlohmann/jsoncpp library <https://github.com/nlohmann/json>`_ for you. For example: ``cmake -DENABLE_JSON=ON ..``
- JIT-compiled chemistry functions
- This requires `LLVM <https://llvm.org/docs/index.html>`_ to be installed with on your system. Once it is, you can include the jit options with ``cmake -DENBABLE_LLVM=ON ..``
- GPU support
- Coming soon
- OpenMP
- On macOS, you either need to configure cmake to use gcc which ships with OpenMP (either ``CXX=g++ cmake -DENABLE_OPENMP=ON ..`` or ``cmake -DCMAKE_CXX_COMPILER=g++ -DENABLE_OPENMP=ON ..``)

Docker Container
~~~~~~~~~~~~~~~~

Expand Down Expand Up @@ -74,7 +86,7 @@ The following example solves the fictitious chemical system::
foo + bar --k2--> baz

The `k1` and `k2` rate constants are for Arrhenius reactions.
See the [MICM documentation](https://ncar.github.io/micm/)
See the `MICM documentation <https://ncar.github.io/micm/>`
for details on the types of reactions available in MICM and how to configure them.
To solve this system save the following code in a file named `foo_chem.cpp`

Expand Down
27 changes: 27 additions & 0 deletions docs/source/user_guide/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,32 @@ If you happen to find our examples are lacking for your needs, please,
`fill out an issue <https://github.com/NCAR/micm/issues/new>`_ and request the kind of example you'd like.


All of these tutorials are included in our automated tests. Each of them can be found in the code base in the
``test/tutorial`` directory. When building MICM with tests (the default), you can each test individually to see the output.


.. code-block:: console
$ git clone https://github.com/NCAR/micm.git
$ cd micm
$ mkdir build
$ cd build
$ cmake ..
$ make
$ ./test_multiple_grid_cells
$ ./test_rate_constants_no_user_defined_example_by_hand
$ ./test_rate_constants_user_defined_example_by_hand
If you would like to include the json examples, you must configure micm to build with json support.

.. code-block:: console
$ cmake -DENABLE_JSON=ON ..
$ make
$ ./test_rate_constants_no_user_defined_example_with_config
$ ./test_rate_constants_user_defined_example_with_config
.. toctree::
:maxdepth: 1
Expand All @@ -17,3 +43,4 @@ If you happen to find our examples are lacking for your needs, please,
rate_constant_tutorial
user_defined_rate_constant_tutorial
multiple_grid_cells
openmp
73 changes: 73 additions & 0 deletions docs/source/user_guide/openmp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
.. _OpenMP:

OpenMP
======

This tutorial will focus on running micm with OpenMP support.
We will use a simple 3-reaction 3-species mechanism. The setup here is the same in
:ref:`Multiple grid cells`, except only one grid cell is used.

.. math::
A &\longrightarrow B, &k_{1, \mathrm{user\ defined}} \\
2B &\longrightarrow B + C, &k_{2, \mathrm{user\ defined}} \\
B + C &\longrightarrow A + C, \qquad &k_{3, \mathrm{user\ defined}} \\
If you're looking for a copy and paste, copy below and be on your way! Otherwise, stick around for a line by line explanation.

.. tabs::

.. tab:: OpenAtmos Configuration reading

.. raw:: html

<div class="download-div">
<a href="../_static/tutorials/robertson.zip" download>
<button class="download-button">Download zip configuration</button>
</a>
</div>

.. literalinclude:: ../../../test/tutorial/test_openmp.cpp
:language: cpp

Line-by-line explanation
------------------------

At present, the Rosenbrock class is not thread safe. Thread safety is being added and will be available soon in new release.

Until then, you can run one instance of the Rosenbrock solver on its own thread. Configuration data, at least, can be shared
across the threads. This tutorial reads a configuraiton file and then configures three solvers, each on their own thread,
with that same configuration information.

First we need to bring in the necessary imports and use the micm namespace.

.. literalinclude:: ../../../test/tutorial/test_openmp.cpp
:language: cpp
:lines: 1-6

Then we'll define a funtion that we can call with the configuration information from each thread. This function will build
and run the rosenbrock solver.

.. literalinclude:: ../../../test/tutorial/test_openmp.cpp
:language: cpp
:lines: 29-69

The main function simply reads the configuration file, sets the number of threads, and then sets up an OpenMP blcok
with three threads. The function defined above is called on each thread.

.. literalinclude:: ../../../test/tutorial/test_openmp.cpp
:language: cpp
:lines: 71-109

Running this program should give an output similar to this:

.. code-block:: console
Thread 1
A, B, C
2.55e-01, 1.37e-06, 7.45e-01
Thread 2
A, B, C
2.55e-01, 1.37e-06, 7.45e-01
Thread 3
A, B, C
2.55e-01, 1.37e-06, 7.45e-01
4 changes: 4 additions & 0 deletions test/tutorial/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ create_standard_test(NAME rate_constants_user_defined_example_by_hand SOURCES te
if(ENABLE_JSON)
create_standard_test(NAME rate_constants_no_user_defined_example_with_config SOURCES test_rate_constants_no_user_defined_with_config.cpp)
create_standard_test(NAME rate_constants_user_defined_example_with_config SOURCES test_rate_constants_user_defined_with_config.cpp)

if(ENABLE_OPENMP)
create_standard_test(NAME openmp_tutorial SOURCES test_openmp.cpp)
endif()
endif()

################################################################################
Expand Down
43 changes: 43 additions & 0 deletions test/tutorial/configs/robertson/reactions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"camp-data": [
{
"name": "reaction rates no user defined",
"type": "MECHANISM",
"reactions": [
{
"type": "PHOTOLYSIS",
"reactants": {
"A": {}
},
"products": {
"B": {}
},
"MUSICA name": "r1"
},
{
"type": "PHOTOLYSIS",
"reactants": {
"B": { "qty": 2}
},
"products": {
"B": {},
"C": {}
},
"MUSICA name": "r2"
},
{
"type": "PHOTOLYSIS",
"reactants": {
"B": {},
"C": {}
},
"products": {
"A": {},
"C": {}
},
"MUSICA name": "r3"
}
]
}
]
}
16 changes: 16 additions & 0 deletions test/tutorial/configs/robertson/species.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"camp-data": [
{
"name": "A",
"type": "CHEM_SPEC"
},
{
"name": "B",
"type": "CHEM_SPEC"
},
{
"name": "C",
"type": "CHEM_SPEC"
}
]
}
Loading

0 comments on commit 1a8e7d2

Please sign in to comment.