diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 91a44e0eaf..35da5ba3c5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -21,7 +21,7 @@ jobs: - name: Build Doxygen run: | sudo apt update -y - sudo apt install -y cmake ninja-build graphviz graphviz + sudo apt install -y cmake ninja-build graphviz texlive-binaries git clone https://github.com/doxygen/doxygen.git ../doxygen cd ../doxygen git checkout Release_1_16_1 diff --git a/docs/Doxyfile.in b/docs/Doxyfile.in index 5a32db918d..4fe3c2c6e5 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.in @@ -35,7 +35,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = "@DOXYGEN_PROJECT_NAME@" +PROJECT_NAME = @DOXYGEN_PROJECT_NAME@ # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -970,7 +970,7 @@ FILTER_SOURCE_PATTERNS = # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = readme.md +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -1205,14 +1205,6 @@ HTML_COLORSTYLE_SAT = 255 HTML_COLORSTYLE_GAMMA = 113 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # documentation will contain a main index with vertical navigation menus that @@ -1801,13 +1793,6 @@ LATEX_HIDE_INDICES = NO LATEX_BIB_STYLE = plain -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_TIMESTAMP = NO # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # path from which the emoji images will be read. If a relative path is entered, diff --git a/docs/documentation/case.md b/docs/documentation/case.md index d0c6431839..d7b5b800a0 100644 --- a/docs/documentation/case.md +++ b/docs/documentation/case.md @@ -82,23 +82,23 @@ Before diving into parameter details, check the **@ref case_constraints "Feature - Full reference: **@ref parameters "Case Parameters"** - Complete parameter documentation There are multiple sets of parameters that must be specified in the python input file: -1. [Runtime Parameters](#1-runtime) -2. [Computational Domain Parameters](#2-computational-domain) -3. [Patch Parameters](#3-patches) -4. [Immersed Boundary Patches](#4-immersed-boundary-patches) -5. [Fluid Material's Parameters](#5-fluid-materials) -6. [Simulation Algorithm Parameters](#6-simulation-algorithm) -7. [Formatted Database and Structure Parameters](#7-formatted-output) -8. [(Optional) Acoustic Source Parameters](#8-acoustic-source) -9. [(Optional) Ensemble-Averaged Bubble Model Parameters](#9-ensemble-averaged-bubble-model) -10. [(Optional) Velocity Field Setup Parameters](#10-velocity-field-setup) -11. [(Optional) Phase Change Parameters](#11-Phase-Change-Model) -12. [(Optional) Artificial Mach Number Parameters](#12-artificial-Mach-number) +1. [Runtime Parameters](#sec-runtime) +2. [Computational Domain Parameters](#sec-computational-domain) +3. [Patch Parameters](#sec-patches) +4. [Immersed Boundary Patches](#sec-immersed-boundary-patches) +5. [Fluid Material's Parameters](#sec-fluid-materials) +6. [Simulation Algorithm Parameters](#sec-simulation-algorithm) +7. [Formatted Database and Structure Parameters](#sec-formatted-output) +8. [(Optional) Acoustic Source Parameters](#sec-acoustic-source) +9. [(Optional) Ensemble-Averaged Bubble Model Parameters](#sec-bubble-models) +10. [(Optional) Velocity Field Setup Parameters](#sec-velocity-field-setup) +11. [(Optional) Phase Change Parameters](#sec-phase-change) +12. [(Optional) Artificial Mach Number Parameters](#sec-artificial-mach-number) Items 8, 9, 10, 11 and 12 are optional sets of parameters that activate the acoustic source model, ensemble-averaged bubble model, initial velocity field setup, phase change, artificial Mach number respectively. Definition of the parameters is described in the following subsections. -### 1. Runtime +### 1. Runtime {#sec-runtime} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -110,7 +110,7 @@ Definition of the parameters is described in the following subsections. The underlying MPI implementation and communication infrastructure must support this feature, detecting GPU pointers and performing RDMA accordingly. -### 2. Computational Domain +### 2. Computational Domain {#sec-computational-domain} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -129,7 +129,7 @@ The parameters define the boundaries of the spatial and temporal domains, and th - `[x,y,z]_domain%[beg,end]` define the spatial domain in $x$, $y$, and $z$ Cartesian coordinates: -$$ x \in \left[ x \\_ domain \\% beg, x \\_ domain \\% end \right], y \in \left[ y \\_ domain \\% beg, y \\_ domain \\% end \right], z \in \left[ z \\_ domain \\% beg, z \\_ domain \\% end \right] $$ +\f[ x \in \left[ x\_domain\%beg, \; x\_domain\%end \right], \quad y \in \left[ y\_domain\%beg, \; y\_domain\%end \right], \quad z \in \left[ z\_domain\%beg, \; z\_domain\%end \right] \f] - $m$, $n$, and $p$ define the number of finite volume cells that uniformly discretize the domain along the $x$, $y$, and $z$ axes, respectively. Note that the actual number of cells in each coordinate axis is given as $[m,n,p]+1$. @@ -141,7 +141,7 @@ The grid is gradually stretched such that the domain boundaries are pushed away - `a_[x,y,z]`, `[x,y,z]_a`, and `[x,y,z]_b` are parameters that define the grid stretching function. When grid stretching along the $x$ axis is considered, the stretching function is given as: -$$ x_{cb,stretch} = x_{cb} + \frac{x_{cb}}{a_x} \Bigg[ \mathrm{log}\left[\mathrm{cosh} \left( \frac{a_x(x_{cb}-x_a)}{L} \right) \right] + \mathrm{log}\left[\mathrm{cosh} \left( \frac{a_x(x_{cb}-x_b)}{L} \right) \right] -2 \mathrm{log}\left[\mathrm{cosh} \left( \frac{a_x(x_b-x_a)}{2L} \right) \right] \Bigg] $$ +\f[ x_{cb,stretch} = x_{cb} + \frac{x_{cb}}{a_x} \Bigg[ \mathrm{log}\left[\mathrm{cosh} \left( \frac{a_x(x_{cb}-x_a)}{L} \right) \right] + \mathrm{log}\left[\mathrm{cosh} \left( \frac{a_x(x_{cb}-x_b)}{L} \right) \right] -2 \mathrm{log}\left[\mathrm{cosh} \left( \frac{a_x(x_b-x_a)}{2L} \right) \right] \Bigg] \f] where `x_cb` and `x_[cb,stretch]` are the coordinates of a cell boundary at the original and stretched domains, respectively. `L` is the domain length along the `x` axis: `L`=`x_domain%%end`-`x_domain%%beg`. @@ -158,7 +158,7 @@ When $p=0$, the domain is defined on $x$-$y$ axi-symmetric coordinates. In both Coordinates, mesh stretching can be defined along the $x$- and $y$-axes. MPI topology is automatically optimized to maximize the parallel efficiency for given choice of coordinate systems. -### 3. Patches +### 3. Patches {#sec-patches} | Parameter | Type | Analytical Definition | Description | | ---: | :----: | :----: | :--- | @@ -220,7 +220,7 @@ Additionally, the following variables are made available as shorthand: | `y` | `y_cc(j)` | `ly` | The patch's `length_y` | `yc` | The patch's `y_centroid` | | `z` | `z_cc(k)` | `lz` | The patch's `length_z` | `zc` | The patch's `z_centroid` | | `eps` | The patch's `epsilon` | `beta` | The patch's `beta` | `radii` | The patch's `radii` | -| `tau_e` | The patch's `tau_e` | `r` | The patch's `radius` | `pi` and `e` | $\pi$ and $e$ | +| `tau_e` | The patch's `tau_e` | `r` | The patch's `radius` | `pi` and `e` | \f$\pi\f$ and \f$e\f$ | where $(i,j,k)$ are the grid-indices of the current cell in each coordinate direction. @@ -300,7 +300,7 @@ These physical parameters must be consistent with fluid material's parameters de Initial conditions in which not all patches support the `patch_icpp(j)%smoothen` parameter can still be smoothed by applying iterations of the heat equation to the initial condition. This is enabled by adding `'elliptic_smoothing': "T",` and `'elliptic_smoothing_iters': N,` to the case dictionary, where `N` is the number of smoothing iterations to apply. -### 4. Immersed Boundary Patches +### 4. Immersed Boundary Patches {#sec-immersed-boundary-patches} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -345,7 +345,7 @@ Additional details on this specification can be found in [The Naca Airfoil Serie - `slip` applies a slip boundary to the surface of the patch if true and a no-slip boundary condition to the surface if false. -- Please see [Patch Parameters](#3-patches) for the descriptions of `model_filepath`, `model_scale`, `model_rotate`, `model_translate`, `model_spc`, and `model_threshold`. +- Please see [Patch Parameters](#sec-patches) for the descriptions of `model_filepath`, `model_scale`, `model_rotate`, `model_translate`, `model_spc`, and `model_threshold`. - `moving_ibm` sets the method by which movement will be applied to the immersed boundary. Using 0 will result in no movement. Using 1 will result 1-way coupling where the boundary moves at a constant rate and applied forces to the fluid based upon it's own motion. In 1-way coupling, the fluid does not apply forces back onto the IB. @@ -353,12 +353,12 @@ Additional details on this specification can be found in [The Naca Airfoil Serie - `angular_vel(i)` is the initial angular velocity of the IB about the x, y, z axes for i=1, 2, 3 in radians per second. When `moving_ibm` equals 1, this angular velocity is constant. -### 5. Fluid Material’s +### 5. Fluid Material's {#sec-fluid-materials} | Parameter | Type | Description | | ---: | :----: | :--- | -| `gamma` | Real | Stiffened-gas parameter $\Gamma$ of fluid. | -| `pi_inf` | Real | Stiffened-gas parameter $\Pi_\infty$ of fluid. | +| `gamma` | Real | Stiffened-gas parameter \f$\Gamma\f$ of fluid. | +| `pi_inf` | Real | Stiffened-gas parameter \f$\Pi_\infty\f$ of fluid. | | `Re(1)` * | Real | Shear viscosity of fluid. | | `Re(2)` * | Real | Volume viscosity of fluid. | | `cv` ** | Real | Sffened-gas parameter $c_v$ of fluid. | @@ -376,7 +376,7 @@ Fluid material's parameters. All parameters except for sigma should be prepended The table lists the fluid material's parameters. The parameters define material's property of compressible fluids that are used in simulation. -- `fluid_pp(i)%%gamma` and `fluid_pp(i)%%pi_inf` define $\Gamma$ and $\Pi$ as parameters of $i$-th fluid that are used in stiffened gas equation of state. +- `fluid_pp(i)%%gamma` and `fluid_pp(i)%%pi_inf` define \f$\Gamma\f$ and \f$\Pi\f$ as parameters of $i$-th fluid that are used in stiffened gas equation of state. - `fluid_pp(i)%%Re(1)` and `fluid_pp(i)%%Re(2)` define the shear and volume viscosities of $i$-th fluid, respectively. @@ -387,15 +387,17 @@ Details of implementation of viscosity in MFC can be found in \cite Coralic15. - `fluid_pp(i)%%G` is required for `hypoelasticity`. -### 6. Simulation Algorithm - +### 6. Simulation Algorithm {#sec-simulation-algorithm} + +See @ref equations "Equations" for the mathematical models these parameters control. + | Parameter | Type | Description | | ---: | :----: | :--- | | `bc_[x,y,z]%%beg[end]` | Integer | Beginning [ending] boundary condition in the $[x,y,z]$-direction (negative integer, see table [Boundary Conditions](#boundary-conditions)) | | `bc_[x,y,z]%%vb[1,2,3]`‑ | Real | Velocity in the (x,1), (y, 2), (z,3) direction applied to `bc_[x,y,z]%%beg` | | `bc_[x,y,z]%%ve[1,2,3]`‑ | Real | Velocity in the (x,1), (y, 2), (z,3) direction applied to `bc_[x,y,z]%%end` | -| `model_eqns` | Integer | Multicomponent model: [1] $\Gamma/\Pi_\infty$; [2] 5-equation; [3] 6-equation; [4] 4-equation | -| `alt_soundspeed` * | Logical | Alternate sound speed and $K \nabla \cdot u$ for 5-equation model | +| `model_eqns` | Integer | Multicomponent model: [1] \f$\Gamma/\Pi_\infty\f$; [2] 5-equation; [3] 6-equation; [4] 4-equation | +| `alt_soundspeed` * | Logical | Alternate sound speed and \f$K \nabla \cdot u\f$ for 5-equation model | | `adv_n` | Logical | Solving directly for the number density (in the method of classes) and compute void fraction from the number density | | `mpp_lim` | Logical | Mixture physical parameters limits | | `mixture_err` | Logical | Mixture properties correction | @@ -467,16 +469,16 @@ Tangential velocities require viscosity, `weno_avg = T`, and `bc_[x,y,z]%%beg = Tangential velocities require viscosity, `weno_avg = T`, and `bc_[x,y,z]%%end = 16` to work properly. Normal velocities require `bc_[x,y,z]%%end = -15` or `\bc_[x,y,z]%%end = -16` to work properly. - `model_eqns` specifies the choice of the multi-component model that is used to formulate the dynamics of the flow using integers from 1 through 3. -`model_eqns = 1`, `2`, and `3` correspond to $\Gamma$-$\Pi_\infty$ model (\cite Johnsen08), 5-equation model (\cite Allaire02), and 6-equation model (\cite Saurel09), respectively. +`model_eqns = 1`, `2`, and `3` correspond to \f$\Gamma\f$-\f$\Pi_\infty\f$ model (\cite Johnsen08), 5-equation model (\cite Allaire02), and 6-equation model (\cite Saurel09), respectively. The difference of the two models is assessed by (\cite Schmidmayer20). Note that some code parameters are only compatible with 5-equation model. -- `alt_soundspeed` activates the source term in the advection equations for the volume fractions, $K\nabla\cdot \underline{u}$, that regularizes the speed of sound in the mixture region when the 5-equation model is used. +- `alt_soundspeed` activates the source term in the advection equations for the volume fractions, \f$K\nabla\cdot \underline{u}\f$, that regularizes the speed of sound in the mixture region when the 5-equation model is used. The effect and use of the source term are assessed by \cite Schmidmayer20. - `adv_n` activates the direct computation of number density by the Riemann solver instead of computing number density from the void fraction in the method of classes. -- `mpp_lim` activates correction of solutions to avoid a negative void fraction of each component in each grid cell, such that $\alpha_i>\varepsilon$ is satisfied at each time step. +- `mpp_lim` activates correction of solutions to avoid a negative void fraction of each component in each grid cell, such that \f$\alpha_i>\varepsilon\f$ is satisfied at each time step. - `mixture_err` activates correction of solutions to avoid imaginary speed of sound at each grid cell. @@ -535,7 +537,7 @@ This option requires `weno_Re_flux` to be true because cell boundary values are - `hypoelasticity` activates elastic stress calculations for fluid-solid interactions. Requires `G` to be set in the fluid material's parameters. -#### Boundary Condition Patches +#### Boundary Condition Patches {#boundary-condition-patches} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -545,7 +547,7 @@ This option requires `weno_Re_flux` to be true because cell boundary values are | `type`* | Integer | The geometry of the patch. [1]: Line [2]: Circle [3]: Rectangle | | `x[y,z]_centroid`* | Real | Centroid of the boundary patch in the x[y,z]-direction | | `length_x[y,z]`* | Real | Length of the boundary patch in the x[y,z]-direction | -| `radiue`* | Real | Radius of the boundary patch | +| `radius`* | Real | Radius of the boundary patch | *: These parameters should be prepended with `patch_bc(j)%` where $j$ is the patch index. Boundary condition patches can be used with the following boundary condition types: @@ -563,7 +565,7 @@ Squares and circles on each face are supported for 3D simulations. - `dt` specifies the constant time step size used in the simulation. The value of `dt` needs to be sufficiently small to satisfy the Courant-Friedrichs-Lewy (CFL) condition. -- `t_step_start` and `t_step_end` define the time steps at which the simulation starts and ends. +- `t_step_start` and `t_step_stop` define the time steps at which the simulation starts and ends. `t_step_save` is the time step interval for data output during simulation. To newly start the simulation, set `t_step_start = 0`. @@ -586,7 +588,7 @@ To restart the simulation from $k$-th time step, set `t_step_start = k`; see @re To newly start the simulation, set `n_start = 0`. To restart the simulation from $k$-th time step, see @ref running "Restarting Cases". -### 7. Formatted Output +### 7. Formatted Output {#sec-formatted-output} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -612,7 +614,6 @@ To restart the simulation from $k$-th time step, see @ref running "Restarting Ca | `schlieren_wrt` | Logical | Add the numerical schlieren to the database| | `qm_wrt` | Logical | Add the Q-criterion to the database| | `liutex_wrt` | Logical | Add the Liutex to the database| -| `tau_wrt` | Logical | Add the elastic stress components to the database| | `fd_order` | Integer | Order of finite differences for computing the vorticity and the numerical Schlieren function [1,2,4] | | `schlieren_alpha(i)` | Real | Intensity of the numerical Schlieren computed via `alpha(i)` | | `probe_wrt` | Logical | Write the flow chosen probes data files for each time step | @@ -671,7 +672,7 @@ This is useful for large domains where only a portion of the domain is of intere It is not supported when `precision = 1` and `format = 1`. It also cannot be enabled with `flux_wrt`, `heat_ratio_wrt`, `pres_inf_wrt`, `c_wrt`, `omega_wrt`, `ib`, `schlieren_wrt`, `qm_wrt`, or 'liutex_wrt'. -### 8. Acoustic Source {#acoustic-source} +### 8. Acoustic Source {#sec-acoustic-source} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -752,7 +753,7 @@ Details of the transducer acoustic source model can be found in \cite Maeda17. - `%%bb_lowest_freq` specifies the lower frequency bound of the broadband acoustic wave. The upper frequency bound will be calculated as `%%bb_lowest_freq + %%bb_num_freq * %%bb_bandwidth`. The wave is no longer broadband below the lower bound and above the upper bound. -### 9. Sub-grid Bubble Models +### 9. Sub-grid Bubble Models {#sec-bubble-models} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -797,6 +798,8 @@ This table lists the sub-grid bubble model parameters, which can be utilized in Implementation of the parameters into the model follows \cite Ando10. +See @ref equations "Equations" Section 9 for the bubble dynamics equations. + #### 9.1 Ensemble-Averaged Bubble Model | Parameter | Type | Description | @@ -867,7 +870,7 @@ When ``polytropic = 'F'``, the gas compression is modeled as non-polytropic due - `massTransfer_model` Activates the mass transfer model at the bubble's interface based on (\cite Preston07). -### 10. Velocity Field Setup +### 10. Velocity Field Setup {#sec-velocity-field-setup} | Parameter | Type | Description | | ---: | :----: | :--- | @@ -897,11 +900,11 @@ The parameters are optionally used to define initial velocity profiles and pertu - `mixlayer_vel_coef` is a parameter for the hyperbolic tangent profile of a mixing layer when `mixlayer_vel_profile = 'T'`. The mean streamwise velocity profile is given as: -$$ u = \mbox{patch\_icpp(1)\%vel(1)} * \tanh( y_{cc} * \mbox{mixlayer\_vel\_coef}) $$ +\f[ u = \text{patch\_icpp(1)\%vel(1)} \cdot \tanh( y_{cc} \cdot \text{mixlayer\_vel\_coef}) \f] - `mixlayer_perturb` activates the velocity perturbation for a temporal mixing layer with hyperbolic tangent mean streamwise velocity profile, using an inverter version of the spectrum-based synthetic turbulence generation method proposed by \cite Guo23. This option only works for `p > 0` and `mixlayer_vel_profile = 'T'`. -### 11. Phase Change Model +### 11. Phase Change Model {#sec-phase-change} | Parameter | Type | Description | | ---: | :----: | :--- | | `relax` | Logical | Activates Phase Change model | @@ -917,7 +920,7 @@ $$ u = \mbox{patch\_icpp(1)\%vel(1)} * \tanh( y_{cc} * \mbox{mixlayer\_vel\_coef - `ptgalpha_eps` Specifies the tolerance used for the Newton Solvers used in the pTg-equilibrium model. -### 12. Artificial Mach Number +### 12. Artificial Mach Number {#sec-artificial-mach-number} | Parameter | Type | Description | | ---: | :----: | :--- | | `pi_fac` | Real | Ratio of artificial and true `pi_\infty` values| @@ -937,7 +940,7 @@ This parameter enables the use of true `pi_\infty` in bubble dynamics models whe `k_x[y,z]`, `w_x[y,z]`, `p_x[y,z]`, and `g_x[y,z]` define an oscillating acceleration in the `x[y,z]` direction with the form -$$ a_{x[y,z]} = g_{x[y,z]} + k_{x[y,z]}\sin\left(w_{x[y,z]}t + p_{x[y,z]}\right). $$ +\f[ a_{x[y,z]} = g_{x[y,z]} + k_{x[y,z]}\sin\left(w_{x[y,z]}t + p_{x[y,z]}\right). \f] By convention, positive accelerations in the `x[y,z]` direction are in the positive `x[y,z]` direction. @@ -994,7 +997,7 @@ When ``cyl_coord = 'T'`` is set in 3D the following constraints must be met: - `z_domain%beg = 0` sets the azimuthal starting point to 0 -- `z_comain%end = 2*math.pi` to set the azimuthal ending point to $2\pi$ (note, requires `import math` in the case file) +- `z_domain%end = 2*math.pi` to set the azimuthal ending point to \f$2\pi\f$ (note, requires `import math` in the case file) When ``cyl_coord = 'T'`` is set in 2D the following constraints must be met: @@ -1018,7 +1021,7 @@ When ``cyl_coord = 'T'`` is set in 2D the following constraints must be met: ## Enumerations -### Boundary conditions +### Boundary conditions {#boundary-conditions} | # | Type | Description | | ---: | :----: | :--- | @@ -1041,7 +1044,7 @@ When ``cyl_coord = 'T'`` is set in 2D the following constraints must be met: *: This boundary condition is only used for `bc_y%%beg` when using cylindrical coordinates (``cyl_coord = 'T'`` and 3D). For axisymmetric problems, use `bc_y%%beg = -2` with ``cyl_coord = 'T'`` in 2D. The boundary condition supported by the MFC are listed in table [Boundary Conditions](#boundary-conditions). -Their number (`#`) corresponds to the input value in `input.py` labeled `bc_[x,y,z]%[beg,end]` (see table [Simulation Algorithm Parameters](#5-simulation-algorithm)). +Their number (`#`) corresponds to the input value in `input.py` labeled `bc_[x,y,z]%[beg,end]` (see table [Simulation Algorithm Parameters](#sec-simulation-algorithm)). The entries labeled "Characteristic." are characteristic boundary conditions based on \cite Thompson87 and \cite Thompson90. ### Generalized Characteristic Boundary conditions @@ -1060,7 +1063,7 @@ The entries labeled "Characteristic." are characteristic boundary conditions bas This boundary condition can be used for subsonic inflow (`bc_[x,y,z]%[beg,end]` = -7) and subsonic outflow (`bc_[x,y,z]%[beg,end]` = -8) characteristic boundary conditions. These are based on \cite Pirozzoli13. This enables to provide inflow and outflow conditions outside the computational domain. -### Patch types +### Patch types {#patch-types} | # | Name | Dim. | Smooth | Description | | ---: | :----: | :---: | :---: | :--- | @@ -1084,14 +1087,14 @@ This boundary condition can be used for subsonic inflow (`bc_[x,y,z]%[beg,end]` | 18 | 2D Varcircle | 2 | Y | Requires `[x,y]_centroid`, `radius`, and `thickness` | | 19 | 3D Varcircle | 3 | Y | Requires `[x,y,z]_centroid`, `length_z`, `radius`, and `thickness` | | 20 | 2D Taylor-Green Vortex | 2 | N | Requires `[x,y]_centroid`, `length_x`, `length_y`, `vel(1)`, and `vel(2)` | -| 21 | Model | 2 & 3 | Y | Imports a Model (STL/OBJ). Requires `model%%filepath`. | +| 21 | Model | 2 & 3 | Y | Imports a Model (STL/OBJ). Requires `model_filepath`. | The patch types supported by the MFC are listed in table [Patch Types](#patch-types). This includes types exclusive to one-, two-, and three-dimensional problems. The patch type number (`#`) corresponds to the input value in `input.py` labeled `patch_icpp(j)%%geometry` where $j$ is the patch index. Each patch requires a different set of parameters, which are also listed in this table. -### Immersed Boundary Patch Types +### Immersed Boundary Patch Types {#immersed-boundary-patch-types} | # | Name | Dim. | | ---: | :----: | :--- | @@ -1116,7 +1119,7 @@ Each patch requires a different set of parameters, which are also listed in this | 10 | Annular Transducer Array | 2D-Axisym | #9 requirements | | 11 | Circular Transducer Array | 3D | #7 requirements, `%%element_polygon_ratio`, and `%%rotate_angle` | -The required parameters for each acoustic support type are listed in [Acoustic Source](#acoustic-source). +The required parameters for each acoustic support type are listed in [Acoustic Source](#sec-acoustic-source). The acoustic support number (`#`) corresponds to the acoustic support type `Acoustic(i)%%support`, where $i$ is the acoustic source index. For each `%%parameter`, prepend the parameter with `acoustic(i)%`. @@ -1137,10 +1140,10 @@ Description of the acoustic support types: - `%%support = 1` specifies an infinite source plane that is normal to the $x$-axis and intersects with the axis at $x=$ `%%loc(1)` in 1D simulation. `%%dir > 0` specifies a rightward propagating wave, and `%%dir < 0` specifies a leftward propagating wave. `%%dir = 0` is not allowed. - `%%support = 2` specifies a semi-infinite source plane in 2D simulation. -The midplane location is [`%%loc(1)`, `%%loc(2)`] and the normal vector is [$\mathrm{cos}$(`%%dir`), $\mathrm{sin}$(`%%dir`)]. The length of the source plane is `%%length`, and the plane is perpendicular to the direction of wave propagation (defined by `%%dir`). +The midplane location is [`%%loc(1)`, `%%loc(2)`] and the normal vector is [\f$\mathrm{cos}\f$(`%%dir`), \f$\mathrm{sin}\f$(`%%dir`)]. The length of the source plane is `%%length`, and the plane is perpendicular to the direction of wave propagation (defined by `%%dir`). - `%%support = 3` specifies a semi-infinite source plane in 3D simulation. -The midplane location is [`%%loc(1)`, `%%loc(2)`] and the normal vector is [$\mathrm{cos}$(`%%dir`), $\mathrm{sin}$(`%%dir`)]. The length of the source plane is `%%length`, and the plane is perpendicular to the direction of wave propagation (defined by `%%dir`). Note that the plane is infinite in the $z$-direction, so `%%loc(3)` is not required. +The midplane location is [`%%loc(1)`, `%%loc(2)`] and the normal vector is [\f$\mathrm{cos}\f$(`%%dir`), \f$\mathrm{sin}\f$(`%%dir`)]. The length of the source plane is `%%length`, and the plane is perpendicular to the direction of wave propagation (defined by `%%dir`). Note that the plane is infinite in the $z$-direction, so `%%loc(3)` is not required. - `%%support = 5` specifies a circular transducer in 2D simulation. The transducer is centered at [`%%loc(1)`, `%%loc(2)`] with a focal length of `%%foc_length` and an aperture of `%%aperture`. The center location is not the focal point; it is the tip of the circular arc (intersection of the arc and the x-axis). The aperture is the length of the projection of the circular arc onto the y-axis. If a semi-circle is desired, set the aperture to double the focal length. Note that this is physically a cylindrical transducer, and due to the complexity of Green's function for 2D wave, no closed-form solution is available for the 2D circular transducer, and an approximate is used (see \cite Maeda17 for details). For the mass source term correction factor, the theoretical approximation factor of -0.5 in ($r_{foc}^{-0.5}$) is replaced by an empirically determined factor of -0.85. diff --git a/docs/documentation/contributing.md b/docs/documentation/contributing.md index 0f2cbf9db7..8b1ba8fcdd 100644 --- a/docs/documentation/contributing.md +++ b/docs/documentation/contributing.md @@ -148,7 +148,7 @@ Both human reviewers and AI code reviewers reference this section. ### Memory and Allocation - **ALLOCATE/DEALLOCATE pairing:** Every `@:ALLOCATE()` must have a matching `@:DEALLOCATE()`. Missing deallocations leak GPU memory. -- **@:ACC_SETUP_VFs / @:ACC_SETUP_SFs:** Vector/scalar fields must have GPU pointer setup before use in kernels. +- **`@:ACC_SETUP_VFs` / `@:ACC_SETUP_SFs`:** Vector/scalar fields must have GPU pointer setup before use in kernels. - **Conditional allocation:** If an array is allocated inside an `if` block, its deallocation must follow the same condition. - **Out-of-bounds access:** Fortran is permissive with assumed-shape arrays. Check that index arithmetic stays within declared bounds. @@ -212,10 +212,27 @@ Adding a parameter touches both the Python toolchain and Fortran source. Follow Add a call to `_r()` inside the `_load()` function: ```python -_r("my_param", REAL, {"my_feature_tag"}) +_r("my_param", REAL, {"my_feature_tag"}, + desc="Description of the parameter", + math=r"\f$\xi\f$") ``` -The arguments are: name, type (`INT`, `REAL`, `LOG`, `STR`), and a set of feature tags. You can add an explicit description with `desc="..."`, otherwise one is auto-generated from `_SIMPLE_DESCS` or `_ATTR_DESCS`. +The arguments are: +- **name**: parameter name (must match the Fortran namelist variable) +- **type**: `INT`, `REAL`, `LOG`, `STR`, or `A_REAL` (analytic expression) +- **tags**: set of feature tags for grouping (e.g. `{"bubbles"}`, `{"mhd"}`) +- **desc**: human-readable description (optional; auto-generated from `_SIMPLE_DESCS` or `_ATTR_DESCS` if omitted) +- **math**: LaTeX math symbol in Doxygen format (optional; shown in the Symbol column of @ref parameters) + +For indexed families like `fluid_pp`, put the symbol next to its attribute name using tuples: + +```python +for f in range(1, NF + 1): + px = f"fluid_pp({f})%" + for a, sym in [("gamma", r"\f$\gamma_k\f$"), + ("my_attr", r"\f$\xi_k\f$")]: # <-- add here + _r(f"{px}{a}", REAL, math=sym) +``` **Step 2: Add constraints** (same file, `CONSTRAINTS` dict) diff --git a/docs/documentation/equations.md b/docs/documentation/equations.md index 59c6a5c776..efa881f570 100644 --- a/docs/documentation/equations.md +++ b/docs/documentation/equations.md @@ -7,6 +7,8 @@ Each section notes the input parameter(s) that activate the corresponding physic The models and algorithms described here are detailed in \cite Wilfong26 (MFC 5.0) and \cite Bryngelson21. Foundational references for each model are cited inline; see the \ref citelist "Bibliography" for full details. +For parameter details and allowed values, see @ref case "Case Files" and the @ref parameters "Case Parameters" reference. + --- ## 1. Overview diff --git a/docs/documentation/getting-started.md b/docs/documentation/getting-started.md index 47befe309f..0e305023b5 100644 --- a/docs/documentation/getting-started.md +++ b/docs/documentation/getting-started.md @@ -70,7 +70,7 @@ for a Linux experience.
-

Windows + WSL (Recommended)

+ Windows + WSL (Recommended) Install [Windows Subsystem for Linux (WSL)](https://docs.microsoft.com/en-us/windows/wsl/) on Windows 11: Either @@ -92,7 +92,7 @@ Once you have WSL installed, you can follow the instructions for *nix systems ab
-

Native Windows (Intel)

+ Native Windows (Intel) Install the latest version of: - [Microsoft Visual Studio Community](https://visualstudio.microsoft.com/) @@ -118,7 +118,9 @@ You will also have access to the `.sln` Microsoft Visual Studio solution files f
-

MacOS

+
+ + MacOS Using [Homebrew](https://brew.sh/) you can install the necessary dependencies before configuring your environment: diff --git a/docs/documentation/readme.md b/docs/documentation/readme.md index d72395cae0..83673ed81e 100644 --- a/docs/documentation/readme.md +++ b/docs/documentation/readme.md @@ -35,5 +35,5 @@ Welcome to the Multi-component Flow Code (MFC) documentation. ## About - @ref papers "Papers" - Publications using MFC -- @ref references "References" - Bibliography +- \ref citelist "Bibliography" - Cited references - @ref authors "Authors" - Contributors diff --git a/docs/documentation/references.md b/docs/documentation/references.md deleted file mode 100644 index 7a9f1cfe6c..0000000000 --- a/docs/documentation/references.md +++ /dev/null @@ -1,7 +0,0 @@ -@page references References - -# References - -All references cited throughout the MFC documentation are managed via BibTeX and rendered automatically by Doxygen. - -See the \ref citelist "Bibliography" for the full list of cited works. diff --git a/docs/documentation/visualization.md b/docs/documentation/visualization.md index 10c1fca271..955465a3b8 100644 --- a/docs/documentation/visualization.md +++ b/docs/documentation/visualization.md @@ -54,17 +54,17 @@ For analysis and processing of the database using VisIt's capability, the user i ## Serial data output If ``parallel_io = 'F'``, MFC will output the conservative variables to a directory `D/`. -If multiple cores are used ($\mathtt{ppn > 1}$), then a separate file is created for each core. +If multiple cores are used (\f$\mathtt{ppn > 1}\f$), then a separate file is created for each core. If only one coordinate dimension (`n = 0` and `p = 0`) exists, the primitive variables will also be written to `D/`. The file names correspond to the variables associated with each equation solved by MFC. They are written at every `t_step_save` time step. The conservative variables are -$$ {(\rho \alpha)}\_{1}, \dots, (\rho\alpha)\_{N\_c}, \rho u\_{1}, \dots, \rho u\_{N\_d}, E, \alpha\_1, \dots, \alpha\_{N\_c} $$ +\f[ (\rho \alpha)_{1}, \dots, (\rho\alpha)_{N_c}, \rho u_{1}, \dots, \rho u_{N_d}, E, \alpha_1, \dots, \alpha_{N_c} \f] and the primitive variables are -$$ {(\rho \alpha)}\_1, \dots, (\rho\alpha)\_{N\_c}, u\_1, \dots, u\_{N\_d}, p, \alpha\_1, \dots, \alpha\_{N\_c} $$ +\f[ (\rho \alpha)_1, \dots, (\rho\alpha)_{N_c}, u_1, \dots, u_{N_d}, p, \alpha_1, \dots, \alpha_{N_c} \f] where $N_c$ are the number of components `num_fluids` and $N_d$ is the number of spatial dimensions. There are exceptions: if `model_eqns = 3`, then the six-equation model appends these variables with the internal energies of each component. @@ -72,12 +72,12 @@ If there are sub-grid bubbles `bubbles = T`, then the bubble variables are also These depend on the bubble dynamics model used. If ``polytropic = 'T'``, then the conservative variables are appended by -$$ n\_b R\_1, n\_b {\\dot R}\_1, \dots, n\_b R\_{N\_b}, n\_b {\\dot R}\_{N\_b} $$ +\f[ n_b R_1, n_b \dot{R}_1, \dots, n_b R_{N_b}, n_b \dot{R}_{N_b} \f] where $n_B$ is the bubble number density, and $N_b$ is the number of bubble sizes (see the matching variable in the input file, `Nb`). The primitive bubble variables do not include $n_B$: -$$ R\_1, {\\dot R}\_1, \dots, R\_{N\_b}, {\\dot R}\_{N\_b} $$ +\f[ R_1, \dot{R}_1, \dots, R_{N_b}, \dot{R}_{N_b} \f] ## Remote Visualization on PACE Phoenix diff --git a/src/common/m_boundary_common.fpp b/src/common/m_boundary_common.fpp index 4b5f660bd6..8b8d301123 100644 --- a/src/common/m_boundary_common.fpp +++ b/src/common/m_boundary_common.fpp @@ -1,5 +1,5 @@ !> -!! @file m_boundary_conditions_common.fpp +!! @file !! @brief Contains module m_boundary_conditions_common !> @brief The purpose of the module is to apply noncharacteristic and processor diff --git a/src/common/m_checker_common.fpp b/src/common/m_checker_common.fpp index ff4af7bd20..52549e7a10 100644 --- a/src/common/m_checker_common.fpp +++ b/src/common/m_checker_common.fpp @@ -1,5 +1,5 @@ !> -!!@file m_checker_common.f90 +!!@file !!@brief Contains module m_checker_common #:include 'case.fpp' diff --git a/src/common/m_chemistry.fpp b/src/common/m_chemistry.fpp index 69aba788db..a6ca8da449 100644 --- a/src/common/m_chemistry.fpp +++ b/src/common/m_chemistry.fpp @@ -1,5 +1,5 @@ !!> -!! @file m_chemistry.f90 +!! @file !! @brief Contains module m_chemistry !! @author Henry Le Berre diff --git a/src/common/m_compile_specific.f90 b/src/common/m_compile_specific.f90 index 8479755961..87e1849abf 100644 --- a/src/common/m_compile_specific.f90 +++ b/src/common/m_compile_specific.f90 @@ -1,5 +1,5 @@ !> -!! @file m_compile_specific.f90 +!! @file !! @brief Contains module m_compile_specific !> @brief This module contains subroutines that are compiler specific diff --git a/src/common/m_compute_levelset.fpp b/src/common/m_compute_levelset.fpp index 7473c19deb..2037418f51 100644 --- a/src/common/m_compute_levelset.fpp +++ b/src/common/m_compute_levelset.fpp @@ -1,5 +1,5 @@ !> -!! @file m_compute_levelset.fpp +!! @file !! @brief Contains module m_compute_levelset #:include 'macros.fpp' diff --git a/src/common/m_constants.fpp b/src/common/m_constants.fpp index b4d5982aa5..d728447f5f 100644 --- a/src/common/m_constants.fpp +++ b/src/common/m_constants.fpp @@ -1,5 +1,5 @@ !> -!! @file m_constants.f90 +!! @file !! @brief Contains constant values used throughout the code(s). module m_constants diff --git a/src/common/m_derived_types.fpp b/src/common/m_derived_types.fpp index 5c36a7ae11..ddded5740d 100644 --- a/src/common/m_derived_types.fpp +++ b/src/common/m_derived_types.fpp @@ -1,5 +1,5 @@ !> -!! @file m_derived_types.f90 +!! @file !! @brief Contains module m_derived_types #:include "macros.fpp" diff --git a/src/common/m_helper.fpp b/src/common/m_helper.fpp index 5ee39f7aab..d990a83345 100644 --- a/src/common/m_helper.fpp +++ b/src/common/m_helper.fpp @@ -2,7 +2,7 @@ #:include 'macros.fpp' !> -!! @file m_helper.f90 +!! @file !! @brief Contains module m_helper module m_helper diff --git a/src/common/m_helper_basic.fpp b/src/common/m_helper_basic.fpp index eca8c3ccb7..d8ce26f485 100644 --- a/src/common/m_helper_basic.fpp +++ b/src/common/m_helper_basic.fpp @@ -1,5 +1,5 @@ -!! @file m_helper_basic.f90 +!! @file !! @brief Contains module m_helper_basic #:include 'macros.fpp' diff --git a/src/common/m_ib_patches.fpp b/src/common/m_ib_patches.fpp index 3db86ceab5..6ff2a327a5 100644 --- a/src/common/m_ib_patches.fpp +++ b/src/common/m_ib_patches.fpp @@ -1,5 +1,5 @@ !> -!! @file m_patches.fpp +!! @file !! @brief Contains module m_patches #:include 'case.fpp' diff --git a/src/common/m_model.fpp b/src/common/m_model.fpp index dd8f2204f7..ff338dc06d 100644 --- a/src/common/m_model.fpp +++ b/src/common/m_model.fpp @@ -1,5 +1,5 @@ !> -!! @file m_model.fpp +!! @file !! @author Henry Le Berre !! @brief Contains module m_model diff --git a/src/common/m_variables_conversion.fpp b/src/common/m_variables_conversion.fpp index d322810e84..1f8245da8b 100644 --- a/src/common/m_variables_conversion.fpp +++ b/src/common/m_variables_conversion.fpp @@ -1,5 +1,5 @@ !> -!! @file m_variables_conversion.f90 +!! @file !! @brief Contains module m_variables_conversion #:include 'macros.fpp' diff --git a/src/post_process/m_checker.fpp b/src/post_process/m_checker.fpp index 291b9f5979..82aacff953 100644 --- a/src/post_process/m_checker.fpp +++ b/src/post_process/m_checker.fpp @@ -1,5 +1,5 @@ !> -!!@file m_checker.f90 +!!@file !!@brief Contains module m_checker #:include 'macros.fpp' diff --git a/src/post_process/m_data_input.f90 b/src/post_process/m_data_input.f90 index 98c85e8612..f88da90cb9 100644 --- a/src/post_process/m_data_input.f90 +++ b/src/post_process/m_data_input.f90 @@ -1,5 +1,5 @@ !> -!! @file m_data_input.f90 +!! @file !> @brief Contains module m_data_input !> @brief This module features procedures, which for a specific time-step, @@ -211,8 +211,10 @@ impure subroutine s_read_ib_data_files(file_loc_base, t_step) end subroutine s_read_ib_data_files !> Helper subroutine to allocate field arrays for given dimensionality - !! @param start_idx Starting index for allocation - !! @param end_x, end_y, end_z End indices for each dimension + !! @param local_start_idx Starting index for allocation + !! @param end_x End index for x dimension + !! @param end_y End index for y dimension + !! @param end_z End index for z dimension impure subroutine s_allocate_field_arrays(local_start_idx, end_x, end_y, end_z) integer, intent(in) :: local_start_idx, end_x, end_y, end_z diff --git a/src/post_process/m_data_output.fpp b/src/post_process/m_data_output.fpp index def195a61d..2b5416fe87 100644 --- a/src/post_process/m_data_output.fpp +++ b/src/post_process/m_data_output.fpp @@ -1,5 +1,5 @@ !> -!! @file m_data_output.f90 +!! @file !! @brief Contains module m_data_output !> @brief This module enables the restructuring of the raw simulation data diff --git a/src/post_process/m_derived_variables.fpp b/src/post_process/m_derived_variables.fpp index 497178ccf3..d0bf8a689e 100644 --- a/src/post_process/m_derived_variables.fpp +++ b/src/post_process/m_derived_variables.fpp @@ -1,5 +1,5 @@ !> -!! @file m_derived_variables.f90 +!! @file !! @brief Contains module m_derived_variables !> @brief This module features subroutines that allow for the derivation of diff --git a/src/post_process/m_global_parameters.fpp b/src/post_process/m_global_parameters.fpp index b21af0fad6..1411b104d4 100644 --- a/src/post_process/m_global_parameters.fpp +++ b/src/post_process/m_global_parameters.fpp @@ -1,5 +1,5 @@ !> -!! @file m_global_parameters.f90 +!! @file !! @brief Contains module m_global_parameters #:include 'case.fpp' diff --git a/src/post_process/m_mpi_proxy.fpp b/src/post_process/m_mpi_proxy.fpp index bb9bea6b4e..8c004dc8bc 100644 --- a/src/post_process/m_mpi_proxy.fpp +++ b/src/post_process/m_mpi_proxy.fpp @@ -1,5 +1,5 @@ !> -!! @file m_mpi_proxy.f90 +!! @file !! @brief Contains module m_mpi_proxy !> @brief This module serves as a proxy to the parameters and subroutines diff --git a/src/post_process/m_start_up.fpp b/src/post_process/m_start_up.fpp index 329a85f433..aacd208bfe 100644 --- a/src/post_process/m_start_up.fpp +++ b/src/post_process/m_start_up.fpp @@ -1,7 +1,7 @@ #:include 'macros.fpp' !> -!! @file m_start_up.f90 +!! @file !! @brief Contains module m_start_up !> @brief This module contains the subroutines that read in and check the diff --git a/src/post_process/p_main.fpp b/src/post_process/p_main.fpp index 12d6353c67..b8980ac012 100644 --- a/src/post_process/p_main.fpp +++ b/src/post_process/p_main.fpp @@ -1,5 +1,5 @@ !> -!! @file p_main.f90 +!! @file !! @brief Contains program p_main !> @brief The post-process restructures raw unformatted data, outputted by diff --git a/src/pre_process/m_assign_variables.fpp b/src/pre_process/m_assign_variables.fpp index 95473be145..6d967bb1da 100644 --- a/src/pre_process/m_assign_variables.fpp +++ b/src/pre_process/m_assign_variables.fpp @@ -1,5 +1,5 @@ !> -!! @file m_assign_variables.f90 +!! @file !! @brief Contains module m_assign_variables #:include 'case.fpp' diff --git a/src/pre_process/m_boundary_conditions.fpp b/src/pre_process/m_boundary_conditions.fpp index 66ef57cbef..1d2d706a55 100644 --- a/src/pre_process/m_boundary_conditions.fpp +++ b/src/pre_process/m_boundary_conditions.fpp @@ -1,5 +1,5 @@ !> -!! @file m_boundary_conditions.fpp +!! @file !! @brief Contains module m_boundary_conditions !> @brief This module contains diff --git a/src/pre_process/m_checker.fpp b/src/pre_process/m_checker.fpp index 5499262c61..91d4a7f4cb 100644 --- a/src/pre_process/m_checker.fpp +++ b/src/pre_process/m_checker.fpp @@ -1,5 +1,5 @@ !> -!!@file m_checker.f90 +!!@file !!@brief Contains module m_checker #:include 'macros.fpp' diff --git a/src/pre_process/m_data_output.fpp b/src/pre_process/m_data_output.fpp index ca5fb3c56a..002188ab0b 100644 --- a/src/pre_process/m_data_output.fpp +++ b/src/pre_process/m_data_output.fpp @@ -1,5 +1,5 @@ !> -!! @file m_data_output.f90 +!! @file !! @brief Contains module m_data_output !> @brief This module takes care of writing the grid and initial condition diff --git a/src/pre_process/m_global_parameters.fpp b/src/pre_process/m_global_parameters.fpp index 9dd5cebb42..169d996544 100644 --- a/src/pre_process/m_global_parameters.fpp +++ b/src/pre_process/m_global_parameters.fpp @@ -1,5 +1,5 @@ !> -!! @file m_global_parameters.f90 +!! @file !! @brief Contains module m_global_parameters #:include 'case.fpp' diff --git a/src/pre_process/m_grid.f90 b/src/pre_process/m_grid.f90 index 5467e61f79..454531b4e1 100644 --- a/src/pre_process/m_grid.f90 +++ b/src/pre_process/m_grid.f90 @@ -1,5 +1,5 @@ !> -!! @file m_grid.f90 +!! @file !! @brief Contains module m_grid !> @brief This module takes care of creating the rectilinear grid on which diff --git a/src/pre_process/m_icpp_patches.fpp b/src/pre_process/m_icpp_patches.fpp index fc0afdeec6..1c3d6b54cd 100644 --- a/src/pre_process/m_icpp_patches.fpp +++ b/src/pre_process/m_icpp_patches.fpp @@ -1,5 +1,5 @@ !> -!! @file m_patches.fpp +!! @file !! @brief Contains module m_patches #:include 'case.fpp' diff --git a/src/pre_process/m_initial_condition.fpp b/src/pre_process/m_initial_condition.fpp index 35f8bec0db..96b91b4df1 100644 --- a/src/pre_process/m_initial_condition.fpp +++ b/src/pre_process/m_initial_condition.fpp @@ -1,5 +1,5 @@ !> -!! @file m_initial_condition.f90 +!! @file !! @brief Contains module m_initial_condition !> @brief This module provides a platform that is analogous to constructive @@ -53,11 +53,15 @@ module m_initial_condition type(integer_field), dimension(:, :), allocatable :: bc_type !< bc_type fields +!> @cond #ifdef MFC_MIXED_PRECISION integer(kind=1), allocatable, dimension(:, :, :) :: patch_id_fp #else +!> @endcond integer, allocatable, dimension(:, :, :) :: patch_id_fp +!> @cond #endif +!> @endcond !! Bookkepping variable used to track the patch identities (id) associated !! with each of the cells in the computational domain. Note that only one diff --git a/src/pre_process/m_mpi_proxy.fpp b/src/pre_process/m_mpi_proxy.fpp index 050929a9e3..c7b6bb4e4b 100644 --- a/src/pre_process/m_mpi_proxy.fpp +++ b/src/pre_process/m_mpi_proxy.fpp @@ -1,5 +1,5 @@ !> -!! @file m_mpi_proxy.f90 +!! @file !! @brief Contains module m_mpi_proxy !> @brief This module serves as a proxy to the parameters and subroutines diff --git a/src/pre_process/m_perturbation.fpp b/src/pre_process/m_perturbation.fpp index 2ea291c27f..ad17cf11d9 100644 --- a/src/pre_process/m_perturbation.fpp +++ b/src/pre_process/m_perturbation.fpp @@ -1,5 +1,5 @@ !> -!! @file m_perturbation.fpp +!! @file !! @brief Contains module m_perturbation !> @brief This module contains subroutines that compute perturbations to the diff --git a/src/pre_process/m_start_up.fpp b/src/pre_process/m_start_up.fpp index 614f628d49..298092f54b 100644 --- a/src/pre_process/m_start_up.fpp +++ b/src/pre_process/m_start_up.fpp @@ -1,5 +1,5 @@ !> -!! @file m_start_up.f90 +!! @file !! @brief Contains module m_start_up !> @brief This module contains subroutines that read, and check consistency diff --git a/src/pre_process/p_main.f90 b/src/pre_process/p_main.f90 index 4ce377f5cb..9197eecf8f 100644 --- a/src/pre_process/p_main.f90 +++ b/src/pre_process/p_main.f90 @@ -1,5 +1,5 @@ !> -!! @file p_main.f90 +!! @file !! @brief Contains program p_main !> @brief This program takes care of setting up the initial condition and diff --git a/src/simulation/m_acoustic_src.fpp b/src/simulation/m_acoustic_src.fpp index 75a61104da..3a3a080578 100644 --- a/src/simulation/m_acoustic_src.fpp +++ b/src/simulation/m_acoustic_src.fpp @@ -1,5 +1,5 @@ !> -!! @file m_acoustic_src.fpp +!! @file !! @brief Contains module m_acoustic_src #:include 'macros.fpp' diff --git a/src/simulation/m_bubbles.fpp b/src/simulation/m_bubbles.fpp index db29e90cdc..65703d34ea 100644 --- a/src/simulation/m_bubbles.fpp +++ b/src/simulation/m_bubbles.fpp @@ -1,5 +1,5 @@ !> -!! @file m_bubbles.f90 +!! @file !! @brief Contains module m_bubbles #:include 'macros.fpp' diff --git a/src/simulation/m_bubbles_EE.fpp b/src/simulation/m_bubbles_EE.fpp index dfc36f2a32..e041b4f939 100644 --- a/src/simulation/m_bubbles_EE.fpp +++ b/src/simulation/m_bubbles_EE.fpp @@ -1,5 +1,5 @@ !> -!! @file m_bubbles_EE.f90 +!! @file !! @brief Contains module m_bubbles_EE #:include 'macros.fpp' diff --git a/src/simulation/m_bubbles_EL.fpp b/src/simulation/m_bubbles_EL.fpp index ec84e95c65..0256b70138 100644 --- a/src/simulation/m_bubbles_EL.fpp +++ b/src/simulation/m_bubbles_EL.fpp @@ -1,5 +1,5 @@ !> -!! @file m_bubbles_EL.fpp +!! @file !! @brief Contains module m_bubbles_EL #:include 'macros.fpp' diff --git a/src/simulation/m_bubbles_EL_kernels.fpp b/src/simulation/m_bubbles_EL_kernels.fpp index 5d709d6913..f9114fd829 100644 --- a/src/simulation/m_bubbles_EL_kernels.fpp +++ b/src/simulation/m_bubbles_EL_kernels.fpp @@ -1,5 +1,5 @@ !> -!! @file m_bubbles_EL_kernels.f90 +!! @file !! @brief Contains module m_bubbles_EL_kernels #:include 'macros.fpp' diff --git a/src/simulation/m_cbc.fpp b/src/simulation/m_cbc.fpp index 012d2358f2..41800cb638 100644 --- a/src/simulation/m_cbc.fpp +++ b/src/simulation/m_cbc.fpp @@ -1,5 +1,5 @@ !> -!! @file m_cbc.f90 +!! @file !! @brief Contains module m_cbc !> @brief The module features a large database of characteristic boundary diff --git a/src/simulation/m_checker.fpp b/src/simulation/m_checker.fpp index 9ec3c6981f..4f78f9d52d 100644 --- a/src/simulation/m_checker.fpp +++ b/src/simulation/m_checker.fpp @@ -1,5 +1,5 @@ !> -!!@file m_start_up.f90 +!!@file !!@brief Contains module m_checker #:include 'macros.fpp' diff --git a/src/simulation/m_compute_cbc.fpp b/src/simulation/m_compute_cbc.fpp index 13bd6a8209..28ae092abb 100644 --- a/src/simulation/m_compute_cbc.fpp +++ b/src/simulation/m_compute_cbc.fpp @@ -1,5 +1,5 @@ !> -!! @file m_compute_cbc.f90 +!! @file !! @brief CBC computation module #:include 'case.fpp' #:include 'macros.fpp' diff --git a/src/simulation/m_data_output.fpp b/src/simulation/m_data_output.fpp index 6e97af027c..d0986d9628 100644 --- a/src/simulation/m_data_output.fpp +++ b/src/simulation/m_data_output.fpp @@ -1,4 +1,4 @@ -!! @file m_data_output.f90 +!! @file !! @brief Contains module m_data_output #:include 'macros.fpp' diff --git a/src/simulation/m_derived_variables.fpp b/src/simulation/m_derived_variables.fpp index 81cd185c4c..589d5710a3 100644 --- a/src/simulation/m_derived_variables.fpp +++ b/src/simulation/m_derived_variables.fpp @@ -1,5 +1,5 @@ !> -!! @file m_derived_variables.f90 +!! @file !! @brief Contains module m_derived_variables !> @brief This module features subroutines that allow for the derivation of diff --git a/src/simulation/m_fftw.fpp b/src/simulation/m_fftw.fpp index 411485af10..03f5df32a6 100644 --- a/src/simulation/m_fftw.fpp +++ b/src/simulation/m_fftw.fpp @@ -1,5 +1,5 @@ !> -!! @file m_fftw.f90 +!! @file !! @brief Contains module m_fftw #:include 'macros.fpp' @@ -52,11 +52,15 @@ module m_fftw complex(dp), allocatable, target :: data_fltr_cmplx_gpu(:) $:GPU_DECLARE(create='[data_real_gpu,data_cmplx_gpu,data_fltr_cmplx_gpu]') +!> @cond #if defined(__PGI) integer :: fwd_plan_gpu, bwd_plan_gpu #else +!> @endcond type(c_ptr) :: fwd_plan_gpu, bwd_plan_gpu +!> @cond #endif +!> @endcond integer, allocatable :: gpu_fft_size(:), iembed(:), oembed(:) diff --git a/src/simulation/m_global_parameters.fpp b/src/simulation/m_global_parameters.fpp index 78d8d1a7c0..7736425f33 100644 --- a/src/simulation/m_global_parameters.fpp +++ b/src/simulation/m_global_parameters.fpp @@ -1,5 +1,5 @@ !> -!! @file m_global_parameters.f90 +!! @file !! @brief Contains module m_global_parameters #:include 'case.fpp' diff --git a/src/simulation/m_hyperelastic.fpp b/src/simulation/m_hyperelastic.fpp index 9efc638ab9..0133613904 100644 --- a/src/simulation/m_hyperelastic.fpp +++ b/src/simulation/m_hyperelastic.fpp @@ -1,5 +1,5 @@ !> -!! @file m_hyperelastic.f90 +!! @file !! @brief Contains module m_hyperelastic #:include 'macros.fpp' diff --git a/src/simulation/m_hypoelastic.fpp b/src/simulation/m_hypoelastic.fpp index a265b9bdd6..fead6ee117 100644 --- a/src/simulation/m_hypoelastic.fpp +++ b/src/simulation/m_hypoelastic.fpp @@ -1,5 +1,5 @@ !> -!! @file m_hypoelastic.f90 +!! @file !! @brief Contains module m_hypoelastic #:include 'macros.fpp' diff --git a/src/simulation/m_ibm.fpp b/src/simulation/m_ibm.fpp index 5e5e136629..c63027a1ff 100644 --- a/src/simulation/m_ibm.fpp +++ b/src/simulation/m_ibm.fpp @@ -1,5 +1,5 @@ !> -!! @file m_ibm.fpp +!! @file !! @brief Contains module m_ibm #:include 'macros.fpp' diff --git a/src/simulation/m_igr.fpp b/src/simulation/m_igr.fpp index 8aff221313..fa06ef9092 100644 --- a/src/simulation/m_igr.fpp +++ b/src/simulation/m_igr.fpp @@ -24,6 +24,7 @@ module m_igr s_igr_flux_add, & s_finalize_igr_module +!> @cond #ifdef __NVCOMPILER_GPU_UNIFIED_MEM integer, dimension(3) :: nv_uvm_temp_on_gpu real(wp), pointer, contiguous, dimension(:, :, :) :: jac, jac_rhs, jac_old @@ -31,10 +32,13 @@ module m_igr real(wp), allocatable, dimension(:, :, :), pinned, target :: jac_rhs_host real(wp), allocatable, dimension(:, :, :), pinned, target :: jac_old_host #else +!> @endcond real(wp), allocatable, target, dimension(:, :, :) :: jac real(wp), allocatable, dimension(:, :, :) :: jac_rhs, jac_old $:GPU_DECLARE(create='[jac, jac_rhs, jac_old]') +!> @cond #endif +!> @endcond type(scalar_field), dimension(1) :: jac_sf $:GPU_DECLARE(create='[jac_sf]') diff --git a/src/simulation/m_mpi_proxy.fpp b/src/simulation/m_mpi_proxy.fpp index 515f599390..1cb9f684c0 100644 --- a/src/simulation/m_mpi_proxy.fpp +++ b/src/simulation/m_mpi_proxy.fpp @@ -1,5 +1,5 @@ !> -!! @file m_mpi_proxy.f90 +!! @file !! @brief Contains module m_mpi_proxy #:include 'case.fpp' diff --git a/src/simulation/m_pressure_relaxation.fpp b/src/simulation/m_pressure_relaxation.fpp index b94871044c..5482778357 100644 --- a/src/simulation/m_pressure_relaxation.fpp +++ b/src/simulation/m_pressure_relaxation.fpp @@ -1,5 +1,5 @@ !> -!! @file m_pressure_relaxation.fpp +!! @file !! @brief Contains module m_pressure_relaxation #:include 'case.fpp' diff --git a/src/simulation/m_qbmm.fpp b/src/simulation/m_qbmm.fpp index 84f95af557..d580688ba6 100644 --- a/src/simulation/m_qbmm.fpp +++ b/src/simulation/m_qbmm.fpp @@ -1,5 +1,5 @@ !> -!! @file m_qbmm.f90 +!! @file !! @brief Contains module m_qbmm #:include 'case.fpp' diff --git a/src/simulation/m_rhs.fpp b/src/simulation/m_rhs.fpp index 56b5e30665..4fca1f0620 100644 --- a/src/simulation/m_rhs.fpp +++ b/src/simulation/m_rhs.fpp @@ -1,5 +1,5 @@ !> -!! @file m_rhs.f90 +!! @file !! @brief Contains module m_rhs #:include 'case.fpp' diff --git a/src/simulation/m_riemann_solvers.fpp b/src/simulation/m_riemann_solvers.fpp index 378c0c54c2..0416bfc464 100644 --- a/src/simulation/m_riemann_solvers.fpp +++ b/src/simulation/m_riemann_solvers.fpp @@ -1,5 +1,5 @@ !> -!! @file m_riemann_solvers.f90 +!! @file !! @brief Contains module m_riemann_solvers !> @brief This module features a database of approximate and exact Riemann @@ -4668,14 +4668,14 @@ contains !! Calculates Cartesian components of the stress tensor using averaged velocity derivatives !! and cylindrical geometric factors, then updates `flux_src_vf`. !! Assumes x-dir is axial (z_cyl), y-dir is radial (r_cyl), z-dir is azimuthal (theta_cyl for derivatives). - !! @param[in] velL_vf Left boundary velocity ($v_x, v_y, v_z$) (num_dims scalar_field). - !! @param[in] dvelL_dx_vf Left boundary $\partial v_i/\partial x$ (num_dims scalar_field). - !! @param[in] dvelL_dy_vf Left boundary $\partial v_i/\partial y$ (num_dims scalar_field). - !! @param[in] dvelL_dz_vf Left boundary $\partial v_i/\partial z$ (num_dims scalar_field). - !! @param[in] velR_vf Right boundary velocity ($v_x, v_y, v_z$) (num_dims scalar_field). - !! @param[in] dvelR_dx_vf Right boundary $\partial v_i/\partial x$ (num_dims scalar_field). - !! @param[in] dvelR_dy_vf Right boundary $\partial v_i/\partial y$ (num_dims scalar_field). - !! @param[in] dvelR_dz_vf Right boundary $\partial v_i/\partial z$ (num_dims scalar_field). + !! @param[in] velL_vf Left boundary velocity (\f$v_x, v_y, v_z\f$) (num_dims scalar_field). + !! @param[in] dvelL_dx_vf Left boundary \f$\partial v_i/\partial x\f$ (num_dims scalar_field). + !! @param[in] dvelL_dy_vf Left boundary \f$\partial v_i/\partial y\f$ (num_dims scalar_field). + !! @param[in] dvelL_dz_vf Left boundary \f$\partial v_i/\partial z\f$ (num_dims scalar_field). + !! @param[in] velR_vf Right boundary velocity (\f$v_x, v_y, v_z\f$) (num_dims scalar_field). + !! @param[in] dvelR_dx_vf Right boundary \f$\partial v_i/\partial x\f$ (num_dims scalar_field). + !! @param[in] dvelR_dy_vf Right boundary \f$\partial v_i/\partial y\f$ (num_dims scalar_field). + !! @param[in] dvelR_dz_vf Right boundary \f$\partial v_i/\partial z\f$ (num_dims scalar_field). !! @param[inout] flux_src_vf Intercell source flux array to update (sys_size scalar_field). !! @param[in] norm_dir Interface normal direction (1=x-face, 2=y-face, 3=z-face). !! @param[in] ix Global X-direction loop bounds (int_bounds_info). @@ -4697,30 +4697,30 @@ contains ! Local variables #:if not MFC_CASE_OPTIMIZATION and USING_AMD - real(wp), dimension(3) :: avg_v_int !!< Averaged interface velocity $(v_x, v_y, v_z)$ (grid directions). - real(wp), dimension(3) :: avg_dvdx_int !!< Averaged interface $\partial v_i/\partial x$ (grid dir 1). - real(wp), dimension(3) :: avg_dvdy_int !!< Averaged interface $\partial v_i/\partial y$ (grid dir 2). - real(wp), dimension(3) :: avg_dvdz_int !!< Averaged interface $\partial v_i/\partial z$ (grid dir 3). - real(wp), dimension(3) :: vel_src_int !!< Interface velocity $(v_1,v_2,v_3)$ (grid directions) for viscous work. - real(wp), dimension(3) :: stress_vector_shear !!< Shear stress vector $(\sigma_{N1}, \sigma_{N2}, \sigma_{N3})$ on N-face (grid directions). + real(wp), dimension(3) :: avg_v_int !!< Averaged interface velocity (\f$v_x, v_y, v_z\f$) (grid directions). + real(wp), dimension(3) :: avg_dvdx_int !!< Averaged interface \f$\partial v_i/\partial x\f$ (grid dir 1). + real(wp), dimension(3) :: avg_dvdy_int !!< Averaged interface \f$\partial v_i/\partial y\f$ (grid dir 2). + real(wp), dimension(3) :: avg_dvdz_int !!< Averaged interface \f$\partial v_i/\partial z\f$ (grid dir 3). + real(wp), dimension(3) :: vel_src_int !!< Interface velocity (\f$v_1,v_2,v_3\f$) (grid directions) for viscous work. + real(wp), dimension(3) :: stress_vector_shear !!< Shear stress vector (\f$\sigma_{N1}, \sigma_{N2}, \sigma_{N3}\f$) on N-face (grid directions). #:else - real(wp), dimension(num_dims) :: avg_v_int !!< Averaged interface velocity $(v_x, v_y, v_z)$ (grid directions). - real(wp), dimension(num_dims) :: avg_dvdx_int !!< Averaged interface $\partial v_i/\partial x$ (grid dir 1). - real(wp), dimension(num_dims) :: avg_dvdy_int !!< Averaged interface $\partial v_i/\partial y$ (grid dir 2). - real(wp), dimension(num_dims) :: avg_dvdz_int !!< Averaged interface $\partial v_i/\partial z$ (grid dir 3). - real(wp), dimension(num_dims) :: vel_src_int !!< Interface velocity $(v_1,v_2,v_3)$ (grid directions) for viscous work. - real(wp), dimension(num_dims) :: stress_vector_shear !!< Shear stress vector $(\sigma_{N1}, \sigma_{N2}, \sigma_{N3})$ on N-face (grid directions). + real(wp), dimension(num_dims) :: avg_v_int !!< Averaged interface velocity (\f$v_x, v_y, v_z\f$) (grid directions). + real(wp), dimension(num_dims) :: avg_dvdx_int !!< Averaged interface \f$\partial v_i/\partial x\f$ (grid dir 1). + real(wp), dimension(num_dims) :: avg_dvdy_int !!< Averaged interface \f$\partial v_i/\partial y\f$ (grid dir 2). + real(wp), dimension(num_dims) :: avg_dvdz_int !!< Averaged interface \f$\partial v_i/\partial z\f$ (grid dir 3). + real(wp), dimension(num_dims) :: vel_src_int !!< Interface velocity (\f$v_1,v_2,v_3\f$) (grid directions) for viscous work. + real(wp), dimension(num_dims) :: stress_vector_shear !!< Shear stress vector (\f$\sigma_{N1}, \sigma_{N2}, \sigma_{N3}\f$) on N-face (grid directions). #:endif - real(wp) :: stress_normal_bulk !!< Normal bulk stress component $\sigma_{NN}$ on N-face. + real(wp) :: stress_normal_bulk !!< Normal bulk stress component \f$\sigma_{NN}\f$ on N-face. real(wp) :: Re_s, Re_b !!< Effective interface shear and bulk Reynolds numbers. real(wp) :: r_eff !!< Effective radius at interface for cylindrical terms. - real(wp) :: div_v_term_const !!< Common term $-(2/3)(\nabla \cdot \mathbf{v}) / \text{Re}_s$ for shear stress diagonal. - real(wp) :: divergence_cyl !!< Full divergence $\nabla \cdot \mathbf{v}$ in cylindrical coordinates. + real(wp) :: div_v_term_const !!< Common term \f$-(2/3)(\nabla \cdot \mathbf{v}) / \text{Re}_s\f$ for shear stress diagonal. + real(wp) :: divergence_cyl !!< Full divergence \f$\nabla \cdot \mathbf{v}\f$ in cylindrical coordinates. - integer :: j, k, l !!< Loop iterators for $x, y, z$ grid directions. + integer :: j, k, l !!< Loop iterators for \f$x, y, z\f$ grid directions. integer :: i_vel !!< Loop iterator for velocity components. - integer :: idx_rp(3) !!< Indices $(j,k,l)$ of 'right' point for averaging. + integer :: idx_rp(3) !!< Indices \f$(j,k,l)\f$ of 'right' point for averaging. $:GPU_PARALLEL_LOOP(collapse=3, private='[idx_rp, avg_v_int, avg_dvdx_int, avg_dvdy_int, avg_dvdz_int, Re_s, Re_b, vel_src_int, r_eff, divergence_cyl, stress_vector_shear, stress_normal_bulk, div_v_term_const]') do l = iz%beg, iz%end diff --git a/src/simulation/m_start_up.fpp b/src/simulation/m_start_up.fpp index 9a0ecd9f79..a4243b4418 100644 --- a/src/simulation/m_start_up.fpp +++ b/src/simulation/m_start_up.fpp @@ -1,5 +1,5 @@ !> -!! @file m_start_up.f90 +!! @file !! @brief Contains module m_start_up #:include 'case.fpp' diff --git a/src/simulation/m_time_steppers.fpp b/src/simulation/m_time_steppers.fpp index 274fb7ff7c..098888782a 100644 --- a/src/simulation/m_time_steppers.fpp +++ b/src/simulation/m_time_steppers.fpp @@ -1,5 +1,5 @@ !> -!! @file m_time_steppers.f90 +!! @file !! @brief Contains module m_time_steppers #:include 'macros.fpp' @@ -84,6 +84,7 @@ module m_time_steppers $:GPU_DECLARE(create='[q_cons_ts,q_prim_vf,q_T_sf,rhs_vf,q_prim_ts1,q_prim_ts2,rhs_mv,rhs_pb,max_dt,rk_coef,stor,bc_type]') +!> @cond #if defined(__NVCOMPILER_GPU_UNIFIED_MEM) real(stp), allocatable, dimension(:, :, :, :), pinned, target :: q_cons_ts_pool_host #elif defined(FRONTIER_UNIFIED) @@ -92,6 +93,7 @@ module m_time_steppers integer(kind=8) :: pool_size type(c_ptr) :: cptr_host, cptr_device #endif +!> @endcond contains @@ -129,6 +131,7 @@ contains @:PREFER_GPU(q_cons_ts(i)%vf) end do +!> @cond #if defined(__NVCOMPILER_GPU_UNIFIED_MEM) if (num_ts == 2 .and. nv_uvm_out_of_core) then ! host allocation for q_cons_ts(2)%vf(j)%sf for all j @@ -218,6 +221,7 @@ contains end do end do #else +!> @endcond do i = 1, num_ts do j = 1, sys_size @:ALLOCATE(q_cons_ts(i)%vf(j)%sf(idwbuff(1)%beg:idwbuff(1)%end, & @@ -226,7 +230,9 @@ contains end do @:ACC_SETUP_VFs(q_cons_ts(i)) end do +!> @cond #endif +!> @endcond ! Allocating the cell-average primitive ts variables if (probe_wrt) then diff --git a/src/simulation/m_viscous.fpp b/src/simulation/m_viscous.fpp index e81a243373..177b8c6bb4 100644 --- a/src/simulation/m_viscous.fpp +++ b/src/simulation/m_viscous.fpp @@ -1,5 +1,5 @@ !> -!! @file m_viscous.f90 +!! @file !! @brief Contains module m_viscous #:include 'case.fpp' #:include 'macros.fpp' diff --git a/src/simulation/m_weno.fpp b/src/simulation/m_weno.fpp index 32bd2a2d6e..962c171c83 100644 --- a/src/simulation/m_weno.fpp +++ b/src/simulation/m_weno.fpp @@ -1,5 +1,5 @@ !> -!! @file m_weno.f90 +!! @file !! @brief Contains module m_weno #:include 'case.fpp' #:include 'macros.fpp' diff --git a/src/simulation/p_main.fpp b/src/simulation/p_main.fpp index 29cb3b8281..e65722e191 100644 --- a/src/simulation/p_main.fpp +++ b/src/simulation/p_main.fpp @@ -1,5 +1,5 @@ !> -!! @file p_main.f90 +!! @file !! @brief Contains program p_main !> @brief Quasi-conservative, shock- and interface- capturing finite-volume diff --git a/toolchain/mfc/cli/docs_gen.py b/toolchain/mfc/cli/docs_gen.py index cf120fc07f..f568476081 100644 --- a/toolchain/mfc/cli/docs_gen.py +++ b/toolchain/mfc/cli/docs_gen.py @@ -5,10 +5,20 @@ in sync with the CLI schema definitions. """ +import re from typing import List from .schema import CLISchema, Command, Argument +def _escape_doxygen(text: str) -> str: + """Escape text for Doxygen markdown (avoid unintended refs/tags).""" + # Escape # followed by a letter (Doxygen interprets as section ref) + text = re.sub(r"#([a-zA-Z])", r"\#\1", text) + # Escape bare that aren't HTML (Doxygen treats as XML tag) + text = re.sub(r"<(?!/?(?:code|b|i|em|strong|br|details|summary|p|ul|li|ol|a|pre|table|tr|td|th|sup|sub|hr)\b)(\w+)>", r"\\<\1>", text) + return text + + def _format_argument_row(arg: Argument) -> str: """Format a single argument as a markdown table row.""" flags = [] @@ -20,8 +30,8 @@ def _format_argument_row(arg: Argument) -> str: # Format default value default_str = _format_default(arg.default) - # Escape pipes in help text - help_text = arg.help.replace("|", "\\|") + # Escape pipes and Doxygen-sensitive patterns in help text + help_text = _escape_doxygen(arg.help).replace("|", "\\|") return f"| {flag_str} | {help_text} | {default_str} |" @@ -128,7 +138,7 @@ def _generate_command_section(cmd: Command, schema: CLISchema) -> List[str]: lines = [] # Command header (no alias in heading to keep anchor simple) - lines.append(f"### {cmd.name}") + lines.append(f"### {cmd.name} {{#{cmd.name}}}") lines.append("") # Alias note if present @@ -234,7 +244,7 @@ def generate_cli_reference(schema: CLISchema) -> str: # Command categories core_commands = ["build", "run", "test", "clean", "validate"] utility_commands = ["new", "params", "packer", "completion", "generate", "help"] - dev_commands = ["lint", "format", "spelling", "count", "count_diff"] + dev_commands = ["lint", "format", "spelling", "precheck", "count", "count_diff"] ci_commands = ["bench", "bench_diff"] other_commands = ["load", "interactive"] diff --git a/toolchain/mfc/gen_case_constraints_docs.py b/toolchain/mfc/gen_case_constraints_docs.py index 982c50da01..d2398673ba 100644 --- a/toolchain/mfc/gen_case_constraints_docs.py +++ b/toolchain/mfc/gen_case_constraints_docs.py @@ -282,22 +282,22 @@ def render_playbook_card(entry: PlaybookEntry, summary: Dict[str, Any]) -> str: # Links lines.append("\n**Related Documentation:**") - lines.append(f"- [Model Equations (model_eqns = {summary['model_eqns']})](#-model-equations)") + lines.append(f"- [Model Equations (model_eqns = {summary['model_eqns']})](#model-equations)") if summary['riemann_solver']: - lines.append("- [Riemann Solvers](#️-riemann-solvers)") + lines.append("- [Riemann Solvers](#riemann-solvers)") if summary['bubbles_euler'] or summary['bubbles_lagrange']: - lines.append("- [Bubble Models](#-bubble-models)") + lines.append("- [Bubble Models](#bubble-models)") if summary['mhd']: - lines.append("- [MHD](#magnetohydrodynamics-mhd-mhd)") + lines.append("- [MHD](#compat-physics-models)") if summary['ib']: - lines.append("- [Immersed Boundaries](#immersed-boundaries-ib)") + lines.append("- [Immersed Boundaries](#compat-geometry)") if summary['viscous']: - lines.append("- [Viscosity](#viscosity-viscous)") + lines.append("- [Viscosity](#compat-physics-models)") lines.append("\n
\n") return "\n".join(lines) @@ -310,7 +310,7 @@ def generate_playbook() -> str: # Validate examples - will exit(1) if any are missing validate_playbook_examples() - lines.append("## 🧩 Case Design Playbook\n") + lines.append("## 🧩 Case Design Playbook {#case-design-playbook}\n") lines.append( "> **Learn by example:** The cases below are curated from MFC's `examples/` " "directory and are validated, working configurations. " @@ -382,7 +382,7 @@ def render_markdown(rules: Iterable[Rule]) -> str: # pylint: disable=too-many-l } # 1. Quick Start: Common Configurations - lines.append("## πŸš€ Common Configuration Patterns\n") + lines.append("## πŸš€ Common Configuration Patterns {#common-configuration-patterns}\n") lines.append("Start with these proven combinations:\n") lines.append("") lines.append("
") @@ -426,11 +426,12 @@ def render_markdown(rules: Iterable[Rule]) -> str: # pylint: disable=too-many-l lines.append("
\n") # 2. Feature Compatibility Matrix (simplified, no IGR column) - lines.append("## πŸ“Š Feature Compatibility\n") + lines.append("## πŸ“Š Feature Compatibility {#feature-compatibility}\n") lines.append("What works together:\n") for category, features in major_features.items(): # pylint: disable=too-many-nested-blocks - lines.append(f"\n### {category}\n") + cat_id = "compat-" + category.lower().replace(" ", "-") + lines.append(f"\n### {category} {{#{cat_id}}}\n") # Build compatibility info (exclude IGR from incompatibilities) compat_info = {} @@ -492,7 +493,7 @@ def render_markdown(rules: Iterable[Rule]) -> str: # pylint: disable=too-many-l lines.append("") # 3. Model Equations (data-driven from schema) - lines.append("## πŸ”’ Model Equations\n") + lines.append("## πŸ”’ Model Equations {#model-equations}\n") lines.append("Choose your governing equations:\n") lines.append("") @@ -561,7 +562,7 @@ def _format_model_requirements(val: int) -> str: 5: {"best_for": "Robust fallback", "requirements": "Not with cylindrical+viscous"}, } - lines.append("## βš™οΈ Riemann Solvers\n") + lines.append("## βš™οΈ Riemann Solvers {#riemann-solvers}\n") lines.append("| Solver | `riemann_solver` | Best For | Requirements |") lines.append("|--------|-----------------|----------|-------------|") @@ -577,7 +578,7 @@ def _format_model_requirements(val: int) -> str: # 5. Bubble Models (data-driven from schema dependencies + curated notes) if "bubbles_euler" in by_param or "bubbles_lagrange" in by_param: - lines.append("## πŸ’§ Bubble Models\n") + lines.append("## πŸ’§ Bubble Models {#bubble-models}\n") lines.append("") # Euler-Euler: inject schema dependency info (data-driven) @@ -618,7 +619,7 @@ def _format_model_requirements(val: int) -> str: lines.append("
\n") # 6. Condensed Parameter Reference (auto-collected from schema) - lines.append("## πŸ“– Quick Parameter Reference\n") + lines.append("## πŸ“– Quick Parameter Reference {#quick-parameter-reference}\n") lines.append("Key parameters and their constraints:\n") # Auto-collect all params that have CONSTRAINTS or DEPENDENCIES entries diff --git a/toolchain/mfc/lint_docs.py b/toolchain/mfc/lint_docs.py index f6318b8f03..783ac22c66 100644 --- a/toolchain/mfc/lint_docs.py +++ b/toolchain/mfc/lint_docs.py @@ -1,4 +1,4 @@ -"""Check that file paths, cite keys, and parameters in docs still exist.""" +"""Check that file paths, cite keys, parameters, and @ref targets in docs still exist.""" import re import sys @@ -34,6 +34,28 @@ r"|^[A-Z]" # constants/types (uppercase start) ) +# Backtick tokens in case.md that are not real parameters (analytical shorthands, +# stress tensor component names, prose identifiers, hardcoded constants) +CASE_MD_SKIP = { + # Analytical shorthand variables (stretching formulas, "Analytical Definition" table) + "eps", "lx", "ly", "lz", "xc", "yc", "zc", "x_cb", + # Stress tensor component names (descriptive, not params) + "tau_xx", "tau_xy", "tau_xz", "tau_yy", "tau_yz", "tau_zz", + # Prose identifiers (example names, math symbols) + "scaling", "c_h", "thickness", + # Hardcoded Fortran constants (not case-file params) + "init_dir", "zeros_default", +} + +# Docs to check for parameter references, with per-file skip sets +PARAM_DOCS = { + "docs/documentation/equations.md": set(), + "docs/documentation/case.md": CASE_MD_SKIP, +} + +# Match @ref page_id patterns +REF_RE = re.compile(r"@ref\s+(\w+)") + def check_docs(repo_root: Path) -> list[str]: """Check that file paths referenced in documentation still exist.""" @@ -50,7 +72,10 @@ def check_docs(repo_root: Path) -> list[str]: # Strip trailing punctuation that may have leaked in path_str = path_str.rstrip(".,;:!?") if not (repo_root / path_str).exists(): - errors.append(f" {doc} references '{path_str}' but it does not exist") + errors.append( + f" {doc} references '{path_str}' but it does not exist." + " Fix: update the path or remove the reference" + ) return errors @@ -79,17 +104,53 @@ def check_cite_keys(repo_root: Path) -> list[str]: for match in CITE_RE.finditer(text): key = match.group(1) if key.lower() not in valid_keys: - errors.append(f" {rel} uses \\cite {key} but no bib entry found") + errors.append( + f" {rel} uses \\cite {key} but no bib entry found." + " Fix: add entry to docs/references.bib or fix the key" + ) return errors -def check_param_refs(repo_root: Path) -> list[str]: - """Check that parameter names in equations.md exist in the MFC registry.""" - eq_path = repo_root / "docs" / "documentation" / "equations.md" - if not eq_path.exists(): - return [] +def _strip_code_blocks(text: str) -> str: + """Remove fenced code blocks (``` ... ```) from markdown text.""" + lines = text.split("\n") + result = [] + in_block = False + for line in lines: + if line.strip().startswith("```"): + in_block = not in_block + continue + if not in_block: + result.append(line) + return "\n".join(result) + + +def _is_valid_param(param: str, valid_params: set, sub_params: set) -> bool: + """Check if a param name (possibly with %) is valid against REGISTRY.""" + if "(" in param or ")" in param: + return True # Skip indexed refs like patch_icpp(i)%vel(j) + + base = param.split("%")[0] if "%" in param else param + + if base in valid_params or base in sub_params: + return True + + # Compound params (with %): validate both family prefix and attribute + if "%" in param: + sub = param.split("%")[-1] + family_ok = any(p.startswith(base + "%") for p in valid_params) + return family_ok and sub in sub_params + # Simple params: family prefix check at structural boundaries + if any(p.startswith(base + b) for b in ("(", "%", "_") for p in valid_params): + return True + + return False + + +def check_param_refs(repo_root: Path) -> list[str]: # pylint: disable=too-many-locals + """Check that parameter names in documentation exist in the MFC registry.""" # Import REGISTRY from the toolchain toolchain_dir = str(repo_root / "toolchain") if toolchain_dir not in sys.path: @@ -101,36 +162,184 @@ def check_param_refs(repo_root: Path) -> list[str]: return [] valid_params = set(REGISTRY.all_params.keys()) - # Build set of sub-parameter suffixes (the part after %) - sub_params = {p.split("%")[-1] for p in valid_params if "%" in p} - text = eq_path.read_text(encoding="utf-8") + # Build set of sub-parameter base names (strip trailing (N) indexes) + _sub_raw = {p.split("%")[-1] for p in valid_params if "%" in p} + sub_params = set() + for s in _sub_raw: + sub_params.add(s) + base = re.sub(r"\(\d+(?:,\s*\d+)*\)$", "", s) + if base != s: + sub_params.add(base) + errors = [] - seen = set() - for match in PARAM_RE.finditer(text): - param = match.group(1) - if param in seen: + for doc_rel, extra_skip in PARAM_DOCS.items(): + doc_path = repo_root / doc_rel + if not doc_path.exists(): continue - seen.add(param) - # Skip non-parameter identifiers - if PARAM_SKIP.search(param): - continue - # Skip single-character names (too ambiguous: m, n, p are grid dims) - if len(param) <= 1: - continue - # Skip names containing % (struct members like x_domain%beg are valid - # but the base name before % is what matters) - base = param.split("%")[0] if "%" in param else param - # Check for indexed parameters: strip trailing _N (e.g., patch_icpp(1)%alpha(1)) - # In docs these appear as e.g. `patch_icpp(i)%vel(j)` β€” skip indexed refs - if "(" in param or ")" in param: + text = _strip_code_blocks(doc_path.read_text(encoding="utf-8")) + seen = set() + + # Check plain params + for match in PARAM_RE.finditer(text): + param = match.group(1) + if param in seen: + continue + seen.add(param) + + if PARAM_SKIP.search(param): + continue + if len(param) <= 1: + continue + if param in extra_skip: + continue + if "(" in param or ")" in param: + continue + if "[" in param: + continue # Bracket shorthand (e.g., x[y,z]_domain%%beg[end]) + + # Normalize %% to % for lookup + normalized = param.replace("%%", "%") + if not _is_valid_param(normalized, valid_params, sub_params): + errors.append( + f" {doc_rel} references parameter '{param}' not in REGISTRY." + " Fix: check spelling or add to definitions.py" + ) + + return errors + + +def check_math_syntax(repo_root: Path) -> list[str]: + """Check that docs use Doxygen math syntax (\\f$, \\f[) not raw $$/$.""" + doc_dir = repo_root / "docs" / "documentation" + if not doc_dir.exists(): + return [] + + errors = [] + for md_file in sorted(doc_dir.glob("*.md")): + text = md_file.read_text(encoding="utf-8") + rel = md_file.relative_to(repo_root) + in_code = False + + for i, line in enumerate(text.split("\n"), 1): + if line.strip().startswith("```"): + in_code = not in_code + continue + if in_code: + continue + + # Strip inline code and Doxygen math before checking + cleaned = re.sub(r"`[^`\n]+`", "", line) + cleaned = re.sub(r"\\f\$.*?\\f\$", "", cleaned) + cleaned = re.sub(r"\\f\[.*?\\f\]", "", cleaned) + + if "$$" in cleaned: + errors.append( + f" {rel}:{i} uses $$...$$ display math." + " Fix: replace $$ with \\f[ and \\f]" + ) + continue + + for m in re.finditer(r"\$([^$\n]+?)\$", cleaned): + if re.search(r"\\[a-zA-Z]", m.group(1)): + errors.append( + f" {rel}:{i} uses $...$ with LaTeX commands." + " Fix: replace $ delimiters with \\f$ and \\f$" + ) + break # one error per line + + return errors + + +def _gitignored_docs(repo_root: Path) -> set[str]: + """Return set of gitignored doc file basenames.""" + import subprocess # pylint: disable=import-outside-toplevel + + doc_dir = repo_root / "docs" / "documentation" + try: + result = subprocess.run( + ["git", "ls-files", "--ignored", "--exclude-standard", "-o"], + capture_output=True, text=True, cwd=repo_root, check=False, + ) + return { + Path(f).name for f in result.stdout.splitlines() + if f.startswith(str(doc_dir.relative_to(repo_root))) + } + except FileNotFoundError: + return set() + + +def check_section_anchors(repo_root: Path) -> list[str]: + """Check that markdown ](#id) links have matching {#id} definitions.""" + doc_dir = repo_root / "docs" / "documentation" + if not doc_dir.exists(): + return [] + + ignored = _gitignored_docs(repo_root) + + errors = [] + for md_file in sorted(doc_dir.glob("*.md")): + if md_file.name in ignored: continue + text = md_file.read_text(encoding="utf-8") + rel = md_file.relative_to(repo_root) + + # Collect all {#id} anchors (outside code blocks) + anchors = set() + in_code = False + for line in text.split("\n"): + if line.strip().startswith("```"): + in_code = not in_code + continue + if not in_code: + anchors.update(re.findall(r"\{#([\w-]+)\}", line)) + + # Check all ](#id) links + in_code = False + for i, line in enumerate(text.split("\n"), 1): + if line.strip().startswith("```"): + in_code = not in_code + continue + if in_code: + continue + for m in re.finditer(r"\]\(#([\w-]+)\)", line): + if m.group(1) not in anchors: + errors.append( + f" {rel}:{i} links to #{m.group(1)}" + f" but no {{#{m.group(1)}}} anchor exists." + f" Fix: add {{#{m.group(1)}}} to the target" + " section header" + ) + + return errors + - if base not in valid_params and base not in sub_params: - # Check if it's a known parameter family prefix - if not any(p.startswith(base) for p in valid_params): - errors.append(f" equations.md references parameter '{param}' not in REGISTRY") +def check_page_refs(repo_root: Path) -> list[str]: + """Check that @ref targets in docs reference existing page identifiers.""" + doc_dir = repo_root / "docs" / "documentation" + if not doc_dir.exists(): + return [] + + # Collect all @page identifiers + page_ids = {"citelist"} # Doxygen built-in + for md_file in doc_dir.glob("*.md"): + text = md_file.read_text(encoding="utf-8") + m = re.search(r"^\s*@page\s+(\w+)", text, flags=re.MULTILINE) + if m: + page_ids.add(m.group(1)) + + errors = [] + for md_file in sorted(doc_dir.glob("*.md")): + text = _strip_code_blocks(md_file.read_text(encoding="utf-8")) + rel = md_file.relative_to(repo_root) + for match in REF_RE.finditer(text): + ref_target = match.group(1) + if ref_target not in page_ids: + errors.append( + f" {rel} uses @ref {ref_target} but no @page with that ID exists." + " Fix: check the page ID or add @page declaration" + ) return errors @@ -142,6 +351,9 @@ def main(): all_errors.extend(check_docs(repo_root)) all_errors.extend(check_cite_keys(repo_root)) all_errors.extend(check_param_refs(repo_root)) + all_errors.extend(check_page_refs(repo_root)) + all_errors.extend(check_math_syntax(repo_root)) + all_errors.extend(check_section_anchors(repo_root)) if all_errors: print("Doc reference check failed:") diff --git a/toolchain/mfc/params/definitions.py b/toolchain/mfc/params/definitions.py index c08249c3d8..104f3dcfc3 100644 --- a/toolchain/mfc/params/definitions.py +++ b/toolchain/mfc/params/definitions.py @@ -808,7 +808,7 @@ def get_value_label(param_name: str, value: int) -> str: }, } -def _r(name, ptype, tags=None, desc=None, hint=None): +def _r(name, ptype, tags=None, desc=None, hint=None, math=None): # pylint: disable=too-many-arguments,too-many-positional-arguments """Register a parameter with optional feature tags and description.""" if hint is None: hint = _lookup_hint(name) @@ -827,6 +827,7 @@ def _r(name, ptype, tags=None, desc=None, hint=None): dependencies=DEPENDENCIES.get(name), tags=tags if tags else set(), hint=hint, + math_symbol=math or "", )) @@ -857,7 +858,9 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements for n in ["time_stepper", "t_step_old", "t_step_start", "t_step_stop", "t_step_save", "t_step_print", "adap_dt_max_iters"]: _r(n, INT, {"time"}) - for n in ["dt", "cfl_target", "cfl_max", "t_tol", "adap_dt_tol", "t_stop", "t_save"]: + _r("dt", REAL, {"time"}, math=r"\f$\Delta t\f$") + _r("cfl_target", REAL, {"time"}, math=r"\f$\mathrm{CFL}\f$") + for n in ["cfl_max", "t_tol", "adap_dt_tol", "t_stop", "t_save"]: _r(n, REAL, {"time"}) for n in ["cfl_adap_dt", "cfl_const_dt", "cfl_dt", "adap_dt"]: _r(n, LOG, {"time"}) @@ -867,8 +870,9 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements _r("recon_type", INT) _r("muscl_order", INT) _r("muscl_lim", INT) - for n in ["weno_eps", "teno_CT", "wenoz_q"]: - _r(n, REAL, {"weno"}) + _r("weno_eps", REAL, {"weno"}, math=r"\f$\varepsilon\f$") + _r("teno_CT", REAL, {"weno"}, math=r"\f$C_T\f$") + _r("wenoz_q", REAL, {"weno"}) for n in ["mapped_weno", "wenoz", "teno", "weno_avg", "mp_weno", "null_weights"]: _r(n, LOG, {"weno"}) _r("weno_Re_flux", LOG, {"weno", "viscosity"}) @@ -878,16 +882,18 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements _r(n, INT, {"riemann"}) # --- MHD --- - _r("Bx0", REAL, {"mhd"}) - for n in ["hyper_cleaning_speed", "hyper_cleaning_tau"]: - _r(n, REAL, {"mhd"}) + _r("Bx0", REAL, {"mhd"}, math=r"\f$B_{x,0}\f$") + _r("hyper_cleaning_speed", REAL, {"mhd"}, math=r"\f$c_h\f$") + _r("hyper_cleaning_tau", REAL, {"mhd"}) for n in ["mhd", "hyper_cleaning", "powell"]: _r(n, LOG, {"mhd"}) # --- Bubbles --- - for n in ["R0ref", "nb", "Web", "Ca"]: - _r(n, REAL, {"bubbles"}) - _r("Re_inv", REAL, {"bubbles", "viscosity"}) + _r("R0ref", REAL, {"bubbles"}, math=r"\f$R_0\f$") + _r("nb", REAL, {"bubbles"}, math=r"\f$N_b\f$") + _r("Web", REAL, {"bubbles"}, math=r"\f$\mathrm{We}\f$") + _r("Ca", REAL, {"bubbles"}, math=r"\f$\mathrm{Ca}\f$") + _r("Re_inv", REAL, {"bubbles", "viscosity"}, math=r"\f$\mathrm{Re}^{-1}\f$") _r("bubble_model", INT, {"bubbles"}) for n in ["polytropic", "bubbles_euler", "polydisperse", "qbmm", "bubbles_lagrange"]: _r(n, LOG, {"bubbles"}) @@ -900,7 +906,7 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements _r(n, LOG, {"elasticity"}) # --- Surface tension --- - _r("sigma", REAL, {"surface_tension"}) + _r("sigma", REAL, {"surface_tension"}, math=r"\f$\sigma\f$") _r("surface_tension", LOG, {"surface_tension"}) # --- Chemistry --- @@ -959,10 +965,16 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements "num_igr_warm_start_iters", "igr_iter_solver", "nv_uvm_igr_temps_on_gpu", "flux_lim"]: _r(n, INT) - for n in ["pref", "poly_sigma", "rhoref", "mixlayer_vel_coef", "mixlayer_domain", - "mixlayer_perturb_k0", "perturb_flow_mag", "fluid_rho", "sigR", "sigV", - "rhoRV", "palpha_eps", "ptgalpha_eps", "pi_fac", "tau_star", - "cont_damage_s", "alpha_bar", "alf_factor", "ic_eps", "ic_beta"]: + _r("pref", REAL, math=r"\f$p_\text{ref}\f$") + _r("poly_sigma", REAL, math=r"\f$\sigma_\text{poly}\f$") + _r("rhoref", REAL, math=r"\f$\rho_\text{ref}\f$") + _r("palpha_eps", REAL, math=r"\f$\varepsilon_\alpha\f$") + _r("ptgalpha_eps", REAL, math=r"\f$\varepsilon_\alpha\f$") + _r("pi_fac", REAL, math=r"\f$\pi\text{-factor}\f$") + for n in ["mixlayer_vel_coef", "mixlayer_domain", "mixlayer_perturb_k0", + "perturb_flow_mag", "fluid_rho", "sigR", "sigV", "rhoRV", + "tau_star", "cont_damage_s", "alpha_bar", "alf_factor", + "ic_eps", "ic_beta"]: _r(n, REAL) for n in ["mpp_lim", "relax", "adv_n", "cont_damage", "igr", "down_sample", "old_grid", "old_ic", "mixlayer_vel_profile", "mixlayer_perturb", @@ -974,8 +986,10 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements # Body force for d in ["x", "y", "z"]: - for v in ["k", "w", "p", "g"]: - _r(f"{v}_{d}", REAL) + _r(f"g_{d}", REAL, math=r"\f$g_" + d + r"\f$") + _r(f"k_{d}", REAL, math=r"\f$k_" + d + r"\f$") + _r(f"w_{d}", REAL, math=r"\f$\omega_" + d + r"\f$") + _r(f"p_{d}", REAL, math=r"\f$\phi_" + d + r"\f$") _r(f"bf_{d}", LOG) # ========================================================================== @@ -989,20 +1003,23 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements _r(f"{px}{a}", INT) for a in ["smoothen", "alter_patch"] if i >= 2 else ["smoothen"]: _r(f"{px}{a}", LOG) + for a, sym in [("rho", r"\f$\rho\f$"), ("gamma", r"\f$\gamma\f$"), + ("pi_inf", r"\f$\pi_\infty\f$"), ("cv", r"\f$c_v\f$"), + ("qv", r"\f$q_v\f$"), ("qvp", r"\f$q'_v\f$")]: + _r(f"{px}{a}", REAL, math=sym) for a in ["radius", "radii", "epsilon", "beta", "normal", "alpha_rho", - "non_axis_sym", "smooth_coeff", "rho", "vel", "alpha", "gamma", - "pi_inf", "cv", "qv", "qvp", "model_threshold"]: + "non_axis_sym", "smooth_coeff", "vel", "alpha", "model_threshold"]: _r(f"{px}{a}", REAL) # Bubble fields for a in ["r0", "v0", "p0", "m0"]: _r(f"{px}{a}", REAL, {"bubbles"}) for j in range(2, 10): _r(f"{px}a({j})", REAL) - _r(f"{px}pres", A_REAL) + _r(f"{px}pres", A_REAL, math=r"\f$p\f$") _r(f"{px}cf_val", A_REAL) # MHD fields - for a in ["Bx", "By", "Bz"]: - _r(f"{px}{a}", A_REAL, {"mhd"}) + for a, sym in [("Bx", r"\f$B_x\f$"), ("By", r"\f$B_y\f$"), ("Bz", r"\f$B_z\f$")]: + _r(f"{px}{a}", A_REAL, {"mhd"}, math=sym) # Chemistry species for j in range(1, 101): _r(f"{px}Y({j})", A_REAL, {"chemistry"}) @@ -1016,13 +1033,13 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements for j in range(1, 4): _r(f"{px}radii({j})", REAL) _r(f"{px}normal({j})", REAL) - _r(f"{px}vel({j})", A_REAL) + _r(f"{px}vel({j})", A_REAL, math=r"\f$u_" + str(j) + r"\f$") for f in range(1, NF + 1): - _r(f"{px}alpha({f})", A_REAL) - _r(f"{px}alpha_rho({f})", A_REAL) + _r(f"{px}alpha({f})", A_REAL, math=r"\f$\alpha_" + str(f) + r"\f$") + _r(f"{px}alpha_rho({f})", A_REAL, math=r"\f$\alpha \rho\f$") # Elasticity stress tensor for j in range(1, 7): - _r(f"{px}tau_e({j})", A_REAL, {"elasticity"}) + _r(f"{px}tau_e({j})", A_REAL, {"elasticity"}, math=r"\f$\tau_e\f$") if i >= 2: for j in range(1, i): _r(f"{px}alter_patch({j})", LOG) @@ -1030,21 +1047,30 @@ def _load(): # pylint: disable=too-many-locals,too-many-statements # --- fluid_pp (10 fluids) --- for f in range(1, NF + 1): px = f"fluid_pp({f})%" - for a in ["gamma", "pi_inf", "cv", "qv", "qvp"]: - _r(f"{px}{a}", REAL) - _r(f"{px}mul0", REAL, {"viscosity"}) - _r(f"{px}ss", REAL, {"surface_tension"}) + for a, sym in [("gamma", r"\f$\gamma_k\f$"), ("pi_inf", r"\f$\pi_{\infty,k}\f$"), + ("cv", r"\f$c_{v,k}\f$"), ("qv", r"\f$q_{v,k}\f$"), + ("qvp", r"\f$q'_{v,k}\f$")]: + _r(f"{px}{a}", REAL, math=sym) + _r(f"{px}mul0", REAL, {"viscosity"}, math=r"\f$\mu_{l,k}\f$") + _r(f"{px}ss", REAL, {"surface_tension"}, math=r"\f$\sigma_k\f$") for a in ["pv", "gamma_v", "M_v", "mu_v", "k_v", "cp_v", "D_v"]: _r(f"{px}{a}", REAL, {"bubbles"}) - _r(f"{px}G", REAL, {"elasticity"}) - for j in [1, 2]: - _r(f"{px}Re({j})", REAL, {"viscosity"}) + _r(f"{px}G", REAL, {"elasticity"}, math=r"\f$G_k\f$") + _r(f"{px}Re(1)", REAL, {"viscosity"}, math=r"\f$\mathrm{Re}_k\f$ (shear)") + _r(f"{px}Re(2)", REAL, {"viscosity"}, math=r"\f$\mathrm{Re}_k\f$ (bulk)") # --- bub_pp (bubble properties) --- - for a in ["R0ref", "p0ref", "rho0ref", "T0ref", "ss", "pv", "vd", - "mu_l", "mu_v", "mu_g", "gam_v", "gam_g", - "M_v", "M_g", "k_v", "k_g", "cp_v", "cp_g", "R_v", "R_g"]: - _r(f"bub_pp%{a}", REAL, {"bubbles"}) + for a, sym in [("R0ref", r"\f$R_0\f$"), ("p0ref", r"\f$p_0\f$"), + ("rho0ref", r"\f$\rho_l\f$"), ("T0ref", r"\f$T_0\f$"), + ("ss", r"\f$\sigma\f$"), ("pv", r"\f$p_v\f$"), + ("vd", r"\f$D\f$"), ("mu_l", r"\f$\mu_l\f$"), + ("mu_v", r"\f$\mu_v\f$"), ("mu_g", r"\f$\mu_g\f$"), + ("gam_v", r"\f$\gamma_v\f$"), ("gam_g", r"\f$\gamma_g\f$"), + ("M_v", r"\f$M_v\f$"), ("M_g", r"\f$M_g\f$"), + ("k_v", r"\f$k_v\f$"), ("k_g", r"\f$k_g\f$"), + ("cp_v", r"\f$c_{p,v}\f$"), ("cp_g", r"\f$c_{p,g}\f$"), + ("R_v", r"\f$R_v\f$"), ("R_g", r"\f$R_g\f$")]: + _r(f"bub_pp%{a}", REAL, {"bubbles"}, math=sym) # --- patch_ib (10 immersed boundaries) --- for i in range(1, NI + 1): diff --git a/toolchain/mfc/params/descriptions.py b/toolchain/mfc/params/descriptions.py index b689e3a536..af437c28a2 100644 --- a/toolchain/mfc/params/descriptions.py +++ b/toolchain/mfc/params/descriptions.py @@ -638,6 +638,17 @@ def get_pattern_description(pattern_name: str) -> str: return desc +def get_math_symbol(param_name: str) -> str: + """Get the LaTeX math symbol for a parameter, if one is defined. + + Looks up the math_symbol field from the parameter registry (single source of truth). + Symbols are defined via math= in the _r() calls in definitions.py. + """ + from . import REGISTRY # pylint: disable=import-outside-toplevel + param = REGISTRY.all_params.get(param_name) + return param.math_symbol if param else "" + + # Feature group descriptions (for display purposes) # The actual parameter-to-tag mapping is in definitions.py (single source of truth) FEATURE_DESCRIPTIONS = { diff --git a/toolchain/mfc/params/generators/docs_gen.py b/toolchain/mfc/params/generators/docs_gen.py index 6849c8a01d..b982de610a 100644 --- a/toolchain/mfc/params/generators/docs_gen.py +++ b/toolchain/mfc/params/generators/docs_gen.py @@ -11,7 +11,7 @@ from ..schema import ParamType from ..registry import REGISTRY -from ..descriptions import get_description +from ..descriptions import get_description, get_math_symbol from ..ast_analyzer import analyze_case_validator, classify_message from .. import definitions # noqa: F401 pylint: disable=unused-import @@ -421,7 +421,7 @@ def generate_parameter_docs() -> str: # pylint: disable=too-many-locals,too-man # Document each family for family, params in sorted_families: - lines.append(f"## {family}") + lines.append(f"## {family} {{#{family}}}") lines.append("") desc = family_descriptions.get(family, "") @@ -441,25 +441,29 @@ def generate_parameter_docs() -> str: # pylint: disable=too-many-locals,too-man # Use pattern view if it reduces rows, otherwise show full table if len(patterns) < len(params): # Pattern view - shows collapsed patterns - # Check if any member of a pattern has constraints + # Check if any member of a pattern has constraints or math symbols pattern_has_constraints = False + pattern_has_symbols = False for _pattern, examples in patterns.items(): for ex in examples: p = REGISTRY.all_params[ex] if p.constraints or ex in by_trigger or ex in by_param: pattern_has_constraints = True - break - if pattern_has_constraints: + if get_math_symbol(ex): + pattern_has_symbols = True + if pattern_has_constraints and pattern_has_symbols: break lines.append("### Patterns") lines.append("") + # Build header dynamically based on which optional columns are needed + cols = ["Pattern", "Example", "Description"] + if pattern_has_symbols: + cols.append("Symbol") if pattern_has_constraints: - lines.append("| Pattern | Example | Description | Constraints |") - lines.append("|---------|---------|-------------|-------------|") - else: - lines.append("| Pattern | Example | Description |") - lines.append("|---------|---------|-------------|") + cols.append("Constraints") + lines.append("| " + " | ".join(cols) + " |") + lines.append("| " + " | ".join("-" * max(3, len(c)) for c in cols) + " |") for pattern, examples in sorted(patterns.items()): example = examples[0] @@ -471,6 +475,10 @@ def generate_parameter_docs() -> str: # pylint: disable=too-many-locals,too-man pattern_escaped = _escape_percent(pattern) example_escaped = _escape_percent(example) desc = _escape_percent(desc) + row = f"| `{pattern_escaped}` | `{example_escaped}` | {desc}" + if pattern_has_symbols: + sym = get_math_symbol(example) + row += f" | {sym}" if pattern_has_constraints: p = REGISTRY.all_params[example] constraints = _format_constraints(p) @@ -479,15 +487,21 @@ def generate_parameter_docs() -> str: # pylint: disable=too-many-locals,too-man if not extra: extra = _format_tag_annotation(example, p) extra = _escape_pct_outside_backticks(extra) - lines.append(f"| `{pattern_escaped}` | `{example_escaped}` | {desc} | {extra} |") - else: - lines.append(f"| `{pattern_escaped}` | `{example_escaped}` | {desc} |") + row += f" | {extra}" + lines.append(row + " |") lines.append("") else: # Full table - no patterns to collapse - lines.append("| Parameter | Type | Description | Constraints |") - lines.append("|-----------|------|-------------|-------------|") + # Check if any param in this family has a math symbol + full_has_symbols = any(get_math_symbol(n) for n, _ in params) + + cols = ["Parameter", "Type", "Description"] + if full_has_symbols: + cols.append("Symbol") + cols.append("Constraints") + lines.append("| " + " | ".join(cols) + " |") + lines.append("| " + " | ".join("-" * max(3, len(c)) for c in cols) + " |") for name, param in params: type_str = _type_to_str(param.param_type) @@ -504,7 +518,12 @@ def generate_parameter_docs() -> str: # pylint: disable=too-many-locals,too-man # Escape % for Doxygen (even inside backtick code spans) name_escaped = _escape_percent(name) desc = _escape_percent(desc) - lines.append(f"| `{name_escaped}` | {type_str} | {desc} | {extra} |") + row = f"| `{name_escaped}` | {type_str} | {desc}" + if full_has_symbols: + sym = get_math_symbol(name) + row += f" | {sym}" + row += f" | {extra}" + lines.append(row + " |") lines.append("") diff --git a/toolchain/mfc/params/schema.py b/toolchain/mfc/params/schema.py index 8999dc903a..08ef309254 100644 --- a/toolchain/mfc/params/schema.py +++ b/toolchain/mfc/params/schema.py @@ -61,6 +61,7 @@ class ParamDef: # pylint: disable=too-many-instance-attributes dependencies: Optional[Dict[str, Any]] = None # {"requires": [...], "recommends": [...]} tags: Set[str] = field(default_factory=set) # Feature tags: "mhd", "bubbles", etc. hint: str = "" # Constraint/usage hint for docs (e.g. "Used with grcbc_in") + math_symbol: str = "" # LaTeX math symbol (Doxygen format, e.g. "\\f$\\gamma_k\\f$") def __post_init__(self): # Validate name