incomp-flame-post/search/search_index.json
2026-06-05 13:27:38 +00:00

1 line
No EOL
277 KiB
JSON

{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"],"fields":{"title":{"boost":1000.0},"text":{"boost":1.0},"tags":{"boost":1000000.0}}},"docs":[{"location":"","title":"HPC DNS Post-Processing Reference Manual","text":"<p>Welcome to the automated documentation suite for the high-order compact difference post-processing project! This manual includes reference documentation for both the compiled Fortran core and the Python binds/algebraic generators.</p>"},{"location":"#architecture-overview","title":"Architecture Overview","text":"<p>This post-processor compiles algebraic equations defined in a custom DSL (Domain Specific Language), computes high-order derivatives (1st &amp; 2nd spatial derivatives) using tridiagonal finite differences, and leverages parallel MPI-IO blocks. Below is the primary compiler pipeline:</p> <pre><code>graph TD\n A[code_gen.py / DSL Input] --&gt;|AST Compiler Pipeline| B[post.py / Code Gen]\n B --&gt;|Generates budget kernels| C[m_calculate.f90]\n C --&gt;|LU Tridiagonal Solvers| D[Compact.f90]\n C --&gt;|Array allocations| E[m_arrays.f90]\n F[post.f90 / Main Driver] --&gt;|Orchestrates calculations| C\n F --&gt;|Parallelizes domain| G[m_openmpi.f90]\n F --&gt;|Loads run configuration| H[m_parameters.f90]\n I[pycompact.py / Legacy Bindings - Archived] -.-&gt;|Transitional| C</code></pre>"},{"location":"#navigation-guide","title":"Navigation Guide","text":"<ul> <li>Python API Reference: Automatically parsed API and signatures for the DSL parsers, topological compiler stages, and code generation routines.</li> <li>Fortran Core Reference: Standard documentation compiled by <code>FORD</code> covering tridiagonal compact solvers, math kernels, and MPI bindings.</li> <li>Archived Python Bindings: Legacy bindings wrapping calculation kernels.</li> </ul> <p>Generated automatically using industry-standard tools: FORD, MkDocs, and Material theme.</p>"},{"location":"fortran/","title":"Fortran Core API Reference","text":"<p>The Fortran core elements have been fully documented and compiled using FORD (FORtran Documenter), which extracts comments (<code>!&gt;</code> and <code>!!</code>) and draws rich module dependency graphs.</p>"},{"location":"fortran/#view-interactive-documentation","title":"View Interactive Documentation","text":"<p>\ud83d\udc49 Click Here to Open Interactive Fortran API Reference{: .md-button .md-button--primary .md-button--large }</p>"},{"location":"fortran/#core-modules-cataloged","title":"Core Modules Cataloged","text":"<ul> <li>[[Compact]]: Solves compact finite difference scheme equations using high-order tridiagonal/pentadiagonal schemes.</li> <li>[[m_calculate]]: Runs budget calculations, spatial derivatives, and pieces Arrhenius chemical kinetics.</li> <li>[[m_arrays]]: Handles array allocations and instant budget memory blocks.</li> <li>[[m_openmpi]]: Wraps domain sizing, grid splitting, and MPI communicators.</li> <li>[[m_parameters]]: Loads physical settings, boundary configurations, and grid sizes from file inputs.</li> <li>[[post]]: Entry driver performing budget calculation run tasks.</li> </ul>"},{"location":"archive/pycompact/","title":"Archived Python Bindings (<code>pycompact.py</code>)","text":"<p>!!! warning \"Archived/Legacy Component\" Historical Note: Originally, researchers manually wrote post-processing Fortran codes. To reduce this maintenance overhead, python bindings (<code>pycompact.py</code>) were introduced as a transitional wrapper. However, since the bindings did not significantly improve ease of use, we subsequently defined a custom DSL (Domain Specific Language) for describing post-processing operations and developed a compiler (<code>code_gen.py</code> &amp; <code>post.py</code>) to generate highly optimized Fortran codes. As a result, the python bindings are now archived.</p>"},{"location":"archive/pycompact/#pycompact","title":"<code>pycompact</code>","text":""},{"location":"archive/pycompact/#pycompact.CompactScheme","title":"<code>CompactScheme</code>","text":"<p>Python wrapper for the high-order compact finite difference scheme core.</p> <p>This wraps the compiled Fortran <code>compact</code> solver module, handling grid configurations, boundary periodicities, array allocations, and LU decompositions. It exposes differentiation methods ddx, ddy, and ddz to Python.</p> Source code in <code>code/archive/pycompact/pycompact.py</code> <pre><code>class CompactScheme:\n \"\"\"Python wrapper for the high-order compact finite difference scheme core.\n\n This wraps the compiled Fortran `compact` solver module, handling grid configurations,\n boundary periodicities, array allocations, and LU decompositions. It exposes\n differentiation methods ddx, ddy, and ddz to Python.\n \"\"\"\n\n def __init__ (self, nx, ny, nz, px, py, pz, lx, ly, lz):\n \"\"\"Initializes the CompactScheme solver.\n\n Args:\n nx (int): Grid points in X direction.\n ny (int): Grid points in Y direction.\n nz (int): Grid points in Z direction.\n px (bool): Periodic boundary condition flag for X direction.\n py (bool): Periodic boundary condition flag for Y direction.\n pz (bool): Periodic boundary condition flag for Z direction.\n lx (float): Domain size in X direction.\n ly (float): Domain size in Y direction.\n lz (float): Domain size in Z direction.\n \"\"\"\n\n pi8 = np.arccos(-1., dtype=np.float64)\n\n self.shape = (nz, ny, nx)\n\n self.px = px\n self.py = py\n self.pz = pz\n\n h = pi8 * lx / nx\n self.hx = h\n self.hy = h\n self.hz = h\n\n # Allocate LU\n compact.lxf = np.zeros(nx, dtype=np.float64)\n compact.lxs = np.zeros(nx, dtype=np.float64)\n compact.wxf = np.zeros(nx, dtype=np.float64)\n compact.wxs = np.zeros(nx, dtype=np.float64)\n\n compact.lyf = np.zeros(ny, dtype=np.float64)\n compact.lys = np.zeros(ny, dtype=np.float64)\n compact.wyf = np.zeros(ny, dtype=np.float64)\n compact.wys = np.zeros(ny, dtype=np.float64)\n\n compact.lzf = np.zeros(nz, dtype=np.float64)\n compact.lzs = np.zeros(nz, dtype=np.float64)\n compact.wzf = np.zeros(nz, dtype=np.float64)\n compact.wzs = np.zeros(nz, dtype=np.float64)\n\n bcx = 0 if px else 1\n bcy = 0 if py else 1\n bcz = 0 if pz else 1\n\n compact.ludcmp_calculate(nx, ny, nz, bcx, bcy, bcz)\n\n\n def test_ludcmp (self):\n pp = pprint.PrettyPrinter(indent=4)\n\n # First Derivative Non-periodic BC\n l1 = compact.test_nonp_lud1(self.shape[-1])\n\n # Second Derivative Non-periodic BC\n l2 = compact.test_nonp_lud2(self.shape[-1])\n\n print (\"Test Internally Calculated Non-periodic Coefs\")\n print (np.linalg.norm((l1 - compact.lxf)/compact.lxf))\n print (np.linalg.norm((l2 - compact.lxs)/compact.lxs))\n\n\n def py_rhs_1_np (self, x):\n dx = np.zeros(x.shape)\n\n h1 = 1./self.hx\n\n r1 = 7./3.\n r2 = 1./12.\n r3 = 3.\n a = -1.25\n b = 1.\n c = 0.25\n\n nd, n = x.shape\n\n dx[:, -2] = x[:, -1] - x[:, -3]\n dx[:, -1] = - (a*x[:, -1] + b*x[:, -2] + c*x[:, -3])\n dx[:, 0] = (a*x[:, 0] + b*x[:, 1] + c*x[:, 2])\n dx[:, 1] = x[:, 2] - x[:, 0]\n\n dx[:,-2] = dx[:,-2]*h1*r3\n dx[:,-1] = dx[:,-1]*h1\n dx[:,0] = dx[:,0]*h1\n dx[:,1] = dx[:,1]*h1*r3\n\n for i in range(2,n-2):\n t1=x[:,i+1]-x[:,i-1]\n t2=x[:,i+2]-x[:,i-2]\n dx[:,i]=h1*(r1*t1+r2*t2)\n\n return dx\n\n\n def py_tdslv(self, r, l):\n nd, n = r.shape\n\n r[:,0] = r[:,0] * l[0]\n\n for i in range(1,n):\n r[:,i] = l[i] * (r[:,i] - r[:,i-1])\n\n for i in range(n-1)[::-1]:\n r[:,i] = r[:,i] - l[i] * r[:,i+1]\n\n\n def test_dfnonp (self):\n\n x = np.sin(1.1 * np.arange(512) * self.hx).reshape((1,-1))\n\n exact = 1.1 * np.cos(1.1 * np.arange(512) * self.hx).reshape((1,-1))\n\n\n\n print (\"First Non-periodic RHS Test\")\n\n dx = self.py_rhs_1_np(x)\n\n dx_fortran = compact.rhs1np(self.hx, x)\n\n print (\"RelError Norm: \", np.linalg.norm((dx - dx_fortran) / dx_fortran))\n print (\"RelError Min : \", ((dx - dx_fortran) / dx_fortran).min())\n print (\"RelError Min : \", ((dx - dx_fortran) / dx_fortran).max())\n\n\n\n\n print (\"First Non-periodic TD SOLVE Test\")\n\n l1 = compact.test_nonp_lud1(512)\n\n self.py_tdslv(dx, l1)\n\n compact.tdslv(dx_fortran,l1)\n\n print (\"dx - exact\")\n print (\"RelError Norm: \", np.linalg.norm((dx - exact) / exact))\n print (\"RelError Min : \", ((dx - exact) / exact).min())\n print (\"RelError Min : \", ((dx - exact) / exact).max())\n\n print (\"dx_fortran - exact\")\n print (\"RelError Norm: \", np.linalg.norm((dx_fortran - exact) / exact))\n print (\"RelError Min : \", ((dx_fortran - exact) / exact).min())\n print (\"RelError Min : \", ((dx_fortran - exact) / exact).max())\n\n '''\n import pprint\n pp = pprint.PrettyPrinter(indent=4)\n\n pp.pprint ((dx - exact) / exact)\n\n pp.pprint ((zip ((dx - exact).ravel(), dx.ravel(), exact.ravel())))\n '''\n\n def verify_nonp_lud1(self):\n\n print (\"Non-periodic coef first derivative\")\n\n nx = 512\n aa = np.ones(nx) * 3.\n aa[0] = 0.5\n aa[1] = 4.\n aa[-2] = 4.\n aa[-1] = 0.5\n\n coef = compact.stdlu(aa)\n\n coef_verify = self.py_stdlu(aa)\n\n print (\"RelError Norm: \", np.linalg.norm((coef - coef_verify)/coef_verify))\n\n\n def verify_nonp_lud2(self):\n\n print (\"Non-periodic coef second derivative\")\n\n nx = 512\n aa = np.ones(nx) * 3.\n aa[0] = 2./11.\n aa[1] = 10.\n aa[-2] = 10.\n aa[-1] = 2./11.\n\n coef = compact.stdlu(aa)\n\n coef_verify = self.py_stdlu(aa)\n\n print (\"RelError Norm: \", np.linalg.norm((coef - coef_verify)/coef_verify))\n\n\n def py_stdlu(self, aa):\n coef = np.ones(aa.shape)/aa[0]\n\n print (\"coef.size = \", coef.size)\n\n for i in range(1,coef.size):\n coef[i]=1.0/(aa[i]-coef[i-1])\n\n return coef\n\n\n def ddx (self, src):\n \"\"\"Computes the first-order spatial derivative in the X direction.\n\n Args:\n src (numpy.ndarray): 3D input field array matching (nz, ny, nx) shape.\n\n Returns:\n numpy.ndarray: 3D first derivative array in the X direction.\n \"\"\"\n\n if src.shape != self.shape:\n print (\"error\")\n\n nz, ny, nx = self.shape\n\n xsrc = np.zeros((ny, nx,), dtype=np.float64, order=\"F\")\n\n # dst = np.zeros((nx, ny, nz,), order=\"F\")\n dst = np.zeros((nz, ny, nx,), dtype=np.float64,)\n\n if self.px: # Periodic BC\n for i in range(nz):\n dst[i] = compact.dfp(self.hx, src[i], 1)\n\n else:\n for i in range(nz):\n dst[i] = compact.dfnonp(self.hx, src[i], 1)\n\n # return np.swapaxes(dst, 1, 2)\n return dst\n\n def ddy (self, src):\n \"\"\"Computes the first-order spatial derivative in the Y direction.\n\n Args:\n src (numpy.ndarray): 3D input field array matching (nz, ny, nx) shape.\n\n Returns:\n numpy.ndarray: 3D first derivative array in the Y direction.\n \"\"\"\n\n if src.shape != self.shape:\n print (\"error\")\n\n nz, ny, nx = self.shape\n\n #xsrc = np.zeros((ny, nx,), dtype=np.float64, order=\"F\")\n\n # dst = np.zeros((nx, ny, nz,), order=\"F\")\n dst = np.zeros((nz, ny, nx,), dtype=np.float64,)\n\n if self.py: # Periodic BC\n for i in range(nz):\n dst[i] = compact.dfp(self.hx, src[i].T, 2).T\n\n else:\n for i in range(nz):\n dst[i] = compact.dfnonp(self.hx, src[i].T, 2).T\n\n # return np.swapaxes(dst, 1, 2)\n return dst\n\n def ddz (self, src):\n \"\"\"Computes the first-order spatial derivative in the Z direction.\n\n Args:\n src (numpy.ndarray): 3D input field array matching (nz, ny, nx) shape.\n\n Returns:\n numpy.ndarray: 3D first derivative array in the Z direction.\n \"\"\"\n\n if src.shape != self.shape:\n print (\"error\")\n\n nz, ny, nx = self.shape\n\n\n # dst = np.zeros((nx, ny, nz,), order=\"F\")\n dst = np.zeros((nz, ny, nx,), dtype=np.float64,)\n\n if self.pz: # Periodic BC\n for i in range(ny):\n dst[:,i,:] = compact.dfp(self.hx, src[:,i,:], 3)\n\n else:\n for i in range(ny):\n dst[:,i,:] = compact.dfnonp(self.hx, src[:,i,:], 3)\n\n # return np.swapaxes(dst, 1, 2)\n return dst\n\n def port_nonp_coef (self):\n\n # SUBROUTINE nonp_lud(xyz,xx)\n nz, ny, nx = self.shape\n xx = nx\n\n lxf = np.zeros(xx)\n lxs = np.zeros(xx)\n\n aa = np.zeros(xx)\n aa[:] = 3.\n\n aa[0]=0.5 \n aa[1]=4.\n aa[-2]=4. \n aa[-1]=0.5\n\n # first derivative\n compact.stdlu(aa,lxf) \n\n aa[:] = 5.5\n\n aa[0]=2./11. \n aa[1]=10.\n aa[-2]=10. \n aa[-1]=2./11.\n\n # second derivative\n compact.stdlu(aa,lxs)\n\n compact.lxf = lxf\n compact.lxs = lxs\n</code></pre>"},{"location":"archive/pycompact/#pycompact.CompactScheme.__init__","title":"<code>__init__(nx, ny, nz, px, py, pz, lx, ly, lz)</code>","text":"<p>Initializes the CompactScheme solver.</p> <p>Parameters:</p> Name Type Description Default <code>nx</code> <code>int</code> <p>Grid points in X direction.</p> required <code>ny</code> <code>int</code> <p>Grid points in Y direction.</p> required <code>nz</code> <code>int</code> <p>Grid points in Z direction.</p> required <code>px</code> <code>bool</code> <p>Periodic boundary condition flag for X direction.</p> required <code>py</code> <code>bool</code> <p>Periodic boundary condition flag for Y direction.</p> required <code>pz</code> <code>bool</code> <p>Periodic boundary condition flag for Z direction.</p> required <code>lx</code> <code>float</code> <p>Domain size in X direction.</p> required <code>ly</code> <code>float</code> <p>Domain size in Y direction.</p> required <code>lz</code> <code>float</code> <p>Domain size in Z direction.</p> required Source code in <code>code/archive/pycompact/pycompact.py</code> <pre><code>def __init__ (self, nx, ny, nz, px, py, pz, lx, ly, lz):\n \"\"\"Initializes the CompactScheme solver.\n\n Args:\n nx (int): Grid points in X direction.\n ny (int): Grid points in Y direction.\n nz (int): Grid points in Z direction.\n px (bool): Periodic boundary condition flag for X direction.\n py (bool): Periodic boundary condition flag for Y direction.\n pz (bool): Periodic boundary condition flag for Z direction.\n lx (float): Domain size in X direction.\n ly (float): Domain size in Y direction.\n lz (float): Domain size in Z direction.\n \"\"\"\n\n pi8 = np.arccos(-1., dtype=np.float64)\n\n self.shape = (nz, ny, nx)\n\n self.px = px\n self.py = py\n self.pz = pz\n\n h = pi8 * lx / nx\n self.hx = h\n self.hy = h\n self.hz = h\n\n # Allocate LU\n compact.lxf = np.zeros(nx, dtype=np.float64)\n compact.lxs = np.zeros(nx, dtype=np.float64)\n compact.wxf = np.zeros(nx, dtype=np.float64)\n compact.wxs = np.zeros(nx, dtype=np.float64)\n\n compact.lyf = np.zeros(ny, dtype=np.float64)\n compact.lys = np.zeros(ny, dtype=np.float64)\n compact.wyf = np.zeros(ny, dtype=np.float64)\n compact.wys = np.zeros(ny, dtype=np.float64)\n\n compact.lzf = np.zeros(nz, dtype=np.float64)\n compact.lzs = np.zeros(nz, dtype=np.float64)\n compact.wzf = np.zeros(nz, dtype=np.float64)\n compact.wzs = np.zeros(nz, dtype=np.float64)\n\n bcx = 0 if px else 1\n bcy = 0 if py else 1\n bcz = 0 if pz else 1\n\n compact.ludcmp_calculate(nx, ny, nz, bcx, bcy, bcz)\n</code></pre>"},{"location":"archive/pycompact/#pycompact.CompactScheme.ddx","title":"<code>ddx(src)</code>","text":"<p>Computes the first-order spatial derivative in the X direction.</p> <p>Parameters:</p> Name Type Description Default <code>src</code> <code>ndarray</code> <p>3D input field array matching (nz, ny, nx) shape.</p> required <p>Returns:</p> Type Description <p>numpy.ndarray: 3D first derivative array in the X direction.</p> Source code in <code>code/archive/pycompact/pycompact.py</code> <pre><code>def ddx (self, src):\n \"\"\"Computes the first-order spatial derivative in the X direction.\n\n Args:\n src (numpy.ndarray): 3D input field array matching (nz, ny, nx) shape.\n\n Returns:\n numpy.ndarray: 3D first derivative array in the X direction.\n \"\"\"\n\n if src.shape != self.shape:\n print (\"error\")\n\n nz, ny, nx = self.shape\n\n xsrc = np.zeros((ny, nx,), dtype=np.float64, order=\"F\")\n\n # dst = np.zeros((nx, ny, nz,), order=\"F\")\n dst = np.zeros((nz, ny, nx,), dtype=np.float64,)\n\n if self.px: # Periodic BC\n for i in range(nz):\n dst[i] = compact.dfp(self.hx, src[i], 1)\n\n else:\n for i in range(nz):\n dst[i] = compact.dfnonp(self.hx, src[i], 1)\n\n # return np.swapaxes(dst, 1, 2)\n return dst\n</code></pre>"},{"location":"archive/pycompact/#pycompact.CompactScheme.ddy","title":"<code>ddy(src)</code>","text":"<p>Computes the first-order spatial derivative in the Y direction.</p> <p>Parameters:</p> Name Type Description Default <code>src</code> <code>ndarray</code> <p>3D input field array matching (nz, ny, nx) shape.</p> required <p>Returns:</p> Type Description <p>numpy.ndarray: 3D first derivative array in the Y direction.</p> Source code in <code>code/archive/pycompact/pycompact.py</code> <pre><code>def ddy (self, src):\n \"\"\"Computes the first-order spatial derivative in the Y direction.\n\n Args:\n src (numpy.ndarray): 3D input field array matching (nz, ny, nx) shape.\n\n Returns:\n numpy.ndarray: 3D first derivative array in the Y direction.\n \"\"\"\n\n if src.shape != self.shape:\n print (\"error\")\n\n nz, ny, nx = self.shape\n\n #xsrc = np.zeros((ny, nx,), dtype=np.float64, order=\"F\")\n\n # dst = np.zeros((nx, ny, nz,), order=\"F\")\n dst = np.zeros((nz, ny, nx,), dtype=np.float64,)\n\n if self.py: # Periodic BC\n for i in range(nz):\n dst[i] = compact.dfp(self.hx, src[i].T, 2).T\n\n else:\n for i in range(nz):\n dst[i] = compact.dfnonp(self.hx, src[i].T, 2).T\n\n # return np.swapaxes(dst, 1, 2)\n return dst\n</code></pre>"},{"location":"archive/pycompact/#pycompact.CompactScheme.ddz","title":"<code>ddz(src)</code>","text":"<p>Computes the first-order spatial derivative in the Z direction.</p> <p>Parameters:</p> Name Type Description Default <code>src</code> <code>ndarray</code> <p>3D input field array matching (nz, ny, nx) shape.</p> required <p>Returns:</p> Type Description <p>numpy.ndarray: 3D first derivative array in the Z direction.</p> Source code in <code>code/archive/pycompact/pycompact.py</code> <pre><code>def ddz (self, src):\n \"\"\"Computes the first-order spatial derivative in the Z direction.\n\n Args:\n src (numpy.ndarray): 3D input field array matching (nz, ny, nx) shape.\n\n Returns:\n numpy.ndarray: 3D first derivative array in the Z direction.\n \"\"\"\n\n if src.shape != self.shape:\n print (\"error\")\n\n nz, ny, nx = self.shape\n\n\n # dst = np.zeros((nx, ny, nz,), order=\"F\")\n dst = np.zeros((nz, ny, nx,), dtype=np.float64,)\n\n if self.pz: # Periodic BC\n for i in range(ny):\n dst[:,i,:] = compact.dfp(self.hx, src[:,i,:], 3)\n\n else:\n for i in range(ny):\n dst[:,i,:] = compact.dfnonp(self.hx, src[:,i,:], 3)\n\n # return np.swapaxes(dst, 1, 2)\n return dst\n</code></pre>"},{"location":"python/code_gen/","title":"Code Generator (<code>code_gen.py</code>)","text":""},{"location":"python/code_gen/#code_gen","title":"<code>code_gen</code>","text":""},{"location":"python/code_gen/#code_gen.VersionInfo","title":"<code>VersionInfo</code>","text":"<p> Bases: <code>object</code></p> <p>Encapsulates build and version metadata for the code generator execution.</p> <p>This class queries the current Git repository state to fetch the HEAD commit hash and checks if there are uncommitted changes, appending metadata to identify the exact codebase state used to generate the output files.</p> Source code in <code>code/code_gen/code_gen.py</code> <pre><code>class VersionInfo(object):\n \"\"\"Encapsulates build and version metadata for the code generator execution.\n\n This class queries the current Git repository state to fetch the HEAD commit\n hash and checks if there are uncommitted changes, appending metadata to\n identify the exact codebase state used to generate the output files.\n \"\"\"\n\n def __init__(self, input_raw):\n \"\"\"Initializes VersionInfo with build date, git hash, and terms metadata.\n\n Args:\n input_raw (str): The raw input string containing DSL term definitions.\n \"\"\"\n bd = 'build date: {}'\n bb = 'build base: {}'\n\n self.build_date = bd.format(datetime.datetime.today().ctime())\n\n try:\n self.build_base = bb.format(sp.check_output([\"git\", \"rev-parse\", \"HEAD\"]).strip())\n except sp.CalledProcessError:\n self.build_base = \"None\"\n\n try:\n sp.check_output(\"git diff --exit-code\".split())\n sp.check_output(\"git diff --cached --exit-code\".split())\n self.off_base = \"\"\n except sp.CalledProcessError:\n self.off_base = \"built with changes not commited\"\n\n tinfo = '''\n================================================================================\n************************************ terms *************************************\n--------------------------------------------------------------------------------\n{}\n================================================================================\n'''\n\n self.term_info = tinfo.format(input_raw)\n\n def fparams(self):\n \"\"\"Formats the collected build parameters into a single string.\n\n Returns:\n str: Multi-line string summarizing build date, revision, and terms details.\n \"\"\"\n return \"\\n\".join([self.build_date, self.build_base, self.off_base, self.term_info])\n</code></pre>"},{"location":"python/code_gen/#code_gen.VersionInfo.__init__","title":"<code>__init__(input_raw)</code>","text":"<p>Initializes VersionInfo with build date, git hash, and terms metadata.</p> <p>Parameters:</p> Name Type Description Default <code>input_raw</code> <code>str</code> <p>The raw input string containing DSL term definitions.</p> required Source code in <code>code/code_gen/code_gen.py</code> <pre><code> def __init__(self, input_raw):\n \"\"\"Initializes VersionInfo with build date, git hash, and terms metadata.\n\n Args:\n input_raw (str): The raw input string containing DSL term definitions.\n \"\"\"\n bd = 'build date: {}'\n bb = 'build base: {}'\n\n self.build_date = bd.format(datetime.datetime.today().ctime())\n\n try:\n self.build_base = bb.format(sp.check_output([\"git\", \"rev-parse\", \"HEAD\"]).strip())\n except sp.CalledProcessError:\n self.build_base = \"None\"\n\n try:\n sp.check_output(\"git diff --exit-code\".split())\n sp.check_output(\"git diff --cached --exit-code\".split())\n self.off_base = \"\"\n except sp.CalledProcessError:\n self.off_base = \"built with changes not commited\"\n\n tinfo = '''\n================================================================================\n************************************ terms *************************************\n--------------------------------------------------------------------------------\n{}\n================================================================================\n'''\n\n self.term_info = tinfo.format(input_raw)\n</code></pre>"},{"location":"python/code_gen/#code_gen.VersionInfo.fparams","title":"<code>fparams()</code>","text":"<p>Formats the collected build parameters into a single string.</p> <p>Returns:</p> Name Type Description <code>str</code> <p>Multi-line string summarizing build date, revision, and terms details.</p> Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def fparams(self):\n \"\"\"Formats the collected build parameters into a single string.\n\n Returns:\n str: Multi-line string summarizing build date, revision, and terms details.\n \"\"\"\n return \"\\n\".join([self.build_date, self.build_base, self.off_base, self.term_info])\n</code></pre>"},{"location":"python/code_gen/#code_gen.build_info","title":"<code>build_info(terms_raw)</code>","text":"<p>Generates and prints build information for the current code generation run.</p> <p>Parameters:</p> Name Type Description Default <code>terms_raw</code> <code>str</code> <p>The raw string contents of the DSL terms specification input file.</p> required Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def build_info(terms_raw):\n \"\"\"Generates and prints build information for the current code generation run.\n\n Args:\n terms_raw (str): The raw string contents of the DSL terms specification input file.\n \"\"\"\n vinfo = VersionInfo(terms_raw)\n print(vinfo.fparams())\n</code></pre>"},{"location":"python/code_gen/#code_gen.compile_terms","title":"<code>compile_terms(terms_raw)</code>","text":"<p>Parses DSL terms spec and runs it through the five compiler stages.</p> <p>This function initializes a new <code>CompilationContext</code> and executes the compiler pipeline sequentially: parsing, derivative/fluctuation expansion, SymPy expression simplification, data dependency resolution, and array buffer pooling.</p> <p>Parameters:</p> Name Type Description Default <code>terms_raw</code> <code>str</code> <p>The raw string contents of the DSL terms specification input file.</p> required <p>Returns:</p> Name Type Description <code>CompilationContext</code> <p>The fully compiled and optimized compilation context.</p> Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def compile_terms(terms_raw):\n \"\"\"Parses DSL terms spec and runs it through the five compiler stages.\n\n This function initializes a new `CompilationContext` and executes the compiler pipeline\n sequentially: parsing, derivative/fluctuation expansion, SymPy expression simplification,\n data dependency resolution, and array buffer pooling.\n\n Args:\n terms_raw (str): The raw string contents of the DSL terms specification input file.\n\n Returns:\n CompilationContext: The fully compiled and optimized compilation context.\n \"\"\"\n ctx = CompilationContext()\n ParserStage().execute(terms_raw, ctx)\n DerivativeExpansionStage().execute(ctx)\n SympySimplificationStage().execute(ctx)\n DependencyResolutionStage().execute(ctx)\n SympyOptimizationStage().execute(ctx)\n return ctx\n</code></pre>"},{"location":"python/code_gen/#code_gen.escape_fortran_string","title":"<code>escape_fortran_string(s)</code>","text":"<p>Escapes string content for standard Fortran source formatting.</p> <p>Converts internal double quotes into double-double quotes and splits the string lines, wrapping them in Fortran concatenation syntax <code>// char(10) // &amp;</code> to respect line length limit.</p> <p>Parameters:</p> Name Type Description Default <code>s</code> <code>str</code> <p>The raw string to escape.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>The escaped and formatted Fortran string parameter literal.</p> Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def escape_fortran_string(s):\n \"\"\"Escapes string content for standard Fortran source formatting.\n\n Converts internal double quotes into double-double quotes and splits the string lines,\n wrapping them in Fortran concatenation syntax `// char(10) // &amp;` to respect line length limit.\n\n Args:\n s (str): The raw string to escape.\n\n Returns:\n str: The escaped and formatted Fortran string parameter literal.\n \"\"\"\n escaped = s.replace('\"', '\"\"')\n lines = escaped.splitlines()\n if not lines:\n return '\"\"'\n formatted_lines = [f'\"{line}\"' for line in lines]\n return ' // char(10) // &amp;\\n '.join(formatted_lines)\n</code></pre>"},{"location":"python/code_gen/#code_gen.generate_build_info_module","title":"<code>generate_build_info_module(terms_raw)</code>","text":"<p>Generates a complete standard Fortran module containing build info and LaTeX equations.</p> <p>The generated module contains metadata about the compiler run, including the build base Git hash, and a string representations of the LaTeX equations.</p> <p>Parameters:</p> Name Type Description Default <code>terms_raw</code> <code>str</code> <p>The raw string contents of the DSL terms specification input file.</p> required Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def generate_build_info_module(terms_raw):\n \"\"\"Generates a complete standard Fortran module containing build info and LaTeX equations.\n\n The generated module contains metadata about the compiler run, including the build base Git hash,\n and a string representations of the LaTeX equations.\n\n Args:\n terms_raw (str): The raw string contents of the DSL terms specification input file.\n \"\"\"\n vinfo = VersionInfo(terms_raw)\n build_info_str = vinfo.fparams()\n\n ctx = compile_terms(terms_raw)\n latex_str = get_latex_equations_str(ctx)\n\n fortran_build_info = escape_fortran_string(build_info_str)\n fortran_latex = escape_fortran_string(latex_str)\n\n fortran_code = f\"\"\"module m_build_info\n implicit none\n character(len=*), parameter :: build_info_str = &amp;\n {fortran_build_info}\n character(len=*), parameter :: latex_equations_str = &amp;\n {fortran_latex}\nend module m_build_info\n\"\"\"\n print(fortran_code)\n</code></pre>"},{"location":"python/code_gen/#code_gen.get_latex_equations_str","title":"<code>get_latex_equations_str(ctx)</code>","text":"<p>Generates the LaTeX equations dictionary string from the context.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>The compiled context containing the averaged fields.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>A formatted string representing a Python dictionary mapping field names to LaTeX code.</p> Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def get_latex_equations_str(ctx):\n \"\"\"Generates the LaTeX equations dictionary string from the context.\n\n Args:\n ctx (CompilationContext): The compiled context containing the averaged fields.\n\n Returns:\n str: A formatted string representing a Python dictionary mapping field names to LaTeX code.\n \"\"\"\n latex_lines = [\"{\"]\n for avg in ctx.averaged.values():\n latex_lines.append(' \"{}\" : r\"${}$\",'.format(avg.name, avg.latex))\n latex_lines.append(\"}\")\n return \"\\n\".join(latex_lines)\n</code></pre>"},{"location":"python/code_gen/#code_gen.test","title":"<code>test(terms_raw, report=False, latex=False)</code>","text":"<p>Compiles the post-processing term specifications from DSL into targets.</p> <p>This compiles the Lark AST through all 4 pipeline stages and outputs the resulting Fortran source code via FortranProgramWriter, a LaTeX equation dictionary via LatexWriter, or an IR report via ReportWriter.</p> <p>Parameters:</p> Name Type Description Default <code>terms_raw</code> <code>str</code> <p>The raw string contents of the DSL terms specification.</p> required <code>report</code> <code>bool</code> <p>If True, prints a JSON-based compilation IR report instead. Defaults to False.</p> <code>False</code> <code>latex</code> <code>bool</code> <p>If True, prints LaTeX equation dictionary instead. Defaults to False.</p> <code>False</code> Source code in <code>code/code_gen/code_gen.py</code> <pre><code>def test(terms_raw, report=False, latex=False):\n \"\"\"Compiles the post-processing term specifications from DSL into targets.\n\n This compiles the Lark AST through all 4 pipeline stages\n and outputs the resulting Fortran source code via FortranProgramWriter,\n a LaTeX equation dictionary via LatexWriter, or an IR report via ReportWriter.\n\n Args:\n terms_raw (str): The raw string contents of the DSL terms specification.\n report (bool, optional): If True, prints a JSON-based compilation IR report instead. Defaults to False.\n latex (bool, optional): If True, prints LaTeX equation dictionary instead. Defaults to False.\n \"\"\"\n ctx = compile_terms(terms_raw)\n\n if report:\n ReportWriter().write(ctx)\n elif latex:\n LatexWriter().write(ctx)\n else:\n FortranProgramWriter().write(ctx)\n</code></pre>"},{"location":"python/post/","title":"Compiler Stages (<code>post.py</code>)","text":""},{"location":"python/post/#post","title":"<code>post</code>","text":""},{"location":"python/post/#post--dns-post-processing-code-generator-core-postpy","title":"DNS Post-Processing Code Generator Core (post.py)","text":"<p>\uc774 \ubaa8\ub4c8\uc740 \ub09c\ub958 \ubc0f \uc5f0\uc18c DNS(Direct Numerical Simulation) \ub370\uc774\ud130\uc758 \ud6c4\ucc98\ub9ac\ub97c \uc704\ud55c \uace0\uc131\ub2a5 Fortran \ucf54\ub4dc\ub97c \uc0dd\uc131\ud558\ub294 \ucef4\ud30c\uc77c\ub7ec\uc758 \ucf54\uc5b4\uc785\ub2c8\ub2e4. \uc0ac\uc6a9\uc790\uac00 \uc815\uc758\ud55c DSL(Domain Specific Language) \uc785\ub825 \uc2dd\uc744 \uc77d\uc5b4 \ud30c\uc2f1\ud55c \ud6c4, \ub2e4\uc74c\uacfc \uac19\uc740 4\ub2e8\uacc4 \ucd5c\uc801\ud654 \ucef4\ud30c\uc77c \uacfc\uc815\uc744 \uac70\uccd0 \uadf9\ub3c4\ub85c \ucd5c\uc801\ud654\ub41c 3\ucc28\uc6d0 \ub8e8\ud504 Fortran \ubaa8\ub4c8 \ucf54\ub4dc\ub97c \uc790\ub3d9 \uc0dd\uc131\ud569\ub2c8\ub2e4.</p> <p>[\ucef4\ud30c\uc77c\ub7ec \ud30c\uc774\ud504\ub77c\uc778 4\ub2e8\uacc4 \uac1c\uc694] 1. Stage 1 (AST \uc218\uc9d1 \ubc0f \ubcc0\uc218 \uc815\uc758): - Lark \ud30c\uc11c\uac00 \uc0dd\uc131\ud55c AST(Abstract Syntax Tree)\ub97c \uc21c\ud68c\ud558\uba70 \uae30\ubcf8 \uc785\ub825 \ubcc0\uc218(Primary), \uacc4\uc0b0\uc774 \ud544\uc694\ud55c \ub300\uc785\uc2dd(Derived), \uadf8\ub9ac\uace0 \ud1b5\uacc4 \ubb3c\ub9ac\ub7c9 \uacc4\uc0b0\uc744 \uc704\ud55c \ud3c9\uade0\ud654 \ubcc0\uc218(Averaged)\ub97c \ucd94\ucd9c\ud558\uace0 \ud544\ub4dc \uba54\ud0c0\ub370\uc774\ud130 \uac1d\uccb4\ub97c \uad6c\uc131\ud569\ub2c8\ub2e4. 2. Stage 2 (\uc218\uce58 \ubbf8\ubd84 \ubc0f \ubcc0\ub3d9\ub7c9 \ud655\uc7a5): - \uc218\uc2dd \ub0b4\uc5d0 \uc218\uce58 \ubbf8\ubd84\uc790(ddx, d2dy \ub4f1)\ub098 \ubcc0\ub3d9\ub7c9(fluctuation, u')\uc774 \uc874\uc7ac\ud558\uba74, \uc774\ub97c \ubb3c\ub9ac\uc801\uc73c\ub85c \ucc28\ubd84 \uc5f0\uc0b0\ud560 \uc911\uac04 \ubbf8\ubd84 \ud544\ub4dc(DerivedField) \ubc0f \ubcc0\ub3d9\ub7c9 \ud544\ub4dc(FluctuationField)\ub85c \uc790\ub3d9 \ubcc0\ud658\ud558\uace0 \ubcc0\uc218 \ud14c\uc774\ube14\uc5d0 \ub4f1\ub85d\ud558\uc5ec \ud655\uc7a5\ud569\ub2c8\ub2e4. 3. Stage 3 (\uc758\uc874\uc131 \ubd84\uc11d \ubc0f \uc704\uc0c1 \uc815\ub82c): - \ud544\ub4dc \uac04\uc758 \uc120\ud6c4 \uc5f0\uc0b0 \uad00\uacc4\ub97c \ubd84\uc11d\ud558\uc5ec \uc720\ud5a5 \uc758\uc874\uc131 \uadf8\ub798\ud504(Directed Dependency Graph)\ub97c \uc0dd\uc131\ud569\ub2c8\ub2e4. - \ub09c\ub958 \ud1b5\uacc4\uc758 \ud2b9\uc131\uc0c1 \ud3c9\uade0 \uc5f0\uc0b0\uc744 \uae30\uc900\uc73c\ub85c \"\ud3c9\uade0\uce58 \uacc4\uc0b0 \uc804\uc758 \ub8e8\ud504(Pass 1)\"\uc640 \"\ud3c9\uade0\uce58\ub97c \uad6c\ud55c \ud6c4 \ubcc0\ub3d9\ub7c9\uc744 \uacc4\uc0b0\ud558\ub294 \ub8e8\ud504(Pass 2)\"\ub85c \uc804\uccb4 \uc5f0\uc0b0 \ube14\ub85d\uc744 \ub17c\ub9ac\uc801\uc73c\ub85c \ubd84\ud560\ud558\uace0, \uac01\uac01\uc758 \ube14\ub85d \ub0b4\uc5d0\uc11c \uc62c\ubc14\ub978 \uc21c\uc11c\ub85c \uacc4\uc0b0\ub418\ub3c4\ub85d \uc704\uc0c1 \uc815\ub82c(Topological Sort)\uc744 \uc218\ud589\ud569\ub2c8\ub2e4. 4. Stage 4 (\uc218\uc2dd \uae30\ud638 \ucd5c\uc801\ud654, Liveness \ubd84\uc11d \ubc0f Buffer Array Pooling): - SymPy \uae30\ud638 \uc218\ud559 \ub77c\uc774\ube0c\ub7ec\ub9ac\ub97c \uc774\uc6a9\ud558\uc5ec \ubcf5\uc7a1\ud55c 3\ucc28\uc6d0 \uc218\uc2dd\uc744 \ub300\uc218\uc801\uc73c\ub85c \uac04\uc18c\ud654\ud558\uace0, \uacf5\ud1b5 \ubd80\ubd84 \uc2dd \uc81c\uac70(CSE)\ub97c \uc801\uc6a9\ud558\uc5ec \uc5f0\uc0b0 \ube44\uc6a9(Flops)\uc744 \ucd5c\uc801\ud654\ud569\ub2c8\ub2e4. - \uaca9\uc790 \ub370\uc774\ud130\uac00 \uac70\ub300\ud558\ubbc0\ub85c \ubaa8\ub4e0 \ubcc0\uc218\uc5d0 \uac1c\ubcc4 3D \ubc30\uc5f4\uc744 \ud560\ub2f9\ud558\uba74 \uba54\ubaa8\ub9ac\uac00 \uace0\uac08\ub429\ub2c8\ub2e4. \uc774\ub97c \ubc29\uc9c0\ud558\uae30 \uc704\ud574 \ubcc0\uc218\ub4e4\uc758 \uc0dd\uba85 \uc8fc\uae30(Liveness Window)\ub97c \uc218\ud559\uc801\uc73c\ub85c \ucd94\uc801\ud558\uace0, \ub3d9\uc801 \uba54\ubaa8\ub9ac \ud480\uc744 \uad6c\ucd95\ud558\uc5ec \ub3d9\uc2dc\uc5d0 \ud65c\uc131\ud654\ub418\uc9c0 \uc54a\ub294 \uc784\uc2dc \ubcc0\uc218\ub4e4\uc774 \uacf5\ud1b5\uc758 \uc81c\ud55c\ub41c \ubc84\ud37c \ubc30\uc5f4(xyzbuffer0, xyzbuffer1, ...)\uc744 \ub098\ub204\uc5b4 \uc0ac\uc6a9(Array Pooling)\ud558\ub3c4\ub85d \ud560\ub2f9\ud558\uc5ec \uba54\ubaa8\ub9ac \uc0ac\uc6a9\ub7c9\uc744 \ucd5c\uc18c\ud654\ud569\ub2c8\ub2e4.</p>"},{"location":"python/post/#post.ArrayFCodePrinter","title":"<code>ArrayFCodePrinter</code>","text":"<p> Bases: <code>FCodePrinter</code></p> <p>Custom SymPy printer that formats symbols as Fortran multidimensional array accesses.</p> <p>Transforms plain SymPy symbols into: - 3D grid accesses (e.g., var(i,j,k)) for spatial fields. - 1D array accesses (e.g., var(i)) for spatial averages. - Subtraction expressions (e.g., (u(i,j,k) - avg_u(i))) for fluctuation variables.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class ArrayFCodePrinter(FCodePrinter):\n \"\"\"Custom SymPy printer that formats symbols as Fortran multidimensional array accesses.\n\n Transforms plain SymPy symbols into:\n - 3D grid accesses (e.g., var(i,j,k)) for spatial fields.\n - 1D array accesses (e.g., var(i)) for spatial averages.\n - Subtraction expressions (e.g., (u(i,j,k) - avg_u(i))) for fluctuation variables.\n \"\"\"\n\n def __init__(self, settings=None, array_symbols=None, avg_symbols=None):\n \"\"\"Initializes ArrayFCodePrinter with array settings and symbol catalogs.\n\n Args:\n settings (dict, optional): Printer settings configuration. Defaults to None.\n array_symbols (dict, optional): Maps 3D fields to their buffer array names. Defaults to None.\n avg_symbols (dict, optional): Maps averaged fields to their 1D arrays. Defaults to None.\n \"\"\"\n settings = settings or {}\n settings.setdefault('source_format', 'free') # Default to free-form Fortran 95\n settings.setdefault('standard', 95)\n super().__init__(settings)\n self.array_symbols = array_symbols or {}\n self.avg_symbols = avg_symbols or {}\n\n def _print_Float(self, expr):\n \"\"\"Prints Float constants with double precision (d0) suffix.\n\n Ensures precision is not degraded during Fortran compilation.\n\n Args:\n expr (sympy.Float): SymPy float node.\n\n Returns:\n str: Double precision literal string.\n \"\"\"\n val = str(expr)\n if 'e' in val or 'E' in val:\n return val.replace('e', 'd').replace('E', 'd')\n if '.' not in val:\n return val + \".0d0\"\n return val + \"d0\"\n\n def _print_Symbol(self, expr):\n \"\"\"Maps a SymPy Symbol to a Fortran array expression.\n\n Args:\n expr (sympy.Symbol): SymPy Symbol to print.\n\n Returns:\n str: Formatted Fortran variable access or inline fluctuation calculation.\n \"\"\"\n name = expr.name\n # 1. 3D grid array\n if name in self.array_symbols:\n return f\"{self.array_symbols[name]}(i,j,k)\"\n # 2. 1D averaged array\n if name in self.avg_symbols:\n return f\"{self.avg_symbols[name]}(i)\"\n # 3. Fluctuation substitution (e.g. u' -&gt; u - &lt;u_w&gt;)\n if name.endswith(\"__prime\"):\n base = name[:-7]\n arr = self.array_symbols.get(base, base)\n avg_name = f\"avg_{base}\"\n printed_avg = f\"{self.avg_symbols.get(avg_name, avg_name)}(i)\"\n return f\"({arr}(i,j,k) - {printed_avg})\"\n return name\n\n def _print_Function(self, expr):\n \"\"\"Prints custom non-standard functions securely in Fortran output.\n\n Fallback logic for rxn_rate, udf, etc.\n\n Args:\n expr (sympy.Function): SymPy Function node.\n\n Returns:\n str: Standard Fortran call syntax for the function.\n \"\"\"\n try:\n return super()._print_Function(expr)\n except Exception:\n args = \", \".join(self.doprint(arg) for arg in expr.args)\n return f\"{expr.func.__name__}({args})\"\n</code></pre>"},{"location":"python/post/#post.ArrayFCodePrinter.__init__","title":"<code>__init__(settings=None, array_symbols=None, avg_symbols=None)</code>","text":"<p>Initializes ArrayFCodePrinter with array settings and symbol catalogs.</p> <p>Parameters:</p> Name Type Description Default <code>settings</code> <code>dict</code> <p>Printer settings configuration. Defaults to None.</p> <code>None</code> <code>array_symbols</code> <code>dict</code> <p>Maps 3D fields to their buffer array names. Defaults to None.</p> <code>None</code> <code>avg_symbols</code> <code>dict</code> <p>Maps averaged fields to their 1D arrays. Defaults to None.</p> <code>None</code> Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, settings=None, array_symbols=None, avg_symbols=None):\n \"\"\"Initializes ArrayFCodePrinter with array settings and symbol catalogs.\n\n Args:\n settings (dict, optional): Printer settings configuration. Defaults to None.\n array_symbols (dict, optional): Maps 3D fields to their buffer array names. Defaults to None.\n avg_symbols (dict, optional): Maps averaged fields to their 1D arrays. Defaults to None.\n \"\"\"\n settings = settings or {}\n settings.setdefault('source_format', 'free') # Default to free-form Fortran 95\n settings.setdefault('standard', 95)\n super().__init__(settings)\n self.array_symbols = array_symbols or {}\n self.avg_symbols = avg_symbols or {}\n</code></pre>"},{"location":"python/post/#post.AveragedField","title":"<code>AveragedField</code>","text":"<p> Bases: <code>FieldBase</code></p> <p>\ud2b9\uc815 \ubb3c\ub9ac \ud544\ub4dc\ub97c \uaca9\uc790\uc758 \ub3d9\uc9c8 \ucc28\uc6d0(\uc608: X \ubc29\ud5a5 1D\uc120\uc0c1 \ud3c9\uade0)\uc5d0 \ub300\ud574 \uacf5\uac04 \ud1b5\uacc4 \ud3c9\uade0(Average) \uc5f0\uc0b0\uc744 \uc218\ud589\ud558\ub294 1\ucc28\uc6d0 \ud544\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class AveragedField(FieldBase):\n \"\"\"\ud2b9\uc815 \ubb3c\ub9ac \ud544\ub4dc\ub97c \uaca9\uc790\uc758 \ub3d9\uc9c8 \ucc28\uc6d0(\uc608: X \ubc29\ud5a5 1D\uc120\uc0c1 \ud3c9\uade0)\uc5d0 \ub300\ud574 \n \uacf5\uac04 \ud1b5\uacc4 \ud3c9\uade0(Average) \uc5f0\uc0b0\uc744 \uc218\ud589\ud558\ub294 1\ucc28\uc6d0 \ud544\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.\n \"\"\"\n\n @classmethod\n def id(cls, w, tgt):\n \"\"\"Generates average field naming key.\n\n Args:\n w (str/None): Weight parameter.\n tgt (str): Target field variable name.\n\n Returns:\n str: Generated averaged variable key name.\n \"\"\"\n if w:\n return \"{}_avg_{}\".format(w, tgt)\n else:\n return \"avg_{}\".format(tgt)\n\n def __init__(self, w, tgt, fdict):\n \"\"\"Initializes AveragedField and populates dependency closure.\n\n Args:\n w (str/None): Average weights.\n tgt (str): Target variable to average.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n name = self.id(w, tgt)\n super(AveragedField, self).__init__(name, fdict)\n self.shape = \"nxp\" # Y, Z dimensions averaged out, leaving X-dimension array of size nxp\n self.dim = \":\"\n self.target = tgt\n\n tfield = fdict[tgt]\n self.fset = tfield.checkFluctuation()\n\n self.latex = r\"\\left\\langle {} \\right\\rangle\".format(tfield.latex)\n\n if not self.fset:\n self.tgt = tgt\n self.dep.add(tgt)\n else:\n ftgt = FluctuationField.id(w, tgt)\n self.tgt = ftgt\n self.dep.add(ftgt)\n\n self.weighted = w\n if w:\n self.w = fdict[w]\n self.dep.add(w)\n self.latex += (\"_{{{}}}\".format(w))\n\n def isWeighted(self):\n \"\"\"Checks if average has a weighted density variable.\n\n Returns:\n bool: True if weighted.\n \"\"\"\n return self.weighted is not None\n\n def pass1(self):\n \"\"\"Checks if average variable can be computed in loop Pass 1.\n\n Returns:\n bool: True if Pass 1 average.\n \"\"\"\n return not self.pass2()\n\n def pass2(self):\n \"\"\"Checks if average variable requires Pass 2 (dependent on fluctuation).\n\n Returns:\n bool: True if Pass 2 average.\n \"\"\"\n return len(self.fset) &gt; 0\n</code></pre>"},{"location":"python/post/#post.AveragedField.__init__","title":"<code>__init__(w, tgt, fdict)</code>","text":"<p>Initializes AveragedField and populates dependency closure.</p> <p>Parameters:</p> Name Type Description Default <code>w</code> <code>str / None</code> <p>Average weights.</p> required <code>tgt</code> <code>str</code> <p>Target variable to average.</p> required <code>fdict</code> <code>dict</code> <p>Global variable registry dictionary.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, w, tgt, fdict):\n \"\"\"Initializes AveragedField and populates dependency closure.\n\n Args:\n w (str/None): Average weights.\n tgt (str): Target variable to average.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n name = self.id(w, tgt)\n super(AveragedField, self).__init__(name, fdict)\n self.shape = \"nxp\" # Y, Z dimensions averaged out, leaving X-dimension array of size nxp\n self.dim = \":\"\n self.target = tgt\n\n tfield = fdict[tgt]\n self.fset = tfield.checkFluctuation()\n\n self.latex = r\"\\left\\langle {} \\right\\rangle\".format(tfield.latex)\n\n if not self.fset:\n self.tgt = tgt\n self.dep.add(tgt)\n else:\n ftgt = FluctuationField.id(w, tgt)\n self.tgt = ftgt\n self.dep.add(ftgt)\n\n self.weighted = w\n if w:\n self.w = fdict[w]\n self.dep.add(w)\n self.latex += (\"_{{{}}}\".format(w))\n</code></pre>"},{"location":"python/post/#post.AveragedField.id","title":"<code>id(w, tgt)</code> <code>classmethod</code>","text":"<p>Generates average field naming key.</p> <p>Parameters:</p> Name Type Description Default <code>w</code> <code>str / None</code> <p>Weight parameter.</p> required <code>tgt</code> <code>str</code> <p>Target field variable name.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Generated averaged variable key name.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@classmethod\ndef id(cls, w, tgt):\n \"\"\"Generates average field naming key.\n\n Args:\n w (str/None): Weight parameter.\n tgt (str): Target field variable name.\n\n Returns:\n str: Generated averaged variable key name.\n \"\"\"\n if w:\n return \"{}_avg_{}\".format(w, tgt)\n else:\n return \"avg_{}\".format(tgt)\n</code></pre>"},{"location":"python/post/#post.AveragedField.isWeighted","title":"<code>isWeighted()</code>","text":"<p>Checks if average has a weighted density variable.</p> <p>Returns:</p> Name Type Description <code>bool</code> <p>True if weighted.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def isWeighted(self):\n \"\"\"Checks if average has a weighted density variable.\n\n Returns:\n bool: True if weighted.\n \"\"\"\n return self.weighted is not None\n</code></pre>"},{"location":"python/post/#post.AveragedField.pass1","title":"<code>pass1()</code>","text":"<p>Checks if average variable can be computed in loop Pass 1.</p> <p>Returns:</p> Name Type Description <code>bool</code> <p>True if Pass 1 average.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def pass1(self):\n \"\"\"Checks if average variable can be computed in loop Pass 1.\n\n Returns:\n bool: True if Pass 1 average.\n \"\"\"\n return not self.pass2()\n</code></pre>"},{"location":"python/post/#post.AveragedField.pass2","title":"<code>pass2()</code>","text":"<p>Checks if average variable requires Pass 2 (dependent on fluctuation).</p> <p>Returns:</p> Name Type Description <code>bool</code> <p>True if Pass 2 average.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def pass2(self):\n \"\"\"Checks if average variable requires Pass 2 (dependent on fluctuation).\n\n Returns:\n bool: True if Pass 2 average.\n \"\"\"\n return len(self.fset) &gt; 0\n</code></pre>"},{"location":"python/post/#post.CollectDefinitions","title":"<code>CollectDefinitions</code>","text":"<p> Bases: <code>Visitor</code></p> <p>Visitor that walks the Lark AST to collect variable and assignment declarations.</p> <p>Gathers the primary fields (direct file inputs), derived calculation definitions, and average directives (statistical averages) to build the compiler's initial model.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class CollectDefinitions(Visitor):\n \"\"\"Visitor that walks the Lark AST to collect variable and assignment declarations.\n\n Gathers the primary fields (direct file inputs), derived calculation definitions,\n and average directives (statistical averages) to build the compiler's initial model.\n \"\"\"\n\n def __init__(self, primary, derived, averaged):\n \"\"\"Initializes CollectDefinitions visitor.\n\n Args:\n primary (set): Set to accumulate primary input field names.\n derived (dict): Dictionary to accumulate derived Field objects.\n averaged (dict): Dictionary to accumulate average variable targets.\n \"\"\"\n self.primary = primary\n self.derived = derived\n self.averaged = averaged\n\n def varlist(self, tree):\n \"\"\"Parses list of primary inputs declared in bracket syntax (e.g. [u, v, w]).\n\n Args:\n tree (Tree): Lark AST node for varlist.\n \"\"\"\n for v in tree.children:\n self.primary.add(v.value)\n self.derived[v.value] = PrimaryField(v.value, self.derived)\n\n def assign_var(self, tree):\n \"\"\"Parses variable assignment statements and registers corresponding Field objects.\n\n Args:\n tree (Tree): Lark AST node for assignment.\n \"\"\"\n if len(tree.children) &gt; 2:\n lval, lattr, rval = tree.children\n else:\n lval, rval = tree.children\n lattr = None\n\n attr_dict = {}\n\n if lattr is not None:\n for t in lattr.children:\n k, v = t.children\n attr_dict[k.value] = v.value\n\n if lval.value in self.derived:\n raise ValueError(\"duplicate definition of \" + lval)\n self.derived[lval.value] = Field(lval.value, attr_dict, rval, self.derived)\n\n def assign_avg_var(self, tree):\n \"\"\"Parses average directives and registers target variables for spatial averaging.\n\n Args:\n tree (Tree): Lark AST node for average declaration.\n \"\"\"\n w = tree.children[0]\n targets = tree.children[1:]\n\n if (not w.children) or (w.children[0] is None):\n self.averaged[None] = set([x.value for x in targets])\n else:\n self.averaged[w.children[0].value] = set([x.value for x in targets])\n</code></pre>"},{"location":"python/post/#post.CollectDefinitions.__init__","title":"<code>__init__(primary, derived, averaged)</code>","text":"<p>Initializes CollectDefinitions visitor.</p> <p>Parameters:</p> Name Type Description Default <code>primary</code> <code>set</code> <p>Set to accumulate primary input field names.</p> required <code>derived</code> <code>dict</code> <p>Dictionary to accumulate derived Field objects.</p> required <code>averaged</code> <code>dict</code> <p>Dictionary to accumulate average variable targets.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, primary, derived, averaged):\n \"\"\"Initializes CollectDefinitions visitor.\n\n Args:\n primary (set): Set to accumulate primary input field names.\n derived (dict): Dictionary to accumulate derived Field objects.\n averaged (dict): Dictionary to accumulate average variable targets.\n \"\"\"\n self.primary = primary\n self.derived = derived\n self.averaged = averaged\n</code></pre>"},{"location":"python/post/#post.CollectDefinitions.assign_avg_var","title":"<code>assign_avg_var(tree)</code>","text":"<p>Parses average directives and registers target variables for spatial averaging.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Lark AST node for average declaration.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def assign_avg_var(self, tree):\n \"\"\"Parses average directives and registers target variables for spatial averaging.\n\n Args:\n tree (Tree): Lark AST node for average declaration.\n \"\"\"\n w = tree.children[0]\n targets = tree.children[1:]\n\n if (not w.children) or (w.children[0] is None):\n self.averaged[None] = set([x.value for x in targets])\n else:\n self.averaged[w.children[0].value] = set([x.value for x in targets])\n</code></pre>"},{"location":"python/post/#post.CollectDefinitions.assign_var","title":"<code>assign_var(tree)</code>","text":"<p>Parses variable assignment statements and registers corresponding Field objects.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Lark AST node for assignment.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def assign_var(self, tree):\n \"\"\"Parses variable assignment statements and registers corresponding Field objects.\n\n Args:\n tree (Tree): Lark AST node for assignment.\n \"\"\"\n if len(tree.children) &gt; 2:\n lval, lattr, rval = tree.children\n else:\n lval, rval = tree.children\n lattr = None\n\n attr_dict = {}\n\n if lattr is not None:\n for t in lattr.children:\n k, v = t.children\n attr_dict[k.value] = v.value\n\n if lval.value in self.derived:\n raise ValueError(\"duplicate definition of \" + lval)\n self.derived[lval.value] = Field(lval.value, attr_dict, rval, self.derived)\n</code></pre>"},{"location":"python/post/#post.CollectDefinitions.varlist","title":"<code>varlist(tree)</code>","text":"<p>Parses list of primary inputs declared in bracket syntax (e.g. [u, v, w]).</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Lark AST node for varlist.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def varlist(self, tree):\n \"\"\"Parses list of primary inputs declared in bracket syntax (e.g. [u, v, w]).\n\n Args:\n tree (Tree): Lark AST node for varlist.\n \"\"\"\n for v in tree.children:\n self.primary.add(v.value)\n self.derived[v.value] = PrimaryField(v.value, self.derived)\n</code></pre>"},{"location":"python/post/#post.CompilationContext","title":"<code>CompilationContext</code>","text":"<p> Bases: <code>object</code></p> <p>Holds compilation pipeline state across parsing, resolution, and optimization stages.</p> <p>Attributes:</p> Name Type Description <code>primary</code> <code>set of str</code> <p>Names of primary input fields.</p> <code>derived</code> <code>dict of str -&gt; FieldBase</code> <p>Calculated, derivative, and fluctuation fields.</p> <code>averaged</code> <code>dict of str -&gt; AveragedField</code> <p>Spatial averaged variables.</p> <code>dependency</code> <code>dict of str -&gt; set of str</code> <p>DAG representing direct dependencies.</p> <code>pass1</code> <code>list of str</code> <p>Topologically sorted variables for average-precursor calculation.</p> <code>pass2</code> <code>list of str</code> <p>Topologically sorted variables for post-average calculations.</p> <code>avg1</code> <code>set of AveragedField</code> <p>Averaged variables calculated in Pass 1.</p> <code>avg2</code> <code>set of AveragedField</code> <p>Averaged variables calculated in Pass 2.</p> <code>alloc1</code> <code>dict of str -&gt; str</code> <p>Buffer pooling maps for Pass 1.</p> <code>alloc2</code> <code>dict of str -&gt; str</code> <p>Buffer pooling maps for Pass 2.</p> <code>narr</code> <code>int</code> <p>Maximum number of shared XYZ buffer arrays needed.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class CompilationContext(object):\n \"\"\"Holds compilation pipeline state across parsing, resolution, and optimization stages.\n\n Attributes:\n primary (set of str): Names of primary input fields.\n derived (dict of str -&gt; FieldBase): Calculated, derivative, and fluctuation fields.\n averaged (dict of str -&gt; AveragedField): Spatial averaged variables.\n dependency (dict of str -&gt; set of str): DAG representing direct dependencies.\n pass1 (list of str): Topologically sorted variables for average-precursor calculation.\n pass2 (list of str): Topologically sorted variables for post-average calculations.\n avg1 (set of AveragedField): Averaged variables calculated in Pass 1.\n avg2 (set of AveragedField): Averaged variables calculated in Pass 2.\n alloc1 (dict of str -&gt; str): Buffer pooling maps for Pass 1.\n alloc2 (dict of str -&gt; str): Buffer pooling maps for Pass 2.\n narr (int): Maximum number of shared XYZ buffer arrays needed.\n \"\"\"\n\n def __init__(self):\n \"\"\"Initializes an empty CompilationContext.\"\"\"\n self.primary = set()\n self.derived = {}\n self.averaged = {}\n self.dependency = {}\n self.pass1 = []\n self.pass2 = []\n self.avg1 = set()\n self.avg2 = set()\n self.alloc1 = {}\n self.alloc2 = {}\n self.narr = 0\n</code></pre>"},{"location":"python/post/#post.CompilationContext.__init__","title":"<code>__init__()</code>","text":"<p>Initializes an empty CompilationContext.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self):\n \"\"\"Initializes an empty CompilationContext.\"\"\"\n self.primary = set()\n self.derived = {}\n self.averaged = {}\n self.dependency = {}\n self.pass1 = []\n self.pass2 = []\n self.avg1 = set()\n self.avg2 = set()\n self.alloc1 = {}\n self.alloc2 = {}\n self.narr = 0\n</code></pre>"},{"location":"python/post/#post.DependencyNode","title":"<code>DependencyNode</code>","text":"<p> Bases: <code>object</code></p> <p>\uc758\uc874\uc131 \uad00\uacc4 \ubd84\uc11d\uc744 \ub2f4\ub2f9\ud558\ub294 \ucd94\uc0c1 \uc778\ud130\ud398\uc774\uc2a4 \ubc0f \ub178\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.</p> <p>Compiler pipeline stages use this graph to resolve topological sort order.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class DependencyNode(object):\n \"\"\"\uc758\uc874\uc131 \uad00\uacc4 \ubd84\uc11d\uc744 \ub2f4\ub2f9\ud558\ub294 \ucd94\uc0c1 \uc778\ud130\ud398\uc774\uc2a4 \ubc0f \ub178\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.\n\n Compiler pipeline stages use this graph to resolve topological sort order.\n \"\"\"\n\n def __init__(self, name, fdict):\n \"\"\"Initializes DependencyNode.\n\n Args:\n name (str): Variable name.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n self.name = name\n self.fdict = fdict\n self.dep = set([])\n self.fluc = False\n\n def depends_on(self, a):\n \"\"\"Checks if this node depends directly on the given variable.\n\n Args:\n a (str): Target variable name.\n\n Returns:\n bool: True if directly dependent.\n \"\"\"\n return a in self.dep\n\n def is_fluctuation(self):\n \"\"\"Checks if this node is a fluctuation variable.\n\n Returns:\n bool: True if fluctuation variable.\n \"\"\"\n return self.fluc\n\n def checkFluctuation(self):\n \"\"\"\ubcf8 \ubcc0\uc218 \ud639\uc740 \uc758\uc874\ud558\uace0 \uc788\ub294 \ud558\uc704 \uae30\ud638\ub4e4 \uc911\uc5d0 \ubcc0\ub3d9\ub7c9(Fluctuation) \uad00\ub828 \uacc4\uc0b0\uc774 \uac1c\uc785\ub418\uc5b4 \uc788\ub294\uc9c0\n \uc0c1\ud5a5\uc2dd\uc73c\ub85c \uc804\ud30c \ucd94\uc801\ud558\ub294 \uc7ac\uadc0 \uba54\uc11c\ub4dc\uc785\ub2c8\ub2e4.\n\n Returns:\n set: Set of variable names that require fluctuation calculations.\n \"\"\"\n fset = set([])\n for d in map(self.fdict.get, self.dep):\n fset.update(d.checkFluctuation())\n if self.is_fluctuation() or len(fset) &gt; 0:\n fset.add(self.name)\n return fset\n\n def depClosure(self):\n \"\"\"\ud574\ub2f9 \ubcc0\uc218\ub97c \uacc4\uc0b0\ud558\uae30 \uc704\ud574 \uc120\ud589 \uacc4\uc0b0\ub418\uc5b4\uc57c \ud558\ub294 \ubaa8\ub4e0 \ud558\uc704 \ubcc0\uc218 \ub178\ub4dc\ub4e4\uc744 \n \uc7ac\uadc0\uc801\uc73c\ub85c \ud0c0\uace0 \ub0b4\ub824\uac00 \ucd1d\ud569 \ud3d0\uc1c4 \uc9d1\ud569(Closure Set)\uc73c\ub85c \ubb36\uc5b4 \ubc18\ud658\ud569\ub2c8\ub2e4.\n\n Returns:\n set: Complete transitive dependency set.\n \"\"\"\n fset = set(self.dep)\n for d in self.dep:\n fset.update(self.fdict[d].depClosure())\n return fset\n</code></pre>"},{"location":"python/post/#post.DependencyNode.__init__","title":"<code>__init__(name, fdict)</code>","text":"<p>Initializes DependencyNode.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Variable name.</p> required <code>fdict</code> <code>dict</code> <p>Global variable registry dictionary.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, name, fdict):\n \"\"\"Initializes DependencyNode.\n\n Args:\n name (str): Variable name.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n self.name = name\n self.fdict = fdict\n self.dep = set([])\n self.fluc = False\n</code></pre>"},{"location":"python/post/#post.DependencyNode.checkFluctuation","title":"<code>checkFluctuation()</code>","text":"<p>\ubcf8 \ubcc0\uc218 \ud639\uc740 \uc758\uc874\ud558\uace0 \uc788\ub294 \ud558\uc704 \uae30\ud638\ub4e4 \uc911\uc5d0 \ubcc0\ub3d9\ub7c9(Fluctuation) \uad00\ub828 \uacc4\uc0b0\uc774 \uac1c\uc785\ub418\uc5b4 \uc788\ub294\uc9c0 \uc0c1\ud5a5\uc2dd\uc73c\ub85c \uc804\ud30c \ucd94\uc801\ud558\ub294 \uc7ac\uadc0 \uba54\uc11c\ub4dc\uc785\ub2c8\ub2e4.</p> <p>Returns:</p> Name Type Description <code>set</code> <p>Set of variable names that require fluctuation calculations.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def checkFluctuation(self):\n \"\"\"\ubcf8 \ubcc0\uc218 \ud639\uc740 \uc758\uc874\ud558\uace0 \uc788\ub294 \ud558\uc704 \uae30\ud638\ub4e4 \uc911\uc5d0 \ubcc0\ub3d9\ub7c9(Fluctuation) \uad00\ub828 \uacc4\uc0b0\uc774 \uac1c\uc785\ub418\uc5b4 \uc788\ub294\uc9c0\n \uc0c1\ud5a5\uc2dd\uc73c\ub85c \uc804\ud30c \ucd94\uc801\ud558\ub294 \uc7ac\uadc0 \uba54\uc11c\ub4dc\uc785\ub2c8\ub2e4.\n\n Returns:\n set: Set of variable names that require fluctuation calculations.\n \"\"\"\n fset = set([])\n for d in map(self.fdict.get, self.dep):\n fset.update(d.checkFluctuation())\n if self.is_fluctuation() or len(fset) &gt; 0:\n fset.add(self.name)\n return fset\n</code></pre>"},{"location":"python/post/#post.DependencyNode.depClosure","title":"<code>depClosure()</code>","text":"<p>\ud574\ub2f9 \ubcc0\uc218\ub97c \uacc4\uc0b0\ud558\uae30 \uc704\ud574 \uc120\ud589 \uacc4\uc0b0\ub418\uc5b4\uc57c \ud558\ub294 \ubaa8\ub4e0 \ud558\uc704 \ubcc0\uc218 \ub178\ub4dc\ub4e4\uc744 \uc7ac\uadc0\uc801\uc73c\ub85c \ud0c0\uace0 \ub0b4\ub824\uac00 \ucd1d\ud569 \ud3d0\uc1c4 \uc9d1\ud569(Closure Set)\uc73c\ub85c \ubb36\uc5b4 \ubc18\ud658\ud569\ub2c8\ub2e4.</p> <p>Returns:</p> Name Type Description <code>set</code> <p>Complete transitive dependency set.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def depClosure(self):\n \"\"\"\ud574\ub2f9 \ubcc0\uc218\ub97c \uacc4\uc0b0\ud558\uae30 \uc704\ud574 \uc120\ud589 \uacc4\uc0b0\ub418\uc5b4\uc57c \ud558\ub294 \ubaa8\ub4e0 \ud558\uc704 \ubcc0\uc218 \ub178\ub4dc\ub4e4\uc744 \n \uc7ac\uadc0\uc801\uc73c\ub85c \ud0c0\uace0 \ub0b4\ub824\uac00 \ucd1d\ud569 \ud3d0\uc1c4 \uc9d1\ud569(Closure Set)\uc73c\ub85c \ubb36\uc5b4 \ubc18\ud658\ud569\ub2c8\ub2e4.\n\n Returns:\n set: Complete transitive dependency set.\n \"\"\"\n fset = set(self.dep)\n for d in self.dep:\n fset.update(self.fdict[d].depClosure())\n return fset\n</code></pre>"},{"location":"python/post/#post.DependencyNode.depends_on","title":"<code>depends_on(a)</code>","text":"<p>Checks if this node depends directly on the given variable.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Target variable name.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <p>True if directly dependent.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def depends_on(self, a):\n \"\"\"Checks if this node depends directly on the given variable.\n\n Args:\n a (str): Target variable name.\n\n Returns:\n bool: True if directly dependent.\n \"\"\"\n return a in self.dep\n</code></pre>"},{"location":"python/post/#post.DependencyNode.is_fluctuation","title":"<code>is_fluctuation()</code>","text":"<p>Checks if this node is a fluctuation variable.</p> <p>Returns:</p> Name Type Description <code>bool</code> <p>True if fluctuation variable.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def is_fluctuation(self):\n \"\"\"Checks if this node is a fluctuation variable.\n\n Returns:\n bool: True if fluctuation variable.\n \"\"\"\n return self.fluc\n</code></pre>"},{"location":"python/post/#post.DependencyResolutionStage","title":"<code>DependencyResolutionStage</code>","text":"<p> Bases: <code>object</code></p> <p>Compiler pipeline Stage 3: Resolves data dependencies and orders calculations.</p> <p>Splits loops into: - Pass 1 (calculating variables required prior to averages). - Pass 2 (calculating fluctuations and statistics after averages are resolved). Performs topological sorting to ensure correctness.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class DependencyResolutionStage(object):\n \"\"\"Compiler pipeline Stage 3: Resolves data dependencies and orders calculations.\n\n Splits loops into:\n - Pass 1 (calculating variables required prior to averages).\n - Pass 2 (calculating fluctuations and statistics after averages are resolved).\n Performs topological sorting to ensure correctness.\n \"\"\"\n\n def execute(self, ctx):\n \"\"\"Executes Stage 3 dependency resolution and topological sort.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n # \uc774\ub984 \ucda9\ub3cc \ubc29\uc9c0 \uac80\uc99d\n assert set(ctx.derived.keys()).isdisjoint(ctx.averaged.keys())\n\n # Pass 1\uacfc Pass 2 \ub300\uc0c1 \ud3c9\uade0\ud654 \ubcc0\uc218 \ub17c\ub9ac \ubd84\ud560\n ctx.avg1 = set(filter(AveragedField.pass1, ctx.averaged.values()))\n ctx.avg2 = set(filter(AveragedField.pass2, ctx.averaged.values()))\n\n # Pass 1 \uc704\uc0c1 \uc815\ub82c: Pass 1 \ud3c9\uade0 \ubcc0\uc218\ub4e4\uc758 \uc5f0\uc0b0\uc5d0 \uad00\uc5ec\ud558\ub294 \ubaa8\ub4e0 \uc885\uc18d \uad00\uacc4\ub97c \uc218\uc9d1\ud558\uc5ec \uc815\ub82c\n pass1calc = set(map(repr, ctx.avg1))\n for x in ctx.avg1:\n pass1calc.update(x.depClosure())\n ctx.pass1 = self.sort_vars_new(ctx.dependency, pass1calc - ctx.primary)\n\n # Pass 2 \uc704\uc0c1 \uc815\ub82c: Pass 2 \ud3c9\uade0 \ubcc0\uc218(\ubcc0\ub3d9 \uc5f0\uc0b0 \uc5f0\uacc4)\ub4e4\uc758 \uc5f0\uc0b0\uc5d0 \uad00\uc5ec\ud558\ub294 \uc885\uc18d\uc131\uc744 \uc815\ub82c\n pass2calc = set(map(repr, ctx.avg2))\n for x in ctx.avg2:\n pass2calc.update(x.depClosure())\n ctx.pass2 = self.sort_vars_new(ctx.dependency, pass2calc - ctx.primary)\n\n def calc_size(self, dependency, ordered, remaining):\n \"\"\"Calculates topological dependency metrics for ordering weight sorting.\n\n Args:\n dependency (dict): Graph mapping variable names to dependency sets.\n ordered (set): Topologically ordered variable names.\n remaining (set): Unsorted remaining variable names.\n\n Returns:\n int: The degree of active connection impact.\n \"\"\"\n count = 0\n dep_union = set()\n for v in remaining:\n dep_union |= set(dependency[v])\n for v in ordered:\n if v in dep_union:\n count += 1\n return count\n\n def sort_vars_new(self, dependency, group):\n \"\"\"Performs topological sort using an impact-weight heuristic.\n\n Minimizes variable lifetime durations to optimize array reuse.\n\n Args:\n dependency (dict): Graph mapping variable names to dependency sets.\n group (set): Set of variable names to sort.\n\n Returns:\n list: Topologically sorted list of variable names.\n \"\"\"\n order = []\n remain = list(group)\n remain.sort()\n\n while len(remain) &gt; 0:\n candidate = []\n for v in remain:\n if set(dependency[v]).isdisjoint(remain):\n candidate.append(v)\n\n impact = {}\n size0 = self.calc_size(dependency, set(order), set(remain))\n\n for v in candidate:\n impact[v] = self.calc_size(dependency, set(order) | set([v]), set(remain) - set([v])) - size0\n\n candidate.sort(key=impact.get)\n order.append(candidate[0])\n remain.remove(candidate[0])\n\n return order\n</code></pre>"},{"location":"python/post/#post.DependencyResolutionStage.calc_size","title":"<code>calc_size(dependency, ordered, remaining)</code>","text":"<p>Calculates topological dependency metrics for ordering weight sorting.</p> <p>Parameters:</p> Name Type Description Default <code>dependency</code> <code>dict</code> <p>Graph mapping variable names to dependency sets.</p> required <code>ordered</code> <code>set</code> <p>Topologically ordered variable names.</p> required <code>remaining</code> <code>set</code> <p>Unsorted remaining variable names.</p> required <p>Returns:</p> Name Type Description <code>int</code> <p>The degree of active connection impact.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def calc_size(self, dependency, ordered, remaining):\n \"\"\"Calculates topological dependency metrics for ordering weight sorting.\n\n Args:\n dependency (dict): Graph mapping variable names to dependency sets.\n ordered (set): Topologically ordered variable names.\n remaining (set): Unsorted remaining variable names.\n\n Returns:\n int: The degree of active connection impact.\n \"\"\"\n count = 0\n dep_union = set()\n for v in remaining:\n dep_union |= set(dependency[v])\n for v in ordered:\n if v in dep_union:\n count += 1\n return count\n</code></pre>"},{"location":"python/post/#post.DependencyResolutionStage.execute","title":"<code>execute(ctx)</code>","text":"<p>Executes Stage 3 dependency resolution and topological sort.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def execute(self, ctx):\n \"\"\"Executes Stage 3 dependency resolution and topological sort.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n # \uc774\ub984 \ucda9\ub3cc \ubc29\uc9c0 \uac80\uc99d\n assert set(ctx.derived.keys()).isdisjoint(ctx.averaged.keys())\n\n # Pass 1\uacfc Pass 2 \ub300\uc0c1 \ud3c9\uade0\ud654 \ubcc0\uc218 \ub17c\ub9ac \ubd84\ud560\n ctx.avg1 = set(filter(AveragedField.pass1, ctx.averaged.values()))\n ctx.avg2 = set(filter(AveragedField.pass2, ctx.averaged.values()))\n\n # Pass 1 \uc704\uc0c1 \uc815\ub82c: Pass 1 \ud3c9\uade0 \ubcc0\uc218\ub4e4\uc758 \uc5f0\uc0b0\uc5d0 \uad00\uc5ec\ud558\ub294 \ubaa8\ub4e0 \uc885\uc18d \uad00\uacc4\ub97c \uc218\uc9d1\ud558\uc5ec \uc815\ub82c\n pass1calc = set(map(repr, ctx.avg1))\n for x in ctx.avg1:\n pass1calc.update(x.depClosure())\n ctx.pass1 = self.sort_vars_new(ctx.dependency, pass1calc - ctx.primary)\n\n # Pass 2 \uc704\uc0c1 \uc815\ub82c: Pass 2 \ud3c9\uade0 \ubcc0\uc218(\ubcc0\ub3d9 \uc5f0\uc0b0 \uc5f0\uacc4)\ub4e4\uc758 \uc5f0\uc0b0\uc5d0 \uad00\uc5ec\ud558\ub294 \uc885\uc18d\uc131\uc744 \uc815\ub82c\n pass2calc = set(map(repr, ctx.avg2))\n for x in ctx.avg2:\n pass2calc.update(x.depClosure())\n ctx.pass2 = self.sort_vars_new(ctx.dependency, pass2calc - ctx.primary)\n</code></pre>"},{"location":"python/post/#post.DependencyResolutionStage.sort_vars_new","title":"<code>sort_vars_new(dependency, group)</code>","text":"<p>Performs topological sort using an impact-weight heuristic.</p> <p>Minimizes variable lifetime durations to optimize array reuse.</p> <p>Parameters:</p> Name Type Description Default <code>dependency</code> <code>dict</code> <p>Graph mapping variable names to dependency sets.</p> required <code>group</code> <code>set</code> <p>Set of variable names to sort.</p> required <p>Returns:</p> Name Type Description <code>list</code> <p>Topologically sorted list of variable names.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def sort_vars_new(self, dependency, group):\n \"\"\"Performs topological sort using an impact-weight heuristic.\n\n Minimizes variable lifetime durations to optimize array reuse.\n\n Args:\n dependency (dict): Graph mapping variable names to dependency sets.\n group (set): Set of variable names to sort.\n\n Returns:\n list: Topologically sorted list of variable names.\n \"\"\"\n order = []\n remain = list(group)\n remain.sort()\n\n while len(remain) &gt; 0:\n candidate = []\n for v in remain:\n if set(dependency[v]).isdisjoint(remain):\n candidate.append(v)\n\n impact = {}\n size0 = self.calc_size(dependency, set(order), set(remain))\n\n for v in candidate:\n impact[v] = self.calc_size(dependency, set(order) | set([v]), set(remain) - set([v])) - size0\n\n candidate.sort(key=impact.get)\n order.append(candidate[0])\n remain.remove(candidate[0])\n\n return order\n</code></pre>"},{"location":"python/post/#post.DerivativeExpansionStage","title":"<code>DerivativeExpansionStage</code>","text":"<p> Bases: <code>object</code></p> <p>Compiler pipeline Stage 2: Expands differential operators and fluctuation terms.</p> <p>Finds derivative expressions (e.g., ddx, d2dy) and fluctuation identifiers (u'), instantiates DerivedField and FluctuationField objects, registers them in the variable registry, and builds initial DAG dependencies.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class DerivativeExpansionStage(object):\n \"\"\"Compiler pipeline Stage 2: Expands differential operators and fluctuation terms.\n\n Finds derivative expressions (e.g., ddx, d2dy) and fluctuation identifiers (u'),\n instantiates DerivedField and FluctuationField objects, registers them in\n the variable registry, and builds initial DAG dependencies.\n \"\"\"\n\n def execute(self, ctx):\n \"\"\"Executes Stage 2 derivative and fluctuation expansion.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n # 1. \uacc4\uc0b0\uc2dd \ub0b4\uc5d0 \uc874\uc7ac\ud558\ub294 \uace0\ucc28 \ucc28\ubd84 \ubbf8\ubd84\ud56d(ddx, d2dy \ub4f1)\uc744 \ucc3e\uc544 \uc911\uac04 DerivedField\ub85c \ub4f1\ub85d\n dset = set()\n for k, v in ctx.derived.items():\n dset.update(v.derivs)\n\n for tup in dset:\n a = DerivedField(tup[0], tup[1], ctx.derived)\n ctx.derived[a.name] = a\n\n # 2. \ud1b5\uacc4 \ubb3c\ub9ac\ub7c9 \ud3c9\uade0\ud654 \ub300\uc0c1 \ubcc0\uc218\ub4e4\uc744 AveragedField \uad6c\uc870\uccb4\ub85c \uad6c\uc131\ud558\uace0, \n # \ubcc0\ub3d9\ub7c9 \uacc4\uc0b0\uc774 \ud544\uc694\ud55c \uacbd\uc6b0 FluctuationField\ub85c \ub4f1\ub85d\n averaged_raw = ctx.averaged\n ctx.averaged = {}\n for w, tgts in averaged_raw.items():\n for t in tgts:\n a = AveragedField(w, t, ctx.derived)\n ctx.averaged[a.name] = a\n # \ud3c9\uade0 \ud3b8\ucc28\uac00 \ub3d9\ubc18\ub41c \ud56d\ub4e4\uc5d0 \ub300\ud574 FluctuationField \uc0dd\uc131\n for ff in a.fset:\n b = FluctuationField(w, ff, a.fset, ctx.derived)\n ctx.derived[b.name] = b\n\n # 3. \ud504\ub85c\uadf8\ub7a8 \ub0b4 \ubaa8\ub4e0 \ud544\ub4dc \uac04\uc758 1\ucc28 \uc758\uc874 \uad00\uacc4 \uadf8\ub798\ud504(Dependency Graph) \ucd94\ucd9c\n ctx.dependency = {}\n for k, v in ctx.derived.items():\n ctx.dependency[k] = v.dep\n for k, v in ctx.averaged.items():\n ctx.dependency[k] = v.dep\n</code></pre>"},{"location":"python/post/#post.DerivativeExpansionStage.execute","title":"<code>execute(ctx)</code>","text":"<p>Executes Stage 2 derivative and fluctuation expansion.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def execute(self, ctx):\n \"\"\"Executes Stage 2 derivative and fluctuation expansion.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n # 1. \uacc4\uc0b0\uc2dd \ub0b4\uc5d0 \uc874\uc7ac\ud558\ub294 \uace0\ucc28 \ucc28\ubd84 \ubbf8\ubd84\ud56d(ddx, d2dy \ub4f1)\uc744 \ucc3e\uc544 \uc911\uac04 DerivedField\ub85c \ub4f1\ub85d\n dset = set()\n for k, v in ctx.derived.items():\n dset.update(v.derivs)\n\n for tup in dset:\n a = DerivedField(tup[0], tup[1], ctx.derived)\n ctx.derived[a.name] = a\n\n # 2. \ud1b5\uacc4 \ubb3c\ub9ac\ub7c9 \ud3c9\uade0\ud654 \ub300\uc0c1 \ubcc0\uc218\ub4e4\uc744 AveragedField \uad6c\uc870\uccb4\ub85c \uad6c\uc131\ud558\uace0, \n # \ubcc0\ub3d9\ub7c9 \uacc4\uc0b0\uc774 \ud544\uc694\ud55c \uacbd\uc6b0 FluctuationField\ub85c \ub4f1\ub85d\n averaged_raw = ctx.averaged\n ctx.averaged = {}\n for w, tgts in averaged_raw.items():\n for t in tgts:\n a = AveragedField(w, t, ctx.derived)\n ctx.averaged[a.name] = a\n # \ud3c9\uade0 \ud3b8\ucc28\uac00 \ub3d9\ubc18\ub41c \ud56d\ub4e4\uc5d0 \ub300\ud574 FluctuationField \uc0dd\uc131\n for ff in a.fset:\n b = FluctuationField(w, ff, a.fset, ctx.derived)\n ctx.derived[b.name] = b\n\n # 3. \ud504\ub85c\uadf8\ub7a8 \ub0b4 \ubaa8\ub4e0 \ud544\ub4dc \uac04\uc758 1\ucc28 \uc758\uc874 \uad00\uacc4 \uadf8\ub798\ud504(Dependency Graph) \ucd94\ucd9c\n ctx.dependency = {}\n for k, v in ctx.derived.items():\n ctx.dependency[k] = v.dep\n for k, v in ctx.averaged.items():\n ctx.dependency[k] = v.dep\n</code></pre>"},{"location":"python/post/#post.DerivedField","title":"<code>DerivedField</code>","text":"<p> Bases: <code>FieldBase</code></p> <p>\uc218\uce58 \uacf5\uac04 \ubbf8\ubd84(ddx, d2dy \ub4f1)\uc744 \uc218\ud589\ud558\uc5ec \uacc4\uc0b0\ub418\ub294 \uc720\ub3c4 \ud544\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. Fortran \uc218\uce58 \ucc28\ubd84 \ud328\ud0a4\uc9c0 \uc11c\ube0c\ub8e8\ud2f4(Compact.f90 \uc5d0 \uad6c\ud604\ub41c dfnonp, dfp \ub4f1)\uc758 \ub3d9\uc801 \ud638\ucd9c \ucf54\ub4dc\ub97c \ucd9c\ub825\ud569\ub2c8\ub2e4.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class DerivedField(FieldBase):\n \"\"\"\uc218\uce58 \uacf5\uac04 \ubbf8\ubd84(ddx, d2dy \ub4f1)\uc744 \uc218\ud589\ud558\uc5ec \uacc4\uc0b0\ub418\ub294 \uc720\ub3c4 \ud544\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.\n Fortran \uc218\uce58 \ucc28\ubd84 \ud328\ud0a4\uc9c0 \uc11c\ube0c\ub8e8\ud2f4(Compact.f90 \uc5d0 \uad6c\ud604\ub41c dfnonp, dfp \ub4f1)\uc758 \n \ub3d9\uc801 \ud638\ucd9c \ucf54\ub4dc\ub97c \ucd9c\ub825\ud569\ub2c8\ub2e4.\n \"\"\"\n\n def __init__(self, op, v, fdict):\n \"\"\"Initializes DerivedField derivative node.\n\n Args:\n op (str): Differential operator name (e.g. 'ddx').\n v (str): Variable being differentiated (e.g. 'u').\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n name = \"{}_{}\".format(op, v)\n super(DerivedField, self).__init__(name, fdict)\n self.op = op\n self.v = v\n self.dep = set([v])\n\n partial = differential_operator_registry.get_latex_symbol(op)\n self.latex = partial + \"(\" + fdict[v].latex + \")\"\n</code></pre>"},{"location":"python/post/#post.DerivedField.__init__","title":"<code>__init__(op, v, fdict)</code>","text":"<p>Initializes DerivedField derivative node.</p> <p>Parameters:</p> Name Type Description Default <code>op</code> <code>str</code> <p>Differential operator name (e.g. 'ddx').</p> required <code>v</code> <code>str</code> <p>Variable being differentiated (e.g. 'u').</p> required <code>fdict</code> <code>dict</code> <p>Global variable registry dictionary.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, op, v, fdict):\n \"\"\"Initializes DerivedField derivative node.\n\n Args:\n op (str): Differential operator name (e.g. 'ddx').\n v (str): Variable being differentiated (e.g. 'u').\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n name = \"{}_{}\".format(op, v)\n super(DerivedField, self).__init__(name, fdict)\n self.op = op\n self.v = v\n self.dep = set([v])\n\n partial = differential_operator_registry.get_latex_symbol(op)\n self.latex = partial + \"(\" + fdict[v].latex + \")\"\n</code></pre>"},{"location":"python/post/#post.DifferentialOperatorRegistry","title":"<code>DifferentialOperatorRegistry</code>","text":"<p>Registry for spatial differential operators mapping operators to LaTeX representations.</p> <p>Handles default and custom differential operators (e.g., ddx, d2dy) used during derivation expansion.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class DifferentialOperatorRegistry:\n \"\"\"Registry for spatial differential operators mapping operators to LaTeX representations.\n\n Handles default and custom differential operators (e.g., ddx, d2dy) used during derivation expansion.\n \"\"\"\n\n def __init__(self):\n \"\"\"Initializes DifferentialOperatorRegistry with empty operator mappings.\"\"\"\n self._operators = {}\n\n def register(self, op_name, latex_symbol):\n \"\"\"Registers a custom LaTeX representation for a given operator.\n\n Args:\n op_name (str): The differential operator name (e.g., 'ddx').\n latex_symbol (str): The corresponding LaTeX math symbol.\n \"\"\"\n self._operators[op_name] = latex_symbol\n\n def get_latex_symbol(self, op_name):\n \"\"\"Retrieves the LaTeX representation of a differential operator.\n\n Args:\n op_name (str): The name of the operator.\n\n Returns:\n str: The LaTeX code for the differential operator (e.g. '\\\\partial_{x}').\n \"\"\"\n if op_name in self._operators:\n return self._operators[op_name]\n # Fallback to dynamic parsing matching original code\n fmt = r\"\\partial_{{{}}}\"\n coord = op_name[-1] if op_name else \"\"\n return fmt.format(coord + coord if len(op_name) &gt; 3 else coord)\n</code></pre>"},{"location":"python/post/#post.DifferentialOperatorRegistry.__init__","title":"<code>__init__()</code>","text":"<p>Initializes DifferentialOperatorRegistry with empty operator mappings.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self):\n \"\"\"Initializes DifferentialOperatorRegistry with empty operator mappings.\"\"\"\n self._operators = {}\n</code></pre>"},{"location":"python/post/#post.DifferentialOperatorRegistry.get_latex_symbol","title":"<code>get_latex_symbol(op_name)</code>","text":"<p>Retrieves the LaTeX representation of a differential operator.</p> <p>Parameters:</p> Name Type Description Default <code>op_name</code> <code>str</code> <p>The name of the operator.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>The LaTeX code for the differential operator (e.g. '\\partial_{x}').</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def get_latex_symbol(self, op_name):\n \"\"\"Retrieves the LaTeX representation of a differential operator.\n\n Args:\n op_name (str): The name of the operator.\n\n Returns:\n str: The LaTeX code for the differential operator (e.g. '\\\\partial_{x}').\n \"\"\"\n if op_name in self._operators:\n return self._operators[op_name]\n # Fallback to dynamic parsing matching original code\n fmt = r\"\\partial_{{{}}}\"\n coord = op_name[-1] if op_name else \"\"\n return fmt.format(coord + coord if len(op_name) &gt; 3 else coord)\n</code></pre>"},{"location":"python/post/#post.DifferentialOperatorRegistry.register","title":"<code>register(op_name, latex_symbol)</code>","text":"<p>Registers a custom LaTeX representation for a given operator.</p> <p>Parameters:</p> Name Type Description Default <code>op_name</code> <code>str</code> <p>The differential operator name (e.g., 'ddx').</p> required <code>latex_symbol</code> <code>str</code> <p>The corresponding LaTeX math symbol.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def register(self, op_name, latex_symbol):\n \"\"\"Registers a custom LaTeX representation for a given operator.\n\n Args:\n op_name (str): The differential operator name (e.g., 'ddx').\n latex_symbol (str): The corresponding LaTeX math symbol.\n \"\"\"\n self._operators[op_name] = latex_symbol\n</code></pre>"},{"location":"python/post/#post.ExpInspector","title":"<code>ExpInspector</code>","text":"<p> Bases: <code>Visitor</code></p> <p>Visitor to inspect mathematical AST nodes to extract dependencies and attributes.</p> <p>Finds the list of dependent variables, checks if the expression references turbulence fluctuation variables (primed variables), and extracts derivative operators such as spatial first and second order derivatives (e.g. ddx, d2dy).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class ExpInspector(Visitor):\n \"\"\"Visitor to inspect mathematical AST nodes to extract dependencies and attributes.\n\n Finds the list of dependent variables, checks if the expression references\n turbulence fluctuation variables (primed variables), and extracts derivative operators\n such as spatial first and second order derivatives (e.g. ddx, d2dy).\n \"\"\"\n\n def __init__(self):\n \"\"\"Initializes ExpInspector state.\"\"\"\n self.fluctuation = False\n self.dep = set([])\n self.deriv = set([])\n\n @classmethod\n def inspect(cls, tree):\n \"\"\"Inspects the given AST tree and returns extracted attributes.\n\n Args:\n tree (Tree): Lark AST subtree.\n\n Returns:\n tuple: (has_fluctuation, dependencies_set, derivatives_set).\n \"\"\"\n self = cls()\n return self(tree)\n\n def __call__(self, tree):\n \"\"\"Executes the inspection traversal.\n\n Args:\n tree (Tree): Lark AST subtree.\n\n Returns:\n tuple: (has_fluctuation, dependencies_set, derivatives_set).\n \"\"\"\n self.visit(tree)\n return self.fluctuation, self.dep, self.deriv\n\n def fluc(self, tree):\n \"\"\"Processes a fluctuation node.\n\n Args:\n tree (Tree): Fluctuation AST node.\n \"\"\"\n self.fluctuation = True\n self.dep.add(tree.children[0].value)\n\n def var(self, tree):\n \"\"\"Processes a variable reference node.\n\n Args:\n tree (Tree): Variable reference AST node.\n \"\"\"\n self.dep.add(tree.children[0].value)\n\n def dnx(self, tree):\n \"\"\"Processes a spatial derivative node, registering intermediate fields.\n\n Args:\n tree (Tree): Derivative operation AST node.\n \"\"\"\n op, v = tree.children\n deriv = \"{}_{}\".format(op.data, v.value)\n self.dep.add(deriv)\n self.deriv.add((op.data, v.value))\n</code></pre>"},{"location":"python/post/#post.ExpInspector.__call__","title":"<code>__call__(tree)</code>","text":"<p>Executes the inspection traversal.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Lark AST subtree.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p>(has_fluctuation, dependencies_set, derivatives_set).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __call__(self, tree):\n \"\"\"Executes the inspection traversal.\n\n Args:\n tree (Tree): Lark AST subtree.\n\n Returns:\n tuple: (has_fluctuation, dependencies_set, derivatives_set).\n \"\"\"\n self.visit(tree)\n return self.fluctuation, self.dep, self.deriv\n</code></pre>"},{"location":"python/post/#post.ExpInspector.__init__","title":"<code>__init__()</code>","text":"<p>Initializes ExpInspector state.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self):\n \"\"\"Initializes ExpInspector state.\"\"\"\n self.fluctuation = False\n self.dep = set([])\n self.deriv = set([])\n</code></pre>"},{"location":"python/post/#post.ExpInspector.dnx","title":"<code>dnx(tree)</code>","text":"<p>Processes a spatial derivative node, registering intermediate fields.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Derivative operation AST node.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def dnx(self, tree):\n \"\"\"Processes a spatial derivative node, registering intermediate fields.\n\n Args:\n tree (Tree): Derivative operation AST node.\n \"\"\"\n op, v = tree.children\n deriv = \"{}_{}\".format(op.data, v.value)\n self.dep.add(deriv)\n self.deriv.add((op.data, v.value))\n</code></pre>"},{"location":"python/post/#post.ExpInspector.fluc","title":"<code>fluc(tree)</code>","text":"<p>Processes a fluctuation node.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Fluctuation AST node.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def fluc(self, tree):\n \"\"\"Processes a fluctuation node.\n\n Args:\n tree (Tree): Fluctuation AST node.\n \"\"\"\n self.fluctuation = True\n self.dep.add(tree.children[0].value)\n</code></pre>"},{"location":"python/post/#post.ExpInspector.inspect","title":"<code>inspect(tree)</code> <code>classmethod</code>","text":"<p>Inspects the given AST tree and returns extracted attributes.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Lark AST subtree.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p>(has_fluctuation, dependencies_set, derivatives_set).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@classmethod\ndef inspect(cls, tree):\n \"\"\"Inspects the given AST tree and returns extracted attributes.\n\n Args:\n tree (Tree): Lark AST subtree.\n\n Returns:\n tuple: (has_fluctuation, dependencies_set, derivatives_set).\n \"\"\"\n self = cls()\n return self(tree)\n</code></pre>"},{"location":"python/post/#post.ExpInspector.var","title":"<code>var(tree)</code>","text":"<p>Processes a variable reference node.</p> <p>Parameters:</p> Name Type Description Default <code>tree</code> <code>Tree</code> <p>Variable reference AST node.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def var(self, tree):\n \"\"\"Processes a variable reference node.\n\n Args:\n tree (Tree): Variable reference AST node.\n \"\"\"\n self.dep.add(tree.children[0].value)\n</code></pre>"},{"location":"python/post/#post.ExpToCode","title":"<code>ExpToCode</code>","text":"<p> Bases: <code>Transformer</code></p> <p>Transformer to compile the DSL mathematical AST directly into Fortran array expressions.</p> <p>Formats variable accesses with spatial index wrappers (e.g., <code>(i,j,k)</code> or <code>(i)</code>) and converts inline functions or standard math calls.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@v_args(inline=True)\nclass ExpToCode(Transformer):\n \"\"\"Transformer to compile the DSL mathematical AST directly into Fortran array expressions.\n\n Formats variable accesses with spatial index wrappers (e.g., `(i,j,k)` or `(i)`) and\n converts inline functions or standard math calls.\n \"\"\"\n\n def __init__(self, fdict):\n \"\"\"Initializes ExpToCode transformer.\n\n Args:\n fdict (dict): Dictionary mapping variable names to FieldBase objects.\n \"\"\"\n self.fdict = fdict\n\n def number(self, numeral):\n \"\"\"Converts float literal numbers.\n\n Args:\n numeral (Token): Number token.\n\n Returns:\n str: Floating point string.\n \"\"\"\n return str(float(numeral))\n\n def env(self, name):\n \"\"\"Converts environment variables.\n\n Args:\n name (Token): Environment variable name token.\n\n Returns:\n str: Variable name.\n \"\"\"\n return name.value\n\n def paren(self, name):\n \"\"\"Wraps in parentheses.\n\n Args:\n name (str): Inner expression.\n\n Returns:\n str: Parenthesized string.\n \"\"\"\n return \"({})\".format(str(name))\n\n def var(self, name):\n \"\"\"Formats a variable access with spatial grid index (i,j,k).\n\n Args:\n name (Token): Variable token.\n\n Returns:\n str: Fortran array access.\n \"\"\"\n try:\n arrname = self.fdict[name.value].array\n except KeyError:\n arrname = name.value\n\n return arrname + \"(i,j,k)\"\n\n def fluc(self, name):\n \"\"\"Formats a fluctuation prime variable access.\n\n Saves index reference for inline replacement of averages.\n\n Args:\n name (Token): Fluctuation variable token.\n\n Returns:\n str: Fortran inline fluctuation subtraction formula.\n \"\"\"\n try:\n arrname = self.fdict[name.value].array\n except KeyError:\n arrname = name.value\n\n fmt = \"({0}(i,j,k) - {{0}}avg_{1}(i))\"\n return fmt.format(arrname, name.value)\n\n def dnx(self, partial, b):\n \"\"\"Formats spatial derivatives as array accesses.\n\n Args:\n partial (Token): Derivative operator.\n b (Token): Variable token.\n\n Returns:\n str: Fortran array access for derivative.\n \"\"\"\n signature = \"{}_{}\".format(partial.data, b.value)\n try:\n arrname = self.fdict[signature].array\n except KeyError:\n arrname = signature\n\n return arrname + \"(i,j,k)\"\n\n def icall(self, a, b):\n \"\"\"Formats inline functions (sqr, pow3) to Fortran multiplication.\n\n Args:\n a (Token): Inline function operator.\n b (str): Argument code.\n\n Returns:\n str: Fortran math expression.\n \"\"\"\n if a.data == \"sqr\":\n fcode = \"(({0})*({0}))\".format(b)\n elif a.data == \"pow3\":\n fcode = \"(({0})*({0})*({0}))\".format(b)\n else:\n fcode = \"({0})\".format(b)\n return fcode\n\n def fcall(self, *args):\n \"\"\"Formats standard math function calls.\n\n Args:\n *args: Variable length argument list. First argument is the function token.\n\n Returns:\n str: Fortran function call string.\n \"\"\"\n a = args[0]\n b = \", \".join(args[1:])\n fcode = \"( {} ( {} ) )\".format(a, b)\n return fcode\n\n def neg(self, b):\n \"\"\"Formats negation.\n\n Args:\n b (str): Code string to negate.\n\n Returns:\n str: Negated code string.\n \"\"\"\n fcode = \"( - {} )\".format(b)\n return fcode\n\n def add(self, a, b):\n \"\"\"Formats addition.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran addition code.\n \"\"\"\n fcode = \"( {} + {} )\".format(a, b)\n return fcode\n\n def sub(self, a, b):\n \"\"\"Formats subtraction.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran subtraction code.\n \"\"\"\n fcode = \"( {} - {} )\".format(a, b)\n return fcode\n\n def mul(self, a, b):\n \"\"\"Formats multiplication.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran multiplication code.\n \"\"\"\n fcode = \"( {} * {} )\".format(a, b)\n return fcode\n\n def div(self, a, b):\n \"\"\"Formats division.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran division code.\n \"\"\"\n fcode = \"( {} / {} )\".format(a, b)\n return fcode\n\n log = lambda self: \"log\"\n exp = lambda self: \"exp\"\n sqrt = lambda self: \"sqrt\"\n abs = lambda self: \"abs\"\n rxn_rate = lambda self: \"rxn_rate\"\n udf = lambda self, a: a.value\n</code></pre>"},{"location":"python/post/#post.ExpToCode.__init__","title":"<code>__init__(fdict)</code>","text":"<p>Initializes ExpToCode transformer.</p> <p>Parameters:</p> Name Type Description Default <code>fdict</code> <code>dict</code> <p>Dictionary mapping variable names to FieldBase objects.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, fdict):\n \"\"\"Initializes ExpToCode transformer.\n\n Args:\n fdict (dict): Dictionary mapping variable names to FieldBase objects.\n \"\"\"\n self.fdict = fdict\n</code></pre>"},{"location":"python/post/#post.ExpToCode.add","title":"<code>add(a, b)</code>","text":"<p>Formats addition.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand code.</p> required <code>b</code> <code>str</code> <p>Right operand code.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran addition code.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def add(self, a, b):\n \"\"\"Formats addition.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran addition code.\n \"\"\"\n fcode = \"( {} + {} )\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.div","title":"<code>div(a, b)</code>","text":"<p>Formats division.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand code.</p> required <code>b</code> <code>str</code> <p>Right operand code.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran division code.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def div(self, a, b):\n \"\"\"Formats division.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran division code.\n \"\"\"\n fcode = \"( {} / {} )\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.dnx","title":"<code>dnx(partial, b)</code>","text":"<p>Formats spatial derivatives as array accesses.</p> <p>Parameters:</p> Name Type Description Default <code>partial</code> <code>Token</code> <p>Derivative operator.</p> required <code>b</code> <code>Token</code> <p>Variable token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran array access for derivative.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def dnx(self, partial, b):\n \"\"\"Formats spatial derivatives as array accesses.\n\n Args:\n partial (Token): Derivative operator.\n b (Token): Variable token.\n\n Returns:\n str: Fortran array access for derivative.\n \"\"\"\n signature = \"{}_{}\".format(partial.data, b.value)\n try:\n arrname = self.fdict[signature].array\n except KeyError:\n arrname = signature\n\n return arrname + \"(i,j,k)\"\n</code></pre>"},{"location":"python/post/#post.ExpToCode.env","title":"<code>env(name)</code>","text":"<p>Converts environment variables.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Environment variable name token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Variable name.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def env(self, name):\n \"\"\"Converts environment variables.\n\n Args:\n name (Token): Environment variable name token.\n\n Returns:\n str: Variable name.\n \"\"\"\n return name.value\n</code></pre>"},{"location":"python/post/#post.ExpToCode.fcall","title":"<code>fcall(*args)</code>","text":"<p>Formats standard math function calls.</p> <p>Parameters:</p> Name Type Description Default <code>*args</code> <p>Variable length argument list. First argument is the function token.</p> <code>()</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran function call string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def fcall(self, *args):\n \"\"\"Formats standard math function calls.\n\n Args:\n *args: Variable length argument list. First argument is the function token.\n\n Returns:\n str: Fortran function call string.\n \"\"\"\n a = args[0]\n b = \", \".join(args[1:])\n fcode = \"( {} ( {} ) )\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.fluc","title":"<code>fluc(name)</code>","text":"<p>Formats a fluctuation prime variable access.</p> <p>Saves index reference for inline replacement of averages.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Fluctuation variable token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran inline fluctuation subtraction formula.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def fluc(self, name):\n \"\"\"Formats a fluctuation prime variable access.\n\n Saves index reference for inline replacement of averages.\n\n Args:\n name (Token): Fluctuation variable token.\n\n Returns:\n str: Fortran inline fluctuation subtraction formula.\n \"\"\"\n try:\n arrname = self.fdict[name.value].array\n except KeyError:\n arrname = name.value\n\n fmt = \"({0}(i,j,k) - {{0}}avg_{1}(i))\"\n return fmt.format(arrname, name.value)\n</code></pre>"},{"location":"python/post/#post.ExpToCode.icall","title":"<code>icall(a, b)</code>","text":"<p>Formats inline functions (sqr, pow3) to Fortran multiplication.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Token</code> <p>Inline function operator.</p> required <code>b</code> <code>str</code> <p>Argument code.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran math expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def icall(self, a, b):\n \"\"\"Formats inline functions (sqr, pow3) to Fortran multiplication.\n\n Args:\n a (Token): Inline function operator.\n b (str): Argument code.\n\n Returns:\n str: Fortran math expression.\n \"\"\"\n if a.data == \"sqr\":\n fcode = \"(({0})*({0}))\".format(b)\n elif a.data == \"pow3\":\n fcode = \"(({0})*({0})*({0}))\".format(b)\n else:\n fcode = \"({0})\".format(b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.mul","title":"<code>mul(a, b)</code>","text":"<p>Formats multiplication.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand code.</p> required <code>b</code> <code>str</code> <p>Right operand code.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran multiplication code.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def mul(self, a, b):\n \"\"\"Formats multiplication.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran multiplication code.\n \"\"\"\n fcode = \"( {} * {} )\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.neg","title":"<code>neg(b)</code>","text":"<p>Formats negation.</p> <p>Parameters:</p> Name Type Description Default <code>b</code> <code>str</code> <p>Code string to negate.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Negated code string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def neg(self, b):\n \"\"\"Formats negation.\n\n Args:\n b (str): Code string to negate.\n\n Returns:\n str: Negated code string.\n \"\"\"\n fcode = \"( - {} )\".format(b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.number","title":"<code>number(numeral)</code>","text":"<p>Converts float literal numbers.</p> <p>Parameters:</p> Name Type Description Default <code>numeral</code> <code>Token</code> <p>Number token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Floating point string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def number(self, numeral):\n \"\"\"Converts float literal numbers.\n\n Args:\n numeral (Token): Number token.\n\n Returns:\n str: Floating point string.\n \"\"\"\n return str(float(numeral))\n</code></pre>"},{"location":"python/post/#post.ExpToCode.paren","title":"<code>paren(name)</code>","text":"<p>Wraps in parentheses.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Inner expression.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Parenthesized string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def paren(self, name):\n \"\"\"Wraps in parentheses.\n\n Args:\n name (str): Inner expression.\n\n Returns:\n str: Parenthesized string.\n \"\"\"\n return \"({})\".format(str(name))\n</code></pre>"},{"location":"python/post/#post.ExpToCode.sub","title":"<code>sub(a, b)</code>","text":"<p>Formats subtraction.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand code.</p> required <code>b</code> <code>str</code> <p>Right operand code.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran subtraction code.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def sub(self, a, b):\n \"\"\"Formats subtraction.\n\n Args:\n a (str): Left operand code.\n b (str): Right operand code.\n\n Returns:\n str: Fortran subtraction code.\n \"\"\"\n fcode = \"( {} - {} )\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToCode.var","title":"<code>var(name)</code>","text":"<p>Formats a variable access with spatial grid index (i,j,k).</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Variable token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran array access.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def var(self, name):\n \"\"\"Formats a variable access with spatial grid index (i,j,k).\n\n Args:\n name (Token): Variable token.\n\n Returns:\n str: Fortran array access.\n \"\"\"\n try:\n arrname = self.fdict[name.value].array\n except KeyError:\n arrname = name.value\n\n return arrname + \"(i,j,k)\"\n</code></pre>"},{"location":"python/post/#post.ExpToLatex","title":"<code>ExpToLatex</code>","text":"<p> Bases: <code>Transformer</code></p> <p>Transformer to compile the DSL mathematical AST into a LaTeX math string.</p> <p>Converts operations, variables, derivatives, and functions into LaTeX syntax (e.g., partial derivative notation, fraction blocks, and bracket sizing) to generate mathematical report files.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@v_args(inline=True)\nclass ExpToLatex(Transformer):\n \"\"\"Transformer to compile the DSL mathematical AST into a LaTeX math string.\n\n Converts operations, variables, derivatives, and functions into LaTeX syntax\n (e.g., partial derivative notation, fraction blocks, and bracket sizing)\n to generate mathematical report files.\n \"\"\"\n\n def __init__(self, fdict):\n \"\"\"Initializes ExpToLatex transformer.\n\n Args:\n fdict (dict): Dictionary mapping variable names to FieldBase objects.\n \"\"\"\n self.fdict = fdict\n\n def arithmatic_rooted(self, name):\n \"\"\"Checks if a variable's root operation is arithmetic.\n\n Args:\n name (str): Variable name.\n\n Returns:\n bool: True if arithmetic-rooted.\n \"\"\"\n try:\n exproot = self.fdict[name].exp.data\n except AttributeError:\n exproot = \"something_11fasq2afa3rfzsaerqw23\"\n\n return ((exproot == \"add\") or (exproot == \"sub\") or\n (exproot == \"mul\") or (exproot == \"div\"))\n\n def parenthise(self, name):\n \"\"\"Formats a variable name, wrapping it in parentheses if it has lower priority operators.\n\n Args:\n name (str): Variable name.\n\n Returns:\n str: Parenthesized LaTeX equation representation.\n \"\"\"\n try:\n latex = self.fdict[name].latex\n latex_given = self.fdict[name].latex_given\n except KeyError:\n warnings.warn(name + \" is not found\")\n latex = r\"\\mathrm{{{}}}\".format(name)\n latex_given = None\n\n if self.arithmatic_rooted(name) and (latex_given is None):\n latex = \"(\" + latex + \")\"\n\n return latex\n\n def number(self, numeral):\n \"\"\"Returns LaTeX literal for numbers.\n\n Args:\n numeral (Token): Number token.\n\n Returns:\n str: LaTeX representation.\n \"\"\"\n return numeral\n\n def env(self, name):\n \"\"\"Returns LaTeX literal for environment variables.\n\n Args:\n name (Token): Environment variable name token.\n\n Returns:\n str: LaTeX representation.\n \"\"\"\n return r\"\\mathrm{{{}}}\".format(name.value)\n\n def paren(self, name):\n \"\"\"Formats parentheses.\n\n Args:\n name (str): Inner LaTeX content.\n\n Returns:\n str: Parenthesized string.\n \"\"\"\n return \"({})\".format(str(name))\n\n def var(self, name):\n \"\"\"Formats variables in LaTeX.\n\n Args:\n name (Token): Variable token.\n\n Returns:\n str: LaTeX variable representation.\n \"\"\"\n return self.parenthise(name.value)\n\n def fluc(self, name):\n \"\"\"Formats fluctuation prime (u'') variables in LaTeX.\n\n Args:\n name (Token): Variable token.\n\n Returns:\n str: LaTeX prime variable string.\n \"\"\"\n return self.parenthise(name.value) + \"''\"\n\n def dnx(self, partial, b):\n \"\"\"Formats spatial derivatives in LaTeX (e.g. \\\\partial_x(u)).\n\n Args:\n partial (Token): Derivative operator token.\n b (Token): Variable token.\n\n Returns:\n str: LaTeX partial derivative expression.\n \"\"\"\n fmt = r\"\\partial_{{{}}}\"\n coord = partial.data[-1]\n op = fmt.format(coord + coord if len(partial.data) &gt; 3 else coord)\n\n signature = \"{}_{}\".format(partial.data, b.value)\n\n try:\n eq = self.fdict[signature].latex\n except KeyError:\n eq = op + self.parenthise(b.value)\n warnings.warn(signature + \" is not found: \" + eq)\n\n return eq\n\n def icall(self, a, b):\n \"\"\"Formats inline functions (sqr, pow3) in LaTeX.\n\n Args:\n a (Token): Inline function operator.\n b (str): LaTeX representation of argument.\n\n Returns:\n str: LaTeX representation.\n \"\"\"\n if a.data == \"sqr\":\n fcode = \"({0})^2\".format(b)\n elif a.data == \"pow3\":\n fcode = \"({0})^3\".format(b)\n else:\n fcode = \"({0})\".format(b)\n return fcode\n\n def fcall(self, *args):\n \"\"\"Formats function calls in LaTeX.\n\n Args:\n *args: Variable length arguments. The first argument is function name token.\n\n Returns:\n str: LaTeX function representation.\n \"\"\"\n a = args[0]\n func_name = a.value if hasattr(a, 'value') else str(a)\n return function_registry.to_latex(func_name, *args[1:])\n\n def neg(self, b):\n \"\"\"Formats negation.\n\n Args:\n b (str): Inner LaTeX expression.\n\n Returns:\n str: LaTeX negated expression.\n \"\"\"\n fcode = \"(-{})\".format(b)\n return fcode\n\n def add(self, a, b):\n \"\"\"Formats addition.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX addition expression.\n \"\"\"\n fcode = \"{} + {}\".format(a, b)\n return fcode\n\n def sub(self, a, b):\n \"\"\"Formats subtraction.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX subtraction expression.\n \"\"\"\n fcode = \"{} - {}\".format(a, b)\n return fcode\n\n def mul(self, a, b):\n \"\"\"Formats multiplication.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX multiplication expression.\n \"\"\"\n fcode = \"{} {}\".format(a, b)\n return fcode\n\n def div(self, a, b):\n \"\"\"Formats division.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX division expression.\n \"\"\"\n fcode = \"{} / {}\".format(a, b)\n return fcode\n\n log = lambda self: \"\\log\"\n exp = lambda self: \"\\exp\"\n sqrt = lambda self: \"sqrt\"\n abs = lambda self: \"abs\"\n rxn_rate = lambda self: \"\\omega\"\n udf = lambda self, a: a.value\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.__init__","title":"<code>__init__(fdict)</code>","text":"<p>Initializes ExpToLatex transformer.</p> <p>Parameters:</p> Name Type Description Default <code>fdict</code> <code>dict</code> <p>Dictionary mapping variable names to FieldBase objects.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, fdict):\n \"\"\"Initializes ExpToLatex transformer.\n\n Args:\n fdict (dict): Dictionary mapping variable names to FieldBase objects.\n \"\"\"\n self.fdict = fdict\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.add","title":"<code>add(a, b)</code>","text":"<p>Formats addition.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand.</p> required <code>b</code> <code>str</code> <p>Right operand.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX addition expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def add(self, a, b):\n \"\"\"Formats addition.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX addition expression.\n \"\"\"\n fcode = \"{} + {}\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.arithmatic_rooted","title":"<code>arithmatic_rooted(name)</code>","text":"<p>Checks if a variable's root operation is arithmetic.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Variable name.</p> required <p>Returns:</p> Name Type Description <code>bool</code> <p>True if arithmetic-rooted.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def arithmatic_rooted(self, name):\n \"\"\"Checks if a variable's root operation is arithmetic.\n\n Args:\n name (str): Variable name.\n\n Returns:\n bool: True if arithmetic-rooted.\n \"\"\"\n try:\n exproot = self.fdict[name].exp.data\n except AttributeError:\n exproot = \"something_11fasq2afa3rfzsaerqw23\"\n\n return ((exproot == \"add\") or (exproot == \"sub\") or\n (exproot == \"mul\") or (exproot == \"div\"))\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.div","title":"<code>div(a, b)</code>","text":"<p>Formats division.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand.</p> required <code>b</code> <code>str</code> <p>Right operand.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX division expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def div(self, a, b):\n \"\"\"Formats division.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX division expression.\n \"\"\"\n fcode = \"{} / {}\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.dnx","title":"<code>dnx(partial, b)</code>","text":"<p>Formats spatial derivatives in LaTeX (e.g. \\partial_x(u)).</p> <p>Parameters:</p> Name Type Description Default <code>partial</code> <code>Token</code> <p>Derivative operator token.</p> required <code>b</code> <code>Token</code> <p>Variable token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX partial derivative expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def dnx(self, partial, b):\n \"\"\"Formats spatial derivatives in LaTeX (e.g. \\\\partial_x(u)).\n\n Args:\n partial (Token): Derivative operator token.\n b (Token): Variable token.\n\n Returns:\n str: LaTeX partial derivative expression.\n \"\"\"\n fmt = r\"\\partial_{{{}}}\"\n coord = partial.data[-1]\n op = fmt.format(coord + coord if len(partial.data) &gt; 3 else coord)\n\n signature = \"{}_{}\".format(partial.data, b.value)\n\n try:\n eq = self.fdict[signature].latex\n except KeyError:\n eq = op + self.parenthise(b.value)\n warnings.warn(signature + \" is not found: \" + eq)\n\n return eq\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.env","title":"<code>env(name)</code>","text":"<p>Returns LaTeX literal for environment variables.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Environment variable name token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def env(self, name):\n \"\"\"Returns LaTeX literal for environment variables.\n\n Args:\n name (Token): Environment variable name token.\n\n Returns:\n str: LaTeX representation.\n \"\"\"\n return r\"\\mathrm{{{}}}\".format(name.value)\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.fcall","title":"<code>fcall(*args)</code>","text":"<p>Formats function calls in LaTeX.</p> <p>Parameters:</p> Name Type Description Default <code>*args</code> <p>Variable length arguments. The first argument is function name token.</p> <code>()</code> <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX function representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def fcall(self, *args):\n \"\"\"Formats function calls in LaTeX.\n\n Args:\n *args: Variable length arguments. The first argument is function name token.\n\n Returns:\n str: LaTeX function representation.\n \"\"\"\n a = args[0]\n func_name = a.value if hasattr(a, 'value') else str(a)\n return function_registry.to_latex(func_name, *args[1:])\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.fluc","title":"<code>fluc(name)</code>","text":"<p>Formats fluctuation prime (u'') variables in LaTeX.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Variable token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX prime variable string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def fluc(self, name):\n \"\"\"Formats fluctuation prime (u'') variables in LaTeX.\n\n Args:\n name (Token): Variable token.\n\n Returns:\n str: LaTeX prime variable string.\n \"\"\"\n return self.parenthise(name.value) + \"''\"\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.icall","title":"<code>icall(a, b)</code>","text":"<p>Formats inline functions (sqr, pow3) in LaTeX.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Token</code> <p>Inline function operator.</p> required <code>b</code> <code>str</code> <p>LaTeX representation of argument.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def icall(self, a, b):\n \"\"\"Formats inline functions (sqr, pow3) in LaTeX.\n\n Args:\n a (Token): Inline function operator.\n b (str): LaTeX representation of argument.\n\n Returns:\n str: LaTeX representation.\n \"\"\"\n if a.data == \"sqr\":\n fcode = \"({0})^2\".format(b)\n elif a.data == \"pow3\":\n fcode = \"({0})^3\".format(b)\n else:\n fcode = \"({0})\".format(b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.mul","title":"<code>mul(a, b)</code>","text":"<p>Formats multiplication.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand.</p> required <code>b</code> <code>str</code> <p>Right operand.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX multiplication expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def mul(self, a, b):\n \"\"\"Formats multiplication.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX multiplication expression.\n \"\"\"\n fcode = \"{} {}\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.neg","title":"<code>neg(b)</code>","text":"<p>Formats negation.</p> <p>Parameters:</p> Name Type Description Default <code>b</code> <code>str</code> <p>Inner LaTeX expression.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX negated expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def neg(self, b):\n \"\"\"Formats negation.\n\n Args:\n b (str): Inner LaTeX expression.\n\n Returns:\n str: LaTeX negated expression.\n \"\"\"\n fcode = \"(-{})\".format(b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.number","title":"<code>number(numeral)</code>","text":"<p>Returns LaTeX literal for numbers.</p> <p>Parameters:</p> Name Type Description Default <code>numeral</code> <code>Token</code> <p>Number token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def number(self, numeral):\n \"\"\"Returns LaTeX literal for numbers.\n\n Args:\n numeral (Token): Number token.\n\n Returns:\n str: LaTeX representation.\n \"\"\"\n return numeral\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.paren","title":"<code>paren(name)</code>","text":"<p>Formats parentheses.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Inner LaTeX content.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Parenthesized string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def paren(self, name):\n \"\"\"Formats parentheses.\n\n Args:\n name (str): Inner LaTeX content.\n\n Returns:\n str: Parenthesized string.\n \"\"\"\n return \"({})\".format(str(name))\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.parenthise","title":"<code>parenthise(name)</code>","text":"<p>Formats a variable name, wrapping it in parentheses if it has lower priority operators.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Variable name.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Parenthesized LaTeX equation representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def parenthise(self, name):\n \"\"\"Formats a variable name, wrapping it in parentheses if it has lower priority operators.\n\n Args:\n name (str): Variable name.\n\n Returns:\n str: Parenthesized LaTeX equation representation.\n \"\"\"\n try:\n latex = self.fdict[name].latex\n latex_given = self.fdict[name].latex_given\n except KeyError:\n warnings.warn(name + \" is not found\")\n latex = r\"\\mathrm{{{}}}\".format(name)\n latex_given = None\n\n if self.arithmatic_rooted(name) and (latex_given is None):\n latex = \"(\" + latex + \")\"\n\n return latex\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.sub","title":"<code>sub(a, b)</code>","text":"<p>Formats subtraction.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>str</code> <p>Left operand.</p> required <code>b</code> <code>str</code> <p>Right operand.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX subtraction expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def sub(self, a, b):\n \"\"\"Formats subtraction.\n\n Args:\n a (str): Left operand.\n b (str): Right operand.\n\n Returns:\n str: LaTeX subtraction expression.\n \"\"\"\n fcode = \"{} - {}\".format(a, b)\n return fcode\n</code></pre>"},{"location":"python/post/#post.ExpToLatex.var","title":"<code>var(name)</code>","text":"<p>Formats variables in LaTeX.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Variable token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>LaTeX variable representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def var(self, name):\n \"\"\"Formats variables in LaTeX.\n\n Args:\n name (Token): Variable token.\n\n Returns:\n str: LaTeX variable representation.\n \"\"\"\n return self.parenthise(name.value)\n</code></pre>"},{"location":"python/post/#post.Field","title":"<code>Field</code>","text":"<p> Bases: <code>FieldBase</code></p> <p>\uc77c\ubc18 \ub300\uc785 \uacc4\uc0b0 \ubcc0\uc218\ub97c \uad00\ub9ac\ud558\uba70, 3\ucc28\uc6d0 \uaca9\uc790\uc810 \ub8e8\ud504 \ucf54\ub4dc \uc0dd\uc131\uc744 \ub2f4\ub2f9\ud558\ub294 \ud575\uc2ec \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. SymPy \ucd5c\uc801\ud654 \ubc0f CSE \uc801\uc6a9 \ucf54\ub4dc\ub97c \ub8e8\ud504 \ubcf8\ubb38\uc5d0 \uacb0\ud569\ud569\ub2c8\ub2e4.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class Field(FieldBase):\n \"\"\"\uc77c\ubc18 \ub300\uc785 \uacc4\uc0b0 \ubcc0\uc218\ub97c \uad00\ub9ac\ud558\uba70, 3\ucc28\uc6d0 \uaca9\uc790\uc810 \ub8e8\ud504 \ucf54\ub4dc \uc0dd\uc131\uc744 \ub2f4\ub2f9\ud558\ub294 \ud575\uc2ec \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.\n SymPy \ucd5c\uc801\ud654 \ubc0f CSE \uc801\uc6a9 \ucf54\ub4dc\ub97c \ub8e8\ud504 \ubcf8\ubb38\uc5d0 \uacb0\ud569\ud569\ub2c8\ub2e4.\n \"\"\"\n\n def __init__(self, name, attr, exp, fdict):\n \"\"\"Initializes Field properties and inspects expression details.\n\n Args:\n name (str): Calculated variable name.\n attr (dict): Attribute configuration tags.\n exp (Tree): Mathematical equation AST subtree.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n super(Field, self).__init__(name, fdict)\n self.attr = attr\n self.exp = exp\n self.fluc, self.dep, self.derivs = ExpInspector.inspect(exp)\n self.comment = self.name + \" = \" + ExpToCode(self.fdict).transform(self.exp)\n\n self.latex_given = self.attr.get(\"latex\")\n if self.latex_given is None:\n self.latex = ExpToLatex(self.fdict).transform(self.exp)\n else:\n self.latex = self.latex_given\n\n self.exporter = None\n try:\n if self.attr[\"export\"]:\n self.exporter = FieldExporter(self.name, self.attr, self)\n except KeyError:\n pass\n\n def export_on(self):\n \"\"\"Checks if file exporting is enabled.\n\n Returns:\n bool: True if an exporter is configured.\n \"\"\"\n return self.exporter is not None\n</code></pre>"},{"location":"python/post/#post.Field.__init__","title":"<code>__init__(name, attr, exp, fdict)</code>","text":"<p>Initializes Field properties and inspects expression details.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Calculated variable name.</p> required <code>attr</code> <code>dict</code> <p>Attribute configuration tags.</p> required <code>exp</code> <code>Tree</code> <p>Mathematical equation AST subtree.</p> required <code>fdict</code> <code>dict</code> <p>Global variable registry dictionary.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, name, attr, exp, fdict):\n \"\"\"Initializes Field properties and inspects expression details.\n\n Args:\n name (str): Calculated variable name.\n attr (dict): Attribute configuration tags.\n exp (Tree): Mathematical equation AST subtree.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n super(Field, self).__init__(name, fdict)\n self.attr = attr\n self.exp = exp\n self.fluc, self.dep, self.derivs = ExpInspector.inspect(exp)\n self.comment = self.name + \" = \" + ExpToCode(self.fdict).transform(self.exp)\n\n self.latex_given = self.attr.get(\"latex\")\n if self.latex_given is None:\n self.latex = ExpToLatex(self.fdict).transform(self.exp)\n else:\n self.latex = self.latex_given\n\n self.exporter = None\n try:\n if self.attr[\"export\"]:\n self.exporter = FieldExporter(self.name, self.attr, self)\n except KeyError:\n pass\n</code></pre>"},{"location":"python/post/#post.Field.export_on","title":"<code>export_on()</code>","text":"<p>Checks if file exporting is enabled.</p> <p>Returns:</p> Name Type Description <code>bool</code> <p>True if an exporter is configured.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def export_on(self):\n \"\"\"Checks if file exporting is enabled.\n\n Returns:\n bool: True if an exporter is configured.\n \"\"\"\n return self.exporter is not None\n</code></pre>"},{"location":"python/post/#post.FieldBase","title":"<code>FieldBase</code>","text":"<p> Bases: <code>DependencyNode</code></p> <p>\ubaa8\ub4e0 \ubb3c\ub9ac \ud544\ub4dc \uac1d\uccb4\uc758 \ucd5c\uc0c1\uc704 \uae30\ubcf8 \ud074\ub798\uc2a4\ub85c\uc11c \uacf5\ud1b5 \ub370\uc774\ud130 \uad6c\uc870\ub97c \uc815\uc758\ud569\ub2c8\ub2e4.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class FieldBase(DependencyNode):\n \"\"\"\ubaa8\ub4e0 \ubb3c\ub9ac \ud544\ub4dc \uac1d\uccb4\uc758 \ucd5c\uc0c1\uc704 \uae30\ubcf8 \ud074\ub798\uc2a4\ub85c\uc11c \uacf5\ud1b5 \ub370\uc774\ud130 \uad6c\uc870\ub97c \uc815\uc758\ud569\ub2c8\ub2e4.\"\"\"\n\n def __init__(self, name, fdict):\n \"\"\"Initializes FieldBase properties.\n\n Args:\n name (str): Variable name.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n super(FieldBase, self).__init__(name, fdict)\n self.array = name\n self.prime = False\n self.shape = \"nxp,nyp,nzp\"\n self.dim = \":,:,:\"\n\n def export_on(self):\n \"\"\"Checks if disk exporting is enabled for this field.\n\n Returns:\n bool: Always False for the base field class.\n \"\"\"\n return False\n\n def __repr__(self):\n \"\"\"String representation of the field (returns variable name).\"\"\"\n return self.name\n</code></pre>"},{"location":"python/post/#post.FieldBase.__init__","title":"<code>__init__(name, fdict)</code>","text":"<p>Initializes FieldBase properties.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Variable name.</p> required <code>fdict</code> <code>dict</code> <p>Global variable registry dictionary.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, name, fdict):\n \"\"\"Initializes FieldBase properties.\n\n Args:\n name (str): Variable name.\n fdict (dict): Global variable registry dictionary.\n \"\"\"\n super(FieldBase, self).__init__(name, fdict)\n self.array = name\n self.prime = False\n self.shape = \"nxp,nyp,nzp\"\n self.dim = \":,:,:\"\n</code></pre>"},{"location":"python/post/#post.FieldBase.__repr__","title":"<code>__repr__()</code>","text":"<p>String representation of the field (returns variable name).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __repr__(self):\n \"\"\"String representation of the field (returns variable name).\"\"\"\n return self.name\n</code></pre>"},{"location":"python/post/#post.FieldBase.export_on","title":"<code>export_on()</code>","text":"<p>Checks if disk exporting is enabled for this field.</p> <p>Returns:</p> Name Type Description <code>bool</code> <p>Always False for the base field class.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def export_on(self):\n \"\"\"Checks if disk exporting is enabled for this field.\n\n Returns:\n bool: Always False for the base field class.\n \"\"\"\n return False\n</code></pre>"},{"location":"python/post/#post.FieldExporter","title":"<code>FieldExporter</code>","text":"<p> Bases: <code>object</code></p> <p>\ubb3c\ub9ac \ud544\ub4dc \ub370\uc774\ud130\ub97c \ubcd1\ub82c \ubd84\uc0b0 \ub514\uc2a4\ud06c \uc2dc\uc2a4\ud15c\uc73c\ub85c \uc9c1\uc811 \ucd94\ucd9c(Export)\ud558\ub294 \uace0\uc131\ub2a5 MPI-IO \uc11c\ube0c\ub8e8\ud2f4 \ube14\ub85d\uc744 \uc815\uc758\ud558\ub294 \ub3c4\uba54\uc778 \ub370\uc774\ud130 \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class FieldExporter(object):\n \"\"\"\ubb3c\ub9ac \ud544\ub4dc \ub370\uc774\ud130\ub97c \ubcd1\ub82c \ubd84\uc0b0 \ub514\uc2a4\ud06c \uc2dc\uc2a4\ud15c\uc73c\ub85c \uc9c1\uc811 \ucd94\ucd9c(Export)\ud558\ub294 \uace0\uc131\ub2a5 MPI-IO \uc11c\ube0c\ub8e8\ud2f4 \ube14\ub85d\uc744 \n \uc815\uc758\ud558\ub294 \ub3c4\uba54\uc778 \ub370\uc774\ud130 \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.\n \"\"\"\n mpi_io_decl = \"\"\"\n! field exporter common\ninteger(kind=MPI_OFFSET_KIND) :: offset\n\"\"\"\n\n def __init__(self, name, attr, parent):\n \"\"\"Initializes FieldExporter with MPI configurations.\n\n Args:\n name (str): Field exporter name.\n attr (dict): Attributes dictionary containing slice coordinates (e.g. xs, xe).\n parent (Field): Parent field object owning this exporter.\n \"\"\"\n self.name = name\n self.attr = attr\n self.parent = parent\n\n self.params = dict(attr)\n\n self.params.setdefault(\"xs\", 1)\n self.params.setdefault(\"xe\", \"nxp\")\n self.params.setdefault(\"ys\", 1)\n self.params.setdefault(\"ye\", \"nyp\")\n self.params.setdefault(\"zs\", 1)\n self.params.setdefault(\"ze\", \"nzp\")\n\n self.params.setdefault(\"field_name\", self.name)\n\n self.params.setdefault(\"len_xpts\", f\"({self.params['xe']} - {self.params['xs']} + 1)\")\n\n fmt_xpts_init = '''\ndo i = {{ xs }}, {{ xe }}\n{{ field_name }}_xpts(i-{{ xs }}+1) = i\nend do\n'''\n self.params.setdefault(\"xpts_init\", Template(fmt_xpts_init).render(**self.params))\n\n try:\n # Sampling at listed x coordinates\n fmt_xpts_init_list = \"{{ field_name }}_xpts = (/ {{ list_xpts }} /)\"\n\n raw_xpts = self.params[\"xpts\"]\n int_xpts = list(map(int, raw_xpts.split()))\n len_xpts = len(int_xpts)\n self.params[\"len_xpts\"] = len_xpts\n self.params[\"list_xpts\"] = \",\".join(map(str, int_xpts))\n self.params[\"xpts_init\"] = Template(fmt_xpts_init_list).render(**self.params)\n except KeyError:\n pass\n\n self.use_subarray = (\"xpts\" not in self.params)\n</code></pre>"},{"location":"python/post/#post.FieldExporter.__init__","title":"<code>__init__(name, attr, parent)</code>","text":"<p>Initializes FieldExporter with MPI configurations.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Field exporter name.</p> required <code>attr</code> <code>dict</code> <p>Attributes dictionary containing slice coordinates (e.g. xs, xe).</p> required <code>parent</code> <code>Field</code> <p>Parent field object owning this exporter.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code> def __init__(self, name, attr, parent):\n \"\"\"Initializes FieldExporter with MPI configurations.\n\n Args:\n name (str): Field exporter name.\n attr (dict): Attributes dictionary containing slice coordinates (e.g. xs, xe).\n parent (Field): Parent field object owning this exporter.\n \"\"\"\n self.name = name\n self.attr = attr\n self.parent = parent\n\n self.params = dict(attr)\n\n self.params.setdefault(\"xs\", 1)\n self.params.setdefault(\"xe\", \"nxp\")\n self.params.setdefault(\"ys\", 1)\n self.params.setdefault(\"ye\", \"nyp\")\n self.params.setdefault(\"zs\", 1)\n self.params.setdefault(\"ze\", \"nzp\")\n\n self.params.setdefault(\"field_name\", self.name)\n\n self.params.setdefault(\"len_xpts\", f\"({self.params['xe']} - {self.params['xs']} + 1)\")\n\n fmt_xpts_init = '''\ndo i = {{ xs }}, {{ xe }}\n{{ field_name }}_xpts(i-{{ xs }}+1) = i\nend do\n'''\n self.params.setdefault(\"xpts_init\", Template(fmt_xpts_init).render(**self.params))\n\n try:\n # Sampling at listed x coordinates\n fmt_xpts_init_list = \"{{ field_name }}_xpts = (/ {{ list_xpts }} /)\"\n\n raw_xpts = self.params[\"xpts\"]\n int_xpts = list(map(int, raw_xpts.split()))\n len_xpts = len(int_xpts)\n self.params[\"len_xpts\"] = len_xpts\n self.params[\"list_xpts\"] = \",\".join(map(str, int_xpts))\n self.params[\"xpts_init\"] = Template(fmt_xpts_init_list).render(**self.params)\n except KeyError:\n pass\n\n self.use_subarray = (\"xpts\" not in self.params)\n</code></pre>"},{"location":"python/post/#post.FluctuationField","title":"<code>FluctuationField</code>","text":"<p> Bases: <code>FieldBase</code></p> <p>\ubb3c\ub9ac \ud544\ub4dc\uc758 \ub09c\ub958 \ubcc0\ub3d9 \uc131\ubd84(Fluctuation, u' = u - )\uc744 \uacc4\uc0b0\ud558\uae30 \uc704\ud55c \ubcc0\uc218 \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. \uc218\uc2dd \ub0b4\uc758 u' \uae30\ud638\ub97c \ud3c9\uade0\ub7c9\uacfc\uc758 \ucc28\uc774 \uc218\uc2dd\uc73c\ub85c \ud33d\ucc3d\ud558\uc5ec \ud560\ub2f9\ud569\ub2c8\ub2e4. Source code in <code>code/code_gen/post.py</code> <pre><code>class FluctuationField(FieldBase):\n \"\"\"\ubb3c\ub9ac \ud544\ub4dc\uc758 \ub09c\ub958 \ubcc0\ub3d9 \uc131\ubd84(Fluctuation, u' = u - &lt;u_w&gt;)\uc744 \uacc4\uc0b0\ud558\uae30 \uc704\ud55c \ubcc0\uc218 \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4.\n \uc218\uc2dd \ub0b4\uc758 u' \uae30\ud638\ub97c \ud3c9\uade0\ub7c9\uacfc\uc758 \ucc28\uc774 \uc218\uc2dd\uc73c\ub85c \ud33d\ucc3d\ud558\uc5ec \ud560\ub2f9\ud569\ub2c8\ub2e4.\n \"\"\"\n\n def __init__(self, w, field, fset, fdict):\n \"\"\"Initializes FluctuationField.\n\n Args:\n w (str/None): Weight variable name or average identifier.\n field (str): Base variable name (e.g. 'u').\n fset (set): Active fluctuation dependency names.\n fdict (dict): Global variable registry.\n \"\"\"\n super(FluctuationField, self).__init__(self.id(w, field), fdict)\n\n if w is not None:\n self.w = w + \"_\"\n else:\n self.w = \"\"\n\n self.field = fdict[field]\n self.dep = self.field.dep - fset\n for df in self.field.dep &amp; fset:\n self.dep.add(self.id(w, df))\n\n self.comment = ExpToCode(self.fdict).transform(self.field.exp)\n\n if self.field.is_fluctuation():\n self.comment = self.comment.format(self.w)\n\n self.comment = self.name + \" = \" + self.comment\n\n @classmethod\n def id(cls, w, field):\n \"\"\"Generates dynamic fluctuation field naming key.\n\n Args:\n w (str/None): Average weight suffix.\n field (str): Base field name.\n\n Returns:\n str: Generated composite fluctuation variable name.\n \"\"\"\n if w:\n name = \"{}____{}_avg\".format(field, w)\n else:\n name = \"{}____avg\".format(field)\n return name\n</code></pre>"},{"location":"python/post/#post.FluctuationField.__init__","title":"<code>__init__(w, field, fset, fdict)</code>","text":"<p>Initializes FluctuationField.</p> <p>Parameters:</p> Name Type Description Default <code>w</code> <code>str / None</code> <p>Weight variable name or average identifier.</p> required <code>field</code> <code>str</code> <p>Base variable name (e.g. 'u').</p> required <code>fset</code> <code>set</code> <p>Active fluctuation dependency names.</p> required <code>fdict</code> <code>dict</code> <p>Global variable registry.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, w, field, fset, fdict):\n \"\"\"Initializes FluctuationField.\n\n Args:\n w (str/None): Weight variable name or average identifier.\n field (str): Base variable name (e.g. 'u').\n fset (set): Active fluctuation dependency names.\n fdict (dict): Global variable registry.\n \"\"\"\n super(FluctuationField, self).__init__(self.id(w, field), fdict)\n\n if w is not None:\n self.w = w + \"_\"\n else:\n self.w = \"\"\n\n self.field = fdict[field]\n self.dep = self.field.dep - fset\n for df in self.field.dep &amp; fset:\n self.dep.add(self.id(w, df))\n\n self.comment = ExpToCode(self.fdict).transform(self.field.exp)\n\n if self.field.is_fluctuation():\n self.comment = self.comment.format(self.w)\n\n self.comment = self.name + \" = \" + self.comment\n</code></pre>"},{"location":"python/post/#post.FluctuationField.id","title":"<code>id(w, field)</code> <code>classmethod</code>","text":"<p>Generates dynamic fluctuation field naming key.</p> <p>Parameters:</p> Name Type Description Default <code>w</code> <code>str / None</code> <p>Average weight suffix.</p> required <code>field</code> <code>str</code> <p>Base field name.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Generated composite fluctuation variable name.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@classmethod\ndef id(cls, w, field):\n \"\"\"Generates dynamic fluctuation field naming key.\n\n Args:\n w (str/None): Average weight suffix.\n field (str): Base field name.\n\n Returns:\n str: Generated composite fluctuation variable name.\n \"\"\"\n if w:\n name = \"{}____{}_avg\".format(field, w)\n else:\n name = \"{}____avg\".format(field)\n return name\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator","title":"<code>FortranCodeGenerator</code>","text":"<p> Bases: <code>object</code></p> <p>Visitor implementation that decouples code generation from domain AST node details.</p> <p>Implements a classic visitor dispatch pattern that matches class names of the Field objects to their code generation routines (e.g. generate_code, generate_decl, generate_alloc, generate_free).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class FortranCodeGenerator(object):\n \"\"\"Visitor implementation that decouples code generation from domain AST node details.\n\n Implements a classic visitor dispatch pattern that matches class names of the Field objects\n to their code generation routines (e.g. generate_code, generate_decl, generate_alloc, generate_free).\n \"\"\"\n\n def __init__(self, fdict):\n \"\"\"Initializes FortranCodeGenerator with the variable registry dictionary.\n\n Args:\n fdict (dict): Dictionary mapping variable names to their corresponding FieldBase objects.\n \"\"\"\n self.fdict = fdict\n\n def generate_code(self, field, alloc=None):\n \"\"\"Dispatches visitor to generate actual calculation code for the field.\n\n Args:\n field (FieldBase): The field node to generate code for.\n alloc (dict, optional): Buffer allocation map for array pooling. Defaults to None.\n\n Returns:\n str: Generated Fortran statement(s) inside loop blocks.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_code'\n visitor = getattr(self, method_name, self.generic_code)\n return visitor(field, alloc)\n\n def generate_decl(self, field):\n \"\"\"Dispatches visitor to generate variable type declarations.\n\n Args:\n field (FieldBase): The field node to generate declaration for.\n\n Returns:\n str: Fortran variable declaration statement.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_decl'\n visitor = getattr(self, method_name, self.generic_decl)\n return visitor(field)\n\n def generate_alloc(self, field):\n \"\"\"Dispatches visitor to generate dynamic memory allocation statements.\n\n Args:\n field (FieldBase): The field node to allocate.\n\n Returns:\n str: Fortran allocate and initialization statements.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_alloc'\n visitor = getattr(self, method_name, self.generic_alloc)\n return visitor(field)\n\n def generate_free(self, field):\n \"\"\"Dispatches visitor to generate deallocation statements.\n\n Args:\n field (FieldBase): The field node to deallocate.\n\n Returns:\n str: Fortran deallocate statements.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_free'\n visitor = getattr(self, method_name, self.generic_free)\n return visitor(field)\n\n def generate_avg(self, field):\n \"\"\"Dispatches visitor to generate average accumulators.\n\n Args:\n field (FieldBase): The averaged field node.\n\n Returns:\n str: Fortran summation and normalization statements.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_avg'\n visitor = getattr(self, method_name, self.generic_avg)\n return visitor(field)\n\n # --- Generic Fallbacks ---\n def generic_code(self, field, alloc=None):\n \"\"\"Generic fallback for code generation.\n\n Args:\n field (FieldBase): The field node.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Empty string.\n \"\"\"\n return \"\"\n\n def generic_decl(self, field):\n \"\"\"Generic fallback for declaration code generation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Standard allocatable real 3D/1D array declaration.\n \"\"\"\n real_array_decl = \"real(real64), allocatable, dimension({1}) :: {0}\"\n return real_array_decl.format(field.name, field.dim)\n\n def generic_alloc(self, field):\n \"\"\"Generic fallback for dynamic allocation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Fortran allocate statement.\n \"\"\"\n return make_allocate(field.name, field.shape)\n\n def generic_free(self, field):\n \"\"\"Generic fallback for deallocation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Fortran deallocate statement.\n \"\"\"\n real_array_free = \"deallocate({})\"\n return real_array_free.format(field.name)\n\n def generic_avg(self, field):\n \"\"\"Generic fallback for average code generation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Empty string.\n \"\"\"\n return \"\"\n\n # --- Visit Methods ---\n\n def visit_FieldExporter_code(self, exporter, alloc=None):\n \"\"\"Generates Fortran code for exporting fields using parallel MPI-IO.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: MPI writing code block.\n \"\"\"\n exporter.params[\"work_array\"] = exporter.parent.array\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_CALC_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_CALC_LEGACY).render(**exporter.params)\n\n def visit_FieldExporter_decl(self, exporter):\n \"\"\"Generates declarations for MPI-IO handles.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n\n Returns:\n str: Declarations block.\n \"\"\"\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_DECL_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_DECL_LEGACY).render(**exporter.params)\n\n def visit_FieldExporter_alloc(self, exporter):\n \"\"\"Generates initialization code for MPI-IO types and file opens.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n\n Returns:\n str: Initialization block.\n \"\"\"\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_INIT_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_INIT_LEGACY).render(**exporter.params)\n\n def visit_FieldExporter_free(self, exporter):\n \"\"\"Generates finalization code for MPI-IO types and file closes.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n\n Returns:\n str: MPI-IO finalization statements.\n \"\"\"\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_FINAL_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_FINAL_LEGACY).render(**exporter.params)\n\n def visit_Field_code(self, field, alloc=None):\n \"\"\"Generates calculation code for normal derived fields with SymPy CSE optimization.\n\n Args:\n field (Field): The calculated field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Renders optimized 3D loop including CSE declarations.\n \"\"\"\n field.array = alloc[field.name] if alloc else field.name\n\n opt = SympyOptimizer.get_instance(self.fdict)\n rhs, cse_decls, cse_assigns = opt.optimize_field(field.name, alloc)\n\n decls_str = \"\\n\".join(cse_decls) if cse_decls else \"\"\n assigns_str = \"\\n\".join(cse_assigns) if cse_assigns else \"\"\n\n calculation_code = Template(FortranTemplateStore.REAL_ARRAY_LOOP).render(\n comment=field.comment,\n decls_str=decls_str,\n assigns_str=assigns_str,\n array=field.array,\n rhs=rhs\n )\n\n export_code = self.generate_code(field.exporter) if field.export_on() else \"\"\n return calculation_code + export_code\n\n def visit_FluctuationField_code(self, field, alloc=None):\n \"\"\"Generates calculation code for turbulence fluctuations.\n\n Args:\n field (FluctuationField): The fluctuation field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Renders 3D loop for calculating u' = u - &lt;u_w&gt;.\n \"\"\"\n field.array = alloc[field.name] if alloc else field.name\n rhs = ExpToCode(self.fdict).transform(field.field.exp)\n\n if field.field.is_fluctuation():\n rhs = rhs.format(field.w)\n\n return Template(FortranTemplateStore.FLUCTUATION_ARRAY_LOOP).render(\n comment=field.comment,\n array=field.array,\n rhs=rhs\n )\n\n def visit_PrimaryField_code(self, field, alloc=None):\n \"\"\"No code generation needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n\n def visit_PrimaryField_decl(self, field):\n \"\"\"No declaration needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n\n def visit_PrimaryField_alloc(self, field):\n \"\"\"No allocation needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n\n def visit_PrimaryField_free(self, field):\n \"\"\"No deallocation needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n\n def visit_DerivedField_code(self, field, alloc=None):\n \"\"\"Generates derivative calculation statements, calling Compact solver subroutines.\n\n Args:\n field (DerivedField): The derivative field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Fortran subroutine call string.\n \"\"\"\n field.array = alloc[field.name] if alloc else field.name\n varray = alloc[field.v] if alloc else field.v\n return \"call {0} ( {2}, {1} )\".format(field.op, varray, field.array)\n\n def visit_AveragedField_code(self, field, alloc=None):\n \"\"\"Generates local accumulation summation loop for spatial averaging.\n\n Args:\n field (AveragedField): The averaged variable field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Renders local sum code block.\n \"\"\"\n arrname = self.fdict[field.tgt].array + \"(i,j,k)\"\n if field.weighted is not None:\n arrname = arrname + \" * \" + field.w.array + \"(i,j,k)\"\n\n return Template(FortranTemplateStore.AVG_ARRAY_SUM).render(name=field.name, arrname=arrname)\n\n def visit_AveragedField_avg(self, field):\n \"\"\"Generates normalization and parallel reduction via MPI_ALLREDUCE.\n\n Args:\n field (AveragedField): The averaged variable field.\n\n Returns:\n str: Renders global reduce and normalize statement.\n \"\"\"\n dWeight = (f\"/ avg_{field.weighted}\" if field.weighted else \"\")\n return Template(FortranTemplateStore.AVG_ARRAY_DIVIDE).render(name=field.name, dWeight=dWeight)\n\n def generate_write_avg(self, avglist):\n \"\"\"Generates final module output writers for 1D spatial averages.\n\n Also generates first and second derivatives of the averaged data using\n ddx1d and d2dx1d subroutines.\n\n Args:\n avglist (list): List of averaged field names.\n\n Returns:\n str: Code block to write values to output files.\n \"\"\"\n avgarr = \"{}(i)\"\n deriv1_avgarr = \"\"\"call ddx1d ( xbuffer, {} ) ; write (200,*) xbuffer\"\"\"\n deriv2_avgarr = \"\"\"call d2dx1d ( xbuffer, {} ) ; write (200,*) xbuffer\"\"\"\n\n num_args = len(avglist) + 1\n formatted_avglist = \", \".join(map(avgarr.format, avglist))\n deriv1_lines = \"\\n\".join(map(deriv1_avgarr.format, avglist))\n deriv2_lines = \"\\n\".join(map(deriv2_avgarr.format, avglist))\n\n write_avg = Template(FortranTemplateStore.AVG_ARRAY_WRITE).render(\n num_args=num_args,\n formatted_avglist=formatted_avglist,\n deriv1_lines=deriv1_lines,\n deriv2_lines=deriv2_lines\n )\n return write_avg\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.__init__","title":"<code>__init__(fdict)</code>","text":"<p>Initializes FortranCodeGenerator with the variable registry dictionary.</p> <p>Parameters:</p> Name Type Description Default <code>fdict</code> <code>dict</code> <p>Dictionary mapping variable names to their corresponding FieldBase objects.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, fdict):\n \"\"\"Initializes FortranCodeGenerator with the variable registry dictionary.\n\n Args:\n fdict (dict): Dictionary mapping variable names to their corresponding FieldBase objects.\n \"\"\"\n self.fdict = fdict\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generate_alloc","title":"<code>generate_alloc(field)</code>","text":"<p>Dispatches visitor to generate dynamic memory allocation statements.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node to allocate.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran allocate and initialization statements.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generate_alloc(self, field):\n \"\"\"Dispatches visitor to generate dynamic memory allocation statements.\n\n Args:\n field (FieldBase): The field node to allocate.\n\n Returns:\n str: Fortran allocate and initialization statements.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_alloc'\n visitor = getattr(self, method_name, self.generic_alloc)\n return visitor(field)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generate_avg","title":"<code>generate_avg(field)</code>","text":"<p>Dispatches visitor to generate average accumulators.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The averaged field node.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran summation and normalization statements.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generate_avg(self, field):\n \"\"\"Dispatches visitor to generate average accumulators.\n\n Args:\n field (FieldBase): The averaged field node.\n\n Returns:\n str: Fortran summation and normalization statements.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_avg'\n visitor = getattr(self, method_name, self.generic_avg)\n return visitor(field)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generate_code","title":"<code>generate_code(field, alloc=None)</code>","text":"<p>Dispatches visitor to generate actual calculation code for the field.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node to generate code for.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map for array pooling. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Generated Fortran statement(s) inside loop blocks.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generate_code(self, field, alloc=None):\n \"\"\"Dispatches visitor to generate actual calculation code for the field.\n\n Args:\n field (FieldBase): The field node to generate code for.\n alloc (dict, optional): Buffer allocation map for array pooling. Defaults to None.\n\n Returns:\n str: Generated Fortran statement(s) inside loop blocks.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_code'\n visitor = getattr(self, method_name, self.generic_code)\n return visitor(field, alloc)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generate_decl","title":"<code>generate_decl(field)</code>","text":"<p>Dispatches visitor to generate variable type declarations.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node to generate declaration for.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran variable declaration statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generate_decl(self, field):\n \"\"\"Dispatches visitor to generate variable type declarations.\n\n Args:\n field (FieldBase): The field node to generate declaration for.\n\n Returns:\n str: Fortran variable declaration statement.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_decl'\n visitor = getattr(self, method_name, self.generic_decl)\n return visitor(field)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generate_free","title":"<code>generate_free(field)</code>","text":"<p>Dispatches visitor to generate deallocation statements.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node to deallocate.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran deallocate statements.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generate_free(self, field):\n \"\"\"Dispatches visitor to generate deallocation statements.\n\n Args:\n field (FieldBase): The field node to deallocate.\n\n Returns:\n str: Fortran deallocate statements.\n \"\"\"\n method_name = 'visit_' + field.__class__.__name__ + '_free'\n visitor = getattr(self, method_name, self.generic_free)\n return visitor(field)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generate_write_avg","title":"<code>generate_write_avg(avglist)</code>","text":"<p>Generates final module output writers for 1D spatial averages.</p> <p>Also generates first and second derivatives of the averaged data using ddx1d and d2dx1d subroutines.</p> <p>Parameters:</p> Name Type Description Default <code>avglist</code> <code>list</code> <p>List of averaged field names.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Code block to write values to output files.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generate_write_avg(self, avglist):\n \"\"\"Generates final module output writers for 1D spatial averages.\n\n Also generates first and second derivatives of the averaged data using\n ddx1d and d2dx1d subroutines.\n\n Args:\n avglist (list): List of averaged field names.\n\n Returns:\n str: Code block to write values to output files.\n \"\"\"\n avgarr = \"{}(i)\"\n deriv1_avgarr = \"\"\"call ddx1d ( xbuffer, {} ) ; write (200,*) xbuffer\"\"\"\n deriv2_avgarr = \"\"\"call d2dx1d ( xbuffer, {} ) ; write (200,*) xbuffer\"\"\"\n\n num_args = len(avglist) + 1\n formatted_avglist = \", \".join(map(avgarr.format, avglist))\n deriv1_lines = \"\\n\".join(map(deriv1_avgarr.format, avglist))\n deriv2_lines = \"\\n\".join(map(deriv2_avgarr.format, avglist))\n\n write_avg = Template(FortranTemplateStore.AVG_ARRAY_WRITE).render(\n num_args=num_args,\n formatted_avglist=formatted_avglist,\n deriv1_lines=deriv1_lines,\n deriv2_lines=deriv2_lines\n )\n return write_avg\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generic_alloc","title":"<code>generic_alloc(field)</code>","text":"<p>Generic fallback for dynamic allocation.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran allocate statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generic_alloc(self, field):\n \"\"\"Generic fallback for dynamic allocation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Fortran allocate statement.\n \"\"\"\n return make_allocate(field.name, field.shape)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generic_avg","title":"<code>generic_avg(field)</code>","text":"<p>Generic fallback for average code generation.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Empty string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generic_avg(self, field):\n \"\"\"Generic fallback for average code generation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Empty string.\n \"\"\"\n return \"\"\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generic_code","title":"<code>generic_code(field, alloc=None)</code>","text":"<p>Generic fallback for code generation.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Empty string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generic_code(self, field, alloc=None):\n \"\"\"Generic fallback for code generation.\n\n Args:\n field (FieldBase): The field node.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Empty string.\n \"\"\"\n return \"\"\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generic_decl","title":"<code>generic_decl(field)</code>","text":"<p>Generic fallback for declaration code generation.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Standard allocatable real 3D/1D array declaration.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generic_decl(self, field):\n \"\"\"Generic fallback for declaration code generation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Standard allocatable real 3D/1D array declaration.\n \"\"\"\n real_array_decl = \"real(real64), allocatable, dimension({1}) :: {0}\"\n return real_array_decl.format(field.name, field.dim)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.generic_free","title":"<code>generic_free(field)</code>","text":"<p>Generic fallback for deallocation.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FieldBase</code> <p>The field node.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran deallocate statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def generic_free(self, field):\n \"\"\"Generic fallback for deallocation.\n\n Args:\n field (FieldBase): The field node.\n\n Returns:\n str: Fortran deallocate statement.\n \"\"\"\n real_array_free = \"deallocate({})\"\n return real_array_free.format(field.name)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_AveragedField_avg","title":"<code>visit_AveragedField_avg(field)</code>","text":"<p>Generates normalization and parallel reduction via MPI_ALLREDUCE.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>AveragedField</code> <p>The averaged variable field.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Renders global reduce and normalize statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_AveragedField_avg(self, field):\n \"\"\"Generates normalization and parallel reduction via MPI_ALLREDUCE.\n\n Args:\n field (AveragedField): The averaged variable field.\n\n Returns:\n str: Renders global reduce and normalize statement.\n \"\"\"\n dWeight = (f\"/ avg_{field.weighted}\" if field.weighted else \"\")\n return Template(FortranTemplateStore.AVG_ARRAY_DIVIDE).render(name=field.name, dWeight=dWeight)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_AveragedField_code","title":"<code>visit_AveragedField_code(field, alloc=None)</code>","text":"<p>Generates local accumulation summation loop for spatial averaging.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>AveragedField</code> <p>The averaged variable field.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Renders local sum code block.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_AveragedField_code(self, field, alloc=None):\n \"\"\"Generates local accumulation summation loop for spatial averaging.\n\n Args:\n field (AveragedField): The averaged variable field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Renders local sum code block.\n \"\"\"\n arrname = self.fdict[field.tgt].array + \"(i,j,k)\"\n if field.weighted is not None:\n arrname = arrname + \" * \" + field.w.array + \"(i,j,k)\"\n\n return Template(FortranTemplateStore.AVG_ARRAY_SUM).render(name=field.name, arrname=arrname)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_DerivedField_code","title":"<code>visit_DerivedField_code(field, alloc=None)</code>","text":"<p>Generates derivative calculation statements, calling Compact solver subroutines.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>DerivedField</code> <p>The derivative field.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran subroutine call string.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_DerivedField_code(self, field, alloc=None):\n \"\"\"Generates derivative calculation statements, calling Compact solver subroutines.\n\n Args:\n field (DerivedField): The derivative field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Fortran subroutine call string.\n \"\"\"\n field.array = alloc[field.name] if alloc else field.name\n varray = alloc[field.v] if alloc else field.v\n return \"call {0} ( {2}, {1} )\".format(field.op, varray, field.array)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_FieldExporter_alloc","title":"<code>visit_FieldExporter_alloc(exporter)</code>","text":"<p>Generates initialization code for MPI-IO types and file opens.</p> <p>Parameters:</p> Name Type Description Default <code>exporter</code> <code>FieldExporter</code> <p>Exporter metadata.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Initialization block.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_FieldExporter_alloc(self, exporter):\n \"\"\"Generates initialization code for MPI-IO types and file opens.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n\n Returns:\n str: Initialization block.\n \"\"\"\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_INIT_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_INIT_LEGACY).render(**exporter.params)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_FieldExporter_code","title":"<code>visit_FieldExporter_code(exporter, alloc=None)</code>","text":"<p>Generates Fortran code for exporting fields using parallel MPI-IO.</p> <p>Parameters:</p> Name Type Description Default <code>exporter</code> <code>FieldExporter</code> <p>Exporter metadata.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>MPI writing code block.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_FieldExporter_code(self, exporter, alloc=None):\n \"\"\"Generates Fortran code for exporting fields using parallel MPI-IO.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: MPI writing code block.\n \"\"\"\n exporter.params[\"work_array\"] = exporter.parent.array\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_CALC_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_CALC_LEGACY).render(**exporter.params)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_FieldExporter_decl","title":"<code>visit_FieldExporter_decl(exporter)</code>","text":"<p>Generates declarations for MPI-IO handles.</p> <p>Parameters:</p> Name Type Description Default <code>exporter</code> <code>FieldExporter</code> <p>Exporter metadata.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Declarations block.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_FieldExporter_decl(self, exporter):\n \"\"\"Generates declarations for MPI-IO handles.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n\n Returns:\n str: Declarations block.\n \"\"\"\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_DECL_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_DECL_LEGACY).render(**exporter.params)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_FieldExporter_free","title":"<code>visit_FieldExporter_free(exporter)</code>","text":"<p>Generates finalization code for MPI-IO types and file closes.</p> <p>Parameters:</p> Name Type Description Default <code>exporter</code> <code>FieldExporter</code> <p>Exporter metadata.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>MPI-IO finalization statements.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_FieldExporter_free(self, exporter):\n \"\"\"Generates finalization code for MPI-IO types and file closes.\n\n Args:\n exporter (FieldExporter): Exporter metadata.\n\n Returns:\n str: MPI-IO finalization statements.\n \"\"\"\n if exporter.use_subarray:\n return Template(FortranTemplateStore.FMT_FINAL_SUBARRAY).render(**exporter.params)\n else:\n return Template(FortranTemplateStore.FMT_FINAL_LEGACY).render(**exporter.params)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_Field_code","title":"<code>visit_Field_code(field, alloc=None)</code>","text":"<p>Generates calculation code for normal derived fields with SymPy CSE optimization.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>Field</code> <p>The calculated field.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Renders optimized 3D loop including CSE declarations.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_Field_code(self, field, alloc=None):\n \"\"\"Generates calculation code for normal derived fields with SymPy CSE optimization.\n\n Args:\n field (Field): The calculated field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Renders optimized 3D loop including CSE declarations.\n \"\"\"\n field.array = alloc[field.name] if alloc else field.name\n\n opt = SympyOptimizer.get_instance(self.fdict)\n rhs, cse_decls, cse_assigns = opt.optimize_field(field.name, alloc)\n\n decls_str = \"\\n\".join(cse_decls) if cse_decls else \"\"\n assigns_str = \"\\n\".join(cse_assigns) if cse_assigns else \"\"\n\n calculation_code = Template(FortranTemplateStore.REAL_ARRAY_LOOP).render(\n comment=field.comment,\n decls_str=decls_str,\n assigns_str=assigns_str,\n array=field.array,\n rhs=rhs\n )\n\n export_code = self.generate_code(field.exporter) if field.export_on() else \"\"\n return calculation_code + export_code\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_FluctuationField_code","title":"<code>visit_FluctuationField_code(field, alloc=None)</code>","text":"<p>Generates calculation code for turbulence fluctuations.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>FluctuationField</code> <p>The fluctuation field.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Renders 3D loop for calculating u' = u - . Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_FluctuationField_code(self, field, alloc=None):\n \"\"\"Generates calculation code for turbulence fluctuations.\n\n Args:\n field (FluctuationField): The fluctuation field.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Renders 3D loop for calculating u' = u - &lt;u_w&gt;.\n \"\"\"\n field.array = alloc[field.name] if alloc else field.name\n rhs = ExpToCode(self.fdict).transform(field.field.exp)\n\n if field.field.is_fluctuation():\n rhs = rhs.format(field.w)\n\n return Template(FortranTemplateStore.FLUCTUATION_ARRAY_LOOP).render(\n comment=field.comment,\n array=field.array,\n rhs=rhs\n )\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_PrimaryField_alloc","title":"<code>visit_PrimaryField_alloc(field)</code>","text":"<p>No allocation needed for primary inputs.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>PrimaryField</code> <p>The primary input.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Comment statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_PrimaryField_alloc(self, field):\n \"\"\"No allocation needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_PrimaryField_code","title":"<code>visit_PrimaryField_code(field, alloc=None)</code>","text":"<p>No code generation needed for primary inputs.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>PrimaryField</code> <p>The primary input.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation map. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Comment statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_PrimaryField_code(self, field, alloc=None):\n \"\"\"No code generation needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n alloc (dict, optional): Buffer allocation map. Defaults to None.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_PrimaryField_decl","title":"<code>visit_PrimaryField_decl(field)</code>","text":"<p>No declaration needed for primary inputs.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>PrimaryField</code> <p>The primary input.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Comment statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_PrimaryField_decl(self, field):\n \"\"\"No declaration needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n</code></pre>"},{"location":"python/post/#post.FortranCodeGenerator.visit_PrimaryField_free","title":"<code>visit_PrimaryField_free(field)</code>","text":"<p>No deallocation needed for primary inputs.</p> <p>Parameters:</p> Name Type Description Default <code>field</code> <code>PrimaryField</code> <p>The primary input.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Comment statement.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def visit_PrimaryField_free(self, field):\n \"\"\"No deallocation needed for primary inputs.\n\n Args:\n field (PrimaryField): The primary input.\n\n Returns:\n str: Comment statement.\n \"\"\"\n return \"! {} is read from file\".format(field.name)\n</code></pre>"},{"location":"python/post/#post.FortranProgramWriter","title":"<code>FortranProgramWriter</code>","text":"<p> Bases: <code>object</code></p> <p>Renders the final, compiled Fortran 95 post-processing modules.</p> <p>Uses Jinja2 templates to combine calculations, averages, declarations, reductions, subarray parallel IO writers, and pooled dynamic array buffers.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class FortranProgramWriter(object):\n \"\"\"Renders the final, compiled Fortran 95 post-processing modules.\n\n Uses Jinja2 templates to combine calculations, averages, declarations,\n reductions, subarray parallel IO writers, and pooled dynamic array buffers.\n \"\"\"\n\n def write(self, ctx):\n \"\"\"Generates the code module and prints it directly to standard output.\n\n Args:\n ctx (CompilationContext): The compiled context containing sorted equations and pooling allocations.\n \"\"\"\n from resources.m_template import mod_form\n\n allvar = dict(ctx.derived)\n allvar.update(ctx.averaged)\n\n generator = FortranCodeGenerator(allvar)\n\n # \ud3c9\uade0 \ubcc0\uc218\ub4e4\uc744 \uc21c\uc11c\ub300\ub85c \ubd84\ubc30\n set1 = sorted([a.name for a in filter(AveragedField.pass1, ctx.averaged.values())])\n set2 = sorted([a.name for a in filter(AveragedField.pass2, ctx.averaged.values())])\n\n # \uc678\ubd80 \ub514\uc2a4\ud06c \ud30c\uc77c \uc775\uc2a4\ud3ec\ud2b8 \ud65c\uc131\ud654 \uc5ec\ubd80 \ud655\uc778\n set_export_on = list(filter(lambda x: x.export_on(), ctx.derived.values()))\n\n ffmt = 'logical, parameter :: pass2_required={}'\n declf = ffmt.format('.true.' if len(set2) &gt; 0 else '.false.')\n\n hfmt = 'character (len = *), parameter :: output_header=\"{}\"'\n declh = hfmt.format(\" \".join([\"x\"] + set1 + set2))\n\n # \uacf5\uc6a9 Pooling 3D \ubc84\ud37c \ubc30\uc5f4\uc758 \uc120\uc5b8/\ud560\ub2f9 \ucf54\ub4dc \uc0dd\uc131\n declarr, allocarr, freearr = self.work_array_codes(ctx.narr)\n\n # 1\ucc28\uc6d0 \ud3c9\uade0 \ubb3c\ub9ac\ub7c9 \ubc30\uc5f4\ub4e4\uc758 \uc120\uc5b8/\ud560\ub2f9 \ucf54\ub4dc \uc0dd\uc131\n declavg = \"\\n\".join(generator.generate_decl(ctx.averaged[v]) for v in sorted(ctx.averaged))\n allocavg = \"\\n\".join(generator.generate_alloc(ctx.averaged[v]) for v in sorted(ctx.averaged))\n freeavg = \"\\n\".join(generator.generate_free(ctx.averaged[v]) for v in sorted(ctx.averaged))\n\n # \ubcd1\ub82c \ud30c\uc77c \uc4f0\uae30(MPI Subarray)\ub97c \uc704\ud55c MPI \ub9ac\uc18c\uc2a4 \uc120\uc5b8/\ud560\ub2f9 \ucf54\ub4dc \uc0dd\uc131\n decl_export = \"\\n\".join(generator.generate_decl(v.exporter) for v in set_export_on)\n alloc_export = \"\\n\".join(generator.generate_alloc(v.exporter) for v in set_export_on)\n free_export = \"\\n\".join(generator.generate_free(v.exporter) for v in set_export_on)\n\n # Pass 1\uacfc Pass 2 \ub8e8\ud504 \ub0b4\ubd80 \ubcf8\ubb38 \uc5f0\uc0b0 \ucf54\ub4dc\ub4e4\uc744 \uc0dd\uc131 (\uac01\uc790 \ubc84\ud37c \ub9f5 alloc1, alloc2 \uc801\uc6a9)\n sub_calc1 = \"\\n\".join(generator.generate_code(allvar[v], ctx.alloc1) for v in ctx.pass1 if v in ctx.averaged or v in ctx.alloc1)\n sub_calc2 = \"\\n\".join(generator.generate_code(allvar[v], ctx.alloc2) for v in ctx.pass2 if v in ctx.averaged or v in ctx.alloc2)\n\n # \ud3c9\uade0 \ub204\uc801 \uc5f0\uc0b0 \ucf54\ub4dc \uc0dd\uc131\n sub_avg1 = \"\\n\".join(generator.generate_avg(allvar[v]) for v in set1)\n sub_avg2 = \"\\n\".join(generator.generate_avg(allvar[v]) for v in set2)\n\n # \ud30c\uc77c \uc4f0\uae30 \ub8e8\ud2f4 \ucf54\ub4dc \uc0dd\uc131\n sub_write_avg = generator.generate_write_avg(set1+set2)\n\n md = {}\n md[\"module_name\"] = \"terms\"\n md[\"module_data\"] = \"\\n\".join((declf, declh, declavg, FieldExporter.mpi_io_decl, decl_export, declarr))\n md[\"module_init\"] = \"\\n\".join((allocavg, alloc_export, allocarr))\n md[\"module_finalize\"] = \"\\n\".join((freeavg, free_export, freearr))\n md[\"module_pass1\"] = sub_calc1\n md[\"module_pass1_avg\"] = sub_avg1\n md[\"module_pass2\"] = sub_calc2\n md[\"module_pass2_avg\"] = sub_avg2\n md[\"module_write_result\"] = sub_write_avg\n\n print(Template(mod_form).render(**md))\n\n def work_array_codes(self, narr):\n \"\"\"Generates dynamic memory helper statements for shared xyzbuffer buffers.\n\n Args:\n narr (int): Number of buffers needed.\n\n Returns:\n tuple: (declarations_string, allocations_string, deallocations_string).\n \"\"\"\n array_name = \"xyzbuffer{}\"\n array_names = [array_name.format(i) for i in range(narr)]\n\n real_array_decl = \"real(real64), allocatable, dimension(:,:,:) :: {0}\"\n decl = \"\\n\".join([real_array_decl.format(v) for v in array_names])\n alloc = \"\\n\".join([make_allocate(v, \"nxp,nyp,nzp\") for v in array_names])\n free = \"\\n\".join([\"deallocate({})\".format(v) for v in array_names])\n\n return decl, alloc, free\n</code></pre>"},{"location":"python/post/#post.FortranProgramWriter.work_array_codes","title":"<code>work_array_codes(narr)</code>","text":"<p>Generates dynamic memory helper statements for shared xyzbuffer buffers.</p> <p>Parameters:</p> Name Type Description Default <code>narr</code> <code>int</code> <p>Number of buffers needed.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p>(declarations_string, allocations_string, deallocations_string).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def work_array_codes(self, narr):\n \"\"\"Generates dynamic memory helper statements for shared xyzbuffer buffers.\n\n Args:\n narr (int): Number of buffers needed.\n\n Returns:\n tuple: (declarations_string, allocations_string, deallocations_string).\n \"\"\"\n array_name = \"xyzbuffer{}\"\n array_names = [array_name.format(i) for i in range(narr)]\n\n real_array_decl = \"real(real64), allocatable, dimension(:,:,:) :: {0}\"\n decl = \"\\n\".join([real_array_decl.format(v) for v in array_names])\n alloc = \"\\n\".join([make_allocate(v, \"nxp,nyp,nzp\") for v in array_names])\n free = \"\\n\".join([\"deallocate({})\".format(v) for v in array_names])\n\n return decl, alloc, free\n</code></pre>"},{"location":"python/post/#post.FortranProgramWriter.write","title":"<code>write(ctx)</code>","text":"<p>Generates the code module and prints it directly to standard output.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>The compiled context containing sorted equations and pooling allocations.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def write(self, ctx):\n \"\"\"Generates the code module and prints it directly to standard output.\n\n Args:\n ctx (CompilationContext): The compiled context containing sorted equations and pooling allocations.\n \"\"\"\n from resources.m_template import mod_form\n\n allvar = dict(ctx.derived)\n allvar.update(ctx.averaged)\n\n generator = FortranCodeGenerator(allvar)\n\n # \ud3c9\uade0 \ubcc0\uc218\ub4e4\uc744 \uc21c\uc11c\ub300\ub85c \ubd84\ubc30\n set1 = sorted([a.name for a in filter(AveragedField.pass1, ctx.averaged.values())])\n set2 = sorted([a.name for a in filter(AveragedField.pass2, ctx.averaged.values())])\n\n # \uc678\ubd80 \ub514\uc2a4\ud06c \ud30c\uc77c \uc775\uc2a4\ud3ec\ud2b8 \ud65c\uc131\ud654 \uc5ec\ubd80 \ud655\uc778\n set_export_on = list(filter(lambda x: x.export_on(), ctx.derived.values()))\n\n ffmt = 'logical, parameter :: pass2_required={}'\n declf = ffmt.format('.true.' if len(set2) &gt; 0 else '.false.')\n\n hfmt = 'character (len = *), parameter :: output_header=\"{}\"'\n declh = hfmt.format(\" \".join([\"x\"] + set1 + set2))\n\n # \uacf5\uc6a9 Pooling 3D \ubc84\ud37c \ubc30\uc5f4\uc758 \uc120\uc5b8/\ud560\ub2f9 \ucf54\ub4dc \uc0dd\uc131\n declarr, allocarr, freearr = self.work_array_codes(ctx.narr)\n\n # 1\ucc28\uc6d0 \ud3c9\uade0 \ubb3c\ub9ac\ub7c9 \ubc30\uc5f4\ub4e4\uc758 \uc120\uc5b8/\ud560\ub2f9 \ucf54\ub4dc \uc0dd\uc131\n declavg = \"\\n\".join(generator.generate_decl(ctx.averaged[v]) for v in sorted(ctx.averaged))\n allocavg = \"\\n\".join(generator.generate_alloc(ctx.averaged[v]) for v in sorted(ctx.averaged))\n freeavg = \"\\n\".join(generator.generate_free(ctx.averaged[v]) for v in sorted(ctx.averaged))\n\n # \ubcd1\ub82c \ud30c\uc77c \uc4f0\uae30(MPI Subarray)\ub97c \uc704\ud55c MPI \ub9ac\uc18c\uc2a4 \uc120\uc5b8/\ud560\ub2f9 \ucf54\ub4dc \uc0dd\uc131\n decl_export = \"\\n\".join(generator.generate_decl(v.exporter) for v in set_export_on)\n alloc_export = \"\\n\".join(generator.generate_alloc(v.exporter) for v in set_export_on)\n free_export = \"\\n\".join(generator.generate_free(v.exporter) for v in set_export_on)\n\n # Pass 1\uacfc Pass 2 \ub8e8\ud504 \ub0b4\ubd80 \ubcf8\ubb38 \uc5f0\uc0b0 \ucf54\ub4dc\ub4e4\uc744 \uc0dd\uc131 (\uac01\uc790 \ubc84\ud37c \ub9f5 alloc1, alloc2 \uc801\uc6a9)\n sub_calc1 = \"\\n\".join(generator.generate_code(allvar[v], ctx.alloc1) for v in ctx.pass1 if v in ctx.averaged or v in ctx.alloc1)\n sub_calc2 = \"\\n\".join(generator.generate_code(allvar[v], ctx.alloc2) for v in ctx.pass2 if v in ctx.averaged or v in ctx.alloc2)\n\n # \ud3c9\uade0 \ub204\uc801 \uc5f0\uc0b0 \ucf54\ub4dc \uc0dd\uc131\n sub_avg1 = \"\\n\".join(generator.generate_avg(allvar[v]) for v in set1)\n sub_avg2 = \"\\n\".join(generator.generate_avg(allvar[v]) for v in set2)\n\n # \ud30c\uc77c \uc4f0\uae30 \ub8e8\ud2f4 \ucf54\ub4dc \uc0dd\uc131\n sub_write_avg = generator.generate_write_avg(set1+set2)\n\n md = {}\n md[\"module_name\"] = \"terms\"\n md[\"module_data\"] = \"\\n\".join((declf, declh, declavg, FieldExporter.mpi_io_decl, decl_export, declarr))\n md[\"module_init\"] = \"\\n\".join((allocavg, alloc_export, allocarr))\n md[\"module_finalize\"] = \"\\n\".join((freeavg, free_export, freearr))\n md[\"module_pass1\"] = sub_calc1\n md[\"module_pass1_avg\"] = sub_avg1\n md[\"module_pass2\"] = sub_calc2\n md[\"module_pass2_avg\"] = sub_avg2\n md[\"module_write_result\"] = sub_write_avg\n\n print(Template(mod_form).render(**md))\n</code></pre>"},{"location":"python/post/#post.FortranTemplateStore","title":"<code>FortranTemplateStore</code>","text":"<p>Static store containing Jinja2 code templates for generating Fortran source blocks.</p> <p>Attributes:</p> Name Type Description <code>REAL_ARRAY_LOOP</code> <code>str</code> <p>Standard 3D loop for calculating derived variables, integrating SymPy CSE blocks.</p> <code>FLUCTUATION_ARRAY_LOOP</code> <code>str</code> <p>Loop for calculating fluctuation fields (with averages subtracted).</p> <code>AVG_ARRAY_SUM</code> <code>str</code> <p>Accumulator loop to sum grid values for spatial averaging.</p> <code>AVG_ARRAY_DIVIDE</code> <code>str</code> <p>Global MPI MPI_ALLREDUCE and divide step to finalize statistics.</p> <code>FMT_DECL_SUBARRAY</code> <code>str</code> <p>MPI subarray-based I/O file handle and type variable declarations.</p> <code>FMT_INIT_SUBARRAY</code> <code>str</code> <p>Initialization block for creating MPI file handles and commit subarray types.</p> <code>FMT_FINAL_SUBARRAY</code> <code>str</code> <p>Cleanup code block to close and release MPI types and file handles.</p> <code>FMT_CALC_SUBARRAY</code> <code>str</code> <p>Actual high-performance parallel MPI file writing using subarray layout.</p> <code>FMT_DECL_LEGACY</code> <code>str</code> <p>Declarations for legacy, process-local buffer-based MPI exports.</p> <code>FMT_INIT_LEGACY</code> <code>str</code> <p>Allocation and initialization for legacy buffer arrays.</p> <code>FMT_FINAL_LEGACY</code> <code>str</code> <p>Finalization and deallocation for legacy buffer arrays.</p> <code>FMT_CALC_LEGACY</code> <code>str</code> <p>Data slicing and local buffer writing for legacy export routines.</p> <code>AVG_ARRAY_WRITE</code> <code>str</code> <p>Serial file writing structure for exporting 1D averaged data and derivatives.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class FortranTemplateStore:\n \"\"\"Static store containing Jinja2 code templates for generating Fortran source blocks.\n\n Attributes:\n REAL_ARRAY_LOOP (str): Standard 3D loop for calculating derived variables, integrating SymPy CSE blocks.\n FLUCTUATION_ARRAY_LOOP (str): Loop for calculating fluctuation fields (with averages subtracted).\n AVG_ARRAY_SUM (str): Accumulator loop to sum grid values for spatial averaging.\n AVG_ARRAY_DIVIDE (str): Global MPI MPI_ALLREDUCE and divide step to finalize statistics.\n FMT_DECL_SUBARRAY (str): MPI subarray-based I/O file handle and type variable declarations.\n FMT_INIT_SUBARRAY (str): Initialization block for creating MPI file handles and commit subarray types.\n FMT_FINAL_SUBARRAY (str): Cleanup code block to close and release MPI types and file handles.\n FMT_CALC_SUBARRAY (str): Actual high-performance parallel MPI file writing using subarray layout.\n FMT_DECL_LEGACY (str): Declarations for legacy, process-local buffer-based MPI exports.\n FMT_INIT_LEGACY (str): Allocation and initialization for legacy buffer arrays.\n FMT_FINAL_LEGACY (str): Finalization and deallocation for legacy buffer arrays.\n FMT_CALC_LEGACY (str): Data slicing and local buffer writing for legacy export routines.\n AVG_ARRAY_WRITE (str): Serial file writing structure for exporting 1D averaged data and derivatives.\n \"\"\"\n REAL_ARRAY_LOOP = \"\"\"\n! {{ comment }}\n{% if decls_str -%}\nblock\n{{ decls_str | indent(4, True) }}\n{%- endif %}\ndo k = 1, nzp\ndo j = 1, nyp\ndo i = 1, nxp\n{% if assigns_str -%}\n{{ assigns_str | indent(4, True) }}\n {{ array }}(i,j,k) = {{ rhs }}\n{%- else -%}\n {{ array }}(i,j,k) = {{ rhs }}\n{%- endif %}\nend do\nend do\nend do\n{% if decls_str -%}\nend block\n{%- endif %}\n\"\"\"\n\n FLUCTUATION_ARRAY_LOOP = \"\"\"\n! {{ comment }}\ndo k = 1, nzp\ndo j = 1, nyp\ndo i = 1, nxp\n{{ array }}(i,j,k) = {{ rhs }}\nend do\nend do\nend do\n\"\"\"\n\n AVG_ARRAY_SUM = \"\"\"\ndo k = 1, nzp\ndo j = 1, nyp\ndo i = 1, nxp\n{{ name }}(i) = {{ name }}(i) + {{ arrname }}\nend do\nend do\nend do\n\"\"\"\n\n AVG_ARRAY_DIVIDE = \"\"\"\ncall MPI_ALLREDUCE(MPI_IN_PLACE, {{ name }}, nxp, MPI_REAL8, MPI_SUM, MPI_COMM_TASK, mpi_err)\n\n{{ name }} = {{ name }} {{ dWeight }} / denum\n\"\"\"\n\n FMT_DECL_SUBARRAY = \"\"\"\n! - file_handles and mpi_infos\ninteger(kind=MPI_INTEGER_KIND) :: {{ field_name }}_fh\ninteger(kind=MPI_INTEGER_KIND) :: {{ field_name }}_info\ninteger(kind=MPI_INTEGER_KIND) :: {{ field_name }}_filetype\n\"\"\"\n\n FMT_INIT_SUBARRAY = \"\"\"\n! init subarray datatype for {{ field_name }}\nblock\n integer(4) :: sizes(3), subsizes(3), starts(3)\n call MPI_INFO_CREATE({{ field_name }}_info, mpi_err)\n call MPI_FILE_OPEN(MPI_COMM_TASK,'export-{{ field_name }}.dat',MPI_MODE_WRONLY+MPI_MODE_CREATE,{{ field_name }}_info,{{ field_name }}_fh,mpi_err)\n sizes = (/ nxp, nyp, nzp /)\n subsizes = (/ {{ len_xpts }}, {{ ye }} - {{ ys }} + 1, {{ ze }} - {{ zs }} + 1 /)\n starts = (/ {{ xs }} - 1, {{ ys }} - 1, {{ zs }} - 1 /)\n call MPI_TYPE_CREATE_SUBARRAY(3, sizes, subsizes, starts, MPI_ORDER_FORTRAN, MPI_REAL8, {{ field_name }}_filetype, mpi_err)\n call MPI_TYPE_COMMIT({{ field_name }}_filetype, mpi_err)\nend block\n\"\"\"\n\n FMT_FINAL_SUBARRAY = \"\"\"\n! finalize\ncall MPI_FILE_CLOSE({{ field_name }}_fh, mpi_err)\ncall MPI_INFO_FREE({{ field_name }}_info, mpi_err)\ncall MPI_TYPE_FREE({{ field_name }}_filetype, mpi_err)\n\"\"\"\n\n FMT_CALC_SUBARRAY = \"\"\"\n! write to file via MPI Subarray\ncount = ({{ len_xpts }}) * ({{ ye }} - {{ ys }} + 1) * ({{ ze }} - {{ zs }} + 1)\noffset = export_offset(fidx) * count * 8\ncall MPI_FILE_WRITE_AT({{ field_name }}_fh, offset, {{ work_array }}, 1, {{ field_name }}_filetype, mpi_status, mpi_err)\n\"\"\"\n\n FMT_DECL_LEGACY = \"\"\"\n! - file_handles and mpi_infos\ninteger(kind=MPI_INTEGER_KIND) :: {{ field_name }}_fh\ninteger(kind=MPI_INTEGER_KIND) :: {{ field_name }}_info\n\n! - buffer\nreal(real64), allocatable, dimension(:,:,:) :: {{ field_name }}_export_array\ninteger, allocatable, dimension(:) :: {{ field_name }}_xpts\n\"\"\"\n\n FMT_INIT_LEGACY = \"\"\"\n! init\ncall MPI_INFO_CREATE({{ field_name }}_info, mpi_err)\ncall MPI_FILE_OPEN(MPI_COMM_TASK,'export-{{ field_name }}.dat',MPI_MODE_WRONLY+MPI_MODE_CREATE,{{ field_name }}_info,{{ field_name }}_fh,mpi_err)\nallocate({{ field_name }}_export_array(1:{{ len_xpts }},{{ ys }}:{{ ye }},{{ zs }}:{{ ze }}), stat=ierr)\nif (ierr /= 0) then\n write(0,*) 'Error: allocation of {{ field_name }}_export_array failed on process', myid\n call MPI_ABORT(MPI_COMM_TASK, 1, mpi_err)\nend if\n{{ field_name }}_export_array = 0.\nallocate({{ field_name }}_xpts(1:{{ len_xpts }}), stat=ierr)\nif (ierr /= 0) then\n write(0,*) 'Error: allocation of {{ field_name }}_xpts failed on process', myid\n call MPI_ABORT(MPI_COMM_TASK, 1, mpi_err)\nend if\n{{ xpts_init }}\n\"\"\"\n\n FMT_FINAL_LEGACY = \"\"\"\n! finalize\ncall MPI_FILE_CLOSE({{ field_name }}_fh, mpi_err)\ncall MPI_INFO_FREE({{ field_name }}_info, mpi_err)\ndeallocate({{ field_name }}_export_array)\ndeallocate({{ field_name }}_xpts)\n\"\"\"\n\n FMT_CALC_LEGACY = \"\"\"\n! copy to array for export\ndo k = {{ zs }}, {{ ze }}\ndo j = {{ ys }}, {{ ye }}\ndo i = 1, {{ len_xpts }}\n{{ field_name }}_export_array(i,j,k) = {{ work_array }}({{ field_name }}_xpts(i),j,k)\nend do\nend do\nend do\n\n! write to file\ncount = ({{ len_xpts }}) * ({{ ye }} - {{ ys }} + 1) * ({{ ze }} - {{ zs }} + 1)\noffset = export_offset(fidx) * count * 8\ncall MPI_FILE_WRITE_AT({{ field_name }}_fh, offset, {{ field_name }}_export_array, count, MPI_REAL8, mpi_status, mpi_err)\n\"\"\"\n\n AVG_ARRAY_WRITE = \"\"\"\nreal(real64), dimension(nxp) :: xbuffer\ninteger :: i\n\nopen (200, file=\"qEdge_X.dat\")\nwrite (200,*) output_header\ndo i=1,nxp\n write (200,'({{ num_args }}e20.10)') real(i)*hxp, {{ formatted_avglist }}\nend do\nclose (200)\n\nopen (200, file=\"d1.dat\")\n{{ deriv1_lines }}\nclose (200)\n\nopen (200, file=\"d2.dat\")\n{{ deriv2_lines }}\nclose (200)\n\"\"\"\n</code></pre>"},{"location":"python/post/#post.FunctionRegistry","title":"<code>FunctionRegistry</code>","text":"<p>Registry to map mathematical DSL functions to SymPy constructors and LaTeX representations.</p> <p>This class enables SOLID Open-Closed Principle (OCP) compliance by decoupling core parsing logic from mathematical functions, allowing new functions to be added without modifying the parser.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class FunctionRegistry:\n \"\"\"Registry to map mathematical DSL functions to SymPy constructors and LaTeX representations.\n\n This class enables SOLID Open-Closed Principle (OCP) compliance by decoupling core parsing\n logic from mathematical functions, allowing new functions to be added without modifying the parser.\n \"\"\"\n\n def __init__(self):\n \"\"\"Initializes FunctionRegistry with empty SymPy and LaTeX mappings.\"\"\"\n self._sympy_registry = {}\n self._latex_registry = {}\n\n def register_sympy(self, name, sympy_builder):\n \"\"\"Registers a handler to convert a DSL function to a SymPy representation.\n\n Args:\n name (str): The name of the DSL function.\n sympy_builder (callable): A callable mapping function arguments to a SymPy object.\n \"\"\"\n self._sympy_registry[name] = sympy_builder\n\n def register_latex(self, name, latex_builder):\n \"\"\"Registers a handler to convert a DSL function to a LaTeX math representation.\n\n Args:\n name (str): The name of the DSL function.\n latex_builder (callable): A callable mapping arguments to a LaTeX string.\n \"\"\"\n self._latex_registry[name] = latex_builder\n\n def to_sympy(self, name, *args):\n \"\"\"Converts a function call to its corresponding SymPy expression.\n\n Args:\n name (str): The name of the function.\n *args: Arguments to pass to the sympy builder.\n\n Returns:\n sympy.Expr: SymPy node representation of the function call.\n \"\"\"\n if name in self._sympy_registry:\n return self._sympy_registry[name](*args)\n return sympy.Function(name)(*args)\n\n def to_latex(self, name, *args):\n \"\"\"Converts a function call to its corresponding LaTeX representation.\n\n Args:\n name (str): The name of the function.\n *args (str): Already-formatted LaTeX strings of the arguments.\n\n Returns:\n str: The LaTeX math representation of the function call.\n \"\"\"\n if name in self._latex_registry:\n return self._latex_registry[name](*args)\n b = \", \".join(args)\n if name.startswith(\"\\\\\"):\n return r\"{}{{({})}}\".format(name, b)\n return r\"\\mathrm{{{}}}({})\".format(name, b)\n</code></pre>"},{"location":"python/post/#post.FunctionRegistry.__init__","title":"<code>__init__()</code>","text":"<p>Initializes FunctionRegistry with empty SymPy and LaTeX mappings.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self):\n \"\"\"Initializes FunctionRegistry with empty SymPy and LaTeX mappings.\"\"\"\n self._sympy_registry = {}\n self._latex_registry = {}\n</code></pre>"},{"location":"python/post/#post.FunctionRegistry.register_latex","title":"<code>register_latex(name, latex_builder)</code>","text":"<p>Registers a handler to convert a DSL function to a LaTeX math representation.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>The name of the DSL function.</p> required <code>latex_builder</code> <code>callable</code> <p>A callable mapping arguments to a LaTeX string.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def register_latex(self, name, latex_builder):\n \"\"\"Registers a handler to convert a DSL function to a LaTeX math representation.\n\n Args:\n name (str): The name of the DSL function.\n latex_builder (callable): A callable mapping arguments to a LaTeX string.\n \"\"\"\n self._latex_registry[name] = latex_builder\n</code></pre>"},{"location":"python/post/#post.FunctionRegistry.register_sympy","title":"<code>register_sympy(name, sympy_builder)</code>","text":"<p>Registers a handler to convert a DSL function to a SymPy representation.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>The name of the DSL function.</p> required <code>sympy_builder</code> <code>callable</code> <p>A callable mapping function arguments to a SymPy object.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def register_sympy(self, name, sympy_builder):\n \"\"\"Registers a handler to convert a DSL function to a SymPy representation.\n\n Args:\n name (str): The name of the DSL function.\n sympy_builder (callable): A callable mapping function arguments to a SymPy object.\n \"\"\"\n self._sympy_registry[name] = sympy_builder\n</code></pre>"},{"location":"python/post/#post.FunctionRegistry.to_latex","title":"<code>to_latex(name, *args)</code>","text":"<p>Converts a function call to its corresponding LaTeX representation.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>The name of the function.</p> required <code>*args</code> <code>str</code> <p>Already-formatted LaTeX strings of the arguments.</p> <code>()</code> <p>Returns:</p> Name Type Description <code>str</code> <p>The LaTeX math representation of the function call.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def to_latex(self, name, *args):\n \"\"\"Converts a function call to its corresponding LaTeX representation.\n\n Args:\n name (str): The name of the function.\n *args (str): Already-formatted LaTeX strings of the arguments.\n\n Returns:\n str: The LaTeX math representation of the function call.\n \"\"\"\n if name in self._latex_registry:\n return self._latex_registry[name](*args)\n b = \", \".join(args)\n if name.startswith(\"\\\\\"):\n return r\"{}{{({})}}\".format(name, b)\n return r\"\\mathrm{{{}}}({})\".format(name, b)\n</code></pre>"},{"location":"python/post/#post.FunctionRegistry.to_sympy","title":"<code>to_sympy(name, *args)</code>","text":"<p>Converts a function call to its corresponding SymPy expression.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>The name of the function.</p> required <code>*args</code> <p>Arguments to pass to the sympy builder.</p> <code>()</code> <p>Returns:</p> Type Description <p>sympy.Expr: SymPy node representation of the function call.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def to_sympy(self, name, *args):\n \"\"\"Converts a function call to its corresponding SymPy expression.\n\n Args:\n name (str): The name of the function.\n *args: Arguments to pass to the sympy builder.\n\n Returns:\n sympy.Expr: SymPy node representation of the function call.\n \"\"\"\n if name in self._sympy_registry:\n return self._sympy_registry[name](*args)\n return sympy.Function(name)(*args)\n</code></pre>"},{"location":"python/post/#post.LarkToSympy","title":"<code>LarkToSympy</code>","text":"<p> Bases: <code>Transformer</code></p> <p>Transformer to convert Lark AST math nodes to SymPy symbolic expressions.</p> <p>Maps DSL expression trees into SymPy expressions to allow down-pipeline algebraic simplification, common subexpression elimination (CSE), and memory optimization.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@v_args(inline=True)\nclass LarkToSympy(Transformer):\n \"\"\"Transformer to convert Lark AST math nodes to SymPy symbolic expressions.\n\n Maps DSL expression trees into SymPy expressions to allow down-pipeline algebraic\n simplification, common subexpression elimination (CSE), and memory optimization.\n \"\"\"\n\n def __init__(self, fdict):\n \"\"\"Initializes LarkToSympy transformer.\n\n Args:\n fdict (dict): Dictionary mapping variable names to FieldBase objects.\n \"\"\"\n self.fdict = fdict\n\n def number(self, numeral):\n \"\"\"Converts number strings into SymPy Float objects.\n\n Args:\n numeral (Token/str): Numeric string from the AST.\n\n Returns:\n sympy.Float: SymPy floating point object.\n \"\"\"\n return sympy.Float(float(numeral))\n\n def env(self, name):\n \"\"\"Converts environment variable tokens to SymPy Symbol objects.\n\n Args:\n name (Token): Environment variable name token (prefixed with $).\n\n Returns:\n sympy.Symbol: SymPy symbol representation.\n \"\"\"\n return sympy.Symbol(name.value)\n\n def paren(self, val):\n \"\"\"Preserves precedence inside parentheses and returns the child expression.\n\n Args:\n val (sympy.Expr): Expression inside parentheses.\n\n Returns:\n sympy.Expr: The inner expression unchanged.\n \"\"\"\n return val\n\n def var(self, name):\n \"\"\"Maps variable name tokens to SymPy Symbol objects.\n\n Args:\n name (Token): Variable name token.\n\n Returns:\n sympy.Symbol: SymPy symbol representation.\n \"\"\"\n return sympy.Symbol(name.value)\n\n def fluc(self, name):\n \"\"\"Maps turbulence fluctuation variables (e.g., u') to a SymPy Symbol with '__prime' suffix.\n\n Args:\n name (Token): Variable name token representing fluctuation.\n\n Returns:\n sympy.Symbol: SymPy symbol with prime suffix identifier.\n \"\"\"\n return sympy.Symbol(name.value + \"__prime\")\n\n def dnx(self, partial, b):\n \"\"\"Maps spatial derivative operations (e.g., ddx(u)) to a single composite SymPy Symbol.\n\n This treats the derivative term (e.g., ddx_u) as an independent symbol.\n\n Args:\n partial (Token): Derivative operator token.\n b (Token): Variable name token being differentiated.\n\n Returns:\n sympy.Symbol: Composite derivative symbol representation.\n \"\"\"\n signature = f\"{partial.data}_{b.value}\"\n return sympy.Symbol(signature)\n\n def icall(self, op, val):\n \"\"\"Converts inline functions (e.g., sqr, pow3) to direct SymPy exponent expressions.\n\n Args:\n op (Token): Inline function operator token.\n val (sympy.Expr): The function argument expression.\n\n Returns:\n sympy.Expr: SymPy power expression.\n \"\"\"\n if op.data == \"sqr\":\n return val**2\n elif op.data == \"pow3\":\n return val**3\n return val\n\n def fcall(self, *args):\n \"\"\"Maps standard built-in functions or UDFs to their SymPy representations.\n\n Args:\n *args: Variable length argument list. The first argument is the function name Token,\n and the subsequent arguments are the function parameter expressions.\n\n Returns:\n sympy.Expr: SymPy function node or registered mathematical expression.\n \"\"\"\n a = args[0]\n func_name = a.value if hasattr(a, 'value') else str(a)\n if func_name == \"udf\":\n return sympy.Function(a.value if hasattr(a, 'value') else str(a))(*args[1:])\n return function_registry.to_sympy(func_name, *args[1:])\n\n def neg(self, val):\n \"\"\"Converts negation to SymPy unary negation.\n\n Args:\n val (sympy.Expr): The expression to negate.\n\n Returns:\n sympy.Expr: Negated SymPy expression.\n \"\"\"\n return -val\n\n def add(self, a, b):\n \"\"\"Converts addition to SymPy sum expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy addition expression.\n \"\"\"\n return a + b\n\n def sub(self, a, b):\n \"\"\"Converts subtraction to SymPy difference expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy subtraction expression.\n \"\"\"\n return a - b\n\n def mul(self, a, b):\n \"\"\"Converts multiplication to SymPy product expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy product expression.\n \"\"\"\n return a * b\n\n def div(self, a, b):\n \"\"\"Converts division to SymPy division expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy division expression.\n \"\"\"\n return a / b\n\n def udf(self, a):\n \"\"\"Maps user defined function names to string representations.\n\n Args:\n a (Token): Function token.\n\n Returns:\n str: Name of the user defined function.\n \"\"\"\n return a.value\n\n log = lambda self: \"log\"\n exp = lambda self: \"exp\"\n sqrt = lambda self: \"sqrt\"\n abs = lambda self: \"abs\"\n rxn_rate = lambda self: \"rxn_rate\"\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.__init__","title":"<code>__init__(fdict)</code>","text":"<p>Initializes LarkToSympy transformer.</p> <p>Parameters:</p> Name Type Description Default <code>fdict</code> <code>dict</code> <p>Dictionary mapping variable names to FieldBase objects.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, fdict):\n \"\"\"Initializes LarkToSympy transformer.\n\n Args:\n fdict (dict): Dictionary mapping variable names to FieldBase objects.\n \"\"\"\n self.fdict = fdict\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.add","title":"<code>add(a, b)</code>","text":"<p>Converts addition to SymPy sum expression.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Expr</code> <p>Left expression.</p> required <code>b</code> <code>Expr</code> <p>Right expression.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: SymPy addition expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def add(self, a, b):\n \"\"\"Converts addition to SymPy sum expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy addition expression.\n \"\"\"\n return a + b\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.div","title":"<code>div(a, b)</code>","text":"<p>Converts division to SymPy division expression.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Expr</code> <p>Left expression.</p> required <code>b</code> <code>Expr</code> <p>Right expression.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: SymPy division expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def div(self, a, b):\n \"\"\"Converts division to SymPy division expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy division expression.\n \"\"\"\n return a / b\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.dnx","title":"<code>dnx(partial, b)</code>","text":"<p>Maps spatial derivative operations (e.g., ddx(u)) to a single composite SymPy Symbol.</p> <p>This treats the derivative term (e.g., ddx_u) as an independent symbol.</p> <p>Parameters:</p> Name Type Description Default <code>partial</code> <code>Token</code> <p>Derivative operator token.</p> required <code>b</code> <code>Token</code> <p>Variable name token being differentiated.</p> required <p>Returns:</p> Type Description <p>sympy.Symbol: Composite derivative symbol representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def dnx(self, partial, b):\n \"\"\"Maps spatial derivative operations (e.g., ddx(u)) to a single composite SymPy Symbol.\n\n This treats the derivative term (e.g., ddx_u) as an independent symbol.\n\n Args:\n partial (Token): Derivative operator token.\n b (Token): Variable name token being differentiated.\n\n Returns:\n sympy.Symbol: Composite derivative symbol representation.\n \"\"\"\n signature = f\"{partial.data}_{b.value}\"\n return sympy.Symbol(signature)\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.env","title":"<code>env(name)</code>","text":"<p>Converts environment variable tokens to SymPy Symbol objects.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Environment variable name token (prefixed with $).</p> required <p>Returns:</p> Type Description <p>sympy.Symbol: SymPy symbol representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def env(self, name):\n \"\"\"Converts environment variable tokens to SymPy Symbol objects.\n\n Args:\n name (Token): Environment variable name token (prefixed with $).\n\n Returns:\n sympy.Symbol: SymPy symbol representation.\n \"\"\"\n return sympy.Symbol(name.value)\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.fcall","title":"<code>fcall(*args)</code>","text":"<p>Maps standard built-in functions or UDFs to their SymPy representations.</p> <p>Parameters:</p> Name Type Description Default <code>*args</code> <p>Variable length argument list. The first argument is the function name Token, and the subsequent arguments are the function parameter expressions.</p> <code>()</code> <p>Returns:</p> Type Description <p>sympy.Expr: SymPy function node or registered mathematical expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def fcall(self, *args):\n \"\"\"Maps standard built-in functions or UDFs to their SymPy representations.\n\n Args:\n *args: Variable length argument list. The first argument is the function name Token,\n and the subsequent arguments are the function parameter expressions.\n\n Returns:\n sympy.Expr: SymPy function node or registered mathematical expression.\n \"\"\"\n a = args[0]\n func_name = a.value if hasattr(a, 'value') else str(a)\n if func_name == \"udf\":\n return sympy.Function(a.value if hasattr(a, 'value') else str(a))(*args[1:])\n return function_registry.to_sympy(func_name, *args[1:])\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.fluc","title":"<code>fluc(name)</code>","text":"<p>Maps turbulence fluctuation variables (e.g., u') to a SymPy Symbol with '__prime' suffix.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Variable name token representing fluctuation.</p> required <p>Returns:</p> Type Description <p>sympy.Symbol: SymPy symbol with prime suffix identifier.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def fluc(self, name):\n \"\"\"Maps turbulence fluctuation variables (e.g., u') to a SymPy Symbol with '__prime' suffix.\n\n Args:\n name (Token): Variable name token representing fluctuation.\n\n Returns:\n sympy.Symbol: SymPy symbol with prime suffix identifier.\n \"\"\"\n return sympy.Symbol(name.value + \"__prime\")\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.icall","title":"<code>icall(op, val)</code>","text":"<p>Converts inline functions (e.g., sqr, pow3) to direct SymPy exponent expressions.</p> <p>Parameters:</p> Name Type Description Default <code>op</code> <code>Token</code> <p>Inline function operator token.</p> required <code>val</code> <code>Expr</code> <p>The function argument expression.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: SymPy power expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def icall(self, op, val):\n \"\"\"Converts inline functions (e.g., sqr, pow3) to direct SymPy exponent expressions.\n\n Args:\n op (Token): Inline function operator token.\n val (sympy.Expr): The function argument expression.\n\n Returns:\n sympy.Expr: SymPy power expression.\n \"\"\"\n if op.data == \"sqr\":\n return val**2\n elif op.data == \"pow3\":\n return val**3\n return val\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.mul","title":"<code>mul(a, b)</code>","text":"<p>Converts multiplication to SymPy product expression.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Expr</code> <p>Left expression.</p> required <code>b</code> <code>Expr</code> <p>Right expression.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: SymPy product expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def mul(self, a, b):\n \"\"\"Converts multiplication to SymPy product expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy product expression.\n \"\"\"\n return a * b\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.neg","title":"<code>neg(val)</code>","text":"<p>Converts negation to SymPy unary negation.</p> <p>Parameters:</p> Name Type Description Default <code>val</code> <code>Expr</code> <p>The expression to negate.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: Negated SymPy expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def neg(self, val):\n \"\"\"Converts negation to SymPy unary negation.\n\n Args:\n val (sympy.Expr): The expression to negate.\n\n Returns:\n sympy.Expr: Negated SymPy expression.\n \"\"\"\n return -val\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.number","title":"<code>number(numeral)</code>","text":"<p>Converts number strings into SymPy Float objects.</p> <p>Parameters:</p> Name Type Description Default <code>numeral</code> <code>Token / str</code> <p>Numeric string from the AST.</p> required <p>Returns:</p> Type Description <p>sympy.Float: SymPy floating point object.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def number(self, numeral):\n \"\"\"Converts number strings into SymPy Float objects.\n\n Args:\n numeral (Token/str): Numeric string from the AST.\n\n Returns:\n sympy.Float: SymPy floating point object.\n \"\"\"\n return sympy.Float(float(numeral))\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.paren","title":"<code>paren(val)</code>","text":"<p>Preserves precedence inside parentheses and returns the child expression.</p> <p>Parameters:</p> Name Type Description Default <code>val</code> <code>Expr</code> <p>Expression inside parentheses.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: The inner expression unchanged.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def paren(self, val):\n \"\"\"Preserves precedence inside parentheses and returns the child expression.\n\n Args:\n val (sympy.Expr): Expression inside parentheses.\n\n Returns:\n sympy.Expr: The inner expression unchanged.\n \"\"\"\n return val\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.sub","title":"<code>sub(a, b)</code>","text":"<p>Converts subtraction to SymPy difference expression.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Expr</code> <p>Left expression.</p> required <code>b</code> <code>Expr</code> <p>Right expression.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: SymPy subtraction expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def sub(self, a, b):\n \"\"\"Converts subtraction to SymPy difference expression.\n\n Args:\n a (sympy.Expr): Left expression.\n b (sympy.Expr): Right expression.\n\n Returns:\n sympy.Expr: SymPy subtraction expression.\n \"\"\"\n return a - b\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.udf","title":"<code>udf(a)</code>","text":"<p>Maps user defined function names to string representations.</p> <p>Parameters:</p> Name Type Description Default <code>a</code> <code>Token</code> <p>Function token.</p> required <p>Returns:</p> Name Type Description <code>str</code> <p>Name of the user defined function.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def udf(self, a):\n \"\"\"Maps user defined function names to string representations.\n\n Args:\n a (Token): Function token.\n\n Returns:\n str: Name of the user defined function.\n \"\"\"\n return a.value\n</code></pre>"},{"location":"python/post/#post.LarkToSympy.var","title":"<code>var(name)</code>","text":"<p>Maps variable name tokens to SymPy Symbol objects.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>Token</code> <p>Variable name token.</p> required <p>Returns:</p> Type Description <p>sympy.Symbol: SymPy symbol representation.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def var(self, name):\n \"\"\"Maps variable name tokens to SymPy Symbol objects.\n\n Args:\n name (Token): Variable name token.\n\n Returns:\n sympy.Symbol: SymPy symbol representation.\n \"\"\"\n return sympy.Symbol(name.value)\n</code></pre>"},{"location":"python/post/#post.LatexWriter","title":"<code>LatexWriter</code>","text":"<p> Bases: <code>object</code></p> <p>Outputs the compiled average physical quantities LaTeX equations as a Python dictionary.</p> <p>Prints the mapped string representation of the dictionary directly to stdout.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class LatexWriter(object):\n \"\"\"Outputs the compiled average physical quantities LaTeX equations as a Python dictionary.\n\n Prints the mapped string representation of the dictionary directly to stdout.\n \"\"\"\n\n def write(self, ctx):\n \"\"\"Writes the LaTeX equation definitions dictionary to standard output.\n\n Args:\n ctx (CompilationContext): The compiled context.\n \"\"\"\n latex_lines = [\"{\"]\n for avg in ctx.averaged.values():\n latex_lines.append(' \"{}\" : r\"${}$\",'.format(avg.name, avg.latex))\n latex_lines.append(\"}\")\n print(\"\\n\".join(latex_lines))\n</code></pre>"},{"location":"python/post/#post.LatexWriter.write","title":"<code>write(ctx)</code>","text":"<p>Writes the LaTeX equation definitions dictionary to standard output.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>The compiled context.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def write(self, ctx):\n \"\"\"Writes the LaTeX equation definitions dictionary to standard output.\n\n Args:\n ctx (CompilationContext): The compiled context.\n \"\"\"\n latex_lines = [\"{\"]\n for avg in ctx.averaged.values():\n latex_lines.append(' \"{}\" : r\"${}$\",'.format(avg.name, avg.latex))\n latex_lines.append(\"}\")\n print(\"\\n\".join(latex_lines))\n</code></pre>"},{"location":"python/post/#post.ParserStage","title":"<code>ParserStage</code>","text":"<p> Bases: <code>object</code></p> <p>Compiler pipeline Stage 1: Parses DSL specifications and extracts initial definitions.</p> <p>Reads raw DSL specifications and uses Lark parser to build the AST. Populates primary inputs, derived variables, and averaged variable lists.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class ParserStage(object):\n \"\"\"Compiler pipeline Stage 1: Parses DSL specifications and extracts initial definitions.\n\n Reads raw DSL specifications and uses Lark parser to build the AST.\n Populates primary inputs, derived variables, and averaged variable lists.\n \"\"\"\n\n def __init__(self):\n \"\"\"Initializes ParserStage with calc_grammar.\"\"\"\n self.parser = Lark(calc_grammar,\n parser='lalr',\n lexer_callbacks={\n 'ESCAPED_STRING': tok_to_str,\n 'INT': tok_to_int,\n 'BOOL': tok_to_bool\n })\n\n def execute(self, terms_raw, ctx):\n \"\"\"Executes Stage 1 parser.\n\n Args:\n terms_raw (str): Raw DSL term specification string.\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n tree = self.parser.parse(terms_raw)\n CollectDefinitions(ctx.primary, ctx.derived, ctx.averaged).visit(tree)\n</code></pre>"},{"location":"python/post/#post.ParserStage.__init__","title":"<code>__init__()</code>","text":"<p>Initializes ParserStage with calc_grammar.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self):\n \"\"\"Initializes ParserStage with calc_grammar.\"\"\"\n self.parser = Lark(calc_grammar,\n parser='lalr',\n lexer_callbacks={\n 'ESCAPED_STRING': tok_to_str,\n 'INT': tok_to_int,\n 'BOOL': tok_to_bool\n })\n</code></pre>"},{"location":"python/post/#post.ParserStage.execute","title":"<code>execute(terms_raw, ctx)</code>","text":"<p>Executes Stage 1 parser.</p> <p>Parameters:</p> Name Type Description Default <code>terms_raw</code> <code>str</code> <p>Raw DSL term specification string.</p> required <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def execute(self, terms_raw, ctx):\n \"\"\"Executes Stage 1 parser.\n\n Args:\n terms_raw (str): Raw DSL term specification string.\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n tree = self.parser.parse(terms_raw)\n CollectDefinitions(ctx.primary, ctx.derived, ctx.averaged).visit(tree)\n</code></pre>"},{"location":"python/post/#post.PrimaryField","title":"<code>PrimaryField</code>","text":"<p> Bases: <code>FieldBase</code></p> <p>\uaca9\uc790 \uc815\ubcf4\ub098 \uc678\ubd80 \ubb3c\ub9ac\uacc4 \uc218\uce58 \ub370\uc774\ud130(u, v, w, T \ub4f1) \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc804\uc5d0 \ub85c\ub4dc\ud558\uc5ec \uba54\ubaa8\ub9ac\uc5d0 \uc0c1\uc8fc\ud558\ub294 \uae30\ubcf8 \uc6d0\ubcf8 \uc785\ub825 \ud544\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. \uc790\uccb4 \uacc4\uc0b0 \ub8e8\ud504\ub098 \ub3d9\uc801 \ud560\ub2f9 \ucf54\ub4dc\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class PrimaryField(FieldBase):\n \"\"\"\uaca9\uc790 \uc815\ubcf4\ub098 \uc678\ubd80 \ubb3c\ub9ac\uacc4 \uc218\uce58 \ub370\uc774\ud130(u, v, w, T \ub4f1) \ud30c\uc77c\uc5d0\uc11c \uc0ac\uc804\uc5d0 \ub85c\ub4dc\ud558\uc5ec \n \uba54\ubaa8\ub9ac\uc5d0 \uc0c1\uc8fc\ud558\ub294 \uae30\ubcf8 \uc6d0\ubcf8 \uc785\ub825 \ud544\ub4dc \ud074\ub798\uc2a4\uc785\ub2c8\ub2e4. \n \uc790\uccb4 \uacc4\uc0b0 \ub8e8\ud504\ub098 \ub3d9\uc801 \ud560\ub2f9 \ucf54\ub4dc\ub97c \uc9c1\uc811 \uc0dd\uc131\ud558\uc9c0 \uc54a\uc2b5\ub2c8\ub2e4.\n \"\"\"\n\n def __init__(self, name, fdict):\n \"\"\"Initializes PrimaryField.\n\n Args:\n name (str): Input field name.\n fdict (dict): Variable registry dictionary.\n \"\"\"\n super(PrimaryField, self).__init__(name, fdict)\n self.derivs = set([])\n self.prime = True\n self.latex = name\n self.latex_given = None\n</code></pre>"},{"location":"python/post/#post.PrimaryField.__init__","title":"<code>__init__(name, fdict)</code>","text":"<p>Initializes PrimaryField.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Input field name.</p> required <code>fdict</code> <code>dict</code> <p>Variable registry dictionary.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, name, fdict):\n \"\"\"Initializes PrimaryField.\n\n Args:\n name (str): Input field name.\n fdict (dict): Variable registry dictionary.\n \"\"\"\n super(PrimaryField, self).__init__(name, fdict)\n self.derivs = set([])\n self.prime = True\n self.latex = name\n self.latex_given = None\n</code></pre>"},{"location":"python/post/#post.ReportWriter","title":"<code>ReportWriter</code>","text":"<p> Bases: <code>object</code></p> <p>Outputs a compilation analysis summary in JSON format.</p> <p>Creates <code>ir2.py</code> containing topological sort order and graph relationships to verify pipeline execution properties.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class ReportWriter(object):\n \"\"\"Outputs a compilation analysis summary in JSON format.\n\n Creates `ir2.py` containing topological sort order and graph relationships\n to verify pipeline execution properties.\n \"\"\"\n\n def write(self, ctx):\n \"\"\"Writes the IR details to `ir2.py`.\n\n Args:\n ctx (CompilationContext): The compiled context.\n \"\"\"\n import json\n dg = {k:list(v) for k,v in ctx.dependency.items()}\n\n with open(\"ir2.py\", \"w\") as irf:\n print(\"g = \", json.dumps(dg, indent=4), file=irf)\n print(\"l1 = \", json.dumps(ctx.pass1, indent=4), file=irf)\n print(\"l2 = \", json.dumps(ctx.pass2, indent=4), file=irf)\n print(\"avg1 = \", json.dumps(list(map(repr, ctx.avg1)), indent=4), file=irf)\n print(\"avg2 = \", json.dumps(list(map(repr, ctx.avg2)), indent=4), file=irf)\n</code></pre>"},{"location":"python/post/#post.ReportWriter.write","title":"<code>write(ctx)</code>","text":"<p>Writes the IR details to <code>ir2.py</code>.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>The compiled context.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def write(self, ctx):\n \"\"\"Writes the IR details to `ir2.py`.\n\n Args:\n ctx (CompilationContext): The compiled context.\n \"\"\"\n import json\n dg = {k:list(v) for k,v in ctx.dependency.items()}\n\n with open(\"ir2.py\", \"w\") as irf:\n print(\"g = \", json.dumps(dg, indent=4), file=irf)\n print(\"l1 = \", json.dumps(ctx.pass1, indent=4), file=irf)\n print(\"l2 = \", json.dumps(ctx.pass2, indent=4), file=irf)\n print(\"avg1 = \", json.dumps(list(map(repr, ctx.avg1)), indent=4), file=irf)\n print(\"avg2 = \", json.dumps(list(map(repr, ctx.avg2)), indent=4), file=irf)\n</code></pre>"},{"location":"python/post/#post.SympyOptimizationStage","title":"<code>SympyOptimizationStage</code>","text":"<p> Bases: <code>object</code></p> <p>Compiler pipeline Stage 5: Performs liveness analysis and memory buffer sharing.</p> <p>This stage runs liveness window analysis to map multiple non-overlapping temporary variables to a limited set of shared XYZ buffers (array pooling) to prevent RAM exhaustion.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class SympyOptimizationStage(object):\n \"\"\"Compiler pipeline Stage 5: Performs liveness analysis and memory buffer sharing.\n\n This stage runs liveness window analysis to map multiple non-overlapping temporary\n variables to a limited set of shared XYZ buffers (array pooling) to prevent RAM exhaustion.\n \"\"\"\n\n def execute(self, ctx):\n \"\"\"Executes Stage 5 array buffer sharing based on topologically sorted lists.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n self.array_name = \"xyzbuffer{}\"\n\n # 1. Pass 1 \ubc0f Pass 2 \uc5f0\uc0b0 \uc21c\uc11c \ubc30\uc5f4\ub4e4\uc5d0 \ub300\ud574 \uac01\uac01 \ubc84\ud37c \uacf5\uc720 \ub9e4\ud551(Pooling) \uc218\ud589\n narr1, alloc1 = (self.allocate_arr(ctx, ctx.pass1))\n narr2, alloc2 = (self.allocate_arr(ctx, ctx.pass2))\n\n # \uc804\uccb4 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ud544\uc694\ud55c \ub3d9\uc801 \uacf5\uc720 3D \ubc84\ud37c \ubc30\uc5f4\uc758 \ucd5c\ub300 \ud06c\uae30 \uc124\uc815\n ctx.narr = max(narr1, narr2)\n\n ctx.alloc1 = alloc1\n ctx.alloc2 = alloc2\n\n def liveness(self, ctx, l1, g):\n \"\"\"Analyzes variable lifetimes to identify overlap intervals.\n\n Constructs a liveness matrix where matrix[i, j] is True if variable i\n is still live (in memory) at step j.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n l1 (list): Topologically sorted variable names.\n g (dict): Graph mapping variable names to dependency sets.\n\n Returns:\n np.ndarray: Boolean liveness matrix of shape (len(l1), len(l1)).\n \"\"\"\n import numpy as np\n img = np.zeros((len(l1), len(l1)))\n for i, v in enumerate(l1):\n for j in range(i, len(l1)):\n img[i,i:j+1] = img[i,i:j+1] + (1 if v in g[l1[j]] else 0)\n return img &gt; 0\n\n def allocate_arr(self, ctx, l):\n \"\"\"Performs liveness-based memory buffer pooling.\n\n Assigns variables with disjoint active lifetimes to share the same\n allocated `xyzbufferN` 3D arrays.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n l (list): Topologically sorted list of variable names.\n\n Returns:\n tuple: (max_buffers_needed, var_to_buffer_mapping) where:\n max_buffers_needed (int): Maximum buffers required concurrently.\n var_to_buffer_mapping (dict): Map of variable names to their pooled buffer arrays.\n \"\"\"\n import numpy as np\n dg = ctx.dependency\n mask = self.liveness(ctx, l, dg)\n try:\n narr = mask.astype(int).sum(axis=0).max()\n except ValueError:\n narr = 0\n\n array_pool = set([self.array_name.format(i) for i in range(narr)])\n livesets = [set([])] + [set(np.asarray(l)[row]) for row in mask.T]\n var2arr = { p : p for p in ctx.primary }\n\n for i, (s0, s1) in enumerate(zip(livesets[:-1], livesets[1:])):\n array_pool.update(map(var2arr.get, s0 - s1))\n for new in s1 - s0:\n var2arr[new] = array_pool.pop()\n\n return narr, var2arr\n</code></pre>"},{"location":"python/post/#post.SympyOptimizationStage.allocate_arr","title":"<code>allocate_arr(ctx, l)</code>","text":"<p>Performs liveness-based memory buffer pooling.</p> <p>Assigns variables with disjoint active lifetimes to share the same allocated <code>xyzbufferN</code> 3D arrays.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context.</p> required <code>l</code> <code>list</code> <p>Topologically sorted list of variable names.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p>(max_buffers_needed, var_to_buffer_mapping) where: max_buffers_needed (int): Maximum buffers required concurrently. var_to_buffer_mapping (dict): Map of variable names to their pooled buffer arrays.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def allocate_arr(self, ctx, l):\n \"\"\"Performs liveness-based memory buffer pooling.\n\n Assigns variables with disjoint active lifetimes to share the same\n allocated `xyzbufferN` 3D arrays.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n l (list): Topologically sorted list of variable names.\n\n Returns:\n tuple: (max_buffers_needed, var_to_buffer_mapping) where:\n max_buffers_needed (int): Maximum buffers required concurrently.\n var_to_buffer_mapping (dict): Map of variable names to their pooled buffer arrays.\n \"\"\"\n import numpy as np\n dg = ctx.dependency\n mask = self.liveness(ctx, l, dg)\n try:\n narr = mask.astype(int).sum(axis=0).max()\n except ValueError:\n narr = 0\n\n array_pool = set([self.array_name.format(i) for i in range(narr)])\n livesets = [set([])] + [set(np.asarray(l)[row]) for row in mask.T]\n var2arr = { p : p for p in ctx.primary }\n\n for i, (s0, s1) in enumerate(zip(livesets[:-1], livesets[1:])):\n array_pool.update(map(var2arr.get, s0 - s1))\n for new in s1 - s0:\n var2arr[new] = array_pool.pop()\n\n return narr, var2arr\n</code></pre>"},{"location":"python/post/#post.SympyOptimizationStage.execute","title":"<code>execute(ctx)</code>","text":"<p>Executes Stage 5 array buffer sharing based on topologically sorted lists.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def execute(self, ctx):\n \"\"\"Executes Stage 5 array buffer sharing based on topologically sorted lists.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n \"\"\"\n self.array_name = \"xyzbuffer{}\"\n\n # 1. Pass 1 \ubc0f Pass 2 \uc5f0\uc0b0 \uc21c\uc11c \ubc30\uc5f4\ub4e4\uc5d0 \ub300\ud574 \uac01\uac01 \ubc84\ud37c \uacf5\uc720 \ub9e4\ud551(Pooling) \uc218\ud589\n narr1, alloc1 = (self.allocate_arr(ctx, ctx.pass1))\n narr2, alloc2 = (self.allocate_arr(ctx, ctx.pass2))\n\n # \uc804\uccb4 \ud504\ub85c\uadf8\ub7a8\uc5d0\uc11c \ud544\uc694\ud55c \ub3d9\uc801 \uacf5\uc720 3D \ubc84\ud37c \ubc30\uc5f4\uc758 \ucd5c\ub300 \ud06c\uae30 \uc124\uc815\n ctx.narr = max(narr1, narr2)\n\n ctx.alloc1 = alloc1\n ctx.alloc2 = alloc2\n</code></pre>"},{"location":"python/post/#post.SympyOptimizationStage.liveness","title":"<code>liveness(ctx, l1, g)</code>","text":"<p>Analyzes variable lifetimes to identify overlap intervals.</p> <p>Constructs a liveness matrix where matrix[i, j] is True if variable i is still live (in memory) at step j.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context.</p> required <code>l1</code> <code>list</code> <p>Topologically sorted variable names.</p> required <code>g</code> <code>dict</code> <p>Graph mapping variable names to dependency sets.</p> required <p>Returns:</p> Type Description <p>np.ndarray: Boolean liveness matrix of shape (len(l1), len(l1)).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def liveness(self, ctx, l1, g):\n \"\"\"Analyzes variable lifetimes to identify overlap intervals.\n\n Constructs a liveness matrix where matrix[i, j] is True if variable i\n is still live (in memory) at step j.\n\n Args:\n ctx (CompilationContext): Active compilation context.\n l1 (list): Topologically sorted variable names.\n g (dict): Graph mapping variable names to dependency sets.\n\n Returns:\n np.ndarray: Boolean liveness matrix of shape (len(l1), len(l1)).\n \"\"\"\n import numpy as np\n img = np.zeros((len(l1), len(l1)))\n for i, v in enumerate(l1):\n for j in range(i, len(l1)):\n img[i,i:j+1] = img[i,i:j+1] + (1 if v in g[l1[j]] else 0)\n return img &gt; 0\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer","title":"<code>SympyOptimizer</code>","text":"<p>Manages algebra optimization and Common Subexpression Elimination (CSE) via SymPy.</p> <p>This optimization engine: 1. Expands intermediate temporary variables recursively. 2. Simplifies arithmetic terms (fraction cancellation, trigonometric expansions). 3. Runs CSE to pull duplicate sub-operations out into loop local scalar variables, significantly reducing FLOPS and memory bandwidth requirements.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class SympyOptimizer:\n \"\"\"Manages algebra optimization and Common Subexpression Elimination (CSE) via SymPy.\n\n This optimization engine:\n 1. Expands intermediate temporary variables recursively.\n 2. Simplifies arithmetic terms (fraction cancellation, trigonometric expansions).\n 3. Runs CSE to pull duplicate sub-operations out into loop local scalar variables,\n significantly reducing FLOPS and memory bandwidth requirements.\n \"\"\"\n _instance = None\n\n @classmethod\n def get_instance(cls, fdict):\n \"\"\"Retrieves or instantiates the singleton optimizer.\n\n Args:\n fdict (dict): Current variable field registry mapping name -&gt; FieldBase object.\n\n Returns:\n SympyOptimizer: The active singleton instance.\n \"\"\"\n if cls._instance is None or cls._instance.fdict is not fdict:\n cls._instance = cls(fdict)\n return cls._instance\n\n def __init__(self, fdict):\n \"\"\"Initializes SympyOptimizer registry caches.\n\n Args:\n fdict (dict): Variable field registry.\n \"\"\"\n self.fdict = fdict\n self.sympy_cache = {}\n self.exported_fields = set(\n name for name, f in fdict.items()\n if hasattr(f, 'attr') and f.attr.get('export')\n )\n self.averaged_targets = set()\n self.avg_names = set()\n\n def set_averaged(self, averaged_dict):\n \"\"\"Sets the targets and names of averaged variables.\n\n Args:\n averaged_dict (dict): Dictionary mapping average variable names to AveragedField objects.\n \"\"\"\n self.averaged_targets = {a.target for a in averaged_dict.values()}\n self.avg_names = set(averaged_dict.keys())\n\n def get_sympy_expr(self, name):\n \"\"\"Recursively builds and caches a fully substituted SymPy Expression for a variable.\n\n Avoids expanding boundary fields (PrimaryField, DerivedField representing spatial derivatives,\n AveragedField, and FluctuationField) to preserve the grid boundaries. Expands other temporary variables.\n\n Args:\n name (str): Variable name.\n\n Returns:\n sympy.Expr: SymPy node representing the fully-expanded mathematical expression.\n \"\"\"\n if name in self.sympy_cache:\n return self.sympy_cache[name]\n\n field = self.fdict[name]\n\n if hasattr(field, 'prime') and field.prime:\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n if hasattr(field, 'op'): # DerivedField (ddx, etc.)\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n if hasattr(field, 'weighted'): # AveragedField\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n if hasattr(field, 'field') and hasattr(field, 'w'): # FluctuationField\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n transformer = LarkToSympy(self.fdict)\n expr = transformer.transform(field.exp)\n\n # Recursively substitute intermediate variables\n expanded_expr = expr\n changed = True\n while changed:\n changed = False\n free_syms = list(expanded_expr.free_symbols)\n sub_dict = {}\n for sym in free_syms:\n sym_name = sym.name\n if sym_name in self.fdict:\n f = self.fdict[sym_name]\n is_derived_field = hasattr(f, 'op')\n is_averaged_field = hasattr(f, 'weighted')\n is_primary_field = hasattr(f, 'prime') and f.prime\n is_exported = sym_name in self.exported_fields\n is_averaged_target = sym_name in self.averaged_targets\n\n if not (is_derived_field or is_averaged_field or is_primary_field or is_exported or is_averaged_target):\n sub_dict[sym] = self.get_sympy_expr(sym_name)\n changed = True\n\n if sub_dict:\n expanded_expr = expanded_expr.subs(sub_dict)\n\n self.sympy_cache[name] = expanded_expr\n return expanded_expr\n\n def calculate_flops_and_heavy(self, expr):\n \"\"\"Measures computational cost (FLOPS and heavy operators) for a SymPy expression.\n\n Useful for logging optimization statistics.\n\n Args:\n expr (sympy.Expr): The expression to evaluate.\n\n Returns:\n tuple: (flops_count, heavy_operators_count).\n \"\"\"\n flops = 0\n heavy = 0\n for node in sympy.preorder_traversal(expr):\n if isinstance(node, sympy.Add):\n flops += len(node.args) - 1\n elif isinstance(node, sympy.Mul):\n flops += len(node.args) - 1\n elif isinstance(node, sympy.Pow):\n base, exp = node.args\n if exp == 0.5 or exp == -0.5:\n flops += 10 # Square root/inv square root weight\n heavy += 1\n elif exp == -1:\n flops += 4 # Division weight\n heavy += 1\n elif isinstance(exp, sympy.Integer):\n val = abs(int(exp))\n if val &gt; 1:\n flops += val - 1\n else:\n flops += 10\n heavy += 1\n elif isinstance(node, (sympy.Derivative, sympy.Function)):\n name = node.func.__name__\n if name == 'sqrt':\n flops += 10\n heavy += 1\n elif name in ('exp', 'log', 'sin', 'cos', 'tan', 'rxn_rate'):\n flops += 10\n heavy += 1\n elif name == 'Abs':\n flops += 1\n else:\n flops += 10\n heavy += 1\n return flops, heavy\n\n def count_3d_loads(self, expr, three_d_arrays):\n \"\"\"Counts the total 3D array memory read accesses in the expression.\n\n Args:\n expr (sympy.Expr): The expression to analyze.\n three_d_arrays (set): Names of active 3D arrays.\n\n Returns:\n int: The memory load count.\n \"\"\"\n count = 0\n for node in sympy.preorder_traversal(expr):\n if isinstance(node, sympy.Symbol) and node.name in three_d_arrays:\n count += 1\n return count\n\n def optimize_field(self, name, alloc=None):\n \"\"\"Optimizes a physical field expression and extracts Common Subexpressions.\n\n Applies SymPy simplification and CSE, printing optimization reports to stderr.\n\n Args:\n name (str): The name of the field to optimize.\n alloc (dict, optional): Buffer allocation mapping. Defaults to None.\n\n Returns:\n tuple: (rhs_code, cse_declarations, cse_assignments) where:\n rhs_code (str): The final right hand side Fortran expression.\n cse_declarations (list of str): Code strings to declare local CSE scalars.\n cse_assignments (list of str): Code strings to calculate CSE values.\n \"\"\"\n expr = self.get_sympy_expr(name)\n\n three_d_arrays = {\n k for k, v in self.fdict.items()\n if hasattr(v, 'dim') and v.dim == ':,:,:'\n }\n\n # Optimization metrics before\n before_flops, before_heavy = self.calculate_flops_and_heavy(expr)\n before_loads = self.count_3d_loads(expr, three_d_arrays)\n\n # Simplify expression\n simplified_expr = sympy.simplify(expr)\n simplified_expr = sympy.cancel(simplified_expr)\n\n array_symbols = {}\n for k, v in self.fdict.items():\n if hasattr(v, 'array') and v.array:\n array_symbols[k] = v.array\n elif alloc and k in alloc:\n array_symbols[k] = alloc[k]\n else:\n array_symbols[k] = k\n\n avg_symbols = {k: k for k in getattr(self, 'avg_names', [])}\n printer = ArrayFCodePrinter(array_symbols=array_symbols, avg_symbols=avg_symbols)\n\n # Perform Common Subexpression Elimination\n replacements, reduced_exprs = sympy.cse(simplified_expr)\n reduced_expr = reduced_exprs[0]\n\n # Optimization metrics after\n after_flops = 0\n after_heavy = 0\n after_loads = 0\n\n for temp_var, temp_expr in replacements:\n f_val, h_val = self.calculate_flops_and_heavy(temp_expr)\n after_flops += f_val\n after_heavy += h_val\n after_loads += self.count_3d_loads(temp_expr, three_d_arrays)\n\n f_val, h_val = self.calculate_flops_and_heavy(reduced_expr)\n after_flops += f_val\n after_heavy += h_val\n after_loads += self.count_3d_loads(reduced_expr, three_d_arrays)\n\n def pct_str(before, after):\n if before == 0:\n return \"0.0%\" if after == 0 else \"+inf%\"\n diff = after - before\n pct = (diff / before) * 100\n return f\"{pct:+.1f}%\"\n\n flops_pct = pct_str(before_flops, after_flops)\n heavy_pct = pct_str(before_heavy, after_heavy)\n loads_pct = pct_str(before_loads, after_loads)\n\n if after_flops &lt; before_flops * 0.5 or after_loads &lt; before_loads * 0.5:\n est_speedup = \"Highly significant\"\n elif after_flops &lt; before_flops or after_loads &lt; before_loads:\n est_speedup = \"Moderate\"\n else:\n est_speedup = \"Minimal / Already optimal\"\n\n sys.stderr.write(f\"\\n[SymPy Optimizer Report: {name}]\\n\")\n sys.stderr.write(f\"- Floating Point Ops : {before_flops} -&gt; {after_flops} ({flops_pct})\\n\")\n sys.stderr.write(f\"- Heavy Ops (Div/Sqrt): {before_heavy} -&gt; {after_heavy} ({heavy_pct})\\n\")\n sys.stderr.write(f\"- 3D Array Mem Reads : {before_loads} -&gt; {after_loads} ({loads_pct})\\n\")\n sys.stderr.write(f\"=&gt; Estimated Speedup in loop: {est_speedup}\\n\\n\")\n\n cse_decls = []\n cse_assigns = []\n\n if replacements:\n for temp_var, temp_expr in replacements:\n cse_decls.append(f\"real(real64) :: {temp_var}\")\n cse_assigns.append(f\"{temp_var} = {printer.doprint(temp_expr)}\")\n\n rhs = printer.doprint(reduced_expr)\n\n return rhs, cse_decls, cse_assigns\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.__init__","title":"<code>__init__(fdict)</code>","text":"<p>Initializes SympyOptimizer registry caches.</p> <p>Parameters:</p> Name Type Description Default <code>fdict</code> <code>dict</code> <p>Variable field registry.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def __init__(self, fdict):\n \"\"\"Initializes SympyOptimizer registry caches.\n\n Args:\n fdict (dict): Variable field registry.\n \"\"\"\n self.fdict = fdict\n self.sympy_cache = {}\n self.exported_fields = set(\n name for name, f in fdict.items()\n if hasattr(f, 'attr') and f.attr.get('export')\n )\n self.averaged_targets = set()\n self.avg_names = set()\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.calculate_flops_and_heavy","title":"<code>calculate_flops_and_heavy(expr)</code>","text":"<p>Measures computational cost (FLOPS and heavy operators) for a SymPy expression.</p> <p>Useful for logging optimization statistics.</p> <p>Parameters:</p> Name Type Description Default <code>expr</code> <code>Expr</code> <p>The expression to evaluate.</p> required <p>Returns:</p> Name Type Description <code>tuple</code> <p>(flops_count, heavy_operators_count).</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def calculate_flops_and_heavy(self, expr):\n \"\"\"Measures computational cost (FLOPS and heavy operators) for a SymPy expression.\n\n Useful for logging optimization statistics.\n\n Args:\n expr (sympy.Expr): The expression to evaluate.\n\n Returns:\n tuple: (flops_count, heavy_operators_count).\n \"\"\"\n flops = 0\n heavy = 0\n for node in sympy.preorder_traversal(expr):\n if isinstance(node, sympy.Add):\n flops += len(node.args) - 1\n elif isinstance(node, sympy.Mul):\n flops += len(node.args) - 1\n elif isinstance(node, sympy.Pow):\n base, exp = node.args\n if exp == 0.5 or exp == -0.5:\n flops += 10 # Square root/inv square root weight\n heavy += 1\n elif exp == -1:\n flops += 4 # Division weight\n heavy += 1\n elif isinstance(exp, sympy.Integer):\n val = abs(int(exp))\n if val &gt; 1:\n flops += val - 1\n else:\n flops += 10\n heavy += 1\n elif isinstance(node, (sympy.Derivative, sympy.Function)):\n name = node.func.__name__\n if name == 'sqrt':\n flops += 10\n heavy += 1\n elif name in ('exp', 'log', 'sin', 'cos', 'tan', 'rxn_rate'):\n flops += 10\n heavy += 1\n elif name == 'Abs':\n flops += 1\n else:\n flops += 10\n heavy += 1\n return flops, heavy\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.count_3d_loads","title":"<code>count_3d_loads(expr, three_d_arrays)</code>","text":"<p>Counts the total 3D array memory read accesses in the expression.</p> <p>Parameters:</p> Name Type Description Default <code>expr</code> <code>Expr</code> <p>The expression to analyze.</p> required <code>three_d_arrays</code> <code>set</code> <p>Names of active 3D arrays.</p> required <p>Returns:</p> Name Type Description <code>int</code> <p>The memory load count.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def count_3d_loads(self, expr, three_d_arrays):\n \"\"\"Counts the total 3D array memory read accesses in the expression.\n\n Args:\n expr (sympy.Expr): The expression to analyze.\n three_d_arrays (set): Names of active 3D arrays.\n\n Returns:\n int: The memory load count.\n \"\"\"\n count = 0\n for node in sympy.preorder_traversal(expr):\n if isinstance(node, sympy.Symbol) and node.name in three_d_arrays:\n count += 1\n return count\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.get_instance","title":"<code>get_instance(fdict)</code> <code>classmethod</code>","text":"<p>Retrieves or instantiates the singleton optimizer.</p> <p>Parameters:</p> Name Type Description Default <code>fdict</code> <code>dict</code> <p>Current variable field registry mapping name -&gt; FieldBase object.</p> required <p>Returns:</p> Name Type Description <code>SympyOptimizer</code> <p>The active singleton instance.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>@classmethod\ndef get_instance(cls, fdict):\n \"\"\"Retrieves or instantiates the singleton optimizer.\n\n Args:\n fdict (dict): Current variable field registry mapping name -&gt; FieldBase object.\n\n Returns:\n SympyOptimizer: The active singleton instance.\n \"\"\"\n if cls._instance is None or cls._instance.fdict is not fdict:\n cls._instance = cls(fdict)\n return cls._instance\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.get_sympy_expr","title":"<code>get_sympy_expr(name)</code>","text":"<p>Recursively builds and caches a fully substituted SymPy Expression for a variable.</p> <p>Avoids expanding boundary fields (PrimaryField, DerivedField representing spatial derivatives, AveragedField, and FluctuationField) to preserve the grid boundaries. Expands other temporary variables.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>Variable name.</p> required <p>Returns:</p> Type Description <p>sympy.Expr: SymPy node representing the fully-expanded mathematical expression.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def get_sympy_expr(self, name):\n \"\"\"Recursively builds and caches a fully substituted SymPy Expression for a variable.\n\n Avoids expanding boundary fields (PrimaryField, DerivedField representing spatial derivatives,\n AveragedField, and FluctuationField) to preserve the grid boundaries. Expands other temporary variables.\n\n Args:\n name (str): Variable name.\n\n Returns:\n sympy.Expr: SymPy node representing the fully-expanded mathematical expression.\n \"\"\"\n if name in self.sympy_cache:\n return self.sympy_cache[name]\n\n field = self.fdict[name]\n\n if hasattr(field, 'prime') and field.prime:\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n if hasattr(field, 'op'): # DerivedField (ddx, etc.)\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n if hasattr(field, 'weighted'): # AveragedField\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n if hasattr(field, 'field') and hasattr(field, 'w'): # FluctuationField\n expr = sympy.Symbol(name)\n self.sympy_cache[name] = expr\n return expr\n\n transformer = LarkToSympy(self.fdict)\n expr = transformer.transform(field.exp)\n\n # Recursively substitute intermediate variables\n expanded_expr = expr\n changed = True\n while changed:\n changed = False\n free_syms = list(expanded_expr.free_symbols)\n sub_dict = {}\n for sym in free_syms:\n sym_name = sym.name\n if sym_name in self.fdict:\n f = self.fdict[sym_name]\n is_derived_field = hasattr(f, 'op')\n is_averaged_field = hasattr(f, 'weighted')\n is_primary_field = hasattr(f, 'prime') and f.prime\n is_exported = sym_name in self.exported_fields\n is_averaged_target = sym_name in self.averaged_targets\n\n if not (is_derived_field or is_averaged_field or is_primary_field or is_exported or is_averaged_target):\n sub_dict[sym] = self.get_sympy_expr(sym_name)\n changed = True\n\n if sub_dict:\n expanded_expr = expanded_expr.subs(sub_dict)\n\n self.sympy_cache[name] = expanded_expr\n return expanded_expr\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.optimize_field","title":"<code>optimize_field(name, alloc=None)</code>","text":"<p>Optimizes a physical field expression and extracts Common Subexpressions.</p> <p>Applies SymPy simplification and CSE, printing optimization reports to stderr.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>The name of the field to optimize.</p> required <code>alloc</code> <code>dict</code> <p>Buffer allocation mapping. Defaults to None.</p> <code>None</code> <p>Returns:</p> Name Type Description <code>tuple</code> <p>(rhs_code, cse_declarations, cse_assignments) where: rhs_code (str): The final right hand side Fortran expression. cse_declarations (list of str): Code strings to declare local CSE scalars. cse_assignments (list of str): Code strings to calculate CSE values.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def optimize_field(self, name, alloc=None):\n \"\"\"Optimizes a physical field expression and extracts Common Subexpressions.\n\n Applies SymPy simplification and CSE, printing optimization reports to stderr.\n\n Args:\n name (str): The name of the field to optimize.\n alloc (dict, optional): Buffer allocation mapping. Defaults to None.\n\n Returns:\n tuple: (rhs_code, cse_declarations, cse_assignments) where:\n rhs_code (str): The final right hand side Fortran expression.\n cse_declarations (list of str): Code strings to declare local CSE scalars.\n cse_assignments (list of str): Code strings to calculate CSE values.\n \"\"\"\n expr = self.get_sympy_expr(name)\n\n three_d_arrays = {\n k for k, v in self.fdict.items()\n if hasattr(v, 'dim') and v.dim == ':,:,:'\n }\n\n # Optimization metrics before\n before_flops, before_heavy = self.calculate_flops_and_heavy(expr)\n before_loads = self.count_3d_loads(expr, three_d_arrays)\n\n # Simplify expression\n simplified_expr = sympy.simplify(expr)\n simplified_expr = sympy.cancel(simplified_expr)\n\n array_symbols = {}\n for k, v in self.fdict.items():\n if hasattr(v, 'array') and v.array:\n array_symbols[k] = v.array\n elif alloc and k in alloc:\n array_symbols[k] = alloc[k]\n else:\n array_symbols[k] = k\n\n avg_symbols = {k: k for k in getattr(self, 'avg_names', [])}\n printer = ArrayFCodePrinter(array_symbols=array_symbols, avg_symbols=avg_symbols)\n\n # Perform Common Subexpression Elimination\n replacements, reduced_exprs = sympy.cse(simplified_expr)\n reduced_expr = reduced_exprs[0]\n\n # Optimization metrics after\n after_flops = 0\n after_heavy = 0\n after_loads = 0\n\n for temp_var, temp_expr in replacements:\n f_val, h_val = self.calculate_flops_and_heavy(temp_expr)\n after_flops += f_val\n after_heavy += h_val\n after_loads += self.count_3d_loads(temp_expr, three_d_arrays)\n\n f_val, h_val = self.calculate_flops_and_heavy(reduced_expr)\n after_flops += f_val\n after_heavy += h_val\n after_loads += self.count_3d_loads(reduced_expr, three_d_arrays)\n\n def pct_str(before, after):\n if before == 0:\n return \"0.0%\" if after == 0 else \"+inf%\"\n diff = after - before\n pct = (diff / before) * 100\n return f\"{pct:+.1f}%\"\n\n flops_pct = pct_str(before_flops, after_flops)\n heavy_pct = pct_str(before_heavy, after_heavy)\n loads_pct = pct_str(before_loads, after_loads)\n\n if after_flops &lt; before_flops * 0.5 or after_loads &lt; before_loads * 0.5:\n est_speedup = \"Highly significant\"\n elif after_flops &lt; before_flops or after_loads &lt; before_loads:\n est_speedup = \"Moderate\"\n else:\n est_speedup = \"Minimal / Already optimal\"\n\n sys.stderr.write(f\"\\n[SymPy Optimizer Report: {name}]\\n\")\n sys.stderr.write(f\"- Floating Point Ops : {before_flops} -&gt; {after_flops} ({flops_pct})\\n\")\n sys.stderr.write(f\"- Heavy Ops (Div/Sqrt): {before_heavy} -&gt; {after_heavy} ({heavy_pct})\\n\")\n sys.stderr.write(f\"- 3D Array Mem Reads : {before_loads} -&gt; {after_loads} ({loads_pct})\\n\")\n sys.stderr.write(f\"=&gt; Estimated Speedup in loop: {est_speedup}\\n\\n\")\n\n cse_decls = []\n cse_assigns = []\n\n if replacements:\n for temp_var, temp_expr in replacements:\n cse_decls.append(f\"real(real64) :: {temp_var}\")\n cse_assigns.append(f\"{temp_var} = {printer.doprint(temp_expr)}\")\n\n rhs = printer.doprint(reduced_expr)\n\n return rhs, cse_decls, cse_assigns\n</code></pre>"},{"location":"python/post/#post.SympyOptimizer.set_averaged","title":"<code>set_averaged(averaged_dict)</code>","text":"<p>Sets the targets and names of averaged variables.</p> <p>Parameters:</p> Name Type Description Default <code>averaged_dict</code> <code>dict</code> <p>Dictionary mapping average variable names to AveragedField objects.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def set_averaged(self, averaged_dict):\n \"\"\"Sets the targets and names of averaged variables.\n\n Args:\n averaged_dict (dict): Dictionary mapping average variable names to AveragedField objects.\n \"\"\"\n self.averaged_targets = {a.target for a in averaged_dict.values()}\n self.avg_names = set(averaged_dict.keys())\n</code></pre>"},{"location":"python/post/#post.SympySimplificationStage","title":"<code>SympySimplificationStage</code>","text":"<p> Bases: <code>object</code></p> <p>Compiler pipeline Stage 3: Expands, simplifies equations and prunes dependencies.</p> <p>This stage: 1. Invokes the SympyOptimizer to substitute and simplify equations. 2. Updates variable dependencies in CompilationContext to reflect optimized equations.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>class SympySimplificationStage(object):\n \"\"\"Compiler pipeline Stage 3: Expands, simplifies equations and prunes dependencies.\n\n This stage:\n 1. Invokes the SympyOptimizer to substitute and simplify equations.\n 2. Updates variable dependencies in CompilationContext to reflect optimized equations.\n \"\"\"\n\n def execute(self, ctx):\n \"\"\"Executes Stage 3 mathematical expression expansion and dependency pruning.\n\n Args:\n ctx (CompilationContext): Active compilation context to update.\n \"\"\"\n # 1. SymPy \uc218\uc2dd \ucd5c\uc801\ud654 \uc5d4\uc9c4 \ucd08\uae30\ud654\n opt = SympyOptimizer.get_instance(ctx.derived)\n opt.set_averaged(ctx.averaged)\n\n # 2. SymPy\uac00 \ub300\uc785\uc2dd \uce58\ud658(Substitution) \uacfc\uc815\uc5d0\uc11c \uc81c\uac70\ud55c \ubd88\ud544\uc694\ud55c \uc758\uc874\uc131 \uad00\uacc4\ub97c \n # \uc758\uc874\uc131 \uadf8\ub798\ud504\uc5d0 \uc989\uac01 \ubc18\uc601\ud558\uc5ec \uc2e4\uc81c \uacc4\uc0b0\uc744 \uc704\ud55c \uc758\uc874\uc131 \uccb4\uc778\uc744 \uc2ac\ub9bc\ud558\uac8c \uc815\ub9ac\ud569\ub2c8\ub2e4.\n updated_dependency = {}\n for name, dep_set in ctx.dependency.items():\n if name in ctx.derived and isinstance(ctx.derived[name], Field):\n expr = opt.get_sympy_expr(name)\n # \uc2e4\uc81c \uc815\ub9ac\ub41c SymPy \uc2dd\uc5d0 \uc794\uc874\ud558\ub294 \uc790\uc720 \uae30\ud638 \uba85\uce6d\ub4e4\ub9cc \ucd94\ucd9c\n free_sym_names = {sym.name for sym in expr.free_symbols}\n valid_deps = {dep for dep in free_sym_names if dep in ctx.derived or dep in ctx.primary}\n updated_dependency[name] = valid_deps\n else:\n updated_dependency[name] = dep_set\n ctx.dependency = updated_dependency\n</code></pre>"},{"location":"python/post/#post.SympySimplificationStage.execute","title":"<code>execute(ctx)</code>","text":"<p>Executes Stage 3 mathematical expression expansion and dependency pruning.</p> <p>Parameters:</p> Name Type Description Default <code>ctx</code> <code>CompilationContext</code> <p>Active compilation context to update.</p> required Source code in <code>code/code_gen/post.py</code> <pre><code>def execute(self, ctx):\n \"\"\"Executes Stage 3 mathematical expression expansion and dependency pruning.\n\n Args:\n ctx (CompilationContext): Active compilation context to update.\n \"\"\"\n # 1. SymPy \uc218\uc2dd \ucd5c\uc801\ud654 \uc5d4\uc9c4 \ucd08\uae30\ud654\n opt = SympyOptimizer.get_instance(ctx.derived)\n opt.set_averaged(ctx.averaged)\n\n # 2. SymPy\uac00 \ub300\uc785\uc2dd \uce58\ud658(Substitution) \uacfc\uc815\uc5d0\uc11c \uc81c\uac70\ud55c \ubd88\ud544\uc694\ud55c \uc758\uc874\uc131 \uad00\uacc4\ub97c \n # \uc758\uc874\uc131 \uadf8\ub798\ud504\uc5d0 \uc989\uac01 \ubc18\uc601\ud558\uc5ec \uc2e4\uc81c \uacc4\uc0b0\uc744 \uc704\ud55c \uc758\uc874\uc131 \uccb4\uc778\uc744 \uc2ac\ub9bc\ud558\uac8c \uc815\ub9ac\ud569\ub2c8\ub2e4.\n updated_dependency = {}\n for name, dep_set in ctx.dependency.items():\n if name in ctx.derived and isinstance(ctx.derived[name], Field):\n expr = opt.get_sympy_expr(name)\n # \uc2e4\uc81c \uc815\ub9ac\ub41c SymPy \uc2dd\uc5d0 \uc794\uc874\ud558\ub294 \uc790\uc720 \uae30\ud638 \uba85\uce6d\ub4e4\ub9cc \ucd94\ucd9c\n free_sym_names = {sym.name for sym in expr.free_symbols}\n valid_deps = {dep for dep in free_sym_names if dep in ctx.derived or dep in ctx.primary}\n updated_dependency[name] = valid_deps\n else:\n updated_dependency[name] = dep_set\n ctx.dependency = updated_dependency\n</code></pre>"},{"location":"python/post/#post.make_allocate","title":"<code>make_allocate(name, shape, init_zero=True)</code>","text":"<p>Fortran \ubc30\uc5f4\uc744 \ub3d9\uc801 \ud560\ub2f9\ud558\uace0 \uc608\uc678 \ubc1c\uc0dd \uc2dc \ud504\ub85c\uc138\uc2a4\ub97c \uc548\uc804\ud558\uac8c \ud3ed\ud30c\uc2dc\ud0a4\ub294 \ud560\ub2f9 \ucf54\ub4dc\ub97c \uc791\uc131\ud574 \uc90d\ub2c8\ub2e4.</p> <p>Parameters:</p> Name Type Description Default <code>name</code> <code>str</code> <p>\ud560\ub2f9\ud560 \ubc30\uc5f4\uc758 \uc774\ub984.</p> required <code>shape</code> <code>str</code> <p>\ud560\ub2f9 \ud06c\uae30 \ud615\ud0dc (\uc608: 'nxp,nyp,nzp').</p> required <code>init_zero</code> <code>bool</code> <p>True\uc778 \uacbd\uc6b0 0.0d0\uc73c\ub85c \ucd08\uae30\ud654 \uad6c\ubb38\uc744 \ub367\ubd99\uc785\ub2c8\ub2e4. Defaults to True.</p> <code>True</code> <p>Returns:</p> Name Type Description <code>str</code> <p>Fortran dynamic allocation code block.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def make_allocate(name, shape, init_zero=True):\n \"\"\"Fortran \ubc30\uc5f4\uc744 \ub3d9\uc801 \ud560\ub2f9\ud558\uace0 \uc608\uc678 \ubc1c\uc0dd \uc2dc \ud504\ub85c\uc138\uc2a4\ub97c \uc548\uc804\ud558\uac8c \ud3ed\ud30c\uc2dc\ud0a4\ub294 \ud560\ub2f9 \ucf54\ub4dc\ub97c \uc791\uc131\ud574 \uc90d\ub2c8\ub2e4.\n\n Args:\n name (str): \ud560\ub2f9\ud560 \ubc30\uc5f4\uc758 \uc774\ub984.\n shape (str): \ud560\ub2f9 \ud06c\uae30 \ud615\ud0dc (\uc608: 'nxp,nyp,nzp').\n init_zero (bool, optional): True\uc778 \uacbd\uc6b0 0.0d0\uc73c\ub85c \ucd08\uae30\ud654 \uad6c\ubb38\uc744 \ub367\ubd99\uc785\ub2c8\ub2e4. Defaults to True.\n\n Returns:\n str: Fortran dynamic allocation code block.\n \"\"\"\n alloc_str = f\"allocate({name}({shape}), stat=ierr)\\n\"\n alloc_str += f\"if (ierr /= 0) then\\n\"\n alloc_str += f\" write(0,*) 'Error: allocation of {name} failed on process', myid\\n\"\n alloc_str += f\" call MPI_ABORT(MPI_COMM_TASK, 1, mpi_err)\\n\"\n alloc_str += f\"end if\"\n if init_zero:\n alloc_str += f\"\\n{name} = 0.\"\n return alloc_str\n</code></pre>"},{"location":"python/post/#post.tok_to_bool","title":"<code>tok_to_bool(tok)</code>","text":"<p>Convert the value of <code>tok</code> from string to bool, while maintaining line number &amp; column.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def tok_to_bool(tok):\n \"Convert the value of `tok` from string to bool, while maintaining line number &amp; column.\"\n return Token.new_borrow_pos(tok.type, tok.value == \"true\", tok)\n</code></pre>"},{"location":"python/post/#post.tok_to_int","title":"<code>tok_to_int(tok)</code>","text":"<p>Convert the value of <code>tok</code> from string to int, while maintaining line number &amp; column.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def tok_to_int(tok):\n \"Convert the value of `tok` from string to int, while maintaining line number &amp; column.\"\n return Token.new_borrow_pos(tok.type, int(tok), tok)\n</code></pre>"},{"location":"python/post/#post.tok_to_str","title":"<code>tok_to_str(tok)</code>","text":"<p>Convert the value of <code>tok</code> from string to string, while maintaining line number &amp; column.</p> Source code in <code>code/code_gen/post.py</code> <pre><code>def tok_to_str(tok):\n \"Convert the value of `tok` from string to string, while maintaining line number &amp; column.\"\n return Token.new_borrow_pos(tok.type, tok.value.strip('\"'), tok)\n</code></pre>"}]}