Skip to content

Commit 5fc31be

Browse files
Merge branch 'master' into gpu-optimizations
2 parents 6cc7acc + ad35e0e commit 5fc31be

117 files changed

Lines changed: 1572 additions & 417 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/docs.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ jobs:
1515

1616
steps:
1717
- uses: actions/checkout@v4
18+
with:
19+
fetch-depth: 0 # Full history for per-page last-updated dates
1820

1921
# We build doxygen from source because of
2022
# https://github.com/doxygen/doxygen/issues/9016
@@ -35,6 +37,12 @@ jobs:
3537
cmake -S . -B build -G Ninja --install-prefix="$(pwd)/build/install" -D MFC_DOCUMENTATION=ON
3638
ninja -C build install
3739
40+
- name: Verify essential site files
41+
run: |
42+
for f in index.html 404.html robots.txt; do
43+
test -f "build/install/docs/mfc/$f" || { echo "Missing $f"; exit 1; }
44+
done
45+
3846
- name: Upload Built Documentation Artifact
3947
uses: actions/upload-artifact@v4
4048
with:
@@ -51,7 +59,7 @@ jobs:
5159
base-url-path: https://mflowcode.github.io/
5260
path-to-root: build/install/docs/mfc
5361
include-pdf: false
54-
sitemap-format: txt
62+
sitemap-format: xml
5563

5664
- name: Output stats
5765
run: |
@@ -63,7 +71,7 @@ jobs:
6371
uses: lycheeverse/lychee-action@v2
6472
with:
6573
args: -c .lychee.toml build/install/docs/mfc/
66-
fail: false
74+
fail: true
6775

6876
- name: Publish Documentation
6977
if: github.repository == 'MFlowCode/MFC' && github.ref == 'refs/heads/master' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' )

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,11 @@ docs/documentation/*-example.png
4545
docs/documentation/examples.md
4646
docs/documentation/case_constraints.md
4747
docs/documentation/physics_constraints.md
48+
docs/documentation/architecture.md
49+
docs/pre_process/readme.md
50+
docs/simulation/readme.md
51+
docs/post_process/readme.md
52+
docs/api/readme.md
4853

4954
examples/*batch/*/
5055
examples/**/D/*

.lychee.toml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,13 @@ accept = ["200", "429"]
1616

1717
verbose = "error"
1818

19-
# Exclude sitemap from link checking (it contains pre-publish production URLs)
20-
exclude_path = ["**/sitemap.txt"]
19+
# Exclude sitemap file from scanning (it contains pre-publish production URLs)
20+
exclude_path = ["sitemap\\.xml"]
21+
22+
# Exclude URLs that fail due to external issues (broken SSL, pre-deploy only, etc.)
23+
exclude = [
24+
"https://mflowcode\\.github\\.io/sitemap\\.xml", # Only exists after deployment
25+
"https://cpe\\.ext\\.hpe\\.com", # HPE Cray docs have broken SSL cert
26+
"https://sc22\\.supercomputing\\.org", # Returns 415 to automated requests
27+
"https://strawberryperl\\.com", # Frequently times out
28+
]

CMakeLists.txt

Lines changed: 84 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,8 @@ if (MFC_DOCUMENTATION)
727727
set(DOXYGEN_IMAGE_PATH "\"${CMAKE_CURRENT_SOURCE_DIR}/docs/res\"\
728728
\"${CMAKE_CURRENT_SOURCE_DIR}/docs/${target}\"")
729729

730+
set(DOXYGEN_WARN_LOGFILE "\"${CMAKE_CURRENT_BINARY_DIR}/${target}-doxygen-warnings.log\"")
731+
730732
file(MAKE_DIRECTORY "${DOXYGEN_OUTPUT_DIRECTORY}")
731733

732734
configure_file(
@@ -801,11 +803,88 @@ if (MFC_DOCUMENTATION)
801803
\"${CMAKE_CURRENT_SOURCE_DIR}/docs/custom.css\"")
802804

803805
# > Generate Documentation & Landing Page
804-
GEN_DOCS(pre_process "MFC: Pre-Process")
805-
GEN_DOCS(simulation "MFC: Simulation")
806-
GEN_DOCS(post_process "MFC: Post-Process")
806+
GEN_DOCS(pre_process "MFC")
807+
GEN_DOCS(simulation "MFC")
808+
GEN_DOCS(post_process "MFC")
809+
GEN_DOCS(api "MFC")
807810
GEN_DOCS(documentation "MFC")
808811

812+
# Generate API landing pages for pre_process, simulation, post_process.
813+
# Scans src/{target}/*.fpp to produce module lists in docs/{target}/readme.md.
814+
add_custom_command(
815+
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gen-api-landing.stamp"
816+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/docs/gen_api_landing.py"
817+
${pre_process_FPPs} ${pre_process_F90s}
818+
${simulation_FPPs} ${simulation_F90s}
819+
${post_process_FPPs} ${post_process_F90s}
820+
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/docs/gen_api_landing.py"
821+
"${CMAKE_CURRENT_SOURCE_DIR}"
822+
COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/gen-api-landing.stamp"
823+
COMMENT "Generating API landing pages"
824+
VERBATIM
825+
)
826+
add_custom_target(gen_api_landing DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gen-api-landing.stamp")
827+
add_dependencies(pre_process_doxygen gen_api_landing)
828+
add_dependencies(simulation_doxygen gen_api_landing)
829+
add_dependencies(post_process_doxygen gen_api_landing)
830+
add_dependencies(api_doxygen gen_api_landing)
831+
832+
# Fix @file/@brief headers to match actual module/program declarations.
833+
# Handles mixed-case Fortran names and catches stale module renames.
834+
add_custom_command(
835+
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/fix-file-briefs.stamp"
836+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/docs/fix_file_briefs.py"
837+
${pre_process_FPPs} ${pre_process_F90s}
838+
${simulation_FPPs} ${simulation_F90s}
839+
${post_process_FPPs} ${post_process_F90s}
840+
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/docs/fix_file_briefs.py"
841+
"${CMAKE_CURRENT_SOURCE_DIR}"
842+
COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/fix-file-briefs.stamp"
843+
COMMENT "Fixing @file brief headers"
844+
VERBATIM
845+
)
846+
add_custom_target(fix_file_briefs DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/fix-file-briefs.stamp")
847+
add_dependencies(pre_process_doxygen fix_file_briefs)
848+
add_dependencies(simulation_doxygen fix_file_briefs)
849+
add_dependencies(post_process_doxygen fix_file_briefs)
850+
851+
# Generate architecture.md from template + module_categories.json + source briefs.
852+
add_custom_command(
853+
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/gen-architecture.stamp"
854+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/docs/gen_architecture.py"
855+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/module_categories.json"
856+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/documentation/architecture.md.in"
857+
${pre_process_FPPs} ${pre_process_F90s}
858+
${simulation_FPPs} ${simulation_F90s}
859+
${post_process_FPPs} ${post_process_F90s}
860+
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/docs/gen_architecture.py"
861+
"${CMAKE_CURRENT_SOURCE_DIR}"
862+
COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/gen-architecture.stamp"
863+
COMMENT "Generating architecture page"
864+
VERBATIM
865+
)
866+
add_custom_target(gen_architecture DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gen-architecture.stamp")
867+
add_dependencies(documentation_doxygen gen_architecture)
868+
869+
# Inject per-page last-updated dates into documentation markdown files.
870+
# Runs after auto-generated .md files exist, before Doxygen processes them.
871+
# Uses a stamp file so it only runs once per build.
872+
add_custom_command(
873+
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/inject-dates.stamp"
874+
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/docs/documentation/examples.md"
875+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/documentation/case_constraints.md"
876+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/documentation/physics_constraints.md"
877+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/documentation/cli-reference.md"
878+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/documentation/parameters.md"
879+
COMMAND "${Python3_EXECUTABLE}" "${CMAKE_CURRENT_SOURCE_DIR}/docs/inject-dates.py"
880+
"${CMAKE_CURRENT_SOURCE_DIR}"
881+
COMMAND "${CMAKE_COMMAND}" -E touch "${CMAKE_CURRENT_BINARY_DIR}/inject-dates.stamp"
882+
COMMENT "Injecting page dates into documentation"
883+
VERBATIM
884+
)
885+
add_custom_target(inject_page_dates DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/inject-dates.stamp")
886+
add_dependencies(documentation_doxygen inject_page_dates)
887+
809888
# > Copy Resources (main landing page & assets)
810889
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/docs/res"
811890
DESTINATION "docs/mfc")
@@ -814,6 +893,8 @@ if (MFC_DOCUMENTATION)
814893
DESTINATION "docs/mfc")
815894

816895
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/docs/index.html"
896+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/404.html"
897+
"${CMAKE_CURRENT_SOURCE_DIR}/docs/simulations.json"
817898
DESTINATION "docs/mfc")
818899
endif()
819900

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ Your first simulation:
7878
Visualize the output in `examples/3D_shockdroplet/silo_hdf5/` with ParaView, VisIt, or your favorite tool.
7979
For detailed build instructions (Linux, macOS, Windows/WSL, HPC clusters), see the [Getting Started guide](https://mflowcode.github.io/documentation/getting-started.html).
8080

81+
MFC is developed by the [Computational Physics Group at Georgia Tech](https://comp-physics.group) and collaborators.
8182
Get in touch with <a href="mailto:shb@gatech.edu">Spencer</a> if you have questions!
8283
We have an [active Slack channel](https://join.slack.com/t/mflowcode/shared_invite/zt-y75wibvk-g~zztjknjYkK1hFgCuJxVw) and development team.
8384
MFC has high- and low-level documentation, visualizations, and more on [its website](https://mflowcode.github.io/).

docs/404.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>404 | MFC</title>
7+
<script src="https://cdn.tailwindcss.com"></script>
8+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9+
</head>
10+
<body class="bg-slate-900 text-white min-h-screen flex flex-col items-center justify-center px-4">
11+
<div class="text-center max-w-md">
12+
<div class="text-8xl font-extrabold text-amber-400 mb-4">404</div>
13+
<h1 class="text-2xl font-bold mb-2">Page not found</h1>
14+
<p class="text-slate-400 mb-8">The page you're looking for doesn't exist or has been moved.</p>
15+
<div class="flex flex-col sm:flex-row gap-4 justify-center">
16+
<a href="/" class="px-6 py-3 bg-amber-400 text-slate-900 font-semibold rounded hover:bg-amber-300 transition-colors no-underline">
17+
<i class="fa-solid fa-house mr-2"></i>Home
18+
</a>
19+
<a href="/documentation/" class="px-6 py-3 bg-slate-700 font-semibold rounded hover:bg-slate-600 transition-colors no-underline">
20+
<i class="fa-solid fa-book mr-2"></i>Documentation
21+
</a>
22+
<a href="https://github.com/MFlowCode/MFC" class="px-6 py-3 bg-slate-700 font-semibold rounded hover:bg-slate-600 transition-colors no-underline">
23+
<i class="fa-brands fa-github mr-2"></i>GitHub
24+
</a>
25+
</div>
26+
</div>
27+
</body>
28+
</html>

docs/Doxyfile.in

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ WARN_FORMAT = "$file:$line: $text"
806806
# messages should be written. If left blank the output is written to standard
807807
# error (stderr).
808808

809-
WARN_LOGFILE =
809+
WARN_LOGFILE = @DOXYGEN_WARN_LOGFILE@
810810

811811
#---------------------------------------------------------------------------
812812
# Configuration options related to the input files
@@ -983,7 +983,7 @@ USE_MDFILE_AS_MAINPAGE =
983983
# also VERBATIM_HEADERS is set to NO.
984984
# The default value is: NO.
985985

986-
SOURCE_BROWSER = NO
986+
SOURCE_BROWSER = YES
987987

988988
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
989989
# classes and enums directly into the documentation.

docs/custom.css

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,44 @@
33
* Overrides for doxygen-awesome theme
44
*/
55

6+
/* Hide empty nav-path footer (kept for navtree.js height calculation) */
7+
#nav-path {
8+
height: 0;
9+
overflow: hidden;
10+
}
11+
12+
/* Cross-navigation panel at top of sidebar */
13+
#mfc-nav {
14+
display: flex;
15+
flex-direction: column;
16+
padding: 10px 12px 8px;
17+
border-bottom: 1px solid var(--separator-color);
18+
background: var(--side-nav-background);
19+
font-size: 0.8rem;
20+
}
21+
22+
#mfc-nav a {
23+
display: block;
24+
padding: 4px 8px;
25+
border-radius: 4px;
26+
color: var(--page-foreground-color);
27+
text-decoration: none;
28+
opacity: 0.75;
29+
transition: background 0.12s, opacity 0.12s;
30+
}
31+
32+
#mfc-nav a:hover {
33+
opacity: 1;
34+
background: var(--side-nav-background-highlight, rgba(0,0,0,0.05));
35+
}
36+
37+
#mfc-nav a.active {
38+
font-weight: 600;
39+
opacity: 1;
40+
color: var(--primary-color);
41+
background: var(--side-nav-background-highlight, rgba(0,0,0,0.05));
42+
}
43+
644
/* Narrower left navigation panel */
745
html {
846
--side-nav-fixed-width: 210px;
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Code Architecture {#architecture}
2+
3+
This page explains how MFC's source code is organized, how data flows through the solver, and where to find things. Read this before diving into the source.
4+
5+
## Three-Phase Pipeline
6+
7+
MFC runs as three separate executables that communicate via binary files on disk:
8+
9+
```
10+
pre_process ──> simulation ──> post_process
11+
(grid + (time (derived
12+
initial advance) quantities +
13+
conditions) visualization)
14+
```
15+
16+
| Phase | Entry Point | What It Does |
17+
|-------|-------------|--------------|
18+
| **Pre-Process** | `src/pre_process/p_main.f90` | Generates the computational grid and initial conditions from patch definitions. Writes binary grid and state files. |
19+
| **Simulation** | `src/simulation/p_main.fpp` | Reads the initial state and advances the governing equations in time. Periodically writes solution snapshots. |
20+
| **Post-Process** | `src/post_process/p_main.fpp` | Reads snapshots, computes derived quantities (vorticity, Schlieren, etc.), and writes Silo/HDF5 files for VisIt or ParaView. |
21+
22+
Each phase is an independent MPI program. The simulation phase is where nearly all compute time is spent.
23+
24+
## Directory Layout
25+
26+
```
27+
src/
28+
common/ Shared modules used by all three phases
29+
pre_process/ Pre-process source (grid generation, patch construction)
30+
simulation/ Simulation source (solver core, physics models)
31+
post_process/ Post-process source (derived quantities, formatted I/O)
32+
```
33+
34+
Shared modules in `src/common/` include MPI communication, derived types, variable conversion, and utility functions. They are compiled into each phase.
35+
36+
## Key Data Structures
37+
38+
Two arrays carry the solution through the entire simulation:
39+
40+
| Variable | Contents | When Used |
41+
|----------|----------|-----------|
42+
| `q_cons_vf` | **Conservative** variables: \f$\alpha\rho\f$, \f$\rho u\f$, \f$\rho v\f$, \f$\rho w\f$, \f$E\f$, \f$\alpha\f$ | Storage, time integration, I/O |
43+
| `q_prim_vf` | **Primitive** variables: \f$\rho\f$, \f$u\f$, \f$v\f$, \f$w\f$, \f$p\f$, \f$\alpha\f$ | Reconstruction, Riemann solving, physics |
44+
45+
Both are `vector_field` types (defined in `m_derived_types`), which are arrays of `scalar_field`. Each `scalar_field` wraps a 3D real array `sf(0:m, 0:n, 0:p)` representing one variable on the grid.
46+
47+
The index layout within `q_cons_vf` depends on the flow model:
48+
49+
```
50+
For model_eqns == 2 (5-equation, multi-fluid):
51+
52+
Index: 1 .. num_fluids | num_fluids+1 .. +num_vels | E_idx | adv_idx
53+
Meaning: alpha*rho_k | momentum components | energy | volume fractions
54+
```
55+
56+
Additional variables are appended for bubbles, elastic stress, magnetic fields, or chemistry species when those models are enabled. The total count is `sys_size`.
57+
58+
## The Simulation Loop
59+
60+
The simulation advances the solution through this call chain each time step:
61+
62+
```
63+
p_main (time-step loop)
64+
└─ s_perform_time_step
65+
├─ s_compute_dt [adaptive CFL time step]
66+
└─ s_tvd_rk [Runge-Kutta stages]
67+
├─ s_compute_rhs [assemble dq/dt]
68+
│ ├─ s_convert_conservative_to_primitive_variables
69+
│ ├─ s_populate_variables_buffers [MPI halo exchange]
70+
│ └─ for each direction (x, y, z):
71+
│ ├─ s_reconstruct_cell_boundary_values [WENO]
72+
│ ├─ s_riemann_solver [HLL/HLLC/HLLD]
73+
│ ├─ s_compute_advection_source_term [flux divergence]
74+
│ └─ (physics source terms: viscous, bubbles, etc.)
75+
├─ RK update: q_cons = weighted combination of stages
76+
├─ s_apply_bodyforces [if enabled]
77+
├─ s_pressure_relaxation [if 6-equation model]
78+
└─ s_ibm_correct_state [if immersed boundaries]
79+
```
80+
81+
### What happens at each stage
82+
83+
1. **Conservative → Primitive**: Convert stored `q_cons_vf` to `q_prim_vf` (density, velocity, pressure) using the equation of state. This is done by `m_variables_conversion`.
84+
85+
2. **MPI Halo Exchange**: Ghost cells at subdomain boundaries are filled by communicating with neighbor ranks. Handled by `m_mpi_proxy`.
86+
87+
3. **WENO Reconstruction** (`m_weno`): For each coordinate direction, reconstruct left and right states at cell faces from cell-average primitives using high-order weighted essentially non-oscillatory stencils.
88+
89+
4. **Riemann Solver** (`m_riemann_solvers`): At each cell face, solve the Riemann problem between left and right states to compute intercell fluxes. Available solvers: HLL, HLLC, HLLD.
90+
91+
5. **Flux Differencing** (`m_rhs`): Accumulate the RHS as \f$\partial q / \partial t = -\frac{1}{\Delta x}(F_{j+1/2} - F_{j-1/2})\f$ plus source terms (viscous stress, surface tension, bubble dynamics, body forces, etc.).
92+
93+
6. **Runge-Kutta Update** (`m_time_steppers`): Combine the RHS with the current state using TVD Runge-Kutta coefficients (1st, 2nd, or 3rd order SSP).
94+
95+
## Module Map
96+
97+
MFC has ~80 Fortran modules organized by function. Here is where to look for what:
98+
99+
<!-- MODULE_MAP -->
100+
101+
## MPI Parallelization
102+
103+
The computational domain is decomposed into subdomains via `MPI_Cart_create`. Each rank owns a contiguous block of cells in (x, y, z). Ghost cells of width `buff_size` surround each subdomain and are filled by halo exchange before each RHS evaluation.
104+
105+
On GPUs, the same domain decomposition applies. GPU kernels operate on the local subdomain, with explicit host-device transfers for MPI communication (unless GPU-aware MPI / RDMA is available).
106+
107+
## Adding New Physics
108+
109+
To add a new source term or physics model:
110+
111+
1. **Create a module** in `src/simulation/` (e.g., `m_my_model.fpp`)
112+
2. **Add initialization/finalization** subroutines called from `m_start_up`
113+
3. **Add RHS contributions** called from the dimensional loop in `m_rhs:s_compute_rhs`
114+
4. **Add parameters** to `m_global_parameters` and input validation to `m_checker`
115+
5. **Add a module-level brief** (enforced by the linter in `lint_docs.py`)
116+
6. **Add the module to `docs/module_categories.json`** so it appears in this page
117+
118+
Follow the pattern of existing modules like `m_body_forces` (simple) or `m_viscous` (more involved) as a template.

0 commit comments

Comments
 (0)