164 lines
6.4 KiB
Python
164 lines
6.4 KiB
Python
#!/usr/bin/env python3
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
|
|
def check_command_installed(cmd):
|
|
"""Checks if a command-line tool is installed in the current environment."""
|
|
return shutil.which(cmd) is not None
|
|
|
|
def run_process(args, description):
|
|
"""Runs a subprocess with clean console updates."""
|
|
print(f"\n[Running] {description}...")
|
|
try:
|
|
res = subprocess.run(args, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
print(f"[Success] {description} completed successfully!")
|
|
if res.stdout.strip():
|
|
print(res.stdout.strip())
|
|
return True
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"[Error] {description} FAILED with exit code {e.returncode}!")
|
|
if e.stdout:
|
|
print("--- STDOUT ---")
|
|
print(e.stdout.strip())
|
|
if e.stderr:
|
|
print("--- STDERR ---")
|
|
print(e.stderr.strip())
|
|
return False
|
|
except Exception as e:
|
|
print(f"[Error] Failed to execute process: {e}")
|
|
return False
|
|
|
|
def build_orchestrator():
|
|
workspace_dir = os.path.dirname(os.path.abspath(__file__))
|
|
docs_dir = os.path.join(workspace_dir, "docs")
|
|
site_dir = os.path.join(workspace_dir, "site")
|
|
|
|
# Clean old docs and site
|
|
if os.path.exists(docs_dir):
|
|
shutil.rmtree(docs_dir)
|
|
os.makedirs(docs_dir, exist_ok=True)
|
|
os.makedirs(os.path.join(docs_dir, "python"), exist_ok=True)
|
|
|
|
if os.path.exists(site_dir):
|
|
shutil.rmtree(site_dir)
|
|
|
|
# 1. Create landing index.md
|
|
index_path = os.path.join(docs_dir, "index.md")
|
|
print(f"Creating landing index: {index_path}")
|
|
with open(index_path, 'w', encoding='utf-8') as f:
|
|
f.write("""# HPC DNS Post-Processing Reference Manual
|
|
|
|
Welcome to the automated documentation suite for the high-order compact difference post-processing project! This manual includes reference documentation for both the compiled Fortran core and the Python binds/algebraic generators.
|
|
|
|
---
|
|
|
|
## Architecture Overview
|
|
|
|
This post-processor compiles algebraic equations defined in a custom DSL (Domain Specific Language), computes high-order derivatives (1st & 2nd spatial derivatives) using tridiagonal finite differences, and leverages parallel MPI-IO blocks. Below is the primary compiler pipeline:
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[code_gen.py / DSL Input] -->|AST Compiler Pipeline| B[post.py / Code Gen]
|
|
B -->|Generates budget kernels| C[m_calculate.f90]
|
|
C -->|LU Tridiagonal Solvers| D[Compact.f90]
|
|
C -->|Array allocations| E[m_arrays.f90]
|
|
F[post.f90 / Main Driver] -->|Orchestrates calculations| C
|
|
F -->|Parallelizes domain| G[m_openmpi.f90]
|
|
F -->|Loads run configuration| H[m_parameters.f90]
|
|
I[pycompact.py / Bindings] -->|Wraps CPU calculations| C
|
|
```
|
|
|
|
---
|
|
|
|
## Navigation Guide
|
|
|
|
- **[Python API Reference](python/code_gen.md)**: Automatically parsed API and signatures for the DSL parsers, topological compiler stages, and Python wrappers.
|
|
- **[Fortran Core Reference](fortran.md)**: Standard documentation compiled by `FORD` covering tridiagonal compact solvers, math kernels, and MPI bindings.
|
|
|
|
*Generated automatically using industry-standard tools: FORD, MkDocs, and Material theme.*
|
|
""")
|
|
|
|
# 2. Create fortran.md entry page
|
|
fortran_entry_path = os.path.join(docs_dir, "fortran.md")
|
|
print(f"Creating Fortran entry: {fortran_entry_path}")
|
|
with open(fortran_entry_path, 'w', encoding='utf-8') as f:
|
|
f.write("""# Fortran Core API Reference
|
|
|
|
The Fortran core elements have been fully documented and compiled using **FORD** (FORtran Documenter), which extracts comments (`!>` and `!!`) and draws rich module dependency graphs.
|
|
|
|
---
|
|
|
|
## View Interactive Documentation
|
|
|
|
[👉 Click Here to Open Interactive Fortran API Reference](fortran_api/index.html){: .md-button .md-button--primary .md-button--large }
|
|
|
|
---
|
|
|
|
### Core Modules Cataloged
|
|
|
|
- **[[Compact]]**: Solves compact finite difference scheme equations using high-order tridiagonal/pentadiagonal schemes.
|
|
- **[[m_calculate]]**: Runs budget calculations, spatial derivatives, and pieces Arrhenius chemical kinetics.
|
|
- **[[m_arrays]]**: Handles array allocations and instant budget memory blocks.
|
|
- **[[m_openmpi]]**: Wraps domain sizing, grid splitting, and MPI communicators.
|
|
- **[[m_parameters]]**: Loads physical settings, boundary configurations, and grid sizes from file inputs.
|
|
- **[[post]]**: Entry driver performing budget calculation run tasks.
|
|
""")
|
|
|
|
# 3. Create Python stubs for mkdocstrings
|
|
python_modules = [
|
|
("code_gen", "Code Generator (`code_gen.py`)"),
|
|
("post", "Compiler Stages (`post.py`)"),
|
|
("pycompact", "Python Bindings (`pycompact.py`)")
|
|
]
|
|
for mod_name, title in python_modules:
|
|
stub_path = os.path.join(docs_dir, "python", f"{mod_name}.md")
|
|
print(f"Creating Python stub: {stub_path}")
|
|
with open(stub_path, 'w', encoding='utf-8') as f:
|
|
f.write(f"""# {title}
|
|
|
|
::: {mod_name}
|
|
""")
|
|
|
|
# 4. Environment validation
|
|
missing_tools = []
|
|
if not check_command_installed("ford"):
|
|
missing_tools.append("ford")
|
|
if not check_command_installed("mkdocs"):
|
|
missing_tools.append("mkdocs")
|
|
|
|
if missing_tools:
|
|
print("\n" + "="*80)
|
|
print(" [Warning] Missing Required Documentation Tools!")
|
|
print("="*80)
|
|
print("To compile the complete interactive manual, please install the requirements:")
|
|
print(" pip install -r requirements.txt")
|
|
print("Note: If running in a virtualenv, make sure it is activated.")
|
|
print("="*80 + "\n")
|
|
return False
|
|
|
|
# 5. Compile Fortran API docs using FORD
|
|
ford_success = run_process(["ford", "ford.md"], "FORD Fortran Compiler")
|
|
if not ford_success:
|
|
print("[Warning] FORD documentation compilation failed. Continuing to MkDocs compilation...")
|
|
|
|
# 6. Compile Python API and build MkDocs site
|
|
mkdocs_success = run_process(["mkdocs", "build"], "MkDocs Website Compiler")
|
|
if mkdocs_success:
|
|
print("\n" + "="*80)
|
|
print(" 🎉 Documentation manual built successfully!")
|
|
print("="*80)
|
|
print(f"Output directory: {site_dir}")
|
|
print("To view or serve the website locally, run:")
|
|
print(" mkdocs serve")
|
|
print("="*80)
|
|
else:
|
|
print("\n[Error] MkDocs website compilation FAILED!")
|
|
return False
|
|
|
|
return True
|
|
|
|
if __name__ == "__main__":
|
|
success = build_orchestrator()
|
|
sys.exit(0 if success else 1)
|