Skip to content

Commit 620ff38

Browse files
authored
Merge pull request #198 from WaterLily-jl/turbulence_modelling
Turbulence utils: SGS model and on-the-fly temporal averaging
2 parents 3b304d0 + 2f22bd1 commit 620ff38

File tree

7 files changed

+225
-45
lines changed

7 files changed

+225
-45
lines changed

ext/WaterLilyJLD2Ext.jl

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,20 @@ save!(fname, flow::Flow; dir="./") = jldsave(
2323
save!(fname::String, sim::AbstractSimulation; dir="./") = save!(fname, sim.flow; dir)
2424

2525
"""
26-
load!(flow::Flow, fname::String; dir="./")
26+
save!(fname, meanflow::MeanFlow; dir="./")
27+
28+
Save the `meanflow::MeanFlow` time-averaged pressure, velocity, velocity-squared, and time arrays into a JLD2-formatted binary file (HDF5 compatible).
29+
"""
30+
save!(fname, meanflow::MeanFlow; dir="./") = jldsave(
31+
joinpath(dir, fname);
32+
P=Array(meanflow.P),
33+
U=Array(meanflow.U),
34+
UU=Array(meanflow.UU),
35+
t=meanflow.t
36+
)
37+
38+
"""
39+
load!(flow::Flow; kwargs...)
2740
2841
Load pressure, velocity, and time steps arrays from a JLD2-formatted binary file.
2942
Keyword arguments considered are `fname="WaterLily.jld2"` and `dir="./"`.
@@ -42,4 +55,24 @@ function load!(flow::Flow; kwargs...)
4255
end
4356
load!(sim::AbstractSimulation, ::Val{:jld2}; kwargs...) = load!(sim.flow; kwargs...)
4457

58+
59+
"""
60+
load!(meanflow::MeanFlow; kwargs...)
61+
62+
Load time-averaged pressure, velocity, velocity-square, and time arrays from a JLD2-formatted binary file.
63+
Keyword arguments considered are `fname="WaterLilyMean.jld2"` and `dir="./"`.
64+
"""
65+
function load!(meanflow::MeanFlow; kwargs...)
66+
fname = get(Dict(kwargs), :fname, "WaterLilyMean.jld2")
67+
dir = get(Dict(kwargs), :dir, "./")
68+
obj = jldopen(joinpath(dir, fname))
69+
@assert size(meanflow.P) == size(obj["P"]) "Simulation size does not match the size of the JLD2-stored simulation."
70+
f = typeof(meanflow.P).name.wrapper
71+
meanflow.P .= obj["P"] |> f
72+
meanflow.U .= obj["U"] |> f
73+
empty!(meanflow.t)
74+
push!(meanflow.t, obj["t"]...)
75+
close(obj)
76+
end
77+
4578
end # module

src/Flow.jl

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
@inline ϕ(a,I,f) = @inbounds (f[I]+f[I-δ(a,I)])/2
44
@fastmath quick(u,c,d) = median((5c+2d-u)/6,c,median(10c-9u,c,d))
55
@fastmath vanLeer(u,c,d) = (cmin(u,d) || cmax(u,d)) ? c : c+(d-c)*(c-u)/(d-u)
6-
@inline ϕu(a,I,f,u,λ=quick) = @inbounds u>0 ? u*λ(f[I-2δ(a,I)],f[I-δ(a,I)],f[I]) : u*λ(f[I+δ(a,I)],f[I],f[I-δ(a,I)])
7-
@inline ϕuP(a,Ip,I,f,u,λ=quick) = @inbounds u>0 ? u*λ(f[Ip],f[I-δ(a,I)],f[I]) : u*λ(f[I+δ(a,I)],f[I],f[I-δ(a,I)])
8-
@inline ϕuL(a,I,f,u,λ=quick) = @inbounds u>0 ? u*ϕ(a,I,f) : u*λ(f[I+δ(a,I)],f[I],f[I-δ(a,I)])
9-
@inline ϕuR(a,I,f,u,λ=quick) = @inbounds u<0 ? u*ϕ(a,I,f) : u*λ(f[I-2δ(a,I)],f[I-δ(a,I)],f[I])
6+
@fastmath cds(u,c,d) = (c+d)/2
7+
8+
@inline ϕu(a,I,f,u,λ) = @inbounds u>0 ? u*λ(f[I-2δ(a,I)],f[I-δ(a,I)],f[I]) : u*λ(f[I+δ(a,I)],f[I],f[I-δ(a,I)])
9+
@inline ϕuP(a,Ip,I,f,u,λ) = @inbounds u>0 ? u*λ(f[Ip],f[I-δ(a,I)],f[I]) : u*λ(f[I+δ(a,I)],f[I],f[I-δ(a,I)])
10+
@inline ϕuL(a,I,f,u,λ) = @inbounds u>0 ? u*ϕ(a,I,f) : u*λ(f[I+δ(a,I)],f[I],f[I-δ(a,I)])
11+
@inline ϕuR(a,I,f,u,λ) = @inbounds u<0 ? u*ϕ(a,I,f) : u*λ(f[I-2δ(a,I)],f[I-δ(a,I)],f[I])
1012

1113
@fastmath @inline function div(I::CartesianIndex{m},u) where {m}
1214
init=zero(eltype(u))
@@ -33,31 +35,31 @@ function median(a,b,c)
3335
return a
3436
end
3537

36-
function conv_diff!(r,u,Φ;ν=0.1,perdir=())
38+
function conv_diff!(r,u,Φ::F=0.1,perdir=()) where {F}
3739
r .= zero(eltype(r))
3840
N,n = size_u(u)
3941
for i 1:n, j 1:n
4042
# if it is periodic direction
4143
tagper = (j in perdir)
4244
# treatment for bottom boundary with BCs
43-
lowerBoundary!(r,u,Φ,ν,i,j,N,Val{tagper}())
45+
lowerBoundary!(r,u,Φ,ν,i,j,N,λ,Val{tagper}())
4446
# inner cells
45-
@loop (Φ[I] = ϕu(j,CI(I,i),u,ϕ(i,CI(I,j),u)) - ν*(j,CI(I,i),u);
47+
@loop (Φ[I] = ϕu(j,CI(I,i),u,ϕ(i,CI(I,j),u)) - ν*(j,CI(I,i),u);
4648
r[I,i] += Φ[I]) over I inside_u(N,j)
4749
@loop r[I-δ(j,I),i] -= Φ[I] over I inside_u(N,j)
4850
# treatment for upper boundary with BCs
49-
upperBoundary!(r,u,Φ,ν,i,j,N,Val{tagper}())
51+
upperBoundary!(r,u,Φ,ν,i,j,N,λ,Val{tagper}())
5052
end
5153
end
5254

5355
# Neumann BC Building block
54-
lowerBoundary!(r,u,Φ,ν,i,j,N,::Val{false}) = @loop r[I,i] += ϕuL(j,CI(I,i),u,ϕ(i,CI(I,j),u)) - ν*(j,CI(I,i),u) over I slice(N,2,j,2)
55-
upperBoundary!(r,u,Φ,ν,i,j,N,::Val{false}) = @loop r[I-δ(j,I),i] += -ϕuR(j,CI(I,i),u,ϕ(i,CI(I,j),u)) + ν*(j,CI(I,i),u) over I slice(N,N[j],j,2)
56+
lowerBoundary!(r,u,Φ,ν,i,j,N,λ,::Val{false}) = @loop r[I,i] += ϕuL(j,CI(I,i),u,ϕ(i,CI(I,j),u)) - ν*(j,CI(I,i),u) over I slice(N,2,j,2)
57+
upperBoundary!(r,u,Φ,ν,i,j,N,λ,::Val{false}) = @loop r[I-δ(j,I),i] += -ϕuR(j,CI(I,i),u,ϕ(i,CI(I,j),u)) + ν*(j,CI(I,i),u) over I slice(N,N[j],j,2)
5658

5759
# Periodic BC Building block
58-
lowerBoundary!(r,u,Φ,ν,i,j,N,::Val{true}) = @loop (
59-
Φ[I] = ϕuP(j,CIj(j,CI(I,i),N[j]-2),CI(I,i),u,ϕ(i,CI(I,j),u)) -ν*(j,CI(I,i),u); r[I,i] += Φ[I]) over I slice(N,2,j,2)
60-
upperBoundary!(r,u,Φ,ν,i,j,N,::Val{true}) = @loop r[I-δ(j,I),i] -= Φ[CIj(j,I,2)] over I slice(N,N[j],j,2)
60+
lowerBoundary!(r,u,Φ,ν,i,j,N,λ,::Val{true}) = @loop (
61+
Φ[I] = ϕuP(j,CIj(j,CI(I,i),N[j]-2),CI(I,i),u,ϕ(i,CI(I,j),u)) -ν*(j,CI(I,i),u); r[I,i] += Φ[I]) over I slice(N,2,j,2)
62+
upperBoundary!(r,u,Φ,ν,i,j,N,λ,::Val{true}) = @loop r[I-δ(j,I),i] -= Φ[CIj(j,I,2)] over I slice(N,N[j],j,2)
6163

6264
"""
6365
accelerate!(r,t,g,U)
@@ -137,24 +139,24 @@ function project!(a::Flow{n},b::AbstractPoisson,w=1) where n
137139
end
138140

139141
"""
140-
mom_step!(a::Flow,b::AbstractPoisson)
142+
mom_step!(a::Flow,b::AbstractPoisson;λ=quick,udf=nothing,kwargs...)
141143
142144
Integrate the `Flow` one time step using the [Boundary Data Immersion Method](https://eprints.soton.ac.uk/369635/)
143145
and the `AbstractPoisson` pressure solver to project the velocity onto an incompressible flow.
144146
"""
145-
@fastmath function mom_step!(a::Flow{N},b::AbstractPoisson;udf=nothing,kwargs...) where N
147+
@fastmath function mom_step!(a::Flow{N},b::AbstractPoisson;λ=quick,udf=nothing,kwargs...) where N
146148
a.u⁰ .= a.u; scale_u!(a,0); t₁ = sum(a.Δt); t₀ = t₁-a.Δt[end]
147149
# predictor u → u'
148150
@log "p"
149-
conv_diff!(a.f,a.u⁰,a.σ,ν=a.ν,perdir=a.perdir)
151+
conv_diff!(a.f,a.u⁰,a.σ,λ;ν=a.ν,perdir=a.perdir)
150152
udf!(a,udf,t₀; kwargs...)
151153
accelerate!(a.f,t₀,a.g,a.uBC)
152154
BDIM!(a); BC!(a.u,a.uBC,a.exitBC,a.perdir,t₁) # BC MUST be at t₁
153155
a.exitBC && exitBC!(a.u,a.u⁰,a.Δt[end]) # convective exit
154156
project!(a,b); BC!(a.u,a.uBC,a.exitBC,a.perdir,t₁)
155157
# corrector u → u¹
156158
@log "c"
157-
conv_diff!(a.f,a.u,a.σ,ν=a.ν,perdir=a.perdir)
159+
conv_diff!(a.f,a.u,a.σ,λ;ν=a.ν,perdir=a.perdir)
158160
udf!(a,udf,t₁; kwargs...)
159161
accelerate!(a.f,t₁,a.g,a.uBC)
160162
BDIM!(a); scale_u!(a,0.5); BC!(a.u,a.uBC,a.exitBC,a.perdir,t₁)

src/Metrics.jl

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ Base.@propagate_inbounds @fastmath function permute(f,i)
99
f(j,k)-f(k,j)
1010
end
1111
×(a,b) = fSV(i->permute((j,k)->a[j]*b[k],i),3)
12+
@fastmath @inline function dot(a,b)
13+
init=zero(eltype(a))
14+
@inbounds for ij in eachindex(a)
15+
init += a[ij] * b[ij]
16+
end
17+
return init
18+
end
1219

1320
"""
1421
ke(I::CartesianIndex,u,U=0)
@@ -141,4 +148,60 @@ function pressure_moment(x₀,p,df,body,t=0)
141148
df .= zero(Tp)
142149
@loop df[I,:] .= p[I]*cross(loc(0,I,Tp)-x₀,nds(body,loc(0,I,Tp),t)) over I inside(p)
143150
sum(To,df,dims=ntuple(i->i,ndims(p)))[:] |> Array
151+
end
152+
153+
"""
154+
MeanFlow{T, Sf<:AbstractArray{T}, Vf<:AbstractArray{T}, Mf<:AbstractArray{T}}
155+
156+
Holds temporal averages of velocity, squared velocity, pressure, and Reynolds stresses.
157+
"""
158+
struct MeanFlow{T, Sf<:AbstractArray{T}, Vf<:AbstractArray{T}, Mf}
159+
P :: Sf # pressure scalar field
160+
U :: Vf # velocity vector field
161+
UU :: Mf # squared velocity tensor, u⊗u
162+
t :: Vector{T} # time steps vector
163+
uu_stats :: Bool # flag to compute UU on-the-fly temporal averages
164+
function MeanFlow(flow::Flow{D,T}; t_init=time(flow), uu_stats=false) where {D,T}
165+
f = typeof(flow.u).name.wrapper
166+
P = zeros(T, size(flow.p)) |> f
167+
U = zeros(T, size(flow.u)) |> f
168+
UU = uu_stats ? zeros(T, size(flow.p)...,D,D) |> f : nothing
169+
new{T,typeof(P),typeof(U),typeof(UU)}(P,U,UU,T[t_init],uu_stats)
170+
end
171+
end
172+
173+
time(meanflow::MeanFlow) = meanflow.t[end]-meanflow.t[1]
174+
175+
function reset!(meanflow::MeanFlow; t_init=0.0)
176+
fill!(meanflow.P, 0); fill!(meanflow.U, 0)
177+
!isnothing(meanflow.UU) && fill!(meanflow.UU, 0)
178+
deleteat!(meanflow.t, collect(1:length(meanflow.t)))
179+
push!(meanflow.t, t_init)
180+
end
181+
182+
function update!(meanflow::MeanFlow, flow::Flow)
183+
dt = time(flow) - meanflow.t[end]
184+
ε = dt / (dt + (meanflow.t[end] - meanflow.t[1]) + eps(eltype(flow.p)))
185+
@loop meanflow.P[I] = ε * flow.p[I] + (1 - ε) * meanflow.P[I] over I in CartesianIndices(flow.p)
186+
@loop meanflow.U[Ii] = ε * flow.u[Ii] + (1 - ε) * meanflow.U[Ii] over Ii in CartesianIndices(flow.u)
187+
if meanflow.uu_stats
188+
for i in 1:ndims(flow.p), j in 1:ndims(flow.p)
189+
@loop meanflow.UU[I,i,j] = ε * (flow.u[I,i] .* flow.u[I,j]) + (1 - ε) * meanflow.UU[I,i,j] over I in CartesianIndices(flow.p)
190+
end
191+
end
192+
push!(meanflow.t, meanflow.t[end] + dt)
193+
end
194+
195+
uu!(τ,a::MeanFlow) = for i in 1:ndims(a.P), j in 1:ndims(a.P)
196+
@loop τ[I,i,j] = a.UU[I,i,j] - a.U[I,i,j] * a.U[I,i,j] over I in CartesianIndices(a.P)
197+
end
198+
function uu(a::MeanFlow)
199+
τ = zeros(eltype(a.UU), size(a.UU)...) |> typeof(meanflow.UU).name.wrapper
200+
uu!(τ,a)
201+
return τ
202+
end
203+
204+
function copy!(a::Flow, b::MeanFlow)
205+
a.u .= b.U
206+
a.p .= b.P
144207
end

src/WaterLily.jl

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ include("MultiLevelPoisson.jl")
1818
export MultiLevelPoisson,solver!,mult!
1919

2020
include("Flow.jl")
21-
export Flow,mom_step!
21+
export Flow,mom_step!,quick,cds
2222

2323
include("Body.jl")
2424
export AbstractBody,measure_sdf!
@@ -27,6 +27,7 @@ include("AutoBody.jl")
2727
export AutoBody,Bodies,measure,sdf,+,-
2828

2929
include("Metrics.jl")
30+
export MeanFlow
3031

3132
abstract type AbstractSimulation end
3233
"""
@@ -88,24 +89,29 @@ scales.
8889
sim_time(sim::AbstractSimulation) = time(sim)*sim.U/sim.L
8990

9091
"""
91-
sim_step!(sim::Simulation,t_end=sim(time)+Δt;max_steps=typemax(Int),remeasure=true,verbose=false)
92+
sim_step!(sim::AbstractSimulation,t_end;remeasure=true,λ=quick,max_steps=typemax(Int),verbose=false,
93+
udf=nothing,meanflow=nothing,kwargs...)
9294
9395
Integrate the simulation `sim` up to dimensionless time `t_end`.
94-
If `remeasure=true`, the body is remeasured at every time step.
95-
Can be set to `false` for static geometries to speed up simulation.
96+
If `remeasure=true`, the body is remeasured at every time step. Can be set to `false` for static geometries to speed up simulation.
9697
A user-defined function `udf` can be passed to arbitrarily modify the `::Flow` during the predictor and corrector steps.
9798
If the `udf` user keyword arguments, these needs to be included in the `sim_step!` call as well.
99+
A `::MeanFlow` can also be passed to compute on-the-fly temporal averages.
100+
A `λ::Function` function can be passed as a custom convective scheme, following the interface of `λ(u,c,d)` (for upstream, central,
101+
downstream points).
98102
"""
99-
function sim_step!(sim::AbstractSimulation,t_end;remeasure=true,max_steps=typemax(Int),udf=nothing,verbose=false,kwargs...)
103+
function sim_step!(sim::AbstractSimulation,t_end;remeasure=true=quick,max_steps=typemax(Int),verbose=false,
104+
udf=nothing,meanflow=nothing,kwargs...)
100105
steps₀ = length(sim.flow.Δt)
101106
while sim_time(sim) < t_end && length(sim.flow.Δt) - steps₀ < max_steps
102-
sim_step!(sim; remeasure, udf, kwargs...)
107+
sim_step!(sim; remeasure, λ, udf, meanflow, kwargs...)
103108
verbose && sim_info(sim)
104109
end
105110
end
106-
function sim_step!(sim::AbstractSimulation;remeasure=true,udf=nothing,kwargs...)
111+
function sim_step!(sim::AbstractSimulation;remeasure=true,λ=quick,udf=nothing,meanflow=nothing,kwargs...)
107112
remeasure && measure!(sim)
108-
mom_step!(sim.flow, sim.pois; udf, kwargs...)
113+
mom_step!(sim.flow, sim.pois; λ, udf, kwargs...)
114+
!isnothing(meanflow) && update!(meanflow,sim.flow)
109115
end
110116

111117
"""

src/util.jl

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,22 +136,23 @@ macro loop(args...)
136136
grab!(sym,ex) # get arguments and replace composites in `ex`
137137
setdiff!(sym,[I]) # don't want to pass I as an argument
138138
symT = symtypes(sym) # generate a list of types for each symbol
139+
symWtypes = joinsymtype(rep.(sym),symT) # symbols with types: [a::A, b::B, ...]
139140
@gensym(kern, kern_) # generate unique kernel function names for serial and KA execution
140141
@static if backend == "KernelAbstractions"
141142
return quote
142-
@kernel function $kern_($(rep.(sym)...),@Const(I0)) # replace composite arguments
143+
@kernel function $kern_($(symWtypes...),@Const(I0)) where {$(symT...)} # replace composite arguments
143144
$I = @index(Global,Cartesian)
144145
$I += I0
145146
@fastmath @inbounds $ex
146147
end
147-
function $kern($(joinsymtype(rep.(sym),symT)...)) where {$(symT...)}
148+
function $kern($(symWtypes...)) where {$(symT...)}
148149
$kern_(get_backend($(sym[1])),64)($(sym...),$R[1]-oneunit($R[1]),ndrange=size($R))
149150
end
150151
$kern($(sym...))
151152
end |> esc
152153
else # backend == "SIMD"
153154
return quote
154-
function $kern($(joinsymtype(rep.(sym),symT)...)) where {$(symT...)}
155+
function $kern($(symWtypes...)) where {$(symT...)}
155156
@simd for $I $R
156157
@fastmath @inbounds $ex
157158
end
@@ -285,6 +286,39 @@ function interp(x::SVector{D}, varr::AbstractArray) where {D}
285286
return SVector{D}(interp(x+shift(i),@view(varr[..,i])) for i in 1:D)
286287
end
287288

289+
"""
290+
sgs!(flow, t; νₜ, S, Cs, Δ)
291+
292+
Implements a user-defined function `udf` to model subgrid-scale LES stresses based on the Boussinesq approximation
293+
τᵃᵢⱼ = τʳᵢⱼ - (1/3)τʳₖₖδᵢⱼ = -2νₜS̅ᵢⱼ
294+
where
295+
▁▁▁▁
296+
τʳᵢⱼ = uᵢuⱼ - u̅ᵢu̅ⱼ
297+
298+
and we add -∂ⱼ(τᵃᵢⱼ) to the RHS as a body force (the isotropic part of the tensor is automatically modelled by the pressure gradient term).
299+
Users need to define the turbulent viscosity function `νₜ` and pass it as a keyword argument to this function together with rate-of-strain
300+
tensor array buffer `S`, Smagorinsky constant `Cs`, and filter width `Δ`.
301+
For example, the standard Smagorinsky–Lilly model for the sub-grid scale stresses is
302+
303+
νₜ = (CₛΔ)²|S̅ᵢⱼ|=(CₛΔ)²√(2S̅ᵢⱼS̅ᵢⱼ)
304+
305+
It can be implemented as
306+
`smagorinsky(I::CartesianIndex{m} where m; S, Cs, Δ) = @views (Cs*Δ)^2*sqrt(dot(S[I,:,:],S[I,:,:]))`
307+
and passed into `sim_step!` as a keyword argument together with the varibles than the function needs (`S`, `Cs`, and `Δ`):
308+
`sim_step!(sim, ...; udf=sgs, νₜ=smagorinsky, S, Cs, Δ)`
309+
"""
310+
function sgs!(flow, t; νₜ, S, Cs, Δ)
311+
N,n = size_u(flow.u)
312+
@loop S[I,:,:] .= WaterLily.S(I,flow.u) over I inside(flow.σ)
313+
for i 1:n, j 1:n
314+
WaterLily.@loop (
315+
flow.σ[I] = -νₜ(I;S,Cs,Δ)*(j,CI(I,i),flow.u);
316+
flow.f[I,i] += flow.σ[I];
317+
) over I inside_u(N,j)
318+
WaterLily.@loop flow.f[I-δ(j,I),i] -= flow.σ[I] over I WaterLily.inside_u(N,j)
319+
end
320+
end
321+
288322
check_fn(f,N,T,nargs) = nothing
289323
function check_fn(f::Function,N,T,nargs)
290324
@assert first(methods(f)).nargs==nargs+1 "$f signature needs $nargs arguments"
@@ -296,4 +330,4 @@ xtargs(::Val{3},N,T) = (zeros(SVector{N,T}),zero(T))
296330
ic_function(uBC::Function) = (i,x)->uBC(i,x,0)
297331
ic_function(uBC::Tuple) = (i,x)->uBC[i]
298332

299-
squeeze(a::AbstractArray) = dropdims(a, dims = tuple(findall(size(a) .== 1)...))
333+
squeeze(a::AbstractArray) = dropdims(a, dims = tuple(findall(size(a) .== 1)...))

test/alloctest.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,19 @@ backend != "SIMD" && throw(ArgumentError("KernelAbstractions backend not allowed
1414
Simulation((20L,20L),(U,0),L,ν=U*L/Re,body=AutoBody(sdf,map),T=Float32,perdir=perdir)
1515
end
1616
sim = Sim(Float32/36))
17-
sim_step!(sim)
17+
18+
sim_step!(sim) # runs with λ=quick
1819
b = @benchmarkable mom_step!($sim.flow, $sim.pois) samples=100; tune!(b) # check 100 times
1920
r = run(b)
2021
println("▶ Allocated "*@sprintf("%.0f", r.memory/1e3)*" KiB")
2122
@test r.memory < 50000 # less than 50 KiB allocated on the best mom_step! run (commit f721343 ≈ 8 KiB)
2223

24+
sim_step!(sim; λ=cds)
25+
b = @benchmarkable mom_step!($sim.flow, $sim.pois; λ=$cds) samples=100; tune!(b) # check 100 times
26+
r = run(b)
27+
println("▶ Allocated "*@sprintf("%.0f", r.memory/1e3)*" KiB")
28+
@test r.memory < 50000 # less than 50 KiB allocated on the best mom_step! run (commit f721343 ≈ 8 KiB)
29+
2330
sim = Sim(Float32/36); perdir=(2,))
2431
sim_step!(sim)
2532
b = @benchmarkable mom_step!($sim.flow, $sim.pois) samples=100; tune!(b) # check 100 times

0 commit comments

Comments
 (0)