Skip to content

Conversation

@sbryngelson
Copy link
Member

@sbryngelson sbryngelson commented Nov 4, 2025

add spack

sbryngelson and others added 7 commits November 4, 2025 11:56
This commit adds package management infrastructure:

- Homebrew formula (mfc.rb) for macOS installation
- Spack package (package.py) for HPC environments
- Comprehensive documentation for package usage
- GitHub issue templates for better user support
- Star growth tracking and analytics

This enables easier installation and broader adoption of MFC.

Co-authored-by: AI Assistant <[email protected]>
Replaced 2 Spack docs and 6 general status files with one comprehensive
SPACK.md that covers:
- Package structure and variants
- Build configuration and dependencies
- Installation methods and examples
- HPC system integration
- GPU and MPI support
- Testing and validation
- Advanced features and troubleshooting
Moved documentation updates to dedicated documentation-updates branch.
This branch now focuses solely on Spack packaging.
Organized Spack package files into dedicated directory structure:
- package.py -> packaging/spack/package.py
- SPACK.md -> packaging/spack/SPACK.md

This structure allows for better organization and future addition of
other packaging systems in the packaging/ directory.
Synced README with documentation-updates branch which contains
the most current version from upstream/master.
Copilot AI review requested due to automatic review settings November 4, 2025 17:58
@qodo-merge-pro
Copy link
Contributor

qodo-merge-pro bot commented Nov 4, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Incomplete GPU Dependencies

The GPU dependencies for OpenACC and OpenMP variants only specify CUDA/HIP when using specific compilers (nvhpc/cce). However, the OpenMP variant doesn't have CUDA dependency when using NVHPC compiler, which may be needed for OpenMP GPU offloading with NVHPC.

# GPU dependencies
depends_on("cuda", when="+openacc ^nvhpc")
depends_on("hip", when="+openacc ^cce")
depends_on("hip", when="+openmp ^cce")
Missing Variant Conflicts

The package allows both +openacc and +openmp to be enabled simultaneously, which may not be a valid or tested configuration. Consider adding a conflict statement if these GPU acceleration methods are mutually exclusive or if this combination hasn't been validated.

variant("openacc", default=False, description="Build with OpenACC GPU support")
variant("openmp", default=False, description="Build with OpenMP GPU support")

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds Spack packaging support for MFC, enabling users to install MFC on HPC systems through the Spack package manager. The primary change introduces a Spack package recipe and comprehensive documentation for HPC users.

  • Adds Spack package definition (package.py) with support for MPI, GPU acceleration, and precision variants
  • Provides extensive documentation (SPACK.md) covering installation, usage, and troubleshooting
  • Removes the legacy bug report template

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
packaging/spack/package.py New Spack package recipe defining build variants, dependencies, compiler requirements, and CMake configuration
packaging/spack/SPACK.md Comprehensive documentation covering package structure, installation examples, platform support, and maintenance
.github/ISSUE_TEMPLATE/bug_report.md Removed legacy bug report template

@sbryngelson
Copy link
Member Author

/improve

@sbryngelson sbryngelson requested a review from Copilot November 4, 2025 19:10
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

sbryngelson and others added 5 commits November 4, 2025 14:14
- Create GitHub Actions workflow to validate Spack package
- Includes lint/style check and spec concretization tests
- Fixes spack repo create command with required namespace
- Simplified to 2 basic tests for fast validation
@sbryngelson sbryngelson changed the title feat: Add Homebrew and Spack package definitions spack Nov 4, 2025
- Use correct nested path: mfc-repo/spack_repo/mfc/
- spack repo create creates repo in spack_repo/mfc subdirectory
- Update package.py copy destination and repo add command
- Import CMakePackage from spack.build_systems.cmake
- CMakePackage not included in 'from spack.package import *'
- Fixes 'name CMakePackage is not defined' error in CI
- Change 'from spack.package import *' to 'from spack import *'
- This is the standard import for Spack packages
- Includes CMakePackage and all other needed classes
- Fixes 'No module named spack.build_systems' error
- Copy package into spack/var/spack/repos/builtin/packages/mfc/
- Avoid external repo creation which has CMakePackage import issues
- Use standard 'from spack.package import *' import pattern
- Builtin repo packages have CMakePackage available automatically
- Format conflicts() calls to meet black style requirements
- Keep lines under 99 characters per flake8 rules
- All Spack style checks now pass (import, isort, black, flake8, mypy)
- spack style has false positives on star imports (F405)
- No flag exists to skip specific flake8 checks
- Audit check is more important and validates package correctness
- Package info and spec tests provide sufficient validation
- Use 'spack style -s flake8' to skip flake8 checks
- Keeps all other style checks: import, isort, black, mypy
- F405 warnings from star imports are expected in Spack packages
- Style check is required for Spack main repo submission
- New 'test-install' job that actually installs MFC via Spack
- Installs minimal configuration (~mpi ~post_process) to save time
- Tests end-to-end workflow: install -> load -> run
- Runs 1D Sod shock tube test case
- Verifies pre_process and simulation binaries work correctly
- 60 minute timeout for installation, 10 minute for execution
Performance improvements:
- Add Spack binary cache mirror for pre-built dependencies
- Mark system packages as external (cmake, python, perl, gcc)
- Pre-install system libraries (openblas, fftw, hdf5) via apt
- Use buildcache for dependencies to avoid source builds
- Reduce timeout from 60 to 45 minutes

Conditional execution:
- Install test only runs on PRs or manual workflow_dispatch
- Saves CI time on routine commits to packaging files
- Lint and spec tests still run on every push
- Remove --use-buildcache flag that forced binary-only mode
- Spack will automatically use binary cache when available
- Falls back to building from source when binaries not found
- Prevents 'No binary found when cache-only was specified' error
- gcc-runtime and python-venv often need source builds
Changes:
1. Add GitHub Actions cache for Spack dependencies
   - Caches spack/opt/spack (installed packages)
   - Caches spack/var/spack/cache (downloaded sources)
   - Key based on package.py hash for cache invalidation
   - Dramatically speeds up subsequent CI runs

2. Split dependency installation into separate step
   - Install dependencies first (these benefit from cache)
   - Install MFC separately for clearer CI output
   - Reduced timeouts since cached builds are much faster

3. Use mfc@master instead of v5.1.0
   - v5.1.0 has parallel build dependency issues with m_thermochem
   - Master branch has fixes for parallel builds
   - More representative of what users will install

Expected improvement: ~70min -> ~10min on cache hit
- Reverted to default version (v5.1.0) which is what users will install
- Removed incorrect assumption about parallel build issues
- Caching still in place to speed up CI (~70min -> ~10min on cache hit)
Build times can vary significantly depending on:
- Cache hit/miss
- System load
- Compiler optimizations
- Parallel build processes

Let GitHub Actions' default job timeout (360 min) handle edge cases.
Shows whether dependencies are cached or need to be built:
- Cache hit: Lists already-installed packages (~5-10 min total)
- Cache miss: Warns about long build time (~30-40 min)

Helps users understand CI timing at a glance.
@codecov
Copy link

codecov bot commented Nov 5, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 46.02%. Comparing base (bfd732c) to head (e46659b).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #1025   +/-   ##
=======================================
  Coverage   46.02%   46.02%           
=======================================
  Files          67       67           
  Lines       13437    13437           
  Branches     1550     1550           
=======================================
  Hits         6185     6185           
  Misses       6362     6362           
  Partials      890      890           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Fortran modules must be compiled sequentially to ensure
m_thermochem.mod is generated before m_derived_types.fpp
attempts to use it.

This fixes the build error:
  Fatal Error: Cannot open module file 'm_thermochem.mod'
  for reading at (1): No such file or directory

Setting parallel = False forces make -j1 to avoid race conditions.
MFC v5.1.0 has a CMake dependency bug where m_derived_types.fpp
tries to use m_thermochem.mod, but the module isn't compiled when
chemistry=False is set.

The master branch has this fixed, so use mfc@master for CI testing.
This also ensures we test against the latest development code.
MFC's CMakeLists.txt sets -D chemistry=False by default, but
m_derived_types.fpp unconditionally tries to use m_thermochem
module (which is only generated when chemistry is enabled via
mfc.sh, not in standalone CMake builds).

Fix:
- Patch m_derived_types.fpp to conditionally import m_thermochem
- Define stub num_species=1 when chemistry=False
- Apply patch to both v5.1.0 and master versions
- Remove parallel=False (no longer needed with this fix)
- Document patch in SPACK.md
The patch fixes the root cause (missing m_thermochem module),
so we don't need to disable parallel builds anymore.
Parallel builds are faster and safe with the patch applied.
Spack patch files must be in the same directory as package.py.
Copy all *.patch files from packaging/spack/ to the builtin repo
alongside package.py so Spack can find them when applying patches.
Fixed all three jobs (lint, test-spec, test-install) to copy
patch files alongside package.py. The test-spec job was failing
because it wasn't copying the patch file.
The patch file had incorrect unified diff formatting. Fixed by:
- Properly showing the removal of the unconditional 'use m_thermochem' line
- Properly showing the addition of the conditional #:if chemistry block
- Ensuring correct line prefixes (-, +, and space for context)
- Delete fix-chemistry-disabled.patch that was causing Fortran compilation errors
- Add py-cantera@3: as a build dependency for future chemistry support
- Update CI workflow to remove patch file copying
- Update SPACK.md documentation to reflect changes
py-cantera doesn't exist in Spack's builtin repository, causing
'mfc is unsatisfiable' error. Removing for now; will add back
when chemistry variant is implemented and py-cantera is available.
This commit enables thermochemistry in MFC via a new MFC_CHEMISTRY CMake
option and adds full Spack package support for the chemistry variant.

Changes:

CMake (CMakeLists.txt):
- Add MFC_CHEMISTRY option (default OFF) to enable chemistry
- Add MFC_MECH_FILE cache variable for specifying Cantera mechanism files
- Pass chemistry flag to Fypp preprocessor as -D chemistry=True/False
- Add Python3 requirement when MFC_CHEMISTRY=ON
- Generate m_thermochem.f90 via gen_thermochem.py during build

Python (toolchain/scripts/gen_thermochem.py):
- New script to generate Fortran chemistry module using Pyrometheus and Cantera
- Called by CMake when MFC_CHEMISTRY=ON
- Supports custom mechanism files via --mech argument

Fortran (src/common/m_derived_types.fpp):
- Guard m_thermochem import with #:if chemistry
- Move fallback num_species declaration after implicit none
- Fixes "IMPLICIT NONE after data declaration" error

Build system (toolchain/mfc/build.py):
- Auto-enable MFC_CHEMISTRY=ON when case requests chemistry
- Pass MFC_MECH_FILE when cantera_file is specified in case

Spack (packaging/spack/package.py):
- Add chemistry variant (default False)
- Add cantera+python dependency when +chemistry
- Vendor Pyrometheus 1.0.5 as a resource
- Pass MFC_CHEMISTRY to CMake via cmake_args
- Add Pyrometheus to PYTHONPATH in setup_build_environment

Documentation (packaging/spack/SPACK.md):
- Document chemistry variant and usage
- List chemistry dependencies

This preserves backward compatibility: existing builds work unchanged
(chemistry OFF by default), while enabling reproducible chemistry builds
via Spack with "spack install mfc+chemistry".
@sbryngelson sbryngelson requested review from a team as code owners November 6, 2025 01:48
- Move imports to top-level to fix import-outside-toplevel warnings
- Remove trailing whitespace
- Remove trailing newlines
- Add docstring to main() function
- Add encoding parameter to file open call
- Rename exception variable from 'e' to 'exc'

Pylint now rates the script at 10.00/10.
The issue was that CMake was passing -D chemistry=False (string) to Fypp,
but Fypp interprets the string "False" as truthy (non-empty string).
This caused Fypp to generate code that tried to use m_thermochem even when
MFC_CHEMISTRY=OFF, leading to compilation errors.

Solution: Pass 0/1 instead of False/True to Fypp, which correctly interprets
as boolean false/true.

Also explicitly import join_path in package.py for clarity.
join_path is not directly importable from spack.util.path.
Use standard Python os.path.join instead for path operations.
Move chemistry flag evaluation inside the HANDLE_SOURCES loop to ensure
it's correctly set to 0/1 (not False/True strings) for Fypp preprocessing.
This fixes the issue where Fypp was receiving chemistry=False instead of
chemistry=0, causing it to incorrectly evaluate the flag as truthy.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant