Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
9 changes: 5 additions & 4 deletions .github/workflows/mac.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Mac

on:
on:
push:
branches:
- main
Expand All @@ -19,6 +19,7 @@ jobs:
matrix:
xcode: ['16.4']
build_type: [Release]
use_fmt: [OFF, ON]
compiler:
- { cpp: g++-13, c: gcc-13 }
- { cpp: g++-14, c: gcc-14 }
Expand All @@ -36,13 +37,13 @@ jobs:
with:
xcode-version: ${{ matrix.xcode }}

- name: Run Cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }}
- name: Run Cmake
run: cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=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
ctest -C ${{ matrix.build_type }} --rerun-failed --output-on-failure --verbose
34 changes: 17 additions & 17 deletions .github/workflows/ubuntu.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: Ubuntu

on:
on:
push:
branches:
- main
pull_request:
workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref || github.run_id }}
cancel-in-progress: true
Expand All @@ -18,36 +18,36 @@ jobs:
strategy:
matrix:
compiler:
- { cpp: g++-12, c: gcc-12 }
- { cpp: g++-13, c: gcc-13 }
- { cpp: g++-14, c: gcc-14 }
- { cpp: clang++, c: clang }
build_type: [Release]
use_fmt: [OFF, ON]
exclude:
- compiler: { cpp: g++-12, c: gcc-12 }
use_fmt: OFF
env:
CC: ${{ matrix.compiler.c }}
CXX: ${{ matrix.compiler.cpp }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install GCC 13 if needed
if: matrix.compiler.cpp == 'clang++'
run: |
sudo apt update
sudo apt install -y gcc-13 g++-13
# Clang on Ubuntu defaults to libstdc++, whose std::expected is not visible to
# clang-18 (no template named 'expected'). Build the clang job against libc++,
# which provides std::expected and std::format.
- name: Install libc++ (clang)
if: matrix.compiler.cpp == 'clang++'
run: sudo apt-get update && sudo apt-get install -y libc++-dev libc++abi-dev

- name: Configure CMake
run: |
if [[ "${{ matrix.compiler.cpp }}" == "clang++" ]]; then
cmake -S . -B build \
-D CMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-D CMAKE_CXX_STANDARD=20 \
-D CMAKE_CXX_COMPILER=${CXX} \
-D CMAKE_EXE_LINKER_FLAGS="-stdlib=libstdc++" \
-D CMAKE_CXX_FLAGS="--gcc-toolchain=/usr"
else
cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-D CMAKE_CXX_STANDARD=20
EXTRA_FLAGS=""
if [ "${{ matrix.compiler.cpp }}" = "clang++" ]; then
EXTRA_FLAGS="-D CMAKE_CXX_FLAGS=-stdlib=libc++"
fi
cmake -S . -B build -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON $EXTRA_FLAGS

- name: Build
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
Expand Down
29 changes: 9 additions & 20 deletions .github/workflows/windows.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Windows

on:
on:
push:
branches:
- main
Expand All @@ -19,28 +19,15 @@ jobs:
matrix:
build_type: [Release, Debug]
architecture: [Win32, x64]
use_fmt: [OFF, ON]

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Setup Python
if: matrix.architecture == 'Win32'
uses: actions/setup-python@v5
with:
python-version: '3.9'
architecture: 'x86'

- name: Setup Python
if: matrix.architecture == 'x64'
uses: actions/setup-python@v5
with:
python-version: '3.9'
architecture: 'x64'

- name: Run Cmake
run: cmake -S . -B build -A ${{ matrix.architecture }} -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -DCMAKE_POLICY_VERSION_MINIMUM="3.5"
run: cmake -S . -B build -A ${{ matrix.architecture }} -D CMAKE_BUILD_TYPE=${{ matrix.build_type }} -D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} -D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON

- name: Build
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10

Expand All @@ -51,11 +38,12 @@ jobs:

msys2:
runs-on: windows-latest
continue-on-error: true
continue-on-error: true
strategy:
fail-fast: false
matrix:
build_type: [Debug, Release]
use_fmt: [OFF, ON]

steps:
- name: Checkout code
Expand All @@ -81,7 +69,8 @@ jobs:
run: |
cmake -S . -B build -G "MinGW Makefiles" \
-D CMAKE_BUILD_TYPE=${{ matrix.build_type }} \
-D CMAKE_POLICY_VERSION_MINIMUM=3.5
-D MECH_CONFIG_USE_FMT=${{ matrix.use_fmt }} \
-D MECH_CONFIG_COMPILE_WARNING_AS_ERROR=ON

- name: Build the project
shell: msys2 {0}
Expand All @@ -90,4 +79,4 @@ jobs:
- name: Run tests
shell: msys2 {0}
run: ctest --rerun-failed --output-on-failure . --verbose
working-directory: build
working-directory: build
2 changes: 1 addition & 1 deletion CITATION.cff
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
cff-version: 1.2.0
message: If you use this software, please cite it as below.
title: Chemical Mechanism Configurations
version: v1.1.2
version: v2.0.0
doi: "10.5281/zenodo.15116380"
authors:
- family-names: Dawson
Expand Down
24 changes: 20 additions & 4 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# must be on the same line so that pyproject.toml can correctly identify the version
project(mechanism_configuration VERSION 1.1.2 LANGUAGES CXX)
project(mechanism_configuration VERSION 2.0.0 LANGUAGES CXX)

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
Expand All @@ -27,6 +27,8 @@ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}/cmake")
option(MECH_CONFIG_ENABLE_TESTS "Build the tests" ON)
option(MECH_CONFIG_BUILD_SHARED_LIBS "Build shared libraries" OFF)
option(MECH_CONFIG_ENABLE_COVERAGE "Enable code coverage output" OFF)
option(MECH_CONFIG_USE_FMT "Use {fmt} library instead of std::format" OFF)
option(MECH_CONFIG_COMPILE_WARNING_AS_ERROR "Treat compiler warnings as errors for mechanism configuration targets" OFF)

set(MECH_CONFIG_INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(MECH_CONFIG_LIB_DIR ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
Expand All @@ -36,6 +38,19 @@ set(MECH_CONFIG_LIB_DIR ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})

include(cmake/dependencies.cmake)

################################################################################
# Code coverage instrumentation
#
# These flags must be applied BEFORE add_subdirectory(src) so the library
# targets are compiled with coverage instrumentation. append_coverage_compiler_flags()
# only affects targets defined after it runs, so calling it later would leave the
# library uninstrumented and the report would cover almost nothing.

if(PROJECT_IS_TOP_LEVEL AND MECH_CONFIG_ENABLE_TESTS AND MECH_CONFIG_ENABLE_COVERAGE)
include(cmake/CodeCoverage.cmake)
append_coverage_compiler_flags()
endif()

################################################################################
# project source code

Expand All @@ -47,12 +62,13 @@ add_subdirectory(src)
if(PROJECT_IS_TOP_LEVEL AND MECH_CONFIG_ENABLE_TESTS)
# Test code coverage
if(MECH_CONFIG_ENABLE_COVERAGE)
include(cmake/CodeCoverage.cmake)
append_coverage_compiler_flags()
setup_target_for_coverage_lcov(
NAME coverage
EXECUTABLE "ctest" -j 4
EXCLUDE "${PROJECT_SOURCE_DIR}/test/*"
EXCLUDE
"${PROJECT_SOURCE_DIR}/test/*"
"${CMAKE_BINARY_DIR}/_deps/*"
"/usr/*"
BASE_DIRECTORY "${PROJECT_SOURCE_DIR}/src"
LCOV_ARGS --ignore-errors mismatch)
endif()
Expand Down
69 changes: 67 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
An attempt at defining a model-independent configuration schema for atmospheric chemical systems in JSON and YAML.

[![GitHub Releases](https://img.shields.io/github/release/ncar/MechanismConfiguration.svg)](https://github.com/ncar/MechanismConfiguration/releases)
[![License](https://img.shields.io/github/license/ncar/MechanismConfiguration.svg)](https://github.com/ncar/MechanismConfiguration/blob/master/LICENSE)
[![Docs build](https://github.com/ncar/MechanismConfiguration/actions/workflows/gh-pages.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/gh-pages.yml)
[![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](https://github.com/NCAR/MechanismConfiguration/blob/main/LICENSE)
[![Windows](https://github.com/ncar/MechanismConfiguration/actions/workflows/windows.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/windows.yml)
[![Mac](https://github.com/ncar/MechanismConfiguration/actions/workflows/mac.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/mac.yml)
[![Ubuntu](https://github.com/ncar/MechanismConfiguration/actions/workflows/ubuntu.yml/badge.svg)](https://github.com/ncar/MechanismConfiguration/actions/workflows/ubuntu.yml)
Expand All @@ -15,6 +14,72 @@ Copyright (C) 2017–2026 University Corporation for Atmospheric Research, Unive

The configuration documentation can be found [here](https://ncar.github.io/MechanismConfiguration/).

## Usage

Everything goes through the canonical `mechanism_configuration::Mechanism`. You can either
**parse** a configuration file (the version is detected and dispatched automatically), or build
a `Mechanism` in code and **validate** it. `Validate()` runs the same semantic checks the parser
uses, so it applies to any mechanism regardless of where it came from.

```cpp
#include <mechanism_configuration/mechanism_configuration.hpp>

#include <iostream>

using namespace mechanism_configuration;

void print_errors(const Errors& errors)
{
for (const auto& [code, message] : errors)
std::cerr << " [" << ErrorCodeToString(code) << "] " << message << '\n';
}

int main()
{
int status = 0;

// 1) Parse from a file (YAML or JSON; v0 or v1). Returns std::expected<Mechanism, Errors>
// with both structural and semantic errors reported.
if (auto parsed = Parse("examples/v1/full_configuration.yaml"))
{
const Mechanism& mechanism = *parsed;
std::cout << "Parsed '" << mechanism.name << "': " << mechanism.species.size()
<< " species, " << mechanism.reactions.arrhenius.size() << " Arrhenius reactions\n";
}
else
{
std::cerr << "Failed to parse file:\n";
print_errors(parsed.error());
status = 1;
}

// 2) Build a Mechanism in code and validate it (species exist, reactants are in their
// phase, no duplicate names, ...).
Mechanism mechanism;
mechanism.name = "example";
mechanism.species = { { .name = "A" }, { .name = "B" } };
mechanism.phases = { { .name = "gas", .species = { { .name = "A" }, { .name = "B" } } } };

types::Arrhenius reaction;
reaction.name = "A -> B";
reaction.gas_phase = "gas";
reaction.reactants = { { .name = "A" } }; // reactants must be registered in the phase
reaction.products = { { .name = "B" } }; // products may reference any phase
mechanism.reactions.arrhenius = { reaction };

if (Errors errors = Validate(mechanism); errors.empty())
std::cout << "In-code mechanism is valid\n";
else
{
std::cerr << "In-code mechanism is invalid:\n";
print_errors(errors);
status = 1;
}

return status;
}
```

## Building the Documentation

With python and pip installed, go to the `docs/` folder and run:
Expand Down
2 changes: 1 addition & 1 deletion cmake/CodeCoverage.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ elseif(NOT CMAKE_COMPILER_IS_GNUCXX)
endif()
endif()

set(COVERAGE_COMPILER_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage -fcheck=bounds,do,pointer -ffpe-trap=zero,overflow,invalid"
set(COVERAGE_COMPILER_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage"
CACHE INTERNAL "")
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
include(CheckCXXCompilerFlag)
Expand Down
22 changes: 21 additions & 1 deletion cmake/dependencies.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ if(PROJECT_IS_TOP_LEVEL AND MECH_CONFIG_ENABLE_TESTS)
FetchContent_MakeAvailable(googletest)
endif()

################################################################################
# fmt

if(MECH_CONFIG_USE_FMT)
set_git_default(FMT_GIT_REPOSITORY https://github.com/fmtlib/fmt.git)
set_git_default(FMT_GIT_TAG 12.1.0)

FetchContent_Declare(fmt
GIT_REPOSITORY ${FMT_GIT_REPOSITORY}
GIT_TAG ${FMT_GIT_TAG}
FIND_PACKAGE_ARGS NAMES fmt
)

FetchContent_MakeAvailable(fmt)

if(fmt_POPULATED AND MECH_CONFIG_BUILD_SHARED_LIBS)
set_target_properties(fmt PROPERTIES POSITION_INDEPENDENT_CODE ON)
endif()
endif()

################################################################################
# yaml-cpp

Expand All @@ -42,4 +62,4 @@ FetchContent_Declare(yaml-cpp
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(YAML_BUILD_SHARED_LIBS ${MECH_CONFIG_BUILD_SHARED_LIBS} CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(yaml-cpp)
FetchContent_MakeAvailable(yaml-cpp)
6 changes: 6 additions & 0 deletions cmake/mechanism_configurationConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

if(@MECH_CONFIG_FMT_FIND_DEPENDENCY@)
find_dependency(fmt)
endif()

include("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@_Exports.cmake")

check_required_components("@PROJECT_NAME@")
4 changes: 4 additions & 0 deletions cmake/test_util.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ function(create_standard_test)
add_executable(test_${TEST_NAME} ${TEST_SOURCES})

target_link_libraries(test_${TEST_NAME} PUBLIC musica::mechanism_configuration GTest::gtest_main)
target_include_directories(test_${TEST_NAME}
PUBLIC
${PROJECT_SOURCE_DIR}/src
)


# link additional libraries
Expand Down
Loading
Loading