API Reference
This page lists the public API exported by BiGSTARS. Most workflows use the DSL macros plus the discretize / solve path:
using BiGSTARS
cache = discretize(prob)
results = solve(cache, k_values; sigma_0=0.02)For lower-level control, assemble matrices with assemble and pass them to EigenSolver.
Public API
BiGSTARS.AssemblyWorkspace — Type
Pre-allocated workspace for in-place assembly. One per thread.
Create with allocate_workspace(cache), reuse across wavenumbers.
BiGSTARS.ConvergenceHistory — Type
ConvergenceHistoryTracks convergence information during eigenvalue computation.
BiGSTARS.DiscretizationCache — Type
Cache of pre-discretized sparse matrix components, separated by k-power.
BiGSTARS.Domain — Type
Domain(; x=FourierTransformed(), y=Fourier(N=60, L=1.0), z=Chebyshev(N=30, lower=0, upper=1))A multi-dimensional domain with named coordinates. Each coordinate is one of:
FourierTransformed()— wavenumber parameter directionFourier(N=..., L=...)— resolved periodic directionChebyshev(N=..., lower=..., upper=...)— resolved non-periodic direction
BiGSTARS.EVP — Type
EVP(domain; variables, eigenvalue)Eigenvalue problem container. Accumulates equations, BCs, parameters, and substitutions before discretization.
Usage:
prob = EVP(domain, variables=[:psi, :b], eigenvalue=:sigma)
prob[:U] = U_field
prob[:E] = 1e-12BiGSTARS.EigenSolver — Type
EigenSolverMain solver object for generalized eigenvalue problems Ax = λBx.
Fields
A::AbstractMatrix: Left-hand side matrixB::AbstractMatrix: Right-hand side matrixconfig::SolverConfig: Solver configurationresults::Union{SolverResults, Nothing}: Latest results (if available)
BiGSTARS.FourierTransformed — Type
Marker type for a Fourier-transformed (wavenumber) direction.
BiGSTARS.SolverConfig — Type
SolverConfigConfiguration parameters for eigenvalue solvers.
Fields
method::Symbol: Solver method (:Arnoldi, :Arpack, :Krylov)σ₀::Float64: Initial shift valuewhich::Symbol: Which eigenvalues to find (:LM, :LR, :SR, etc.)nev::Int: Number of eigenvalues to computemaxiter::Int: Maximum iterationstol::Float64: Convergence tolerancesortby::Symbol: Sort eigenvalues by (:R, :I, :M)n_tries::Int: Number of retry attemptsΔσ₀::Float64: Initial shift incrementincre::Float64: Increment growth factorϵ::Float64: Successive eigenvalue tolerancekrylovdim::Int: Krylov subspace dimension (Krylov method only)
BiGSTARS.SolverResults — Type
SolverResultsContains results from eigenvalue computation.
Fields
eigenvalues::Vector{ComplexF64}: Computed eigenvalueseigenvectors::Matrix{ComplexF64}: Corresponding eigenvectorsconverged::Bool: Whether computation convergedmethod_used::Symbol: Method that produced the resultfinal_shift::Float64: Final shift value usediterations::Int: Total iterationssolve_time::Float64: Wall-clock time for solutionhistory::ConvergenceHistory: Detailed convergence information
BiGSTARS.@bc — Macro
@bc left(psi) = 0
@bc right(dz(psi)) = 0
@bc left(psi) == 0 # == also worksAdd a boundary condition. prob is optional.
BiGSTARS.@compute — Macro
@compute v = -dy(dz(w)) + dx(zeta)Evaluate a DSL expression on the solved eigenvector fields and assign the result. Requires cache, eigvec, and k to be in scope (set via @compute_setup).
cache = discretize(prob)
results = solve(cache, [0.1]; sigma_0=0.02)
@compute_setup cache results[1].eigenvectors[:, 1] 0.1
@compute v = -dy(dz(w)) + dx(zeta)
@compute u = -dx(dz(w)) - dy(zeta)
@compute vort = dx(dx(psi)) + dy(dy(psi))
@compute flux = U * dy(b) - E * D2(zeta)BiGSTARS.@compute_setup — Macro
@compute_setup cache eigvec kSet up the context for @compute. Call once after solving.
@compute_setup cache results[1].eigenvectors[:, 1] 0.1
@compute v = -dy(dz(w)) + dx(zeta)BiGSTARS.@derive — Macro
@derive prob Dh2_v = rhs # Form 1: named operator
@derive prob v where dx(dx(v)) + dy(dy(v)) = rhs # Form 2: inline operatorDefine a derived (auxiliary) variable implicitly. The code computes Op^{-1} and substitutes v = Op^{-1} * rhs_expr into any equation that references v.
Form 1 (Op_var = rhs): The name is split on _ — everything before the last _ is a @substitution name, the part after is the variable. Dh2_v means "Dh2(v) = rhs".
Form 2 (v where lhs_expr = rhs): The operator is defined inline as any expression involving v. No separate @substitution needed.
v is NOT added to the variable list — it's eliminated automatically.
Examples:
# Form 1 (requires @substitution Dh2):
@derive prob Dh2_v = -dy(dz(w)) + dx(zeta)
# Form 2 (inline, no @substitution needed):
@derive prob v where dx(dx(v)) + dy(dy(v)) = -dy(dz(w)) + dx(zeta)
# General operator:
@derive prob v where 3*dz(dz(v)) + alpha*v = dz(w)BiGSTARS.@derive_bc — Macro
@derive_bc v left(v) == 0
@derive_bc v right(dz(v)) == 0
@derive_bc prob v left(v) == 0 # explicit probAdd BCs for a derived variable's inversion. prob is optional.
BiGSTARS.@equation — Macro
@equation sigma * psi == U * dx(psi)
@equation sigma * psi = U * dx(psi) # = also worksAdd an equation LHS = RHS (or LHS == RHS). prob is optional.
BiGSTARS.@substitution — Macro
@substitution Lap(A) = dx(dx(A)) + dz(dz(A))
@substitution prob Lap(A) = dx(dx(A)) + dz(dz(A)) # explicit probDefine a substitution template. prob is optional — uses the active EVP if omitted.
BiGSTARS.allocate_workspace — Method
allocate_workspace(cache) -> AssemblyWorkspaceAllocate a dense (A, B, temp) workspace matching the cache dimensions. Dense because eigenvalue solvers need dense matrices for factorization anyway, and in-place overwrites require fixed memory layout.
BiGSTARS.assemble! — Method
assemble!(ws, cache, k)Assemble A and B into the pre-allocated workspace ws for wavenumber k. Overwrites ws.A and ws.B in-place. Derived-variable terms still allocate while rebuilding their k-dependent inverse operators.
BiGSTARS.assemble — Method
assemble(cache, k) -> (A, B)Assemble the full A and B matrices for a given wavenumber k (allocating). A(k) = Σp k^p * Ap + derived variable contributions with H(k).
BiGSTARS.assemble — Method
assemble(cache; k_x=0.0, k_y=0.0, ...) -> (A, B)Assemble for multiple FourierTransformed directions using keyword wavenumbers. Each keyword name must match a FourierTransformed coordinate name.
# Domain with two FourierTransformed directions:
domain = Domain(x=FourierTransformed(), y=FourierTransformed(), z=Chebyshev(N=30, lower=0, upper=1))
cache = discretize(prob)
A, B = assemble(cache; k_x=1.0, k_y=0.5)BiGSTARS.chebyshev_coefficients — Method
chebyshev_coefficients(f_values) -> Vector{Float64}Compute Chebyshev expansion coefficients from function values at Chebyshev-Gauss-Lobatto points (in the ordering from chebyshev_points, i.e., from x=1 down to x=-1).
Uses the DCT-I (type 1) relation. Given N function values at the CGL points x_j = cos(j*pi/(N-1)), j=0,...,N-1, the Chebyshev coefficients are:
ck = (2 / (N-1)) * sum{j=0}^{N-1} '' f(x_j) * cos(kjpi/(N-1))
where '' means the first and last terms are halved.
The returned vector has length N, where c[k] is the coefficient of T_{k-1}.
BiGSTARS.chebyshev_evaluate — Method
chebyshev_evaluate(c, x) -> Vector{Float64}Evaluate a Chebyshev expansion with coefficients c at points x ∈ [-1, 1]. Uses Clenshaw's algorithm for numerical stability.
BiGSTARS.chebyshev_points — Function
chebyshev_points(N, a=-1.0, b=1.0) -> Vector{Float64}Compute N Chebyshev-Gauss-Lobatto points on the interval [a, b].
On [-1,1]: x_j = cos(j * pi / (N-1)) for j = 0, ..., N-1
These are then linearly mapped to [a, b].
BiGSTARS.compare_methods! — Method
compare_methods!(solver::EigenSolver; methods=[:Arnoldi, :Arpack, :Krylov], verbose=true)Compare multiple methods on the same problem.
Returns
Dict{Symbol, SolverResults}: Results for each method
BiGSTARS.differentiate — Method
differentiate(f, domain, coord; order=1, filter=:none) -> VectorSpectrally differentiate a function given as physical-space values on the grid.
Chebyshev directions: converts to T coefficients, applies the differentiation operator chain D{order-1} * ⋯ * D0, converts the C^(order) result back to physical space. Chebyshev methods do not suffer from Gibbs ringing for smooth non-periodic functions.
Fourier directions: applies (ik)^order in Fourier space. An optional spectral filter can suppress Gibbs ringing from under-resolved gradients:
:none— no filter (default; exact for smooth periodic functions):exp— exponential filterexp(-α(|k|/k_max)^p)with α=36, p=36 (sharp cutoff that preserves well-resolved modes):2/3— 2/3 dealiasing rule (zeros out the top 1/3 of modes)- A
Function— custom filterσ(k, k_max)applied as multiplier
Examples
domain = Domain(z = Chebyshev(N=64, lower=0.0, upper=1.0))
z = gridpoints(domain, :z)
U = @. z^2
dUdz = differentiate(U, domain, :z) # ≈ 2z
d2Udz2 = differentiate(U, domain, :z; order=2) # ≈ 2
domain_y = Domain(y = Fourier(N=64, L=2π))
y = gridpoints(domain_y, :y)
g = sin.(y)
dgdy = differentiate(g, domain_y, :y) # cos(y), no filter
dgdy = differentiate(g, domain_y, :y; filter=:exp) # cos(y), filtered
dgdy = differentiate(g, domain_y, :y; filter=:2/3) # cos(y), dealiasedBiGSTARS.discretize — Method
discretize(prob::EVP) -> DiscretizationCacheValidate the problem, expand substitutions, lower derivatives, separate by k-power, and build sparse matrix components. Returns a cache for fast wavenumber assembly.
BiGSTARS.evaluate_field — Method
evaluate_field(cache, prob, eigvec, k, expr_fn) -> Vector{ComplexF64}Evaluate a general expression on the eigenvector fields.
expr_fn is a function that takes a Dict of variable coefficient vectors and returns the result. Operators from the cache can be applied.
# Manual field computation:
v_coeffs = evaluate_field(cache, prob, eigvec, 0.1) do fields
# fields[:w], fields[:zeta], fields[:b] are coefficient vectors
# Apply operators manually:
D_y = get_diff_operator(prob.domain, :y, 1)
D_z_T = ... # build T-basis z-derivative
return -D_y * D_z_T * fields[:w] + im * 0.1 * fields[:zeta]
endFor derived variables, use reconstruct(cache, prob, eigvec, k, :v) instead.
BiGSTARS.fourier_points — Method
fourier_points(N, L) -> Vector{Float64}Return N equally-spaced points on [0, L), excluding the right endpoint.
BiGSTARS.get_results — Method
get_results(solver::EigenSolver)Extract eigenvalues and eigenvectors from solved system.
Returns
(λ, Χ): Eigenvalues and eigenvectors
Throws
ArgumentError: If solver hasn't been solved or didn't converge
BiGSTARS.meshgrid — Method
meshgrid(domain, dim1, dim2) -> (Matrix, Matrix)Return 2D meshgrid arrays for two resolved dimensions. Convention: dim2 (typically z) varies along rows, dim1 (typically y) along columns. Result matrices are size (Ndim2, Ndim1) — z-fastest, matching state vector ordering.
Y, Z = meshgrid(domain, :y, :z)
U = @. Z - 0.5 + 0.1 * sin(2π * Y) # 2D field, N_z × N_y
prob[:U] = vec(U) # flatten for DSLBiGSTARS.print_evals — Method
print_evals(λs::AbstractVector{<:Number}; n::Int=length(λs), by::Symbol=:abs)Pretty-print the top n eigenvalues from the list λs, optionally sorted by :real, :imag, or :abs.
BiGSTARS.print_summary — Method
print_summary(solver::EigenSolver)Print a summary of solver results.
BiGSTARS.reconstruct — Method
reconstruct(cache, prob, eigvec, k, field_name::Symbol) -> Vector{ComplexF64}Reconstruct a derived variable's coefficient vector from an eigenvector.
Given the solved eigenvector eigvec (containing coefficients for all declared variables) and wavenumber k, computes the derived field using its stored operator inverse: v = H(k) * rhs(eigvec).
cache = discretize(prob)
results = solve(cache, [0.1]; sigma_0=0.02)
eigvec = results[1].eigenvectors[:, 1]
# Reconstruct derived variables:
v_coeffs = reconstruct(cache, prob, eigvec, 0.1, :v)
u_coeffs = reconstruct(cache, prob, eigvec, 0.1, :u)BiGSTARS.reconstruct_all — Method
reconstruct_all(cache, prob, eigvec, k) -> Dict{Symbol, Vector{ComplexF64}}Reconstruct ALL fields (declared variables + derived variables) from an eigenvector.
fields = reconstruct_all(cache, prob, eigvec, 0.1)
# fields[:w], fields[:zeta], fields[:b] — from eigenvector
# fields[:v], fields[:u] — reconstructed from @derive definitionsBiGSTARS.remove_evals — Method
Accept Symbol for remove_evals as well (convenience).
BiGSTARS.solve — Function
solve(cache, k_values; sigma_0, method=:Krylov, parallel=false, kwargs...)Solve the eigenvalue problem for each wavenumber in k_values. Returns a Vector{SolverResults}.
Uses in-place assembly to reuse the main dense matrix workspace. When parallel=true, one pre-allocated workspace per thread is created. Problems with derived variables still allocate per wavenumber while rebuilding H(k).
Keyword arguments
sigma_0::Float64— initial shift for the eigenvalue solver (required)method::Symbol— solver method::Krylov(default),:Arnoldi, or:Arpackparallel::Bool— iftrue, solve wavenumbers in parallel usingThreads.@threads. Start Julia with multiple threads (julia -t auto) to benefit from this.verbose::Bool— print solver progress (defaultfalse)
Example
cache = discretize(prob)
k_values = range(0.1, 5.0, length=50)
# Sequential (1 workspace, reused for all wavenumbers):
results = solve(cache, k_values; sigma_0=0.02)
# Parallel (1 workspace per thread, reused across wavenumbers):
results = solve(cache, k_values; sigma_0=0.02, parallel=true)BiGSTARS.solve! — Method
solve!(solver::EigenSolver; verbose::Bool=true)Solve the generalized eigenvalue problem with adaptive shift selection.
Returns
solver.results: Updated with solution results
Example
solver = EigenSolver(A, B; σ₀=1.0, method=:Arnoldi, nev=5)
solve!(solver)
λ, Χ = get_results(solver)BiGSTARS.solve — Method
solve(cache; sigma_0, kwargs...) -> Vector{SolverResults}Solve a problem with no FourierTransformed direction (pure 1D/2D, no wavenumber sweep).
BiGSTARS.sort_evals — Method
λs_sorted, χ_sorted = sort_evals(λs, χ, "R"; sorting="lm")
Sort the eigenvalues `λs` and corresponding eigenvectors `χ` based on the specified criterion
(`"M"` for magnitude, `"I"` for imaginary part, or `"R"` for real part).
The `sorting` argument determines the order: `"lm"` for descending order.BiGSTARS.sort_evals — Method
sort_evals(λ, Χ, by::Symbol; rev::Bool=true)Sort eigenvalues λ and corresponding eigenvectors Χ by:
:R→ real part:I→ imaginary part:M→ magnitude (abs)
Set rev=true for descending (default), false for ascending.
BiGSTARS.to_coefficients — Method
to_coefficients(f_physical, coord_type, N) -> VectorTransform physical-space values to spectral coefficients.
:chebyshev→ Chebyshev T coefficients via DCT:fourier→ Fourier coefficients via FFT (scaled by 1/N)
BiGSTARS.to_physical — Method
to_physical(c, coord_type, x) -> VectorTransform spectral coefficients back to physical-space values.
:chebyshev→ evaluate Chebyshev expansion at points x:fourier→ inverse FFT