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

Implement Lees-Edwards boundary conditions #4457

Merged
merged 1 commit into from
Feb 28, 2022
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
8 changes: 0 additions & 8 deletions doc/sphinx/advanced_methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,6 @@ The following limitations currently apply for the collision detection:
between virtual sites


.. _Lees-Edwards boundary conditions:

Lees-Edwards boundary conditions
--------------------------------

Lees-Edwards boundary conditions are not available in the current version of |es|.


.. _Immersed Boundary Method for soft elastic objects:

Immersed Boundary Method for soft elastic objects
Expand Down
1 change: 1 addition & 0 deletions doc/sphinx/running.rst
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ Notes:
* For the instantaneous pressure, the same limitations of applicability hold as described in :ref:`Pressure`.
* The particle forces :math:`F` include interactions as well as a friction (:math:`\gamma^0`) and noise term (:math:`\sqrt{k_B T \gamma^0 dt} \overline{\eta}`) analogous to the terms in the :ref:`Langevin thermostat`.
* The particle forces are only calculated in step 5 and then reused in step 1 of the next iteration. See :ref:`Velocity Verlet Algorithm` for the implications of that.
* The NpT algorithm doesn't support :ref:`Lees-Edwards boundary conditions`.

.. _Steepest descent:

Expand Down
126 changes: 126 additions & 0 deletions doc/sphinx/system_setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ for further calculations, you should explicitly make a copy e.g. via
dimension non-periodic does not hinder particles from leaving the box in
this direction. In this case for keeping particles in the simulation box
a constraint has to be set.
For more details, see :ref:`Boundary conditions`.

* :py:attr:`~espressomd.system.System.time_step`

Expand Down Expand Up @@ -81,6 +82,131 @@ or by calling the corresponding ``get_state()`` methods like::
gamma = system.thermostat.get_state()[0]['gamma']
gamma_rot = system.thermostat.get_state()[0]['gamma_rotation']

.. _Boundary conditions:

Boundary conditions
-------------------

.. _Periodic boundaries:

Periodic boundaries
~~~~~~~~~~~~~~~~~~~

With periodic boundary conditions, particles interact with periodic
images of all particles in the system. This is the default behavior.
When particles cross a box boundary, their position are folded and
their image box counter are incremented.

From the Python interface, the folded position is accessed with
:attr:`~espressomd.particle_data.ParticleHandle.pos_folded` and the image
box counter with :attr:`~espressomd.particle_data.ParticleHandle.image_box`.
Note that :attr:`~espressomd.particle_data.ParticleHandle.pos` gives the
unfolded particle position.

Example::

import espressomd
system = espressomd.System(box_l=[5.0, 5.0, 5.0], periodicity=[True, True, True])
system.time_step = 0.1
system.cell_system.skin = 0.0
p = system.part.add(pos=[4.9, 0.0, 0.0], v=[0.1, 0.0, 0.0])
system.integrator.run(20)
print(f"pos = {p.pos}")
print(f"pos_folded = {p.pos_folded}")
print(f"image_box = {p.image_box}")

Output:

.. code-block:: none

pos = [5.1 0. 0. ]
pos_folded = [0.1 0. 0. ]
image_box = [1 0 0]

.. _Open boundaries:

Open boundaries
~~~~~~~~~~~~~~~

With open boundaries, particles can leave the simulation box.
What happens in this case depends on which algorithm is used.
Some algorithms may require open boundaries,
such as :ref:`Stokesian Dynamics`.

Example::

import espressomd
system = espressomd.System(box_l=[5.0, 5.0, 5.0], periodicity=[False, False, False])
system.time_step = 0.1
system.cell_system.skin = 0.0
p = system.part.add(pos=[4.9, 0.0, 0.0], v=[0.1, 0.0, 0.0])
system.integrator.run(20)
print(f"pos = {p.pos}")
print(f"pos_folded = {p.pos_folded}")
print(f"image_box = {p.image_box}")

Output:

.. code-block:: none

pos = [5.1 0. 0. ]
pos_folded = [5.1 0. 0. ]
image_box = [0 0 0]

.. _Lees-Edwards boundary conditions:

Lees--Edwards boundary conditions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Lees--Edwards boundary conditions (LEbc) are special periodic boundary
conditions to simulation systems under shear stress :cite:`lees72a`.
Periodic images of particles across the shear boundary appear with a
time-dependent position offset. When a particle crosses the shear boundary,
it appears to the opposite side of the simulation box with a position offset
and a shear velocity :cite:`bindgen21a`.

LEbc require a fully periodic system and are configured with
:class:`~espressomd.lees_edwards.LinearShear` and
:class:`~espressomd.lees_edwards.OscillatoryShear`.
To temporarily disable LEbc, use :class:`~espressomd.lees_edwards.Off`.
To completely disable LEbc and reinitialize the box geometry, do
``system.lees_edwards.protocol = None``.

Example::

import espressomd
import espressomd.lees_edwards
system = espressomd.System(box_l=[5.0, 5.0, 5.0])
system.time_step = 0.1
system.cell_system.skin = 0.0
system.cell_system.set_n_square(use_verlet_lists=True)
le_protocol = espressomd.lees_edwards.LinearShear(
shear_velocity=-0.1, initial_pos_offset=0.0, time_0=-0.1)
system.lees_edwards.protocol = le_protocol
system.lees_edwards.shear_direction = 1 # shear along y-axis
system.lees_edwards.shear_plane_normal = 0 # shear when crossing the x-boundary
p = system.part.add(pos=[4.9, 0.0, 0.0], v=[0.1, 0.0, 0.0])
system.integrator.run(20)
print(f"pos = {p.pos}")
print(f"pos_folded = {p.pos_folded}")
print(f"image_box = {p.image_box}")
print(f"velocity = {p.v}")

Output:

.. code-block:: none

pos = [5.1 0.2 0. ]
pos_folded = [0.1 0.2 0. ]
image_box = [1 0 0]
velocity = [0.1 0.1 0. ]

Particles inserted outside the box boundaries will be wrapped around
using the normal periodic boundary rules, i.e. they will not be sheared,
even though their :attr:`~espressomd.particle_data.ParticleHandle.image_box`
is *not* zero.


.. _Cellsystems:

Cellsystems
Expand Down
21 changes: 21 additions & 0 deletions doc/sphinx/zrefs.bib
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,17 @@ @ARTICLE{ballenegger09a
publisher = {AIP},
}

@Article{bindgen21a,
author = {Bindgen, Sebastian and Weik, Florian and Weeber, Rudolf and Koos, Erin and de Buyl, Pierre},
title = {Lees-Edwards boundary conditions for translation invariant shear flow: implementation and transport properties},
journal = {Physics of Fluids},
year = {2021},
volume = {33},
number = {8},
doi = {10.1063/5.0055396},
pages = {083615},
}

@ARTICLE{brodka04a,
author = {Br\'{o}dka, A.},
title = {{E}wald summation method with electrostatic layer correction for interactions
Expand Down Expand Up @@ -296,6 +307,16 @@ @ARTICLE{humphrey96a
doi = {10.1016/0263-7855(96)00018-5},
}

@Article{lees72a,
author = {Lees, A. W. and Edwards, S. F.},
title = {The computer study of transport processes under extreme conditions},
journal = {Journal of Physics C: Solid State Physics},
year = {1972},
volume = {5},
number = {15},
doi = {10.1088/0022-3719/5/15/006},
}

@ARTICLE{tyagi08a,
author = {Sandeep Tyagi and Axel Arnold and Christian Holm},
title = {Electrostatic layer correction with image charges: A linear scaling
Expand Down
2 changes: 2 additions & 0 deletions src/core/AtomDecomposition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class AtomDecomposition : public ParticleDecomposition {
return m_box;
}

BoxGeometry box() const override { return m_box; };

private:
/**
* @brief Find cell for id.
Expand Down
53 changes: 53 additions & 0 deletions src/core/BoxGeometry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@
#ifndef CORE_BOX_GEOMETRY_HPP
#define CORE_BOX_GEOMETRY_HPP

#include "LeesEdwardsBC.hpp"
#include "algorithm/periodic_fold.hpp"

#include <utils/Vector.hpp>
#include <utils/math/sgn.hpp>

#include <bitset>
#include <cassert>
Expand Down Expand Up @@ -68,8 +70,28 @@ template <typename T> T get_mi_coord(T a, T b, T box_length, bool periodic) {
}
} // namespace detail

enum class BoxType { CUBOID = 0, LEES_EDWARDS = 1 };

class BoxGeometry {
public:
BoxGeometry() {
set_length(Utils::Vector3d{1., 1., 1.});
set_periodic(0, true);
set_periodic(1, true);
set_periodic(2, true);
set_type(BoxType::CUBOID);
}
BoxGeometry(BoxGeometry const &rhs) {
m_type = rhs.type();
set_length(rhs.length());
set_periodic(0, rhs.periodic(0));
set_periodic(1, rhs.periodic(1));
set_periodic(2, rhs.periodic(2));
m_lees_edwards_bc = rhs.m_lees_edwards_bc;
}

private:
BoxType m_type = BoxType::CUBOID;
/** Flags for all three dimensions whether pbc are applied (default). */
std::bitset<3> m_periodic = 0b111;
/** Side lengths of the box */
Expand All @@ -79,6 +101,9 @@ class BoxGeometry {
/** Half side lengths of the box */
Utils::Vector3d m_length_half = {0.5, 0.5, 0.5};

/** Lees-Edwards boundary conditions */
LeesEdwardsBC m_lees_edwards_bc;

public:
/**
* @brief Set periodicity for direction
Expand Down Expand Up @@ -161,9 +186,37 @@ class BoxGeometry {
template <typename T>
Utils::Vector<T, 3> get_mi_vector(const Utils::Vector<T, 3> &a,
const Utils::Vector<T, 3> &b) const {
if (type() == BoxType::LEES_EDWARDS) {
return clees_edwards_bc().distance(a - b, length(), length_half(),
length_inv(), m_periodic);
}
assert(type() == BoxType::CUBOID);
return {get_mi_coord(a[0], b[0], 0), get_mi_coord(a[1], b[1], 1),
get_mi_coord(a[2], b[2], 2)};
}

BoxType type() const { return m_type; }
void set_type(BoxType type) { m_type = type; }

LeesEdwardsBC &lees_edwards_bc() { return m_lees_edwards_bc; }
LeesEdwardsBC const &clees_edwards_bc() const { return m_lees_edwards_bc; }
void set_lees_edwards_bc(LeesEdwardsBC bc) { m_lees_edwards_bc = bc; }

/** Calculate the velocity difference including the Lees-Edwards velocity */
Utils::Vector3d velocity_difference(Utils::Vector3d const &x,
Utils::Vector3d const &y,
Utils::Vector3d const &u,
Utils::Vector3d const &v) const {
auto ret = u - v;
if (type() == BoxType::LEES_EDWARDS) {
auto const &le = m_lees_edwards_bc;
auto const dy = x[le.shear_plane_normal] - y[le.shear_plane_normal];
if (fabs(dy) > 0.5 * length_half()[le.shear_plane_normal]) {
ret[le.shear_direction] -= Utils::sgn(dy) * le.shear_velocity;
}
}
return ret;
}
};

/** @brief Fold a coordinate to primary simulation box.
Expand Down
5 changes: 4 additions & 1 deletion src/core/CellStructure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include "AtomDecomposition.hpp"
#include "CellStructureType.hpp"
#include "RegularDecomposition.hpp"
#include "grid.hpp"
#include "lees_edwards.hpp"

#include <utils/contains.hpp>

Expand Down Expand Up @@ -221,7 +223,7 @@ struct UpdateParticleIndexVisitor {
};
} // namespace

void CellStructure::resort_particles(int global_flag) {
void CellStructure::resort_particles(int global_flag, BoxGeometry const &box) {
invalidate_ghosts();

static std::vector<ParticleChange> diff;
Expand All @@ -234,6 +236,7 @@ void CellStructure::resort_particles(int global_flag) {
}

m_rebuild_verlet_list = true;
m_le_pos_offset_at_last_resort = box.clees_edwards_bc().pos_offset;

#ifdef ADDITIONAL_CHECKS
check_particle_index();
Expand Down
Loading