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

Encapsulate long-range actors #4749

Merged
merged 5 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 21 additions & 14 deletions doc/sphinx/electrostatics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ the particles via the particle property

All solvers need a prefactor and a set of other required parameters.
This example shows the general usage of the electrostatic method ``P3M``.
An instance of the solver is created and added to the actors list, at which
An instance of the solver is created and attached to the system, at which
point it will be automatically activated. This activation will internally
call a tuning function to achieve the requested accuracy::

Expand All @@ -48,13 +48,17 @@ call a tuning function to achieve the requested accuracy::
system.time_step = 0.01
system.part.add(pos=[[0, 0, 0], [1, 1, 1]], q=[-1, 1])
solver = espressomd.electrostatics.P3M(prefactor=2., accuracy=1e-3)
system.actors.add(solver)
system.electrostatics.solver = solver

where the prefactor is defined as :math:`C` in Eqn. :eq:`coulomb_prefactor`.

The list of actors can be cleared with
:meth:`system.actors.clear() <espressomd.actors.Actors.clear>` and
:meth:`system.actors.remove(actor) <espressomd.actors.Actors.remove>`.
The solver can be detached with either::

system.electrostatics.solver = None

or::

system.electrostatics.clear()


.. _Coulomb P3M:
Expand Down Expand Up @@ -190,9 +194,12 @@ surface. ICC relies on a Coulomb solver that is already initialized. So far, it
is implemented and well tested with the Coulomb solver P3M. ICC is an |es|
actor and can be activated via::

import espressomd.electrostatics
import espressomd.electrostatic_extensions
p3m = espressomd.electrostatics.P3M(...)
icc = espressomd.electrostatic_extensions.ICC(...)
system.actors.add(icc)
system.electrostatics.solver = p3m
system.electrostatics.extension = icc

The ICC particles are setup as normal |es| particles. Note that they should
be fixed in space and need an initial non-zero charge. The following example
Expand Down Expand Up @@ -248,7 +255,7 @@ sets up parallel metallic plates and activates ICC::
sigmas=iccSigmas,
epsilons=iccEpsilons)

system.actors.add(icc)
system.electrostatics.extension = icc


With each iteration, ICC has to solve electrostatics which can severely slow
Expand Down Expand Up @@ -290,7 +297,7 @@ Usage notes:
import espressomd.electrostatics
p3m = espressomd.electrostatics.P3M(prefactor=1, accuracy=1e-4)
elc = espressomd.electrostatics.ELC(actor=p3m, gap_size=box_l * 0.2, maxPWerror=1e-3)
system.actors.add(elc)
system.electrostatics.solver = elc

Although it is technically feasible to remove ``elc`` from the list of actors
and then to add the ``p3m`` object, it is not recommended because the P3M
Expand Down Expand Up @@ -404,7 +411,7 @@ the library, and can be queried with
:meth:`espressomd.electrostatics.Scafacos.get_available_methods`.

To use ScaFaCoS, create an instance of :class:`~espressomd.electrostatics.Scafacos`
and add it to the list of active actors. Three parameters have to be specified:
and attach it to the system. Three parameters have to be specified:
``prefactor`` (as defined in :eq:`coulomb_prefactor`), ``method_name``,
``method_params``. The method-specific parameters are described in the
ScaFaCoS manual. In addition, methods supporting tuning have a parameter
Expand All @@ -415,11 +422,11 @@ To use a specific electrostatics solver from ScaFaCoS for your system,
e.g. ``ewald``, set its cutoff to :math:`1.5` and tune the other parameters
for an accuracy of :math:`10^{-3}`::

import espressomd.electrostatics
scafacos = espressomd.electrostatics.Scafacos(
prefactor=1, method_name="ewald",
method_params={"ewald_r_cut": 1.5, "tolerance_field": 1e-3})
system.actors.add(scafacos)
import espressomd.electrostatics
scafacos = espressomd.electrostatics.Scafacos(
prefactor=1, method_name="ewald",
method_params={"ewald_r_cut": 1.5, "tolerance_field": 1e-3})
system.electrostatics.solver = scafacos

For details of the various methods and their parameters please refer to
the ScaFaCoS manual. To use this feature, ScaFaCoS has to be built as a
Expand Down
13 changes: 8 additions & 5 deletions doc/sphinx/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -259,16 +259,19 @@ electrostatics solver. We start by adding the particles: ::
cation = system.part.add(pos=[4.0, 1.0, 1.0], type=2, q=1.0)
anion = system.part.add(pos=[6.0, 1.0, 1.0], type=2, q=-1.0)

Long-range interactions and other methods that might be mutually exclusive
are treated as so-called *actors*. They are used by first creating an instance
of the desired actor::
Long-range interaction solvers for electrostatics, magnetostatis, hydrodynamics
and electrokinetics are treated as self-contained objects that can be attached
to the system. We start by first creating an instance of the desired solver::

p3m = espressomd.electrostatics.P3M(accuracy=1e-3, prefactor=1.0)

and then adding it to the system: ::
and then we attach it to the system::

print("Tuning p3m ...")
system.actors.add(p3m)
system.electrostatics.solver = p3m

Solvers for electrostatics and magnetostatics automatically tune their
parameters when attached to a system.

.. rubric:: Integration

Expand Down
45 changes: 33 additions & 12 deletions doc/sphinx/magnetostatics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,15 @@ Magnetostatic interactions are activated via the actor framework::
rotation=2 * [(True, True, True)])

actor = espressomd.magnetostatics.DipolarDirectSumCpu(prefactor=1.)
system.actors.add(actor)
system.magnetostatics.solver = actor

The list of actors can be cleared with
:meth:`system.actors.clear() <espressomd.actors.Actors.clear>` and
:meth:`system.actors.remove(actor) <espressomd.actors.Actors.remove>`.
The solver can be detached with either::

system.magnetostatics.solver = None

or::

system.magnetostatics.clear()


.. _Dipolar P3M:
Expand All @@ -66,7 +70,7 @@ the omitted parameters are tuned::

import espressomd.magnetostatics as magnetostatics
p3m = magnetostatics.DipolarP3M(prefactor=1, mesh=32, accuracy=1E-4)
system.actors.add(p3m)
system.magnetostatics.solver = p3m

It is important to note that the error estimates given in :cite:`cerda08d`
used in the tuning contain assumptions about the system. In particular, a
Expand Down Expand Up @@ -109,7 +113,7 @@ The method is used as follows::
import espressomd.magnetostatics
dp3m = espressomd.magnetostatics.DipolarP3M(prefactor=1, accuracy=1E-4)
mdlc = espressomd.magnetostatics.DLC(actor=dp3m, maxPWerror=1E-5, gap_size=2.)
system.actors.add(mdlc)
system.magnetostatics.solver = mdlc


.. _Dipolar direct sum:
Expand Down Expand Up @@ -144,13 +148,13 @@ Two methods are available:

To use the methods, create an instance of either
:class:`~espressomd.magnetostatics.DipolarDirectSumCpu` or
:class:`~espressomd.magnetostatics.DipolarDirectSumGpu` and add it to the
system's list of active actors. The only required parameter is the prefactor
:class:`~espressomd.magnetostatics.DipolarDirectSumGpu` and
attach it to the system. The only required parameter is the prefactor
:eq:`dipolar_prefactor`::

import espressomd.magnetostatics
dds = espressomd.magnetostatics.DipolarDirectSumGpu(prefactor=1)
system.actors.add(dds)
system.magnetostatics.solver = dds

The CPU implementation has an optional argument ``n_replicas`` which
adds periodic copies to the system along periodic directions. In that
Expand Down Expand Up @@ -182,11 +186,11 @@ Barnes-Hut method application to the dipole-dipole interactions, please
refer to :cite:`polyakov13a`.

To use the method, create an instance of :class:`~espressomd.magnetostatics.DipolarBarnesHutGpu`
and add it to the system's list of active actors::
and attach it to the system::

import espressomd.magnetostatics
bh = espressomd.magnetostatics.DipolarBarnesHutGpu(prefactor=1., epssq=200.0, itolsq=8.0)
system.actors.add(bh)
system.magnetostatics.solver = bh


.. _ScaFaCoS magnetostatics:
Expand All @@ -204,12 +208,29 @@ the ScaFaCoS code. The specific methods available can be queried with
:meth:`espressomd.electrostatics.Scafacos.get_available_methods`.

To use ScaFaCoS, create an instance of :class:`~espressomd.magnetostatics.Scafacos`
and add it to the list of active actors. Three parameters have to be specified:
and attach it to the system. Three parameters have to be specified:
``prefactor``, ``method_name``, ``method_params``. The method-specific
parameters are described in the ScaFaCoS manual. In addition, methods
supporting tuning have a parameter ``tolerance_field`` which sets the desired
root mean square accuracy for the magnetic field.

Here is an example with the P2NFFT method for 2D-periodic systems::

import espressomd.magnetostatics
scafacos = espressomd.magnetostatics.Scafacos(
prefactor=1., method_name="p2nfft",
method_params={
"p2nfft_verbose_tuning": 0,
"pnfft_N": "80,80,160",
"pnfft_window_name": "bspline",
"pnfft_m": "4",
"p2nfft_ignore_tolerance": "1",
"pnfft_diff_ik": "0",
"p2nfft_r_cut": "6",
"p2nfft_alpha": "0.8",
"p2nfft_epsB": "0.05"})
system.magnetostatics.solver = scafacos

For details of the various methods and their parameters please refer to
the ScaFaCoS manual. To use this feature, ScaFaCoS has to be built as a
shared library.
28 changes: 19 additions & 9 deletions doc/tutorials/charged_system/charged_system.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,14 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we set up the electrostatics method to calculate the forces and energies from the long-range Coulomb interaction. **ESPResSo** uses so-called <tt>actors</tt> for electrostatics, magnetostatics and hydrodynamics. This ensures that unphysical combinations of algorithms are avoided, for example simultaneous usage of two electrostatic interactions. Adding an actor to the system also activates the method and calls necessary initialization routines. Here, we define a P$^3$M object using the Bjerrum length and rms force error. This automatically starts a tuning function which tries to find optimal parameters for P$^3$M and prints them to the screen. For more details, see the user guide chapter on [Electrostatics](https://espressomd.github.io/doc/electrostatics.html)."
"Now we set up the electrostatics method to calculate the forces and energies from the long-range Coulomb interaction.\n",
"**ESPResSo** uses so-called <tt>solvers</tt> for electrostatics, magnetostatics and hydrodynamics.\n",
"They are attached to system slots in such a way that unphysical combinations of algorithms are avoided,\n",
"for example simultaneous usage of two electrostatics solvers.\n",
"Adding an actor to the system also activates the method and calls necessary initialization routines.\n",
"Here, we define a P$^3$M object using the Bjerrum length and rms force error.\n",
"This automatically starts a tuning function which tries to find optimal parameters for P$^3$M and prints them to the screen.\n",
"For more details, see the user guide chapter on [Electrostatics](https://espressomd.github.io/doc/electrostatics.html)."
]
},
{
Expand All @@ -249,7 +256,9 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"For the accuracy, **ESPResSo** estimates the relative error in the force calculation introduced by the approximations of $P^3M$. We choose a relatively poor accuracy (large value) for this tutorial to make it run faster. For your own production simulations you should reduce that number."
"For the accuracy, **ESPResSo** estimates the relative error in the force calculation introduced by the approximations of $P^3M$.\n",
"We choose a relatively poor accuracy (large value) for this tutorial to make it run faster.\n",
"For your own production simulations you should reduce that number."
]
},
{
Expand All @@ -260,7 +269,7 @@
},
"source": [
"**Exercise:**\n",
"* Set up a ``p3m`` instance and add it to the ``actors`` of the system"
"* Set up a ``p3m`` instance and add it to the ``electrostatics`` slot of the system"
]
},
{
Expand All @@ -271,7 +280,7 @@
"source": [
"```python\n",
"p3m = espressomd.electrostatics.P3M(**p3m_params)\n",
"system.actors.add(p3m)\n",
"system.electrostatics.solver = p3m\n",
"```"
]
},
Expand All @@ -286,7 +295,8 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Before we can start the simulation, we need to remove the overlap between particles to avoid large forces which would crash the simulation. For this, we use the steepest descent integrator with a relative convergence criterion for forces and energies."
"Before we can start the simulation, we need to remove the overlap between particles to avoid large forces which would crash the simulation.\n",
"For this, we use the steepest descent integrator with a relative convergence criterion for forces and energies."
]
},
{
Expand Down Expand Up @@ -504,7 +514,7 @@
"* Write a function ``clear_system(system)`` that\n",
" * turns off the thermostat\n",
" * removes all particles\n",
" * removes all actors\n",
" * removes the electrostatics solver\n",
" * removes all accumulators added to the auto-update-list\n",
" * resets the system clock\n",
"\n",
Expand All @@ -527,7 +537,7 @@
"def clear_system(system):\n",
" system.thermostat.turn_off()\n",
" system.part.clear()\n",
" system.actors.clear()\n",
" system.electrostatics.clear()\n",
" system.auto_update_accumulators.clear()\n",
" system.time = 0.\n",
"```"
Expand Down Expand Up @@ -618,7 +628,7 @@
" system, run['params']['counterion_valency'], COUNTERION_TYPE,\n",
" run['params']['rod_charge_dens'], N_rod_beads, ROD_TYPE)\n",
" p3m = espressomd.electrostatics.P3M(**p3m_params)\n",
" system.actors.add(p3m)\n",
" system.electrostatics.solver = p3m\n",
" remove_overlap(system, STEEPEST_DESCENT_PARAMS)\n",
" system.thermostat.set_langevin(**LANGEVIN_PARAMS)\n",
" print('', end='', flush=True)\n",
Expand Down Expand Up @@ -845,7 +855,7 @@
"assert abs(sum(anions.q) + sum(cations.q)) < 1e-10\n",
"\n",
"p3m = espressomd.electrostatics.P3M(**p3m_params)\n",
"system.actors.add(p3m)\n",
"system.electrostatics.solver = p3m\n",
"remove_overlap(system, STEEPEST_DESCENT_PARAMS)\n",
"system.thermostat.set_langevin(**LANGEVIN_PARAMS)\n",
"print('', end='', flush=True)\n",
Expand Down
14 changes: 7 additions & 7 deletions doc/tutorials/constant_pH/constant_pH.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -534,14 +534,14 @@
"if USE_ELECTROSTATICS:\n",
" COULOMB_PREFACTOR=BJERRUM_LENGTH_REDUCED * KT_REDUCED\n",
" if USE_P3M:\n",
" coulomb = espressomd.electrostatics.P3M(prefactor = COULOMB_PREFACTOR, \n",
" coulomb = espressomd.electrostatics.P3M(prefactor=COULOMB_PREFACTOR,\n",
" accuracy=1e-3)\n",
" else:\n",
" coulomb = espressomd.electrostatics.DH(prefactor = COULOMB_PREFACTOR, \n",
" kappa = KAPPA_REDUCED, \n",
" r_cut = 1. / KAPPA_REDUCED)\n",
" \n",
" system.actors.add(coulomb)\n",
" coulomb = espressomd.electrostatics.DH(prefactor=COULOMB_PREFACTOR,\n",
" kappa=KAPPA_REDUCED,\n",
" r_cut=1. / KAPPA_REDUCED)\n",
"\n",
" system.electrostatics.solver = coulomb\n",
"else:\n",
" # this speeds up the simulation of dilute systems with small particle numbers\n",
" system.cell_system.set_n_square()"
Expand Down Expand Up @@ -715,7 +715,7 @@
" * an integer `num_samples` that determines the number of sampling steps to be performed\n",
" * a numpy array `num_As`, such that `len(num_As) == num_samples` which will be used to store the time series of the instantaneous values of $N_{\\mathrm{A^{-}}}$\n",
" * a float `reaction_steps` that determines the number of reactions to be performed\n",
" \n",
"\n",
"\n",
"* The function should perform the following tasks:\n",
" * sample the composition fluctuations using reaction moves of the constant $\\mathrm{pH}$ algorithm by calling [`RE.reaction()`](https://espressomd.github.io/doc/espressomd.html#espressomd.reaction_methods.ReactionAlgorithm.reaction)\n",
Expand Down
21 changes: 17 additions & 4 deletions doc/tutorials/ferrofluid/ferrofluid_part1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,10 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now we add the particles with their positions and orientations to our system. Thereby we activate all degrees of freedom for the orientation of the dipole moments. As we want a two dimensional system we only allow the particles to translate in $x$- and $y$-direction and not in $z$-direction by using the <tt>fix</tt> argument."
"Now we add the particles with their positions and orientations to our system.\n",
"Thereby we activate all degrees of freedom for the orientation of the dipole moments.\n",
"As we want a two dimensional system we only allow the particles to translate\n",
"in $x$- and $y$-direction and not in $z$-direction by using the <tt>fix</tt> argument."
]
},
{
Expand Down Expand Up @@ -525,7 +528,9 @@
"After that we set up the thermostat which is, in our case, a Langevin thermostat to simulate in an NVT ensemble.\n",
"\n",
"**Hint:**\n",
"It should be noted that we seed the Langevin thermostat, thus the time evolution of the system is partly predefined. Partly because of the numeric accuracy and the automatic tuning algorithms of Dipolar P3M and DLC where the resulting parameters are slightly different every time. You can change the seed to get a guaranteed different time evolution."
"It should be noted that we seed the Langevin thermostat, thus the time evolution of the system is partly predefined.\n",
"Partly because of the numeric accuracy and the automatic tuning algorithms of Dipolar P3M and DLC where the resulting parameters are slightly different every time.\n",
"You can change the seed to get a guaranteed different time evolution."
]
},
{
Expand All @@ -543,7 +548,15 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"To calculate the dipole-dipole interaction we use the Dipolar P3M method (see Ref. <a href='#[1]'>[1]</a>) which is based on the Ewald summation. By default the boundary conditions of the system are set to conducting which means the dielectric constant is set to infinity for the surrounding medium. As we want to simulate a two dimensional system we additionally use the dipolar layer correction (DLC) (see Ref. <a href='#[2]'>[2]</a>). As we add <tt>DipolarP3M</tt> to our system as an actor, a tuning function is started automatically which tries to find the optimal parameters for Dipolar P3M and prints them to the screen. The last line of the output is the value of the tuned skin."
"To calculate the dipole-dipole interaction we use the dipolar P3M method\n",
"(see Ref. <a href='#[1]'>[1]</a>) which is based on the Ewald summation.\n",
"By default the boundary conditions of the system are set to conducting which\n",
"means the dielectric constant is set to infinity for the surrounding medium.\n",
"As we want to simulate a two dimensional system we additionally use the dipolar\n",
"layer correction (DLC) (see Ref. <a href='#[2]'>[2]</a>).\n",
"As we attach <tt>DipolarP3M</tt> to our system, a tuning function is started automatically\n",
"which tries to find the optimal parameters for dipolar P3M and prints them to the screen.\n",
"The last line of the output is the value of the tuned skin."
]
},
{
Expand All @@ -558,7 +571,7 @@
"# Setup dipolar P3M and dipolar layer correction\n",
"dp3m = espressomd.magnetostatics.DipolarP3M(accuracy=5E-4, prefactor=DIP_LAMBDA * LJ_SIGMA**3 * KT, **CI_DP3M_PARAMS)\n",
"mdlc = espressomd.magnetostatics.DLC(actor=dp3m, maxPWerror=1E-4, gap_size=BOX_SIZE - LJ_SIGMA)\n",
"system.actors.add(mdlc)\n",
"system.magnetostatics.solver = mdlc\n",
"\n",
"# tune verlet list skin\n",
"system.cell_system.tune_skin(min_skin=0.4, max_skin=2., tol=0.2, int_steps=100)\n",
Expand Down
Loading