0

I have to solve a series of differential equations along with a constraint that has to be satisfied at each point of time where $t\in [0, 100]$ The model parameters are

β = 0.1; c1 = 10; c2 = 30; k1 = 100; k2 = 300; T = 100; 
δ1 = 0.1; δ2 = 0.3; Subscript[y, 0] = 1000; a = 4000; b = 200;

To solve the differential equations, I first assume that μ[t]=0solves the following in order to obtain $\lambda (t)$ and $x(t)$

sol1 = NDSolve[{λ'[t] == -((c1^2 - 4*k1*β*λ[t] - 
   2*c1*(λ[t] + μ[t]) + (λ[t] + μ[t])^2)/(
   4 k1)), x'[t] == -((c2^2 - 4*k2*(β*x[t] + δ1 (x[t] - λ[t])) - 2*c2*(x[t] + μ[t]) + 
   (x[t] + μ[t])^2)/(4 k2)), λ[T] == 0, x[T] == 0}, {λ, x}, {t, 0, 100}];

having λ[t] and x[t], I calculate ρ1[t] and ρ2[t]

ρ1[t_] := (c1 - {λ[t] /. sol1} - μ[t])/(2*k1);
ρ1[t][[1, 1]];

ρ2[t_] := (c2 - {x[t] /. sol1} - μ[t])/(2*k2);
ρ2[t][[1, 1]];

Having ρ1[t] and λ[t], ρ2[t] and x[t], I have to solve the following differential equations where `

d[t_] := a + b*Sin[(2*π*t/25)];

s = NDSolve[{y3'[t] == d[t] - δ2*y3[t], 
y2'[t] == δ2*y3[t] - (δ1 - ρ2[t][[1, 1]]) y2[t], 
y1'[t] == δ1*y2[t] - ρ1[t][[1, 1]]*y1[t], 
y3[0] == Subscript[y, 0], y2[0] == Subscript[y, 0], 
y1[0] == Subscript[y, 0]}, {y3, y2, y1}, {t, 0, 100}];

The problem is my constraint is based on ρ1[t], y1[t], ρ2[t] and y2[t]. So only after calculating everything with the assumption of μ[t]=0, I can actually check my constraint to see if it is satisfied, the constraint is the following: if

d[t] - (ρ1[t]*{y1[t] /. s} + ρ2[t]*{y2[t] /. s}) >= 0

then μ[t] = 0. Otherwise calculate the $μ[t]$ from below

μ[t] := (-2*d[t]*k1*k2 + c1*k2*{y1[t] /. s} + c2*k1*{y2[t] /. s} - 
 k2*{y1[t] /. s}*{λ[t] /. sol1} - 
 k1*{y2[t] /. s}*{x[t] /. sol1})/(k2*{y1[t] /. s} + 
 k1*{y2[t] /. s})]

and then I have to solve everything with from the beginning with new value of μ[t]. With μ=0 I get something like this

Plot[{d[t], ρ1[t]*{y1[t] /. s} + ρ2[t]*{y2[t] /. s}}, {t, 0,
   100}, PlotRange -> {0, 6000}, Frame -> True, 
 FrameLabel -> {"time", "d(t)-(ρ1(t)y1(t)+ρ2(t)y2(t))"}]

enter image description here

basically after the intersection point both lines should be adjusted (this should be taken care of by the new value of μ[t]) Is there anyways to code this model to check μ[t] at each point of time and see if the constraint is satisfied or not? do I need to create a loop to do this?

Michael E2
  • 235,386
  • 17
  • 334
  • 747
Baboda
  • 55
  • 6
  • If you're using v10.0 or above, then you might want to look into WhenEvent. – Michael Seifert Jul 22 '15 at 19:39
  • @MichaelSeifert, no unfortunatly I'm using v9.0. – Baboda Jul 22 '15 at 19:58
  • WhenEvent is in 9. I think you will need to explicitly show the u dependance on rho, eg rho1[t_,u_]:=.. – george2079 Jul 22 '15 at 20:17
  • @george2079, the problem is I have first assume that $\mu(0)=0$ and solve all the equations to find $y1(t)$ and $y2(t)$ then check the constraint then if the constraint is violated then adjust $\mu$ and solve everything again. and this might happens several times in a planning horizon. any suggestion on how to write the code for this? – Baboda Jul 23 '15 at 09:07
  • @bbgodfrey, sorry for typo mistakes. I addressed them in the edited version. the planning horizon is $t \in [0,100]$. I know that at least at one point of time my constraint is not satisfied i.e. d[t] - (ρ1[t]*{y1[t] /. s} + ρ2[t]*{y2[t] /. s}) < 0 . what i have to do is at that point of time i should calculate μ[t] and then go back to the first step and recalcuate everyhing based on the value of μ[t]. – Baboda Jul 24 '15 at 09:41
  • At the end μ[t] seems to depend on ρ1[t] and ρ1[t] depends on μ[t], which would lead to infinite recursion. Please clarify how μ[t] is to be defined. At first, it is just 0, but why not omit it then? Or is μ[t] to be replaced at some point by another definition, and is sol1 to be recomputed at that point? – Michael E2 Jul 24 '15 at 12:12
  • @MichaelE2, at the beginning we start off by the assumption that μ[t] is equal to zero. but at a point of time that constraint is violated then I have to calculate the value of μ[t] from μ[t] := (-2*d[t]*k1*k2 + c1*k2*{y1[t] /. s} + c2*k1*{y2[t] /. s} - k2*{y1[t] /. s}*{λ[t] /. sol1} - k1*{y2[t] /. s}*{x[t] /. sol1})/(k2*{y1[t] /. s} + k1*{y2[t] /. s})] and then go back and compute sol1 based on the new values of μ[t]. so for example in the graph up to t=20 μ[t]=0 is fine but after that I have to recalculate μ[t] and sol1. – Baboda Jul 24 '15 at 12:42
  • I understood all that from the question. I guess I mean that your code does not reflect this "assumption," so I'm unsure how you implemented it. The following problem is confusing me: What is the definition of μ[t] when ρ1[t] is calculated? When you change the definition of μ[t], that changes the value of ρ1[t] and ρ2[t], which in turn might change when the constraint d[t] - (ρ1[t]*{y1[t] /. s} + ρ2[t]*{y2[t] /. s}) >= 0 is satisfied. Do you mean to iterate the process and stop when it converges to a stable definition of μ[t]? Perhaps it just happens to work with a single iteration? – Michael E2 Jul 24 '15 at 12:54
  • @MichaelE2, μ[t] act as Lagrangian multiplier in my model. Yes, you are right, so basically when as long as the constraints is satisfied with I'll continue with μ[t]=0 and when the constraint is not satisfied I have to recalculate μ[t] for that time onward. Obviously it should change ρ1[t] and ρ2[t] to satisfy the constraint again. I think i need to code some sort of loop. I'm not sure if iterating the process do the job and how should i do it. I hope that I explained it better this time. – Baboda Jul 24 '15 at 13:20
  • Are you saying that you need to change μ[t] everywhere, if the constraint is not satisfied anywhere, or that you need to change μ[t] only for t at which the constraint is not satisfied? – bbgodfrey Jul 24 '15 at 13:29
  • @bbgodfrey I have to change μ[t] only for t at which the constraints is not satisfied. so we have to switch from μ[t]=0 to new μ[t] and continue with new μ[t] towards the end of the planning horizon. – Baboda Jul 24 '15 at 13:34
  • 1
    @bbgodfrey so lets say for 0<t<20 constraint is satisfied so we keep μ[t]=0 and then at t=20 we should switch to new μ[t] and continue with that. I think depending on d[t] we might switch more than once. – Baboda Jul 24 '15 at 13:41
  • @bbgodfrey I didn't completely understand the approach, and I'm not an expert in Mathematica coding. Is it possible for you to illustrate it? – Baboda Jul 24 '15 at 14:03
  • @bbgodfrey, thanks for the help tomorrow is fine. – Baboda Jul 24 '15 at 14:18

1 Answers1

2

This interesting problem can be solved by iterating several times on μ. (WhenEvent cannot be used, because this is a boundary value, not an initial value, computation.)

μ[t_] = 0;
β = 1/10; c1 = 10; c2 = 30; k1 = 100; k2 = 300; T = 100; 
δ1 = 1/10; δ2 = 3/10; Subscript[y, 0] = 1000; a = 4000; b = 200;
d[t_] = a + b*Sin[(2*π*t/25)];
y3[t_] = DSolveValue[{y3t'[t] == d[t] - δ2*y3t[t], y3t[0] == Subscript[y, 0]},
    y3t[t], {t, 0, T}];

Do[sol1 = First@NDSolve[
    {λ'[t] == -((c1^2 - 4*k1*β*λ[t] - 2*c1*(λ[t] + μ[t]) + (λ[t] + μ[t])^2)/(4 k1)), 
     x'[t] == -((c2^2 - 4*k2*(β*x[t] + δ1 (x[t] - λ[t])) - 
         2*c2*(x[t] + μ[t]) + (x[t] + μ[t])^2)/(4 k2)),
     ρ1[t] == (c1 - λ[t] - μ[t])/(2*k1),
     ρ2[t] == (c2 - x[t] - μ[t])/(2*k2),
     λ[T] == 0, x[T] == 0}, {λ, x, ρ1, ρ2}, {t, 0, T}];
s = First@NDSolve[
     {y2'[t] == δ2*y3[t] - (δ1 - (ρ2[t] /. sol1)) y2[t], 
      y1'[t] == δ1*y2[t] - (ρ1[t] /. sol1)*y1[t], 
      y2[0] == Subscript[y, 0], y1[0] == Subscript[y, 0]}, {y2, y1}, {t, 0, T}];
μ[t_] = If[.99 d[t] >= ρ1[t]*y1[t] + ρ2[t]*y2[t], 0,
            Max[(-2*d[t]*k1*k2 + c1*k2*y1[t] + c2*k1*y2[t] - 
            k2*y1[t]*λ[t] - k1*y2[t]*x[t])/(k2*y1[t] + k1*y2[t]), 0]] /. s /. sol1, {i, 5}]

Grid[{{Plot[{d[t], (ρ1[t] /. sol1)*(y1[t] /. s) + (ρ2[t] /. sol1)*(y2[t] /. s)}, {t, 0, T},
         PlotRange -> {0, 6000}, Frame -> True, FrameLabel -> {"t", "d-(ρ1 y1 +ρ2 y2)"}, 
         ImageSize -> Medium],
      Plot[{μ[t], λ[t] /. sol1, x[t] /. sol1}, {t, 0, T}, Frame -> True, 
         FrameLabel -> {"t", "μ, λ, x"}, ImageSize -> Medium]},
     {Plot[{ρ1[t] /. sol1, ρ2[t] /. sol1}, {t, 0, T}, Frame -> True, 
         FrameLabel -> {"t", "ρ1, ρ2"}, ImageSize -> Medium],
      Plot[{y1[t] /. s, y2[t] /. s, y3[t]}, {t, 0, T}, Frame -> True, 
         FrameLabel -> {"t", "y1, y2, y3"}, ImageSize -> Medium]}}]

enter image description here

Several points are worth noting:

  • The calculation of y3 is independent of μ and can be moved outside the iteration process. It is computed exactly here, although the gain in accuracy is negligible.
  • ρ1 and ρ2 are calculated inside NDSolve, so that they are represented as single InterpolatingFunctions. Otherwise, FunctionInterpolation must be used, so that recursive definitions of μ do not accumulate in them, causing the iteration to fail.
  • A safety factor is needed in the definition of μ so that the sign of the first argument of If does not oscillate during the iteration. However, this safety factor can allow μ to dip slightly negative near t = 21. Max is used to prevent this, even though its effect is negligible.
  • Convergence is rapid, yielding no visible changes to the curves after four iterations.

Edit: Simplified expression for μ and corrected typo based on recommendations by MichaelE2.

Plotting Results for Several Parameter Values

As requested in a comment below, curves for several values of a parameter (here, δ1) can be computed and plotted as follows.

Do[δ1 = j/10; μ[t_] = 0; 
Do[sol1 = First@NDSolve[
    {λ'[t] == -((c1^2 - 4*k1*β*λ[t] - 2*c1*(λ[t] + μ[t]) + (λ[t] + μ[t])^2)/(4 k1)), 
     x'[t] == -((c2^2 - 4*k2*(β*x[t] + δ1 (x[t] - λ[t])) - 
         2*c2*(x[t] + μ[t]) + (x[t] + μ[t])^2)/(4 k2)),
     ρ1[t] == (c1 - λ[t] - μ[t])/(2*k1),
     ρ2[t] == (c2 - x[t] - μ[t])/(2*k2),
     λ[T] == 0, x[T] == 0}, {λ, x, ρ1, ρ2}, {t, 0, T}];
s = First@NDSolve[
     {y2'[t] == δ2*y3[t] - (δ1 - (ρ2[t] /. sol1)) y2[t], 
      y1'[t] == δ1*y2[t] - (ρ1[t] /. sol1)*y1[t], 
      y2[0] == Subscript[y, 0], y1[0] == Subscript[y, 0]}, {y2, y1}, {t, 0, T}];
μ[t_] = If[.99 d[t] >= ρ1[t]*y1[t] + ρ2[t]*y2[t], 0,
           Max[(-2*d[t]*k1*k2 + c1*k2*y1[t] + c2*k1*y2[t] - 
           k2*y1[t]*λ[t] - k1*y2[t]*x[t])/(k2*y1[t] + k1*y2[t]), 0]] /. s /. sol1, {i, 5}];
ρ1sav[j] = ρ1 /. sol1; ρ2sav[j] = ρ2 /. sol1, {j, 7}]

ParametricPlot3D[Evaluate[Table[{t, j, ρ1sav[j][t]}, {j, 7}]], {t, 0, T}, 
    PlotRange -> {Automatic, Automatic, {0, .05}}, BoxRatios -> {2, 1, .7}, 
    AxesLabel -> {"t", "10 δ1", "ρ1"}, LabelStyle -> Directive[Bold, 14], 
    ImageSize -> Large]

and similarly for ρ2. The plot design is based on the answer by Heike to question 1413.

enter image description here

bbgodfrey
  • 61,439
  • 17
  • 89
  • 156
  • There are still syntax errors in the Grid...Check FrameLabel...Missing {: FrameLabel -> {"t", "d-(\[Rho]1 y1 +\[Rho]2 y2)"} – Michael E2 Jul 25 '15 at 15:05
  • If you define \[Mu][t_] = If[...] /. s /. sol1 with the replacements outside the If, you don't need DependentVariables and the code is shorter. Some remark on how many times to iterate might be helpful, too. – Michael E2 Jul 25 '15 at 15:24
  • @MichaelE2 Thank you for your helpful suggestions, which I have incorporated and acknowledged. – bbgodfrey Jul 25 '15 at 16:42
  • You're welcome. It's a very nice answer. +1 – Michael E2 Jul 25 '15 at 17:02
  • @bbgodfrey- thanks, thats exactly how I wanted the model to work. its interesting because I was expecting to have jumps for paths λ[t] and x[t] when μ switches. – Baboda Jul 25 '15 at 21:52
  • @Baboda Thank you for accepting the answer. μ enters into the equations for the derivatives of λ and x, so the derivatives change rapidly. The variables themselves have rapid changes in their slopes, as shown in the figure. Best wishes. – bbgodfrey Jul 25 '15 at 22:12
  • @bbgodfrey, I'm just wondering if it is possible to convert the pots into 3D plots in order to investigate the impact of constant parameters? for instance if I want to see how changes in δ1 impact on ρ1 and ρ2. – Baboda Jul 27 '15 at 09:23
  • @Baboda Any of the answers to 1413 that involve a Table of 2D curves will do the job. By the way, I believe that there is some much simpler way to solve your overall problem. Perhaps, start by using ρ1 and ρ2 as the dependent variables instead of λ and x in the first two equations, which would convert μ to source terms only in those equations and eliminate it entirely from the y equations. – bbgodfrey Jul 27 '15 at 15:00
  • @bbgodfrey, I presented the solution based on the Pontryagain Maximum Principle hoping that I could t solve it analytically. So initially I wanted to find how optimal solution (ρ1 and ρ2) behaves according to co-states λ and x. I'm sure there are more ways to solve it but I'm not sure if I fully understand your suggestion. Btw, I still couldn't figure out how to generate a 3D graph from the answers to 1413 (sorry its my lack of experience in coding). how can I see for instance the changes in ρ1 and ρ2 over t for different values of δ1? – Baboda Jul 28 '15 at 12:00
  • @Baboda What values of δ1 would you like? – bbgodfrey Jul 28 '15 at 13:04
  • @bbgodfrey Lets say delta1 changes on the interval [0.1, 0.7]. – Baboda Jul 28 '15 at 16:03
  • Done, based on the approach by @Heike. – bbgodfrey Jul 29 '15 at 01:35