-
-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Riccati ODE solver to dsolve benchmarks #76
base: master
Are you sure you want to change the base?
Conversation
@oscarbenjamin Some existing tests are failing. I fixed the failure in |
Are you asking about this?
I think that what has happened is that |
Yes. Now |
The The previous output was: In [1]: v = Function('v')
In [2]: t, k0, k1, u0 = symbols('t, k0, k1, u0')
In [3]: eq = Eq(Derivative(v(t), t), k0*u0*exp(-k0*t) - k1*v(t))
In [4]: eq
Out[4]:
d -k₀⋅t
──(v(t)) = k₀⋅u₀⋅ℯ - k₁⋅v(t)
dt
In [5]: dsolve(eq)
Out[5]:
⎛ ⎛⎧ k₁⋅t ⎞⎞
⎜ ⎜⎪ -ℯ ⎟⎟
⎜ ⎜⎪─────────────────── for k₀ ≠ k₁⎟⎟ -k₁⋅t
v(t) = ⎜C₁ + k₀⋅u₀⋅⎜⎨ k₀⋅t k₀⋅t ⎟⎟⋅ℯ
⎜ ⎜⎪k₀⋅ℯ - k₁⋅ℯ ⎟⎟
⎜ ⎜⎪ ⎟⎟
⎝ ⎝⎩ t otherwise ⎠⎠ The new output is In [5]: dsolve(eq)
Out[5]:
⎡ ⎧ C₁⋅k₀ C₁⋅k₁ k₀⋅u₀ ⎤
⎢ ⎧ -k₀⋅t -k₀⋅t ⎪─────────────────── - ─────────────────── - ─────────────────── for k₀ ≠ k₁⎥
⎢ ⎪C₁⋅ℯ + k₀⋅t⋅u₀⋅ℯ for k₀ = k₁ ⎪ k₁⋅t k₁⋅t k₁⋅t k₁⋅t k₀⋅t k₀⋅t ⎥
⎢v(t) = ⎨ , v(t) = ⎨k₀⋅ℯ - k₁⋅ℯ k₀⋅ℯ - k₁⋅ℯ k₀⋅ℯ - k₁⋅ℯ ⎥
⎢ ⎪ nan otherwise ⎪ ⎥
⎢ ⎩ ⎪ nan otherwise ⎥
⎣ ⎩ ⎦ This is really just a convoluted way of writing the same thing. If In [15]: sol1, sol2 = dsolve(eq)
In [16]: sol2.rhs.args[0][0]
Out[16]:
C₁⋅k₀ C₁⋅k₁ k₀⋅u₀
─────────────────── - ─────────────────── - ───────────────────
k₁⋅t k₁⋅t k₁⋅t k₁⋅t k₀⋅t k₀⋅t
k₀⋅ℯ - k₁⋅ℯ k₀⋅ℯ - k₁⋅ℯ k₀⋅ℯ - k₁⋅ℯ
In [17]: sol2.rhs.args[0][0].collect(Symbol('C1'), cancel)
Out[17]:
-k₁⋅t k₀⋅u₀
C₁⋅ℯ - ───────────────────
k₀⋅t k₀⋅t
k₀⋅ℯ - k₁⋅ℯ Of course the single Piecewise solution is the preferred form so this is a regression. Looks related to the comment here: sympy/sympy#21124 (comment) |
I'm really not sure why that |
I guess the benchmarks are tested to make sure they don't break, and also so you can run the tests against an older version of SymPy to ensure that the benchmarks actually do benchmark the right thing. The latter case is more important in my opinion. If we want to guard against regressions, we should add the tests to the SymPy test suite. And if the goal is just to be able to check validity of the benchmark, the tests here should be written in a much more generic way. Instead of asserting an exact solution, it should only check that it is mathematically correct, e.g., using checkodesol, or using some sort of numerical consistency checks for non-solver benchmarks where this isn't possible. |
See sympy/sympy#21459