-
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
Electroneutrality breaks when combining Widom + cpH methods #4595
Comments
I can reproduce it on 4.2.0 with 2 MPI ranks, but not with 1 MPI rank. The bug also doesn't always happen. Could not reproduce it on 4.3-dev. |
I cannot bisect the bug due to how randomly it happens. UBSAN doesn't catch any undefined behavior on 1 MPI rank. On 2 MPI ranks it catches a null pointer dereference in the boost::mpi code when runtime error messages are reduced on the head node after setting the box size (no idea why). |
@jngrad I did some tests on my work station too. I can reproduce it with 4.2.0 with 1, 2 and 4 MPI ranks (although not always happens, sometimes it actually runs). It never seem to happen in the devel version with any number of ranks. I am very confused about this bug, I will try to dig further into it and see if I can pin point its origin |
@davidbbeyer @jngrad I have make some progress in improving the reproducibility of this bug. I have updated the example script, it now produces the bug with both espresso 4.2.0 and espresso devel. The bug can be switched on and off with
|
Ok, I finally have pinpointed the origin of the bug. The problem is on the bookkeeping of "empty ids" done with the attribute |
@pm-blanco Good find! I completely forgot about that bookkeeping feature. Ideally this container of "free" ids should have been a shared pointer global variable in Just for future reference, and for readers of the bugfix release changelog, here is an illustration of the second variant of the bug. Consider a system of 10 particles with id 0 to 9. A reaction deletes particle with id 5 and marks it as "available". Then the user creates a particle with id 5. This particle id will be later used to create a new particle by the reaction algorithm. But in ESPResSo, the function that creates a particle doesn't throw an error if the particle already exists, and instead silently moves it (terrible design decision!). If the user-defined particle has an electric charge that differs from the one that will be created, the system will throw a runtime error about the system not being charge-neutral. However if the reaction is uncharged, there is now way to notify the user that something went wrong. Here is a MWE derived from a sample: diff --git a/samples/reaction_ensemble_complex_reaction.py b/samples/reaction_ensemble_complex_reaction.py
index cd727a587..308dc0fca 100644
--- a/samples/reaction_ensemble_complex_reaction.py
+++ b/samples/reaction_ensemble_complex_reaction.py
@@ -100,7 +100,13 @@ numbers = {type_A: [], type_B: [], type_C: [], type_D: [], type_E: []}
RE.set_non_interacting_type(type=max(types) + 1)
# warmup
-RE.reaction(reaction_steps=200)
+RE.reaction(reaction_steps=2)
+p = system.part.add(pos=np.random.random(3) * system.box_l, type=55, id=52)
+print(p.type, p.pos)
+RE.reaction(reaction_steps=2)
+p = system.part.by_id(52)
+print(p.type, p.pos)
+exit(0)
for i in range(200):
RE.reaction(reaction_steps=10) Here is the output, with printfs to show when an id is added or taken from
Computing the free id when needed as proposed by @pm-blanco is probably the best solution, even though it comes with a performance penalty. @RudolfWeeber do you have any objection? |
Description of changes: - particle state tracking is now fully encapsulated - helps with separation of concerns and reducing code duplication - particle creation and particle moves are now carried out by 2 independent functions - this makes the reaction methods bugs throw an error instead of silently reacting particles of the wrong type (#4595)
Fixes #4595 Description of changes: - Reaction methods now rebuild the list of free particle ids every time `ReactionAlgorithm::do_reaction()` and `WidomInsertion::calculate_particle_insertion_potential_energy()` are called - Added a new test that checks that the reaction methods do the bookkeeping of empty ids by setting up two different instances of the reaction methods (constant pH and Widom insertion) with competing reactions. I benchmarked my implementation against the current python branch using the `mc_acid_base_reservoir.py` script and I get the following timings: 1.564e-04 (my PR) vs 1.473e-04 (current python branch). That means that my implementation comes with a 6% performance loss in its current state.
Fixes espressomd#4595 Description of changes: - Reaction methods now rebuild the list of free particle ids every time `ReactionAlgorithm::do_reaction()` and `WidomInsertion::calculate_particle_insertion_potential_energy()` are called - Added a new test that checks that the reaction methods do the bookkeeping of empty ids by setting up two different instances of the reaction methods (constant pH and Widom insertion) with competing reactions. I benchmarked my implementation against the current python branch using the `mc_acid_base_reservoir.py` script and I get the following timings: 1.564e-04 (my PR) vs 1.473e-04 (current python branch). That means that my implementation comes with a 6% performance loss in its current state.
Fixes espressomd#4595 Description of changes: - Reaction methods now rebuild the list of free particle ids every time `ReactionAlgorithm::do_reaction()` and `WidomInsertion::calculate_particle_insertion_potential_energy()` are called - Added a new test that checks that the reaction methods do the bookkeeping of empty ids by setting up two different instances of the reaction methods (constant pH and Widom insertion) with competing reactions. I benchmarked my implementation against the current python branch using the `mc_acid_base_reservoir.py` script and I get the following timings: 1.564e-04 (my PR) vs 1.473e-04 (current python branch). That means that my implementation comes with a 6% performance loss in its current state.
Fixes espressomd#4595 Description of changes: - Reaction methods now rebuild the list of free particle ids every time `ReactionAlgorithm::do_reaction()` and `WidomInsertion::calculate_particle_insertion_potential_energy()` are called - Added a new test that checks that the reaction methods do the bookkeeping of empty ids by setting up two different instances of the reaction methods (constant pH and Widom insertion) with competing reactions. I benchmarked my implementation against the current python branch using the `mc_acid_base_reservoir.py` script and I get the following timings: 1.564e-04 (my PR) vs 1.473e-04 (current python branch). That means that my implementation comes with a 6% performance loss in its current state.
@davidbbeyer and I have observed that when combining the Widom insertion method with the constant pH method (and possibly also with the Reaction ensemble) leads to the destruction of an additional ion, ultimately breaking the electroneutrality of the system.
Below I provide a minimal example script that produces the bug. This only happens in the 4.2.0 version of espresso but it does not happen in the previous version 4.1.4, so it could be related to one of the newer changes we introduced.
The text was updated successfully, but these errors were encountered: