I am checking a complex situation where a function x1[t1]
only exit in a finite time span, and after this a new function x2[t2]
will be set up according to the final value of x1
, and then repeat the same procedure to build x3[t3]
, ..., xn[tn]
.
A most simple 3-nest toy code can be rawly formatted like this
d0 = 1;
{c1, c2, c3} = {1, 2, 3};
end=20;
res1 = NDSolve[{
x1'[t1] == c1, x1[0] == 0,
WhenEvent[x1[t1] == d0,
res2 = NDSolve[{
x2'[t2] == c2, x2[t1] == x1[t1],
WhenEvent[x2[t2] == 2*d0,
res3 = NDSolve[{
x3'[t3] == c3, x3[t2] == x2[t2]
}, x3, {t3, t2, end}, MaxSteps -> 1000000];
"StopIntegration"
]}, x2, {t2, t1, end}, MaxSteps -> 1000000];
"StopIntegration"
]}, x1, {t1, 0, end}, MaxSteps -> 1000000];
We can now check res1
, res2
and res3
, and they work. But I hope that this code can be more concise than its current state, like how we discard the previous functions and code the remaining inner-nest part, especially for multiple-nest cases, ie. a 100-nest case. I think the most proper way would be to go meta-programming together with recursion... am I right?
Update
Based on Albert Retey's answer, we can furthe treat x[t] as a vector function, like this
cVals = {{1, 1/2}, {1/3, 1/4}, {1/5, 1/10}};
tvals = {5, 10, 20};
tstart = 0;
xsol = Quiet[
NDSolveValue[{
x'[t] == cVals[[n[t]]], x[tstart] == {0, 0}, n[tstart] == 1,
WhenEvent[t == tvals[[n[t]]],
If[TrueQ[n[t] < Length[cVals]], n[t] -> n[t] + 1, "RemoveEvent"]]
}, x, {t, tstart, 20},
DiscreteVariables -> {Element[n, Integers]}, MaxSteps -> 1000000
], Part::pspec];
Plot[xsol[t], {t, ##}] &[Sequence @@ xsol["Domain"][[1]]]
Where we used cVals = {{1, 1/2}, {1/3, 1/4}, {1/5, 1/10}}
.
I think the code can be more general if we can use something like cVals = {1, {1/2, 1/3}, {1/4, 1/5, 1/6}}
so that the x[t]
can have variable dimensions at different time scopes. I wonder if this idea is feasible?
Update 2
Here is a first try, which shows the idea, but the code does not work yet...
cVals = {1, {1/2, 1/3}};
tvals = {5, 10};
tstart = 0;
xsol = Quiet[
NDSolveValue[{
x'[t] == cVals[[n[t]]], x[tstart] == 0, n[tstart] == 1,
WhenEvent[t > tvals[[n[t]]],
If[TrueQ[n[t] < Length[cVals]],
xv = x[t];
n[t] -> n[t] + 1;
x[t] -> {xv, xv},
"RemoveEvent"]]
}, x, {t, tstart, 20},
DiscreteVariables -> {Element[n, Integers]}, MaxSteps -> 1000000
], Part::pspec];
Plot[xsol[t], {t, ##}] &[Sequence @@ xsol["Domain"][[1]]]
NDSolves
? As far as I understand you are just stopping at certain conditions and then run anotherNDSolve
with the final point of the previous as initial conditions, stop that at another condition and so on. No need for a recursion at all. In fact as only a parameter changes in your restarted equations you could handle that within theWhenEvent
without even restarting... $\endgroup$NDSolve
results (as in the question, where the ODE is assumed linear for simplicity) happening at time t1, t2, ... for the multiple paths' coupling. It uses only a singleWhile
for dynamic looping. The real problem can be solved by developing an XFEM kink-enrichment method, but for comparison it will be better if we can use finite difference method to solve the problem to some extent. $\endgroup$WhenEvent
without restarting. But how can we do this? Could you provide an example? $\endgroup$