Skip to content

Commit 93787dc

Browse files
committed
Revise docstrings across mpi-igg branch
Add missing docstrings for exported and internal functions (set_backend, global_dot/sum/length/min, scalar_halo!, velocity_halo!, global_perdot, L₂, conv_diff!, BDIM!, project!, CFL, _apply_offset, up/down/restrict/ restrictL/restrictML/restrictL!, Vcycle!, MultiLevelPoisson solver!). Fix inaccuracies and typos and update existing docstrings with MPI-relevant details
1 parent c882a4e commit 93787dc

9 files changed

Lines changed: 200 additions & 50 deletions

File tree

ext/WaterLilyMPIExt.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ hooks through `par_mode[]` (defaults to `Serial()`). This extension defines
1010
`Parallel <: AbstractParMode` and adds new dispatch methods — no method
1111
overwriting, so precompilation works normally.
1212
13-
Functions with MPI-specific behavior (via dispatch or subtype specialization):
13+
Functions with MPI-specific behavior (via dispatch on `::Parallel`):
1414
_wallBC_L! — zero L at physical walls only (skip MPI-internal) + halo on L
15-
_exitBC! — global reductions for inflow/outflow mass flux (dispatches on ::Parallel)
15+
_exitBC! — global reductions for inflow/outflow mass flux
1616
_divisible — stricter coarsening threshold (N>8) for multigrid
1717
"""
1818
module WaterLilyMPIExt

src/AutoBody.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ struct AutoBody{F1<:Function,F2<:Function} <: AbstractBody
1212
map::F2
1313
end
1414
AutoBody(sdf, map=(x,t)->x) = AutoBody(sdf, map)
15+
"""
16+
_apply_offset(body::AutoBody, offset)
17+
18+
Wrap the body's `map` function so that rank-local coordinates are shifted
19+
by `offset` before evaluation. This lets users write SDFs in global
20+
coordinates while each MPI rank indexes with local coordinates.
21+
"""
1522
_apply_offset(body::AutoBody, offset) =
1623
AutoBody(body.sdf, let m=body.map, o=offset; (x,t)->m(x .+ o, t); end)
1724

src/Body.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,13 @@ struct SetBody{O<:Function,Ta<:AbstractBody,Tb<:AbstractBody} <: AbstractBody
9797
b::Tb
9898
end
9999

100-
# Default _apply_offset: identity for generic bodies
100+
"""
101+
_apply_offset(body::AbstractBody, offset)
102+
103+
Wrap the body's coordinate mapping so rank-local coordinates are shifted by
104+
`offset` before evaluation. Default is identity (no-op). `SetBody` recurses
105+
into its children; `AutoBody` wraps the `map` function (see `AutoBody.jl`).
106+
"""
101107
_apply_offset(body::AbstractBody, offset) = body
102108
_apply_offset(body::SetBody, offset) = SetBody(body.op, _apply_offset(body.a, offset), _apply_offset(body.b, offset))
103109

src/Flow.jl

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ function median(a,b,c)
3232
return a
3333
end
3434

35+
"""
36+
conv_diff!(r, u, Φ, λ; ν=0.1, perdir=())
37+
38+
Compute the convective and diffusive fluxes of velocity `u` using the
39+
convection scheme `λ(u,c,d)` and kinematic viscosity `ν`. The result is
40+
accumulated into `r` (force per unit volume) and `Φ` is a working scalar.
41+
"""
3542
function conv_diff!(r,u,Φ,λ::F=0.1,perdir=()) where {F}
3643
r .= zero(eltype(r))
3744
N,n = size_u(u)
@@ -53,14 +60,17 @@ accelerate!(r,t,g::Function,::Union{Nothing,Tuple}) = accelerate!(r,t,g)
5360
accelerate!(r,t,::Nothing,U::Function) = accelerate!(r,t,(i,x,t)->ForwardDiff.derivative->U(i,x,τ),t))
5461
accelerate!(r,t,g::Function,U::Function) = accelerate!(r,t,(i,x,t)->g(i,x,t)+ForwardDiff.derivative->U(i,x,τ),t))
5562
"""
56-
Flow{D::Int, T::Float, Sf<:AbstractArray{T,D}, Vf<:AbstractArray{T,D+1}, Tf<:AbstractArray{T,D+2}}
63+
Flow{D, T, Sf, Vf, Tf}
5764
5865
Composite type for a multidimensional immersed boundary flow simulation.
5966
6067
Flow solves the unsteady incompressible [Navier-Stokes equations](https://en.wikipedia.org/wiki/Navier%E2%80%93Stokes_equations) on a Cartesian grid.
6168
Solid boundaries are modelled using the [Boundary Data Immersion Method](https://eprints.soton.ac.uk/369635/).
6269
The primary variables are the scalar pressure `p` (an array of dimension `D`)
6370
and the velocity vector field `u` (an array of dimension `D+1`).
71+
72+
All arrays use the N+4 staggered layout: `N` interior cells plus 2 ghost/boundary
73+
cells per side, giving total size `M = N + 4` per spatial dimension.
6474
"""
6575
struct Flow{D, T, Sf<:AbstractArray{T}, Vf<:AbstractArray{T}, Tf<:AbstractArray{T}}
6676
# Fluid fields
@@ -77,7 +87,7 @@ struct Flow{D, T, Sf<:AbstractArray{T}, Vf<:AbstractArray{T}, Tf<:AbstractArray{
7787
uBC :: Union{NTuple{D,Number},Function} # domain boundary values/function
7888
Δt:: Vector{T} # time step (stored in CPU memory)
7989
ν :: T # kinematic viscosity
80-
g :: Union{Function,Nothing} # acceleration field funciton
90+
g :: Union{Function,Nothing} # acceleration field function
8191
exitBC :: Bool # Convection exit
8292
perdir :: NTuple # tuple of periodic direction
8393
function Flow(N::NTuple{D}, uBC; f=Array, Δt=0.25, ν=0., g=nothing,
@@ -103,12 +113,26 @@ Current flow time.
103113
"""
104114
time(a::Flow) = sum(@view(a.Δt[1:end-1]))
105115

116+
"""
117+
BDIM!(a::Flow)
118+
119+
Apply the Boundary Data Immersion Method to enforce the body velocity.
120+
Uses the zeroth and first kernel moments (`μ₀`, `μ₁`) to blend the
121+
body velocity `V` with the predicted fluid velocity.
122+
"""
106123
function BDIM!(a::Flow)
107124
dt = a.Δt[end]
108125
@loop a.f[Ii] = a.u⁰[Ii]+dt*a.f[Ii]-a.V[Ii] over Ii in CartesianIndices(a.f)
109126
@loop a.u[Ii] += μddn(Ii,a.μ₁,a.f)+a.V[Ii]+a.μ₀[Ii]*a.f[Ii] over Ii inside_u(size(a.p))
110127
end
111128

129+
"""
130+
project!(a::Flow, b::AbstractPoisson, w=1)
131+
132+
Project the velocity field onto a divergence-free field by solving
133+
the pressure Poisson equation `∇⋅(L∇p) = ∇⋅u/Δt` and correcting
134+
the velocity: `u -= L∇p`. The weight `w` scales `Δt` (0.5 for the corrector).
135+
"""
112136
function project!(a::Flow{n},b::AbstractPoisson,w=1) where n
113137
dt = w*a.Δt[end]
114138
@inside b.z[I] = div(I,a.u); b.x .*= dt # set source term & solution IC
@@ -146,6 +170,12 @@ and the `AbstractPoisson` pressure solver to project the velocity onto an incomp
146170
end
147171
scale_u!(a,scale) = @loop a.u[Ii] *= scale over Ii inside_u(size(a.p))
148172

173+
"""
174+
CFL(a::Flow; Δt_max=10)
175+
176+
Compute the CFL-limited time step from the maximum outward flux at each cell.
177+
Uses `global_min` for MPI-safe reduction across all ranks.
178+
"""
149179
function CFL(a::Flow;Δt_max=10)
150180
@inside a.σ[I] = flux_out(I,a.u)
151181
global_min(Δt_max,inv(maximum(a.σ)+5a.ν))

src/Metrics.jl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ Compute ``∥𝛚∥`` at the center of cell `I`.
7272
"""
7373
ω_mag(I::CartesianIndex{3},u) = norm2(ω(I,u))
7474
"""
75-
ω_θ(I::CartesianIndex{3},z,center,u)
75+
ω_θ(I::CartesianIndex{3}, z, center, u; offset=zero(SVector{3,eltype(u)}))
7676
7777
Compute ``𝛚⋅𝛉`` at the center of cell `I` where ``𝛉`` is the azimuth
78-
direction around vector `z` passing through `center`.
78+
direction around vector `z` passing through `center`. The optional
79+
`offset` shifts the cell location — used in MPI parallel to map
80+
rank-local indices to global coordinates.
7981
"""
8082
function ω_θ(I::CartesianIndex{3},z,center,u;offset=zero(SVector{3,eltype(u)}))
8183
θ = z × (loc(0,I,eltype(u))+offset-SVector{3}(center))
@@ -138,9 +140,11 @@ total_force(sim) = pressure_force(sim) .+ viscous_force(sim)
138140

139141
using LinearAlgebra: cross
140142
"""
141-
pressure_moment(x₀,sim::Simulation)
143+
pressure_moment(x₀, sim::Simulation; offset=zero(x₀))
142144
143-
Computes the pressure moment on an immersed body relative to point x₀.
145+
Compute the pressure moment on an immersed body relative to point `x₀`.
146+
The optional `offset` shifts cell locations — used in MPI parallel to map
147+
rank-local indices to global coordinates.
144148
"""
145149
pressure_moment(x₀,sim;kwargs...) = pressure_moment(x₀,sim.flow,sim.body;kwargs...)
146150
pressure_moment(x₀,flow,body;kwargs...) = pressure_moment(x₀,flow.p,flow.f,body,time(flow);kwargs...)

src/MultiLevelPoisson.jl

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,34 @@
1+
"""
2+
up(I, a=0)
3+
4+
Return the fine-grid `CartesianIndices` range that maps to coarse cell `I`.
5+
When `a≠0`, the range is shifted by `-δ(a,I)` for staggered (face) restriction.
6+
"""
17
@inline up(I::CartesianIndex,a=0) = (2I-3oneunit(I)):(2I-2oneunit(I)-δ(a,I))
8+
"""
9+
down(I)
10+
11+
Map fine-grid index `I` to the corresponding coarse-grid index.
12+
"""
213
@inline down(I::CartesianIndex) = CI((I.I .- 1) 2 .+ 2)
14+
"""
15+
restrict(I, b)
16+
17+
Sum the fine-grid scalar values in `b` that map to coarse cell `I`.
18+
"""
319
@fastmath @inline function restrict(I::CartesianIndex,b)
420
s = zero(eltype(b))
521
for J up(I)
622
s += @inbounds(b[J])
723
end
824
return s
925
end
26+
"""
27+
restrictL(I, i, b)
28+
29+
Restrict the Poisson conductivity `b` in dimension `i` from the fine grid
30+
to coarse cell `I`, averaging the two fine-grid face values.
31+
"""
1032
@fastmath @inline function restrictL(I::CartesianIndex,i,b)
1133
s = zero(eltype(b))
1234
for J up(I,i)
@@ -15,6 +37,12 @@ end
1537
return 0.5s
1638
end
1739

40+
"""
41+
restrictML(b::Poisson)
42+
43+
Build a new coarse-level `Poisson` from fine-level `b` by restricting the
44+
conductivity `L` and allocating matching solution/residual arrays.
45+
"""
1846
function restrictML(b::Poisson)
1947
N,n = size_u(b.L)
2048
Na = map(i->i÷2+2,N)
@@ -23,6 +51,12 @@ function restrictML(b::Poisson)
2351
restrictL!(aL,b.L,perdir=b.perdir)
2452
Poisson(ax,aL,copy(ax);b.perdir)
2553
end
54+
"""
55+
restrictL!(a, b; perdir=())
56+
57+
Restrict the fine-grid conductivity `b` into coarse-grid `a`, then apply
58+
boundary conditions (`BC!` and `wallBC_L!`) on the coarse level.
59+
"""
2660
function restrictL!(a::AbstractArray{T,M},b;perdir=()) where {T,M}
2761
Na,n = size_u(a)
2862
for i 1:n
@@ -36,10 +70,10 @@ prolongate!(a,b) = @inside a[I] = b[down(I)]
3670

3771
@inline divisible(l::Poisson) = all(size(l.x) .|> divisible)
3872
"""
39-
MultiLevelPoisson{N,M}
73+
MultiLevelPoisson{T,S,V}
4074
4175
Composite type used to solve the pressure Poisson equation with a [geometric multigrid](https://en.wikipedia.org/wiki/Multigrid_method) method.
42-
The only variable is `levels`, a vector of nested `Poisson` systems.
76+
The main field is `levels`, a vector of nested `Poisson` systems from fine to coarse.
4377
"""
4478
struct MultiLevelPoisson{T,S<:AbstractArray{T},V<:AbstractArray{T}} <: AbstractPoisson{T,S,V}
4579
x::S
@@ -67,6 +101,13 @@ function update!(ml::MultiLevelPoisson)
67101
end
68102
end
69103

104+
"""
105+
Vcycle!(ml::MultiLevelPoisson; l=1, ω=1)
106+
107+
Perform one multigrid V-cycle starting at level `l`: smooth on the fine grid,
108+
restrict the residual, solve (or recurse) on the coarse grid, then prolongate
109+
and correct the fine-grid solution.
110+
"""
70111
function Vcycle!(ml::MultiLevelPoisson;l=1=1)
71112
fine,coarse = ml.levels[l],ml.levels[l+1]
72113
# set up coarse level
@@ -86,6 +127,13 @@ residual!(ml::MultiLevelPoisson,x) = residual!(ml.levels[1],x)
86127

87128
smooth! = GaussSeidelRB!
88129

130+
"""
131+
solver!(ml::MultiLevelPoisson; tol=1e-4, itmx=32)
132+
133+
Multigrid solver: iterates V-cycles with adaptive relaxation `ω` until the
134+
`L₂`-norm residual drops below `tol`. Ends with `pin_pressure!` + `comm!`
135+
to remove the null-space mode and synchronize halos.
136+
"""
89137
function solver!(ml::MultiLevelPoisson{T};tol=1e-4,itmx=32) where T
90138
p = ml.levels[1]
91139
residual!(p); r₂ = L₂(p); ω = T(1)

src/Poisson.jl

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
abstract type AbstractPoisson{T,S,V} end
22

33
"""
4-
Poisson{N,M}
4+
Poisson{T, S, V}
55
66
Composite type for conservative variable coefficient Poisson equations:
77
@@ -13,11 +13,18 @@ The resulting linear system is
1313
1414
where A is symmetric, block-tridiagonal and extremely sparse. Moreover,
1515
`D[I]=-∑ᵢ(L[I,i]+L'[I,i])`. This means matrix storage, multiplication,
16-
ect can be easily implemented and optimized without external libraries.
17-
18-
To help iteratively solve the system above, the Poisson structure holds
19-
helper arrays for `inv(D)`, the error `ϵ`, and residual `r=z-Ax`. An iterative
20-
solution method then estimates the error `ϵ=̃A⁻¹r` and increments `x+=ϵ`, `r-=Aϵ`.
16+
etc. can be easily implemented and optimized without external libraries.
17+
18+
The conductivity `L` is initialized from `flow.μ₀` and modified by
19+
`wallBC_L!` (zero at physical walls for Neumann BCs). Ghost-cell
20+
synchronization uses `comm!` (= `perBC!` + `scalar_halo!`) rather than
21+
bare `perBC!`, so that MPI rank-internal boundaries are handled correctly.
22+
23+
To help iteratively solve the system, the structure holds helper arrays
24+
for `inv(D)`, the error `ϵ`, and residual `r=z-Ax`. An iterative solution
25+
method estimates the error `ϵ≈A⁻¹r` and increments `x+=ϵ`, `r-=Aϵ`.
26+
The solver ends with `pin_pressure!` + `comm!` to remove the null-space
27+
mode and synchronize halos.
2128
"""
2229
struct Poisson{T,S<:AbstractArray{T},V<:AbstractArray{T}} <: AbstractPoisson{T,S,V}
2330
L :: V # Lower diagonal coefficients
@@ -58,7 +65,7 @@ end
5865
mult!(p::Poisson,x)
5966
6067
Efficient function for Poisson matrix-vector multiplication.
61-
Fills `p.z = p.A x` with 0 in the ghost cells.
68+
Fills `p.z = Ax` with 0 in the ghost cells, where `A` is the Poisson matrix implied by `L` and `D`.
6269
"""
6370
function mult!(p::Poisson,x)
6471
@assert axes(p.z)==axes(x)
@@ -135,7 +142,7 @@ end
135142
GaussSeidelRB!(p::Poisson;it=4, ω=1)
136143
137144
Red-black Gauss-Seidel smoother. Runs `it` iterations; a complete red-black cycle requires `it` to be even.
138-
`ω` under-/over-relaxs the solution through scaling the deferred corrections in `increment!`.
145+
`ω` under-/over-relaxes the solution through scaling the deferred corrections in `increment!`.
139146
Note: This performs best on GPU configurations and is the default smoother.
140147
"""
141148
function GaussSeidelRB!(p::Poisson{T};it=4, ω=1) where {T}
@@ -150,7 +157,7 @@ end
150157
"""
151158
pcg!(p::Poisson; it=6)
152159
153-
Conjugate-Gradient smoother with Jacobi predictioning. Runs at most `it` iterations,
160+
Conjugate-Gradient smoother with Jacobi preconditioning. Runs at most `it` iterations,
154161
but will exit early if the Gram-Schmidt update parameter `|α| < 1%` or `|r D⁻¹ r| < 1e-8`.
155162
Note: This runs for general backends.
156163
"""
@@ -180,16 +187,19 @@ L₂(p::Poisson) = global_dot(p.r, p.r) # special method since outside(p.r)≡0
180187
L∞(p::Poisson) = maximum(abs,p.r)
181188

182189
"""
183-
solver!(A::Poisson;tol=1e-4,itmx=1e3)
190+
solver!(A::Poisson; tol=1e-4, itmx=1e3)
184191
185-
Approximate iterative solver for the Poisson matrix equation `Ax=b`.
192+
Iterative solver for the Poisson matrix equation `Ax=b` using
193+
preconditioned conjugate gradients (`pcg!`).
186194
187-
- `A`: Poisson matrix with working arrays.
188-
- `A.x`: Solution vector. Can start with an initial guess.
189-
- `A.z`: Right-Hand-Side vector. Will be overwritten!
190-
- `A.n[end]`: stores the number of iterations performed.
195+
- `A.x`: Solution vector (can start with an initial guess).
196+
- `A.z`: Right-hand-side vector (overwritten).
197+
- `A.n[end]`: Number of iterations performed.
191198
- `tol`: Convergence tolerance on the `L₂`-norm residual.
192199
- `itmx`: Maximum number of iterations.
200+
201+
Ends with `pin_pressure!` (remove null-space mean) and `comm!`
202+
(halo sync) so the solution is ready for use in `project!`.
193203
"""
194204
function solver!(p::Poisson;tol=1e-4,itmx=1e3)
195205
residual!(p); r₂ = L₂(p)

src/WaterLily.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export RigidMap,setmap
6060

6161
"""
6262
Simulation(dims::NTuple, uBC::Union{NTuple,Function}, L::Number;
63-
U=norm2(Uλ), Δt=0.25, ν=0., ϵ=1, g=nothing,
63+
U=√sum(abs2,uBC), Δt=0.25, ν=0., ϵ=1, g=nothing,
6464
perdir=(), exitBC=false,
6565
body::AbstractBody=NoBody(),
6666
T=Float32, mem=Array)

0 commit comments

Comments
 (0)