# How to help DSolve obtain this solution to $y'(x)=\sec (y(x))$

V 14

ode = Cos[y[x]]*y'[x] == 1
ic = y[0] == 2
DSolve[{ode, ic}, y[x], x]


Anything can be done to help DSolve obtain the following solution?

## Hand solution

\begin{align*} \cos\left( y\right) y^{\prime} & =1\\ y\left( 0\right) & =2 \end{align*} Integrating gives \begin{align} \int\cos ydy & =\int dx\nonumber\\ \sin y & =x+c \tag{1}% \end{align} Solving for $$c$$ first from (1) gives $$\sin\left( 2\right) =c$$ Substituting this into (1) gives $$$$\sin y=x+\sin\left( 2\right) \tag{2}$$$$ Now we can solve for $$y$$ using trig relation $$\sin\left( y\right) =A\Longrightarrow$$ $$y=-\arcsin\left( A\right) +2\pi n+\pi$$. Using this on the above to solve for $$y$$ gives $$y=-\arcsin\left( x+\sin\left( 2\right) \right) +2n\pi+\pi$$ For $$n$$ integer. Trying $$n=0$$ gives $$y=-\arcsin\left( x+\sin\left( 2\right) \right) +\pi$$ Which satisfies the ode and the IC.

## Verification

mysol = y -> Function[{x}, -ArcSin[x + Sin[2]] + Pi]
{ode, ic} /. mysol


• DSolve[y'[x] == Sec[y[x]], y[x], x] gives the same warning message that you obtained, but it also gives the solution. I am using version 13.3.1 for MacOS. Commented Jun 9 at 12:32
• @StephenLuttrell You need to add the IC $y(0)=2$ to see the issue. Commented Jun 9 at 12:35
• I presume that it is the branch cuts in ArcSin that restrict what Mathematica can automatically compute. I haven't looked into it any further than that. Commented Jun 9 at 17:38

Tricks required:

• For Accessing Reduce from DSolve, we use Reduce in Solve to give a conditional solution.

• DSolve doesn't seem particularly happy that solving a sine equation involves a discrete parameter, so we rename it $c[2]. This fools DSolve to keep going. • But this yields a conditional expression with a spurious condition, which we can post-process. sol = InternalInheritedBlock[{Solve}, Unprotect[Solve]; Solve[eq_, v_, opts___] /; ! TrueQ[$$in] := Block[{in = True, res1, res2}, Solve[eq, v, Method -> Reduce, opts] /. C[2] ->$$c[2] (* DSolve stops if too many C[]'s *) ]; Protect[Solve]; DSolve[{ode, ic}, y[x], x] ] sol = sol /. Rule -> Equal // Map[Solve[(* eliminate discrete parameter *) #, {y[x]}, {$c[2]}] &] //
Apply@Join

(* CHECK *)
ode /. DSolveDSolveToPureFunction[sol] // Simplify
ic /. (# /. x -> 0) & /@ sol // Simplify


DSolve::bvnul: For some branches of the general solution, the given boundary conditions lead to an empty solution.

(*
{{y[x] ->
ConditionalExpression[\[Pi] -
ArcSin[x + Sin[2]], $$c[2] \[Element] Integers &&$$c[2] == 0]}}

{{y[x] -> \[Pi] - ArcSin[x + Sin[2]]}}

{True}  - ODE satisfied

{True}  - IC satisfied
*)


Here's almost the same thing, but using DSolve to get just the general solution and post-processing to solve the IVP:

sol = InternalInheritedBlock[{Solve},
Unprotect[Solve];
Solve[eq_, v_, opts___] /; ! TrueQ[$$in] := Block[{in = True, res1,$$res2},
Solve[eq, v, Method -> Reduce, opts]];
Protect[Solve];

DSolve[{ode}, y, x
] // Map[
Replace[ (* solve IC for each solution component *)
Solve[ic /. #, C[1]],
{{s_Rule} :> (# /. s),(* sub C[1] for IVP sol *)
{} -> Nothing}, (* no solution for IC *)
1] &
] // Map[(* change solution to equation *)
Replace[#,
{{{s_Rule}} :> y[x] == (y[x] /. s), (* Function Rule to Equal *)
{} -> Nothing}] & (* no solution to IC *)
]
] // Solve[(* eliminate discrete parameter *)
#, {y[x]}, {C[2]}] &
(* CHECK *)
ode /. DSolveDSolveToPureFunction[sol] // Simplify
ic /. (# /. x -> 0) & /@ sol // Simplify


Let us switch to the inverse function x[y] . Then y'[x]==1/x'[y] and x[2]==0. Now we have

DSolve[{x'[y] == Cos[y], x[2] == 0}, x[y], y]


{{x[y] -> -Sin[2] + Sin[y]}}

To finish the job

InverseFunction[-Sin[2] + Sin[#] &]


\[Pi] - ArcSin[#1 + Sin[2]] &

and a warning "InverseFunction::ifun: Inverse functions are being used. Values may be lost for multivalued inverses".

• Unfortunately, DSolveChangeVariables[ Inactive[DSolve][{Cos[y[x]]*y'[x] == 1, y[0] == 2}, y, x], u, t, {y[x] == t, x == u[t]}] fails. Commented Jun 9 at 5:20

Here's a second answer that is distinguished by a function localICSolve[] that tries to reduce the general solution to the particular solution by adding assumptions that the dependent and independent variables are in a small neighborhood of the initial condition. I thought a few might like to see it. I wonder if there's a better way to achieve this. I'm not sure how robust it is, but it works on the OP's problem.

(* solve {sol, ic} in neighborhood of initial condition ic *)
localICSolve // ClearAll;
localICSolve[gensol_Equal, ic_Equal, y_[x_]] :=
localICSolve[gensol, ic, y[x], {1/100, 1/10000}];
localICSolve[gensol_Equal, ic_Equal, y_[x_], eps_?Positive] :=
localICSolve[gensol, ic, y[x], {eps, eps*Min[1/10, eps]}];
localICSolve[gensol_Equal, ic_Equal, y_[x_],
{eps1_?Positive, (* neighborhood for solving *)
eps2_?Positive} (* (smaller) neighborhood for simplifying *)
] :=
Replace[Solve[ic], {
{{y[x0_] -> y0_}} :> (* if IC has a simple solution *)
With[{
nbhd1 =(* local neighborhood *)
-eps1 < x - x0 < eps1 && -eps1 < y[x] - y0 < eps1,
nbhd2 =(* hyperlocal neighborhood *)
-eps2 < x - x0 < eps2 && -eps2 < y[x] - y0 < eps2},
Simplify[
Solve[{
gensol
, Reduce[{gensol, y[x] == y0, x == x0}, C[1], {x}] (* solve for C[1] *)
, nbhd1} (* solve locally *)
, y[x], {y[x0], C[1]}] (* eliminate C[
1] to get particular solution *)
, nbhd2] (* simplify in hyperlocal neighborhood *)
]
, _ -> (* failed to solve IC *)
Failure["IC not solved", <|"Sol" -> gensol, "IC" -> ic|>]
}];


We hijack DSolve at the moment it has the implicit solution to the ode and apply localICSolve[] to it:

Trace[
DSolve[ode, y[x], x],
HoldPattern[s : Solve[implicit_, y[x]] /; ! FreeQ[Hold[s], C[1]]] :>
Return[localICSolve[implicit, ic, y[x]], Trace],
TraceInternal -> True]

(*  {{y[x] -> \[Pi] - ArcSin[x + Sin[2]]}}  *)


This is an edit to be explicit motivated by @MichaelE2 comment

Please note the role of y and g have been swapped from my original answer to be consistent with the question but the approach is identical just more explicit. It removes confusionn(alluded to by @MichaelE2 comment).

The motivation for “guess” was noting $$\sin(y)= \sin(\pi-y)$$ and this leads to nice simplifications that avoid forcing Reduce and other simplifications. Other initial conditions could be handled with thoughtful “guesses”.

From inspection the differential equation can be seen as a total derivative. Further, the solution will involve ArcSin but the initial condition is outside function domain of ArcSin in Mma/WL.

We can solve by “guessing” a more suitable form of solution $$y(x) = \pi - g(x)$$ and this is more “digestible” for Mma/WL.

In the following, $$y(x)$$ is the desired solution, $$\pi -g(x)$$ is “guessed” form and pleasantly leaves DE soluble and back substitution yields desired solution.

Dt[Sin[y[x]], x]== 1
de = Dt[Sin[y[x]] /.y[x]→(Pi-g[x]),x] == 1
ysol = Pi-g[x]/.DSolve[{de,Pi-g[0]==2},g[x],x][[1]]


• This is not it: the condition g[0] == 2 means Pi-y[0]==2. Commented Jun 10 at 18:38
• +1, but I think you're fooling people into thinking that your y is the same as the OP's desired y, when it seems to be that g[x] is desired solution. You might consider renaming things y2[x_] := Pi - z[x] etc. Then y2[x] /. DSolve[{eq, y2[0] == 2}, z[x], x]. Or not. Sometimes thinking is fun, sometimes I'm too hasty, tired, or lazy to be bothered. Commented Jun 10 at 19:49
• @MichaelE2 you are absolutely right. I just posted this to show that MMA could get result with a little help/prep but you’d have to use different cheats for different ic. I’ll change when I get a chance. Am late for work. Commented Jun 10 at 20:58
• @MichaelE2 I have tried to make it clearer. I also want to let you know I have learned a lot from your many recent answers: “looking under the hood” but am not brave or smart enough to do myself. So very grateful! Commented Jun 11 at 0:46
• Thank you/you're welcome. P.S. I liked the original reference to the symmetry $\sin y=\sin(\pi-y)$, although I think ode /. y -> Function[x, Pi - y[x]]$\mapsto$ ode might be a better motivation for the guess, which is a symmetry based on knowing the problem (versus a symmetry based on knowing the answer). Commented Jun 11 at 2:36

EDIT1:

Apologies. There was an error by oversight. At first shall post a numerical solution, can come to analytical solution next.

Raise the order of ode to two, priming w.r.t. $$x$$; ode is $$y^{''}=y'^2 \tan y$$

ode = {Y''[x] == Y'[x]^2  Tan[Y[x]]};
ic = {Y[0] == 2., Y'[0] == Sec[2.]};
NDSolve[{ode, ic}, Y, {x, 0, 0.91}];
y[x_] = Y[x] /. First[%];
Plot[y[x], {x, 0, 0.0905}, GridLines -> Automatic, AspectRatio -> .25,
PlotStyle -> {Thick, Green}]
Plot[y'[x] - Sec[y[x]], {x, 0, 0.0905}, GridLines -> Automatic,
AspectRatio -> 1, PlotStyle -> {Thick, Red}]


EDIT2:

We can consider the inverse function by interchanging coordinate axes.

$$y'= \sec y~; \to \frac{-1}{Y'}= \sec X~ \to~ Y'= -\cos X;$$ $$\text {integrating},~ Y= c_1- \sin X ~..$$

• This is not it. Your code ode = {y''[x] == y'[x] Tan[x]}; ic = {y[0] == 2, y'[0] == 1}; sol = DSolve[{ode, ic}, y, x] produces {{y -> Function[{x}, 2 (1 + ArcTanh[Tan[x/2]])]}} which does not satisfy the original ODE: FullSimplify[Cos[y[x]]*y'[x] /. sol] outputs {Cos[2 (1 + ArcTanh[Tan[x/2]])] Sec[x]}, not {1}. Commented Jun 9 at 6:23
• Thanks for pointing it out. Posting a numerical solution at first. Commented Jun 9 at 9:05
• ButNDSolve solves the original problem. Commented Jun 9 at 12:57
• Yes, it is round about ! Commented Jun 9 at 13:24