DSolve crashes on elementary differential equations

Dear Community,
About two years ago I sent a bug report about DSolve to Support and here on Community.
It was for y’(x)=sqrt(y(x)). (which at the time returned 2 solutions)
No one at Support or here admitted there was a bug in DSolve…
But incindently the bug was corrected in the next release.
Now have a look on the notebook and watch DSolve crash on 2 elementary DE.
I sent only two examples of the bug but there are many…
ALL the DSolve functions should be greatly improved.
After all this is 14.2.1.
Kind regards,
Jean-Michel

Sans titre-1.nb (6.74 KB)

Maybe for such equations Mathematica would do better giving the implicit function version of the differential equations

Cos[y[x]] + Tanh[x + C[1]] == 0
Cosh[y[x]] + Tanh[x + C[1]] == 0

and leave it at that. Instead, it gives two partial solutions based on branches of the inverses of Cos and Cosh. I would not call this a bug, because a warning is generated about a possible loss of solutions.

Is it really too much trouble to state the equations in the text of the message? And what exactly is crashing?

It’s not clear that there is anything you want to discuss, and you certainly don’t ask any questions. What I would like to see is a way for the user to request DSolve[] to work harder, in the way we can use Reduce[] instead of Solve[], or use MaxExtraConditions in Solve[]. I think there’s great value in DSolve[] being quick and generic (okay, “quick” as a design goal, even if it sometimes takes forever). But it’s also the case the Mathematica can give a more robust solution in some cases, if the user is willing to let Mathematica perform operations that risk being computationally intensive.

For instance DSolve[{y'[x] == Sin[y[x]], y[0] == y0}, y, x] returns only two one-parameter families of solutions. But the ODE y'[x] == Sin[y[x]] admits the symmetries generated by {{y -> -y}, {y -> Pi-y}, {x -> x+C[1]}}. So there are infinitely many one-parameter families of solutions.

For instance, the following hacky way culls the implicit solution before it’s solved, so that we can get the complete solution, which DSolve[] does not do on its own:

ode = y'[x] == Sin[y[x]];
implSOL = Trace[
  DSolve[{ode, y[0] == y0}, y, x]
  , s : HoldPattern[Solve[_, y[x], ___]] :> 
          Return[Inactivate[s, Solve], Trace]
  , TraceInternal -> True]
dsol2 = Activate[implSOL] // DSolve`DSolveToPureFunction
ode /. % // FullSimplify
(*
Solve[-ArcTanh[Cos[y[x]]]\[Equal]x+C[1],y[x]]

{{y -> Function[{x},ConditionalExpression[-ArcCos[-Tanh[x+C[1]]]+2 \[Pi] C[2], <<>>]]},
 {y -> Function[{x},ConditionalExpression[ArcCos[-Tanh[x+C[1]]]+2 \[Pi] C[2],<<>>]]}}

{ConditionalExpression[True,<<>>], ConditionalExpression[True,<<>>]}
*)

If we add assumptions that only a single one-parameter family satisfies, DSolve[y'\[x\] == Sin[y\[x\]\], y, x, Assumptions -> 0 < y\[x\] < Pi && {x, C[1]} \[Element] Reals] still returns two families, one of which satisfies the assumptions. This does not bother me in one way, because I appreciate the difference between “if P then Q” (P is an assumption) and “P and Q” (P is a constraint). In another way, it bothers me that I can’t add a constraint to the solution. So here is another hacky way in which we treat $Assumptions as constraints when Solve\[\] is called by DSolve\[\]:

Internal`InheritedBlock[{Solve},
 Unprotect[Solve];
 Solve[eq_, v_, opts___] /; ! TrueQ[$in] := 
  Block[{$in = True}, 
   Simplify@Solve[Flatten@{eq, $Assumptions}, v, opts]];
 Protect[Solve];
 DSolve[y'[x] == Sin[y[x]], y, x, 
  Assumptions -> 0 < y[x] < Pi && {x, C[1]} \[Element] Reals]]

(*  {{y -> Function[{x}, ArcCos[-Tanh[x + C[1]]]]}}  *)

There is no problem, theoretically, solving any IVP for this ODE. But DSolve[] fails if the initial condition cannot be satisfied by one of the two one-parameter familiar in its “general solution”:

DSolve[{y'[x] == Sin[y[x]], y[0] == 3 Pi/2}, y, x, 
 Assumptions -> 0 < y[x] < Pi && {x, C[1]} \[Element] Reals]

(* DSolve::bvnul, DSolve::ifun errors  *)
(*  {}  *)

But if I add constraints to Solve[] as above, then Solve[] will find the right branch of the general solution for the IVP:

Internal`InheritedBlock[{Solve},
 Unprotect[Solve];
 Solve[eq_, v_, opts___] /; ! TrueQ[$in] := 
  Block[{$in = True}, 
   Simplify@Solve[Flatten@{eq, $Assumptions}, v, opts]];
 Protect[Solve];
 DSolve[{y'[x] == Sin[y[x]], y[0] == 3 Pi/2}, y, x, 
  Assumptions -> Pi < y[x] < 2 Pi && {x, C[1]} \[Element] Reals]]

(*  {{y -> Function[{x}, 2 \[Pi] - ArcCos[-Tanh[x]]]}}  *)

Indeed, we can find the general solution for this range of y, a solution that is not contained in the “general solution” returned by DSolve[{y'[x] == Sin[y[x]], y[0] == y0}, y, x]:

Internal`InheritedBlock[{Solve},
 Unprotect[Solve];
 Solve[eq_, v_, opts___] /; ! TrueQ[$in] := 
  Block[{$in = True}, 
   Simplify@Solve[Flatten@{eq, $Assumptions}, v, opts]];
 Protect[Solve];
 DSolve[y'[x] == Sin[y[x]], y, x, 
  Assumptions -> Pi < y[x] < 2 Pi && {x, C[1]} \[Element] Reals]]

(*  {{y -> Function[{x}, 2 \[Pi] - ArcCos[-Tanh[x + C[1]]]]}}  *)

Since you express interest in the improvement of DSolve[], someone on mathematica.stackexchange has been tracking its progress for several version and posts their results here:

https://mathematica.stackexchange.com/questions/221959/is-mathematica-adequately-improving/221960#221960