Skip to content

Commit fb7d1a4

Browse files
jngradpm-blanco
andauthored
Monte Carlo re-implementation in Python (#4765)
Description of changes: - rewrite Monte Carlo methods in Python - allow user-defined MC acceptance criteria - API change: reaction methods now take a `system` argument Co-authored-by: Pablo Miguel Blanco Andrés <blancoapa@natur.cuni.cz>
1 parent 13f6e2b commit fb7d1a4

63 files changed

Lines changed: 1827 additions & 3594 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
3535
# project info
3636
project(
3737
ESPResSo
38-
VERSION "5.0.1"
38+
VERSION "5.1.0"
3939
LANGUAGES C CXX
4040
HOMEPAGE_URL "https://espressomd.org"
4141
DESCRIPTION

doc/sphinx/particles.rst

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -734,23 +734,13 @@ Particle number counting feature
734734

735735

736736
Knowing the number of particles of a certain type in simulations where
737-
particle numbers can fluctuate is of interest.
738-
Particle ids can be stored in a map for each individual type::
737+
particle numbers can fluctuate is of interest::
739738

740739
import espressomd
741740
system = espressomd.System(box_l=[1, 1, 1])
742-
system.setup_type_map([_type])
743741
system.number_of_particles(_type)
744742

745-
If you want to keep track of particle ids of a certain type you have to
746-
initialize the method by calling ::
747-
748-
system.setup_type_map([_type])
749-
750-
After that the system will keep track of particle ids of that type. Keeping
751-
track of particles of a given type is not enabled by default since it requires
752-
memory. The keyword ``number_of_particles`` as argument will return the number
753-
of particles which have the given type. For counting the number of particles
743+
For counting the number of particles
754744
of a given type you could also use
755745
:meth:`ParticleList.select() <espressomd.particle_data.ParticleList.select>` ::
756746

@@ -763,9 +753,8 @@ of a given type you could also use
763753
print(len(system.part.select(type=2)))
764754

765755
However calling ``select(type=type)`` results in looping over all particles,
766-
which is slow. In contrast, the system
767-
:meth:`~espressomd.system.System.number_of_particles` method can return the
768-
number of particles with that type.
756+
and creating temporary particle objects, which is slow. In contrast, the system
757+
:meth:`~espressomd.system.System.number_of_particles` method has low overhead.
769758

770759
.. _Self-propelled swimmers:
771760

doc/sphinx/reaction_methods.rst

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ Please keep in mind the following remarks:
3535
:meth:`~espressomd.reaction_methods.ReactionAlgorithm.set_non_interacting_type`
3636
in all reaction method classes.
3737

38-
* Some of the functionality requires particle book-keeping. If your simulation
39-
script raises runtime errors about "provided particle type X is currently not
40-
tracked by the system", use :meth:`system.setup_type_map(type_list=[X])
41-
<espressomd.system.System.setup_type_map>` where ``X`` is the particle
42-
type to track.
43-
4438
Thermodynamic ensembles
4539
-----------------------
4640

@@ -196,7 +190,8 @@ As before in the reaction ensemble, one can define multiple reactions (e.g. for
196190

197191
.. code-block:: python
198192
199-
cpH = reaction_methods.ConstantpHEnsemble(kT=1, exclusion_range=1., seed=77)
193+
cpH = reaction_methods.ConstantpHEnsemble(
194+
kT=1., seed=77, exclusion_range=1., system=system)
200195
cpH.add_reaction(gamma=K_diss,
201196
reactant_types=[0],
202197
reactant_coefficients=[1],
@@ -252,7 +247,7 @@ For this one has to provide the following reaction to the Widom method:
252247
.. code-block:: python
253248
254249
type_B = 1
255-
widom = reaction_methods.WidomInsertion(kT=1, seed=77)
250+
widom = reaction_methods.WidomInsertion(kT=1., seed=77, system=system)
256251
widom.add_reaction(reactant_types=[],
257252
reactant_coefficients=[],
258253
product_types=[type_B],
@@ -353,14 +348,44 @@ The Monte Carlo (MC) sampling of the reaction can be coupled with a configurati
353348
For non-interacting systems this coupling is not an issue, but for interacting systems the insertion of new particles
354349
can lead to instabilities in the MD integration ultimately leading to a crash of the simulation.
355350

356-
This integration instabilities can be avoided by defining a distance around the particles which already exist in the system
357-
where new particles will not be inserted, which is defined by the required keyword ``exclusion_range``.
358-
This prevents big overlaps with the newly inserted particles, avoiding too big forces between particles, which prevents the MD integration from crashing.
359-
The value of the exclusion range does not affect the limiting result and it only affects the convergence and the stability of the integration. For interacting systems,
360-
it is usually a good practice to choose the exclusion range such that it is comparable to the diameter of the particles.
361-
362-
If particles with significantly different sizes are present, it is desired to define a different exclusion range for each pair of particle types. This can be done by
363-
defining an exclusion radius per particle type by using the optional argument ``exclusion_radius_per_type``. Then, their exclusion range is calculated using
364-
the Lorentz-Berthelot combination rule, *i.e.* ``exclusion_range = exclusion_radius_per_type[particle_type_1] + exclusion_radius_per_type[particle_type_2]``.
365-
If the exclusion radius of one particle type is not defined, the value of the parameter provided in ``exclusion_range`` is used by default.
366-
If the value in ``exclusion_radius_per_type`` is equal to 0, then the exclusion range of that particle type with any other particle is 0.
351+
These integration instabilities can be avoided by defining a distance
352+
``exclusion_range`` around particles in the system, within which new particles
353+
will not be inserted (and old particles will not be removed, to maintain detailed balance).
354+
This prevents big overlaps with the newly inserted particles, which would
355+
otherwise cause large forces between particles and crash the MD integrator.
356+
The value of the exclusion range does not affect the limiting result
357+
and only affects the convergence and the stability of the integration.
358+
For interacting systems, it is usually a good practice to choose the exclusion
359+
range such that it is comparable to the diameter of the particles.
360+
361+
If particles with significantly different sizes are present, it is desirable
362+
to define a different exclusion range for each pair of particle types.
363+
This can be done by defining an exclusion radius per particle type via
364+
the optional argument ``exclusion_radius_per_type``.
365+
Then, their exclusion range is calculated using the Lorentz-Berthelot
366+
combination rule, *i.e.*
367+
368+
.. code-block:: python
369+
370+
exclusion_range = exclusion_radius_per_type[particle_type_1] + \
371+
exclusion_radius_per_type[particle_type_2]
372+
373+
If the exclusion radius of one particle type is not defined, the value
374+
of the parameter provided in ``exclusion_range`` is used by default.
375+
If the value in ``exclusion_radius_per_type`` is equal to 0,
376+
then the exclusion range of that particle type with any other particle is 0.
377+
For more detail, see :class:`~espressomd.reaction_methods.ExclusionRadius`.
378+
379+
.. _Writing new Monte Carlo methods:
380+
381+
Writing new Monte Carlo methods
382+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
383+
384+
Most of the logic for reaction methods is implemented at the Python level.
385+
The C++ core is only used for performance-relevant operations on particles.
386+
Hence, one can prototype new reaction methods with relative ease.
387+
For example, the acceptance probability for a Monte Carlo trial move
388+
is exposed in :meth:`ReactionAlgorithm.calculate_acceptance_probability()
389+
<espressomd.reaction_methods.ReactionAlgorithm.calculate_acceptance_probability>`.
390+
Reaction method classes override this function with their custom expression
391+
for the acceptance probability.

doc/tutorials/boltzmann_inversion/boltzmann_inversion.ipynb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@
230230
"system = espressomd.System(box_l=[BOX_LENGTH]*3)\n",
231231
"system.time_step = DT\n",
232232
"system.cell_system.skin = SKIN\n",
233-
"system.setup_type_map(type_list=list(types.values()))\n",
234233
"np.random.seed(42)\n",
235234
"\n",
236235
"# Add the colloidal particles\n",

doc/tutorials/constant_pH/constant_pH.ipynb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@
623623
"# SOLUTION CELL\n",
624624
"exclusion_range = PARTICLE_SIZE_REDUCED if USE_WCA else 0.0\n",
625625
"RE = espressomd.reaction_methods.ConstantpHEnsemble(\n",
626+
" system=system,\n",
626627
" kT=KT_REDUCED,\n",
627628
" exclusion_range=exclusion_range,\n",
628629
" seed=77,\n",

doc/tutorials/grand_canonical_monte_carlo/grand_canonical_monte_carlo.ipynb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,8 @@
597597
" c_salt_res_sim.magnitude))\n",
598598
"RE = espressomd.reaction_methods.ReactionEnsemble(kT=KT,\n",
599599
" exclusion_range=1.0,\n",
600-
" seed=reaction_seed)\n",
600+
" seed=reaction_seed,\n",
601+
" system=system)\n",
601602
"RE.add_reaction(gamma=K_XX,\n",
602603
" reactant_types=[],\n",
603604
" reactant_coefficients=[],\n",

doc/tutorials/widom_insertion/widom_insertion.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@
338338
"source": [
339339
"# SOLUTION CELL\n",
340340
"# add reaction for Widom particle insertion\n",
341-
"widom = espressomd.reaction_methods.WidomInsertion(kT=KT, seed=42)\n",
341+
"widom = espressomd.reaction_methods.WidomInsertion(kT=KT, seed=42, system=system)\n",
342342
"widom.add_reaction(reactant_types=[], reactant_coefficients=[],\n",
343343
" product_types=[types[\"Xplus\"], types[\"Xminus\"]], product_coefficients=[1, 1],\n",
344344
" default_charges={types[\"Xplus\"]: charges[\"Xplus\"], types[\"Xminus\"]: charges[\"Xminus\"]})\n",

maintainer/benchmarks/mc_acid_base_reservoir.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,7 @@ def calc_donnan_coefficient(c_acid, I_res, charge=-1):
226226
# ### Set up the constant pH ensemble using the reaction ensemble module
227227
exclusion_range = PARTICLE_SIZE_REDUCED
228228
RE = espressomd.reaction_methods.ReactionEnsemble(
229+
system=system,
229230
kT=KT_REDUCED,
230231
exclusion_range=exclusion_range,
231232
seed=77

samples/grand_canonical.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,12 @@
8989
epsilon=wca_eps, sigma=wca_sig)
9090

9191
RE = espressomd.reaction_methods.ReactionEnsemble(
92-
kT=temperature, exclusion_range=wca_sig, seed=3)
92+
system=system, kT=temperature, exclusion_range=wca_sig, seed=3)
9393
RE.add_reaction(
9494
gamma=cs_bulk**2 * np.exp(excess_chemical_potential_pair / temperature),
9595
reactant_types=[], reactant_coefficients=[], product_types=[1, 2],
9696
product_coefficients=[1, 1], default_charges={1: -1, 2: +1})
9797
print(RE.get_status())
98-
system.setup_type_map(type_list=[0, 1, 2])
9998

10099
# Set the hidden particle type to the lowest possible number to speed
101100
# up the simulation

samples/reaction_ensemble_complex_reaction.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282

8383
# use an exclusion radius of 0 to simulate an ideal gas
8484
RE = espressomd.reaction_methods.ReactionEnsemble(
85-
kT=1, exclusion_range=0, seed=4)
85+
kT=1., exclusion_range=0., seed=4, system=system)
8686

8787

8888
RE.add_reaction(

0 commit comments

Comments
 (0)