Skip to content

Commit 094a4f9

Browse files
hermite-based weights of Finite difference(2020)
1 parent 9f9f446 commit 094a4f9

File tree

1 file changed

+33
-12
lines changed

1 file changed

+33
-12
lines changed

src/discretization/fornberg.jl

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
1-
#############################################################
2-
# Fornberg algorithm
3-
4-
# This implements the Fornberg (1988) algorithm (https://doi.org/10.1090/S0025-5718-1988-0935077-0)
5-
# to obtain Finite Difference weights over arbitrary points to arbitrary order.
6-
7-
function calculate_weights(order::Int, x0::T, x::AbstractVector) where T<:Real
8-
#=
1+
#= Fornberg algorithm
2+
This implements the Fornberg (1988) algorithm (https://doi.org/10.1090/S0025-5718-1988-0935077-0)
3+
and hermite-based finite difference Fornberg(2020) algorithm (https://doi.org/10.1093/imanum/draa006)
4+
to obtain Finite Difference weights over arbitrary points to arbitrary order.
5+
Inputs:
96
order: The derivative order for which we need the coefficients
107
x0 : The point in the array 'x' for which we need the coefficients
118
x : A dummy array with relative coordinates, e.g., central differences
129
need coordinates centred at 0 while those at boundaries need
1310
coordinates starting from 0 to the end point
11+
dfdx : optional argument to consider weights of the first-derivative of function or not
12+
if dfdx == false (default kwarg), implies Fornberg(1988)
13+
dfdx == true, implies Fornberg(2020)
14+
Outputs:
15+
if dfdx == false (default kwarg), _C : weights to approximate derivative of required order using function values only.
16+
else, _D,_E : weights to approximate derivative of required order using function and its first-
17+
derivative values respectively.
18+
=#
1419

15-
The approximation order of the stencil is automatically determined from
16-
the number of requested stencil points.
17-
=#
20+
function calculate_weights(order::Int, x0::T, x::AbstractVector) where T<:Real
1821
N = length(x)
1922
@assert order < N "Not enough points for the requested order."
2023
M = order
@@ -58,5 +61,23 @@ function calculate_weights(order::Int, x0::T, x::AbstractVector) where T<:Real
5861
if order != 0
5962
_C[div(N,2)+1] -= sum(_C)
6063
end
61-
return _C
64+
if dfdx == false
65+
return _C
66+
else
67+
A = x .- x';
68+
s = sum(1 ./ (A + I(N)), dims = 1) .- 1;
69+
cp = factorial.(0:M);
70+
cc = C./cp'
71+
= zeros(N, M+2);
72+
for k in 1:M+1
73+
c̃[:,k+1] = sum(cc[:,1:k].*cc[:,k:-1:1], dims = 2);
74+
end
75+
E = c̃[:,1:M+1] - (x .- x0).*c̃[:,2:M+2];
76+
D = c̃[:,2:M+2] + 2*E.*s';
77+
D = D.*cp';
78+
E = E.*cp';
79+
80+
_D = D[:,end]; _E = E[:,end]
81+
return _D, _E
82+
end
6283
end

0 commit comments

Comments
 (0)