@@ -105,6 +105,8 @@ function CenteredDifference{N}(derivative_order::Int,
105105 )
106106end
107107
108+
109+
108110function generate_coordinates (i:: Int , stencil_x, dummy_x, dx:: AbstractVector{T} ) where T <: Real
109111 len = length (stencil_x)
110112 stencil_x .= stencil_x.* zero (T)
@@ -161,6 +163,98 @@ function CenteredDifference{N}(derivative_order::Int,
161163 )
162164end
163165
166+
167+ # TODO : Set weight to zero if its below a certain threshold
168+ """
169+ A helper function to compute the coefficients of a derivative operator including the boundary coefficients in the centered scheme.
170+ """
171+ function CompleteCenteredDifference (derivative_order:: Int ,
172+ approximation_order:: Int , dx:: T ) where {T<: Real ,N}
173+ @assert approximation_order> 1 " approximation_order must be greater than 1."
174+ stencil_length = derivative_order + approximation_order - 1 + (derivative_order+ approximation_order)% 2
175+ boundary_stencil_length = derivative_order + approximation_order
176+ dummy_x = - div (stencil_length,2 ) : div (stencil_length,2 )
177+ left_boundary_x = 0 : (boundary_stencil_length- 1 )
178+ right_boundary_x = reverse (- boundary_stencil_length+ 1 : 0 )
179+
180+ boundary_point_count = div (stencil_length,2 ) # -1 due to the ghost point
181+ # 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.
182+ # deriv_spots = (-div(stencil_length,2)+1) : -1 # unused
183+ L_boundary_deriv_spots = left_boundary_x[1 : div (stencil_length,2 )]
184+
185+ stencil_coefs = convert (SVector{stencil_length, T}, (1 / dx^ derivative_order) * calculate_weights (derivative_order, zero (T), dummy_x))
186+ _low_boundary_coefs = SVector{boundary_stencil_length, T}[convert (SVector{boundary_stencil_length, T}, (1 / dx^ derivative_order) * calculate_weights (derivative_order, oneunit (T)* x0, left_boundary_x)) for x0 in L_boundary_deriv_spots]
187+ low_boundary_coefs = convert (SVector{boundary_point_count},vcat (_low_boundary_coefs))
188+
189+ # _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]
190+ high_boundary_coefs = convert (SVector{boundary_point_count},[reverse (v)* (- 1 )^ derivative_order for v in _low_boundary_coefs])
191+
192+ offside = 0
193+
194+ coefficients = nothing
195+
196+
197+ DerivativeOperator{T,Nothing,false ,T,typeof (stencil_coefs),
198+ typeof (low_boundary_coefs),typeof (high_boundary_coefs),typeof (coefficients),
199+ Nothing}(
200+ derivative_order, approximation_order, dx, 1 , stencil_length,
201+ stencil_coefs,
202+ boundary_stencil_length,
203+ boundary_point_count,
204+ low_boundary_coefs,
205+ high_boundary_coefs,offside,coefficients,nothing
206+ )
207+ end
208+
209+
210+ """
211+ 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
212+ """
213+ function CompleteHalfCenteredDifference (derivative_order:: Int ,
214+ approximation_order:: Int , dx:: T ) where {T<: Real ,N}
215+ @assert approximation_order> 1 " approximation_order must be greater than 1."
216+ centered_stencil_length = approximation_order + 2 * Int (floor (derivative_order/ 2 )) + (approximation_order% 2 )
217+ boundary_stencil_length = derivative_order + approximation_order
218+ endpoint = div (centered_stencil_length, 2 )
219+ dummy_x = 1 - endpoint : endpoint
220+ left_boundary_x = 1 : (boundary_stencil_length)
221+ right_boundary_x = reverse (- boundary_stencil_length: - 1 )
222+
223+ boundary_point_count = div (centered_stencil_length,2 ) # -1 due to the ghost point
224+ # ? Is fornberg valid when taking an x0 outside of the stencil i.e at the boundary?
225+ xoffset = range (1.5 , length= boundary_point_count, step = 1.0 )
226+
227+ # 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.
228+ # deriv_spots = (-div(stencil_length,2)+1) : -1 # unused
229+ L_boundary_deriv_spots = xoffset[1 : div (centered_stencil_length,2 )]
230+
231+ stencil_coefs = convert (SVector{centered_stencil_length, T}, (1 / dx^ derivative_order) * calculate_weights (derivative_order, convert (T, 0.5 ), dummy_x))
232+ # For each boundary point, for each tappoint in the half offset central difference stencil, we need to calculate the coefficients for the stencil.
233+
234+
235+ _low_boundary_coefs = [convert (SVector{boundary_stencil_length, T}, (1 / dx^ derivative_order) * calculate_weights (derivative_order, offset, left_boundary_x)) for offset in L_boundary_deriv_spots]
236+ low_boundary_coefs = convert (SVector{boundary_point_count}, _low_boundary_coefs)
237+
238+ _high_boundary_coefs = [reverse (stencil)* (- 1 )^ derivative_order for stencil in low_boundary_coefs]
239+ high_boundary_coefs = convert (SVector{boundary_point_count}, _high_boundary_coefs)
240+ # _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]
241+
242+ offside = 0
243+
244+ coefficients = nothing
245+
246+
247+ DerivativeOperator{T,Nothing,false ,T,typeof (stencil_coefs),
248+ typeof (low_boundary_coefs),typeof (high_boundary_coefs),typeof (coefficients),Nothing}(
249+ derivative_order, approximation_order, dx, 1 , centered_stencil_length,
250+ stencil_coefs,
251+ boundary_stencil_length,
252+ boundary_point_count,
253+ low_boundary_coefs,
254+ high_boundary_coefs,offside,coefficients,nothing
255+ )
256+ end
257+
164258struct UpwindDifference{N} end
165259
166260"""
@@ -287,6 +381,50 @@ function UpwindDifference{N}(derivative_order::Int,
287381 )
288382end
289383
384+ """
385+ A helper function to compute the coefficients of a derivative operator including the boundary coefficients in the upwind scheme.
386+ """
387+ function CompleteUpwindDifference (derivative_order:: Int ,
388+ approximation_order:: Int , dx:: T ,
389+ offside:: Int = 0 ) where {T<: Real ,N}
390+
391+ @assert offside > - 1 " Number of offside points should be non-negative"
392+ @assert offside <= div (derivative_order + approximation_order - 1 ,2 ) " Number of offside points should not exceed the primary wind points"
393+
394+ stencil_length = derivative_order + approximation_order
395+ boundary_stencil_length = derivative_order + approximation_order
396+ boundary_point_count = boundary_stencil_length - 1 - offside
397+
398+ # TODO : Clean up the implementation here so that it is more readable and easier to extend in the future
399+ dummy_x = (0.0 - offside) : stencil_length - 1.0 - offside
400+ stencil_coefs = convert (SVector{stencil_length, T}, (1 / dx^ derivative_order) * calculate_weights (derivative_order, 0.0 , dummy_x))
401+
402+ low_boundary_x = 0.0 : (boundary_stencil_length- 1 )
403+ L_boundary_deriv_spots = 0.0 : boundary_stencil_length - 2.0 - offside
404+ _low_boundary_coefs = SVector{boundary_stencil_length, T}[convert (SVector{boundary_stencil_length, T}, (1 / dx^ derivative_order) * calculate_weights (derivative_order, oneunit (T)* x0, low_boundary_x)) for x0 in L_boundary_deriv_spots]
405+ low_boundary_coefs = convert (SVector{boundary_point_count},_low_boundary_coefs)
406+
407+ high_boundary_x = 0.0 : - 1.0 : - (boundary_stencil_length- 1.0 )
408+ R_boundary_deriv_spots = 0.0 : - 1.0 : - (boundary_stencil_length- 2.0 )
409+ _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, high_boundary_x)) for x0 in R_boundary_deriv_spots]
410+ high_boundary_coefs = convert (SVector{boundary_point_count + offside},_high_boundary_coefs)
411+
412+ coefficients = fill! (Vector {T} (undef,len),0 )
413+
414+
415+ DerivativeOperator{T,N,true ,T,typeof (stencil_coefs),
416+ typeof (low_boundary_coefs),typeof (high_boundary_coefs),Vector{T},
417+ typeof (coeff_func)}(
418+ derivative_order, approximation_order, dx, len, stencil_length,
419+ stencil_coefs,
420+ boundary_stencil_length,
421+ boundary_point_count,
422+ low_boundary_coefs,
423+ high_boundary_coefs,offside,coefficients,coeff_func
424+ )
425+ end
426+
427+
290428CenteredDifference (args... ) = CenteredDifference {1} (args... )
291429UpwindDifference (args... ;kwargs... ) = UpwindDifference {1} (args... ;kwargs... )
292430nonlinear_diffusion (args... ) = nonlinear_diffusion {1} (args... )
0 commit comments