Skip to content

Commit 081e2ac

Browse files
committed
Add option for a smooth boundary. Introduces a new default (smooth - the boundary densities now use a different formula).
1 parent d71bd29 commit 081e2ac

File tree

3 files changed

+93
-50
lines changed

3 files changed

+93
-50
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "EpithelialDynamics1D"
22
uuid = "ace8a2d7-7779-48a6-a8a4-cf6831a7e55b"
33
authors = ["Daniel VandenHeuvel <danj.vandenheuvel@gmail.com>"]
4-
version = "1.5.0"
4+
version = "1.6.0"
55

66
[deps]
77
CommonSolve = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2"

src/statistics.jl

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,25 +33,44 @@ function cell_midpoints(cell_positions::AbstractVector{T}) where {T<:Number}
3333
return x
3434
end
3535

36-
"""
37-
node_densities(cell_positions::AbstractVector{T}) where {T<:Number}
36+
@doc raw"""
37+
node_densities(cell_positions::AbstractVector{T}; smooth_boundary=true) where {T<:Number}
38+
39+
Compute the cell densities from the cell positions, assigning a density to each node. If
40+
`smooth_boundary` is true, then
41+
42+
```math
43+
q_i(t) = \begin{cases} \dfrac{2}{x_2(t)-x_1(t)} - \dfrac{2}{x_3(t)-x_1(t)} & i=1, \\[6pt]
44+
\dfrac{2}{x_{i+1}(t)-x_{i-1}(t)} & i=2,\ldots,n-1, \\[6pt]
45+
\dfrac{2}{x_n(t) - x_{n-1}(t)} - \dfrac{2}{x_n(t)-x_{n-2}(t)} & i=n. \end{cases}
46+
```
47+
48+
Otherwise,
3849
39-
Compute the cell densities from the cell positions, assigning a density to each node.
40-
The `i`th density is given by `2/(cell_positions[i+1] - cell_positions[i-1])` if
41-
`i` is not the first or last node, `1/(cell_positions[i+1] - cell_positions[i])`
42-
if `i` is the first node, and `1/(cell_positions[i] - cell_positions[i-1])` if `i`
43-
is the last node.
50+
```math
51+
q_i(t) = \begin{cases} \dfrac{1}{x_2(t)-x_1(t)} & i=1, \\[6pt]
52+
\dfrac{2}{x_{i+1}(t)-x_{i-1}(t)} & i=2,\ldots,n-1, \\[6pt]
53+
\dfrac{1}{x_n(t) - x_{n-1}(t)} & i=n. \end{cases}
54+
```
4455
4556
If you want estimates of the densities for each cell rather than at each node,
4657
see [`cell_densities`](@ref).
4758
"""
48-
function node_densities(cell_positions::AbstractVector{T}) where {T<:Number}
59+
function node_densities(cell_positions::AbstractVector{T}; smooth_boundary=true) where {T<:Number}
4960
q = similar(cell_positions)
5061
for i in eachindex(q)
5162
if i == firstindex(q)
52-
q[i] = 1 / (cell_positions[i+1] - cell_positions[i])
63+
if !smooth_boundary
64+
q[i] = 1 / (cell_positions[i+1] - cell_positions[i])
65+
else
66+
q[i] = 2 / (cell_positions[i+1] - cell_positions[i]) - 2 / (cell_positions[i+2] - cell_positions[i])
67+
end
5368
elseif i == lastindex(q)
54-
q[i] = 1 / (cell_positions[i] - cell_positions[i-1])
69+
if !smooth_boundary
70+
q[i] = 1 / (cell_positions[i] - cell_positions[i-1])
71+
else
72+
q[i] = 2 / (cell_positions[i] - cell_positions[i-1]) - 2 / (cell_positions[i] - cell_positions[i-2])
73+
end
5574
else
5675
q[i] = 2 / (cell_positions[i+1] - cell_positions[i-1])
5776
end
@@ -112,7 +131,7 @@ function get_knots(sol::ODESolution, num_knots=500)
112131
end
113132

114133
"""
115-
node_densities(sol::EnsembleSolution; num_knots=500, knots=get_knots(sol, num_knots), alpha=0.05, interp_fnc=(u, t) -> LinearInterpolation{true}(u, t))
134+
node_densities(sol::EnsembleSolution; num_knots=500, knots=get_knots(sol, num_knots), alpha=0.05, interp_fnc=(u, t) -> LinearInterpolation{true}(u, t), smooth_boundary=true)
116135
117136
Computes summary statistics for the node densities from an `EnsembleSolution` to a [`CellProblem`](@ref).
118137
@@ -126,6 +145,7 @@ Computes summary statistics for the node densities from an `EnsembleSolution` to
126145
- `knots::Vector{Vector{Float64}} = get_knots(sol, num_knots; indices, use_extrema)`: The knots to use for the spline interpolation.
127146
- `alpha::Float64 = 0.05`: The significance level for the confidence intervals.
128147
- `interp_fnc = (u, t) -> LinearInterpolation{true}(u, t)`: The function to use for constructing the interpolant.
148+
- `smooth_boundary::Bool = true`: Whether to use the smooth boundary node densities.
129149
130150
# Outputs
131151
- `q::Vector{Vector{Vector{Float64}}}`: The node densities for each cell simulation.
@@ -141,11 +161,12 @@ function node_densities(sol::EnsembleSolution;
141161
use_extrema=true,
142162
knots=get_knots(sol, num_knots; indices, use_extrema),
143163
alpha=0.05,
144-
interp_fnc=(u, t) -> LinearInterpolation{true}(u, t))
164+
interp_fnc=(u, t) -> LinearInterpolation{true}(u, t),
165+
smooth_boundary=true)
145166
q = Vector{Vector{Vector{Float64}}}(undef, length(indices))
146167
r = Vector{Vector{Vector{Float64}}}(undef, length(indices))
147168
Base.Threads.@threads for i in eachindex(indices)
148-
q[i] = node_densities.(sol[indices[i]].u)
169+
q[i] = node_densities.(sol[indices[i]].u; smooth_boundary)
149170
r[i] = sol[indices[i]].u
150171
end
151172
nt = length(first(sol))

test/step_function.jl

Lines changed: 58 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,24 @@ fig_path = normpath(@__DIR__, "..", "docs", "src", "figures")
4646

4747
# Test the cell densities
4848
cell_densities_sol = cell_densities.(sol.u)
49-
node_densities_sol = node_densities.(sol.u)
49+
node_densities_sol_nonsmooth = node_densities.(sol.u; smooth_boundary=false)
50+
node_densities_sol_smooth = node_densities.(sol.u; smooth_boundary=true)
5051
for i in eachindex(sol)
5152
r = sol.u[i]
5253
q = cell_densities_sol[i]
53-
nq = node_densities_sol[i]
54+
nq_ns = node_densities_sol_nonsmooth[i]
55+
nq_s = node_densities_sol_smooth[i]
5456
for j in eachindex(r)
5557
if j == firstindex(r)
56-
@test nq[j] 1 / (r[j+1] - r[j])
58+
@test nq_ns[j] 1 / (r[j+1] - r[j])
59+
@test nq_s[j] LinearInterpolation([1 / (r[2] - r[1]), 2 / (r[3] - r[1])], [(r[1] + r[2]) / 2, r[2]])(r[1])
5760
@test q[j] 1 / (r[j+1] - r[j])
5861
elseif j == lastindex(r)
59-
@test nq[j] 1 / (r[j] - r[j-1])
62+
@test nq_ns[j] 1 / (r[j] - r[j-1])
63+
@test nq_s[j] LinearInterpolation([2 / (r[end] - r[end-2]), 1 / (r[end] - r[end-1])], [r[end-1], (r[end-1] + r[end]) / 2])(r[end])
6064
else
61-
@test nq[j] 2 / (r[j+1] - r[j-1])
65+
@test nq_ns[j] 2 / (r[j+1] - r[j-1])
66+
@test nq_s[j] 2 / (r[j+1] - r[j-1])
6267
@test q[j] 1 / (r[j+1] - r[j])
6368
end
6469
end
@@ -70,7 +75,7 @@ fig_path = normpath(@__DIR__, "..", "docs", "src", "figures")
7075
colors = (:red, :blue, :darkgreen, :black, :orange, :magenta, :cyan, :yellow, :brown, :gray, :lightblue)
7176
ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"q(x, t)",
7277
width=600, height=300)
73-
[lines!(ax, sol.u[i], node_densities_sol[i], color=colors[i], linewidth=2) for i in eachindex(sol)]
78+
[lines!(ax, sol.u[i], node_densities_sol_smooth[i], color=colors[i], linewidth=2) for i in eachindex(sol)]
7479
[lines!(ax, x, fvm_sol.u[i], color=colors[i], linewidth=4, linestyle=:dashdot) for i in eachindex(sol)]
7580
resize_to_layout!(fig)
7681
fig_path = normpath(@__DIR__, "..", "docs", "src", "figures")
@@ -115,19 +120,24 @@ end
115120

116121
# Test the cell densities
117122
cell_densities_sol = cell_densities.(sol.u)
118-
node_densities_sol = node_densities.(sol.u)
123+
node_densities_sol_nonsmooth = node_densities.(sol.u; smooth_boundary=false)
124+
node_densities_sol_smooth = node_densities.(sol.u; smooth_boundary=true)
119125
for i in eachindex(sol)
120126
r = sol.u[i]
121127
q = cell_densities_sol[i]
122-
nq = node_densities_sol[i]
128+
nq_ns = node_densities_sol_nonsmooth[i]
129+
nq_s = node_densities_sol_smooth[i]
123130
for j in eachindex(r)
124131
if j == firstindex(r)
125-
@test nq[j] 1 / (r[j+1] - r[j])
132+
@test nq_ns[j] 1 / (r[j+1] - r[j])
133+
@test nq_s[j] LinearInterpolation([1 / (r[2] - r[1]), 2 / (r[3] - r[1])], [(r[1] + r[2]) / 2, r[2]])(r[1])
126134
@test q[j] 1 / (r[j+1] - r[j])
127135
elseif j == lastindex(r)
128-
@test nq[j] 1 / (r[j] - r[j-1])
136+
@test nq_ns[j] 1 / (r[j] - r[j-1])
137+
@test nq_s[j] LinearInterpolation([2 / (r[end] - r[end-2]), 1 / (r[end] - r[end-1])], [r[end-1], (r[end-1] + r[end]) / 2])(r[end])
129138
else
130-
@test nq[j] 2 / (r[j+1] - r[j-1])
139+
@test nq_ns[j] 2 / (r[j+1] - r[j-1])
140+
@test nq_s[j] 2 / (r[j+1] - r[j-1])
131141
@test q[j] 1 / (r[j+1] - r[j])
132142
end
133143
end
@@ -140,7 +150,7 @@ end
140150
ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"q(x, t)",
141151
title=L"(a): $q(x, t)$", titlealign=:left,
142152
width=600, height=300)
143-
[lines!(ax, sol.u[i], node_densities_sol[i], color=colors[i], linewidth=2) for i in eachindex(sol)]
153+
[lines!(ax, sol.u[i], node_densities_sol_smooth[i], color=colors[i], linewidth=2) for i in eachindex(sol)]
144154
@views [lines!(ax, x .* mb_sol.u[i][end], mb_sol.u[i][begin:(end-1)], color=colors[i], linewidth=4, linestyle=:dashdot) for i in eachindex(sol)]
145155
resize_to_layout!(fig)
146156
fig_path = normpath(@__DIR__, "..", "docs", "src", "figures")
@@ -184,26 +194,34 @@ end
184194
fvm_prob = continuum_limit(prob, 1000; proliferation=true)
185195
fvm_sol = solve(fvm_prob, TRBDF2(linsolve=KLUFactorization()), saveat=0.01)
186196

187-
q, r, means, lowers, uppers, knots = node_densities(sol)
197+
q_s, r, means_s, lowers_s, uppers_s, knots_s = node_densities(sol; smooth_boundary=true)
198+
q_ns, r_ns, means_ns, lowers_ns, uppers_ns, knots_ns = node_densities(sol; smooth_boundary=false)
199+
@test r == r_ns
188200
@inferred node_densities(sol)
189201
N, N_means, N_lowers, N_uppers = cell_numbers(sol)
190202
@inferred cell_numbers(sol)
191203
pde_N = map(eachindex(fvm_sol)) do i
192204
integrate_pde(fvm_sol, i)
193205
end
194-
@test all((LinRange(0, 30, 500)), knots)
206+
@test all((LinRange(0, 30, 500)), knots_s)
207+
@test all((LinRange(0, 30, 500)), knots_ns)
208+
@test knots_s == knots_ns
209+
knots = knots_s
195210

196211
# Test the statistics
197212
for k in rand(1:length(sol), 20)
198213
for j in rand(1:length(sol[k]), 40)
199214
for i in rand(1:length(sol[k][j]), 60)
200215
if i == 1
201-
@test q[k][j][1] 1 / (r[k][j][2] - r[k][j][1])
216+
@test q_ns[k][j][1] 1 / (r[k][j][2] - r[k][j][1])
217+
@test q_s[k][j][1] LinearInterpolation([1 / (r[k][j][2] - r[k][j][1]), 2 / (r[k][j][3] - r[k][j][1])], [(r[k][j][1] + r[k][j][2]) / 2, r[k][j][2]])(r[k][j][1])
202218
elseif i == length(sol[k][j])
203219
n = length(sol[k][j])
204-
@test q[k][j][n] 1 / (r[k][j][n] - r[k][j][n-1])
220+
@test q_ns[k][j][n] 1 / (r[k][j][n] - r[k][j][n-1])
221+
@test q_s[k][j][n] LinearInterpolation([2 / (r[k][j][end] - r[k][j][end-2]), 1 / (r[k][j][end] - r[k][j][end-1])], [r[k][j][end-1], (r[k][j][end-1] + r[k][j][end]) / 2])(r[k][j][end])
205222
else
206-
@test q[k][j][i] 2 / (r[k][j][i+1] - r[k][j][i-1])
223+
@test q_ns[k][j][i] 2 / (r[k][j][i+1] - r[k][j][i-1])
224+
@test q_s[k][j][i] 2 / (r[k][j][i+1] - r[k][j][i-1])
207225
end
208226
@test r[k][j][i] == sol[k][j][i]
209227
end
@@ -220,10 +238,14 @@ end
220238
0.0, 30.0
221239
)
222240
for i in rand(1:length(knots[j]), 50)
223-
all_q = [LinearInterpolation(q[k][j], r[k][j])(knots[j][i]) for k in eachindex(sol)]
224-
@test mean(all_q) means[j][i]
225-
@test quantile(all_q, 0.025) lowers[j][i]
226-
@test quantile(all_q, 0.975) uppers[j][i]
241+
all_q = [LinearInterpolation(q_s[k][j], r[k][j])(knots[j][i]) for k in eachindex(sol)]
242+
@test mean(all_q) means_s[j][i]
243+
@test quantile(all_q, 0.025) lowers_s[j][i]
244+
@test quantile(all_q, 0.975) uppers_s[j][i]
245+
all_q = [LinearInterpolation(q_ns[k][j], r[k][j])(knots[j][i]) for k in eachindex(sol)]
246+
@test mean(all_q) means_ns[j][i]
247+
@test quantile(all_q, 0.025) lowers_ns[j][i]
248+
@test quantile(all_q, 0.975) uppers_ns[j][i]
227249
end
228250
end
229251

@@ -236,8 +258,8 @@ end
236258
ax = Axis(fig[1, 1], xlabel=L"x", ylabel=L"q(x, t)",
237259
title=L"(a): $q(x, t)$", titlealign=:left,
238260
width=600, height=300)
239-
[band!(ax, knots[i], lowers[i], uppers[i], color=(colors[j], 0.3)) for (j, i) in enumerate(plot_idx)]
240-
[lines!(ax, knots[i], means[i], color=colors[j], linewidth=2) for (j, i) in enumerate(plot_idx)]
261+
[band!(ax, knots[i], lowers_s[i], uppers_s[i], color=(colors[j], 0.3)) for (j, i) in enumerate(plot_idx)]
262+
[lines!(ax, knots[i], means_s[i], color=colors[j], linewidth=2) for (j, i) in enumerate(plot_idx)]
241263
[lines!(ax, fvm_prob.geometry.mesh_points, fvm_sol.u[i], color=colors[j], linewidth=4, linestyle=:dashdot) for (j, i) in enumerate(plot_idx)]
242264

243265
ax = Axis(fig[1, 2], xlabel=L"t", ylabel=L"N(t)",
@@ -262,10 +284,10 @@ end
262284
for j in rand(1:length(sol[k]), 40)
263285
for i in rand(1:length(sol[k][j]), 60)
264286
if i == 1
265-
@test q[enum_k][j][1] 1 / (r[enum_k][j][2] - r[enum_k][j][1])
287+
@test q[enum_k][j][1] LinearInterpolation([1 / (r[enum_k][j][2] - r[enum_k][j][1]), 2 / (r[enum_k][j][3] - r[enum_k][j][1])], [(r[enum_k][j][1] + r[enum_k][j][2]) / 2, r[enum_k][j][2]])(r[enum_k][j][1])
266288
elseif i == length(sol[k][j])
267289
n = length(sol[k][j])
268-
@test q[enum_k][j][n] 1 / (r[enum_k][j][n] - r[enum_k][j][n-1])
290+
@test q[enum_k][j][n] LinearInterpolation([2 / (r[enum_k][j][end] - r[enum_k][j][end-2]), 1 / (r[enum_k][j][end] - r[enum_k][j][end-1])], [r[enum_k][j][end-1], (r[enum_k][j][end-1] + r[enum_k][j][end]) / 2])(r[enum_k][j][end])
269291
else
270292
@test q[enum_k][j][i] 2 / (r[enum_k][j][i+1] - r[enum_k][j][i-1])
271293
end
@@ -300,10 +322,10 @@ end
300322
for j in rand(1:length(sol[k]), 40)
301323
for i in rand(1:length(sol[k][j]), 60)
302324
if i == 1
303-
@test q[enum_k][j][1] 1 / (r[enum_k][j][2] - r[enum_k][j][1])
325+
@test q[enum_k][j][1] LinearInterpolation([1 / (r[enum_k][j][2] - r[enum_k][j][1]), 2 / (r[enum_k][j][3] - r[enum_k][j][1])], [(r[enum_k][j][1] + r[enum_k][j][2]) / 2, r[enum_k][j][2]])(r[enum_k][j][1])
304326
elseif i == length(sol[k][j])
305327
n = length(sol[k][j])
306-
@test q[enum_k][j][n] 1 / (r[enum_k][j][n] - r[enum_k][j][n-1])
328+
@test q[enum_k][j][n] LinearInterpolation([2 / (r[enum_k][j][end] - r[enum_k][j][end-2]), 1 / (r[enum_k][j][end] - r[enum_k][j][end-1])], [r[enum_k][j][end-1], (r[enum_k][j][end-1] + r[enum_k][j][end]) / 2])(r[enum_k][j][end])
307329
else
308330
@test q[enum_k][j][i] 2 / (r[enum_k][j][i+1] - r[enum_k][j][i-1])
309331
end
@@ -322,7 +344,7 @@ end
322344

323345
# Using average leading edge
324346
_indices = rand(eachindex(sol), 40)
325-
q, r, means, lowers, uppers, knots = node_densities(sol; indices=_indices, use_extrema=false)
347+
q, r, means, lowers, uppers, knots = node_densities(sol; indices=_indices, use_extrema=false, smooth_boundary=false)
326348
@inferred node_densities(sol; indices=_indices, use_extrema=false)
327349
@test all((LinRange(0, 30, 500)), knots)
328350
for (enum_k, k) in enumerate(_indices)
@@ -378,7 +400,7 @@ end
378400
mb_prob = continuum_limit(prob, 1000; proliferation=true)
379401
mb_sol = solve(mb_prob, TRBDF2(linsolve=KLUFactorization()), saveat=0.01)
380402

381-
q, r, means, lowers, uppers, knots = node_densities(sol)
403+
q, r, means, lowers, uppers, knots = node_densities(sol; smooth_boundary=true)
382404
@inferred node_densities(sol)
383405
N, N_means, N_lowers, N_uppers = cell_numbers(sol)
384406
@inferred cell_numbers(sol)
@@ -404,10 +426,10 @@ end
404426
for j in rand(1:length(sol[k]), 40)
405427
for i in rand(1:length(sol[k][j]), 60)
406428
if i == 1
407-
@test q[k][j][1] 1 / (r[k][j][2] - r[k][j][1])
429+
@test q[k][j][1] LinearInterpolation([1 / (r[k][j][2] - r[k][j][1]), 2 / (r[k][j][3] - r[k][j][1])], [(r[k][j][1] + r[k][j][2]) / 2, r[k][j][2]])(r[k][j][1])
408430
elseif i == length(sol[k][j])
409431
n = length(sol[k][j])
410-
@test q[k][j][n] 1 / (r[k][j][n] - r[k][j][n-1])
432+
@test q[k][j][n] LinearInterpolation([2 / (r[k][j][end] - r[k][j][end-2]), 1 / (r[k][j][end] - r[k][j][end-1])], [r[k][j][end-1], (r[k][j][end-1] + r[k][j][end]) / 2])(r[k][j][end])
411433
else
412434
@test q[k][j][i] 2 / (r[k][j][i+1] - r[k][j][i-1])
413435
end
@@ -469,7 +491,7 @@ end
469491

470492
# Test the statistics when restricting to a specific set of simulation indices
471493
_indices = rand(eachindex(sol), 20)
472-
q, r, means, lowers, uppers, knots = node_densities(sol; indices=_indices)
494+
q, r, means, lowers, uppers, knots = node_densities(sol; indices=_indices, smooth_boundary=false)
473495
@inferred node_densities(sol; indices=_indices)
474496
N, N_means, N_lowers, N_uppers = cell_numbers(sol; indices=_indices)
475497
@inferred cell_numbers(sol; indices=_indices)
@@ -534,10 +556,10 @@ end
534556
for j in rand(1:length(sol[k]), 40)
535557
for i in rand(1:length(sol[k][j]), 60)
536558
if i == 1
537-
@test q[enum_k][j][1] 1 / (r[enum_k][j][2] - r[enum_k][j][1])
559+
@test q[enum_k][j][1] LinearInterpolation([1 / (r[enum_k][j][2] - r[enum_k][j][1]), 2 / (r[enum_k][j][3] - r[enum_k][j][1])], [(r[enum_k][j][1] + r[enum_k][j][2]) / 2, r[enum_k][j][2]])(r[enum_k][j][1])
538560
elseif i == length(sol[k][j])
539561
n = length(sol[k][j])
540-
@test q[enum_k][j][n] 1 / (r[enum_k][j][n] - r[enum_k][j][n-1])
562+
@test q[enum_k][j][n] LinearInterpolation([2 / (r[enum_k][j][end] - r[enum_k][j][end-2]), 1 / (r[enum_k][j][end] - r[enum_k][j][end-1])], [r[enum_k][j][end-1], (r[enum_k][j][end-1] + r[enum_k][j][end]) / 2])(r[enum_k][j][end])
541563
else
542564
@test q[enum_k][j][i] 2 / (r[enum_k][j][i+1] - r[enum_k][j][i-1])
543565
end
@@ -572,10 +594,10 @@ end
572594
for j in rand(1:length(sol[k]), 40)
573595
for i in 1:length(sol[k][j])
574596
if i == 1
575-
@test q[enum_k][j][1] 1 / (r[enum_k][j][2] - r[enum_k][j][1])
597+
@test q[enum_k][j][1] LinearInterpolation([1 / (r[enum_k][j][2] - r[enum_k][j][1]), 2 / (r[enum_k][j][3] - r[enum_k][j][1])], [(r[enum_k][j][1] + r[enum_k][j][2]) / 2, r[enum_k][j][2]])(r[enum_k][j][1])
576598
elseif i == length(sol[k][j])
577599
n = length(sol[k][j])
578-
@test q[enum_k][j][n] 1 / (r[enum_k][j][n] - r[enum_k][j][n-1])
600+
@test q[enum_k][j][n] LinearInterpolation([2 / (r[enum_k][j][end] - r[enum_k][j][end-2]), 1 / (r[enum_k][j][end] - r[enum_k][j][end-1])], [r[enum_k][j][end-1], (r[enum_k][j][end-1] + r[enum_k][j][end]) / 2])(r[enum_k][j][end])
579601
else
580602
@test q[enum_k][j][i] 2 / (r[enum_k][j][i+1] - r[enum_k][j][i-1])
581603
end

0 commit comments

Comments
 (0)