Gyredocs
Depth Practice
API

Gyre/Software Engineering

Code structure

In one minuteA map of the package — which module owns which concept, how data is laid out in memory, and the conventions that the numerical kernels, the solver and the service share.

Written at L2 Practice goes to L3 Mechanics 806 words Markdown

One Python package, src/gyre, in five layers. Numerics (basis, mesh, physics, dg, implicit, linear, functionals) are pure JAX kernels. The discipline (discipline, error, adapt, deform) turns them into “solve, outputs, derivatives”. Cases and execution (cases, runner, io, cli) describe an analysis as data and run it. Delivery (service, agent, client, pipeline) exposes the same execution path over HTTP, MCP and YAML pipelines. Evidence (verify, docsite) produces the verification records and this site. Everything above the discipline calls runner.run_case, so the interfaces cannot drift apart.

Module map#

Module Owns
gyre.basis LGL nodes and weights, derivative and interpolation matrices, SBP operators, pair tables, p-transfer operators (NumPy, set-up time)
gyre.mesh Mesh (global high-order nodes, element→node map, boundary tags), structured-block builder, face connectivity and orientation
gyre.meshgen generators: airfoil_omesh, annulus, bump_channel, flat_plate, sphere_shell (cubed sphere), box, spanwise extrusion
gyre.meshio mesh files: Gmsh MSH reader (2.2 and 4.1, ASCII) and writer (2.2), the NPZ format, validation, inspection, lookup of the file a case names
gyre.physics compressible Euler/Navier–Stokes kernels: variable sets, two-point and interface fluxes (classical and entropy stable), viscous flux, flow parameters
gyre.turbulence negative Spalart–Allmaras closure: model functions, source terms, boundary values, wall distance to curved walls as differentiable foot-point tables, manufactured solutions
gyre.dg Discretization, differentiable geometry, boundary conditions, the residual kernel
gyre.timestep explicit low-storage Runge–Kutta (verification)
gyre.linear flexible GMRES in JAX control flow
gyre.implicit Hierarchy (p-multigrid, block inverses, line factors, forward/transposed solves), SteadySolver
gyre.lines lines of strongly coupled elements of an anisotropic mesh and the colouring used to assemble their coupling blocks (NumPy only)
gyre.functionals surface integration from residual fluxes, force/moment/heat functionals, nodal loads, distributions
gyre.deform inverse-distance-weighted mesh deformation: a stored matrix for small meshes, matrix-free with a hand-written transpose above 2×1072\times10^7 entries
gyre.discipline FlowDiscipline: the MDO contract
gyre.error adjoint-weighted-residual error estimation
gyre.adapt output-driven order selection: uniform p-enrichment until the error estimate of an output meets a tolerance
gyre.mms manufactured solutions with AD-generated forcing
gyre.cases CaseSpec (pydantic), presets, Case
gyre.runner, gyre.io end-to-end execution record; checkpoints, VTK, browser payloads
gyre.identity the one definition of “which code is this”: version, commit, and what makes a tree dirty; stamps results, verification records, pipeline records and the documentation
gyre.service.* API application, job manager, worker, sessions, mesh store, pipeline runs, limits, host validation, response schemas, store
gyre.agent.* MCP server (mounted or standalone proxy)
gyre.client HTTP client and RemoteDiscipline
gyre.pipeline.* pipeline engine and compute tasks
gyre.verify.* verification studies and suite runner
gyre.docsite.* documentation site builder
gyre.integrations.* optional framework adapters (OpenMDAO)

Data layout#

Quantity Shape Notes
state U (nvar, K, n, n[, n]) variables first; n = p + 1 nodes per direction
geometry x (dim, K, n, …) solution nodes
metrics Ja (dim, dim, K, n, …) Ja[a, b] = component b of JaaJ\mathbf a^a
face data (…, K, F, nq) F = 2·dim faces, nq = n^(dim-1) face nodes
neighbour gather plus (K, F, nq) int flat index into a (K·F·nq) face array
block inverses (K, bs, bs) bs = nvar · n^dim

Local face f = 2a + s is the face normal to reference direction a at ξa=−1\xi_a = -1 (s = 0) or +1+1 (s = 1). Face-node arrays keep the remaining reference directions in ascending order; the neighbour’s ordering is reconciled by a permutation encoded in plus.

Neighbours are found topologically: each face is keyed by the sorted global ids of its corner geometry nodes (after mapping periodic images to a common id). The relative orientation of two matching faces — one of two in 2-D, one of eight in 3-D — is found by comparing their geometry node ids under each index symmetry, and the result is stored as three booleans (transpose, flip, flip). The gather index for any polynomial degree is generated from those booleans, so every p-multigrid level reuses one connectivity.

Conventions#

residual(…) returns R\mathbf R with dU/dt=−R\mathrm d\mathbf U/\mathrm dt = -\mathbf R; weak=True returns Rw=(wJ) R\mathbf R_w = (wJ)\,\mathbf R. Solvers, adjoints and error estimates use Rw\mathbf R_w exclusively.

Python-level structure (dimension, degree, boundary kinds, flux names) is fixed when a Discretization is built and never appears inside traced code as data-dependent control flow. Everything numerical — state, geometry, flow parameters, operator tables — is traced.

  • A boundary condition: write a function returning (UL, UR, Ub) and register it in BOUNDARY_CONDITIONS; add it to WALL_KINDS / viscous masks if applicable; add it to the linearisation study’s configurations.
  • A functional: return a Functional from a function of (U, geom, th); build surface quantities with SurfaceOps so they reuse the residual’s fluxes.
  • A mesh generator: produce a geometry lattice and call structured_mesh; add a preset.
  • A pipeline stage: add a task function in gyre.pipeline.tasks and its name to COMPUTE_STAGES.
  • An agent tool: add a REST endpoint first, then a described wrapper in gyre.agent.server.

    ↑ ↓ moveEnter open[ ] change depthResults show section and depth level