Solution of nonlinear ODE

25 views
Skip to first unread message

Nicolas Guarin

unread,
Sep 10, 2021, 11:39:51 AM9/10/21
to sympy

I have the following ODE

    z'' = 1 - z²

That has as solutions z=tanh(C + t) and z=coth(C + t), depending on the initial condition being greater or less than 1. When I use dsolve I get the latter


from sympy import *
init_session()
ode = Eq(f(t).diff(t), 1 - f(t)**2)
sol = dsolve(ode, f(t))

And sol is

                   -1      
f(t) = ────────────  ,
                tanh(C₁ - t)

That is equivalent to coth(C + t).

Is there any reason for SymPy to give this answer and not the other or is this a bug?



Oscar Benjamin

unread,
Sep 10, 2021, 5:44:52 PM9/10/21
to sympy
Are the different solutions not equivalent for different values of the constants (bearing in mind the possibility for the constants to be non-real)? This suggests that one solution can be transformed to the other for appropriate values of the constants:

In [41]: C1, C2 = symbols('C1, C2')


In [42]: s1, s2 = solve(Eq(tanh(C1 + t), coth(C2 + t)), C1)


In [43]: s1.rewrite(exp).simplify()

Out[43]: 

     2⋅C₂⎞

log⎝-ℯ   

───────────

     2     


In [44]: s2.rewrite(exp).simplify()

Out[44]: 

       ________⎞

       2⋅C₂ ⎟

log⎝-╲╱  -ℯ    


In other words tanh(C1 + t) can be equivalent to coth(C2 + t) if C1 = log(-exp(2*C2))/2. Of course if C2 is real then this implies that C1 is not.

Oscar

Aaron Meurer

unread,
Sep 10, 2021, 6:18:48 PM9/10/21
to sympy
Perhaps it would help to set a variable for the initial condition and
solve for that. Unfortunately, dsolve() doesn't presently handle the
case where the initial condition splits into two solutions.

>>> var('t0')
t0
>>> dsolve(ode, f(t), ics={f(0): t0})
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "./sympy/solvers/ode/ode.py", line 639, in dsolve
return _helper_simplify(eq, hint, hints, simplify, ics=ics)
File "./sympy/solvers/ode/ode.py", line 694, in _helper_simplify
solved_constants = solve_ics([rv], [r['func']], cons(rv), ics)
File "./sympy/solvers/ode/ode.py", line 808, in solve_ics
raise NotImplementedError("Initial conditions produced too many
solutions for constants")
NotImplementedError: Initial conditions produced too many solutions
for constants

I think it would be useful if it just returned both solutions here.
Internally, it is producing these two solutions

>>> sol.subs(solved_constants[0])
Eq(f(t), -1/tanh(-t + log(-sqrt((t0 - 1)/(t0 + 1)))))
>>> sol.subs(solved_constants[1])
Eq(f(t), -1/tanh(-t + log((t0 - 1)/(t0 + 1))/2))

It would then take some work to simplify this to your desired forms
(SymPy's own simplification algorithms could be improved here), but at
least in this form you can see how one solution produces a real
function for t0 > 1 and one for t0 < 1. I believe the critical
identities for the simplification are

>>> tanh(x + I*pi/2)
coth(x)
>>> coth(x + I*pi/2)
tanh(x)
>>> log(I)
I*pi/2

and of course 1/tanh(x) = coth(x).

Aaron Meurer
> --
> You received this message because you are subscribed to the Google Groups "sympy" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAHVvXxR2GB86zb07TNLvS%3DQz3CRogyGW9S6Vv%3DxrZ%2BEJ2nAkcQ%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages