diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..9b2c43c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+# Documentation outputs
+site/
+docs/fortran_api/
+
+# Compiled Fortran products
+*.mod
+*.o
+code/x-edge-cold-bc-uPrime-hybrid
+
+# Python caches and local settings
+__pycache__/
+*.pyc
+.pytest_cache/
+
+# Local testing and scratch directories
+scratch/ic1_regression_test/
+Plan-Draft.MD
diff --git a/build_docs.py b/build_docs.py
index d319132..131ba05 100644
--- a/build_docs.py
+++ b/build_docs.py
@@ -1,475 +1,164 @@
#!/usr/bin/env python3
import os
-import re
-import ast
import shutil
+import subprocess
+import sys
-class FortranParser:
- """A robust line-by-line state-machine parser for Fortran free-form source files.
- Correctly resolves line continuations (`&`) and extracts Doxygen/FORD-style comments.
- """
- def __init__(self):
- # Match MODULE name (excluding MODULE PROCEDURE)
- self.module_re = re.compile(r'^\s*module\s+(\w+)\s*$', re.IGNORECASE)
- # Match SUBROUTINE name
- self.subroutine_re = re.compile(r'^\s*(?:recursive\s+|mpich\s+)?subroutine\s+(\w+)\s*(?:\(([^)]*)\))?', re.IGNORECASE)
- # Match FUNCTION name
- self.function_re = re.compile(
- r'^\s*(?:recursive\s+)?(?:real|integer|double\s+precision|logical|character|complex)?(?:\([\w*=]+\))?\s*function\s+(\w+)\s*(?:\(([^)]*)\))?',
- re.IGNORECASE
- )
+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 parse_file(self, filepath):
- with open(filepath, 'r', encoding='utf-8') as f:
- raw_lines = f.readlines()
-
- # Resolve line continuations using &
- lines = []
- current_line = ""
- for line in raw_lines:
- trimmed = line.strip()
- # If the entire line is a comment, keep it as is
- if trimmed.startswith('!'):
- lines.append((line.rstrip('\r\n'), True))
- continue
-
- # Partition the line by '!' to separate code and inline comments
- code_part = ""
- in_string = False
- str_char = None
- for i, char in enumerate(line):
- if char in ("'", '"'):
- if not in_string:
- in_string = True
- str_char = char
- elif str_char == char:
- in_string = False
- elif char == '!' and not in_string:
- code_part = line[:i]
- break
- else:
- code_part = line
-
- code_trimmed = code_part.strip()
- if code_trimmed.endswith('&'):
- current_line += code_trimmed[:-1].strip() + " "
- else:
- if current_line:
- lines.append((current_line + code_trimmed, False))
- current_line = ""
- else:
- lines.append((line.rstrip('\r\n'), False))
+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
- # Parse resolved lines
- elements = []
- current_comments = []
- module_doc = ""
- in_module = False
-
- for line_str, is_cmt in lines:
- trimmed = line_str.strip()
- if is_cmt or trimmed.startswith('!'):
- if trimmed.startswith('!>') or trimmed.startswith('!!'):
- cleaned_comment = trimmed[2:].strip()
- current_comments.append(cleaned_comment)
- continue
-
- if not trimmed:
- if not in_module and not elements and current_comments:
- module_doc = "\n".join(current_comments)
- current_comments = []
- continue
-
- m_mod = self.module_re.match(trimmed)
- m_sub = self.subroutine_re.match(trimmed)
- m_func = self.function_re.match(trimmed)
-
- if m_mod:
- in_module = True
- mod_name = m_mod.group(1)
- elements.append({
- 'type': 'module',
- 'name': mod_name,
- 'doc': "\n".join(current_comments) if current_comments else ""
- })
- current_comments = []
- elif m_sub:
- sub_name = m_sub.group(1)
- args_str = m_sub.group(2) or ""
- args = [a.strip() for a in args_str.split(',') if a.strip()]
- elements.append({
- 'type': 'subroutine',
- 'name': sub_name,
- 'args': args,
- 'doc': "\n".join(current_comments) if current_comments else ""
- })
- current_comments = []
- elif m_func:
- func_name = m_func.group(1)
- args_str = m_func.group(2) or ""
- args = [a.strip() for a in args_str.split(',') if a.strip()]
- elements.append({
- 'type': 'function',
- 'name': func_name,
- 'args': args,
- 'doc': "\n".join(current_comments) if current_comments else ""
- })
- current_comments = []
- else:
- # Clear comment buffer if normal statement is met
- current_comments = []
-
- return {
- 'doc': module_doc,
- 'elements': elements
- }
-
-
-class PythonASTParser:
- """Uses Python standard library `ast` module to safely parse classes, methods,
- decorators, functions, and Google-style docstrings from Python modules.
- """
- def get_node_name(self, node):
- if hasattr(ast, 'unparse'):
- return ast.unparse(node).strip()
- if isinstance(node, ast.Name):
- return node.id
- elif isinstance(node, ast.Attribute):
- return f"{self.get_node_name(node.value)}.{node.attr}"
- elif isinstance(node, ast.Call):
- return f"{self.get_node_name(node.func)}(...)"
- return str(node)
-
- def parse_file(self, filepath):
- with open(filepath, 'r', encoding='utf-8') as f:
- content = f.read()
- try:
- tree = ast.parse(content)
- except SyntaxError as e:
- print(f"Syntax error parsing {filepath}: {e}")
- return None
-
- module_doc = ast.get_docstring(tree) or ""
- elements = []
-
- for node in ast.iter_child_nodes(tree):
- if isinstance(node, ast.ClassDef):
- class_doc = ast.get_docstring(node) or ""
- methods = []
- for child in ast.iter_child_nodes(node):
- if isinstance(child, ast.FunctionDef):
- method_doc = ast.get_docstring(child) or ""
- args = [a.arg for a in child.args.args]
- decorators = [self.get_node_name(d) for d in child.decorator_list]
- methods.append({
- 'name': child.name,
- 'args': args,
- 'doc': method_doc,
- 'decorators': decorators
- })
- elements.append({
- 'type': 'class',
- 'name': node.name,
- 'bases': [self.get_node_name(b) for b in node.bases],
- 'doc': class_doc,
- 'methods': methods
- })
- elif isinstance(node, ast.FunctionDef):
- func_doc = ast.get_docstring(node) or ""
- args = [a.arg for a in node.args.args]
- decorators = [self.get_node_name(d) for d in node.decorator_list]
- elements.append({
- 'type': 'function',
- 'name': node.name,
- 'args': args,
- 'doc': func_doc,
- 'decorators': decorators
- })
- return {
- 'doc': module_doc,
- 'elements': elements
- }
-
-
-def format_docstring(doc):
- """Formats raw docstrings/comments into clean Markdown."""
- if not doc:
- return "*No description provided.*"
-
- # Process Google Style or Doxygen tags into neat markdown sections
- lines = doc.split('\n')
- formatted_lines = []
- in_args = False
- in_returns = False
-
- for line in lines:
- trimmed = line.strip()
-
- # Google style section headers
- if trimmed == 'Args:':
- formatted_lines.append("\n**Arguments:**\n")
- in_args = True
- in_returns = False
- continue
- elif trimmed == 'Returns:':
- formatted_lines.append("\n**Returns:**\n")
- in_args = False
- in_returns = True
- continue
- elif trimmed in ('Raises:', 'Attributes:'):
- formatted_lines.append(f"\n**{trimmed[:-1]}:**\n")
- in_args = in_returns = False
- continue
-
- # Parse params inside arguments or return
- if in_args and trimmed:
- # Format "arg_name (type): description"
- match = re.match(r'^([\w_]+)\s*(?:\(([^)]+)\))?\s*:\s*(.*)$', trimmed)
- if match:
- name, arg_type, desc = match.groups()
- type_str = f" *({arg_type})*" if arg_type else ""
- formatted_lines.append(f"- ` {name} `{type_str}: {desc}")
- continue
-
- # Parse Doxygen tags
- if trimmed.startswith('@param'):
- match = re.match(r'^@param\s+([\w_]+)\s*(.*)$', trimmed)
- if match:
- name, desc = match.groups()
- formatted_lines.append(f"- ` {name} `: {desc}")
- continue
- elif trimmed.startswith('@return'):
- desc = trimmed.replace('@return', '').strip()
- formatted_lines.append(f"\n**Returns:**\n\n{desc}")
- continue
- elif trimmed.startswith('@note'):
- desc = trimmed.replace('@note', '').strip()
- formatted_lines.append(f"\n> [!NOTE]\n> {desc}")
- continue
- elif trimmed.startswith('@author'):
- desc = trimmed.replace('@author', '').strip()
- formatted_lines.append(f"\n*Author: {desc}*")
- continue
-
- formatted_lines.append(line)
-
- return "\n".join(formatted_lines).strip()
-
-
-def build_all_docs():
+def build_orchestrator():
workspace_dir = os.path.dirname(os.path.abspath(__file__))
- code_dir = os.path.join(workspace_dir, "code")
docs_dir = os.path.join(workspace_dir, "docs")
+ site_dir = os.path.join(workspace_dir, "site")
- # Recreate the docs directory
+ # 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)
- fortran_parser = FortranParser()
- py_parser = PythonASTParser()
+ if os.path.exists(site_dir):
+ shutil.rmtree(site_dir)
- # Files to parse
- fortran_files = [
- "Compact.f90",
- "m_arrays.f90",
- "m_calculate.f90",
- "m_openmpi.f90",
- "m_parameters.f90",
- "post.f90",
- "post_dns.f90"
+ # 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}
- python_files = [
- ("code_gen.py", "code/code_gen/code_gen.py"),
- ("post.py", "code/code_gen/post.py"),
- ("pycompact.py", "code/pycompact/pycompact.py")
- ]
+::: {mod_name}
+""")
- all_modules = []
+ # 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")
- # 1. Parse Fortran files
- for fname in fortran_files:
- path = os.path.join(code_dir, fname)
- if not os.path.exists(path):
- continue
-
- print(f"Parsing Fortran file: {fname}")
- res = fortran_parser.parse_file(path)
- if not res:
- continue
-
- all_modules.append({
- 'name': fname,
- 'lang': 'fortran',
- 'data': res
- })
+ 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
- # 2. Parse Python files
- for key_name, rel_path in python_files:
- path = os.path.join(workspace_dir, rel_path)
- if not os.path.exists(path):
- continue
-
- print(f"Parsing Python file: {key_name}")
- res = py_parser.parse_file(path)
- if not res:
- continue
-
- all_modules.append({
- 'name': key_name,
- 'lang': 'python',
- 'data': res
- })
+ # 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...")
- # 3. Generate Markdown files
- for mod in all_modules:
- mname = mod['name']
- lang = mod['lang']
- data = mod['data']
-
- md_filename = mname.replace('.f90', '.md').replace('.py', '.md')
- md_path = os.path.join(docs_dir, md_filename)
-
- with open(md_path, 'w', encoding='utf-8') as md_file:
- # Header banner
- badge = "Fortran Source" if lang == 'fortran' else "Python Source"
- badge_color = "blue" if lang == 'fortran' else "green"
-
- md_file.write(f"# {mname}\n\n")
- md_file.write(f"\n\n")
-
- # Smart Overview Fallback
- overview_doc = data['doc'].strip()
- if not overview_doc:
- for elem in data['elements']:
- if elem['type'] == 'module' and elem.get('doc'):
- overview_doc = elem['doc'].strip()
- break
- else:
- for elem in data['elements']:
- if elem.get('doc'):
- overview_doc = elem['doc'].strip()
- break
-
- md_file.write("## Overview\n\n")
- md_file.write(format_docstring(overview_doc) + "\n\n")
-
- # Table of Contents
- md_file.write("## API Index\n\n")
- has_elements = False
- for elem in data['elements']:
- has_elements = True
- elem_type = elem['type'].capitalize()
- md_file.write(f"- [{elem_type}: `{elem['name']}`](#{elem['name'].lower()})\n")
- if not has_elements:
- md_file.write("*No direct class or function definitions extracted from this file.*\n")
- md_file.write("\n---\n\n")
-
- # API Reference details
- md_file.write("## API Reference\n\n")
- for elem in data['elements']:
- el_name = elem['name']
- el_type = elem['type']
- el_doc = format_docstring(elem.get('doc', ''))
-
- # Format headers depending on type
- if el_type == 'module':
- md_file.write(f"### [Module] `{el_name}`\n\n")
- md_file.write(el_doc + "\n\n")
- elif el_type == 'class':
- bases_str = f"({', '.join(elem['bases'])})" if elem['bases'] else ""
- md_file.write(f"### [Class] `{el_name}{bases_str}`\n\n")
- md_file.write(el_doc + "\n\n")
-
- if elem['methods']:
- md_file.write("#### Methods\n\n")
- for method in elem['methods']:
- m_args = ", ".join(method['args'])
- decs = "".join([f"`@{d}`
" for d in method['decorators']])
- md_file.write(f"##### `{method['name']}({m_args})`\n\n")
- if decs:
- md_file.write(f"**Decorators:** {decs}\n\n")
- md_file.write(format_docstring(method['doc']) + "\n\n")
- elif el_type in ('subroutine', 'function'):
- args_str = ", ".join(elem['args'])
- decs = "".join([f"`@{d}`
" for d in elem.get('decorators', [])])
- elem_badge = "Subroutine" if el_type == 'subroutine' else "Function"
-
- md_file.write(f"### [{elem_badge}] `{el_name}`\n\n")
- md_file.write("```fortran\n" if lang == 'fortran' else "```python\n")
- md_file.write(f"{el_type} {el_name}({args_str})\n")
- md_file.write("```\n\n")
-
- if decs:
- md_file.write(f"**Decorators:** {decs}\n\n")
-
- md_file.write(el_doc + "\n\n")
-
- md_file.write("---\n\n")
-
- # 4. Generate master README.md index
- readme_path = os.path.join(docs_dir, "README.md")
- with open(readme_path, 'w', encoding='utf-8') as ri:
- ri.write("# HPC DNS Post-Processing Reference Manual\n\n")
- ri.write("> [!NOTE]\n")
- ri.write("> This reference documentation is automatically generated from codebase comments and AST analysis using the literal programming compiler.\n\n")
-
- ri.write("## Project Architecture Overview\n\n")
- ri.write("This suite compiles algebraic DSL budget equations, performs high-order compact finite difference calculus, and exports physical terms via MPI-IO. Below is the primary software module pipeline:\n\n")
-
- # Include a Mermaid architecture diagram
- ri.write("```mermaid\n")
- ri.write("graph TD\n")
- ri.write(" A[code_gen.py / DSL Input] -->|AST Compiler Pipeline| B[post.py / Code Gen]\n")
- ri.write(" B -->|Generates budget kernels| C[m_calculate.f90]\n")
- ri.write(" C -->|LU Tridiagonal Solvers| D[Compact.f90]\n")
- ri.write(" C -->|Array allocations| E[m_arrays.f90]\n")
- ri.write(" F[post.f90 / Main Driver] -->|Orchestrates calculations| C\n")
- ri.write(" F -->|Parallelizes domain| G[m_openmpi.f90]\n")
- ri.write(" F -->|Loads run configuration| H[m_parameters.f90]\n")
- ri.write(" I[pycompact.py / Bindings] -->|Wraps CPU calculations| C\n")
- ri.write("```\n\n")
-
- ri.write("## Reference Files Index\n\n")
- ri.write("| Document / Code Module | Language | Description | \n")
- ri.write("| --- | --- | --- |\n")
-
- for mod in all_modules:
- mname = mod['name']
- lang_label = "Fortran 90" if mod['lang'] == 'fortran' else "Python"
- doc_link = mname.replace('.f90', '.md').replace('.py', '.md')
-
- # Smart summary from first line of doc
- overview_doc = mod['data']['doc'].strip()
- if not overview_doc:
- for elem in mod['data']['elements']:
- if elem['type'] == 'module' and elem.get('doc'):
- overview_doc = elem['doc'].strip()
- break
- else:
- for elem in mod['data']['elements']:
- if elem.get('doc'):
- overview_doc = elem['doc'].strip()
- break
-
- doc_lines = overview_doc.split('\n')
- brief = doc_lines[0] if doc_lines and doc_lines[0] else "*No overview description provided.*"
- brief = brief.replace('@brief', '').replace('@author', '').strip()
- if brief.startswith('Google') or brief.startswith('Ignis'):
- for line in doc_lines:
- line_clean = line.replace('@brief', '').replace('@author', '').strip()
- if line_clean and not line.strip().startswith('@'):
- brief = line_clean
- break
-
- ri.write(f"| [{mname}]({doc_link}) | **{lang_label}** | {brief} |\n")
-
- ri.write("\n---\n")
- ri.write("*Generated dynamically by `build_docs.py`.*")
-
- print(f"\nDocumentation built successfully under {docs_dir}!")
+ # 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__":
- build_all_docs()
+ success = build_orchestrator()
+ sys.exit(0 if success else 1)
diff --git a/docs/Compact.md b/docs/Compact.md
deleted file mode 100644
index 112e3d9..0000000
--- a/docs/Compact.md
+++ /dev/null
@@ -1,261 +0,0 @@
-# Compact.f90
-
-
-
-## Overview
-
-*Author: Ignis*
-@brief High-order compact finite difference scheme solver.
-
-This module handles the generation of tridiagonal/pentadiagonal matrices,
-LU decomposition calculations, and tridiagonal solver operations for periodic
-and non-periodic boundary conditions.
-
-## API Index
-
-- [Module: `Compact`](#compact)
-- [Subroutine: `ludcmp`](#ludcmp)
-- [Subroutine: `ludcmp_allocate`](#ludcmp_allocate)
-- [Subroutine: `ludcmp_deallocate`](#ludcmp_deallocate)
-- [Subroutine: `ludcmp_testalloc`](#ludcmp_testalloc)
-- [Subroutine: `ludcmp_calculate`](#ludcmp_calculate)
-- [Subroutine: `test_nonp_lud1`](#test_nonp_lud1)
-- [Subroutine: `test_nonp_lud2`](#test_nonp_lud2)
-- [Subroutine: `test_p_lud1`](#test_p_lud1)
-- [Subroutine: `test_p_lud2`](#test_p_lud2)
-- [Subroutine: `nonp_lud`](#nonp_lud)
-- [Subroutine: `p_lud`](#p_lud)
-- [Subroutine: `stdlu`](#stdlu)
-- [Subroutine: `ptdlu`](#ptdlu)
-- [Subroutine: `rhs1np`](#rhs1np)
-- [Subroutine: `dfnonp`](#dfnonp)
-- [Subroutine: `dfp`](#dfp)
-- [Subroutine: `ptdslv`](#ptdslv)
-- [Subroutine: `d2fp`](#d2fp)
-- [Subroutine: `tdslv`](#tdslv)
-- [Subroutine: `d2fnonp`](#d2fnonp)
-
----
-
-## API Reference
-
-### [Module] `Compact`
-
-*Author: Ignis*
-@brief High-order compact finite difference scheme solver.
-
-This module handles the generation of tridiagonal/pentadiagonal matrices,
-LU decomposition calculations, and tridiagonal solver operations for periodic
-and non-periodic boundary conditions.
-
----
-
-### [Subroutine] `ludcmp`
-
-```fortran
-subroutine ludcmp(nx, ny, nz, xp, yp, zp)
-```
-
-Entry point for LU decomposition calculations.
-
-Prepares the workspace allocations and runs the decomposition calculation for all three directions.
-
-- ` nx `: Grid size in x-direction.
-- ` ny `: Grid size in y-direction.
-- ` nz `: Grid size in z-direction.
-- ` xp `: Periodic flag for x-direction (0 = periodic, other = non-periodic).
-- ` yp `: Periodic flag for y-direction (0 = periodic, other = non-periodic).
-- ` zp `: Periodic flag for z-direction (0 = periodic, other = non-periodic).
-
----
-
-### [Subroutine] `ludcmp_allocate`
-
-```fortran
-subroutine ludcmp_allocate(nx, ny, nz, xp, yp, zp)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ludcmp_deallocate`
-
-```fortran
-subroutine ludcmp_deallocate(xp, yp, zp)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ludcmp_testalloc`
-
-```fortran
-subroutine ludcmp_testalloc()
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ludcmp_calculate`
-
-```fortran
-subroutine ludcmp_calculate(nx, ny, nz, xp, yp, zp)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `test_nonp_lud1`
-
-```fortran
-subroutine test_nonp_lud1(xx, coef)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `test_nonp_lud2`
-
-```fortran
-subroutine test_nonp_lud2(xx, coef)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `test_p_lud1`
-
-```fortran
-subroutine test_p_lud1(xx, coef1, coef2)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `test_p_lud2`
-
-```fortran
-subroutine test_p_lud2(xx, coef1, coef2)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `nonp_lud`
-
-```fortran
-subroutine nonp_lud(xyz, xx)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `p_lud`
-
-```fortran
-subroutine p_lud(xyz, xx)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `stdlu`
-
-```fortran
-subroutine stdlu(a, n, l)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ptdlu`
-
-```fortran
-subroutine ptdlu(a, n, l, w)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `rhs1np`
-
-```fortran
-subroutine rhs1np(n, h, x, dx, nd)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `dfnonp`
-
-```fortran
-subroutine dfnonp(n, h, x, dx, nd, dir)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `dfp`
-
-```fortran
-subroutine dfp(n, h, x, dx, nd, dir)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ptdslv`
-
-```fortran
-subroutine ptdslv(r, n, l, w, nd)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `d2fp`
-
-```fortran
-subroutine d2fp(n, h, x, dx, nd, dir)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `tdslv`
-
-```fortran
-subroutine tdslv(r, n, l, nd)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `d2fnonp`
-
-```fortran
-subroutine d2fnonp(n, h, x, dx, nd, dir)
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/README.md b/docs/README.md
deleted file mode 100644
index 05e8fb5..0000000
--- a/docs/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# HPC DNS Post-Processing Reference Manual
-
-> [!NOTE]
-> This reference documentation is automatically generated from codebase comments and AST analysis using the literal programming compiler.
-
-## Project Architecture Overview
-
-This suite compiles algebraic DSL budget equations, performs high-order compact finite difference calculus, and exports physical terms via MPI-IO. Below is the primary software module 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
-```
-
-## Reference Files Index
-
-| Document / Code Module | Language | Description |
-| --- | --- | --- |
-| [Compact.f90](Compact.md) | **Fortran 90** | This module handles the generation of tridiagonal/pentadiagonal matrices, |
-| [m_arrays.f90](m_arrays.md) | **Fortran 90** | *No overview description provided.* |
-| [m_calculate.f90](m_calculate.md) | **Fortran 90** | This module calculates spatial derivatives (first and second derivatives in X, Y, Z directions) |
-| [m_openmpi.f90](m_openmpi.md) | **Fortran 90** | *No overview description provided.* |
-| [m_parameters.f90](m_parameters.md) | **Fortran 90** | *No overview description provided.* |
-| [post.f90](post.md) | **Fortran 90** | *No overview description provided.* |
-| [post_dns.f90](post_dns.md) | **Fortran 90** | *No overview description provided.* |
-| [code_gen.py](code_gen.md) | **Python** | Convert the value of `tok` from string to bool, while maintaining line number & column. |
-| [post.py](post.md) | **Python** | conversion from tree to python data |
-| [pycompact.py](pycompact.md) | **Python** | *No overview description provided.* |
-
----
-*Generated dynamically by `build_docs.py`.*
\ No newline at end of file
diff --git a/docs/code_gen.md b/docs/code_gen.md
deleted file mode 100644
index 6482047..0000000
--- a/docs/code_gen.md
+++ /dev/null
@@ -1,103 +0,0 @@
-# code_gen.py
-
-
-
-## Overview
-
-Convert the value of `tok` from string to bool, while maintaining line number & column.
-
-## API Index
-
-- [Function: `tok_to_bool`](#tok_to_bool)
-- [Function: `tok_to_int`](#tok_to_int)
-- [Function: `tok_to_str`](#tok_to_str)
-- [Class: `VersionInfo`](#versioninfo)
-- [Function: `test`](#test)
-- [Function: `build_info`](#build_info)
-
----
-
-## API Reference
-
-### [Function] `tok_to_bool`
-
-```python
-function tok_to_bool(tok)
-```
-
-Convert the value of `tok` from string to bool, while maintaining line number & column.
-
----
-
-### [Function] `tok_to_int`
-
-```python
-function tok_to_int(tok)
-```
-
-Convert the value of `tok` from string to int, while maintaining line number & column.
-
----
-
-### [Function] `tok_to_str`
-
-```python
-function tok_to_str(tok)
-```
-
-Convert the value of `tok` from string to string, while maintaining line number & column.
-
----
-
-### [Class] `VersionInfo(object)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, input_raw)`
-
-*No description provided.*
-
-##### `fparams(self)`
-
-*No description provided.*
-
----
-
-### [Function] `test`
-
-```python
-function test(terms_raw, report, latex)
-```
-
-Compiles the post-processing term specifications from DSL into targets.
-
-This compiles the Lark AST through all 4 pipeline stages (Stage 1 to 4)
-and outputs the resulting Fortran source code via Jinja2, a LaTeX equation
-dictionary, or a code generation IR report.
-
-
-**Arguments:**
-
-- ` terms_raw ` *(str)*: The raw string contents of the DSL terms specification input file.
-- ` report ` *(bool)*: If True, generates and saves the intermediate code generation report.
-- ` latex ` *(bool)*: If True, prints LaTeX equations of the averaged terms to stdout.
-
----
-
-### [Function] `build_info`
-
-```python
-function build_info(terms_raw)
-```
-
-Generates and prints build information for the current code generation run.
-
-
-**Arguments:**
-
-- ` terms_raw ` *(str)*: The raw string contents of the DSL terms specification input file.
-
----
-
diff --git a/docs/fortran.md b/docs/fortran.md
new file mode 100644
index 0000000..3b28f2c
--- /dev/null
+++ b/docs/fortran.md
@@ -0,0 +1,20 @@
+# 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.
diff --git a/docs/index.md b/docs/index.md
new file mode 100644
index 0000000..25dd59a
--- /dev/null
+++ b/docs/index.md
@@ -0,0 +1,30 @@
+# 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.*
diff --git a/docs/m_arrays.md b/docs/m_arrays.md
deleted file mode 100644
index 59856cd..0000000
--- a/docs/m_arrays.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# m_arrays.f90
-
-
-
-## Overview
-
-*No description provided.*
-
-## API Index
-
-- [Module: `m_arrays`](#m_arrays)
-- [Subroutine: `m_arrays_init`](#m_arrays_init)
-- [Subroutine: `m_arrays_finalize`](#m_arrays_finalize)
-- [Subroutine: `m_arrays_calculate_instant`](#m_arrays_calculate_instant)
-
----
-
-## API Reference
-
-### [Module] `m_arrays`
-
-*No description provided.*
-
----
-
-### [Subroutine] `m_arrays_init`
-
-```fortran
-subroutine m_arrays_init()
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `m_arrays_finalize`
-
-```fortran
-subroutine m_arrays_finalize()
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `m_arrays_calculate_instant`
-
-```fortran
-subroutine m_arrays_calculate_instant()
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/m_calculate.md b/docs/m_calculate.md
deleted file mode 100644
index 06c772d..0000000
--- a/docs/m_calculate.md
+++ /dev/null
@@ -1,229 +0,0 @@
-# m_calculate.f90
-
-
-
-## Overview
-
-*Author: Google DeepMind Team & Ignis*
-@brief DNS post-processing mathematical operations and derivatives.
-
-This module calculates spatial derivatives (first and second derivatives in X, Y, Z directions)
-using high-order compact finite difference schemes. It also calculates chemical reaction rates,
-positive/negative component extraction, and threshold operations.
-
-## API Index
-
-- [Module: `m_calculate`](#m_calculate)
-- [Subroutine: `m_calculate_init`](#m_calculate_init)
-- [Subroutine: `m_calculate_finalize`](#m_calculate_finalize)
-- [Subroutine: `ddx1d`](#ddx1d)
-- [Subroutine: `ddx`](#ddx)
-- [Subroutine: `ddy`](#ddy)
-- [Subroutine: `ddz`](#ddz)
-- [Subroutine: `d2dx1d`](#d2dx1d)
-- [Subroutine: `d2dx`](#d2dx)
-- [Subroutine: `d2dy`](#d2dy)
-- [Subroutine: `d2dz`](#d2dz)
-- [Subroutine: `tp`](#tp)
-- [Subroutine: `tp2`](#tp2)
-- [Function: `rxn_rate`](#rxn_rate)
-- [Function: `threshold_min_max`](#threshold_min_max)
-- [Function: `positive`](#positive)
-- [Function: `negative`](#negative)
-
----
-
-## API Reference
-
-### [Module] `m_calculate`
-
-*Author: Google DeepMind Team & Ignis*
-@brief DNS post-processing mathematical operations and derivatives.
-
-This module calculates spatial derivatives (first and second derivatives in X, Y, Z directions)
-using high-order compact finite difference schemes. It also calculates chemical reaction rates,
-positive/negative component extraction, and threshold operations.
-
----
-
-### [Subroutine] `m_calculate_init`
-
-```fortran
-subroutine m_calculate_init()
-```
-
-Initializes the workspace arrays and matrices.
-
-Pre-allocates transposed workspace buffers (`xsrc`, `xdst`, `rsrc`, `rdst`)
-and performs the LU decomposition setup via `ludcmp` for the tridiagonal compact schemes.
-
----
-
-### [Subroutine] `m_calculate_finalize`
-
-```fortran
-subroutine m_calculate_finalize()
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ddx1d`
-
-```fortran
-subroutine ddx1d(dst, src)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `ddx`
-
-```fortran
-subroutine ddx(dst, src)
-```
-
-Computes the first-order derivative in the X-direction.
-
-- ` src `: 3D input scalar field (nxp, nyp, nzp).
-- ` dst `: 3D output derivative field (nxp, nyp, nzp).
-
----
-
-### [Subroutine] `ddy`
-
-```fortran
-subroutine ddy(dst, src)
-```
-
-Computes the first-order derivative in the Y-direction.
-
-- ` src `: 3D input scalar field (nxp, nyp, nzp).
-- ` dst `: 3D output derivative field (nxp, nyp, nzp).
-
----
-
-### [Subroutine] `ddz`
-
-```fortran
-subroutine ddz(dst, src)
-```
-
-Computes the first-order derivative in the Z-direction.
-
-- ` src `: 3D input scalar field (nxp, nyp, nzp).
-- ` dst `: 3D output derivative field (nxp, nyp, nzp).
-
----
-
-### [Subroutine] `d2dx1d`
-
-```fortran
-subroutine d2dx1d(dst, src)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `d2dx`
-
-```fortran
-subroutine d2dx(dst, src)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `d2dy`
-
-```fortran
-subroutine d2dy(dst, src)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `d2dz`
-
-```fortran
-subroutine d2dz(dst, src)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `tp`
-
-```fortran
-subroutine tp(a, b, nx)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `tp2`
-
-```fortran
-subroutine tp2(a, b, n1, n2)
-```
-
-*No description provided.*
-
----
-
-### [Function] `rxn_rate`
-
-```fortran
-function rxn_rate(c)
-```
-
-Computes the chemical reaction rate based on the progress variable c.
-
-This uses a piecewise exponential/Arrhenius model depending on whether the progress variable
-is below c_cut, above c_ref, or intermediate.
-
-- ` c `: The progress variable (0.0 to 1.0).
-
-**Returns:**
-
-The computed reaction rate.
-
----
-
-### [Function] `threshold_min_max`
-
-```fortran
-function threshold_min_max(c, minc, maxc)
-```
-
-*No description provided.*
-
----
-
-### [Function] `positive`
-
-```fortran
-function positive(c)
-```
-
-*No description provided.*
-
----
-
-### [Function] `negative`
-
-```fortran
-function negative(c)
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/m_openmpi.md b/docs/m_openmpi.md
deleted file mode 100644
index 727e20e..0000000
--- a/docs/m_openmpi.md
+++ /dev/null
@@ -1,55 +0,0 @@
-# m_openmpi.f90
-
-
-
-## Overview
-
-*No description provided.*
-
-## API Index
-
-- [Module: `m_openmpi`](#m_openmpi)
-- [Subroutine: `m_openmpi_init`](#m_openmpi_init)
-- [Subroutine: `m_openmpi_exit`](#m_openmpi_exit)
-- [Subroutine: `openmpi_get_command_line`](#openmpi_get_command_line)
-
----
-
-## API Reference
-
-### [Module] `m_openmpi`
-
-*No description provided.*
-
----
-
-### [Subroutine] `m_openmpi_init`
-
-```fortran
-subroutine m_openmpi_init()
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `m_openmpi_exit`
-
-```fortran
-subroutine m_openmpi_exit()
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `openmpi_get_command_line`
-
-```fortran
-subroutine openmpi_get_command_line()
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/m_parameters.md b/docs/m_parameters.md
deleted file mode 100644
index df34307..0000000
--- a/docs/m_parameters.md
+++ /dev/null
@@ -1,44 +0,0 @@
-# m_parameters.f90
-
-
-
-## Overview
-
-*No description provided.*
-
-## API Index
-
-- [Module: `m_parameters`](#m_parameters)
-- [Function: `to_omit`](#to_omit)
-- [Subroutine: `read_intro`](#read_intro)
-
----
-
-## API Reference
-
-### [Module] `m_parameters`
-
-*No description provided.*
-
----
-
-### [Function] `to_omit`
-
-```fortran
-function to_omit(num)
-```
-
-*No description provided.*
-
----
-
-### [Subroutine] `read_intro`
-
-```fortran
-subroutine read_intro()
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/post.md b/docs/post.md
deleted file mode 100644
index 633eabe..0000000
--- a/docs/post.md
+++ /dev/null
@@ -1,694 +0,0 @@
-# post.py
-
-
-
-## Overview
-
-conversion from tree to python data
-
-## API Index
-
-- [Class: `LarkToSympy`](#larktosympy)
-- [Class: `ArrayFCodePrinter`](#arrayfcodeprinter)
-- [Class: `SympyOptimizer`](#sympyoptimizer)
-- [Class: `CollectDefinitions`](#collectdefinitions)
-- [Class: `ExpInspector`](#expinspector)
-- [Class: `ExpToLatex`](#exptolatex)
-- [Class: `ExpToCode`](#exptocode)
-- [Function: `make_allocate`](#make_allocate)
-- [Class: `FieldBase`](#fieldbase)
-- [Class: `FieldExporter`](#fieldexporter)
-- [Class: `Field`](#field)
-- [Class: `FluctuationField`](#fluctuationfield)
-- [Class: `PrimaryField`](#primaryfield)
-- [Class: `DerivedField`](#derivedfield)
-- [Class: `AveragedField`](#averagedfield)
-- [Class: `Stage1`](#stage1)
-- [Class: `Stage2`](#stage2)
-- [Class: `Stage3`](#stage3)
-- [Class: `Stage4`](#stage4)
-- [Class: `Stage5`](#stage5)
-- [Class: `Stage6`](#stage6)
-
----
-
-## API Reference
-
-### [Class] `LarkToSympy(Transformer)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, fdict)`
-
-*No description provided.*
-
-##### `number(self, numeral)`
-
-*No description provided.*
-
-##### `env(self, name)`
-
-*No description provided.*
-
-##### `paren(self, val)`
-
-*No description provided.*
-
-##### `var(self, name)`
-
-*No description provided.*
-
-##### `fluc(self, name)`
-
-*No description provided.*
-
-##### `dnx(self, partial, b)`
-
-*No description provided.*
-
-##### `icall(self, op, val)`
-
-*No description provided.*
-
-##### `fcall(self)`
-
-*No description provided.*
-
-##### `neg(self, val)`
-
-*No description provided.*
-
-##### `add(self, a, b)`
-
-*No description provided.*
-
-##### `sub(self, a, b)`
-
-*No description provided.*
-
-##### `mul(self, a, b)`
-
-*No description provided.*
-
-##### `div(self, a, b)`
-
-*No description provided.*
-
-##### `udf(self, a)`
-
-*No description provided.*
-
----
-
-### [Class] `ArrayFCodePrinter(FCodePrinter)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, settings, array_symbols, avg_symbols)`
-
-*No description provided.*
-
-##### `_print_Float(self, expr)`
-
-*No description provided.*
-
-##### `_print_Symbol(self, expr)`
-
-*No description provided.*
-
-##### `_print_Function(self, expr)`
-
-*No description provided.*
-
----
-
-### [Class] `SympyOptimizer`
-
-*No description provided.*
-
-#### Methods
-
-##### `get_instance(cls, fdict)`
-
-**Decorators:** `@classmethod`
-
-*No description provided.*
-
-##### `__init__(self, fdict)`
-
-*No description provided.*
-
-##### `set_averaged(self, averaged_dict)`
-
-*No description provided.*
-
-##### `get_sympy_expr(self, name)`
-
-*No description provided.*
-
-##### `calculate_flops_and_heavy(self, expr)`
-
-*No description provided.*
-
-##### `count_3d_loads(self, expr, three_d_arrays)`
-
-*No description provided.*
-
-##### `optimize_field(self, name, alloc)`
-
-*No description provided.*
-
----
-
-### [Class] `CollectDefinitions(Visitor)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, primary, derived, averaged)`
-
-*No description provided.*
-
-##### `varlist(self, tree)`
-
-*No description provided.*
-
-##### `assign_var(self, tree)`
-
-*No description provided.*
-
-##### `assign_avg_var(self, tree)`
-
-*No description provided.*
-
----
-
-### [Class] `ExpInspector(Visitor)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self)`
-
-*No description provided.*
-
-##### `inspect(cls, tree)`
-
-**Decorators:** `@classmethod`
-
-*No description provided.*
-
-##### `__call__(self, tree)`
-
-*No description provided.*
-
-##### `fluc(self, tree)`
-
-*No description provided.*
-
-##### `var(self, tree)`
-
-*No description provided.*
-
-##### `dnx(self, tree)`
-
-*No description provided.*
-
----
-
-### [Class] `ExpToLatex(Transformer)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, fdict)`
-
-*No description provided.*
-
-##### `arithmatic_rooted(self, name)`
-
-*No description provided.*
-
-##### `parenthise(self, name)`
-
-*No description provided.*
-
-##### `number(self, numeral)`
-
-*No description provided.*
-
-##### `env(self, name)`
-
-*No description provided.*
-
-##### `paren(self, name)`
-
-*No description provided.*
-
-##### `var(self, name)`
-
-*No description provided.*
-
-##### `fluc(self, name)`
-
-*No description provided.*
-
-##### `dnx(self, partial, b)`
-
-*No description provided.*
-
-##### `icall(self, a, b)`
-
-*No description provided.*
-
-##### `fcall(self)`
-
-*No description provided.*
-
-##### `neg(self, b)`
-
-*No description provided.*
-
-##### `add(self, a, b)`
-
-*No description provided.*
-
-##### `sub(self, a, b)`
-
-*No description provided.*
-
-##### `mul(self, a, b)`
-
-*No description provided.*
-
-##### `div(self, a, b)`
-
-*No description provided.*
-
----
-
-### [Class] `ExpToCode(Transformer)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, fdict)`
-
-*No description provided.*
-
-##### `number(self, numeral)`
-
-*No description provided.*
-
-##### `env(self, name)`
-
-*No description provided.*
-
-##### `paren(self, name)`
-
-*No description provided.*
-
-##### `var(self, name)`
-
-*No description provided.*
-
-##### `fluc(self, name)`
-
-*No description provided.*
-
-##### `dnx(self, partial, b)`
-
-*No description provided.*
-
-##### `icall(self, a, b)`
-
-*No description provided.*
-
-##### `fcall(self)`
-
-*No description provided.*
-
-##### `neg(self, b)`
-
-*No description provided.*
-
-##### `add(self, a, b)`
-
-*No description provided.*
-
-##### `sub(self, a, b)`
-
-*No description provided.*
-
-##### `mul(self, a, b)`
-
-*No description provided.*
-
-##### `div(self, a, b)`
-
-*No description provided.*
-
----
-
-### [Function] `make_allocate`
-
-```python
-function make_allocate(name, shape, init_zero)
-```
-
-*No description provided.*
-
----
-
-### [Class] `FieldBase(object)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, name, fdict)`
-
-*No description provided.*
-
-##### `depends_on(self, a)`
-
-*No description provided.*
-
-##### `is_primary(self)`
-
-*No description provided.*
-
-##### `not_primary(self)`
-
-*No description provided.*
-
-##### `is_fluctuation(self)`
-
-*No description provided.*
-
-##### `export_on(self)`
-
-*No description provided.*
-
-##### `__repr__(self)`
-
-*No description provided.*
-
-##### `checkFluctuation(self)`
-
-*No description provided.*
-
-##### `depClosure(self)`
-
-*No description provided.*
-
-##### `code_decl(self)`
-
-*No description provided.*
-
-##### `code_alloc(self)`
-
-*No description provided.*
-
-##### `code_free(self)`
-
-*No description provided.*
-
----
-
-### [Class] `FieldExporter(object)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, name, attr, parent)`
-
-*No description provided.*
-
-##### `code(self)`
-
-*No description provided.*
-
-##### `code_decl(self)`
-
-*No description provided.*
-
-##### `code_alloc(self)`
-
-*No description provided.*
-
-##### `code_free(self)`
-
-*No description provided.*
-
----
-
-### [Class] `Field(FieldBase)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, name, attr, exp, fdict)`
-
-*No description provided.*
-
-##### `export_on(self)`
-
-*No description provided.*
-
-##### `code(self, alloc)`
-
-*No description provided.*
-
----
-
-### [Class] `FluctuationField(FieldBase)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, w, field, fset, fdict)`
-
-*No description provided.*
-
-##### `code(self, alloc)`
-
-*No description provided.*
-
-##### `id(cls, w, field)`
-
-**Decorators:** `@classmethod`
-
-*No description provided.*
-
----
-
-### [Class] `PrimaryField(FieldBase)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, name, fdict)`
-
-*No description provided.*
-
-##### `code(self, alloc)`
-
-*No description provided.*
-
-##### `code_decl(self)`
-
-*No description provided.*
-
-##### `code_alloc(self)`
-
-*No description provided.*
-
-##### `code_free(self)`
-
-*No description provided.*
-
----
-
-### [Class] `DerivedField(FieldBase)`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, op, v, fdict)`
-
-*No description provided.*
-
-##### `code(self, alloc)`
-
-*No description provided.*
-
----
-
-### [Class] `AveragedField(FieldBase)`
-
-*No description provided.*
-
-#### Methods
-
-##### `id(cls, w, tgt)`
-
-**Decorators:** `@classmethod`
-
-*No description provided.*
-
-##### `__init__(self, w, tgt, fdict)`
-
-*No description provided.*
-
-##### `code(self, alloc)`
-
-*No description provided.*
-
-##### `code_avg(self)`
-
-*No description provided.*
-
-##### `isWeighted(self)`
-
-*No description provided.*
-
-##### `pass1(self)`
-
-*No description provided.*
-
-##### `pass2(self)`
-
-*No description provided.*
-
----
-
-### [Class] `Stage1`
-
-conversion from tree to python data
-
-#### Methods
-
-##### `__init__(self, raw_tree)`
-
-*No description provided.*
-
-##### `__repr__(self)`
-
-*No description provided.*
-
----
-
-### [Class] `Stage2`
-
-expand derivatives and averages
-
-#### Methods
-
-##### `__init__(self, src)`
-
-*No description provided.*
-
-##### `__repr__(self)`
-
-*No description provided.*
-
-##### `dependency(self)`
-
-*No description provided.*
-
----
-
-### [Class] `Stage3`
-
-calculate execution order
-
-#### Methods
-
-##### `__init__(self, src)`
-
-*No description provided.*
-
-##### `__repr__(self)`
-
-*No description provided.*
-
-##### `sort_vars(self, dependency, group)`
-
-*No description provided.*
-
-##### `calc_size(self, ordered, remaining)`
-
-*No description provided.*
-
-##### `sort_vars_new(self, dependency, group)`
-
-*No description provided.*
-
-##### `print_program(self)`
-
-*No description provided.*
-
----
-
-### [Class] `Stage4`
-
-analyze liveness and allocate array
-
-#### Methods
-
-##### `__init__(self, src)`
-
-*No description provided.*
-
-##### `liveness(self, l1, g)`
-
-*No description provided.*
-
-##### `allocate_arr(self, l)`
-
-*No description provided.*
-
-##### `work_array_codes(self)`
-
-*No description provided.*
-
-##### `write_avg_codes(self, avglist)`
-
-*No description provided.*
-
-##### `print_program(self)`
-
-*No description provided.*
-
-##### `save_ir(self)`
-
-*No description provided.*
-
----
-
-### [Class] `Stage5`
-
-pass1 and pass2 seperation and calculation ordering
-
----
-
-### [Class] `Stage6`
-
-generate fortran code
-
----
-
diff --git a/docs/post_dns.md b/docs/post_dns.md
deleted file mode 100644
index 0752c8d..0000000
--- a/docs/post_dns.md
+++ /dev/null
@@ -1,37 +0,0 @@
-# post_dns.f90
-
-
-
-## Overview
-
-*No description provided.*
-
-## API Index
-
-- [Function: `build_info_length`](#build_info_length)
-- [Function: `latex_length`](#latex_length)
-
----
-
-## API Reference
-
-### [Function] `build_info_length`
-
-```fortran
-function build_info_length()
-```
-
-*No description provided.*
-
----
-
-### [Function] `latex_length`
-
-```fortran
-function latex_length()
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/pycompact.md b/docs/pycompact.md
deleted file mode 100644
index 7495662..0000000
--- a/docs/pycompact.md
+++ /dev/null
@@ -1,116 +0,0 @@
-# pycompact.py
-
-
-
-## Overview
-
-*No description provided.*
-
-## API Index
-
-- [Class: `CompactScheme`](#compactscheme)
-- [Function: `read_old_data`](#read_old_data)
-- [Function: `read_data`](#read_data)
-- [Function: `validate_trigonometric`](#validate_trigonometric)
-- [Function: `test_dns_data`](#test_dns_data)
-
----
-
-## API Reference
-
-### [Class] `CompactScheme`
-
-*No description provided.*
-
-#### Methods
-
-##### `__init__(self, nx, ny, nz, px, py, pz, lx, ly, lz)`
-
-*No description provided.*
-
-##### `test_ludcmp(self)`
-
-*No description provided.*
-
-##### `py_rhs_1_np(self, x)`
-
-*No description provided.*
-
-##### `py_tdslv(self, r, l)`
-
-*No description provided.*
-
-##### `test_dfnonp(self)`
-
-*No description provided.*
-
-##### `verify_nonp_lud1(self)`
-
-*No description provided.*
-
-##### `verify_nonp_lud2(self)`
-
-*No description provided.*
-
-##### `py_stdlu(self, aa)`
-
-*No description provided.*
-
-##### `ddx(self, src)`
-
-*No description provided.*
-
-##### `ddy(self, src)`
-
-*No description provided.*
-
-##### `ddz(self, src)`
-
-*No description provided.*
-
-##### `port_nonp_coef(self)`
-
-*No description provided.*
-
----
-
-### [Function] `read_old_data`
-
-```python
-function read_old_data(fname)
-```
-
-*No description provided.*
-
----
-
-### [Function] `read_data`
-
-```python
-function read_data(fname)
-```
-
-*No description provided.*
-
----
-
-### [Function] `validate_trigonometric`
-
-```python
-function validate_trigonometric()
-```
-
-*No description provided.*
-
----
-
-### [Function] `test_dns_data`
-
-```python
-function test_dns_data()
-```
-
-*No description provided.*
-
----
-
diff --git a/docs/python/code_gen.md b/docs/python/code_gen.md
new file mode 100644
index 0000000..30a5674
--- /dev/null
+++ b/docs/python/code_gen.md
@@ -0,0 +1,3 @@
+# Code Generator (`code_gen.py`)
+
+::: code_gen
diff --git a/docs/python/post.md b/docs/python/post.md
new file mode 100644
index 0000000..1f2740a
--- /dev/null
+++ b/docs/python/post.md
@@ -0,0 +1,3 @@
+# Compiler Stages (`post.py`)
+
+::: post
diff --git a/docs/python/pycompact.md b/docs/python/pycompact.md
new file mode 100644
index 0000000..e7a154d
--- /dev/null
+++ b/docs/python/pycompact.md
@@ -0,0 +1,3 @@
+# Python Bindings (`pycompact.py`)
+
+::: pycompact
diff --git a/ford.md b/ford.md
new file mode 100644
index 0000000..f4ee1fa
--- /dev/null
+++ b/ford.md
@@ -0,0 +1,22 @@
+---
+project: HPC DNS Post-Processing Fortran Core
+summary: Tridiagonal compact finite difference solver, mathematical operators, and MPI-IO drivers.
+author: Google DeepMind Team & Ignis
+version: 1.0.0
+src_dir: ./code
+output_dir: ./docs/fortran_api
+exclude: **/pycompact/**
+preprocess: true
+display: public
+---
+
+# Fortran Core Documentation
+
+Welcome to the Fortran Core Reference. This section contains automatically generated docs from `FORD` for the high-order compact difference solver modules:
+
+- **[[Compact]]**: Compact finite difference scheme equations.
+- **[[m_calculate]]**: spatial derivatives and chemical kinetics.
+- **[[m_arrays]]**: post-processing field allocation.
+- **[[m_openmpi]]**: MPI parallel domain wrapper.
+- **[[m_parameters]]**: input loaders and physical values.
+- **[[post]]**: main driver pipeline.
diff --git a/mkdocs.yml b/mkdocs.yml
new file mode 100644
index 0000000..2cd00ae
--- /dev/null
+++ b/mkdocs.yml
@@ -0,0 +1,45 @@
+site_name: HPC DNS Post-Processing Reference Manual
+theme:
+ name: material
+ palette:
+ - media: "(prefers-color-scheme: dark)"
+ scheme: slate
+ primary: teal
+ accent: cyan
+ toggle:
+ icon: material/brightness-4
+ name: Switch to light mode
+ - media: "(prefers-color-scheme: light)"
+ scheme: default
+ primary: teal
+ accent: cyan
+ toggle:
+ icon: material/brightness-7
+ name: Switch to dark mode
+ features:
+ - navigation.tabs
+ - navigation.sections
+ - navigation.expand
+ - content.code.copy
+
+plugins:
+ - search
+ - mkdocstrings:
+ default_handler: python
+ handlers:
+ python:
+ paths: [code, code/code_gen, code/pycompact]
+ options:
+ docstring_style: google
+ show_source: true
+ show_root_heading: true
+ show_bases: true
+
+nav:
+ - Home: index.md
+ - Python API Reference:
+ - Code Generator: python/code_gen.md
+ - Compiler Stages: python/post.md
+ - Python Bindings: python/pycompact.md
+ - Fortran Core Reference:
+ - Modules & Procedures: fortran.md
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..1fde9fd
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+mkdocs==1.6.1
+mkdocs-material==9.7.6
+mkdocstrings[python]==0.25.2
+ford==7.0.13
+mkdocs-autorefs==1.3.1