diff --git a/.gitignore b/.gitignore index 1d95edb..48f9cd7 100644 --- a/.gitignore +++ b/.gitignore @@ -63,3 +63,6 @@ target/ .*.sw[op] + +*.svg +*.html diff --git a/make_docs.sh b/make_docs.sh index f2f2fe2..a29558c 100755 --- a/make_docs.sh +++ b/make_docs.sh @@ -1,3 +1,15 @@ #!/bin/bash cd ~/projects/meanas -pdoc3 --html --force --template-dir pdoc_templates -o doc . + +# Approach 1: pdf to html? +#pdoc3 --pdf --force --template-dir pdoc_templates -o doc . | \ +# pandoc --metadata=title:"meanas" --toc --toc-depth=4 --from=markdown+abbreviations --to=html --output=doc.html --gladtex -s - + +# Approach 2: pdf to html with gladtex +pdoc3 --pdf --force --template-dir pdoc_templates -o doc . > doc.md +pandoc --metadata=title:"meanas" --from=markdown+abbreviations --to=html --output=doc.html --gladtex -s --css pdoc_templates/pdoc.css doc.md +gladtex -a -n -d _doc_mathimg -c white doc.html + +# Approach 3: html with gladtex +#pdoc3 --html --force --template-dir pdoc_templates -o doc . +#find doc -iname '*.html' -exec gladtex -a -n -d _mathimg -c white {} \; diff --git a/meanas/fdfd/__init__.py b/meanas/fdfd/__init__.py index c9eba8c..3e9463e 100644 --- a/meanas/fdfd/__init__.py +++ b/meanas/fdfd/__init__.py @@ -14,7 +14,20 @@ Submodules: - `waveguide_3d`: Functions for transforming `waveguide_2d` results into 3D. -=========== +================================================================ + +From the "Frequency domain" section of `meanas.fdmath`, we have + +$$ + \\begin{aligned} + \\tilde{E}_{l, \\vec{r}} &= \\tilde{E}_{\\vec{r}} e^{-\\imath \\omega l \\Delta_t} \\\\ + \\tilde{J}_{l, \\vec{r}} &= \\tilde{J}_{\\vec{r}} e^{-\\imath \\omega (l - \\frac{1}{2}) \\Delta_t} \\\\ + \\hat{\\nabla} \\times (\\mu^{-1}_{\\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_{\\vec{r}}) + -\\Omega^2 \\epsilon_{\\vec{r}} \\cdot \\tilde{E}_{\\vec{r}} &= \\imath \\Omega \\tilde{J}_{\\vec{r}} \\\\ + \\Omega &= 2 \\sin(\\omega \\Delta_t / 2) / \\Delta_t + \\end{aligned} +$$ + # TODO FDFD? # TODO PML diff --git a/meanas/fdfd/functional.py b/meanas/fdfd/functional.py index d995e7b..33ed134 100644 --- a/meanas/fdfd/functional.py +++ b/meanas/fdfd/functional.py @@ -185,8 +185,8 @@ def e_tfsf_source(TF_region: fdfield_t, def poynting_e_cross_h(dxes: dx_lists_t) -> Callable[[fdfield_t, fdfield_t], fdfield_t]: """ Generates a function that takes the single-frequency `E` and `H` fields - and calculates the cross product `E` x `H` = \\( E \\times H \\) as required - for the Poynting vector, \\( S = E \\times H \\) + and calculates the cross product `E` x `H` = $E \\times H$ as required + for the Poynting vector, $S = E \\times H$ Note: This function also shifts the input `E` field by one cell as required diff --git a/meanas/fdfd/waveguide_2d.py b/meanas/fdfd/waveguide_2d.py index abd9935..4113f8d 100644 --- a/meanas/fdfd/waveguide_2d.py +++ b/meanas/fdfd/waveguide_2d.py @@ -12,82 +12,82 @@ As the z-dependence is known, all the functions in this file assume a 2D grid Consider Maxwell's equations in continuous space, in the frequency domain. Assuming a structure with some (x, y) cross-section extending uniformly into the z dimension, -with a diagonal \\( \\epsilon \\) tensor, we have +with a diagonal $\\epsilon$ tensor, we have $$ -\\begin{align*} +\\begin{aligned} \\nabla \\times \\vec{E}(x, y, z) &= -\\imath \\omega \\mu \\vec{H} \\\\ \\nabla \\times \\vec{H}(x, y, z) &= \\imath \\omega \\epsilon \\vec{E} \\\\ \\vec{E}(x,y,z) = (\\vec{E}_t(x, y) + E_z(x, y)\\vec{z}) e^{-\\gamma z} \\\\ \\vec{H}(x,y,z) = (\\vec{H}_t(x, y) + H_z(x, y)\\vec{z}) e^{-\\gamma z} \\\\ -\\end{align*} +\\end{aligned} $$ Expanding the first two equations into vector components, we get $$ -\\begin{align*} +\\begin{aligned} -\\imath \\omega \\mu_{xx} H_x &= \\partial_y E_z - \\partial_z E_y \\\\ -\\imath \\omega \\mu_{yy} H_y &= \\partial_z E_x - \\partial_x E_z \\\\ -\\imath \\omega \\mu_{zz} H_z &= \\partial_x E_y - \\partial_y E_x \\\\ \\imath \\omega \\epsilon_{xx} E_x &= \\partial_y H_z - \\partial_z H_y \\\\ \\imath \\omega \\epsilon_{yy} E_y &= \\partial_z H_x - \\partial_x H_z \\\\ \\imath \\omega \\epsilon_{zz} E_z &= \\partial_x H_y - \\partial_y H_x \\\\ -\\end{align*} +\\end{aligned} $$ -Substituting in our expressions for \\( \\vec{E}, \\vec{H} \\) and discretizing: +Substituting in our expressions for $\\vec{E}$, $\\vec{H}$ and discretizing: $$ -\\begin{align*} +\\begin{aligned} -\\imath \\omega \\mu_{xx} H_x &= \\tilde{\\partial}_y E_z + \\gamma E_y \\\\ -\\imath \\omega \\mu_{yy} H_y &= -\\gamma E_x - \\tilde{\\partial}_x E_z \\\\ -\\imath \\omega \\mu_{zz} H_z &= \\tilde{\\partial}_x E_y - \\tilde{\\partial}_y E_x \\\\ \\imath \\omega \\epsilon_{xx} E_x &= \\hat{\\partial}_y H_z + \\gamma H_y \\\\ \\imath \\omega \\epsilon_{yy} E_y &= -\\gamma H_x - \\hat{\\partial}_x H_z \\\\ \\imath \\omega \\epsilon_{zz} E_z &= \\hat{\\partial}_x H_y - \\hat{\\partial}_y H_x \\\\ -\\end{align*} +\\end{aligned} $$ Rewrite the last three equations as $$ -\\begin{align*} +\\begin{aligned} \\gamma H_y &= \\imath \\omega \\epsilon_{xx} E_x - \\hat{\\partial}_y H_z \\\\ \\gamma H_x &= -\\imath \\omega \\epsilon_{yy} E_y - \\hat{\\partial}_x H_z \\\\ \\imath \\omega E_z &= \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_x H_y - \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_y H_x \\\\ -\\end{align*} +\\end{aligned} $$ -Now apply \\( \\gamma \\tilde{\\partial}_x \\) to the last equation, -then substitute in for \\( \\gamma H_x \\) and \\( \\gamma H_y \\): +Now apply $\\gamma \\tilde{\\partial}_x$ to the last equation, +then substitute in for $\\gamma H_x$ and $\\gamma H_y$: $$ -\\begin{align*} +\\begin{aligned} \\gamma \\tilde{\\partial}_x \\imath \\omega E_z &= \\gamma \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_x H_y - \\gamma \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_y H_x \\\\ - &= \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_x ( \\imath \\omega \\epsilon{xx} E_x - \\hat{\\partial}_y H_z) - - \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_y (-\\imath \\omega \\epsilon{yy} E_y - \\hat{\\partial}_x H_z) \\\\ - &= \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_x ( \\imath \\omega \\epsilon{xx} E_x) - - \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_y (-\\imath \\omega \\epsilon{yy} E_y) \\\\ + &= \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_x ( \\imath \\omega \\epsilon_{xx} E_x - \\hat{\\partial}_y H_z) + - \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_y (-\\imath \\omega \\epsilon_{yy} E_y - \\hat{\\partial}_x H_z) \\\\ + &= \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_x ( \\imath \\omega \\epsilon_{xx} E_x) + - \\tilde{\\partial}_x \\frac{1}{\\epsilon_{zz}} \\hat{\\partial}_y (-\\imath \\omega \\epsilon_{yy} E_y) \\\\ \\gamma \\tilde{\\partial}_x E_z &= \\tilde{\\partial}_x \\frac{1}{\\epsilon_zz} \\hat{\\partial}_x (\\epsilon_{xx} E_x) \\tilde{\\partial}_x \\frac{1}{\\epsilon_zz} \\hat{\\partial}_y (\\epsilon_{yy} E_y) \\\\ -\\end{align*} +\\end{aligned} $$ -With a similar approach (but using \\( \\gamma \\tilde{\\partial}_y \\) instead), we can get +With a similar approach (but using $\\gamma \\tilde{\\partial}_y$ instead), we can get $$ -\\begin{align*} +\\begin{aligned} \\gamma \\tilde{\\partial}_y E_z &= \\tilde{\\partial}_y \\frac{1}{\\epsilon_zz} \\hat{\\partial}_x (\\epsilon_{xx} E_x) \\tilde{\\partial}_y \\frac{1}{\\epsilon_zz} \\hat{\\partial}_y (\\epsilon_{yy} E_y) \\\\ -\\end{align*} +\\end{aligned} $$ -We can combine this equation for \\( \\gamma \\tilde{\\partial}_y E_z \\) with -the unused \\( \\imath \\omega \\mu_{xx} H_z \\) and \\( \\imath \\omega \\mu_{yy} H_y \\) equations to get +We can combine this equation for $\\gamma \\tilde{\\partial}_y E_z$ with +the unused $\\imath \\omega \\mu_{xx} H_z$ and $\\imath \\omega \\mu_{yy} H_y$ equations to get $$ -\\begin{align*} +\\begin{aligned} -\\imath \\omega \\mu_{xx} \\gamma H_x &= \\gamma^2 E_y + \\tilde{\\partial}_y ( \\tilde{\\partial}_x \\frac{1}{\\epsilon_zz} \\hat{\\partial}_x (\\epsilon_{xx} E_x) + \\tilde{\\partial}_x \\frac{1}{\\epsilon_zz} \\hat{\\partial}_y (\\epsilon_{yy} E_y) @@ -96,30 +96,30 @@ $$ \\tilde{\\partial}_y \\frac{1}{\\epsilon_zz} \\hat{\\partial}_x (\\epsilon_{xx} E_x) + \\tilde{\\partial}_y \\frac{1}{\\epsilon_zz} \\hat{\\partial}_y (\\epsilon_{yy} E_y) )\\\\ -\\end{align*} +\\end{aligned} $$ -However, based on our rewritten equation for \\( \\gamma H_x \\) and the so-far unused -equation for \\( \\imath \\omega \\mu_{zz} H_z \\) we can also write +However, based on our rewritten equation for $\\gamma H_x$ and the so-far unused +equation for $\\imath \\omega \\mu_{zz} H_z$ we can also write $$ -\\begin{align*} +\\begin{aligned} -\\imath \\omega \\mu_{xx} (\\gamma H_x) &= -\\imath \\omega \\mu_{xx} (-\\imath \\omega \\epsilon_{yy} E_y - \\hat{\\partial}_x H_z) \\\\ &= -\\omega^2 \\mu_{xx} \\epsilon_{yy} E_y -\\imath \\omega \\mu_{xx} \\hat{\\partial}_x ( \\frac{1}{-\\imath \\omega \\mu_{zz}} (\\tilde{\\partial}_x E_y - \\tilde{\\partial}_y E_x)) \\\\ &= -\\omega^2 \\mu_{xx} \\epsilon_{yy} E_y +\\mu_{xx} \\hat{\\partial}_x \\frac{1}{\\mu_{zz}} (\\tilde{\\partial}_x E_y - \\tilde{\\partial}_y E_x) \\\\ -\\end{align*} +\\end{aligned} $$ and, similarly, $$ -\\begin{align*} +\\begin{aligned} -\\imath \\omega \\mu_{yy} (\\gamma H_y) &= -\\omega^2 \\mu_{yy} \\epsilon_{xx} E_x +\\mu_{yy} \\hat{\\partial}_y \\frac{1}{\\mu_{zz}} (\\tilde{\\partial}_x E_y - \\tilde{\\partial}_y E_x) \\\\ -\\end{align*} +\\end{aligned} $$ Using these, we can construct the eigenvalue problem @@ -137,9 +137,9 @@ $$ \\beta^2 \\begin{bmatrix} E_x \\\\ E_y \\end{bmatrix} $$ -An equivalent eigenvalue problem can be formed using the \\( H_x, H_y \\) fields, if those are more convenient. +An equivalent eigenvalue problem can be formed using the $H_x$ and $H_y$ fields, if those are more convenient. -Note that \\( E_z \\) was never discretized, so \\( \\gamma \\) and \\( \\beta \\) will need adjustment +Note that $E_z$ was never discretized, so $\\gamma$ and $\\beta$ will need adjustment to account for numerical dispersion if the result is introduced into a space with a discretized z-axis. @@ -187,8 +187,8 @@ def operator_e(omega: complex, \\begin{bmatrix} \\hat{\\partial}_x \\epsilon_{xx} & \\hat{\\partial}_y \\epsilon_{yy} \\end{bmatrix} $$ - \\( \\tilde{\\partial}_x \\) and \\( \\hat{\\partial}_x \\) are the forward and backward derivatives along x, - and each \\( \\epsilon_{xx}, \\mu_{yy}, \\) etc. is a diagonal matrix containing the vectorized material + $\\tilde{\\partial}_x$ and $\\hat{\\partial}_x$ are the forward and backward derivatives along x, + and each $\\epsilon_{xx}$, $\\mu_{yy}$, etc. is a diagonal matrix containing the vectorized material property distribution. This operator can be used to form an eigenvalue problem of the form @@ -253,8 +253,8 @@ def operator_h(omega: complex, \\begin{bmatrix} \\tilde{\\partial}_x \\mu_{xx} & \\tilde{\\partial}_y \\mu_{yy} \\end{bmatrix} $$ - \\( \\tilde{\\partial}_x \\) and \\( \\hat{\\partial}_x \\) are the forward and backward derivatives along x, - and each \\( \\epsilon_{xx}, \\mu_{yy}, \\) etc. is a diagonal matrix containing the vectorized material + $\\tilde{\\partial}_x$ and $\\hat{\\partial}_x$ are the forward and backward derivatives along x, + and each $\\epsilon_{xx}$, $\\mu_{yy}$, etc. is a diagonal matrix containing the vectorized material property distribution. This operator can be used to form an eigenvalue problem of the form diff --git a/meanas/fdmath/__init__.py b/meanas/fdmath/__init__.py index 7e4d6ca..a3b1af3 100644 --- a/meanas/fdmath/__init__.py +++ b/meanas/fdmath/__init__.py @@ -43,11 +43,11 @@ Scalar derivatives and cell shifts ---------------------------------- Define the discrete forward derivative as - $$ [\\tilde{\\partial}_x f ]_{m + \\frac{1}{2}} = \\frac{1}{\\Delta_{x, m}} (f_{m + 1} - f_m) $$ - where \\( f \\) is a function defined at discrete locations on the x-axis (labeled using \\( m \\)). - The value at \\( m \\) occupies a length \\( \\Delta_{x, m} \\) along the x-axis. Note that \\( m \\) + $$ [\\tilde{\\partial}_x f]_{m + \\frac{1}{2}} = \\frac{1}{\\Delta_{x, m}} (f_{m + 1} - f_m) $$ + where $f$ is a function defined at discrete locations on the x-axis (labeled using $m$). + The value at $m$ occupies a length $\\Delta_{x, m}$ along the x-axis. Note that $m$ is an index along the x-axis, _not_ necessarily an x-coordinate, since each length - \\( \\Delta_{x, m}, \\Delta_{x, m+1}, ...\\) is independently chosen. + $\\Delta_{x, m}, \\Delta_{x, m+1}, ...$ is independently chosen. If we treat `f` as a 1D array of values, with the `i`-th value `f[i]` taking up a length `dx[i]` along the x-axis, the forward derivative is @@ -62,7 +62,7 @@ Likewise, discrete reverse derivative is deriv_back(f)[i] = (f[i] - f[i - 1]) / dx[i] The derivatives' values are shifted by a half-cell relative to the original function, and -will have different cell widths if all the `dx[i]` ( \\( \\Delta_{x, m} \\) ) are not +will have different cell widths if all the `dx[i]` ( $\\Delta_{x, m}$ ) are not identical: [figure: derivatives and cell sizes] @@ -87,19 +87,20 @@ identical: Periodic boundaries are used here and elsewhere unless otherwise noted. In the above figure, - `f0 =` \\(f_0\\), `f1 =` \\(f_1\\) - `Df0 =` \\([\\tilde{\\partial}f]_{0 + \\frac{1}{2}}\\) - `Df1 =` \\([\\tilde{\\partial}f]_{1 + \\frac{1}{2}}\\) - `df0 =` \\([\\hat{\\partial}f]_{0 - \\frac{1}{2}}\\) + `f0 =` $f_0$, `f1 =` $f_1$ + `Df0 =` $[\\tilde{\\partial}f]_{0 + \\frac{1}{2}}$ + `Df1 =` $[\\tilde{\\partial}f]_{1 + \\frac{1}{2}}$ + `df0 =` $[\\hat{\\partial}f]_{0 - \\frac{1}{2}}$ etc. -The fractional subscript \\( m + \\frac{1}{2} \\) is used to indicate values defined - at shifted locations relative to the original \\( m \\), with corresponding lengths +The fractional subscript $m + \\frac{1}{2}$ is used to indicate values defined + at shifted locations relative to the original $m$, with corresponding lengths $$ \\Delta_{x, m + \\frac{1}{2}} = \\frac{1}{2} * (\\Delta_{x, m} + \\Delta_{x, m + 1}) $$ -Just as \\( m \\) is not itself an x-coordinate, neither is \\( m + \\frac{1}{2} \\); + +Just as $m$ is not itself an x-coordinate, neither is $m + \\frac{1}{2}$; carefully note the positions of the various cells in the above figure vs their labels. -If the positions labeled with \\( m \\) are considered the "base" or "original" grid, -the positions labeled with \\( m + \\frac{1}{2} \\) are said to lie on a "dual" or +If the positions labeled with $m$ are considered the "base" or "original" grid, +the positions labeled with $m + \\frac{1}{2}$ are said to lie on a "dual" or "derived" grid. For the remainder of the `Discrete calculus` section, all figures will show @@ -201,8 +202,8 @@ There are also two divergences, where `g = [gx, gy, gz]` is a fore- or back-vector field. Since we applied the forward divergence to the back-vector (and vice-versa), the resulting scalar value -is defined at the back-vector's (fore-vectors) location \\( (m,n,p) \\) and not at the locations of its components -\\( (m \\pm \\frac{1}{2},n,p) \\) etc. +is defined at the back-vector's (fore-vector's) location $(m,n,p)$ and not at the locations of its components +$(m \\pm \\frac{1}{2},n,p)$ etc. [figure: divergence] ^^ @@ -226,23 +227,23 @@ Curls The two curls are then - $$ \\begin{align*} + $$ \\begin{aligned} \\hat{h}_{m + \\frac{1}{2}, n + \\frac{1}{2}, p + \\frac{1}{2}} &= \\\\ [\\tilde{\\nabla} \\times \\tilde{g}]_{m + \\frac{1}{2}, n + \\frac{1}{2}, p + \\frac{1}{2}} &= \\vec{x} (\\tilde{\\partial}_y g^z_{m,n,p + \\frac{1}{2}} - \\tilde{\\partial}_z g^y_{m,n + \\frac{1}{2},p}) \\\\ &+ \\vec{y} (\\tilde{\\partial}_z g^x_{m + \\frac{1}{2},n,p} - \\tilde{\\partial}_x g^z_{m,n,p + \\frac{1}{2}}) \\\\ &+ \\vec{z} (\\tilde{\\partial}_x g^y_{m,n + \\frac{1}{2},p} - \\tilde{\\partial}_y g^z_{m + \\frac{1}{2},n,p}) - \\end{align*} $$ + \\end{aligned} $$ and $$ \\tilde{h}_{m - \\frac{1}{2}, n - \\frac{1}{2}, p - \\frac{1}{2}} = [\\hat{\\nabla} \\times \\hat{g}]_{m - \\frac{1}{2}, n - \\frac{1}{2}, p - \\frac{1}{2}} $$ - where \\( \\hat{g} \\) and \\( \\tilde{g} \\) are located at \\((m,n,p)\\) - with components at \\( (m \\pm \\frac{1}{2},n,p) \\) etc., - while \\( \\hat{h} \\) and \\( \\tilde{h} \\) are located at \\((m \\pm \\frac{1}{2}, n \\pm \\frac{1}{2}, p \\pm \\frac{1}{2})\\) - with components at \\((m, n \\pm \\frac{1}{2}, p \\pm \\frac{1}{2})\\) etc. + where $\\hat{g}$ and $\\tilde{g}$ are located at $(m,n,p)$ + with components at $(m \\pm \\frac{1}{2},n,p)$ etc., + while $\\hat{h}$ and $\\tilde{h}$ are located at $(m \\pm \\frac{1}{2}, n \\pm \\frac{1}{2}, p \\pm \\frac{1}{2})$ + with components at $(m, n \\pm \\frac{1}{2}, p \\pm \\frac{1}{2})$ etc. [code: curls] @@ -286,27 +287,27 @@ Maxwell's Equations If we discretize both space (m,n,p) and time (l), Maxwell's equations become - $$ \\begin{align*} + $$ \\begin{aligned} \\tilde{\\nabla} \\times \\tilde{E}_{l,\\vec{r}} &= -\\tilde{\\partial}_t \\hat{B}_{l-\\frac{1}{2}, \\vec{r} + \\frac{1}{2}} - \\hat{M}_{l, \\vec{r} + \\frac{1}{2}} \\\\ \\hat{\\nabla} \\times \\hat{H}_{l-\\frac{1}{2},\\vec{r} + \\frac{1}{2}} &= \\hat{\\partial}_t \\tilde{D}_{l, \\vec{r}} + \\tilde{J}_{l-\\frac{1}{2},\\vec{r}} \\\\ \\tilde{\\nabla} \\cdot \\hat{B}_{l-\\frac{1}{2}, \\vec{r} + \\frac{1}{2}} &= 0 \\\\ \\hat{\\nabla} \\cdot \\tilde{D}_{l,\\vec{r}} &= \\rho_{l,\\vec{r}} - \\end{align*} $$ + \\end{aligned} $$ with - $$ \\begin{align*} - \\hat{B}_\\vec{r} &= \\mu_{\\vec{r} + \\frac{1}{2}} \\cdot \\hat{H}_{\\vec{r} + \\frac{1}{2}} \\\\ - \\tilde{D}_\\vec{r} &= \\epsilon_\\vec{r} \\cdot \\tilde{E}_\\vec{r} - \\end{align*} $$ + $$ \\begin{aligned} + \\hat{B}_{\\vec{r}} &= \\mu_{\\vec{r} + \\frac{1}{2}} \\cdot \\hat{H}_{\\vec{r} + \\frac{1}{2}} \\\\ + \\tilde{D}_{\\vec{r}} &= \\epsilon_{\\vec{r}} \\cdot \\tilde{E}_{\\vec{r}} + \\end{aligned} $$ -where the spatial subscripts are abbreviated as \\( \\vec{r} = (m, n, p) \\) and -\\( \\vec{r} + \\frac{1}{2} = (m + \\frac{1}{2}, n + \\frac{1}{2}, p + \\frac{1}{2}) \\), -\\( \\tilde{E} \\) and \\( \\hat{H} \\) are the electric and magnetic fields, -\\( \\tilde{J} \\) and \\( \\hat{M} \\) are the electric and magnetic current distributions, -and \\( \\epsilon \\) and \\( \\mu \\) are the dielectric permittivity and magnetic permeability. +where the spatial subscripts are abbreviated as $\\vec{r} = (m, n, p)$ and +$\\vec{r} + \\frac{1}{2} = (m + \\frac{1}{2}, n + \\frac{1}{2}, p + \\frac{1}{2})$, +$\\tilde{E}$ and $\\hat{H}$ are the electric and magnetic fields, +$\\tilde{J}$ and $\\hat{M}$ are the electric and magnetic current distributions, +and $\\epsilon$ and $\\mu$ are the dielectric permittivity and magnetic permeability. The above is Yee's algorithm, written in a form analogous to Maxwell's equations. The time derivatives can be expanded to form the update equations: @@ -375,12 +376,12 @@ and combining them with charge continuity, Wave equation ------------- -Taking the backward curl of the \\( \\tilde{\\nabla} \\times \\tilde{E} \\) equation and -replacing the resulting \\( \\hat{\\nabla} \\times \\hat{H} \\) term using its respective equation, -and setting \\( \\hat{M} \\) to zero, we can form the discrete wave equation: +Taking the backward curl of the $\\tilde{\\nabla} \\times \\tilde{E}$ equation and +replacing the resulting $\\hat{\\nabla} \\times \\hat{H}$ term using its respective equation, +and setting $\\hat{M}$ to zero, we can form the discrete wave equation: $$ - \\begin{align*} + \\begin{aligned} \\tilde{\\nabla} \\times \\tilde{E}_{l,\\vec{r}} &= -\\tilde{\\partial}_t \\hat{B}_{l-\\frac{1}{2}, \\vec{r} + \\frac{1}{2}} - \\hat{M}_{l-1, \\vec{r} + \\frac{1}{2}} \\\\ @@ -391,11 +392,11 @@ $$ \\hat{\\nabla} \\times (\\mu^{-1}_{\\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_{l,\\vec{r}}) &= -\\tilde{\\partial}_t \\hat{\\nabla} \\times \\hat{H}_{l-\\frac{1}{2}, \\vec{r} + \\frac{1}{2}} \\\\ \\hat{\\nabla} \\times (\\mu^{-1}_{\\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_{l,\\vec{r}}) &= - -\\tilde{\\partial}_t \\hat{\\partial}_t \\epsilon_\\vec{r} \\tilde{E}_{l, \\vec{r}} + \\hat{\\partial}_t \\tilde{J}_{l-\\frac{1}{2},\\vec{r}} \\\\ + -\\tilde{\\partial}_t \\hat{\\partial}_t \\epsilon_{\\vec{r}} \\tilde{E}_{l, \\vec{r}} + \\hat{\\partial}_t \\tilde{J}_{l-\\frac{1}{2},\\vec{r}} \\\\ \\hat{\\nabla} \\times (\\mu^{-1}_{\\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_{l,\\vec{r}}) - + \\tilde{\\partial}_t \\hat{\\partial}_t \\epsilon_\\vec{r} \\cdot \\tilde{E}_{l, \\vec{r}} + + \\tilde{\\partial}_t \\hat{\\partial}_t \\epsilon_{\\vec{r}} \\cdot \\tilde{E}_{l, \\vec{r}} &= \\tilde{\\partial}_t \\tilde{J}_{l - \\frac{1}{2}, \\vec{r}} - \\end{align*} + \\end{aligned} $$ @@ -405,27 +406,27 @@ Frequency domain We can substitute in a time-harmonic fields $$ - \\begin{align*} - \\tilde{E}_\\vec{r} &= \\tilde{E}_\\vec{r} e^{-\\imath \\omega l \\Delta_t} \\\\ - \\tilde{J}_\\vec{r} &= \\tilde{J}_\\vec{r} e^{-\\imath \\omega (l - \\frac{1}{2}) \\Delta_t} - \\end{align*} + \\begin{aligned} + \\tilde{E}_{l, \\vec{r}} &= \\tilde{E}_{\\vec{r}} e^{-\\imath \\omega l \\Delta_t} \\\\ + \\tilde{J}_{l, \\vec{r}} &= \\tilde{J}_{\\vec{r}} e^{-\\imath \\omega (l - \\frac{1}{2}) \\Delta_t} + \\end{aligned} $$ resulting in $$ - \\begin{align*} + \\begin{aligned} \\tilde{\\partial}_t &\\Rightarrow (e^{ \\imath \\omega \\Delta_t} - 1) / \\Delta_t = \\frac{-2 \\imath}{\\Delta_t} \\sin(\\omega \\Delta_t / 2) e^{-\\imath \\omega \\Delta_t / 2} = -\\imath \\Omega e^{-\\imath \\omega \\Delta_t / 2}\\\\ \\hat{\\partial}_t &\\Rightarrow (1 - e^{-\\imath \\omega \\Delta_t}) / \\Delta_t = \\frac{-2 \\imath}{\\Delta_t} \\sin(\\omega \\Delta_t / 2) e^{ \\imath \\omega \\Delta_t / 2} = -\\imath \\Omega e^{ \\imath \\omega \\Delta_t / 2}\\\\ \\Omega &= 2 \\sin(\\omega \\Delta_t / 2) / \\Delta_t - \\end{align*} + \\end{aligned} $$ This gives the frequency-domain wave equation, $$ - \\hat{\\nabla} \\times (\\mu^{-1}_{\\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_\\vec{r}) - -\\Omega^2 \\epsilon_\\vec{r} \\cdot \\tilde{E}_\\vec{r} = \\imath \\Omega \\tilde{J}_\\vec{r} + \\hat{\\nabla} \\times (\\mu^{-1}_{\\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_{\\vec{r}}) + -\\Omega^2 \\epsilon_{\\vec{r}} \\cdot \\tilde{E}_{\\vec{r}} = \\imath \\Omega \\tilde{J}_{\\vec{r}} $$ @@ -435,69 +436,69 @@ Plane waves and Dispersion relation With uniform material distribution and no sources $$ - \\begin{align*} + \\begin{aligned} \\mu_{\\vec{r} + \\frac{1}{2}} &= \\mu \\\\ - \\epsilon_\\vec{r} &= \\epsilon \\\\ - \\tilde{J}_\\vec{r} &= 0 \\\\ - \\end{align*} + \\epsilon_{\\vec{r}} &= \\epsilon \\\\ + \\tilde{J}_{\\vec{r}} &= 0 \\\\ + \\end{aligned} $$ the frequency domain wave equation simplifies to -$$ \\hat{\\nabla} \\times \\tilde{\\nabla} \\times \\tilde{E}_\\vec{r} - \\Omega^2 \\epsilon \\mu \\tilde{E}_\\vec{r} = 0 $$ +$$ \\hat{\\nabla} \\times \\tilde{\\nabla} \\times \\tilde{E}_{\\vec{r}} - \\Omega^2 \\epsilon \\mu \\tilde{E}_{\\vec{r}} = 0 $$ -Since \\( \\hat{\\nabla} \\cdot \\tilde{E}_\\vec{r} = 0 \\), we can simplify +Since $\\hat{\\nabla} \\cdot \\tilde{E}_{\\vec{r}} = 0$, we can simplify $$ - \\begin{align*} - \\hat{\\nabla} \\times \\tilde{\\nabla} \\times \\tilde{E}_\\vec{r} - &= \\tilde{\\nabla}(\\hat{\\nabla} \\cdot \\tilde{E}_\\vec{r}) - \\hat{\\nabla} \\cdot \\tilde{\\nabla} \\tilde{E}_\\vec{r} \\\\ - &= - \\hat{\\nabla} \\cdot \\tilde{\\nabla} \\tilde{E}_\\vec{r} \\\\ - &= - \\tilde{\\nabla}^2 \\tilde{E}_\\vec{r} - \\end{align*} + \\begin{aligned} + \\hat{\\nabla} \\times \\tilde{\\nabla} \\times \\tilde{E}_{\\vec{r}} + &= \\tilde{\\nabla}(\\hat{\\nabla} \\cdot \\tilde{E}_{\\vec{r}}) - \\hat{\\nabla} \\cdot \\tilde{\\nabla} \\tilde{E}_{\\vec{r}} \\\\ + &= - \\hat{\\nabla} \\cdot \\tilde{\\nabla} \\tilde{E}_{\\vec{r}} \\\\ + &= - \\tilde{\\nabla}^2 \\tilde{E}_{\\vec{r}} + \\end{aligned} $$ and we get -$$ \\tilde{\\nabla}^2 \\tilde{E}_\\vec{r} + \\Omega^2 \\epsilon \\mu \\tilde{E}_\\vec{r} = 0 $$ +$$ \\tilde{\\nabla}^2 \\tilde{E}_{\\vec{r}} + \\Omega^2 \\epsilon \\mu \\tilde{E}_{\\vec{r}} = 0 $$ We can convert this to three scalar-wave equations of the form -$$ (\\tilde{\\nabla}^2 + K^2) \\phi_\\vec{r} = 0 $$ +$$ (\\tilde{\\nabla}^2 + K^2) \\phi_{\\vec{r}} = 0 $$ -with \\( K^2 = \\Omega^2 \\mu \\epsilon \\). Now we let +with $K^2 = \\Omega^2 \\mu \\epsilon$. Now we let -$$ \\phi_\\vec{r} = A e^{\\imath (k_x m \\Delta_x + k_y n \\Delta_y + k_z p \\Delta_z)} $$ +$$ \\phi_{\\vec{r}} = A e^{\\imath (k_x m \\Delta_x + k_y n \\Delta_y + k_z p \\Delta_z)} $$ resulting in $$ - \\begin{align*} + \\begin{aligned} \\tilde{\\partial}_x &\\Rightarrow (e^{ \\imath k_x \\Delta_x} - 1) / \\Delta_t = \\frac{-2 \\imath}{\\Delta_x} \\sin(k_x \\Delta_x / 2) e^{ \\imath k_x \\Delta_x / 2} = \\imath K_x e^{ \\imath k_x \\Delta_x / 2}\\\\ \\hat{\\partial}_x &\\Rightarrow (1 - e^{-\\imath k_x \\Delta_x}) / \\Delta_t = \\frac{-2 \\imath}{\\Delta_x} \\sin(k_x \\Delta_x / 2) e^{-\\imath k_x \\Delta_x / 2} = \\imath K_x e^{-\\imath k_x \\Delta_x / 2}\\\\ K_x &= 2 \\sin(k_x \\Delta_x / 2) / \\Delta_x \\\\ - \\end{align*} + \\end{aligned} $$ -with similar expressions for the y and z dimnsions (and \\( K_y, K_z \\)). +with similar expressions for the y and z dimnsions (and $K_y, K_z$). This implies $$ - \\tilde{\\nabla}^2 = -(K_x^2 + K_y^2 + K_z^2) \\phi_\\vec{r} \\\\ + \\tilde{\\nabla}^2 = -(K_x^2 + K_y^2 + K_z^2) \\phi_{\\vec{r}} \\\\ K_x^2 + K_y^2 + K_z^2 = \\Omega^2 \\mu \\epsilon = \\Omega^2 / c^2 $$ -where \\( c = \\sqrt{\\mu \\epsilon} \\). +where $c = \\sqrt{\\mu \\epsilon}$. -Assuming real \\( (k_x, k_y, k_z), \\omega \\) will be real only if +Assuming real $(k_x, k_y, k_z), \\omega$ will be real only if $$ c^2 \\Delta_t^2 = \\frac{\\Delta_t^2}{\\mu \\epsilon} < 1/(\\frac{1}{\\Delta_x^2} + \\frac{1}{\\Delta_y^2} + \\frac{1}{\\Delta_z^2}) $$ -If \\( \\Delta_x = \\Delta_y = \\Delta_z \\), this simplifies to \\( c \\Delta_t < \\Delta_x / \\sqrt{3} \\). +If $\\Delta_x = \\Delta_y = \\Delta_z$, this simplifies to $c \\Delta_t < \\Delta_x / \\sqrt{3}$. This last form can be interpreted as enforcing causality; the distance that light -travels in one timestep (i.e., \\( c \\Delta_t \\)) must be less than the diagonal -of the smallest cell ( \\( \\Delta_x / \\sqrt{3} \\) when on a uniform cubic grid). +travels in one timestep (i.e., $c \\Delta_t$) must be less than the diagonal +of the smallest cell ( $\\Delta_x / \\sqrt{3}$ when on a uniform cubic grid). Grid description @@ -513,9 +514,9 @@ To get a better sense of how this works, let's start by drawing a grid with unif to make the illustration simpler; we need at least two cells in the x dimension to demonstrate how nonuniform `dx` affects the various components. -Place the E fore-vectors at integer indices \\( r = (m, n, p) \\) and the H back-vectors -at fractional indices \\( r + \\frac{1}{2} = (m + \\frac{1}{2}, n + \\frac{1}{2}, -p + \\frac{1}{2}) \\). Remember that these are indices and not coordinates; they can +Place the E fore-vectors at integer indices $r = (m, n, p)$ and the H back-vectors +at fractional indices $r + \\frac{1}{2} = (m + \\frac{1}{2}, n + \\frac{1}{2}, +p + \\frac{1}{2})$. Remember that these are indices and not coordinates; they can correspond to arbitrary (monotonically increasing) coordinates depending on the cell widths. Draw lines to denote the planes on which the H components and back-vectors are defined. diff --git a/meanas/fdmath/functional.py b/meanas/fdmath/functional.py index fc5b0ca..7de046a 100644 --- a/meanas/fdmath/functional.py +++ b/meanas/fdmath/functional.py @@ -63,7 +63,7 @@ def curl_forward(dx_e: List[numpy.ndarray] = None) -> fdfield_updater_t: Returns: Function `f` for taking the discrete forward curl of a field, - `f(E)` -> curlE \\( = \\nabla_f \\times E \\) + `f(E)` -> curlE $= \\nabla_f \\times E$ """ Dx, Dy, Dz = deriv_forward(dx_e) @@ -90,7 +90,7 @@ def curl_back(dx_h: List[numpy.ndarray] = None) -> fdfield_updater_t: Returns: Function `f` for taking the discrete backward curl of a field, - `f(H)` -> curlH \\( = \\nabla_b \\times H \\) + `f(H)` -> curlH $= \\nabla_b \\times H$ """ Dx, Dy, Dz = deriv_back(dx_h) diff --git a/meanas/fdtd/__init__.py b/meanas/fdtd/__init__.py index 2a99f76..64656b7 100644 --- a/meanas/fdtd/__init__.py +++ b/meanas/fdtd/__init__.py @@ -13,7 +13,7 @@ we have $$ c^2 \\Delta_t^2 = \\frac{\\Delta_t^2}{\\mu \\epsilon} < 1/(\\frac{1}{\\Delta_x^2} + \\frac{1}{\\Delta_y^2} + \\frac{1}{\\Delta_z^2}) $$ -or, if \\( \\Delta_x = \\Delta_y = \\Delta_z \\), then \\( c \\Delta_t < \\frac{\\Delta_x}{\\sqrt{3}} \\). +or, if $\\Delta_x = \\Delta_y = \\Delta_z$, then $c \\Delta_t < \\frac{\\Delta_x}{\\sqrt{3}}$. Based on this, we can set @@ -27,21 +27,21 @@ Poynting Vector and Energy Conservation Let -$$ \\begin{align*} +$$ \\begin{aligned} \\tilde{S}_{l, l', \\vec{r}} &=& &\\tilde{E}_{l, \\vec{r}} \\otimes \\hat{H}_{l', \\vec{r} + \\frac{1}{2}} \\\\ &=& &\\vec{x} (\\tilde{E}^y_{l,m+1,n,p} \\hat{H}^z_{l',\\vec{r} + \\frac{1}{2}} - \\tilde{E}^z_{l,m+1,n,p} \\hat{H}^y_{l', \\vec{r} + \\frac{1}{2}}) \\\\ & &+ &\\vec{y} (\\tilde{E}^z_{l,m,n+1,p} \\hat{H}^x_{l',\\vec{r} + \\frac{1}{2}} - \\tilde{E}^x_{l,m,n+1,p} \\hat{H}^z_{l', \\vec{r} + \\frac{1}{2}}) \\\\ & &+ &\\vec{z} (\\tilde{E}^x_{l,m,n,p+1} \\hat{H}^y_{l',\\vec{r} + \\frac{1}{2}} - \\tilde{E}^y_{l,m,n,p+1} \\hat{H}^z_{l', \\vec{r} + \\frac{1}{2}}) - \\end{align*} + \\end{aligned} $$ -where \\( \\vec{r} = (m, n, p) \\) and \\( \\otimes \\) is a modified cross product -in which the \\( \\tilde{E} \\) terms are shifted as indicated. +where $\\vec{r} = (m, n, p)$ and $\\otimes$ is a modified cross product +in which the $\\tilde{E}$ terms are shifted as indicated. By taking the divergence and rearranging terms, we can show that $$ - \\begin{align*} + \\begin{aligned} \\hat{\\nabla} \\cdot \\tilde{S}_{l, l', \\vec{r}} &= \\hat{\\nabla} \\cdot (\\tilde{E}_{l, \\vec{r}} \\otimes \\hat{H}_{l', \\vec{r} + \\frac{1}{2}}) \\\\ &= \\hat{H}_{l', \\vec{r} + \\frac{1}{2}} \\cdot \\tilde{\\nabla} \\times \\tilde{E}_{l, \\vec{r}} - @@ -49,30 +49,30 @@ $$ &= \\hat{H}_{l', \\vec{r} + \\frac{1}{2}} \\cdot (-\\tilde{\\partial}_t \\mu_{\\vec{r} + \\frac{1}{2}} \\hat{H}_{l - \\frac{1}{2}, \\vec{r} + \\frac{1}{2}} - \\hat{M}_{l-1, \\vec{r} + \\frac{1}{2}}) - - \\tilde{E}_{l, \\vec{r}} \\cdot (\\hat{\\partial}_t \\tilde{\\epsilon}_\\vec{r} \\tilde{E}_{l'+\\frac{1}{2}, \\vec{r}} + + \\tilde{E}_{l, \\vec{r}} \\cdot (\\hat{\\partial}_t \\tilde{\\epsilon}_{\\vec{r}} \\tilde{E}_{l'+\\frac{1}{2}, \\vec{r}} + \\tilde{J}_{l', \\vec{r}}) \\\\ &= \\hat{H}_{l'} \\cdot (-\\mu / \\Delta_t)(\\hat{H}_{l + \\frac{1}{2}} - \\hat{H}_{l - \\frac{1}{2}}) - \\tilde{E}_l \\cdot (\\epsilon / \\Delta_t )(\\tilde{E}_{l'+\\frac{1}{2}} - \\tilde{E}_{l'-\\frac{1}{2}}) - \\hat{H}_{l'} \\cdot \\hat{M}_{l-1} - \\tilde{E}_l \\cdot \\tilde{J}_{l'} \\\\ - \\end{align*} + \\end{aligned} $$ where in the last line the spatial subscripts have been dropped to emphasize -the time subscripts \\( l, l' \\), i.e. +the time subscripts $l, l'$, i.e. $$ - \\begin{align*} + \\begin{aligned} \\tilde{E}_l &= \\tilde{E}_{l, \\vec{r}} \\\\ \\hat{H}_l &= \\tilde{H}_{l, \\vec{r} + \\frac{1}{2}} \\\\ - \\tilde{\\epsilon} &= \\tilde{\\epsilon}_\\vec{r} \\\\ - \\end{align*} + \\tilde{\\epsilon} &= \\tilde{\\epsilon}_{\\vec{r}} \\\\ + \\end{aligned} $$ etc. -For \\( l' = l + \\frac{1}{2} \\) we get +For $l' = l + \\frac{1}{2}$ we get $$ - \\begin{align*} + \\begin{aligned} \\hat{\\nabla} \\cdot \\tilde{S}_{l, l + \\frac{1}{2}} &= \\hat{H}_{l + \\frac{1}{2}} \\cdot (-\\mu / \\Delta_t)(\\hat{H}_{l + \\frac{1}{2}} - \\hat{H}_{l - \\frac{1}{2}}) - @@ -87,13 +87,13 @@ $$ +\\epsilon \\tilde{E}^2_l) / \\Delta_t \\ \\ - \\hat{H}_{l+\\frac{1}{2}} \\cdot \\hat{M}_l \\ \\ - \\tilde{E}_l \\cdot \\tilde{J}_{l+\\frac{1}{2}} \\\\ - \\end{align*} + \\end{aligned} $$ -and for \\( l' = l - \\frac{1}{2} \\), +and for $l' = l - \\frac{1}{2}$, $$ - \\begin{align*} + \\begin{aligned} \\hat{\\nabla} \\cdot \\tilde{S}_{l, l - \\frac{1}{2}} &= (\\mu \\hat{H}^2_{l - \\frac{1}{2}} +\\epsilon \\tilde{E}_{l-1} \\cdot \\tilde{E}_l) / \\Delta_t \\ \\ @@ -101,7 +101,7 @@ $$ +\\epsilon \\tilde{E}^2_l) / \\Delta_t \\ \\ - \\hat{H}_{l-\\frac{1}{2}} \\cdot \\hat{M}_l \\ \\ - \\tilde{E}_l \\cdot \\tilde{J}_{l-\\frac{1}{2}} \\\\ - \\end{align*} + \\end{aligned} $$ These two results form the discrete time-domain analogue to Poynting's theorem. @@ -109,16 +109,16 @@ They hint at the expressions for the energy, which can be calculated at the same time-index as either the E or H field: $$ - \\begin{align*} + \\begin{aligned} U_l &= \\epsilon \\tilde{E}^2_l + \\mu \\hat{H}_{l + \\frac{1}{2}} \\cdot \\hat{H}_{l - \\frac{1}{2}} \\\\ U_{l + \\frac{1}{2}} &= \\epsilon \\tilde{E}_l \\cdot \\tilde{E}_{l + 1} + \\mu \\hat{H}^2_{l + \\frac{1}{2}} \\\\ - \\end{align*} + \\end{aligned} $$ Rewriting the Poynting theorem in terms of the energy expressions, $$ - \\begin{align*} + \\begin{aligned} (U_{l+\\frac{1}{2}} - U_l) / \\Delta_t &= -\\hat{\\nabla} \\cdot \\tilde{S}_{l, l + \\frac{1}{2}} \\ \\ - \\hat{H}_{l+\\frac{1}{2}} \\cdot \\hat{M}_l \\ \\ @@ -127,14 +127,14 @@ $$ &= -\\hat{\\nabla} \\cdot \\tilde{S}_{l, l - \\frac{1}{2}} \\ \\ - \\hat{H}_{l-\\frac{1}{2}} \\cdot \\hat{M}_l \\ \\ - \\tilde{E}_l \\cdot \\tilde{J}_{l-\\frac{1}{2}} \\\\ - \\end{align*} + \\end{aligned} $$ This result is exact an should practically hold to within numerical precision. No time- or spatial-averaging is necessary. -Note that each value of \\( J \\) contributes to the energy twice (i.e. once per field update) -despite only causing the value of \\( E \\) to change once (same for \\( M \\) and \\( H \\)). +Note that each value of $J$ contributes to the energy twice (i.e. once per field update) +despite only causing the value of $E$ to change once (same for $M$ and $H$). Sources @@ -149,8 +149,8 @@ shape. It can be written $$ f_r(t) = (1 - \\frac{1}{2} (\\omega (t - \\tau))^2) e^{-(\\frac{\\omega (t - \\tau)}{2})^2} $$ -with \\( \\tau > \\frac{2 * \\pi}{\\omega} \\) as a minimum delay to avoid a discontinuity at -t=0 (assuming the source is off for t<0 this gives \\( \\sim 10^{-3} \\) error at t=0). +with $\\tau > \\frac{2 * \\pi}{\\omega}$ as a minimum delay to avoid a discontinuity at +t=0 (assuming the source is off for t<0 this gives $\\sim 10^{-3}$ error at t=0). diff --git a/pdoc_templates/config.mako b/pdoc_templates/config.mako index 0642566..3010348 100644 --- a/pdoc_templates/config.mako +++ b/pdoc_templates/config.mako @@ -18,8 +18,9 @@ #git_link_template = 'https://github.com/USER/PROJECT/blob/{commit}/{path}#L{start_line}-L{end_line}' #git_link_template = 'https://gitlab.com/USER/PROJECT/blob/{commit}/{path}#L{start_line}-L{end_line}' #git_link_template = 'https://bitbucket.org/USER/PROJECT/src/{commit}/{path}#lines-{start_line}:{end_line}' - #git_link_template = 'https://CGIT_HOSTNAME/PROJECT/tree/{path}?id={commit}#n{start-line}' - git_link_template = None + #git_link_template = 'https://CGIT_HOSTNAME/PROJECT/tree/{path}?id={commit}#n{start_line}' + #git_link_template = None + git_link_template = 'https://mpxd.net/code/jan/fdfd_tools/src/commit/{commit}/{path}#L{start_line}-L{end_line}' # A prefix to use for every HTML hyperlink in the generated documentation. # No prefix results in all links being relative. diff --git a/pdoc_templates/html.mako b/pdoc_templates/html.mako index 9cf1137..6b3326f 100644 --- a/pdoc_templates/html.mako +++ b/pdoc_templates/html.mako @@ -2,7 +2,10 @@ import os import pdoc - from pdoc.html_helpers import extract_toc, glimpse, to_html as _to_html, format_git_link + from pdoc.html_helpers import extract_toc, glimpse, to_html as _to_html, format_git_link, _md, to_markdown + + from markdown.inlinepatterns import InlineProcessor + from markdown.util import AtomicString, etree def link(d, name=None, fmt='{}'): @@ -14,8 +17,33 @@ return '{}'.format(d.refname, url, name) - def to_html(text): - return _to_html(text, module=module, link=link, latex_math=latex_math) + # Altered latex delimeters (allow inline $...$, wrap in ) + class _MathPattern(InlineProcessor): + NAME = 'pdoc-math' + PATTERN = r'(? <%def name="ident(name)">${name} @@ -377,10 +405,6 @@ % endif - % if latex_math: - - % endif - <%include file="head.mako"/> diff --git a/pdoc_templates/pdf.mako b/pdoc_templates/pdf.mako new file mode 100644 index 0000000..50e7989 --- /dev/null +++ b/pdoc_templates/pdf.mako @@ -0,0 +1,185 @@ +<%! + import re + import pdoc + from pdoc.html_helpers import to_markdown, format_git_link + + def link(d, fmt='{}'): + name = fmt.format(d.qualname + ('()' if isinstance(d, pdoc.Function) else '')) + if isinstance(d, pdoc.External): + return name + return '[{}](#{})'.format(name, d.refname) + + def _to_md(text, module): + text = to_markdown(text, module=module, link=link) + # Setext H2 headings to atx H2 headings + text = re.sub(r'\n(.+)\n-{3,}\n', r'\n## \1\n\n', text) + # Convert admonitions into simpler paragraphs, dedent contents + text = re.sub(r'^(?P( *))!!! \w+ \"([^\"]*)\"(.*(?:\n(?P=indent) +.*)*)', + lambda m: '{}**{}:** {}'.format(m.group(2), m.group(3), + re.sub('\n {,4}', '\n', m.group(4))), + text, flags=re.MULTILINE) + return text + + def subh(text, level=2): + # Deepen heading levels so H2 becomes H4 etc. + return re.sub(r'\n(#+) +(.+)\n', r'\n%s\1 \2\n' % ('#' * level), text) +%> + +<%def name="title(level, string, id=None)"> + <% id = ' {#%s}' % id if id is not None else '' %> +${('#' * level) + ' ' + string + id} + + +<%def name="funcdef(f)"> + <% + returns = show_type_annotations and f.return_annotation() or '' + if returns: + returns = ' -> ' + returns + %> +> `${f.funcdef()} ${f.name}(${', '.join(f.params(annotate=show_type_annotations))})${returns}` + + +<%def name="classdef(c)"> +> `class ${c.name}(${', '.join(c.params(annotate=show_type_annotations))})` + + +<%def name="show_source(d)"> + % if (show_source_code or git_link_template) and d.source and d.obj is not getattr(d.inherits, 'obj', None): + <% git_link = format_git_link(git_link_template, d) %> +[[view code]](${git_link}) + %endif + + +--- +description: | + API documentation for modules: ${', '.join(m.name for m in modules)}. + +lang: en + +classoption: oneside +geometry: margin=1in +papersize: a4 + +linkcolor: blue +links-as-notes: true +... +% for module in modules: +<% + submodules = module.submodules() + variables = module.variables() + functions = module.functions() + classes = module.classes() + + def to_md(text): + return _to_md(text, module) +%> + +------------------------------------------- + +${title(1, ('Namespace' if module.is_namespace else 'Module') + ' `%s`' % module.name, module.refname)} +${module.docstring | to_md} + +% if submodules: +${title(2, 'Sub-modules')} + % for m in submodules: +* [${m.name}](#${m.refname}) + % endfor +% endif + +% if variables: +${title(2, 'Variables')} + % for v in variables: +${title(3, 'Variable `%s`' % v.name, v.refname)} +${show_source(v)} +${v.docstring | to_md, subh, subh} + % endfor +% endif + +% if functions: +${title(2, 'Functions')} + % for f in functions: +${title(3, 'Function `%s`' % f.name, f.refname)} +${show_source(f)} + +${funcdef(f)} + +${f.docstring | to_md, subh, subh} + % endfor +% endif + +% if classes: +${title(2, 'Classes')} + % for cls in classes: +${title(3, 'Class `%s`' % cls.name, cls.refname)} +${show_source(cls)} + +${classdef(cls)} + +${cls.docstring | to_md, subh} +<% + class_vars = cls.class_variables(show_inherited_members, sort=sort_identifiers) + static_methods = cls.functions(show_inherited_members, sort=sort_identifiers) + inst_vars = cls.instance_variables(show_inherited_members, sort=sort_identifiers) + methods = cls.methods(show_inherited_members, sort=sort_identifiers) + mro = cls.mro() + subclasses = cls.subclasses() +%> + % if mro: +${title(4, 'Ancestors (in MRO)')} + % for c in mro: +* [${c.refname}](#${c.refname}) + % endfor + % endif + + % if subclasses: +${title(4, 'Descendants')} + % for c in subclasses: +* [${c.refname}](#${c.refname}) + % endfor + % endif + + % if class_vars: +${title(4, 'Class variables')} + % for v in class_vars: +${title(5, 'Variable `%s`' % v.name, v.refname)} +${v.docstring | to_md, subh, subh} + % endfor + % endif + + % if inst_vars: +${title(4, 'Instance variables')} + % for v in inst_vars: +${title(5, 'Variable `%s`' % v.name, v.refname)} +${v.docstring | to_md, subh, subh} + % endfor + % endif + + % if static_methods: +${title(4, 'Static methods')} + % for f in static_methods: +${title(5, '`Method %s`' % f.name, f.refname)} + +${funcdef(f)} + +${f.docstring | to_md, subh, subh} + % endfor + % endif + + % if methods: +${title(4, 'Methods')} + % for f in methods: +${title(5, 'Method `%s`' % f.name, f.refname)} + +${funcdef(f)} + +${f.docstring | to_md, subh, subh} + % endfor + % endif + % endfor +% endif + +##\## for module in modules: +% endfor + +----- +Generated by *pdoc* ${pdoc.__version__} (). diff --git a/pdoc_templates/pdoc.css b/pdoc_templates/pdoc.css new file mode 100644 index 0000000..a563b44 --- /dev/null +++ b/pdoc_templates/pdoc.css @@ -0,0 +1,381 @@ + .flex { + display: flex !important; + } + + body { + line-height: 1.5em; + background: black; + color: #DDD; + max-width: 140ch; + } + + #content { + padding: 20px; + } + + #sidebar { + padding: 30px; + overflow: hidden; + } + + .http-server-breadcrumbs { + font-size: 130%; + margin: 0 0 15px 0; + } + + #footer { + font-size: .75em; + padding: 5px 30px; + border-top: 1px solid #ddd; + text-align: right; + } + #footer p { + margin: 0 0 0 1em; + display: inline-block; + } + #footer p:last-child { + margin-right: 30px; + } + + h1, h2, h3, h4, h5 { + font-weight: 300; + } + h1 { + font-size: 2.5em; + line-height: 1.1em; + border-top: 20px white; + } + h2 { + font-size: 1.75em; + margin: 1em 0 .50em 0; + } + h3 { + font-size: 1.4em; + margin: 25px 0 10px 0; + } + h4 { + margin: 0; + font-size: 105%; + } + + a { + color: #999; + text-decoration: none; + transition: color .3s ease-in-out; + } + a:hover { + color: #18d; + } + + .title code { + font-weight: bold; + } + h2[id^="header-"] { + margin-top: 2em; + } + .ident { + color: #7ff; + } + + pre code { + background: transparent; + font-size: .8em; + line-height: 1.4em; + } + code { + background: #0d0d0e; + padding: 1px 4px; + overflow-wrap: break-word; + } + h1 code { background: transparent } + + pre { + background: #111; + border: 0; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + margin: 1em 0; + padding: 1ex; + } + + #http-server-module-list { + display: flex; + flex-flow: column; + } + #http-server-module-list div { + display: flex; + } + #http-server-module-list dt { + min-width: 10%; + } + #http-server-module-list p { + margin-top: 0; + } + + .toc ul, + #index { + list-style-type: none; + margin: 0; + padding: 0; + } + #index code { + background: transparent; + } + #index h3 { + border-bottom: 1px solid #ddd; + } + #index ul { + padding: 0; + } + #index h4 { + font-weight: bold; + } + #index h4 + ul { + margin-bottom:.6em; + } + /* Make TOC lists have 2+ columns when viewport is wide enough. + Assuming ~20-character identifiers and ~30% wide sidebar. */ + @media (min-width: 200ex) { #index .two-column { column-count: 2 } } + @media (min-width: 300ex) { #index .two-column { column-count: 3 } } + + dl { + margin-bottom: 2em; + } + dl dl:last-child { + margin-bottom: 4em; + } + dd { + margin: 0 0 1em 3em; + } + #header-classes + dl > dd { + margin-bottom: 3em; + } + dd dd { + margin-left: 2em; + } + dd p { + margin: 10px 0; + } + blockquote code { + background: #111; + font-weight: bold; + font-size: .85em; + padding: 5px 10px; + display: inline-block; + min-width: 40%; + } + blockquote code:hover { + background: #101010; + } + .name > span:first-child { + white-space: nowrap; + } + .name.class > span:nth-child(2) { + margin-left: .4em; + } + .inherited { + color: #777; + border-left: 5px solid #eee; + padding-left: 1em; + } + .inheritance em { + font-style: normal; + font-weight: bold; + } + + /* Docstrings titles, e.g. in numpydoc format */ + .desc h2 { + font-weight: 400; + font-size: 1.25em; + } + .desc h3 { + font-size: 1em; + } + .desc dt code { + background: inherit; /* Don't grey-back parameters */ + } + + .source summary, + .git-link-div { + color: #aaa; + text-align: right; + font-weight: 400; + font-size: .8em; + text-transform: uppercase; + } + .source summary > * { + white-space: nowrap; + cursor: pointer; + } + .git-link { + color: inherit; + margin-left: 1em; + } + .source pre { + max-height: 500px; + overflow: auto; + margin: 0; + } + .source pre code { + font-size: 12px; + overflow: visible; + } + .hlist { + list-style: none; + } + .hlist li { + display: inline; + } + .hlist li:after { + content: ',\2002'; + } + .hlist li:last-child:after { + content: none; + } + .hlist .hlist { + display: inline; + padding-left: 1em; + } + + img { + max-width: 100%; + } + + .admonition { + padding: .1em .5em; + margin-bottom: 1em; + } + .admonition-title { + font-weight: bold; + } + .admonition.note, + .admonition.info, + .admonition.important { + background: #610; + } + .admonition.todo, + .admonition.versionadded, + .admonition.tip, + .admonition.hint { + background: #202; + } + .admonition.warning, + .admonition.versionchanged, + .admonition.deprecated { + background: #02b; + } + .admonition.error, + .admonition.danger, + .admonition.caution { + background: darkpink; + } + + @media screen and (min-width: 700px) { + #sidebar { + width: 30%; + } + #content { + width: 70%; + max-width: 100ch; + padding: 3em 4em; + border-left: 1px solid #ddd; + } + pre code { + font-size: 1em; + } + .item .name { + font-size: 1em; + } + main { + display: flex; + flex-direction: row-reverse; + justify-content: flex-end; + } + .toc ul ul, + #index ul { + padding-left: 1.5em; + } + .toc > ul > li { + margin-top: .5em; + } + } + +@media print { + #sidebar h1 { + page-break-before: always; + } + .source { + display: none; + } +} +@media print { + * { + background: transparent !important; + color: #000 !important; /* Black prints faster: h5bp.com/s */ + box-shadow: none !important; + text-shadow: none !important; + } + + a[href]:after { + content: " (" attr(href) ")"; + font-size: 90%; + } + /* Internal, documentation links, recognized by having a title, + don't need the URL explicity stated. */ + a[href][title]:after { + content: none; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + /* + * Don't show links for images, or javascript/internal links + */ + + .ir a:after, + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; /* h5bp.com/t */ + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + @page { + margin: 0.5cm; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + page-break-after: avoid; + } +}