Closed SimonEnsemble closed 2 years ago
Yeah the idea is that sol[c]
will automatically reconstruct the full solution. I think for now something like
@variables c[1:n](t)
sol[c[1](t)]
should work (but having to redefine that first line is annoying)
@unpack c = sys
sol[c[1](t)]
if you did the symbolic discretize to get sys
. We should make that a bit nicer.
@variables c[1:Nₓ](t)
sol[c[1](t)]
gives the error Sym c[1](t) is not callable. Use @syms c[1](t)(var1, var2,...) to create it as a callable.
changing to @syms c[1:Nₓ](t)
gives MethodError: Cannot
convertan object of type Expr to an object of type Symbol
@named pdesys = PDESystem(...)
@unpack c = pdesys # very much later
fails with type PDESystem has no field systems
is if c[1](t)
and c[Nₓ](t)
appeared in the data frame! we are using the dataframe output.
(here, data
is the solution to the PDE)
# Robin BC (write out first order finite difference)
insertcols!(data, 2, "c[1](t)" => zeros(nrow(data)))
for i = 2:nrow(data)
c₂ = data[i, "c[2](t)"]
c₁ = Polynomial([0, 1])
poly = -α * c₁^2 + (-D₀ + α * c₂ - Δx / R) * c₁ + Δx / R * cₑ + D₀ * c₂
poly_rts = roots(poly)
data[i, "c[1](t)"] = poly_rts[isreal.(poly_rts)][1]
end
# no flux BC
insertcols!(data, "c[$(settings.Nₓ)](t)" =>
data[:, "c[$(settings.Nₓ-1)](t)"])
Mixed up the two ways, you can either do
@variables c[1:n](..)
sol[c[1](t)]
or
@variables c[1:n](t)
sol[c[1]]
:bowing_man: thank you!
another weird thing is that for my diffusion eqn. with Robin BC and concentration-dependent diffusion, the "c1" IS automatically appended at the end! but not the end point corresponding to no-flux.
function toy_pde()
@parameters x t
@variables c(..)
∂t = Differential(t)
∂x = Differential(x)
∂²x = Differential(x) ^ 2
D₀ = 1.0
α = 0.15
R = 0.1
cₑ = 2.0
ℓ = 1.0
Δx = 0.05
diff_eq = ∂t(c(x, t)) ~ ∂x((D₀ + α * c(x, t)) * ∂x(c(x, t)))
bcs = [
# initial condition
c(x, 0) ~ 0.0,
# Robin BC
∂x(c(0.0, t)) + (cₑ - c(0.0, t)) / (D₀ + α * c(0.0, t)) / R ~ 0.0,
# no flux BC
∂x(c(ℓ, t)) ~ 0.0]
# define space-time plane
domains = [x ∈ Interval(0.0, ℓ), t ∈ Interval(0.0, 5.0)]
# put it all together into a PDE system
@named pdesys = PDESystem(diff_eq, bcs, domains, [x, t], [c(x, t)]);
# discretize space
discretization = MOLFiniteDifference([x=>Δx], t)
# convert the PDE into a system of ODEs via method of lines
prob = discretize(pdesys, discretization)
# compute number of spatial discretization points, boundaries included.
Nₓ = length(prob.u0) + 1 # change to +2 for Dirichlet
@assert (length(0:Δx:ℓ) == Nₓ)
# solve system of ODEs in time.
sol = solve(prob, saveat=0.01)
# convert solution to data frame. solution at boundaries must be inferred.
data = DataFrame(sol)
@variables c[1:Nₓ](t)
data[:, "c[$Nₓ](t)"] = sol[c[Nₓ]]
ordered_cols = ["c[$i](t)" for i = 1:Nₓ]
pushfirst!(ordered_cols, "timestamp")
return data[:, ordered_cols]
end
hi! solving the diffusion equation with (i) concentration-dependent diffusion coefficient and (ii) Robin BC.
I get an error:
here is our PDE:
so my student found that, if we re-arrange the Robin BC to instead look like:
it works! maybe something to add to the docs?
(for novices like me, would be great to have
c[1](t)
andc[end](t)
inferred by default instead of cutting off the solution at the boundaries.) thanks! EDIT: nevermind, it doesn't start atc[3](t)
. I had an additional BC in there by accident. sorry. I can figure out how to inferc[1](t)
fromc[2](t)
. I'll edit this post when I figure it out. :)