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

Commit ef97c3c

Browse files
Merge pull request #302 from tinosulzer/issue-283-RGF
Use RuntimeGeneratedFunctions instead of @eval and invokelatest
2 parents 56288c4 + 8af6862 commit ef97c3c

File tree

5 files changed

+35
-34
lines changed

5 files changed

+35
-34
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ deps/deps.jl
55
Manifest.toml
66
*.png
77
docs/build
8+
.vscode

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ LazyBandedMatrices = "d7e5e226-e90b-4449-9968-0f923699bf6f"
1313
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1414
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
1515
NNlib = "872c559c-99b0-510c-b3b7-b6c96a88d5cd"
16+
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
17+
RuntimeGeneratedFunctions = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47"
1618
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
1719
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
1820
SuiteSparse = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9"

src/DiffEqOperators.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import LinearAlgebra: mul!, ldiv!, lmul!, rmul!, axpy!, opnorm, factorize, I
66
import DiffEqBase: AbstractDiffEqLinearOperator, update_coefficients!, isconstant
77
using SparseArrays, ForwardDiff, BandedMatrices, NNlib, LazyArrays, BlockBandedMatrices
88
using LazyBandedMatrices, ModelingToolkit
9+
using RuntimeGeneratedFunctions
10+
RuntimeGeneratedFunctions.init(@__MODULE__)
911

1012
abstract type AbstractDiffEqAffineOperator{T} end
1113
abstract type AbstractDerivativeOperator{T} <: AbstractDiffEqLinearOperator{T} end

src/MOL_discretization.jl

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ end
99
# Get boundary conditions from an array
1010
function get_bcs(bcs,tdomain,domain)
1111
lhs_deriv_depvars_bcs = Dict()
12-
no_bcs = size(bcs,1)
13-
for i = 1:no_bcs
12+
num_bcs = size(bcs,1)
13+
for i = 1:num_bcs
1414
var = operation(bcs[i].lhs)
1515
if var isa Sym
1616
var = var.name
@@ -69,10 +69,10 @@ function discretize_2(input,deriv_order,approx_order,dx,X,len,
6969
# input parameters of each derivative
7070
approx_order = 1
7171
L = UpwindDifference(deriv_order,approx_order,dx[i],len[i]-2,-1)
72-
expr = :(-1*($L*Q[$j]*u[:,$j]))
72+
expr = :(-1*($L*all_bcs[$j]*u[:,$j]))
7373
elseif deriv_order == 2
7474
L = CenteredDifference(deriv_order,approx_order,dx[i],len[i]-2)
75-
expr = :($L*Q[$j]*u[:,$j])
75+
expr = :($L*all_bcs[$j]*u[:,$j])
7676
end
7777
end
7878
return expr
@@ -81,7 +81,6 @@ function discretize_2(input,deriv_order,approx_order,dx,X,len,
8181
push!(deriv_var,var)
8282
return discretize_2(input.args[1],deriv_order+1,approx_order,dx,X,
8383
len,deriv_var,dep_var_idx,indep_var_idx)
84-
pop!(deriv_var,var)
8584
else
8685
name = nameof(operation(input))
8786
if size(input.args,1) == 1
@@ -127,13 +126,13 @@ function DiffEqBase.discretize(pdesys::PDESystem,discretization::MOLFiniteDiffer
127126

128127
tdomain = 0.0
129128
indep_var_idx = Dict()
130-
no_indep_vars = size(pdesys.domain,1)
131-
domain = Array{Any}(undef,no_indep_vars)
132-
dx = Array{Any}(undef,no_indep_vars)
133-
X = Array{Any}(undef,no_indep_vars)
134-
len = Array{Any}(undef,no_indep_vars)
129+
num_indep_vars = size(pdesys.domain,1)
130+
domain = Array{Any}(undef,num_indep_vars)
131+
dx = Array{Any}(undef,num_indep_vars)
132+
X = Array{Any}(undef,num_indep_vars)
133+
len = Array{Any}(undef,num_indep_vars)
135134
k = 0
136-
for i = 1:no_indep_vars
135+
for i = 1:num_indep_vars
137136
var = nameof(pdesys.domain[i].variables)
138137
indep_var_idx[var] = i
139138
domain[i] = pdesys.domain[i].domain
@@ -166,8 +165,8 @@ function DiffEqBase.discretize(pdesys::PDESystem,discretization::MOLFiniteDiffer
166165
else
167166
eqs = pdesys.eq
168167
end
169-
no_dep_vars = size(eqs,1)
170-
for j = 1:no_dep_vars
168+
num_dep_vars = size(eqs,1)
169+
for j = 1:num_dep_vars
171170
input = eqs[j].lhs
172171
op = operation(input)
173172
if op isa Sym
@@ -181,49 +180,46 @@ function DiffEqBase.discretize(pdesys::PDESystem,discretization::MOLFiniteDiffer
181180
for (var,j) in dep_var_idx
182181
aux = discretize_2( eqs[j].rhs,0,approx_order,dx,X,len,
183182
[],dep_var_idx,indep_var_idx)
184-
# TODO: is there a better way to convert an Expr into a Function?
185-
dep_var_disc[var] = @eval (Q,u,t) -> $aux
183+
dep_var_disc[var] = @RuntimeGeneratedFunction(:((all_bcs,u,t) -> $aux))
186184
end
187185

188186
### Declare and define boundary conditions ################################
189187

190188
# TODO: extend to Neumann BCs and Robin BCs
191189
lhs_deriv_depvars_bcs = get_bcs(pdesys.bcs,tdomain,domain[2])
192190
t = 0.0
193-
u_t0 = Array{Float64}(undef,len[2]-2,no_dep_vars)
194-
u_x0 = Array{Any}(undef,no_dep_vars)
195-
u_x1 = Array{Any}(undef,no_dep_vars)
196-
Q = Array{RobinBC}(undef,no_dep_vars)
191+
u_ic = Array{Float64}(undef,len[2]-2,num_dep_vars)
192+
u_left_bc = Array{Any}(undef,num_dep_vars)
193+
u_right_bc = Array{Any}(undef,num_dep_vars)
194+
all_bcs = Array{RobinBC}(undef,num_dep_vars)
197195

198196
for var in keys(dep_var_idx)
199197
j = dep_var_idx[var]
200198
bcs = lhs_deriv_depvars_bcs[var]
201199

202-
g = eval(:((x,t) -> $(bcs[1])))
203-
u_t0[:,j] = @eval $g.($(X[2][2:len[2]-1]),$t)
200+
ic = @RuntimeGeneratedFunction(:((x,t) -> $(bcs[1])))
201+
u_ic[:,j] = ic.(X[2][2:len[2]-1],t)
204202

205-
u_x0[j] = @eval (x,t) -> $(bcs[2])
206-
u_x1[j] = @eval (x,t) -> $(bcs[3])
207-
208-
a = Base.invokelatest(u_x0[j],X[2][1],0.0)
209-
b = Base.invokelatest(u_x1[j],last(X[2]),0.0)
210-
Q[j] = DirichletBC(a,b)
203+
left_bc_fn = :((x, t) -> $(bcs[2]))
204+
right_bc_fn = :((x, t) -> $(bcs[3]))
205+
u_left_bc[j] = @RuntimeGeneratedFunction(left_bc_fn)
206+
u_right_bc[j] = @RuntimeGeneratedFunction(right_bc_fn)
211207
end
212208

213209
### Define the discretized PDE as an ODE function #########################
214210

215211
function f(du,u,p,t)
216212

217213
# Boundary conditions can vary with respect to time
218-
for j in 1:no_dep_vars
219-
a = Base.invokelatest(u_x0[j],X[2][1],t)
220-
b = Base.invokelatest(u_x1[j],last(X[2]),t)
221-
Q[j] = DirichletBC(a,b)
214+
for j in 1:num_dep_vars
215+
left_bc_eval = u_left_bc[j](X[2][1],0.0)
216+
right_bc_eval = u_right_bc[j](last(X[2]),0.0)
217+
all_bcs[j] = DirichletBC(left_bc_eval,right_bc_eval)
222218
end
223219

224220
for (var,disc) in dep_var_disc
225221
j = dep_var_idx[var]
226-
res = Base.invokelatest(disc,Q,u,t)
222+
res = disc(all_bcs,u,t)
227223
if haskey(lhs_deriv_depvars,var)
228224
du[:,j] = res
229225
else
@@ -234,5 +230,5 @@ function DiffEqBase.discretize(pdesys::PDESystem,discretization::MOLFiniteDiffer
234230
end
235231

236232
# Return problem ##########################################################
237-
return PDEProblem(ODEProblem(f,u_t0,(tdomain.lower,tdomain.upper),nothing),Q,X)
233+
return PDEProblem(ODEProblem(f,u_ic,(tdomain.lower,tdomain.upper),nothing),all_bcs,X)
238234
end

test/MOL_1D_Linear_Diffusion.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ using ModelingToolkit,DiffEqOperators,DiffEqBase,LinearAlgebra,Test
3838
using OrdinaryDiffEq
3939
sol = solve(prob,Tsit5(),saveat=0.1)
4040

41-
#Plot and save results
41+
# Plot and save results
4242
# using Plots
4343
# plot(prob.space[2],Array(prob.extrapolation[1]*sol[:,1,1]))
4444
# plot!(prob.space[2],Array(prob.extrapolation[1]*sol[:,1,2]))

0 commit comments

Comments
 (0)