The system as presented to DSolve
consists of autonomous linear DEs plus an algebraic equation that on the surface depend on each other. Consequently, DSolve
seems unable to take advantage of the simplicity of the autonomous linear system and applies a DAE solver instead.
Here's an approach: Eliminate the algebraic equation for q[t]
, solve the linear DE system, and construct the solution for q
from the solution to the linear system and the formula for q
:
equations = {
m'[t] == 1/a (r3 + n[t] - (p[t] + (m[t] - r4) r5 ) - (r1 + r2) m[t]),
n'[t] == -(1/b) m[t],
p'[t] == 1/c (m[t] - r4),
m[0] == m0, (*Initial condition for m(t)*)
n[0] == n0, (*Initial condition for n(t)*)
p[0] == p0 (*Initial condition for p(t)*)};
sol = Append[#, q -> Function @@ {t, p[t] + (m[t] - r4) r5 /. #}] & /@
DSolve[equations, {m, n, p}, t] // AbsoluteTiming
(* {69.7276, <1.7 MB output>} *)
Quite a bit faster than the 30+ min. reported in the OP.
Update 1: A faster DSolve[]
We can reduce the number of parameters and simplify the formulas. This makes a marked improved, much more than I would have expected.
{bmat, amat} = CoefficientArrays[
First@SolveValues[equations[[;; 3]], D[Through[{m, n, p}[t]], t]],
Through[{m, n, p}[t]]
];
idx = 0;
reducedAmat =
Replace[Normal@amat,
x_ /; ! PossibleZeroQ[x] :> $a[++idx], {2}];
backsub = Simplify@
DeleteCases[
Thread[Flatten@reducedAmat -> Flatten@Normal@amat],
HoldPattern[0 -> 0]];
(* simplification (by inspection): *)
reducedAmat = reducedAmat /. $a[3] -> -$a[2];
(*ClearSystemCache[]*)(* clear caches for valid timing *)
DSolve[
{D[{m[t], n[t], p[t]}, t] ==
reducedAmat . {m[t], n[t], p[t]} + bmat,
equations[[4 ;;]]},
{m[t], n[t], p[t]}, t] /.
backsub // AbsoluteTiming
(* {2.46386, < 0.9 MB output >} *)
Update 2: Comment on MatrixExp[]
solutions
Aside from lacking working code, the answer from @RolandF has a perhaps subtle mathematical error.
The general matrix exponential solution to $\dot {\bf y}(t) = {\bf A} \mathbin{.} {\bf y}(t) + {\bf b(t)}$ has the form
$${\bf y}(t)=\Psi(t) \mathbin{.}\left({\bf y}(0)+\int_0^t \Psi(-t) \mathbin{.} {\bf b}(t) \; dt\right) \,,\quad \Psi(t) = \exp({\bf A}\,t)$$
When $\bf b$ is constant and $\bf A$ is invertible, this is easily simplified to a solution resembling @RolandF's in outline; however, $\bf A$ is not invertible in the OP's linear system. And since one of the basis functions of the solution space to the homogeneous system is constant (eigenvalue $0$) and $\bf b$ is constant, the situation is equivalent to having a repeated eigenvalue. There is no way to avoid the integral (or a calculation equivalent to it, since the integral would be simple were it not for the numerous parameters making superficially complicated).
{bmat, amat} = CoefficientArrays[
First@SolveValues[equations[[;; 3]], D[Through[{m, n, p}[t]], t]],
Through[{m, n, p}[t]]
];
psi = MatrixExp[amat t] // Simplify; // AbsoluteTiming
(* {2.79531, Null} *)
msol = psi . ({m0, n0, p0} + # - (# /. t -> 0) &@
Integrate[(psi /. t -> -t) . bmat, t]); //
AbsoluteTiming
(* {4.77207, Null} *)
msol // ByteCount
(* 158312 *)
(* put in solution form *)
matexpsol =
Thread[{m, n, p} -> (Function[t, #] & /@
Transpose@ msol)];
matexpsol =
Append[matexpsol,
q -> Function @@ {t, p[t] + (m[t] - r4) r5 /. matexpsol}];
matexpsol // ByteCount
(* 262976 *)
If we use reduceAmat
as in Update 1,
we reduce the times above to a little less than half,
which is about as fast DSolve
in Update 1.
If you worry about the use of the fundamental theorem of calculus to compute msol
, one can, at some cost of time, compute the definite integral:
msol = psi . ({m0, n0, p0} +
Integrate[(psi /. t -> -t) . bmat, {t, 0, t}]); //
AbsoluteTiming
(* {25.6736, Null} *)
The result is equivalent (applying Simplify
to the difference of the two yields 0
).
Update 3: Alternative conversion to linear system
Another way to convert the DAE system to a linear ODE system is to differentiate the equation for q[t]
. DSolve
computes the solution in about a minute, about as fast as the first solution, but the solution here is much larger in size.
equations3 = {
m'[t] ==
1/a (r3 + n[t] - (p[t] + (m[t] - r4) r5) - (r1 + r2) m[t]),
n'[t] == -(1/b) m[t], p'[t] == 1/c (m[t] - r4),
D[q[t] == p[t] + (m[t] - r4) r5, t],
m[0] == m0,(*Initial condition for m(t)*)
n[0] == n0,(*Initial condition for n(t)*)
p[0] == p0, (*Initial condition for p(t)*)
q[t] == p[t] + (m[t] - r4) r5 /. t -> 0};
PrintTemporary@Dynamic@Clock@Infinity;
DSolve[equations3, {m, n, p, q}, t] // ByteCount // AbsoluteTiming
(* {64.1766, 5816160} *)