Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
f3663dc
Merge branch 'master' into develop
mgduda Apr 16, 2026
dde5991
Generalize the name of the 'mp_thompson_aers_in' package in init_atmo…
mgduda May 4, 2026
0fd81c4
Fix memory leak in mpas_io.F
DusanJovic-NOAA May 5, 2026
022e5ca
Fix memory leak in mpas_stream_manager.F
DusanJovic-NOAA May 5, 2026
b464355
Fix memory leak in stream_inquiry.c
DusanJovic-NOAA May 5, 2026
51ee1c4
Fix memory leak in mpas_io.F
DusanJovic-NOAA May 5, 2026
ec93499
Fix memory leak in mpas_pool_routines.F
DusanJovic-NOAA May 5, 2026
e0969a6
Fix memory leak in mpas_framework.F and mpas_domain_routines.F
DusanJovic-NOAA May 5, 2026
af276d2
Fix memory leak in mpas_domain_routines.F
DusanJovic-NOAA May 5, 2026
e3ed446
Fix memory leak in xml_stream_parser
DusanJovic-NOAA May 6, 2026
15d769e
Fix memory leak in mpas_io.F
DusanJovic-NOAA May 6, 2026
8ddd20f
Fix memory leak in mpas_domain_routines.F
DusanJovic-NOAA May 6, 2026
30ef882
Fix memory leak in mpas_pool_routines.F
DusanJovic-NOAA May 6, 2026
613bd0f
Fix memory leak in mpas_block_creator.F
DusanJovic-NOAA May 6, 2026
ae45a18
Fix memory leak in block_dimension_routines.inc
DusanJovic-NOAA May 6, 2026
3bc0c4e
Fix memory leak in mpas_io.F
DusanJovic-NOAA May 6, 2026
0027428
Merge branch 'atmosphere/generalize_mp_aerosols_package' into develop…
mgduda May 7, 2026
7d0cbee
Provide default initialization for members of the met_data derived type
mgduda May 7, 2026
4e670f9
Merge branch 'dev_fix_mem_leaks' into develop (PR #1451)
mgduda May 8, 2026
04e89cb
Merge branch 'init_atmosphere/met_data_default_init' into develop (PR…
mgduda May 10, 2026
4ab5b57
Fix bug in registry-generated code to set up derived dimensions
mgduda May 26, 2026
4069eb3
Clean up indentation in registry-generated code in block_dimension_ro…
mgduda May 26, 2026
c33f6ff
Merge branch 'framework/fix_generated_dimension_ptr' into develop (PR…
mgduda May 26, 2026
c03f2af
Add a dm_info object to the argument list of core mpas_setup_packages…
mgduda May 29, 2026
5191ccc
Merge branch 'setup_packages_with_dminfo' into develop (PR #1463)
mgduda Jun 2, 2026
3bc08ca
Add new routine mpas_split_string_new to the init_atm_core_interface …
mgduda May 29, 2026
f3b116c
Apply packages to individual hydrometeors in the init_atmosphere core
mgduda May 29, 2026
eb75fdc
Merge branch 'master' into develop
mgduda Jun 10, 2026
8f1cde7
Merge branch 'init_atmosphere/hydrometeor_packages' into develop (PR …
mgduda Jun 11, 2026
59b0ca7
Provide optimized code path in check_regex_match function for non-reg…
mgduda May 20, 2026
2bc5d33
Add documentation for the check_regex_match function in regex_matching.c
mgduda Jun 8, 2026
b3ee4d3
Merge branch 'framework/optimize_regex_match' into develop (PR #1466)
mgduda Jun 11, 2026
eab77c9
Add CI files to develop branch, and make manual dispatch only
cenamiller Jul 22, 2026
0190711
Merge pull request #73 from NCAR/ci-add-workflows-to-dev
cenamiller Jul 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions .github/actions/build-mpas/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
name: 'Build MPAS'
description: 'Build MPAS-Atmosphere with specified compiler configuration'

inputs:
compiler:
description: 'Compiler family (gcc, nvhpc, oneapi, etc.)'
required: true
use-pio:
description: 'Use PIO library (true/false)'
required: false
default: 'false'
openacc:
description: 'Enable OpenACC (true/false)'
required: false
default: 'false'
precision:
description: 'Floating-point precision (single or double)'
required: false
default: 'single'
build-timeout:
description: 'Build timeout in minutes'
required: false
default: '20'

outputs:
executable:
description: 'Path to built executable'
value: ${{ steps.build.outputs.executable }}

runs:
using: 'composite'
steps:
- name: Build MPAS-A
id: build
shell: bash
run: |
# Source container environment if available
# This sets NETCDF, PNETCDF, PIO, and other library paths
if [ -f /container/config_env.sh ]; then
echo "Sourcing container environment from /container/config_env.sh"
source /container/config_env.sh
fi

# MPAS Makefile uses `cpp` for Registry preprocessing.
# Some containers (e.g. openSUSE Leap) don't ship it separately.
if ! command -v cpp &>/dev/null; then
echo "cpp not found, installing..."
if command -v zypper &>/dev/null; then
zypper install -y --no-recommends cpp
elif command -v dnf &>/dev/null; then
dnf install -y cpp
elif command -v apt-get &>/dev/null; then
apt-get update && apt-get install -y cpp
fi
fi

# Map compiler input to COMPILER_FAMILY if not already set
# The container should set this, but we provide a fallback
if [ -z "${COMPILER_FAMILY}" ]; then
case "${{ inputs.compiler }}" in
gcc|gfortran|gnu) export COMPILER_FAMILY="gcc" ;;
nvhpc|nvfortran) export COMPILER_FAMILY="nvhpc" ;;
oneapi|intel|ifx) export COMPILER_FAMILY="oneapi" ;;
llvm|flang|clang) export COMPILER_FAMILY="clang" ;;
*) export COMPILER_FAMILY="${{ inputs.compiler }}" ;;
esac
fi

# Set up I/O configuration
if [ "${{ inputs.use-pio }}" = "true" ]; then
export PIO_ROOT=${PIO_ROOT:-/container/pio}
export USE_PIO2=true
else
unset PIO
export USE_PIO2=false
fi

# Set up accelerator configuration
if [ "${{ inputs.openacc }}" = "true" ]; then
export OPENACC=true
fi

echo "Build configuration:"
echo " Compiler input: ${{ inputs.compiler }}"
echo " COMPILER_FAMILY: ${COMPILER_FAMILY}"
echo " NETCDF: ${NETCDF:-not set}"
echo " PNETCDF: ${PNETCDF:-not set}"
echo " USE_PIO2: ${USE_PIO2}"
echo " OPENACC: ${OPENACC:-false}"
echo " PRECISION: ${{ inputs.precision }}"

# Settings from .github/ci-config.env — edit that file to change targets/workarounds
CI_CONFIG="${GITHUB_WORKSPACE}/.github/ci-config.env"
if [ -f "${CI_CONFIG}" ]; then
source "${CI_CONFIG}"
fi

# Map COMPILER_FAMILY to make target via ci-config.env lookup
VARNAME="MAKE_TARGET_${COMPILER_FAMILY}"
MAKE_TARGET="${!VARNAME}"
if [ -z "${MAKE_TARGET}" ]; then
echo "::error::No make target for COMPILER_FAMILY=${COMPILER_FAMILY}. Add MAKE_TARGET_${COMPILER_FAMILY}= to .github/ci-config.env"
exit 1
fi

EXTRA_MAKE_FLAGS=""
if [ "${COMPILER_FAMILY}" = "nvhpc" ]; then
ARCH="${NVHPC_TARGET_ARCH:--tp=px}"
sed -i "/^nvhpc:/,/^[a-z]/ s/\"FFLAGS_OPT = /\"FFLAGS_OPT = ${ARCH} /" Makefile
sed -i "/^nvhpc:/,/^[a-z]/ s/\"CFLAGS_OPT = /\"CFLAGS_OPT = ${ARCH} /" Makefile
sed -i "/^nvhpc:/,/^[a-z]/ s/\"CXXFLAGS_OPT = /\"CXXFLAGS_OPT = ${ARCH} /" Makefile
sed -i "/^nvhpc:/,/^[a-z]/ s/\"LDFLAGS_OPT = /\"LDFLAGS_OPT = ${ARCH} /" Makefile
EXTRA_MAKE_FLAGS="${NVHPC_EXTRA_MAKE_FLAGS}"
elif [ "${COMPILER_FAMILY}" = "oneapi" ]; then
EXTRA_MAKE_FLAGS="${ONEAPI_EXTRA_MAKE_FLAGS}"
fi

echo " Make target: ${MAKE_TARGET}"
echo " Extra make flags: ${EXTRA_MAKE_FLAGS:-<none>}"
echo " Parallel jobs: ${MAKE_J_PROCS:-$(nproc)}"

PRECISION_FLAG=""
if [ "${{ inputs.precision }}" = "double" ]; then
PRECISION_FLAG="PRECISION=double"
fi

timeout ${{ inputs.build-timeout }}m \
make ${MAKE_TARGET} CORE=atmosphere ${EXTRA_MAKE_FLAGS} ${PRECISION_FLAG} --jobs ${MAKE_J_PROCS:-$(nproc)}

# Set output
echo "executable=$(pwd)/atmosphere_model" >> $GITHUB_OUTPUT

- name: Verify executable
shell: bash
run: |
if [ ! -f atmosphere_model ]; then
echo "ERROR: atmosphere_model not found!"
exit 1
fi
ls -la atmosphere_model
file atmosphere_model
97 changes: 97 additions & 0 deletions .github/actions/download-testdata/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
name: 'Download Test Data'
description: 'Download and extract an MPAS test case archive from GitHub releases'

inputs:
resolution:
description: 'Test case resolution (e.g., 240km, 120km). Used to look up RELEASE_TESTDATA_{RES} in ci-config.env.'
required: true
dest-dir:
description: 'Destination directory name for the extracted test case'
required: false
default: ''

outputs:
case-dir:
description: 'Path to the extracted test case directory'
value: ${{ steps.extract.outputs.case-dir }}

runs:
using: composite
steps:
- name: Resolve release tag and archive
id: resolve
shell: bash
run: |
RESOLUTION="${{ inputs.resolution }}"
ARCHIVE="${RESOLUTION}.tar.gz"

CI_CONFIG="${GITHUB_WORKSPACE}/.github/ci-config.env"
if [ ! -f "${CI_CONFIG}" ]; then
echo "::error::ci-config.env not found at ${CI_CONFIG}"
exit 1
fi
source "${CI_CONFIG}"

RES_UPPER=$(echo "${RESOLUTION}" | tr '[:lower:]' '[:upper:]' | tr '-' '_')
TAG_VAR="RELEASE_TESTDATA_${RES_UPPER}"
TAG="${!TAG_VAR}"

if [ -z "${TAG}" ]; then
echo "::error::No release tag for resolution '${RESOLUTION}'. Add ${TAG_VAR}= to ci-config.env."
exit 1
fi

REPO="${DATA_REPOSITORY:-${GITHUB_REPOSITORY}}"
URL="https://github.com/${REPO}/releases/download/${TAG}/${ARCHIVE}"

echo "release-tag=${TAG}" >> $GITHUB_OUTPUT
echo "archive=${ARCHIVE}" >> $GITHUB_OUTPUT
echo "url=${URL}" >> $GITHUB_OUTPUT
echo "Resolved: ${TAG_VAR}=${TAG} → ${URL}"

- name: Cache test case archive
id: cache
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
with:
path: ${{ steps.resolve.outputs.archive }}
key: testdata-${{ steps.resolve.outputs.release-tag }}

- name: Download test case archive
if: steps.cache.outputs.cache-hit != 'true'
shell: bash
run: |
URL="${{ steps.resolve.outputs.url }}"
ARCHIVE="${{ steps.resolve.outputs.archive }}"
echo "Downloading ${ARCHIVE} from ${URL}..."
curl -fsSL --retry 5 --retry-delay 5 "${URL}" -o "${ARCHIVE}"
echo "Downloaded $(du -h "${ARCHIVE}" | cut -f1)"

- name: Extract test case
id: extract
shell: bash
run: |
ARCHIVE="${{ steps.resolve.outputs.archive }}"
DEST="${{ inputs.dest-dir }}"

echo "Cache hit: ${{ steps.cache.outputs.cache-hit }}"
echo "Archive: ${ARCHIVE} ($(du -h "${ARCHIVE}" | cut -f1))"

tar xzf "${ARCHIVE}"

CASE_DIR=$(tar tzf "${ARCHIVE}" 2>/dev/null | head -1 | cut -d/ -f1 || true)
if [ -z "${CASE_DIR}" ]; then
CASE_DIR=$(ls -td */ 2>/dev/null | head -1 | tr -d '/')
fi

if [ -z "${CASE_DIR}" ] || [ ! -d "${CASE_DIR}" ]; then
echo "::error::Failed to extract test case from ${ARCHIVE}"
exit 1
fi

if [ -n "${DEST}" ] && [ "${DEST}" != "${CASE_DIR}" ]; then
mv "${CASE_DIR}" "${DEST}"
CASE_DIR="${DEST}"
fi

echo "case-dir=${CASE_DIR}" >> $GITHUB_OUTPUT
echo "Extracted test case to: ${CASE_DIR}"
100 changes: 100 additions & 0 deletions .github/actions/ect-summary/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: 'ECT Summary'
description: >
Generate a consolidated Ensemble Consistency Test results table from
enriched result files produced by the validate-ect action. Writes a
Markdown table to $GITHUB_STEP_SUMMARY with auto-discovered columns.

inputs:
results-path:
description: 'Directory containing downloaded ect-result-* artifact subdirectories'
required: true

runs:
using: 'composite'
steps:
- name: Generate summary table
shell: bash
run: |
RESULTS_PATH="${{ inputs.results-path }}"

# Collect all result files
RESULT_FILES=()
for f in "${RESULTS_PATH}"/ect-result-*/ect-result.txt; do
[ -f "$f" ] && RESULT_FILES+=("$f")
done

if [ ${#RESULT_FILES[@]} -eq 0 ]; then
echo "::warning::No ECT result files found in ${RESULTS_PATH}"
echo "## Ensemble Consistency Test (ECT) Results" >> "$GITHUB_STEP_SUMMARY"
echo "" >> "$GITHUB_STEP_SUMMARY"
echo "No results available." >> "$GITHUB_STEP_SUMMARY"
exit 0
fi

# Discover column names from the first result file (all keys except "result")
COLUMNS=()
while IFS='=' read -r key value; do
[ -z "$key" ] && continue
if [ "$key" != "result" ]; then
COLUMNS+=("$key")
fi
done < "${RESULT_FILES[0]}"

# Build header row
HEADER="| "
SEPARATOR="| "
for col in "${COLUMNS[@]}"; do
COL_TITLE=$(echo "$col" | sed 's/.*/\u&/')
HEADER+="${COL_TITLE} | "
SEPARATOR+="--- | "
done
HEADER+="Result |"
SEPARATOR+="--- |"

# Build data rows
PASS=0 FAIL=0 ERROR=0 SKIP=0 TOTAL=0
ROWS=""
for f in "${RESULT_FILES[@]}"; do
TOTAL=$((TOTAL + 1))

# Parse key=value pairs
declare -A DATA=()
while IFS='=' read -r key value; do
[ -z "$key" ] && continue
DATA["$key"]="$value"
done < "$f"

RESULT="${DATA[result]}"
case "$RESULT" in
PASSED) ICON="PASSED"; PASS=$((PASS + 1)) ;;
FAILED) ICON="**FAILED**"; FAIL=$((FAIL + 1)) ;;
SKIPPED) ICON="SKIPPED"; SKIP=$((SKIP + 1)) ;;
*) ICON="ERROR"; ERROR=$((ERROR + 1)) ;;
esac

ROW="| "
for col in "${COLUMNS[@]}"; do
ROW+="${DATA[$col]:-—} | "
done
ROW+="${ICON} |"
ROWS+="${ROW}"$'\n'

unset DATA
done

SORTED_ROWS=$(echo "$ROWS" | sort)

{
echo "## Ensemble Consistency Test (ECT) Results"
echo ""
echo "$HEADER"
echo "$SEPARATOR"
echo "$SORTED_ROWS"
echo ""
echo "**Total: ${TOTAL}** — ${PASS} passed, ${FAIL} failed, ${ERROR} error, ${SKIP} skipped"

if [ ${FAIL} -gt 0 ] || [ ${ERROR} -gt 0 ]; then
echo ""
echo "> One or more ECT validations failed. Check individual ECT Validate job logs for PyCECT details."
fi
} >> "$GITHUB_STEP_SUMMARY"
47 changes: 47 additions & 0 deletions .github/actions/mpas-version/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: 'Get MPAS Version'
description: >
Read the MPAS version string from src/core_atmosphere/Registry.xml.
Strict — fails the workflow if the file is missing or the version
attribute cannot be parsed (no silent "unknown" fallback).

inputs:
registry-path:
description: 'Path to Registry.xml relative to GITHUB_WORKSPACE'
required: false
default: 'src/core_atmosphere/Registry.xml'

outputs:
version:
description: 'MPAS version string (e.g., 8.4.0)'
value: ${{ steps.extract.outputs.version }}

runs:
using: 'composite'
steps:
- id: extract
shell: bash
run: |
python3 - "${{ inputs.registry-path }}" <<'PYEOF'
import os
import sys
import xml.etree.ElementTree as ET

path = sys.argv[1]
if not os.path.isfile(path):
print(f"::error::MPAS Registry not found at {path}")
sys.exit(1)
try:
root = ET.parse(path).getroot()
except ET.ParseError as e:
print(f"::error::Could not parse {path}: {e}")
sys.exit(1)

version = root.attrib.get('version')
if not version:
print(f"::error::No version attribute on <registry> in {path}")
sys.exit(1)

with open(os.environ['GITHUB_OUTPUT'], 'a') as f:
f.write(f"version={version}\n")
print(f"MPAS version: {version}")
PYEOF
Loading
Loading