Accessing Reduce from DSolve
It's interesting to see what DSolve
is using Solve
for. This code prints Solve
expressions which occur during the evaluation:
(Note - @belisarius reminds me that TracePrint[DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t], Solve[__],
TraceInternal -> True];
would also work for this purpose)
Internal`InheritedBlock[{Solve},
Unprotect[Solve];
Solve[x___] := Block[{$guard = True},
Print["Solve called : ", HoldForm[Solve[x]]];
Solve[x]] /; ! TrueQ[$guard];
DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t]];
The first of these is just rearranging the original differential equation to get an expression for u'[t]
and causes no problems. The second is an attempt to rearrange the solution, and it's here that the warning is produced. Evaluating Reduce[4 Log[u[t]] + u[t]^2/2 == t + C[1], u[t]]
gives the result and message that rcollyer obtained.
The more general solution that Reduce
provides can also be obtained like this:
SetOptions[Solve, MaxExtraConditions -> All];
DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t]
You could swap Reduce
for Solve
like this:
Internal`InheritedBlock[{Solve}, Unprotect[Solve];Solve = Reduce; Solve[t^2 + t + 1 == 0, t]]
t == -(-1)^(1/3) || t == (-1)^(2/3)
which is indeed Reduce
's output. Solve
's output would have looked like this:
Solve[t^2 + t + 1 == 0, t]
{{t -> -(-1)^(1/3)}, {t -> (-1)^(2/3)}}
Unfortunately, this trick doesn't work for DSolve
:
Internal`InheritedBlock[{Solve}, Unprotect[Solve];Solve = Reduce;
DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t]
]
DSolve[Derivative[1][u][t] == u[t]/(4 + u[t]^2), u[t], t]
It clearly has an effect as it now returns unevaluated, whereas previously you got a solution. So it seems Solve
is indeed used internally. My guess is that the results as returned from Reduce
are not in the form DSolve
expects and wants, so it certainly isn't the last step. I assume that internal error checking then halts execution and spits out the unresolved call.
Given that DSolve
doesn't seem to have options that determine the way the output is treated I don't think that what you want is possible.
As a piggy back onto Sjoerd's solution, here's a solution that will give you Solve
like answers with the conditions still attached:
Block[{Solve, conds},
Unprotect[Solve];
Solve[e_, v_] :=
With[{res = Reduce[e, v]},
(* capture the conditiions via a side-effect *)
conds = res /. Equal[var_?(MemberQ[Flatten[{v}], #] &), __] :> Sequence[];
{
Cases[res,
var_?(MemberQ[Flatten[{v}], #] &) == rhs_ :> Rule[var, rhs],
Infinity
]
}
];
Transpose[{
DSolve[u'[t] == u[t]/(4 + u[t]^2), u[t], t][[1]],
List @@ LogicalExpand[conds]
}]
]
(*
{{u[t] -> -2*
some obscene condition},
...
}
*)
But, it also produces this message:
which could be removed with Quiet
, but I left it in as I don't think it is as bad as the Solve
one. Also, I used Block
instead of Internal`InheritedBlock
as we are completely replacing the behavior of Solve
with something else.