-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Cleanup differential equations examples. #22043
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
Conversation
examples/mplot3d/lorenz_attractor.py
Outdated
ys[i + 1] = ys[i] + (y_dot * dt) | ||
zs[i + 1] = zs[i] + (z_dot * dt) | ||
|
||
xyzs[i + 1] = xyzs[i] + lorenz(*xyzs[i]) * dt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how idiomatic we want to be in python - many scientific programmers, moving between languages, are not going to understand what you are doing here with the *xyzs. Even if it is more typing and even a bit more error prone, I think writing the code out is easier to parse than nice encapsulations like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair point. Would you think it would be better if lorenz() took a single xyz as sole arg, and did x, y, z = xyz
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for array in, array out
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The *
is still here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, fixed.
@@ -51,7 +50,7 @@ def derivs(state, t): | |||
return dydx | |||
|
|||
# create a time array from 0..t_stop sampled at 0.02 second steps | |||
dt = 0.02 | |||
dt = 0.01 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check if this is really necessary. This doubles the number of frames and thus likely the size of the generated file.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I decreased the end time by a factor of two as well; the shorter time step does appear to improve the accuracy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But that means that you're only going half the path from before. Please check if that's still a reasonable path length. I'm afraid that might be a bit short.
I can imagine that the shorter time step improves accuracy. But does that matter here? Alternatively, one could also render only every second step, but that adds additional compelity to the code and I'm not sure that's worth it.
Of course, one could also change to another example like a regular single pendulum. That's simpler to calculate and one could have a continuous cyclic animation with, a period of e.g. 2s.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did check, the path length is fine.
@@ -64,8 +63,13 @@ def derivs(state, t): | |||
# initial state | |||
state = np.radians([th1, w1, th2, w2]) | |||
|
|||
# integrate your ODE using scipy.integrate. | |||
y = integrate.odeint(derivs, state, t) | |||
# integrate the ODE using Euler's method |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes the example longer and IMHO a little harder to understand. Does this outweigh the benefit of not depending on scipy in this example?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The only other use of scipy in the docs can also easily be removed (I have another patch ready for that) so we could entirely drop the dependency on scipy for building the docs, which may or may not be a useful thing (e.g., with the yearly release cycle of cpython, I fear that we're always going to have a small period between having scipy wheels available after the new cpython release, and scipy is significantly harder to build from source (e.g., due to fortran sources) than other dependencies, even numpy).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think dropping SciPy would be pretty helpful if we don't need it. I think its a pretty heavy dependency to carry around for a couple of examples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have oscillated back and forth on having a scipy documentation dependencies a couple of times. I do not have a strong preference either way.
examples/mplot3d/lorenz_attractor.py
Outdated
ys[i + 1] = ys[i] + (y_dot * dt) | ||
zs[i + 1] = zs[i] + (z_dot * dt) | ||
|
||
xyzs[i + 1] = xyzs[i] + lorenz(*xyzs[i]) * dt |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 for array in, array out
Slightly cleanup the lorenz_attractor example; also use Euler's method for the double pendulum. It is less accurate, but sufficient for illustrative purposes (also, 1. the double pendulum is chaotic anyways so even RK4 will end up quite far from the actual behavior, if one waits for long enough, as can be checked by trying various integrators in solve_ivp; 2. we're fine with using Euler's method for the also chaotic lorenz_attractor). The point is also to make fewer examples dependent on scipy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When doc CI finishes, I think this can be merged...
PR Summary
Slightly cleanup the lorenz_attractor example; also use Euler's method
for the double pendulum. It is less accurate, but sufficient for
illustrative purposes (also, 1. the double pendulum is chaotic anyways
so even RK4 will end up quite far from the actual behavior, if one waits
for long enough, as can be checked by trying various integrators in
solve_ivp; 2. we're fine with using Euler's method for the also chaotic
lorenz_attractor).
The point is also to make fewer examples dependent on scipy.
PR Checklist
Tests and Styling
pytest
passes).flake8-docstrings
and runflake8 --docstring-convention=all
).Documentation
doc/users/next_whats_new/
(follow instructions in README.rst there).doc/api/next_api_changes/
(follow instructions in README.rst there).