From be54f572c940cc02555ee3ba62326e40197b0641 Mon Sep 17 00:00:00 2001 From: Marc Henry de Frahan Date: Thu, 26 Oct 2023 15:43:47 -0600 Subject: [PATCH] Add optional MPI for ceptr --- Docs/sphinx/Ceptr.rst | 20 +++++++-- Support/ceptr/ceptr/ceptr.py | 64 ++++++++++++++++++----------- Support/ceptr/ceptr/optional_mpi.py | 19 +++++++++ Support/ceptr/pyproject.toml | 4 ++ 4 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 Support/ceptr/ceptr/optional_mpi.py diff --git a/Docs/sphinx/Ceptr.rst b/Docs/sphinx/Ceptr.rst index 58c5ab40c..32d2d1830 100644 --- a/Docs/sphinx/Ceptr.rst +++ b/Docs/sphinx/Ceptr.rst @@ -1,7 +1,7 @@ .. highlight:: rst .. _sec:ceptr: - + CEPTR: Chemistry Evaluation for Pele Through Recasting ====================================================== @@ -19,10 +19,12 @@ To install CEPTR dependencies:: $ cd ${PELE_PHYSICS_HOME}/Support/ceptr $ poetry update - Usage ----- +Generating for a single chemistry +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + There are three ways to use CEPTR to generate C++ mechanism files for a given chemistry 1. Using CEPTR directly:: @@ -39,11 +41,23 @@ There are three ways to use CEPTR to generate C++ mechanism files for a given ch $ bash ${PELE_PHYSICS_HOME}/Support/Mechanism/Models/converter.sh -f ./LiDryer/mechanism.yaml +Batched generation +^^^^^^^^^^^^^^^^^^ + For non-reduced chemistries, CEPTR can take a file with a list of ``mechanism.yaml`` files to convert:: $ cd ${PELE_PHYSICS_HOME}/Support/ceptr $ poetry run convert -l ${PELE_PHYSICS_HOME}/Support/Mechanism/Models/list_mech +.. note:: + + If you are generating many mechanisms at once (e.g., a list of mechanism files), then you may want to consider using MPI. `mpi4py` is an optional dependency that can be installed and then used like this:: + + $ cd ${PELE_PHYSICS_HOME}/Support/ceptr + $ poetry install -E mpi + $ poetry run mpirun -np 8 convert -l ${PELE_PHYSICS_HOME}/Support/Mechanism/Models/list_mech + + For reduced chemistries, CEPTR can take a file with a list of ``qssa.yaml`` and ``qssa_input.toml`` to convert:: $ cd ${PELE_PHYSICS_HOME}/Support/ceptr @@ -99,5 +113,3 @@ The full list of options is:: For a detailed description of these options and a further information on the way QSS mechanism are treated in `CEPTR` the reader may consult :ref:`the QSS section `. See Tutorials (:ref:`Generating NC12H26 QSS mechanism with analytical jacobian ` and :ref:`Generating NC12H26 QSS mechanism without analytical jacobian `) for generating QSS mechanisms from the ``.yaml`` files. - - diff --git a/Support/ceptr/ceptr/ceptr.py b/Support/ceptr/ceptr/ceptr.py index 07b366cfa..7dbae9a4f 100644 --- a/Support/ceptr/ceptr/ceptr.py +++ b/Support/ceptr/ceptr/ceptr.py @@ -7,6 +7,24 @@ import cantera as ct import ceptr.converter as converter +import ceptr.optional_mpi as ompi + + +def parse_lst_file(lst): + """Parse a file containing a list of mechanism files.""" + fnames = [] + with open(lst, "r") as f: + for line in f: + if not line.startswith("#"): + fnames.append(line) + + if ompi.use_mpi(): + comm = ompi.world_comm() + rank = comm.Get_rank() + nprocs = comm.Get_size() + fnames = fnames[rank::nprocs] + + return fnames def convert( @@ -35,17 +53,16 @@ def convert_lst( ): """Convert mechanisms from a file containing a list of directories.""" lpath = pathlib.Path(lst) - with open(lst, "r") as f: - for line in f: - if not line.startswith("#"): - mechname = lpath.parents[0] / line.strip() - print(f"""Converting file {mechname}""") - convert( - mechname, - jacobian, - qss_format_input, - qss_symbolic_jac, - ) + lines = parse_lst_file(lst) + for line in lines: + mechname = lpath.parents[0] / line.strip() + print(f"""Converting file {mechname}""") + convert( + mechname, + jacobian, + qss_format_input, + qss_symbolic_jac, + ) def convert_lst_qss( @@ -54,19 +71,18 @@ def convert_lst_qss( ): """Convert QSS mechanisms from a file of directories and format input.""" lpath = pathlib.Path(lst) - with open(lst, "r") as f: - for line in f: - if not line.startswith("#"): - mech_file, format_file, _, _ = line.split() - mechname = lpath.parents[0] / mech_file.strip() - qss_format_input = lpath.parents[0] / format_file.strip() - print(f"""Converting file {mechname}""") - convert( - mechname, - jacobian, - qss_format_input, - True, - ) + lines = parse_lst_file(lst) + for line in lines: + mech_file, format_file, _, _ = line.split() + mechname = lpath.parents[0] / mech_file.strip() + qss_format_input = lpath.parents[0] / format_file.strip() + print(f"""Converting file {mechname}""") + convert( + mechname, + jacobian, + qss_format_input, + True, + ) def main(): diff --git a/Support/ceptr/ceptr/optional_mpi.py b/Support/ceptr/ceptr/optional_mpi.py new file mode 100644 index 000000000..18c365cce --- /dev/null +++ b/Support/ceptr/ceptr/optional_mpi.py @@ -0,0 +1,19 @@ +"""Optional import of mpi4py, only if available in the environment.""" + +import sys + +try: + from mpi4py import MPI + +except ModuleNotFoundError: + pass + + +def use_mpi(): + """Detect if mpi4py was imported.""" + return "mpi4py" in sys.modules + + +def world_comm(): + """Return the world communicator.""" + return MPI.COMM_WORLD diff --git a/Support/ceptr/pyproject.toml b/Support/ceptr/pyproject.toml index f7d3a07f0..f60f51c7c 100644 --- a/Support/ceptr/pyproject.toml +++ b/Support/ceptr/pyproject.toml @@ -17,6 +17,7 @@ sympy = "^1.12" symengine = "^0.9.2" pandas = ">=2.0.3" toml = ">=0.10.2" +mpi4py = {version = "^3.1.5", optional = true} [tool.poetry.dev-dependencies] pytest = "^7.4.0" @@ -30,6 +31,9 @@ flake8-docstrings = "^1.7.0" flake8-use-fstring = "^1.4" flynt = "^0.77" +[tool.poetry.extras] +mpi = ["mpi4py"] + [build-system] requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api"