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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/mpi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: MPI Galaxy Demo

permissions:
contents: read

on:
push:
branches: [ main ]
pull_request:

concurrency:
group: mpi-${{ github.ref }}
cancel-in-progress: true

jobs:
mpi-galaxy:
runs-on: ubuntu-latest

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

- name: Install dependencies (MPI + HDF5 + Python)
run: |
sudo apt-get update
sudo apt-get install -y mpich libhdf5-dev libomp-dev cmake build-essential python3

- name: Configure project (CMake)
run: |
mkdir -p build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release -DNEXT_FP64=ON -DNEXT_MPI=ON

- name: Build project
run: |
cd build
cmake --build . -- -j$(nproc)

- name: Run Galaxy demo (timed)
run: |
# Go back to project root
cd $GITHUB_WORKSPACE/examples/GalaxyDemo
python3 galaxy.py
# Run with 2 MPI ranks and 2 OpenMP threads, stop after 20s
timeout 60s mpiexec -n 2 ../../next galaxy.txt 1 0.01 0.1 hdf5 || true

- name: Upload simulation outputs
uses: actions/upload-artifact@v4
with:
name: galaxy-dumps
path: |
examples/GalaxyDemo/dump_*.hdf5
examples/GalaxyDemo/dump_*.xdmf
55 changes: 38 additions & 17 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,41 @@ if (MINGW)
elseif (MSVC)
message(STATUS "Detected MSVC — using MSVC settings")
set(USING_MSVC TRUE)
elseif (APPLE)
message(STATUS "Detected macOS — limited MPI support")
set(USING_APPLE TRUE)
elseif (UNIX)
message(STATUS "Detected Linux/UNIX — using standard settings")
set(USING_UNIX TRUE)
endif()

# ============================
# Options
# ============================
option(NEXT_FP32 "Use 32-bit floats (scalar)" OFF)
option(NEXT_FP64 "Use 64-bit floats (scalar)" ON)
option(NEXT_MPI "Enable MPI support" OFF)

# Option: copy final executable to source dir
option(NEXT_COPY_TO_CMAKE_SOURCE_DIR "Copy final executable from build dir to source dir" ON)

# ============================
# Precision modes
# ============================
set(NEXT_MODES
NEXT_FP32
NEXT_FP64
)
set(NEXT_MODES NEXT_FP32 NEXT_FP64)

# Count enabled modes
set(NEXT_MODE_COUNT 0)
foreach(m ${NEXT_MODES})
if(${m})
math(EXPR NEXT_MODE_COUNT "${NEXT_MODE_COUNT} + 1")
endif()
endforeach()

# Enforce exactly one mode
if(NEXT_MODE_COUNT EQUAL 0)
message(FATAL_ERROR "You must enable NEXT_FP64 or NEXT_FP32.")
elseif(NEXT_MODE_COUNT GREATER 1)
message(FATAL_ERROR "Enable only one precision mode.")
endif()

# Apply compile definitions
if(NEXT_FP32)
add_compile_definitions(NEXT_FP32)
elseif(NEXT_FP64)
Expand All @@ -62,7 +62,10 @@ file(GLOB ARGPARSE_FILES ${CMAKE_SOURCE_DIR}/argparse/*.cpp)

add_executable(next ${SRC_FILES} ${ARGPARSE_FILES})

option(ENABLE_VEC_REPORT "Enable compiler vectorization reports" ON)
# ============================
# Vectorization reports
# ============================
option(ENABLE_VEC_REPORT "Enable compiler vectorization reports" OFF)

if(ENABLE_VEC_REPORT)
if(CMAKE_CXX_COMPILER_ID MATCHES "IntelLLVM")
Expand All @@ -74,38 +77,56 @@ if(ENABLE_VEC_REPORT)
endif()
endif()


# ============================
# OpenMP
# ============================
find_package(OpenMP QUIET)
if(OpenMP_CXX_FOUND)
message(STATUS "OpenMP detected — enabling multithreading.")

if(MSVC)
# Force MSVC to use the modern LLVM backend (supports OpenMP 3.0+ and size_t)
# We add it as a compiler option because MSVC's default find_package
# often defaults to the legacy /openmp flag.
target_compile_options(next PRIVATE /openmp:llvm)
else()
target_link_libraries(next PRIVATE OpenMP::OpenMP_CXX)
endif()

else()
message(STATUS "OpenMP not found — building in single-threaded mode.")
endif()

# ============================
# MPI detection
# ============================
if(NEXT_MPI)
if(USING_UNIX)
# Linux: standard OpenMPI
find_package(MPI REQUIRED)
message(STATUS "MPI (OpenMPI) detected — enabling distributed memory parallelism.")
target_compile_definitions(next PRIVATE NEXT_MPI)
target_link_libraries(next PRIVATE MPI::MPI_CXX)

elseif(USING_MSVC OR USING_MINGW)
# Windows: Microsoft MPI
find_package(MPI REQUIRED)
message(STATUS "MPI (MS-MPI) detected — enabling distributed memory parallelism.")
target_compile_definitions(next PRIVATE NEXT_MPI)
target_link_libraries(next PRIVATE MPI::MPI_CXX)

elseif(USING_APPLE)
message(WARNING "MPI requested, but macOS does not ship MPI by default. Please install OpenMPI via Homebrew (brew install open-mpi).")
find_package(MPI REQUIRED)
target_compile_definitions(next PRIVATE NEXT_MPI)
target_link_libraries(next PRIVATE MPI::MPI_CXX)
endif()
endif()

# ============================
# HDF5 detection
# ============================
# MSVC: use vcpkg or prebuilt binaries
if (USING_MSVC AND DEFINED ENV{HDF5_DIR})
set(HDF5_ROOT "$ENV{HDF5_DIR}")
set(CMAKE_PREFIX_PATH "${HDF5_ROOT};${CMAKE_PREFIX_PATH}")
endif()

if (USING_MINGW)
# MSYS2 MinGW installs HDF5 here
set(CMAKE_PREFIX_PATH "C:/tools/msys64/mingw64")
message(STATUS "Using MSYS2 MinGW HDF5 path: ${CMAKE_PREFIX_PATH}")
endif()
Expand Down
46 changes: 36 additions & 10 deletions argparse/argparse.cpp
Original file line number Diff line number Diff line change
@@ -1,33 +1,59 @@
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#include "argparse.hpp"
#include <iostream>
#include <stdexcept>
#ifdef NEXT_MPI
#include <mpi.h>
#endif

namespace next {

Arguments parse_arguments(int argc, char** argv)
Arguments parse_arguments(int argc, char** argv, int rank)
{
if (argc != 6) {
std::cerr << "Usage: next <input.txt> <threads> <dt> <dump_interval> <vtk|vtu|hdf5>\n";
// Only rank 0 prints usage
if (rank == 0) {
std::cerr << "Usage: next <input.txt> <threads> <dt> <dump_interval> <vtk|vtu|hdf5>\n";
}

#ifdef NEXT_MPI
MPI_Finalize();
#endif
std::exit(1);
}

Arguments args;

args.input_file = argv[1];
args.threads = std::stoi(argv[2]);
args.dt = std::stod(argv[3]);
args.input_file = argv[1];
args.threads = std::stoi(argv[2]);
args.dt = std::stod(argv[3]);
args.dump_interval = std::stod(argv[4]);

std::string fmt = argv[5];

if (fmt == "vtk")
if (fmt == "vtk") {
args.format = OutputFormat::VTK;
else if (fmt == "vtu")
} else if (fmt == "vtu") {
args.format = OutputFormat::VTU;
else if (fmt == "hdf5")
} else if (fmt == "hdf5") {
args.format = OutputFormat::HDF5;
else {
std::cerr << "Choose a file format: vtk, vtu, or hdf5\n";
} else {
if (rank == 0) {
std::cerr << "Choose a file format: vtk, vtu, or hdf5\n";
}
#ifdef NEXT_MPI
MPI_Finalize();
#endif
std::exit(1);
}

Expand Down
2 changes: 1 addition & 1 deletion argparse/argparse.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@ struct Arguments {
OutputFormat format;
};

Arguments parse_arguments(int argc, char** argv);
Arguments parse_arguments(int argc, char** argv, int rank);

}
Loading
Loading