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

Commit cd9bb90

Browse files
Merge pull request #309 from archermarx/seperate_upwind_order
Fix higher order upwind differences and separate centered and upwind order specification in MOLFiniteDifference
2 parents e5b5d07 + 38884ac commit cd9bb90

3 files changed

Lines changed: 37 additions & 15 deletions

File tree

src/MOL_discretization.jl

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,21 @@ using ModelingToolkit: operation, istree, arguments
22
# Method of lines discretization scheme
33
struct MOLFiniteDifference{T} <: DiffEqBase.AbstractDiscretization
44
dxs::T
5-
order::Int
6-
MOLFiniteDifference(args...;order=2) = new{typeof(args[1])}(args[1],order)
5+
upwind_order::Int
6+
centered_order::Int
7+
end
8+
9+
# Constructors. If no order is specified, both upwind and centered differences will be 2nd order
10+
MOLFiniteDifference(dxs::T, order) where T =
11+
MOLFiniteDifference{T}(dxs, order, order)
12+
13+
function MOLFiniteDifference(dxs::T; order = nothing, upwind_order = 1,
14+
centered_order = 2) where T
15+
MOLFiniteDifference(
16+
dxs,
17+
order === nothing ? upwind_order : order,
18+
order === nothing ? centered_order : order
19+
)
720
end
821

922
function throw_bc_err(bc)
@@ -147,7 +160,7 @@ end
147160
# E.g., Dx(u(t,x))=v(t,x)*Dx(u(t,x)), v(t,x)=t*x
148161
# => Dx(u(t,x))=t*x*Dx(u(t,x))
149162

150-
function discretize_2(input,deriv_order,approx_order,dx,X,len_of_indep_vars,
163+
function discretize_2(input,deriv_order,upwind_order,centered_order,dx,X,len_of_indep_vars,
151164
deriv_var,dep_var_idx,indep_var_idx)
152165
if !(input isa ModelingToolkit.Symbolic)
153166
return :($(input))
@@ -171,30 +184,29 @@ function discretize_2(input,deriv_order,approx_order,dx,X,len_of_indep_vars,
171184
elseif deriv_order == 1
172185
# TODO: approx_order and forward/backward should be
173186
# input parameters of each derivative
174-
approx_order = 1
175-
L = UpwindDifference(deriv_order,approx_order,dx[i],len_of_indep_vars[i]-2,-1)
187+
L = UpwindDifference(deriv_order,upwind_order,dx[i],len_of_indep_vars[i]-2,-1)
176188
expr = :(-1*($L*Q[$j]*u[:,$j]))
177189
elseif deriv_order == 2
178-
L = CenteredDifference(deriv_order,approx_order,dx[i],len_of_indep_vars[i]-2)
190+
L = CenteredDifference(deriv_order,centered_order,dx[i],len_of_indep_vars[i]-2)
179191
expr = :($L*Q[$j]*u[:,$j])
180192
end
181193
end
182194
return expr
183195
elseif istree(input) && operation(input) isa Differential
184196
var = nameof(input.op.x)
185197
push!(deriv_var,var)
186-
return discretize_2(input.args[1],deriv_order+1,approx_order,dx,X,
198+
return discretize_2(arguments(input)[1],deriv_order+1,upwind_order,centered_order,dx,X,
187199
len_of_indep_vars,deriv_var,dep_var_idx,indep_var_idx)
188200
else
189201
name = nameof(operation(input))
190-
if size(input.args,1) == 1
191-
aux = discretize_2(input.args[1],deriv_order,approx_order,dx,X,
202+
if size(arguments(input),1) == 1
203+
aux = discretize_2(arguments(input)[1],deriv_order,upwind_order,centered_order,dx,X,
192204
len_of_indep_vars,deriv_var,dep_var_idx,indep_var_idx)
193205
return :(broadcast($name, $aux))
194206
else
195-
aux_1 = discretize_2(input.args[1],deriv_order,approx_order,dx,X,
207+
aux_1 = discretize_2(arguments(input)[1],deriv_order,upwind_order,centered_order,dx,X,
196208
len_of_indep_vars,deriv_var,dep_var_idx,indep_var_idx)
197-
aux_2 = discretize_2(input.args[2],deriv_order,approx_order,dx,X,
209+
aux_2 = discretize_2(arguments(input)[2],deriv_order,upwind_order,centered_order,dx,X,
198210
len_of_indep_vars,deriv_var,dep_var_idx,indep_var_idx)
199211
return :(broadcast($name, $aux_1, $aux_2))
200212
end
@@ -257,7 +269,8 @@ function DiffEqBase.discretize(pdesys::PDESystem,discretization::MOLFiniteDiffer
257269
### Declare and define dependent-variable data structures #################
258270

259271
# TODO: specify order for each derivative
260-
approx_order = discretization.order
272+
upwind_order = discretization.upwind_order
273+
centered_order = discretization.centered_order
261274

262275
lhs_deriv_depvars = Dict()
263276
dep_var_idx = Dict()
@@ -282,7 +295,7 @@ function DiffEqBase.discretize(pdesys::PDESystem,discretization::MOLFiniteDiffer
282295
dep_var_idx[var] = j
283296
end
284297
for (var,j) in dep_var_idx
285-
aux = discretize_2( eqs[j].rhs,0,approx_order,dx,X,len_of_indep_vars,
298+
aux = discretize_2( eqs[j].rhs,0,upwind_order,centered_order,dx,X,len_of_indep_vars,
286299
[],dep_var_idx,indep_var_idx)
287300
dep_var_disc[var] = @RuntimeGeneratedFunction(:((Q,u,t) -> $aux))
288301
end

test/MOL_1D_Linear_Convection.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,17 @@ using ModelingToolkit,DiffEqOperators,DiffEqBase,LinearAlgebra,Test
2929
dx = 2/80
3030
order = 1
3131
discretization = MOLFiniteDifference(dx,order)
32+
# explicitly specify upwind order
33+
discretization_upwind = MOLFiniteDifference(dx; upwind_order=order)
3234

3335
# Convert the PDE problem into an ODE problem
3436
prob = discretize(pdesys,discretization)
37+
prob_upwind = discretize(pdesys, discretization_upwind)
3538

3639
# Solve ODE problem
3740
using OrdinaryDiffEq
3841
sol = solve(prob,Euler(),dt=.025,saveat=0.1)
42+
sol_upwind = solve(prob_upwind,Euler(),dt=.025,saveat=0.1)
3943

4044
# Plot and save results
4145
# using Plots
@@ -53,8 +57,7 @@ using ModelingToolkit,DiffEqOperators,DiffEqBase,LinearAlgebra,Test
5357
t_f = size(sol,3)
5458

5559
@test sol[:,1,t_f] u atol = 0.1;
56-
57-
60+
@test sol_upwind[:,1,t_f] u atol = 0.1;
5861
end
5962

6063
@testset "Test 01: Dt(u(t,x)) ~ -Dx(u(t,x)) + 0.01" begin

test/MOL_1D_Linear_Diffusion.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,16 @@ using ModelingToolkit: Differential
3434
dx = 0.1
3535
order = 2
3636
discretization = MOLFiniteDifference(dx,order)
37+
# Explicitly specify order of centered difference
38+
discretization_centered = MOLFiniteDifference(dx; centered_order=order)
3739

3840
# Convert the PDE problem into an ODE problem
3941
prob = discretize(pdesys,discretization)
42+
prob_centered = discretize(pdesys,discretization_centered)
4043

4144
# Solve ODE problem
4245
sol = solve(prob,Tsit5(),saveat=0.1)
46+
sol_centered = solve(prob_centered,Tsit5(),saveat=0.1)
4347
x = prob.space[2]
4448
t = sol.t
4549

@@ -55,7 +59,9 @@ using ModelingToolkit: Differential
5559
# Test against exact solution
5660
for i in 1:size(t,1)
5761
u_approx = Array(prob.extrapolation[1](t[i])*sol.u[i])
62+
u_approx_centered = Array(prob.extrapolation[1](t[i])*sol_centered.u[i])
5863
@test u_approx u_exact(x, t[i]) atol=0.01
64+
@test u_approx_centered u_exact(x, t[i]) atol=0.01
5965
end
6066
end
6167

0 commit comments

Comments
 (0)