5
$\begingroup$

Solving general differential equations in Mathematica usually leads to somewhat unsightly results.

As an example, consider the solution of the driven, damped harmonic oscillator:

eqn = x''[t] + β x'[t] +  ω0^2 x[t] == f0/m Exp[I ωd t];
s = DSolve[eqn, x[t], t]

Unsightly long result

Using FullSimplify helps to reduce this mess, but the result is still far away from something an engineer or physicist would recognize at first glance:

Simplify[s]

Weirdly simplified result

How can you transform such solutions into something nicer?

$\endgroup$
0

2 Answers 2

6
$\begingroup$

Referring to your own answer there is a much simpler form that you may use, recalling:

Collect[expr, var, h] applies h to the expression that forms the coefficient of each term obtained.

sol = x[t] /. s[[1]];

Collect[sol, _C, Simplify]
(E^(I t ωd) f0)/(m ω0^2 + I m β ωd - m ωd^2) + 
 E^(-(1/2) t (β + Sqrt[β^2 - 4 ω0^2])) C[1] + 
 E^(1/2 t (-β + Sqrt[β^2 - 4 ω0^2])) C[2]

Martin commented:

It's unfortunate that FullSimplify doesn't do this step on its own. The leaf-count is actually lower after collecting on the C[i].

One can add manipulations using TransformationFunctions therefore:

collectC[x_] := Collect[x, _C, Simplify]
SetOptions[FullSimplify, TransformationFunctions -> {Automatic, collectC}];

FullSimplify[sol]
(E^(I t ωd) f0)/(m ω0^2 + I m β ωd - m ωd^2) + 
 E^(-(1/2) t (β + Sqrt[β^2 - 4 ω0^2])) C[1] + 
 E^(1/2 t (-β + Sqrt[β^2 - 4 ω0^2])) C[2]
$\endgroup$
6
  • 4
    $\begingroup$ This is a nice and general method for linear differential equations because the C[i] will always be multiplicative in front of the homogeneous solutions, so collecting them is the natural choice (+1). $\endgroup$
    – Jens
    Commented Oct 15, 2014 at 21:25
  • $\begingroup$ It's unfortunate that FullSimplify doesn't do this step on its own. The leaf-count is actually lower after collecting on the C[i]. $\endgroup$ Commented Oct 16, 2014 at 8:11
  • 1
    $\begingroup$ The result of collecting over m is smaller, but not very systematic because m is a variable that could easily be eliminated from the entire problem. A more systematic way of getting that same result seems to be Simplify /@ Apart@Simplify[sol]. Here I use the fact that Map can also work on expressions that don't have head List - which is also something the OP could have used to avoid converting to List initially. But I think what the physicist expects is really the result of collecting over _C... $\endgroup$
    – Jens
    Commented Oct 16, 2014 at 17:55
  • $\begingroup$ @Jens Points taken. $\endgroup$
    – Mr.Wizard
    Commented Oct 16, 2014 at 18:00
  • $\begingroup$ @Jens I updated my answer to work on _C but I did not introduce Apart. Do you feel like posting that yourself? $\endgroup$
    – Mr.Wizard
    Commented Oct 16, 2014 at 18:04
3
$\begingroup$

One way to tackle the problem is to recognize that the solution is one giant sum with three terms.

You can then convert this sum to a list, simplify the terms individually, and sum all elements of the list back together.

sol = x[t] /. s[[1]];
Total[ FullSimplify[ Apply[ List , sol  ] ] ]

Nicer solution

But this "hack" is somewhat unelegant, because it might fail if the inhomogeneous solution is a sum in it's own.

A more robust solution is to Simplify first, then Collect all terms that contain a C[ ]-factor, and finally simplifying the individual terms in that sum:

sol = x[t] /. s[[1]];
Total [Simplify[Apply[List, Collect[ Simplify[ sol ], _C  ] ] ] ]

It's a bit hard to see what is going in that verbose form, so here is the same code in postfix notation (think "Unix pipes"):

sol = x[t] /. s[[1]];
sol // Simplify // Collect[#, _C]&   // Apply[List, #]&   // Simplify // Total

The output of all these commands is equivalent.

Addendum: I did another FullSimplify of the last result and noticed that it stayed the same (instead of reverting to the original). And indeed, checking the complexity of the expressions revealed 121 for the original "FullSimplified"-version, and 90 for the "Collected" version.

I suspect that FullSimplify somehow misses this simplification. Hopefully it will come in future Mathematica versions.

$\endgroup$
3
  • 1
    $\begingroup$ For a very simple form, set the arbitrary constants to zero: s[[1]] /. {C[1] -> 0, C[2] -> 0} // Simplify $\endgroup$
    – Bob Hanlon
    Commented Oct 15, 2014 at 17:13
  • 2
    $\begingroup$ It's a valid trick, but you have to be careful that you don't lose information that you care about: In the harmonic oscillator example, setting the Cs to 0 gets rid of the transients and leaves you with the steady state solution. $\endgroup$ Commented Oct 15, 2014 at 17:16
  • 1
    $\begingroup$ Another way to write your last line of code, assuming M10 operator forms: Simplify[sol] ~Collect~ C[_] // Apply[List] // Simplify // Total $\endgroup$
    – Mr.Wizard
    Commented Oct 15, 2014 at 19:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.