diff --git a/build_docs.py b/build_docs.py
new file mode 100644
index 0000000..d319132
--- /dev/null
+++ b/build_docs.py
@@ -0,0 +1,475 @@
+#!/usr/bin/env python3
+import os
+import re
+import ast
+import shutil
+
+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 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))
+
+ # 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():
+ 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")
+
+ # Recreate the docs directory
+ if os.path.exists(docs_dir):
+ shutil.rmtree(docs_dir)
+ os.makedirs(docs_dir, exist_ok=True)
+
+ fortran_parser = FortranParser()
+ py_parser = PythonASTParser()
+
+ # Files to parse
+ fortran_files = [
+ "Compact.f90",
+ "m_arrays.f90",
+ "m_calculate.f90",
+ "m_openmpi.f90",
+ "m_parameters.f90",
+ "post.f90",
+ "post_dns.f90"
+ ]
+
+ python_files = [
+ ("code_gen.py", "code/code_gen/code_gen.py"),
+ ("post.py", "code/code_gen/post.py"),
+ ("pycompact.py", "code/pycompact/pycompact.py")
+ ]
+
+ all_modules = []
+
+ # 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
+ })
+
+ # 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
+ })
+
+ # 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}!")
+
+
+if __name__ == "__main__":
+ build_all_docs()
diff --git a/code/Compact.f90 b/code/Compact.f90
index 3eec03d..b62f844 100644
--- a/code/Compact.f90
+++ b/code/Compact.f90
@@ -1,3 +1,9 @@
+ !> @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.
MODULE Compact
use, intrinsic :: iso_fortran_env, only: real64
IMPLICIT NONE
@@ -12,6 +18,16 @@
CONTAINS
+ !> Entry point for LU decomposition calculations.
+ !!
+ !! Prepares the workspace allocations and runs the decomposition calculation for all three directions.
+ !!
+ !! @param nx Grid size in x-direction.
+ !! @param ny Grid size in y-direction.
+ !! @param nz Grid size in z-direction.
+ !! @param xp Periodic flag for x-direction (0 = periodic, other = non-periodic).
+ !! @param yp Periodic flag for y-direction (0 = periodic, other = non-periodic).
+ !! @param zp Periodic flag for z-direction (0 = periodic, other = non-periodic).
SUBROUTINE ludcmp(nx,ny,nz,xp,yp,zp)
INTEGER, INTENT(IN) :: nx,ny,nz
INTEGER, INTENT(IN) :: xp,yp,zp
diff --git a/code/code_gen/code_gen.py b/code/code_gen/code_gen.py
index 680741a..d46f0dd 100644
--- a/code/code_gen/code_gen.py
+++ b/code/code_gen/code_gen.py
@@ -136,6 +136,17 @@ class VersionInfo(object):
def test(terms_raw, report=False, latex=False):
+ """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.
+
+ Args:
+ 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.
+ """
parser = Lark(calc_grammar,
parser='lalr',
@@ -176,6 +187,11 @@ def test(terms_raw, report=False, latex=False):
def build_info(terms_raw):
+ """Generates and prints build information for the current code generation run.
+
+ Args:
+ terms_raw (str): The raw string contents of the DSL terms specification input file.
+ """
vinfo = VersionInfo(terms_raw)
diff --git a/code/m_calculate.f90 b/code/m_calculate.f90
index 791959e..ebae9e7 100644
--- a/code/m_calculate.f90
+++ b/code/m_calculate.f90
@@ -1,3 +1,9 @@
+!> @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.
module m_calculate
use, intrinsic :: iso_fortran_env, only: real64
@@ -19,6 +25,10 @@ module m_calculate
contains
+ !> 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_init
integer :: ierr
@@ -76,7 +86,11 @@ contains
end subroutine ddx1d
- subroutine ddx(dst, src)
+ !> Computes the first-order derivative in the X-direction.
+ !!
+ !! @param src 3D input scalar field (nxp, nyp, nzp).
+ !! @param dst 3D output derivative field (nxp, nyp, nzp).
+ subroutine ddx(dst, src)
real*8, dimension(nxp,nyp,nzp), intent(in) :: src
real*8, dimension(nxp,nyp,nzp), intent(out) :: dst
@@ -102,7 +116,11 @@ contains
end subroutine ddx
- subroutine ddy(dst, src)
+ !> Computes the first-order derivative in the Y-direction.
+ !!
+ !! @param src 3D input scalar field (nxp, nyp, nzp).
+ !! @param dst 3D output derivative field (nxp, nyp, nzp).
+ subroutine ddy(dst, src)
real*8, dimension(nxp,nyp,nzp), intent(in) :: src
real*8, dimension(nxp,nyp,nzp), intent(out) :: dst
@@ -119,7 +137,11 @@ contains
end subroutine ddy
- subroutine ddz(dst, src)
+ !> Computes the first-order derivative in the Z-direction.
+ !!
+ !! @param src 3D input scalar field (nxp, nyp, nzp).
+ !! @param dst 3D output derivative field (nxp, nyp, nzp).
+ subroutine ddz(dst, src)
real*8, dimension(nxp,nyp,nzp), intent(in) :: src
real*8, dimension(nxp,nyp,nzp), intent(out) :: dst
@@ -259,6 +281,13 @@ contains
end subroutine tp2
+ !> 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.
+ !!
+ !! @param c The progress variable (0.0 to 1.0).
+ !! @return The computed reaction rate.
real(real64) function rxn_rate (c)
real(real64) :: c
diff --git a/docs/Compact.md b/docs/Compact.md
new file mode 100644
index 0000000..112e3d9
--- /dev/null
+++ b/docs/Compact.md
@@ -0,0 +1,261 @@
+# 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
new file mode 100644
index 0000000..05e8fb5
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,38 @@
+# 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
new file mode 100644
index 0000000..6482047
--- /dev/null
+++ b/docs/code_gen.md
@@ -0,0 +1,103 @@
+# 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/m_arrays.md b/docs/m_arrays.md
new file mode 100644
index 0000000..59856cd
--- /dev/null
+++ b/docs/m_arrays.md
@@ -0,0 +1,55 @@
+# 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
new file mode 100644
index 0000000..06c772d
--- /dev/null
+++ b/docs/m_calculate.md
@@ -0,0 +1,229 @@
+# 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
new file mode 100644
index 0000000..727e20e
--- /dev/null
+++ b/docs/m_openmpi.md
@@ -0,0 +1,55 @@
+# 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
new file mode 100644
index 0000000..df34307
--- /dev/null
+++ b/docs/m_parameters.md
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 0000000..633eabe
--- /dev/null
+++ b/docs/post.md
@@ -0,0 +1,694 @@
+# 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
new file mode 100644
index 0000000..0752c8d
--- /dev/null
+++ b/docs/post_dns.md
@@ -0,0 +1,37 @@
+# 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
new file mode 100644
index 0000000..7495662
--- /dev/null
+++ b/docs/pycompact.md
@@ -0,0 +1,116 @@
+# 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.*
+
+---
+