Skip to content
This repository was archived by the owner on Jul 19, 2023. It is now read-only.

Commit 5fb77ac

Browse files
committed
began nonuniform
1 parent a057e8e commit 5fb77ac

File tree

1 file changed

+95
-10
lines changed

1 file changed

+95
-10
lines changed

src/derivative_operators/derivative_operator.jl

Lines changed: 95 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ function nonlinear_diffusion!{N}(du::AbstractVector{T}, second_differential_orde
3737
#p is given as some function of q , p being the diffusion coefficient
3838

3939
@assert approx_order>1 "approximation_order must be greater than 1."
40-
if first_differential_order > 0
40+
if first_differential_order > 0
4141
du .= (CenteredDifference{N}(first_differential_order,approx_order,dx,nknots)*q).*(CenteredDifference{N}(second_differential_order,approx_order,dx,nknots)*p)
42-
else
42+
else
4343
du .= q[2:(nknots + 1)].*(CenteredDifference{N}(second_differential_order,approx_order,dx,nknots)*p)
4444
end
4545

@@ -88,10 +88,10 @@ function CenteredDifference{N}(derivative_order::Int,
8888
offside = 0
8989

9090
coefficients = fill!(Vector{T}(undef,len),0)
91-
91+
9292
compute_coeffs!(coeff_func, coefficients)
93-
94-
93+
94+
9595

9696
DerivativeOperator{T,N,false,T,typeof(stencil_coefs),
9797
typeof(low_boundary_coefs),typeof(high_boundary_coefs),typeof(coefficients),
@@ -148,8 +148,8 @@ function CenteredDifference{N}(derivative_order::Int,
148148
coefficients = zeros(T,len)
149149

150150
compute_coeffs!(coeff_func, coefficients)
151-
152-
151+
152+
153153
DerivativeOperator{T,N,false,typeof(dx),typeof(stencil_coefs),
154154
typeof(low_boundary_coefs),typeof(high_boundary_coefs),typeof(coefficients),
155155
typeof(coeff_func)}(
@@ -206,6 +206,44 @@ function CompleteCenteredDifference(derivative_order::Int,
206206
)
207207
end
208208

209+
function CompleteCenteredDifference{N}(derivative_order::Int,
210+
approximation_order::Int, dx::AbstractVector{T}, len::Integer) where {T<:Real,N}
211+
stencil_length = derivative_order + approximation_order - 1 + (derivative_order+approximation_order)%2
212+
boundary_stencil_length = derivative_order + approximation_order
213+
stencil_x = zeros(T, stencil_length)
214+
boundary_point_count = div(stencil_length,2)
215+
216+
interior_x = boundary_point_count+1:len+2-boundary_point_count
217+
dummy_x = -div(stencil_length,2) : div(stencil_length,2)-1
218+
low_boundary_x = [zero(T); cumsum(dx[1:boundary_stencil_length-1])]
219+
high_boundary_x = cumsum(dx[end-boundary_stencil_length+1:end])
220+
# Because it's a N x (N+2) operator, the last stencil on the sides are the [b,0,x,x,x,x] stencils, not the [0,x,x,x,x,x] stencils, since we're never solving for the derivative at the boundary point.
221+
deriv_spots = (-div(stencil_length,2)+1) : -1
222+
223+
stencil_coefs = [convert(SVector{stencil_length, T}, calculate_weights(derivative_order, zero(T), generate_coordinates(i, stencil_x, dummy_x, dx))) for i in interior_x]
224+
_low_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T},
225+
calculate_weights(derivative_order, low_boundary_x[i+1], low_boundary_x)) for i in 0:boundary_point_count-1]
226+
low_boundary_coefs = convert(SVector{boundary_point_count},_low_boundary_coefs)
227+
_high_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T},
228+
calculate_weights(derivative_order, high_boundary_x[end-i], high_boundary_x)) for i in boundary_point_count+1:-1:0]
229+
high_boundary_coefs = convert(SVector{boundary_point_count},_high_boundary_coefs)
230+
231+
offside = 0
232+
coefficients = nothing
233+
234+
DerivativeOperator{T,N,false,typeof(dx),typeof(stencil_coefs),
235+
typeof(low_boundary_coefs),typeof(high_boundary_coefs),typeof(coefficients),
236+
typeof(coeff_func)}(
237+
derivative_order, approximation_order, dx,
238+
len, stencil_length,
239+
stencil_coefs,
240+
boundary_stencil_length,
241+
boundary_point_count,
242+
low_boundary_coefs,
243+
high_boundary_coefs,offside,coefficients,coeff_func
244+
)
245+
end
246+
209247

210248
"""
211249
A helper function to compute the coefficients of a derivative operator including the boundary coefficients in the half offset centered scheme. See table 2 in https://web.njit.edu/~jiang/math712/fornberg.pdf
@@ -240,7 +278,6 @@ function CompleteHalfCenteredDifference(derivative_order::Int,
240278
# _high_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T}, (1/dx^derivative_order) * calculate_weights(derivative_order, oneunit(T)*x0, reverse(right_boundary_x))) for x0 in R_boundary_deriv_spots]
241279

242280
offside = 0
243-
244281
coefficients = nothing
245282

246283

@@ -255,6 +292,54 @@ function CompleteHalfCenteredDifference(derivative_order::Int,
255292
)
256293
end
257294

295+
function CompleteHalfCenteredDifference(derivative_order::Int,
296+
approximation_order::Int, dx::T) where {T<:Real,N}
297+
@assert approximation_order > 1 "approximation_order must be greater than 1."
298+
centered_stencil_length = approximation_order + 2 * Int(floor(derivative_order / 2)) + (approximation_order % 2)
299+
boundary_stencil_length = derivative_order + approximation_order
300+
endpoint = div(centered_stencil_length, 2)
301+
x = [0.0, cumsum(dx)...]
302+
#TODO Improve interpolation
303+
hx = [(x[i] + x[i+1]) / 2 for i in 1:length(x)-1]
304+
305+
306+
low_boundary_x = @view(x[1:boundary_stencil_length])
307+
high_boundary_x = @view(x[end-boundary_stencil_length+1:end])
308+
309+
boundary_point_count = div(centered_stencil_length, 2) # -1 due to the ghost point
310+
# ? Is fornberg valid when taking an x0 outside of the stencil i.e at the boundary?
311+
312+
L_boundary_deriv_spots = hx[1:div(centered_stencil_length, 2)]
313+
# Because it's a N x (N+2) operator, the last stencil on the sides are the [b,0,x,x,x,x] stencils, not the [0,x,x,x,x,x] stencils, since we're never solving for the derivative at the boundary point.
314+
#deriv_spots = (-div(stencil_length,2)+1) : -1 # unused
315+
316+
R_boundary_deriv_spots = hx[length(hx):-1:length(hx)-div(centered_stencil_length, 2)+1]
317+
318+
stencil_coefs = [convert(SVector{centered_stencil_length,T}, calculate_weights(derivative_order, hx[i], x[i-endpoint+1:i+endpoint])) for i in endpoint+1:length(hx)-endpoint, 2)]
319+
# For each boundary point, for each tappoint in the half offset central difference stencil, we need to calculate the coefficients for the stencil.
320+
321+
322+
_low_boundary_coefs = [convert(SVector{boundary_stencil_length,T}, calculate_weights(derivative_order, offset, low_boundary_x)) for offset in L_boundary_deriv_spots]
323+
low_boundary_coefs = convert(SVector{boundary_point_count}, _low_boundary_coefs)
324+
325+
_high_boundary_coefs = [convert(SVector{boundary_stencil_length,T}, calculate_weights(derivative_order, offset, high_boundary_x)) for offset in R_boundary_deriv_spots]
326+
high_boundary_coefs = convert(SVector{boundary_point_count}, _high_boundary_coefs)
327+
# _high_boundary_coefs = SVector{boundary_stencil_length, T}[convert(SVector{boundary_stencil_length, T}, (1/dx^derivative_order) * calculate_weights(derivative_order, oneunit(T)*x0, reverse(right_boundary_x))) for x0 in R_boundary_deriv_spots]
328+
329+
offside = 0
330+
coefficients = nothing
331+
332+
DerivativeOperator{T,Nothing,false,T,typeof(stencil_coefs),
333+
typeof(low_boundary_coefs),typeof(high_boundary_coefs),typeof(coefficients),Nothing}(
334+
derivative_order, approximation_order, dx, 1, centered_stencil_length,
335+
stencil_coefs,
336+
boundary_stencil_length,
337+
boundary_point_count,
338+
low_boundary_coefs,
339+
high_boundary_coefs, offside, coefficients, nothing
340+
)
341+
end
342+
258343
struct UpwindDifference{N} end
259344

260345
"""
@@ -290,7 +375,7 @@ function UpwindDifference{N}(derivative_order::Int,
290375

291376
@assert offside > -1 "Number of offside points should be non-negative"
292377
@assert offside <= div(derivative_order + approximation_order - 1,2) "Number of offside points should not exceed the primary wind points"
293-
378+
294379
stencil_length = derivative_order + approximation_order
295380
boundary_stencil_length = derivative_order + approximation_order
296381
boundary_point_count = boundary_stencil_length - 2 - offside
@@ -357,7 +442,7 @@ function UpwindDifference{N}(derivative_order::Int,
357442

358443
# compute high_boundary_coefs: low_boundary_coefs[upwind = 1 downwind = 2, index of point]
359444
_upwind_coefs = SMatrix{1,boundary_point_count + offside}([convert(SVector{boundary_stencil_length, T}, calculate_weights(derivative_order, x[i+1], x[len-boundary_stencil_length+3:len+2])) for i in len-boundary_point_count+1-offside:len])
360-
if offside == 0
445+
if offside == 0
361446
_downwind_coefs = SMatrix{1,boundary_point_count}([convert(SVector{boundary_stencil_length,T}, calculate_weights(derivative_order, x[i+1], x[i-stencil_length+2:i+1])) for i in len-boundary_point_count+1:len])
362447
elseif offside == 1
363448
_downwind_coefs = SMatrix{1,boundary_point_count + offside}([convert(SVector{boundary_stencil_length,T}, calculate_weights(derivative_order, x[i+1], x[i-stencil_length+2+offside:i+1+offside])) for i in len-boundary_point_count+1-offside:len-offside+1])

0 commit comments

Comments
 (0)