Skip to content
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

Widom excess chemical potential calculation and RxMC performance improvement #4374

Merged
merged 2 commits into from
Nov 2, 2021

Conversation

pm-blanco
Copy link
Contributor

@pm-blanco pm-blanco commented Oct 20, 2021

Description of changes:

  • WidomInsertion.measure_excess_chemical_potential() was replaced by WidomInsertion.calculate_excess_chemical_potential() which returns the instantaneous value of the excess chemical potential instead of the accumulated mean and std. The mean value and std of the excess chemical potential must be now be calculated by the user elsewhere. An example of how to do it is given in samples/widom_insertion.py.
  • ReactionAlgorithm::do_reaction() now only computes the potential energy of the old state at the begininng of the reaction loop. This value is updated after each successful reaction trial move.

@pm-blanco pm-blanco changed the title Widom+rx mc fix Widom+RxMC fix Oct 20, 2021
@RudolfWeeber
Copy link
Contributor

Contentwise this looks good. However, we use semantic versioning. I.e., as long as the major version (4 in 4.1.2) is the same, we promise not to change the outcome of a simulation script silently.
To make your change non-silent, please rename the python function, i.g., calc_instantaneous_chemical_potential()

np.mean(gamma_samples[block * size_block:(block + 1) * size_block]))

mu_ex_mean = -1 * np.log(np.mean(gamma_block)) * temperature
mu_ex_std = np.sqrt(np.var(gamma_block) / np.mean(gamma_block)) * temperature
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a note that this is due to linearized error propagation. In principle you can do better via not using linearization: mu_ex_Delta =abs( -1 * np.log(np.mean(gamma_block)+np.std(gamma_block, dof =1)) * temperature -(-1 * np.log(np.mean(gamma_block)-np.std(gamma_block, dof =1)) * temperature)

the excess chemical potential. The error estimate assumes that
your samples are uncorrelated.

Returns the instantaneous excess chemical potential
Copy link
Member

@jonaslandsgesell jonaslandsgesell Oct 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no instantaneous chemical potential (which is always an ensemble average, please find a better name), it would also miss the application of -kT log().

If you change the logic of how this function works, please describe the needed computations in the doc string

@jonaslandsgesell
Copy link
Member

jonaslandsgesell commented Oct 21, 2021

There is no such thing as an instanteous chemical potential. The chemical potential is per definition an ensemble average. Additionally, the value returned cannot be energy: The application of -kT log is missing (surely because log and the ensemble average do not commute). You could name it compute_exp_of_potential_energy_change_for_excess_chemical_potential_computatiom() which would at be a telling name.

Copy link
Member

@jonaslandsgesell jonaslandsgesell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current naming is misleading, please improve

@@ -123,7 +123,7 @@
n_iterations = 5000
for i in range(n_iterations):

mu_ex = widom.calc_instantaneous_chemical_potential(insertion_reaction_id)
E_ins = widom.calc_particle_insertion_potential_energy(insertion_reaction_id)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider E_pot_insertion. The inserted particles also carry kinetic energy which is not reported in this observable


const double mu = E_pot_new - E_pot_old;
const double E_ins = E_pot_new - E_pot_old;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should avoid abbreviation whenever possible https://medium.com/ltunes/what-is-clean-code-naming-conventions-part-1-426d383eb85d

src/core/reaction_methods/WidomInsertion.hpp Outdated Show resolved Hide resolved
@pm-blanco
Copy link
Contributor Author

@jonaslandsgesell I belive I have resolved all your comments, please take a look and let me know if you find anything else

@jonaslandsgesell
Copy link
Member

Thank you for taking care.

@jonaslandsgesell
Copy link
Member

This PR would be a good check for your benchmark PR. What is the performance before/after your suggested change, when running e.g. 10 reactions in a row for 1000 times?

@pm-blanco
Copy link
Contributor Author

pm-blanco commented Oct 22, 2021

@jonaslandsgesell I did a performance test with the benchmark script of my PR. Performing 1000 MC reactions steps prior my implementation takes ~ 1.5 s on my laptop. Performing the same number of MC steps with the implementation proposed in this PR takes ~ 0.9 s on my laptop. For a sufficiently large number of reaction steps you gain roughly a factor of 2 in computational time (only in the reaction side, of course).

@jonaslandsgesell
Copy link
Member

Could you please add the unittests which checks if the energy is altered after it is passed in? Then this PR is fine from my side

@jngrad
Copy link
Member

jngrad commented Oct 28, 2021

Once the comments by Jonas are resolved, it would be nice to rebase the PR. I find it challenging to follow the changes, because the 19 commits alternate between the Widom refactoring and the ReactionAlgorithm::do_reaction for loop optimization (plus a few random merge and formatting commits). Also most commits don't pass CI, so if I select a commit revision and the code doesn't build or doesn't pass the tests on my workstation, I don't know if the issue comes from my build environment or from the PR.

src/python/espressomd/reaction_ensemble.pyx Show resolved Hide resolved
src/python/espressomd/reaction_ensemble.pyx Outdated Show resolved Hide resolved
src/python/espressomd/reaction_ensemble.pyx Outdated Show resolved Hide resolved
src/python/espressomd/reaction_ensemble.pyx Outdated Show resolved Hide resolved
samples/widom_insertion.py Outdated Show resolved Hide resolved
@pm-blanco
Copy link
Contributor Author

@jonaslandsgesell @jngrad I will try to attend your comments ASAP. Honestly, I have not yet done the unit test because I am unsure on how to implement such test straightforwardly, but I will try to propose something.

@jonaslandsgesell
Copy link
Member

@jonaslandsgesell @jngrad I will try to attend your comments ASAP. Honestly, I have not yet done the unit test because I am unsure on how to implement such test straightforwardly, but I will try to propose something.

@jngrad , could you please assist in the unittest? It might require refactoring to get something which is easily testable.

@pm-blanco
Copy link
Contributor Author

pm-blanco commented Oct 31, 2021

@jonaslandsgesell it took me a while to figure it out how to do it properly, but I managed to implement one unit test in src/core/reaction_methods/tests/ReactionAlgorithm_test.cpp. Basicaly I define a simple identity change reaction D <-> E with a reaction constant Gamma = infinity (i.e. completly shifted to products). Then I create one particle D in the system and I call ReactionAlgorithm::generic_oneway_reaction providing a fake energy of the system equal to 1. Since it is an ideal system with no interactions and the reaction always will be accepted, after this call the energy should be updated to 0. I checked and the test fails if in ReactionAlgorithm::generic_oneway_reaction the energy is provided by value and not by reference and it passes otherwise.
@jngrad I am sorry, but I did not rebase the git history this time. I prefer to practice and learn how to do it properly than mess this PR. Next time I will try to do a more clean PR. I applied all your other revisions.

@pm-blanco
Copy link
Contributor Author

@jngrad it is now failing the CI due to some weird error due to an "unexpected indentation in the docstring" in \src\python\espressomd\reaction_ensemble.pyx, any idea why?

src/python/espressomd/reaction_ensemble.pyx Outdated Show resolved Hide resolved
src/core/reaction_methods/tests/ReactionAlgorithm_test.cpp Outdated Show resolved Hide resolved
src/core/reaction_methods/tests/ReactionAlgorithm_test.cpp Outdated Show resolved Hide resolved
src/core/reaction_methods/tests/ReactionAlgorithm_test.cpp Outdated Show resolved Hide resolved
src/core/reaction_methods/tests/ReactionAlgorithm_test.cpp Outdated Show resolved Hide resolved
src/core/reaction_methods/tests/ReactionAlgorithm_test.cpp Outdated Show resolved Hide resolved
src/python/espressomd/reaction_ensemble.pyx Outdated Show resolved Hide resolved
@jngrad
Copy link
Member

jngrad commented Nov 1, 2021

For the rebase, it's as simple as

# backup current state of the branch
git branch Widom+RxMC_fix_backup
# squash all changes
git reset 5bab6bd51e7

Then do git add -p to select which lines belong to the performance improvement change for the reaction algorithm, commit it, and add the rest to the Widom commit. You can recover the original history at any time with the backed up branch.

@pm-blanco pm-blanco requested a review from jngrad November 2, 2021 09:41
Cache the potential energy value. This saves the cost of an energy
calculation per loop when running multiple reactions.
Widom now returns the particle insertion potential energy and
calculates the excess chemical potential afterwards with block
analysis.
@pm-blanco
Copy link
Contributor Author

@jngrad the PR is now blocked because it does not detect that I did the changes you requested, I belive

@jngrad jngrad added this to the Espresso 4.2 milestone Nov 2, 2021
@jngrad jngrad changed the title Widom+RxMC fix Widom excess chemical potential calculation and RxMC performance improvement Nov 2, 2021
@kodiakhq kodiakhq bot merged commit 7978ce2 into espressomd:python Nov 2, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants