-
Notifications
You must be signed in to change notification settings - Fork 188
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
Refactor exception mechanism in P3M/DP3M tuning functions #3869
Conversation
Regression introduced in a6794cc. The error code is now handled.
The old exception mechanism simply printed the error message to a log string, without halting the flow of the program. This either left the system in an undefined state, or caused other errors to be thrown at the end of the tuning functions, making it difficult to trace the true origin of the issue.
Provide working code samples, add missing list of P3M papers, cleanup outdated documentation.
@RudolfWeeber could you please have a look at the DP3M bisection code? I don't understand why it fails for specific particle configurations. Here is a MWE: import espressomd
import espressomd.magnetostatics
system = espressomd.System(box_l=3*[1])
system.time_step = 0.01
system.part.add(pos=[[0, 0, 0], [0.5, 0.5, 0.5]], rotation=2 * [(1, 1, 1)], dip=2 * [(1, 0, 0)])
solver = espressomd.magnetostatics.DipolarP3M(prefactor=1, accuracy=1e-2)
system.actors.add(solver) # infinite loop The infinite loop was solved in this PR by correctly propagating the error code. But where is the mistake in my MWE? If I set the box dimensions to More generally though, the error code propagation logic in P3M/DP3M badly needs refactoring. We're forwarding integer error codes as floating-point return values. The pointer output arguments are just asking for trouble, I originally ended up with uninitialized values due to early exits from the new exception mechanism and was saved by Clang-Tidy. |
Furthermore, there is this suspicious piece of code in the tuning function that has no coverage: espresso/src/core/electrostatics_magnetostatics/p3m.cpp Lines 965 to 972 in 5ba0735
The body of the first conditional is never visited. Several issue here:
|
Are you sure? I think the dipole correction is not implemented for non-cubic boxes. |
Is it only a restriction on the tuning function? The electrostatics docs don't mention such a restriction. Also, |
If I remember correctly, for the non-cubic case the calculation of the dipole correction is way more complicated, potentially not even available in closed form. If think this is discussed in https://link.springer.com/article/10.1023/A:1018775311536. |
So, one should not be allowed to set epsilon to non-metallic if the box is not cubic. Metallic boundaries are used in 99% of the cases anyway, I'm not even sure that epsilon should be settable, this is more of an expert feature in my opinion. |
Then why don't we throw an error? The rectangular case runs just fine: import espressomd.electrostatics
system = espressomd.System(box_l=[10, 10, 20])
system.time_step = 0.01
system.cell_system.skin = 0.4
system.part.add(pos=[[0, 0, 0], [.5, .5, 1]], q=[-1, 1])
system.non_bonded_inter[0, 0].wca.set_params(epsilon=1.0, sigma=0.1)
solver = espressomd.electrostatics.P3M(prefactor=2, accuracy=1e-2, epsilon=78.)
system.actors.add(solver)
system.integrator.run(100) |
Now that's just brilliant: we overwrite espresso/testsuite/python/p3m_gpu.py Line 41 in 5ba0735
|
The epsilon value was set to zero during tuning before the call to `self._set_params_in_es_core()`. All simulations with a non-zero epsilon were internally using epsilon = 0.0 since ESPResSo 4.0.0. This only affects the P3M and P3MGPU actors, the DipolarP3M and MMM1D actors are not affected.
Range checking was incorrectly rejecting integer values for epsilon.
P3M doesn't support the non-metallic case with non-cubic boxes.
Yeah, the whole cython coulomb complex is quite ... special |
The tests look good. For the rest, I understand that you don't want to put work into this, but in my opinion a minimal solution would be to switch to an error reporting mechanism were non-results can not be ignored, e.g. optional return values, instead of meddling with the signaling return values. This way it can be made sure that errors are not ignored in the future. (E.g. use boost.outcome, if this is available with our version) |
The issue is that we're working for 4.1, where we still have an Ubuntu 16.04 image with boost 1.58. Could we use exceptions to store the error code and catch it in the core tuning function that is called from python? |
I don’t think, tuning fixes should go into 4.1.4, maybe with the exception of the epsilon overwriting thing.
Particularly, if including it in 4.1 makes the fix difficult.
|
Sure, you can also just use exceptions. It is probably better to not needlessly introduce new things (although I think outcome or similar is actually a interesting contribution to the error reporting design space). Please also note that I did not say you should change something, I just pointed out that your fix does not exclude the same type of problem in the future, and that there are solutions that do that. |
@fweik Yes, my fix is brittle and I'd prefer to see a proper exception mechanism. @RudolfWeeber if we don't include the tuning fixes in 4.1, users will still have infinite loops (upon DP3M bisection failure and any P3M failure) and useless error messages (upon any failure, e.g. system with no particles). |
…#3869) Fixes espressomd#3868 Description of changes: - core: correctly propagate errors codes in the P3M/DP3M tuning functions to avoid infinite loops - core: rely on `runtimeErrorMsg()` instead of printing error messages to stderr or char arrays - python: catch errors from the P3M/DP3M tuning functions in the `tune()` method of the relevant python Actors - python: fix the broken `'metallic'` case of the P3M `epsilon` parameter - testsuite: add tests for the `'metallic'` case and for the new exception mechanism - python: fix the non-metallic epsilon case (epsilon was always set to 0 for `P3M ` and `P3MGPU` in the core since 4.0.0) - documentation: fix broken code examples in the user guide - documentation: mention P3M doesn't support non-cubic boxes for non-metallic epsilon
…#3869) Fixes espressomd#3868 Description of changes: - core: correctly propagate an error code in the P3M tuning function to avoid an infinite loop - python: fix the broken `'metallic'` case of the P3M `epsilon` parameter - python: fix the non-metallic epsilon case (epsilon was always set to 0 for `P3M ` and `P3MGPU` in the core since 4.0.0) - documentation: fix broken code examples in the user guide - documentation: mention P3M doesn't support non-cubic boxes for non-metallic epsilon
Fixes #3868
Description of changes:
runtimeErrorMsg()
instead of printing error messages to stderr or char arraystune()
method of the relevant python Actors'metallic'
case of the P3Mepsilon
parameter'metallic'
case and for the new exception mechanismP3M
andP3MGPU
in the core since 4.0.0)