Skip to content

Commit 3739604

Browse files
committed
central deriv works
1 parent db01bac commit 3739604

File tree

7 files changed

+53
-36
lines changed

7 files changed

+53
-36
lines changed

src/MOL_utils.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,18 @@ function get_depvars(eq,depvar_ops)
5959
return depvars
6060
end
6161

62+
"""
63+
A function that creates a tuple of CartesianIndices of unit length and `N` dimensions, one pointing along each dimension.
64+
"""
65+
function unitindices(N::Int) #create unit CartesianIndex for each dimension
66+
out = Vector{CartesianIndex{N}}(undef, N)
67+
null = zeros(Int, N)
68+
for i in 1:N
69+
unit_i = copy(null)
70+
unit_i[i] = 1
71+
out[i] = CartesianIndex(Tuple(unit_i))
72+
end
73+
Tuple(out)
74+
end
75+
6276
half_range(x) = -div(x,2):div(x,2)

src/discretization/MOL_discretization.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function SciMLBase.symbolic_discretize(pdesys::PDESystem, discretization::Method
7272

7373
derivweights = DifferentialDiscretizer(pde, s, discretization)
7474

75-
interior = s.Igrid[[2:(length(grid[x])-1) for x in s.nottime]]
75+
interior = s.Igrid[[2:(length(s, x)-1) for x in s.nottime]]
7676

7777
### PDE EQUATIONS ###
7878
# Create a stencil in the required dimension centered around 0

src/discretization/differential_discretizer.jl

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
# Use DiffEqOperators to generate weights and calculate derivative orders
2-
struct DifferentialDiscretizer{T}
3-
approx_order
4-
map::Dict{Num, DiffEqOperators.DerivativeOperator}
2+
struct DifferentialDiscretizer{T, D1}
3+
approx_order::Int
4+
map::D1
55
nonlinlapmap::Dict{Num, NTuple{2, DiffEqOperators.DerivativeOperator}}
6-
orders::Vector{T}
6+
orders::Dict{Num, Vector{Int}}
77
end
88

99
function DifferentialDiscretizer(pde, s, discretization)
@@ -12,20 +12,20 @@ function DifferentialDiscretizer(pde, s, discretization)
1212

1313
# central_deriv_rules = [(Differential(s)^2)(u) => central_deriv(2,II,j,k) for (j,s) in enumerate(s.nottime), (k,u) in enumerate(s.vars)]
1414
differentialmap = Array{Pair{Num,DiffEqOperators.DerivativeOperator},1}()
15-
nonlinlap = Array{Pair{Num, NTuple{2,DiffEqOperators.DerivativeOperator}}}(undef, nparams(s))
15+
nonlinlap = []
1616
orders = []
1717
# Hardcoded to centered difference, generate weights for each differential
1818
# TODO: Add handling for upwinding
1919
for x in s.nottime
2020
push!(orders, x => d_orders(x))
2121
# TODO: Only generate weights for derivatives that are actually used and avoid redundant calculations
22-
rs = [(Differential(x)^d) => CompleteCenteredDifference(d, approx_order, s.dxs[x],length(s.grid[x])) for d in last(orders).second]
22+
rs = [(Differential(x)^d) => CompleteCenteredDifference(d, approx_order, s.dxs[x] ) for d in last(orders).second]
2323

2424
differentialmap = vcat(differentialmap, rs)
25-
nonlinlap[j] = (x => (CompleteHalfCenteredDifference(0, approx_order, s.dxs[x]), CompleteHalfCenteredDifference(1, approx_order, s.dxs[x])))
25+
push!(nonlinlap, x => (CompleteHalfCenteredDifference(0, approx_order, s.dxs[x]), CompleteHalfCenteredDifference(1, approx_order, s.dxs[x])))
2626
end
2727

28-
return DifferentialDiscretizer{eltype(orders)}(Dict(differentialmap), Dict(nonlinlap), Dict(orders))
28+
return DifferentialDiscretizer{eltype(orders), typeof(Dict(differentialmap))}(approx_order, Dict(differentialmap), Dict(nonlinlap), Dict(orders))
2929
end
3030

3131
# ufunc is a function that returns the correct discretization indexed at Itap, it is designed this way to allow for central differences of arbitrary expressions which may be needed in some schemes
@@ -38,9 +38,9 @@ function central_difference(D, II, s, jx, u, ufunc)
3838
weights = D.low_boundary_coefs[II[j]]
3939
offset = D.boundary_point_count - II[j] + 1
4040
Itap = [II + (i+offset)*I1 for i in half_range(D.boundary_stencil_length)]
41-
elseif II[j] > (length(x) - D.boundary_point_count)
42-
weights = D.high_boundary_coefs[length(s.grid[x])-II[j]+1]
43-
offset = length(x) - II[j] - D.boundary_point_count
41+
elseif II[j] > (length(s, x) - D.boundary_point_count)
42+
weights = D.high_boundary_coefs[length(s, x)-II[j]+1]
43+
offset = length(s, x) - II[j] - D.boundary_point_count
4444
Itap = [II + (i+offset)*I1 for i in half_range(D.boundary_stencil_length)]
4545
else
4646
weights = D.stencil_coefs
@@ -63,9 +63,9 @@ function _get_weights_and_stencil(D, II, I1, s, k, j, x)
6363
offset = D.boundary_point_count - II[j] + 1
6464
# ? Is this offset correct?
6565
Itap = [II + (i+offset)*I1 for i in half_range(D.boundary_stencil_length)]
66-
elseif II[j] > (length(x) - D.boundary_point_count - 1)
67-
weights = D.high_boundary_coefs[length(s.grid[x])-II[j]+1][k]
68-
offset = length(x) - II[j] - D.boundary_point_count
66+
elseif II[j] > (length(s, x) - D.boundary_point_count - 1)
67+
weights = D.high_boundary_coefs[length(s,x)-II[j]+1][k]
68+
offset = length(s, x) - II[j] - D.boundary_point_count
6969
Itap = [II + (i+offset)*I1 for i in half_range(D.boundary_stencil_length)]
7070
else
7171
weights = D.stencil_coefs

src/discretization/discretize_vars.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ end
3333
nparams(::DiscreteSpace{N,M}) where {N,M} = N
3434
nvars(::DiscreteSpace{N,M}) where {N,M} = M
3535

36+
Base.length(s::DiscreteSpace, x) = length(s.grid[x])
37+
Base.size(s::DiscreteSpace) = Tuple(length(s.grid[z]) for z in s.nottime)
38+
39+
params(s::DiscreteSpace{N,M}) where {N,M}= s.params
40+
3641
grid_idxs(s::DiscreteSpace) = CartesianIndices(((axes(g)[1] for g in s.grid)...,))
3742
edge_idxs(s::DiscreteSpace{N}) where {N} = reduce(vcat, [[vcat([Colon() for j = 1:i-1], 1, [Colon() for j = i+1:N]), vcat([Colon() for j = 1:i-1], length(s.axies[i]), [Colon() for j = i+1:N])] for i = 1:N])
3843

@@ -106,7 +111,7 @@ function DiscreteSpace(domain, depvars, indvars, nottime, discretization)
106111

107112
nottime2dim = [nottime[i] => i for i in 1:nspace]
108113
dim2nottime = [i => nottime[i] for i in 1:nspace]
109-
return DiscreteSpace{nspace,length(depvars)}(depvars, Dict(depvarsdisc), nottime, indvars, Dict(axies), Dict(grid), Dict(dxs), Iaxies, Igrid, Iedge, nottime2dim)
114+
return DiscreteSpace{nspace,length(depvars)}(depvars, Dict(depvarsdisc), nottime, indvars, Dict(axies), Dict(grid), Dict(dxs), Iaxies, Igrid, Iedge, Dict(nottime2dim))
110115
end
111116

112117

src/discretization/generate_finite_difference_rules.jl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -151,17 +151,14 @@ Please submit an issue if you know of any special cases that are not implemented
151151
function generate_finite_difference_rules(II, s, pde, derivweights)
152152

153153
valrules = vcat([u => s.discvars[u][II] for u in s.vars],
154-
[x => s.grid[x][II[s.x2i[x]]] for x in params(s)])
154+
[x => s.grid[x][II[j]] for (j,x) in enumerate(s.nottime)])
155155
# central_deriv_rules = [(Differential(s)^2)(u) => central_deriv(2,II,j,k) for (j,s) in enumerate(s.nottime), (k,u) in enumerate(s.vars)]
156156

157157
central_ufunc(u, I, x) = s.discvars[u][I]
158-
central_deriv_rules_cartesian = Array{Pair{Num,Num},1}()
159-
for x in s.nottime
160-
j = s.x2i[x]
161-
rs = [(Differential(x)^d)(u) => central_difference(derivweights.map[Differential(x)^d], II, s, (j,x), u, central_ufunc) for d in derivweights.orders[x], u in s.vars]
158+
159+
central_deriv_rules_cartesian = reduce(vcat, [[(Differential(x)^d)(u) => central_difference(derivweights.map[Differential(x)^d], II, s, (j,x), u, central_ufunc) for d in derivweights.orders[x], u in s.vars] for (j,x) in enumerate(s.nottime)])
160+
162161

163-
central_deriv_rules_cartesian = vcat(central_deriv_rules_cartesian, rs)
164-
end
165162

166163
# TODO: upwind rules needs interpolation into `@rule`
167164
#forward_weights(II,j) = calculate_weights(discretization.upwind_order, 0.0, s.grid[j][[II[j],II[j]+1]])
@@ -204,7 +201,6 @@ function generate_finite_difference_rules(II, s, pde, derivweights)
204201
end
205202
rules = vcat(vec(nonlinlap_rules),
206203
vec(central_deriv_rules_cartesian),
207-
vec(central_deriv_rules_spherical),
208204
valrules)
209205
return rules
210206
end

test/components/finite_diff_schemes.jl

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using ModelingToolkit, MethodOfLines, DomainSets, Test, Symbolics, SymbolicUtils
1+
using ModelingToolkit, MethodOfLines, DomainSets, Test, Symbolics, SymbolicUtils, LinearAlgebra
22

33
@parameters x, t
44
@variables u(..)
@@ -9,10 +9,9 @@ Dt = Differential(t)
99
t_min= 0.
1010
t_max = 2.0
1111
x_min = 0.
12-
x_max = 20.0
12+
x_max = 20.0
1313

1414
dx = 1.0
15-
order = 2
1615

1716
domains = [t Interval(t_min, t_max), x Interval(x_min, x_max)]
1817

@@ -22,14 +21,14 @@ domains = [t ∈ Interval(t_min, t_max), x ∈ Interval(x_min, x_max)]
2221
push!(weights, ([-0.5,0,0.5], [1.,-2.,1.], [-1/2,1.,0.,-1.,1/2]))
2322
push!(weights, ([1/12, -2/3,0,2/3,-1/12], [-1/12,4/3,-5/2,4/3,-1/12], [1/8,-1.,13/8,0.,-13/8,1.,-1/8]))
2423
for d in 1:3
25-
for a in [2,4]
24+
for (i,a) in enumerate([2,4])
2625
pde = Dt(u(t,x)) ~ Dx(d)(u(t,x))
2726
bcs = [u(0,x) ~ cos(x), u(t,0) ~ exp(-t), u(t,Float64(π)) ~ -exp(-t)]
2827

2928
@named pdesys = PDESystem(pde,bcs,domains,[t,x],[u(t,x)])
3029

31-
# Test centered order
32-
disc = MOLFiniteDifference([x=>dx], t; centered_order=order)
30+
# Test centered order
31+
disc = MOLFiniteDifference([x=>dx], t; centered_order=a)
3332

3433
depvar_ops = map(x->operation(x.val),pdesys.depvars)
3534

@@ -47,10 +46,13 @@ domains = [t ∈ Interval(t_min, t_max), x ∈ Interval(x_min, x_max)]
4746

4847
II = s.Igrid[10]
4948

49+
I1 = MethodOfLines.unitindices(1)[1]
50+
5051
rules = MethodOfLines.generate_finite_difference_rules(II, s, pde, derivweights)
51-
@show rules
52+
5253
disc_pde=substitute(pde.lhs,rules) ~ substitute(pde.rhs,rules)
53-
@show disc_pde
54+
55+
@test disc_pde.rhs == dot(weights[i][d], s.discvars[depvars[1]][[II + j*I1 for j in MethodOfLines.half_range(length(weights[i][d]))]])
5456
end
5557
end
5658
end

test/runtests.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ const is_TRAVIS = haskey(ENV,"TRAVIS")
88

99
@time begin
1010

11-
if GROUP == "All" || GROUP == "Component Tests"
12-
@time @safetestset "Test for regression against original code" begin include("regression_test.jl") end
13-
@time @safetestset "MOLFiniteDifference Utils" begin include("utils_test.jl") end
14-
end
11+
# if GROUP == "All" || GROUP == "Component Tests"
12+
# @time @safetestset "Test for regression against original code" begin include("regression_test.jl") end
13+
# @time @safetestset "MOLFiniteDifference Utils" begin include("utils_test.jl") end
14+
# end
1515

1616
if GROUP == "All" || GROUP == "Integration Tests"
1717
@time @safetestset "MOLFiniteDifference Interface" begin include("pde_systems/MOLtest.jl") end

0 commit comments

Comments
 (0)