I’m trying to dig up some past knowledge on the “weighted residual method” – it seems to be quite similar to PINN.
How can I make the following more elegant? To exemplify, I consider a co-current heat exchanger:
with boundary conditions that T_j(t,x=0) = T_j^\mathrm{i}(t) are known functions of time.
The idea is to postulate “trial solutions” T_j^*(t,x) — these would be NN:s in PINNs, I guess. I choose trial solutions that satisfy the boundary conditions.
Next, I choose the collocation variant of weighted residual method (i.e., delta dirac weights in the “error integral”).
Here is my running code:
# Packages
using ModelingToolkit
using DifferentialEquations
using Symbolics
using Plots
# Some MTK definitions
@variables t x
Dt = Differential(t)
Dx = Differential(x)
@parameters v_1=1 α_1=0.1 v_2=2 α_2=0.5 L=10
@variables T_10(t) T_1M(t)=0 T_1L(t)=0 T_20(t)=0 T_2M(t)=0 T_2L(t)=0
#
@register_symbolic T_1i(t)
@register_symbolic T_2i(t)
# Trial solutions -- very simple for now
T_1t = T_10*(x-L)/(0 - L)*(x-L/2)/(0-L/2) + T_1M*(x-L)/(L/2 - L)*(x-0)/(L/2-0) + T_1L*(x-L/2)/(L-L/2)*(x-0)/(L-0)
T_2t = T_20*(x-L)/(0 - L)*(x-L/2)/(0-L/2) + T_2M*(x-L)/(L/2 - L)*(x-0)/(L/2-0) + T_2L*(x-L/2)/(L-L/2)*(x-0)/(L-0)
# Function for generating residuals
residual(T1,T2) = expand_derivatives.([Dt(T1) + v_1*Dx(T1) + α_1*(T1-T2),
Dt(T2) + v_2*Dx(T2) + α_2*(T2-T1)])
# Converting actual residuals to equations
res = residual(T_1t,T_2t)
eqs = [substitute(res[1], [x => L/2]) ~ 0,
substitute(res[1], [x => L]) ~ 0,
substitute(res[2], [x => L/2]) ~ 0,
substitute(res[2], [x => L]) ~ 0,
T_10 ~ T_1i(t),
T_20 ~ T_2i(t)]
# Symbolic model + simplified model
@named sys_ns = ODESystem(eqs,t)
sys = structural_simplify(sys_ns)
# Defining timespan + numeric problem + concrete inputs, and then solving the problem
tspan = (0,50)
#
prob = ODEProblem(sys,[],tspan)
#
T_1i(t) = t<10 ? 10 : 20
T_2i(t) = t<20 ? 5 : 15
#
sol = solve(prob, QNDF())
plot(sol)
Just to illustrate, the solution is as follows:
I have used simple polynomials as “basis functions” in the spatial direction x; T_jM
is the value of the temperature midways between [0,L].
An alternative would be to use some “Finite Element” type basis functions.
Questions
-
How would I need to change the code to get trial solutions T_j^* that are real functions of time and space, which I can plot in a more elegant way? Right now, I can only plot values in the chosen collocation points (x=0, x=L/2, x=L).
-
The MOL equations for PDEs based on collocation can be generated quite fast, leading to ODEs/DAEs that can be efficiently solved using DifferentialEquations solvers. The extra cost of changing the time span is small.
- How does this compare to PINN?
- Does PINN solvers train on a specific domain in time and space, so that the training has to be completely re-done if I, e.g., extend the time span?