-
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
Introduced a bugfix to solve the infinite loop in constant pH algorithm #4200
Conversation
…n algorithm when any direction of the acid-base reaction is possible. The program checks if at least one reaction is possible and otherwise exits the subrutine returning a 1. This value should be later processed so the user gets a warning message informing of this error.
src/core/reaction_ensemble.cpp
Outdated
bool reaction_possible = false; | ||
|
||
for (int reaction_id = 0; reaction_id < reactions.size(); reaction_id++) { | ||
if (all_reactant_particles_exist(reaction_id)) { | ||
reaction_possible = true; | ||
} | ||
} | ||
|
||
if (reaction_possible == false) { | ||
return 1; | ||
} | ||
|
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.
isn't it possible to get this kind of logic implicitly? If no particle of the reactant type is found nothing should happen automatically without manually checking?
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 problem that causes the infinite loop has its source in the while loop in lines 1521-1546. This while loop searches the particle ids that have a type that matches the reactant/product types. Of course, if you do not create such particle, then this loop runs for ever.
As you suggest, another possible solution would be to do this task without using a while statement so that if there is no reactant then the program does nothing. However, in my opinion, manually checking it has the advantage that we can integrate an exception error preventing the user from doing such simulation (since I cannot think where one would attempt to run the algorithm without reactants if it is not by mistake).
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 point is that such situation should not occur. If it occurs, then it is an error in the system setup, so it cannot be a simple no-op. It should raise an error.
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.
in my mind the reaction algorithm itself should be independent of the state of the system. I can also define a non bonded interaction of two non existing particle types without having an infinite loop. The reaction of reactants is also some kind of particle interaction, right? Why should it be special 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.
All methods default to a no-op when not enough particles are present, except for WidomInsertion
which throws an error. I don't immediately see why it should be an issue to not have enough particles of type HA if there is at least one particle of type A-. Could you please clarify this for us?
Also if you reverse the reactant types with the adduct types, you will get a bug in the other direction, if I understand e4104d2 correctly.
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.
@jngrad thank you for your clarification, now I understand your point. Now I agree with you that the desired output would be a no-op so one could couple the acid/base reaction with other reactions
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.
Indeed, @jngrad is right that all reactants could be consumed if different reactions are competing for the same product or reactant. However, I would discourage anybody from intentionally using RxMC in this regime. It suffers from serious finite-size artifacts if the number of (any type of) reacting particles is on the order of unity. It is related to the fact that particle numbers in a simulation have to be integers whereas most existing theories work with concentrations as continuous variables.
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.
Note: SN2 refers to a specific reaction mechanism. A reaction of the type A- + BX <--> AB + X- is not compatible with the way currently reactions are implemented in Espresso. The current implementation allows to create or destroy particles at random positions but it does not allow to transfer a particle between two binding partners. It is also one of the points on our wishlist.
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.
Be aware it definitely depends on what you mean:
Of course it is totally valid to create this reaction
A+B <-> C+D
Whit artbitrary A, B, C, D. I.e. also :
A- + BX <--> AB + X-
However all the types will be "primitive" beads i.e. not have bonds in the bead "BX". But it is completely fine for the "BX" type to have different lenard jones parameters (i.e. appear bigger) etc...
Maybe this would require having a type dependent exclusion radius for some more extreme variations...
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.
A reaction of the type A- + BX <--> AB + X- is not compatible with the way currently reactions are implemented in Espresso. The current implementation allows to create or destroy particles at random positions but it does not allow to transfer a particle between two binding partners.
Good point. I also thought about the case of the titration curve of a buffer solution, i.e. a mixture of a weak acid and a strong acid. Titration by a strong base can trigger the bug once the buffer capacity is used up. But that's an edge case, one probably wouldn't want to add more base than there is buffer.
… occur because there are not enough reactants
In my view, there are two issues:
system.cell_system.skin = 0
system.time_step = 1
system.integrator.run(1) without particles (no-op, as-well) |
Espresso also allows definition of non-bonded interactions for types for which there are (at that point) no particles. The Python call |
I like the solution proposed by @RudolfWeeber Indeed, the user might want to first create a reaction and then particles. However, if we change the behaviour and return value of |
PR superseded by #4207. |
Fixes #4197
When attempting to do a reaction step using the constant pH algorithm, if there are not enough reactants nor product particles, the program simply not does the operation. The apparition of an infinite loop is prevented by existing the reaction subroutine in case that neither direction of the reaction is possible.
Description of changes: