CNAB

Immersa.AbstractCouplerType
AbstractCoupler

Abstract interface for coupling strategies in the CNAB time integration framework.

This type defines a common interface for different coupler implementations that manage interactions between PDE components or immersed bodies during time integration. Specific couplers include:

  • NothingCoupler : No coupling required.
  • PrescribedBodyCoupler : For bodies with prescribed motion or known behavior.
  • FsiCoupler : For fluid-structure interaction problems.

Arguments

None.

Returns

An abstract type that serves as a base for all coupling strategies used in CNAB-based simulations.

source
Immersa.NothingCouplerType
NothingCoupler

A simple subtype of AbstractCoupler representing the absence of coupling.

Use this type when no body-fluid interaction or other coupling is required in the CNAB time integration framework. It serves as a placeholder that satisfies the coupler interface without modifying the solution.

Arguments

None.

Returns

An instance of NothingCoupler, indicating that no coupling is applied during the simulation.

source
Immersa.PrescribedBodyCouplerType
PrescribedBodyCoupler{M}

A subtype of AbstractCoupler for prescribed body motion or constraints.

This coupler stores a field Binv, representing a precomputed operator used to enforce prescribed motion (and forces) on the body. The type M is parametric, allowing flexibility in the data structure used for Binv (e.g., arrays or linear operators).

Arguments

  • Binv::M : Precomputed operator or matrix used to apply constraints for the prescribed body.

Returns

An instance of PrescribedBodyCoupler suitable for simulations where body motion or behavior is explicitly prescribed.

source
Immersa.FsiCouplerType
FsiCoupler{T,O<:GeometricNonlinearBodyOperators,B}

A subtype of AbstractCoupler for fluid–structure interaction (FSI) problems with nonlinear structural dynamics.

This type encapsulates the structural state, geometric nonlinear operators, solver tolerance, BiCGStab solver arguments, and iteration limits required for solving coupled FSI problems using the CNAB time integration framework.

The keyword constructor allows easy setup of the coupler, including automatic initialization of the structural state and operators for a given GeometricNonlinearBody.

Fields

  • state::StructuralState{T} : Current state of the structural body (displacements, velocities, deformations), parameterized by numeric type T.
  • ops::O : Operator object representing the geometric nonlinear structural model.
  • tol::T : Numerical tolerance for the iterative solve.
  • bicgstabl_args::B : Arguments for the BiCGStab(ℓ) iterative solver (tuple or named container).
  • maxiter::Int : Maximum iterations during the solver phase.

Arguments (via keyword constructor)

  • backend::CPU : Computation backend (CPU-based).
  • body::GeometricNonlinearBody{N,T} : Nonlinear structural body with N spatial dimensions and numeric type T.
  • tol : Solver tolerance (default 1e-5).
  • bicgstabl_args : Solver arguments (default (; abstol=T(1e-5), reltol=T(0.0))).
  • maxiter::Int : Maximum iterations (default 100).

Returns

A fully initialized FsiCoupler instance ready to couple the fluid and structural solvers in FSI simulations.

source
Immersa.CNABType
CNAB{N,T,B,U,P,R<:Reg,C<:AbstractCoupler,Au,Aω,Vb,BP<:BodyPoints,A<:ArrayPool,W}

Central mutable type representing the state and configuration of a Crank–Nicolson Adams–Bashforth (CNAB) time integration scheme for coupled fluid–structure simulations.

This struct holds all data required for time-stepping the simulation, including fluid and body fields, transform plans, regularization operators, memory pools, and solver buffers. It is designed for high-performance computing with support for GPU/CPU backends and flexible handling of complex bodies and couplers.

Fields

  • prob::IBProblem{N,T,B,U} : The immersed boundary problem defining the grid and bodies.
  • t0::T : Initial simulation time.
  • i::Int : Current time step index.
  • t::T : Current simulation time.
  • dt::T : Time step size.
  • β::Vector{T} : CNAB scheme coefficients.
  • plan::P : FFT or spectral transform plan.
  • reg::R : Regularizer or interpolation operator.
  • coupler::C : Coupling strategy (FsiCoupler, PrescribedBodyCoupler, NothingCoupler).
  • redist_weights::Au : Redistribution weights for fluid variables.
  • ω::Vector{Aω} : Vorticity field(s).
  • ψ::Vector{Aω} : Streamfunction or auxiliary field(s).
  • u::Vector{Au} : Velocity field(s).
  • f_tilde::Vb, f::Vb : Body force arrays.
  • points::BP : Body point data structure.
  • nonlin::Vector{Vector{Aω}} : Buffers for nonlinear term history.
  • nonlin_count::Int : Counter for nonlinear buffers.
  • ω_bndry::W : Boundary vorticity data.
  • body_pool::A, fluid_pool::A, bndry_pool::A, structure_pool::A : Memory pools to reduce allocations.

Arguments (via constructor)

  • prob::IBProblem{N,T} : Immersed boundary problem containing grid and body setup.
  • dt : Time step size.
  • t0 : Initial simulation time (default 0).
  • n_step : Number of previous time steps to retain for CNAB (default 2).
  • delta : Regularization kernel (default DeltaYang3S()).
  • backend : Computation backend (CPU() or GPU device).
  • coupler_args : Keyword arguments for the coupling constructor (e.g., FsiCoupler).

Description

The constructor automatically allocates all buffers, precomputes FFT plans, regularization operators, and memory pools, and bundles them into a CNAB object ready for time integration. It performs the following main steps:

  1. Setup grid and body: retrieves grid and body from prob.
  2. Pre-allocate main fluid field: creates vorticity arrays.
  3. Create FFT plan: precomputes spectral transforms for efficient solves.
  4. Determine problem sizes: computes number of body points and structure variables.
  5. Allocate memory pools: sizes pools for fluid, body, boundary, and structure arrays.
  6. Bundle arguments: stores all fields and buffers in a named tuple.
  7. Build the solution object: calls initial_sol to wrap arguments into a fully initialized CNAB instance.

Returns

A CNAB object fully initialized for coupled time-stepping with the CNAB scheme.

source
Immersa.initial_solFunction
initial_sol(backend, body, sol_args, coupler_args)

Initialize a CNAB simulation object based on the type of body in the problem.

This function has two methods depending on whether body is a static or geometrically nonlinear (deforming) body:

  1. Static Body Initialization (AbstractStaticBody)

    • Constructs a temporary CNAB with a NothingCoupler.
    • Initializes body point positions.
    • Computes regularization weights.
    • Computes the inverse of the body–fluid coupling matrix.
    • Creates a PrescribedBodyCoupler with the precomputed operator.
    • Builds the final CNAB object with the coupler.
    • Sets simulation time and initializes fluid fields.
  2. Geometric Nonlinear Body Initialization (GeometricNonlinearBody)

    • Constructs an FsiCoupler for nonlinear structural dynamics.
    • Builds the CNAB object with this coupler.
    • Sets simulation time and zeros the fluid fields.
    • Splits prescribed and deforming points.
    • Initializes prescribed body points.
    • Updates the structural state and initializes structure operators.
    • Computes regularization and redistribution weights.

Arguments

  • backend : Computation backend (CPU() or GPU device).
  • body : The body in the problem (AbstractStaticBody or GeometricNonlinearBody).
  • sol_args : Named tuple with CNAB fields and buffers.
  • coupler_args : Keyword arguments passed to the coupler constructor.

Returns

A fully initialized CNAB object ready for time integration, configured according to the type of body and the specified coupling strategy.

source
Immersa.zero_vorticity!Function
zero_vorticity!(sol::CNAB)

Reset all fluid-related fields in a CNAB simulation object.

This function sets the vorticity (ω), streamfunction (ψ), and velocity (u) fields to zero across all grid levels. It also resets the nonlinear history counter and re-applies the initial prescribed flow field (u0).

Arguments

  • sol::CNAB : The CNAB simulation object whose fluid fields are being reset.

Returns

The updated CNAB object with zeroed fluid fields and initial flow re-applied.

source
Immersa.set_time!Function
set_time!(sol::CNAB, i::Integer)

Advance the CNAB integrator to a specific time step.

This function updates the internal step index (i) and computes the corresponding physical time (t) of the simulation using:

t = t0 + dt * (i - 1)

where t0 is the initial simulation time and dt is the time step size. This ensures that all time-dependent operations in the simulation remain consistent.

Arguments

  • sol::CNAB : The CNAB simulation object to update.
  • i::Integer : The target time step index.

Returns

The updated CNAB object with the new time step and physical time.

source
Immersa.step!Function
step!(sol::CNAB)

Advance the CNAB simulation by one time step.

This is the main time integration routine that updates both the fluid and structure fields according to the CNAB scheme. A single call to step! performs the following sequence:

  1. Advance the simulation time step (set_time!).
  2. Predict the new fluid and body state (prediction_step!).
  3. Apply fluid–structure coupling (coupling_step!).
  4. Project the velocity field to enforce incompressibility (projection_step!).
  5. Update the vorticity field (apply_vorticity!).

Arguments

  • sol::CNAB : The CNAB simulation object representing the current state.

Returns

The updated CNAB object after one complete time step.

source
Immersa.update_reg!Function
update_reg!(sol::CNAB, body, i)

Update the regularization weights for the simulation based on the type of body.

There are two methods:

  1. Static bodies (AbstractStaticBody)

    • No update is necessary because the body does not move or deform.
    • The function returns nothing.
  2. Prescribed-motion bodies (AbstractPrescribedBody)

    • Updates the regularization weights by calling update_weights! with the current body point positions.
    • Ensures that the mapping from body points to the grid reflects the current motion.

Arguments

  • sol::CNAB : CNAB simulation object containing the grid and body fields.
  • body : The body object (AbstractStaticBody or AbstractPrescribedBody).
  • i : Index or set of points for which the regularization is updated (used for prescribed bodies).

Returns

  • Nothing for static bodies.
  • Updates sol.reg in-place for prescribed-motion bodies.
source
Immersa._A_factorFunction
_A_factor(sol::CNAB)

Compute the diffusion coefficient used in the CNAB time-stepping scheme.

This coefficient arises in the semi-implicit (Crank–Nicolson) treatment of the viscous term and is given by:

A = Δt / (2 * Re)

Arguments

  • sol::CNAB : CNAB simulation object containing the current state and parameters.

Returns

  • Diffusion coefficient (same numeric type as sol.dt).
source
Immersa.AinvFunction
Ainv(sol::CNAB, level)

Construct the inverse viscous operator used in the CNAB time-stepping scheme.

Arguments

  • sol::CNAB: CNAB simulation object containing the problem definition and FFT plans.
  • level: Grid refinement level at which to build the operator.

Returns

  • EigenbasisTransform: An operator that applies the inverse of (I - aΔ) in spectral space, typically used for implicit diffusion updates within the CNAB integrator.
source
Immersa.prediction_step!Function
prediction_step!(sol::CNAB)
prediction_step!(sol::CNAB, level)
prediction_step!(sol::CNAB, level, u_work)

Perform the CNAB prediction of the vorticity field.

This function advances the fluid state by computing the predicted vorticity using a semi-implicit Crank–Nicolson treatment for diffusion and an Adams–Bashforth treatment for nonlinear convection. It supports multigrid levels and avoids unnecessary allocations with array pools.

Arguments

  • sol::CNAB: CNAB simulation object.
  • level (optional): Grid level for single-level update.
  • u_work (optional): Preallocated velocity array for in-place computation.

Returns

  • Updated vorticity field in-place within sol.
source
Immersa.coupling_step!Function
coupling_step!(sol::CNAB)

Perform the fluid–structure coupling step for the current CNAB time step.

This function dispatches to the appropriate coupling routine based on the solver's coupler. For a prescribed body, it computes the fluid velocity at body points, evaluates the coupling residual, and solves for the correcting body force to enforce velocity constraints.

Arguments

  • sol::CNAB: CNAB simulation object with the current fluid and body state.

Returns

  • Updates sol.f_tilde and body-related fields in-place.
source
Immersa.CNAB_Binv_PrecomputedType

CNABBinvPrecomputed(B)

A precomputed coupling operator for the CNAB solver.

Holds a precomputed matrix B used to solve the body–fluid coupling system directly. Efficient when B is constant (e.g., for rigid or prescribed-motion bodies).

The object is callable like a function to compute the body force f given the desired body velocity u_ib and the CNAB solver sol.

Arguments:

  • B: Precomputed coupling matrix.
  • f: Body force vector (updated in-place).
  • u_ib: Coupling right-hand side (desired body velocity minus interpolated fluid velocity).
  • sol::CNAB: CNAB solver object (included for signature consistency, not used here).

Returns:

  • Updates f in-place.
source
Immersa.CNAB_Binv_IterativeType
CNAB_Binv_Iterative{T}

An iterative coupling operator for the CNAB solver, used when the body–fluid coupling matrix B changes every step (e.g. for moving prescribed bodies).

Instead of precomputing B⁻¹, solves the linear system B f = rhs with BiCGStab(ℓ) at each coupling step. The current contents of f serve as a warm start.

Fields

  • abstol::T : Absolute solver tolerance (default 1e-5).
  • reltol::T : Relative solver tolerance (default 0.0).

Call signature

(op::CNAB_Binv_Iterative)(f, rhs, sol::CNAB)

Solves B f = rhs in place, where B is assembled from the current geometry via B_rigid_mul!.

source
Immersa.B_inverse_rigidFunction
B_inverse_rigid(sol::CNAB{N,T,<:AbstractStaticBody})

Construct a precomputed coupling operator for a rigid (static) body.

This function builds the body–fluid coupling matrix B and precomputes its inverse via Cholesky factorization. The returned object is a CNAB_Binv_Precomputed, which can be applied during the CNAB coupling step as coupler.Binv(sol.f_tilde, rhs, sol).

  • Only for static/non-deforming bodies.
  • Precomputing B ensures fast solves at each timestep.
  • The matrix is assumed symmetric positive definite (SPD).

Inputs

  • sol::CNAB: CNAB simulation object containing the body and grid.

Returns

  • CNAB_Binv_Precomputed: Callable object that efficiently applies B⁻¹.
source
Immersa.B_rigid_mul!Function
B_rigid_mul!(u_ib, f, sol::CNAB{N,T})

Apply the rigid-body coupling operator to a force vector.

This function defines the action of the rigid-body coupling matrix B such that u_ib = B * f, where f is a body force distribution and u_ib is the resulting velocity at the immersed boundary points.

Two methods are provided:

  1. A wrapper that reinterprets flat arrays as vectors of SVector{N,T} and calls the core implementation.
  2. The main routine, which:
    • Regularizes the body forces to the fluid grid.
    • Solves for the induced velocity field via the vorticity–streamfunction formulation.
    • Interpolates the resulting fluid velocity back to the body points.

This operation is used when assembling the coupling matrix in B_inverse_rigid and represents how the fluid mediates the response of the rigid body to applied forces.

Inputs

  • u_ib: Output array for body velocities.
  • f: Body force vector.
  • sol::CNAB: CNAB solver containing grid, operators, and regularization data.

Returns

  • u_ib: The updated body velocity vector after applying the operator.
source
Immersa.B_deform_mul!Function
B_deform_mul!(u_ib, f, sol::CNAB)

Apply the fluid–structure coupling operator B for a deformable body.

This function maps body forces f to immersed-boundary velocities u_ib, accounting for force spreading, structural response, and velocity interpolation back to the Lagrangian points.

Three methods are provided:

  1. A converter that reinterprets flat scalar vectors as structured SVector arrays.
  2. A wrapper that allocates workspace arrays.
  3. The core routine that computes the coupled fluid–structure response.

Arguments

  • u_ib : Output array for body velocities (updated in-place).
  • f : Input body force vector.
  • sol::CNAB : CNAB solver object containing grid, operators, and regularization.

Returns

  • u_ib updated in-place with the velocity induced by f.
source
Immersa.f_to_f_tilde!Function
f_to_f_tilde!(f, sol::CNAB; inverse=false)

Convert between the physical body force f and its regularized (spread) form f_tilde used in the fluid solver.

This function rescales the immersed boundary force depending on the direction of conversion:

  • When inverse=false (default), it converts f_tilde → f, applying the proper scaling for the boundary point spacing and coupling factor.
  • When inverse=true, it converts f → f_tilde, restoring the fluid solver’s representation of the force.

This transformation ensures consistent units and coupling strength between the structure and the fluid solvers.

Notes

The conversion uses:

  • dt : Time step size.
  • ds : Arc length of immersed boundary points.
  • h : Grid spacing.
  • k = _f_tilde_factor(sol) : Coupling-dependent scaling factor.

Arguments

  • f : Force vector, modified in-place.
  • sol::CNAB : CNAB solver object containing time step, grid, and coupling parameters.
  • inverse : Whether to apply the inverse scaling (f → f_tilde).

Returns

This function returns nothing; the input f is modified in place.

source
Immersa.redist!Function
redist!(f, sol::CNAB)

Redistribute forces on the immersed boundary to ensure consistency with the fluid.

This function corrects the body forces f after numerical operations by:

  • Spreading the force to the fluid grid.
  • Applying precomputed redistribution weights.
  • Interpolating the corrected forces back to the body points.

Arguments

  • f: The body force vector (modified in-place).
  • sol::CNAB: The CNAB solver state containing fluid and body information.

Returns

  • nothing: The input f is updated in-place.
source
Immersa.update_redist_weights!Function
update_redist_weights!(sol::CNAB; tol=1e-10)

Compute the redistribution weights used in redist! to ensure consistent transfer of forces between the immersed boundary and the fluid grid.

The weights correct for imbalances caused by spreading forces from body points to the grid, so that later redistribution preserves the physical accuracy of the simulation.

Arguments

  • sol::CNAB: The CNAB solver object containing the body and fluid state.
  • tol: Minimum threshold for weight inversion to avoid division by zero (default 1e-10).

Returns

  • nothing: The redistribution weights are stored in sol.redist_weights and updated in-place.
source
Immersa.projection_step!Function
projection_step!(sol::CNAB)

Project the fluid vorticity field to remove the effect of the applied body forces (f_tilde), ensuring that the flow field satisfies the updated constraints after force spreading and redistribution.

Arguments

  • sol::CNAB: The CNAB solver object containing the fluid and body state.

Effects

  • Modifies sol.ω in-place to account for the applied body forces.
  • Swaps sol.ω and sol.ψ internally to reuse memory.

Returns

  • nothing: The projection modifies the solver state in-place.
source
Immersa.apply_vorticity!Function
apply_vorticity!(sol::CNAB)

Compute the fluid velocity field from the current vorticity (ω) and update the solution to satisfy boundary conditions and base flow.

Arguments

  • sol::CNAB: The CNAB solver object containing the fluid and body state.

Effects

  • Updates sol.u (velocity field) and ensures sol.ω satisfies boundary conditions.
  • Handles all multigrid levels, applying necessary interpolations between levels.

Returns

  • nothing: Modifies the solver state in-place.
source
Immersa.ab_coeffsFunction
ab_coeffs(T, n)

Return the Adams-Bashforth coefficients for a given order n.

Arguments

  • T: Container type to hold the coefficients (e.g., Tuple or Vector).
  • n: Order of the Adams-Bashforth scheme (currently only 1 or 2).

Returns

  • A container of type T with the AB coefficients:
    • n = 1: [1] (forward Euler, AB1)
    • n = 2: [-1//2, 3//2] (AB2)

Notes

  • AB1 is first-order explicit Euler.
  • AB2 is second-order, using current and previous derivative values for better accuracy.
  • Only n=1 and n=2 are supported; other values throw a DomainError.

Example

ab_coeffs(Tuple, 1)  # returns (1,)
ab_coeffs(Tuple, 2)  # returns (-1//2, 3//2)
source
Immersa._f_tilde_factorFunction
_f_tilde_factor(sol)

Compute the scaling factor used to convert between the physical body force f and the regularized force f_tilde used in the fluid solver.

Arguments

  • sol: CNAB solver object containing grid and time step information.

Returns

  • A scalar factor k = - h^N / Δt where:
    • h is the uniform grid spacing
    • N is the spatial dimension
    • Δt is the time step size
    • The negative sign follows the solver convention for force transformation

Notes

  • This factor is used in f_to_f_tilde! to scale forces correctly between the immersed boundary and the fluid grid.
source
Immersa.surface_force!Function
surface_force!(f, sol)

Convert the redistributed force f_tilde back to the physical surface force f.

Arguments

  • f: Output array that will store the physical surface force.
  • sol: CNAB solver object containing f_tilde and grid/time info.

Behavior

  • Computes a scaling factor k = -h^N / Δt using _f_tilde_factor(sol).
  • Applies the formula f .= -k * sol.f_tilde to recover the actual force on the body surface.

Notes

This reverses the scaling applied in f_to_f_tilde!.

Returns

  • nothing: The physical surface force is written in-place to f.
source
Immersa.surface_force_sumFunction
surface_force_sum(sol)

Compute the total hydrodynamic force exerted by the fluid on the immersed body.

Arguments

  • sol: CNAB solver object containing f_tilde and grid/time info.

Behavior

  • Computes the scaling factor k = -h^N / Δt using _f_tilde_factor(sol).
  • Sums all entries of sol.f_tilde (the redistributed force at Lagrangian points).
  • Scales and flips the sign to recover the physical total force: total_force = -k * sum(sol.f_tilde).

Returns

  • total_force: The net physical force vector acting on the body.
source
Immersa.CNAB_signatureConstant
const CNAB_signature

A compile-time constant used as a unique identifier for the CNAB structure. It stores the string Immersa.jl:CNAB as a vector of bytes (Vector{UInt8}).

This signature can be used, for example, in type-checking, serialization, or validation routines.

source
Immersa.saveFunction
save(io::IO, sol::CNAB)

Serialize the current state of a CNAB simulation to a binary I/O stream.

The binary layout (all integers little-endian) is:

  1. CNAB_signature (magic bytes).
  2. UInt32 scalar size (sizeof(T)).
  3. UInt32 spatial dimension N.
  4. SVector{N,UInt32} grid cell counts.
  5. UInt32 number of multigrid levels.
  6. Int32 current time step index.
  7. Vorticity fields (interior values only, little-endian T), one block per component per level.
  8. UInt32 nonlinear history count.
  9. Nonlinear history buffers (same layout as vorticity).

Use load! to restore the state into an existing CNAB object.

Arguments

  • io::IO : Output stream (e.g. an open file).
  • sol::CNAB : Solver state to serialise.
source
save(filename::AbstractString, x)

Save the state of object x to a file on disk.

This function opens the file specified by filename for writing and delegates the actual saving to a user-defined save method for the object x. It serves as a wrapper to manage file I/O while preserving multiple dispatch.

Arguments

  • filename::AbstractString : Path to the file to write to.
  • x : Object whose state will be saved.

Returns

  • Nothing. The function writes the object's state to disk.
source
Immersa.load!Function
load!(io::IO, sol::CNAB)

Restore a previously saved CNAB simulation state from a binary I/O stream into an existing solver object.

Reads the binary format produced by save, verifies the magic signature and grid parameters, then overwrites the vorticity, time step, and nonlinear history in sol. The solver is left in a consistent state ready for further time-stepping.

Arguments

  • io::IO : Input stream positioned at the start of a saved CNAB block.
  • sol::CNAB : Solver object to populate (modified in place).
source
load!(filename::AbstractString, x)

Load the state of object x from a file on disk.

This function opens the file specified by filename and delegates the actual loading to a user-defined load! method for the object x. It acts as a convenient wrapper to handle file I/O while preserving Julia's multiple dispatch semantics.

Arguments

  • filename::AbstractString : Path to the file to load from.
  • x : Object to populate with the loaded data.

Returns

  • The updated object x with its state loaded from the file.
source