API Reference
Pipeline
GridGeneration.GenerateGrid — Function
GenerateGrid(initialGrid, bndInfo, interInfo, M; params=SimParams())
GenerateGrid(blocks::Vector, bndInfo, interInfo, M; params=SimParams(), splitRequests=[])Run the grid generation pipeline on a single-block initialGrid (a [2, Ni, Nj] array) or on a vector of blocks:
- split the block(s) (if
params.useSplitting): a single block atparams.splitLocationswithSplitBlock; multiple blocks withSplitMultiBlockusingsplitRequests([(blockId, [[i_splits...], [j_splits...]]), ...]), which propagates splits across interfaces, - redistribute the block edges according to the metric
Mand rebuild each block with TFI (ifparams.useEdgeSolver), - smooth each block with the elliptic solver (if
params.useSmoothing).
Every stage is optional; a disabled stage passes its input through unchanged.
Returns a NamedTuple (smoothBlocks, blocks, bndInfo, interInfo, finalErrors, finalIterations), which can also be destructured positionally. blocks is the grid before smoothing; when smoothing is disabled smoothBlocks === blocks and finalErrors/finalIterations are empty.
GridGeneration.SimParams — Type
GridGeneration.SimParams
- useSplitting::Bool # whether to use block splitting
- splitLocations::Vector{Vector{Int}} # locations to split the grid, defined using indices of the initial grid
- useEdgeSolver::Bool # whether to use the edge solver on each block after splitting
- boundarySolver::Symbol # :analytic or :numeric, which boundary solver to use
- useSmoothing::Bool # whether to use smoothing on the final grid
- smoothMethod::Symbol # :ellipticSS, which smoothing method to use
- elliptic::EllipticParams # parameters for the elliptic solver if using elliptic smoothing
GridGeneration.EllipticParams — Type
GridGeneration.EllipticParams
- max_iter::Int # maximum number of iterations
- tol::Float64 # tolerance for convergence
- sweep::Symbol # :point (point SOR, default) or :line (alternating ξ/η line Gauss-Seidel with Thomas solves)
- ω::Float64 # relaxation factor (default 0.2 for :point, 0.3 for :line; :line tolerates ω up to ~1.5 when no wall forcing is used)
- useTopWall::Bool # whether to apply forcing on the top wall
- useBottomWall::Bool # whether to apply forcing on the bottom wall
- useLeftWall::Bool # whether to apply forcing on the left wall
- useRightWall::Bool # whether to apply forcing on the right wall
- adecayleft::Float64 # decay parameter for left wall forcing
- bdecayleft::Float64 # decay parameter for left wall forcing
- adecayright::Float64 # decay parameter for right wall forcing
- bdecayright::Float64 # decay parameter for right wall forcing
- adecaytop::Float64 # decay parameter for top wall forcing
- bdecaytop::Float64 # decay parameter for top wall forcing
- adecaybottom::Float64 # decay parameter for bottom wall forcing
- bdecaybottom::Float64 # decay parameter for bottom wall forcing
- verbose::Bool # whether to print convergence information
GridGeneration.SolveAllBlocks — Function
SolveAllBlocks(metric, blocks, bndInfo, interInfo; solver=:analytic)
-> (blocks, bndInfo, interInfo)Redistribute the edge points of every block according to metric(x, y) -> (M11, M22) and rebuild each block with TFI. The optimal number of points in each direction is computed per edge pair and shared across neighbouring blocks so interfaces stay conforming. solver is :analytic or :numeric. Boundary and interface indices are updated to the new block sizes.
GridGeneration.SmoothBlocks — Function
SmoothBlocks(blocks; solver=:ellipticSS, params)Smooth grid blocks using the elliptic PDE solver. params is either a single EllipticParams applied to every block or a vector with one EllipticParams per block.
Returns (smoothBlocks, finalErrors, finalIterations).
Interpolation and splitting
GridGeneration.TFI — Function
TFI(boundary) -> grid2D transfinite interpolation (Coons patch) of a block from its four edges.
boundary = [top, right, bottom, left], each an N×2 array of (x, y) points. All edges run in the positive parameter direction: top and bottom from left to right (N1 points each), left and right from bottom to top (N2 points each), with matching corner points.
Returns a [2, N1, N2] array: grid[1, i, j] and grid[2, i, j] are the x and y coordinates of node (i, j), with i running along bottom/top and j along left/right.
Example
N = 5
top = [range(0, 1, length=N) ones(N)]
right = [ones(N) range(0, 1, length=N)]
bottom = [range(0, 1, length=N) zeros(N)]
left = [zeros(N) range(0, 1, length=N)]
grid = TFI([top, right, bottom, left]) # 2×5×5 uniform grid on the unit squareGridGeneration.SplitMultiBlock — Function
Split multiple blocks with automatic propagation of split constraints across interfaces.
Inputs:
- blocks: Vector of 3D grid arrays
- splitRequests: Vector of tuples (blockId, [[isplits], [jsplits]]) or Dict mapping blockId => [[isplits], [jsplits]]
- bndInfo: Boundary condition dictionary
- interInfo: Interface connectivity dictionary
Returns:
- newBlocks: Vector of split blocks (globally renumbered)
- newBndInfo: Updated boundary information
- newInterInfo: Updated interface information
Grid quality
GridGeneration.ComputeAngleDeviation — Function
ComputeAngleDeviation(blocks) -> (angleDeviations, maxBlockId, maxDeviation, maxI, maxJ)Measure grid orthogonality. For every cell (i, j) of each [2, Ni, Nj] block, compute the angle at its corner node (i, j) between the grid lines towards (i+1, j) and (i, j+1), and return its deviation from 90° in degrees.
angleDeviations[b]is anNi×Njmatrix for blockb(the last row and column, which have no cell, are zero).maxDeviationis the largest deviation over all blocks, found in blockmaxBlockIdat cell(maxI, maxJ).
Degenerate cells (a zero-length edge) are reported as NaN and ignored for the maximum.
Metric utilities
GridGeneration.make_getMetric — Function
make_getMetric(boundary; closed=true,
A_airfoil=1.0, ℓ_airfoil=0.05, p_airfoil=2,
A_origin=1.0, ℓ_origin=0.10, p_origin=2,
floor=1e-4, profile=:rational)Create a closure getMetric(x,y) => (M11, M22) where the scalar field w(x,y) = floor + wairfoil(disttoairfoil) + worigin(disttoorigin) is applied isotropically: M11 = M22 = w.
boundaryis a 2×N polyline for the airfoil (assumed closed by default).A_*set the peak amplitudes.ℓ_*set decay lengths (units = your coordinate units).p_*control tail sharpness for the rational profile.floorprevents degeneracy far away.profile=:rationalor:gauss.
GridGeneration.setup_metric_tree — Function
setup_metric_tree(data) -> (tree, refs)
setup_metric_tree(blocks::Vector{Array{Float64,3}}) -> (tree, refs)Build a KD-tree over the points of a gridded metric field for nearest-neighbour lookup. data is a dictionary with per-block coordinate matrices data["x"] and data["y"]; alternatively pass the blocks directly as [2, Ni, Nj] arrays. refs[k] records the (block, i, j) index of the k-th point in the tree. Use with find_nearest_kd.
GridGeneration.find_nearest_kd — Function
find_nearest_kd(data, tree, refs, xq, yq) -> [M11, M22]Return the diagonal metric components [M11, M22] stored in data["M11"]/data["M22"] at the grid point nearest to (xq, yq). tree and refs come from setup_metric_tree.
Tortuga grid I/O
GridGeneration.setup_turtle_grid_domain — Function
setup_turtle_grid_domain(metricFieldFile, gridFile; metricGridFile=nothing, fix_uneven_interfaces=true)
-> (blocks, bndInfo, interInfo, M)Load the Tortuga grid gridFile with load_turtle_grid and the metric field metricFieldFile with readTurtleFields. Returns the blocks, 1-based boundary/interface information, and a metric function M(x, y) -> [M11, M22] that looks up the metric at the nearest cell centre. The result can be passed straight to GenerateGrid or SolveAllBlocks.
The metric is stored per cell of the grid it was computed on, which need not be gridFile (e.g. when regenerating a grid that was itself produced earlier). That grid is metricGridFile if given; otherwise the grid named in the field file's header, if it exists next to metricFieldFile; otherwise gridFile. Its cell layout must match the field.
GridGeneration.load_turtle_grid — Function
load_turtle_grid(gridFile; fix_uneven_interfaces=true) -> (blocks, bndInfo, interInfo, centers)Read a Tortuga grid file and convert it to the package's conventions: [2, Ni, Nj] blocks (first k-layer), and 1-based boundary/interface information with boundary faces under "faces". Periodic k-direction self-interfaces are dropped. With fix_uneven_interfaces=true, blocks whose interfaces do not span a whole edge are split so every interface is edge-to-edge.
Also returns the cell-centre coordinates centers (before any splitting), which index a metric field read with readTurtleFields.
GridGeneration.ImportTurtleGrid — Function
ImportTurtleGrid(gridfilename::String)Read a Turtle grid file and extract the 2D (first k-layer) node and cell-centre coordinates along with interface and boundary information.
Arguments
gridfilename::String: Path to the grid file.
Returns
(Xno2D, Xcv2D, Xfa, interfaceInfo, bndInfo):
Xno2D: vector of[2, Ni, Nj]node-coordinate blocksXcv2D: vector of[2, Ni-1, Nj-1]cell-centre blocksXfa: face coordinates as read from the fileinterfaceInfo,bndInfo: connectivity with Tortuga's 0-based indices (boundary faces are stored under"faceInfo")
GridGeneration.readTurtleFields — Function
readTurtleFields(filename::String)Reads binary data from a "Turtle" format file, correctly handling row-major data layout for all fields.
This function translates a Python script for reading structured grid data from a custom binary format. It handles file endianness, reads a header, and then iteratively reads different data fields (scalars, vectors, tensors) defined on the grid blocks.
Arguments
filename::String: The path to the turtle file.
Returns
A tuple (data, datatype, gridfile):
data::Dict{String, Any}: A dictionary mapping variable names to their data arrays.datatype::Dict{String, Int}: A dictionary mapping variable names to their type identifiers.gridfile::String: The name of the associated grid file as stored in the header.
Throws an error if the file is not a supported Turtle field file.
GridGeneration.convert_2D_to_3D — Function
convert_2D_to_3D(blocks, bndInfo, interInfo, extrusion_length=0.1, n_layers=2)
-> (mesh3D, bndInfo3D, interInfo3D)Extrude 2D blocks ([2, Ni, Nj] arrays) into n_layers layers spaced extrusion_length apart in z, giving [3, Ni, Nj, n_layers] blocks. Boundary and interface information is converted from the package's 1-based 2D form to Tortuga's 0-based 3D form, and a periodic k-direction self-interface is added for every block. The result can be passed to write_turtle_grid.
GridGeneration.write_turtle_grid — Function
write_turtle_grid(mesh, interfaces, boundaries, filename)Write a 3D multi-block grid to a Tortuga (.grid) file. mesh is a vector of [3, Ni, Nj, Nk] blocks and interfaces/boundaries use Tortuga's 0-based indexing, as returned by convert_2D_to_3D. Boundaries read with ImportTurtleGrid (which stores faces under "faceInfo") can also be written back directly.