diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index eb0f5c136dd..5de0d50577a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -438,6 +438,8 @@ empty:
with_static_analysis: 'true'
with_scafacos: 'false'
with_stokesian_dynamics: 'false'
+ with_coverage: 'false'
+ with_coverage_python: 'true'
script:
- bash maintainer/CI/build_cmake.sh
tags:
diff --git a/doc/sphinx/inter_non-bonded.rst b/doc/sphinx/inter_non-bonded.rst
index e7c07177d38..f7613713e6c 100644
--- a/doc/sphinx/inter_non-bonded.rst
+++ b/doc/sphinx/inter_non-bonded.rst
@@ -18,23 +18,41 @@ explicitly set. A bonded interaction between a set of particles has to
be specified explicitly by the command, while the command is used to
define the interaction parameters.
-.. _Isotropic non-bonded interactions:
+Non-bonded interaction are configured via the
+:class:`espressomd.interactions.NonBondedInteraction` class,
+which is a member of :class:`espressomd.system.System`::
-Isotropic non-bonded interactions
----------------------------------
+ system.non_bonded_inter[type1, type2]
-Non-bonded interaction are configured via the :class:`espressomd.interactions.NonBondedInteraction` class, which is a member of :class:`espressomd.system.System`::
+This command defines an interaction between all particles of type ``type1``
+and ``type2``. All available interaction potentials and their parameters are
+listed below. For example, the following adds a WCA potential between
+particles of type 0::
- system.non_bonded_inter[type1, type2]
+ system.non_bonded_inter[0, 0].wca.set_params(epsilon=1., sigma=2.)
+
+Each type pair can have multiple potentials active at the same time.
+To deactivate a specific potential for a given type pair, do::
+
+ system.non_bonded_inter[0, 0].wca.deactivate()
+
+To deactivate all potentials for a given type pair, do::
-This command defines an interaction between all particles of type ``type1`` and
-``type2``. Possible interaction types and their parameters are
-listed below.
+ system.non_bonded_inter[0, 0].reset()
+
+To deactivate all potentials between all type pairs, do::
+
+ system.non_bonded_inter.reset()
For many non-bonded interactions, it is possible to artificially cap the
forces, which often allows to equilibrate the system much faster. See
the subsection :ref:`Capping the force during warmup` for more details.
+.. _Isotropic non-bonded interactions:
+
+Isotropic non-bonded interactions
+---------------------------------
+
.. _Tabulated interaction:
Tabulated interaction
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9426568be13..852b30d5f4e 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -55,7 +55,8 @@ add_library(
virtual_sites.cpp
exclusions.cpp
PartCfg.cpp
- EspressoSystemStandAlone.cpp)
+ EspressoSystemStandAlone.cpp
+ TabulatedPotential.cpp)
add_library(espresso::core ALIAS espresso_core)
if(CUDA)
diff --git a/src/core/TabulatedPotential.cpp b/src/core/TabulatedPotential.cpp
new file mode 100644
index 00000000000..2ba8a6e61a1
--- /dev/null
+++ b/src/core/TabulatedPotential.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010-2022 The ESPResSo project
+ * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
+ * Max-Planck-Institute for Polymer Research, Theory Group
+ *
+ * This file is part of ESPResSo.
+ *
+ * ESPResSo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ESPResSo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "TabulatedPotential.hpp"
+
+#include
+#include
+
+TabulatedPotential::TabulatedPotential(double minval, double maxval,
+ std::vector const &force,
+ std::vector const &energy)
+ : minval{minval}, maxval{maxval} {
+
+ if (minval > maxval) {
+ throw std::domain_error("TabulatedPotential parameter 'max' must be "
+ "larger than or equal to parameter 'min'");
+ }
+ if (minval != -1.) {
+ if (minval == maxval and force.size() != 1) {
+ throw std::domain_error(
+ "TabulatedPotential parameter 'force' must contain 1 element");
+ }
+ if (force.empty()) {
+ throw std::domain_error("TabulatedPotential parameter 'force' must "
+ "contain at least 1 element");
+ }
+ if (force.size() != energy.size()) {
+ throw std::invalid_argument("TabulatedPotential parameter 'force' must "
+ "have the same size as parameter 'energy'");
+ }
+ invstepsize = static_cast(force.size() - 1) / (maxval - minval);
+ } else {
+ invstepsize = 0.;
+ }
+ force_tab = force;
+ energy_tab = energy;
+}
diff --git a/src/core/TabulatedPotential.hpp b/src/core/TabulatedPotential.hpp
index f05a4db85fe..e63a3bef9d4 100644
--- a/src/core/TabulatedPotential.hpp
+++ b/src/core/TabulatedPotential.hpp
@@ -25,7 +25,6 @@
#include
#include
-#include
#include
/** Evaluate forces and energies using a custom potential profile.
@@ -46,6 +45,11 @@ struct TabulatedPotential {
/** Tabulated energies. */
std::vector energy_tab;
+ TabulatedPotential() = default;
+ TabulatedPotential(double minval, double maxval,
+ std::vector const &force,
+ std::vector const &energy);
+
/** Evaluate the force at position @p x.
* @param x Bond length/angle
* @return Interpolated force.
@@ -67,17 +71,6 @@ struct TabulatedPotential {
}
double cutoff() const { return maxval; }
-
-private:
- friend boost::serialization::access;
- template
- void serialize(Archive &ar, long int /* version */) {
- ar &minval;
- ar &maxval;
- ar &invstepsize;
- ar &force_tab;
- ar &energy_tab;
- }
};
#endif
diff --git a/src/core/bonded_interactions/bonded_interaction_data.hpp b/src/core/bonded_interactions/bonded_interaction_data.hpp
index e25f403af06..2f006186cec 100644
--- a/src/core/bonded_interactions/bonded_interaction_data.hpp
+++ b/src/core/bonded_interactions/bonded_interaction_data.hpp
@@ -133,6 +133,9 @@ class BondedInteractionsMap {
bool empty() const { return m_params.empty(); }
auto size() const { return m_params.size(); }
auto get_next_key() const { return next_key; }
+ auto get_zero_based_type(int bond_id) const {
+ return contains(bond_id) ? at(bond_id)->which() : 0;
+ }
private:
container_type m_params = {};
diff --git a/src/core/bonded_interactions/bonded_interactions.dox b/src/core/bonded_interactions/bonded_interactions.dox
index 5685d6ed817..ab7eb29a285 100644
--- a/src/core/bonded_interactions/bonded_interactions.dox
+++ b/src/core/bonded_interactions/bonded_interactions.dox
@@ -243,37 +243,27 @@
*
* @subsection bondedIA_new_interface Adding the interaction in the Python interface
*
- * Please note that the following is Cython code (www.cython.org), rather than
- * pure Python.
- *
- * * In file src/python/espressomd/interactions.pxd:
- * - Add the bonded interaction to \c enum_bonded_interaction.
+ * * In file src/python/espressomd/interactions.py:
+ * - Add the bonded interaction to \c BONDED_IA.
* The order of the enum values must match the order of types in
* @ref Bonded_IA_Parameters exactly:
* @code{.py}
- * cdef enum enum_bonded_interaction:
- * BONDED_IA_NONE = 0,
- * BONDED_IA_FENE,
- * [...]
+ * class BONDED_IA(enum.IntEnum):
+ * NONE = 0
+ * FENE = enum.auto()
+ * HARMONIC = enum.auto()
+ * # ...
* @endcode
- * * In file src/python/espressomd/interactions.pyx:
- * - Implement the Cython class for the bonded interaction, using the one
+ * - Implement the Python class for the bonded interaction, using the one
* for the FENE bond as template. Please use pep8 naming convention.
- * - Set the class' member
+ * - Set the class' members
* @code{.py}
* _so_name = "Interactions::YourNewBond"
+ * _type_number = BONDED_IA.YOURNEWBOND
* @endcode
* where you put the name of your bond instead of \c YourNewBond.
* This connects the %ScriptInterface class with the Python class.
- * - Create a new entry in the dictionary \c bonded_interaction_classes to
- * register the new class you have written:
- * @code{.py}
- * bonded_interaction_classes = {
- * int(BONDED_IA_FENE): FeneBond,
- * int(BONDED_IA_HARMONIC): HarmonicBond,
- * [...]
- * }
- * @endcode
+ * The type number is the new enum value from \c BONDED_IA.
* * In file testsuite/python/interactions_bonded_interface.py:
* - Add a test case to verify that parameters set and gotten from the
* interaction are consistent.
diff --git a/src/core/bonded_interactions/bonded_tab.cpp b/src/core/bonded_interactions/bonded_tab.cpp
index ff86e49b0af..74762482f91 100644
--- a/src/core/bonded_interactions/bonded_tab.cpp
+++ b/src/core/bonded_interactions/bonded_tab.cpp
@@ -30,20 +30,7 @@
TabulatedBond::TabulatedBond(double min, double max,
std::vector const &energy,
std::vector const &force) {
- assert(max >= min);
- assert((max == min) || force.size() > 1);
- assert(force.size() == energy.size());
-
- auto tab_pot = this->pot = std::make_shared();
-
- /* set table limits */
- tab_pot->minval = min;
- tab_pot->maxval = max;
-
- tab_pot->invstepsize = static_cast(force.size() - 1) / (max - min);
-
- tab_pot->force_tab = force;
- tab_pot->energy_tab = energy;
+ pot = std::make_shared(min, max, force, energy);
}
TabulatedDistanceBond::TabulatedDistanceBond(double min, double max,
diff --git a/src/core/dpd.cpp b/src/core/dpd.cpp
index 8a22f988d8c..52a427b743e 100644
--- a/src/core/dpd.cpp
+++ b/src/core/dpd.cpp
@@ -64,28 +64,15 @@ Vector3d dpd_noise(int pid1, int pid2) {
(pid1 < pid2) ? pid1 : pid2);
}
-int dpd_set_params(int part_type_a, int part_type_b, double gamma, double k,
- double r_c, int wf, double tgamma, double tr_c, int twf) {
- auto &ia_params = *get_ia_param_safe(part_type_a, part_type_b);
-
- ia_params.dpd_radial = DPDParameters{gamma, k, r_c, wf, -1.};
- ia_params.dpd_trans = DPDParameters{tgamma, k, tr_c, twf, -1.};
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
-}
-
void dpd_init(double kT, double time_step) {
for (int type_a = 0; type_a < max_seen_particle_type; type_a++) {
for (int type_b = 0; type_b < max_seen_particle_type; type_b++) {
IA_parameters &ia_params = get_ia_param(type_a, type_b);
- ia_params.dpd_radial.pref =
- sqrt(24.0 * kT * ia_params.dpd_radial.gamma / time_step);
- ia_params.dpd_trans.pref =
- sqrt(24.0 * kT * ia_params.dpd_trans.gamma / time_step);
+ ia_params.dpd.radial.pref =
+ sqrt(24.0 * kT * ia_params.dpd.radial.gamma / time_step);
+ ia_params.dpd.trans.pref =
+ sqrt(24.0 * kT * ia_params.dpd.trans.gamma / time_step);
}
}
}
@@ -116,19 +103,19 @@ Utils::Vector3d dpd_pair_force(Particle const &p1, Particle const &p2,
IA_parameters const &ia_params,
Utils::Vector3d const &d, double dist,
double dist2) {
- if (ia_params.dpd_radial.cutoff <= 0.0 && ia_params.dpd_trans.cutoff <= 0.0) {
+ if (ia_params.dpd.radial.cutoff <= 0.0 && ia_params.dpd.trans.cutoff <= 0.0) {
return {};
}
auto const v21 =
box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
auto const noise_vec =
- (ia_params.dpd_radial.pref > 0.0 || ia_params.dpd_trans.pref > 0.0)
+ (ia_params.dpd.radial.pref > 0.0 || ia_params.dpd.trans.pref > 0.0)
? dpd_noise(p1.id(), p2.id())
: Vector3d{};
- auto const f_r = dpd_pair_force(ia_params.dpd_radial, v21, dist, noise_vec);
- auto const f_t = dpd_pair_force(ia_params.dpd_trans, v21, dist, noise_vec);
+ auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, noise_vec);
+ auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, noise_vec);
/* Projection operator to radial direction */
auto const P = tensor_product(d / dist2, d);
@@ -150,8 +137,8 @@ static auto dpd_viscous_stress_local() {
auto const &ia_params = get_ia_param(p1.type(), p2.type());
auto const dist = std::sqrt(d.dist2);
- auto const f_r = dpd_pair_force(ia_params.dpd_radial, v21, dist, {});
- auto const f_t = dpd_pair_force(ia_params.dpd_trans, v21, dist, {});
+ auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
+ auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
/* Projection operator to radial direction */
auto const P = tensor_product(d.vec21 / d.dist2, d.vec21);
@@ -188,4 +175,5 @@ Utils::Vector9d dpd_stress() {
return Utils::flatten(stress) / volume;
}
-#endif
+
+#endif // DPD
diff --git a/src/core/dpd.hpp b/src/core/dpd.hpp
index ea9e7a7e42c..e921e67da9f 100644
--- a/src/core/dpd.hpp
+++ b/src/core/dpd.hpp
@@ -36,8 +36,6 @@
struct IA_parameters;
-int dpd_set_params(int part_type_a, int part_type_b, double gamma, double k,
- double r_c, int wf, double tgamma, double tr_c, int twf);
void dpd_init(double kT, double time_step);
Utils::Vector3d dpd_pair_force(Particle const &p1, Particle const &p2,
diff --git a/src/core/event.cpp b/src/core/event.cpp
index 1e1ea80524c..0c5a750158d 100644
--- a/src/core/event.cpp
+++ b/src/core/event.cpp
@@ -251,6 +251,11 @@ void on_dipoles_change() {
on_short_range_ia_change();
}
+void on_non_bonded_ia_change() {
+ maximal_cutoff_nonbonded();
+ on_short_range_ia_change();
+}
+
void on_short_range_ia_change() {
cells_re_init(cell_structure.decomposition_type());
recalc_forces = true;
diff --git a/src/core/event.hpp b/src/core/event.hpp
index 6e39cbff4ab..8f1f56c6af6 100644
--- a/src/core/event.hpp
+++ b/src/core/event.hpp
@@ -79,6 +79,9 @@ void on_dipoles_change();
/** called every time short ranged interaction parameters are changed. */
void on_short_range_ia_change();
+/** called every time a non-bonded interaction parameters are changed. */
+void on_non_bonded_ia_change();
+
/** called every time a constraint is changed. */
void on_constraint_change();
diff --git a/src/core/interactions.cpp b/src/core/interactions.cpp
index b050bedab4f..6ba4a77ee67 100644
--- a/src/core/interactions.cpp
+++ b/src/core/interactions.cpp
@@ -18,16 +18,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#include "communication.hpp"
#include "bonded_interactions/bonded_interaction_data.hpp"
#include "collision.hpp"
+#include "communication.hpp"
#include "electrostatics/coulomb.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
#include "magnetostatics/dipoles.hpp"
-
-#include "serialization/IA_parameters.hpp"
+#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
#include
@@ -77,14 +76,3 @@ bool long_range_interactions_sanity_checks() {
}
return false;
}
-
-void mpi_bcast_ia_params_local(int i, int j) {
- boost::mpi::broadcast(comm_cart, get_ia_param(i, j), 0);
- on_short_range_ia_change();
-}
-
-REGISTER_CALLBACK(mpi_bcast_ia_params_local)
-
-void mpi_bcast_ia_params(int i, int j) {
- mpi_call_all(mpi_bcast_ia_params_local, i, j);
-}
diff --git a/src/core/interactions.hpp b/src/core/interactions.hpp
index 4399e5017bf..332891dc14a 100644
--- a/src/core/interactions.hpp
+++ b/src/core/interactions.hpp
@@ -32,17 +32,4 @@ double maximal_cutoff(bool single_node);
*/
bool long_range_interactions_sanity_checks();
-/** Send new IA params.
- * Also calls \ref on_short_range_ia_change.
- *
- * Used for both bonded and non-bonded interaction parameters. Therefore
- * @p i and @p j are used depending on their value:
- *
- * \param i particle type for non-bonded interaction parameters /
- * bonded interaction type number.
- * \param j if not negative: particle type for non-bonded interaction
- * parameters / if negative: flag for bonded interaction
- */
-void mpi_bcast_ia_params(int i, int j);
-
#endif
diff --git a/src/core/nonbonded_interactions/CMakeLists.txt b/src/core/nonbonded_interactions/CMakeLists.txt
index 66570208137..1e52b0fe4d0 100644
--- a/src/core/nonbonded_interactions/CMakeLists.txt
+++ b/src/core/nonbonded_interactions/CMakeLists.txt
@@ -12,8 +12,6 @@ target_sources(
${CMAKE_CURRENT_SOURCE_DIR}/ljgen.cpp
${CMAKE_CURRENT_SOURCE_DIR}/morse.cpp
${CMAKE_CURRENT_SOURCE_DIR}/nonbonded_interaction_data.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/nonbonded_tab.cpp
${CMAKE_CURRENT_SOURCE_DIR}/soft_sphere.cpp
${CMAKE_CURRENT_SOURCE_DIR}/smooth_step.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/thole.cpp
${CMAKE_CURRENT_SOURCE_DIR}/wca.cpp)
diff --git a/src/core/nonbonded_interactions/bmhtf-nacl.cpp b/src/core/nonbonded_interactions/bmhtf-nacl.cpp
index 74c2d0df9d0..df7975415d2 100644
--- a/src/core/nonbonded_interactions/bmhtf-nacl.cpp
+++ b/src/core/nonbonded_interactions/bmhtf-nacl.cpp
@@ -25,35 +25,29 @@
#include "bmhtf-nacl.hpp"
#ifdef BMHTF_NACL
-#include "interactions.hpp"
#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
-#include
-
-int BMHTF_set_params(int part_type_a, int part_type_b, double A, double B,
- double C, double D, double sig, double cut) {
- double shift, dist2, pw6;
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- dist2 = cut * cut;
- pw6 = dist2 * dist2 * dist2;
- shift = -(A * exp(B * (sig - cut)) - C / pw6 - D / pw6 / dist2);
-
- data->bmhtf.A = A;
- data->bmhtf.B = B;
- data->bmhtf.C = C;
- data->bmhtf.D = D;
- data->bmhtf.sig = sig;
- data->bmhtf.cut = cut;
- data->bmhtf.computed_shift = shift;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+
+#include
+
+BMHTF_Parameters::BMHTF_Parameters(double a, double b, double c, double d,
+ double sig, double cutoff)
+ : A{a}, B{b}, C{c}, D{d}, sig{sig}, cut{cutoff} {
+ if (a < 0.) {
+ throw std::domain_error("BMHTF parameter 'a' has to be >= 0");
+ }
+ if (c < 0.) {
+ throw std::domain_error("BMHTF parameter 'c' has to be >= 0");
+ }
+ if (d < 0.) {
+ throw std::domain_error("BMHTF parameter 'd' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("BMHTF parameter 'cutoff' has to be >= 0");
+ }
+ computed_shift = C / Utils::int_pow<6>(cut) + D / Utils::int_pow<8>(cut) -
+ A * std::exp(B * (sig - cut));
}
-#endif
+#endif // BMHTF_NACL
diff --git a/src/core/nonbonded_interactions/bmhtf-nacl.hpp b/src/core/nonbonded_interactions/bmhtf-nacl.hpp
index b5274c751ee..3926beb42ff 100644
--- a/src/core/nonbonded_interactions/bmhtf-nacl.hpp
+++ b/src/core/nonbonded_interactions/bmhtf-nacl.hpp
@@ -33,14 +33,10 @@
#include "nonbonded_interaction_data.hpp"
-#include
#include
#include
-int BMHTF_set_params(int part_type_a, int part_type_b, double A, double B,
- double C, double D, double sig, double cut);
-
/** Calculate BMHTF force factor */
inline double BMHTF_pair_force_factor(IA_parameters const &ia_params,
double dist) {
@@ -67,5 +63,5 @@ inline double BMHTF_pair_energy(IA_parameters const &ia_params, double dist) {
return 0.0;
}
-#endif
+#endif // BMHTF_NACL
#endif
diff --git a/src/core/nonbonded_interactions/buckingham.cpp b/src/core/nonbonded_interactions/buckingham.cpp
index b8b77565d01..7fd90cdad50 100644
--- a/src/core/nonbonded_interactions/buckingham.cpp
+++ b/src/core/nonbonded_interactions/buckingham.cpp
@@ -25,38 +25,35 @@
#include "buckingham.hpp"
#ifdef BUCKINGHAM
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
-int buckingham_set_params(int part_type_a, int part_type_b, double A, double B,
- double C, double D, double cut, double discont,
- double shift) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->buckingham.A = A;
- data->buckingham.B = B;
- data->buckingham.C = C;
- data->buckingham.D = D;
- data->buckingham.cut = cut;
- data->buckingham.discont = discont;
- data->buckingham.shift = shift;
+#include
+
+Buckingham_Parameters::Buckingham_Parameters(double a, double b, double c,
+ double d, double cutoff,
+ double discont, double shift)
+ : A{a}, B{b}, C{c}, D{d}, cut{cutoff}, discont{discont}, shift{shift} {
+ if (a < 0.) {
+ throw std::domain_error("Buckingham parameter 'a' has to be >= 0");
+ }
+ if (b < 0.) {
+ throw std::domain_error("Buckingham parameter 'b' has to be >= 0");
+ }
+ if (c < 0.) {
+ throw std::domain_error("Buckingham parameter 'c' has to be >= 0");
+ }
+ if (d < 0.) {
+ throw std::domain_error("Buckingham parameter 'd' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("Buckingham parameter 'cutoff' has to be >= 0");
+ }
/* Replace the Buckingham potential for interatomic distance less
than or equal to discontinuity by a straight line (F1+F2*r) */
-
auto const F = buck_force_r(A, B, C, D, discont);
- data->buckingham.F1 = buck_energy_r(A, B, C, D, shift, discont) + discont * F;
- data->buckingham.F2 = -F;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+ F1 = buck_energy_r(A, B, C, D, shift, discont) + discont * F;
+ F2 = -F;
}
-#endif
+#endif // BUCKINGHAM
diff --git a/src/core/nonbonded_interactions/buckingham.hpp b/src/core/nonbonded_interactions/buckingham.hpp
index 4bafa45b974..ed9be7130c7 100644
--- a/src/core/nonbonded_interactions/buckingham.hpp
+++ b/src/core/nonbonded_interactions/buckingham.hpp
@@ -32,14 +32,8 @@
#include "nonbonded_interaction_data.hpp"
-#include
-
#include
-int buckingham_set_params(int part_type_a, int part_type_b, double A, double B,
- double C, double D, double cut, double discont,
- double shift);
-
/**Resultant Force due to a Buckingham potential between two particles at
* interatomic separation r greater than or equal to discont*/
inline double buck_force_r(double A, double B, double C, double D, double r) {
@@ -90,5 +84,5 @@ inline double buck_pair_energy(IA_parameters const &ia_params, double dist) {
return 0.0;
}
-#endif
+#endif // BUCKINGHAM
#endif
diff --git a/src/core/nonbonded_interactions/gaussian.cpp b/src/core/nonbonded_interactions/gaussian.cpp
index 51643bcfa27..76821cf4c11 100644
--- a/src/core/nonbonded_interactions/gaussian.cpp
+++ b/src/core/nonbonded_interactions/gaussian.cpp
@@ -25,26 +25,20 @@
#include "gaussian.hpp"
#ifdef GAUSSIAN
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
-int gaussian_set_params(int part_type_a, int part_type_b, double eps,
- double sig, double cut) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->gaussian.eps = eps;
- data->gaussian.sig = sig;
- data->gaussian.cut = cut;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+
+Gaussian_Parameters::Gaussian_Parameters(double eps, double sig, double cutoff)
+ : eps{eps}, sig{sig}, cut{cutoff} {
+ if (eps < 0.) {
+ throw std::domain_error("Gaussian parameter 'eps' has to be >= 0");
+ }
+ if (sig < 0.) {
+ throw std::domain_error("Gaussian parameter 'sig' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("Gaussian parameter 'cutoff' has to be >= 0");
+ }
}
-
-#endif
+#endif // GAUSSIAN
diff --git a/src/core/nonbonded_interactions/gaussian.hpp b/src/core/nonbonded_interactions/gaussian.hpp
index 9b345ab217c..621f7abd359 100644
--- a/src/core/nonbonded_interactions/gaussian.hpp
+++ b/src/core/nonbonded_interactions/gaussian.hpp
@@ -31,16 +31,12 @@
#include "nonbonded_interaction_data.hpp"
-#include
#include
#include
#ifdef GAUSSIAN
-int gaussian_set_params(int part_type_a, int part_type_b, double eps,
- double sig, double cut);
-
/** Calculate Gaussian force factor */
inline double gaussian_pair_force_factor(IA_parameters const &ia_params,
double dist) {
diff --git a/src/core/nonbonded_interactions/gay_berne.cpp b/src/core/nonbonded_interactions/gay_berne.cpp
index d5732832415..12a9a78b907 100644
--- a/src/core/nonbonded_interactions/gay_berne.cpp
+++ b/src/core/nonbonded_interactions/gay_berne.cpp
@@ -25,39 +25,15 @@
#include "gay_berne.hpp"
#ifdef GAY_BERNE
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
+#include
-int gay_berne_set_params(int part_type_a, int part_type_b, double eps,
- double sig, double cut, double k1, double k2,
- double mu, double nu) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
+GayBerne_Parameters::GayBerne_Parameters(double eps, double sig, double cut,
+ double k1, double k2, double mu,
+ double nu)
+ : eps{eps}, sig{sig}, cut{cut}, k1{k1}, k2{k2}, mu{mu}, nu{nu},
+ chi1{((k1 * k1) - 1.) / ((k1 * k1) + 1.)},
+ chi2{(std::pow(k2, 1. / mu) - 1.) / (std::pow(k2, 1. / mu) + 1.)} {}
- if (!data)
- return ES_ERROR;
-
- data->gay_berne.eps = eps;
- data->gay_berne.sig = sig;
- data->gay_berne.cut = cut;
- data->gay_berne.k1 = k1;
- data->gay_berne.k2 = k2;
- data->gay_berne.mu = mu;
- data->gay_berne.nu = nu;
-
- /* Calculate dependent parameters */
-
- data->gay_berne.chi1 = ((data->gay_berne.k1 * data->gay_berne.k1) - 1) /
- ((data->gay_berne.k1 * data->gay_berne.k1) + 1);
- data->gay_berne.chi2 =
- (pow(data->gay_berne.k2, (1 / data->gay_berne.mu)) - 1) /
- (pow(data->gay_berne.k2, (1 / data->gay_berne.mu)) + 1);
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
-}
-
-#endif
+#endif // GAY_BERNE
diff --git a/src/core/nonbonded_interactions/gay_berne.hpp b/src/core/nonbonded_interactions/gay_berne.hpp
index 2804df031a0..93e707b0055 100644
--- a/src/core/nonbonded_interactions/gay_berne.hpp
+++ b/src/core/nonbonded_interactions/gay_berne.hpp
@@ -45,10 +45,6 @@
#include
-int gay_berne_set_params(int part_type_a, int part_type_b, double eps,
- double sig, double cut, double k1, double k2,
- double mu, double nu);
-
/** Calculate Gay-Berne force and torques */
inline ParticleForce gb_pair_force(Utils::Quaternion const &qi,
Utils::Quaternion const &qj,
diff --git a/src/core/nonbonded_interactions/hat.cpp b/src/core/nonbonded_interactions/hat.cpp
index c861851a6d8..00dd4661ecc 100644
--- a/src/core/nonbonded_interactions/hat.cpp
+++ b/src/core/nonbonded_interactions/hat.cpp
@@ -25,24 +25,18 @@
#include "hat.hpp"
#ifdef HAT
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
+#include
-int hat_set_params(int part_type_a, int part_type_b, double Fmax, double r) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->hat.Fmax = Fmax;
- data->hat.r = r;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+Hat_Parameters::Hat_Parameters(double F_max, double cutoff)
+ : Fmax{F_max}, r{cutoff} {
+ if (F_max < 0.) {
+ throw std::domain_error("Hat parameter 'F_max' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("Hat parameter 'cutoff' has to be >= 0");
+ }
}
-#endif
+#endif // HAT
diff --git a/src/core/nonbonded_interactions/hat.hpp b/src/core/nonbonded_interactions/hat.hpp
index bc9785006d2..3128d77ff4b 100644
--- a/src/core/nonbonded_interactions/hat.hpp
+++ b/src/core/nonbonded_interactions/hat.hpp
@@ -33,14 +33,10 @@
#include "nonbonded_interaction_data.hpp"
-#include
-
-int hat_set_params(int part_type_a, int part_type_b, double Fmax, double r);
-
/** Calculate hat force factor */
inline double hat_pair_force_factor(IA_parameters const &ia_params,
double dist) {
- if (dist > 0. && dist < ia_params.hat.r) {
+ if (dist != 0. and dist < ia_params.hat.r) {
return ia_params.hat.Fmax * (1.0 - dist / ia_params.hat.r) / dist;
}
return 0.0;
@@ -55,5 +51,5 @@ inline double hat_pair_energy(IA_parameters const &ia_params, double dist) {
return 0.0;
}
-#endif /* ifdef HAT */
+#endif // HAT
#endif
diff --git a/src/core/nonbonded_interactions/hertzian.cpp b/src/core/nonbonded_interactions/hertzian.cpp
index 025f513b9e5..9ee911d0757 100644
--- a/src/core/nonbonded_interactions/hertzian.cpp
+++ b/src/core/nonbonded_interactions/hertzian.cpp
@@ -25,25 +25,18 @@
#include "hertzian.hpp"
#ifdef HERTZIAN
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
+#include
-int hertzian_set_params(int part_type_a, int part_type_b, double eps,
- double sig) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->hertzian.eps = eps;
- data->hertzian.sig = sig;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+Hertzian_Parameters::Hertzian_Parameters(double eps, double sig)
+ : eps{eps}, sig{sig} {
+ if (eps < 0.) {
+ throw std::domain_error("Hertzian parameter 'eps' has to be >= 0");
+ }
+ if (sig < 0.) {
+ throw std::domain_error("Hertzian parameter 'sig' has to be >= 0");
+ }
}
-#endif
+#endif // HERTZIAN
diff --git a/src/core/nonbonded_interactions/hertzian.hpp b/src/core/nonbonded_interactions/hertzian.hpp
index 767c401dc6d..89dc3bebc23 100644
--- a/src/core/nonbonded_interactions/hertzian.hpp
+++ b/src/core/nonbonded_interactions/hertzian.hpp
@@ -31,15 +31,10 @@
#include "nonbonded_interaction_data.hpp"
-#include
-
#include
#ifdef HERTZIAN
-int hertzian_set_params(int part_type_a, int part_type_b, double eps,
- double sig);
-
/** Calculate Hertzian force factor */
inline double hertzian_pair_force_factor(IA_parameters const &ia_params,
double dist) {
diff --git a/src/core/nonbonded_interactions/lj.cpp b/src/core/nonbonded_interactions/lj.cpp
index ebc988949be..afb8a63b341 100644
--- a/src/core/nonbonded_interactions/lj.cpp
+++ b/src/core/nonbonded_interactions/lj.cpp
@@ -25,31 +25,24 @@
#include "lj.hpp"
#ifdef LENNARD_JONES
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
+#include
+#include
-int lennard_jones_set_params(int part_type_a, int part_type_b, double eps,
- double sig, double cut, double shift,
- double offset, double min) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->lj.eps = eps;
- data->lj.sig = sig;
- data->lj.cut = cut;
- data->lj.shift = shift;
- data->lj.offset = offset;
- if (min > 0) {
- data->lj.min = min;
+LJ_Parameters::LJ_Parameters(double epsilon, double sigma, double cutoff,
+ double offset, double min, double shift)
+ : eps{epsilon}, sig{sigma}, cut{cutoff}, shift{shift}, offset{offset},
+ min{std::max(min, 0.)} {
+ if (epsilon < 0.) {
+ throw std::domain_error("LJ parameter 'epsilon' has to be >= 0");
+ }
+ if (sigma < 0.) {
+ throw std::domain_error("LJ parameter 'sigma' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("LJ parameter 'cutoff' has to be >= 0");
}
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
}
#endif /* ifdef LENNARD_JONES */
diff --git a/src/core/nonbonded_interactions/lj.hpp b/src/core/nonbonded_interactions/lj.hpp
index 99b5d6f7df5..e0eeb4f54a7 100644
--- a/src/core/nonbonded_interactions/lj.hpp
+++ b/src/core/nonbonded_interactions/lj.hpp
@@ -37,15 +37,10 @@
#include
#include
-int lennard_jones_set_params(int part_type_a, int part_type_b, double eps,
- double sig, double cut, double shift,
- double offset, double min);
-
/** Calculate Lennard-Jones force factor */
inline double lj_pair_force_factor(IA_parameters const &ia_params,
double dist) {
- if ((dist < ia_params.lj.cut + ia_params.lj.offset) &&
- (dist > ia_params.lj.min + ia_params.lj.offset)) {
+ if (dist < ia_params.lj.max_cutoff() and dist > ia_params.lj.min_cutoff()) {
auto const r_off = dist - ia_params.lj.offset;
auto const frac6 = Utils::int_pow<6>(ia_params.lj.sig / r_off);
return 48.0 * ia_params.lj.eps * frac6 * (frac6 - 0.5) / (r_off * dist);
@@ -55,8 +50,7 @@ inline double lj_pair_force_factor(IA_parameters const &ia_params,
/** Calculate Lennard-Jones energy */
inline double lj_pair_energy(IA_parameters const &ia_params, double dist) {
- if ((dist < ia_params.lj.cut + ia_params.lj.offset) &&
- (dist > ia_params.lj.min + ia_params.lj.offset)) {
+ if (dist < ia_params.lj.max_cutoff() and dist > ia_params.lj.min_cutoff()) {
auto const r_off = dist - ia_params.lj.offset;
auto const frac6 = Utils::int_pow<6>(ia_params.lj.sig / r_off);
return 4.0 * ia_params.lj.eps *
diff --git a/src/core/nonbonded_interactions/ljcos.cpp b/src/core/nonbonded_interactions/ljcos.cpp
index 78c29d28a80..1fa4d75e266 100644
--- a/src/core/nonbonded_interactions/ljcos.cpp
+++ b/src/core/nonbonded_interactions/ljcos.cpp
@@ -25,34 +25,30 @@
#include "ljcos.hpp"
#ifdef LJCOS
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
#include
#include
-int ljcos_set_params(int part_type_a, int part_type_b, double eps, double sig,
- double cut, double offset) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->ljcos.eps = eps;
- data->ljcos.sig = sig;
- data->ljcos.cut = cut;
- data->ljcos.offset = offset;
-
- /* Calculate dependent parameters */
+#include
+
+LJcos_Parameters::LJcos_Parameters(double epsilon, double sigma, double cutoff,
+ double offset)
+ : eps{epsilon}, sig{sigma}, cut{cutoff}, offset{offset} {
+ if (epsilon < 0.) {
+ throw std::domain_error("LJcos parameter 'epsilon' has to be >= 0");
+ }
+ if (sigma < 0.) {
+ throw std::domain_error("LJcos parameter 'sigma' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("LJcos parameter 'cutoff' has to be >= 0");
+ }
auto const facsq = Utils::cbrt_2() * Utils::sqr(sig);
- data->ljcos.rmin = sqrt(Utils::cbrt_2()) * sig;
- data->ljcos.alfa = Utils::pi() / (Utils::sqr(data->ljcos.cut) - facsq);
- data->ljcos.beta =
- Utils::pi() * (1. - (1. / (Utils::sqr(data->ljcos.cut) / facsq - 1.)));
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+ rmin = sqrt(Utils::cbrt_2()) * sig;
+ alfa = Utils::pi() / (Utils::sqr(cut) - facsq);
+ beta = Utils::pi() * (1. - (1. / (Utils::sqr(cut) / facsq - 1.)));
}
-#endif
+
+#endif // LJCOS
diff --git a/src/core/nonbonded_interactions/ljcos.hpp b/src/core/nonbonded_interactions/ljcos.hpp
index 50e9abd824e..0221bc0c22d 100644
--- a/src/core/nonbonded_interactions/ljcos.hpp
+++ b/src/core/nonbonded_interactions/ljcos.hpp
@@ -33,15 +33,11 @@
#include "nonbonded_interaction_data.hpp"
-#include
#include
#include
#include
-int ljcos_set_params(int part_type_a, int part_type_b, double eps, double sig,
- double cut, double offset);
-
/** Calculate Lennard-Jones cosine force factor */
inline double ljcos_pair_force_factor(IA_parameters const &ia_params,
double dist) {
diff --git a/src/core/nonbonded_interactions/ljcos2.cpp b/src/core/nonbonded_interactions/ljcos2.cpp
index 56237327934..1f4539e26f0 100644
--- a/src/core/nonbonded_interactions/ljcos2.cpp
+++ b/src/core/nonbonded_interactions/ljcos2.cpp
@@ -25,33 +25,27 @@
#include "ljcos2.hpp"
#ifdef LJCOS2
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
#include
-
-int ljcos2_set_params(int part_type_a, int part_type_b, double eps, double sig,
- double offset, double w) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->ljcos2.eps = eps;
- data->ljcos2.sig = sig;
- data->ljcos2.offset = offset;
- data->ljcos2.w = w;
-
- /* calculate dependent parameters */
- data->ljcos2.rchange = pow(2, 1 / 6.) * sig;
- data->ljcos2.cut = w + data->ljcos2.rchange;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+
+LJcos2_Parameters::LJcos2_Parameters(double epsilon, double sigma,
+ double offset, double width)
+ : eps{epsilon}, sig{sigma}, offset{offset}, w{width} {
+ if (epsilon < 0.) {
+ throw std::domain_error("LJcos2 parameter 'epsilon' has to be >= 0");
+ }
+ if (sigma < 0.) {
+ throw std::domain_error("LJcos2 parameter 'sigma' has to be >= 0");
+ }
+ if (width < 0.) {
+ throw std::domain_error("LJcos2 parameter 'width' has to be >= 0");
+ }
+ if (sigma != 0.) {
+ rchange = std::pow(2., 1. / 6.) * sigma;
+ cut = width + rchange;
+ }
}
#endif /* ifdef LJCOS2 */
diff --git a/src/core/nonbonded_interactions/ljcos2.hpp b/src/core/nonbonded_interactions/ljcos2.hpp
index 3d39d94c242..482da3b435a 100644
--- a/src/core/nonbonded_interactions/ljcos2.hpp
+++ b/src/core/nonbonded_interactions/ljcos2.hpp
@@ -36,16 +36,12 @@
#include "nonbonded_interaction_data.hpp"
-#include
#include
#include
#include
#include
-int ljcos2_set_params(int part_type_a, int part_type_b, double eps, double sig,
- double offset, double w);
-
/** Calculate Lennard-Jones cosine squared force factor */
inline double ljcos2_pair_force_factor(IA_parameters const &ia_params,
double dist) {
diff --git a/src/core/nonbonded_interactions/ljgen.cpp b/src/core/nonbonded_interactions/ljgen.cpp
index 862d0dfef81..d97e80f7258 100644
--- a/src/core/nonbonded_interactions/ljgen.cpp
+++ b/src/core/nonbonded_interactions/ljgen.cpp
@@ -25,43 +25,39 @@
#include "ljgen.hpp"
#ifdef LENNARD_JONES_GENERIC
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
-int ljgen_set_params(int part_type_a, int part_type_b, double eps, double sig,
- double cut, double shift, double offset, double a1,
- double a2, double b1, double b2
+#include
+LJGen_Parameters::LJGen_Parameters(double epsilon, double sigma, double cutoff,
+ double shift, double offset,
#ifdef LJGEN_SOFTCORE
- ,
- double lambda, double softrad
+ double lam, double delta,
#endif
-) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->ljgen.eps = eps;
- data->ljgen.sig = sig;
- data->ljgen.cut = cut;
- data->ljgen.shift = shift;
- data->ljgen.offset = offset;
- data->ljgen.a1 = a1;
- data->ljgen.a2 = a2;
- data->ljgen.b1 = b1;
- data->ljgen.b2 = b2;
+ double e1, double e2, double b1, double b2)
+ : eps{epsilon}, sig{sigma}, cut{cutoff}, shift{shift}, offset{offset},
#ifdef LJGEN_SOFTCORE
- data->ljgen.lambda1 = lambda;
- data->ljgen.softrad = softrad;
+ lambda{lam}, softrad{delta},
#endif
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+ a1{e1}, a2{e2}, b1{b1}, b2{b2} {
+ if (epsilon < 0.) {
+ throw std::domain_error("Generic LJ parameter 'epsilon' has to be >= 0");
+ }
+ if (sigma < 0.) {
+ throw std::domain_error("Generic LJ parameter 'sigma' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("Generic LJ parameter 'cutoff' has to be >= 0");
+ }
+#ifdef LJGEN_SOFTCORE
+ if (delta < 0.) {
+ throw std::domain_error("Generic LJ parameter 'delta' has to be >= 0");
+ }
+ if (lam < 0. or lam > 1.) {
+ throw std::domain_error(
+ "Generic LJ parameter 'lam' has to be in the range [0, 1]");
+ }
+#endif // LJGEN_SOFTCORE
}
-#endif
+#endif // LENNARD_JONES_GENERIC
diff --git a/src/core/nonbonded_interactions/ljgen.hpp b/src/core/nonbonded_interactions/ljgen.hpp
index 23afed47a95..5f370d37909 100644
--- a/src/core/nonbonded_interactions/ljgen.hpp
+++ b/src/core/nonbonded_interactions/ljgen.hpp
@@ -47,24 +47,15 @@
#include
-int ljgen_set_params(int part_type_a, int part_type_b, double eps, double sig,
- double cut, double shift, double offset, double a1,
- double a2, double b1, double b2
-#ifdef LJGEN_SOFTCORE
- ,
- double lambda, double softrad
-#endif
-);
-
/** Calculate Lennard-Jones force factor */
inline double ljgen_pair_force_factor(IA_parameters const &ia_params,
double dist) {
- if (dist < (ia_params.ljgen.cut + ia_params.ljgen.offset)) {
+ if (dist < ia_params.ljgen.max_cutoff()) {
auto r_off = dist - ia_params.ljgen.offset;
#ifdef LJGEN_SOFTCORE
r_off *= r_off;
- r_off += Utils::sqr(ia_params.ljgen.sig) * (1.0 - ia_params.ljgen.lambda1) *
+ r_off += Utils::sqr(ia_params.ljgen.sig) * (1.0 - ia_params.ljgen.lambda) *
ia_params.ljgen.softrad;
r_off = sqrt(r_off);
#else
@@ -73,7 +64,7 @@ inline double ljgen_pair_force_factor(IA_parameters const &ia_params,
auto const frac = ia_params.ljgen.sig / r_off;
auto const fac = ia_params.ljgen.eps
#ifdef LJGEN_SOFTCORE
- * ia_params.ljgen.lambda1 *
+ * ia_params.ljgen.lambda *
(dist - ia_params.ljgen.offset) / r_off
#endif
* (ia_params.ljgen.b1 * ia_params.ljgen.a1 *
@@ -88,11 +79,11 @@ inline double ljgen_pair_force_factor(IA_parameters const &ia_params,
/** Calculate Lennard-Jones energy */
inline double ljgen_pair_energy(IA_parameters const &ia_params, double dist) {
- if (dist < (ia_params.ljgen.cut + ia_params.ljgen.offset)) {
+ if (dist < ia_params.ljgen.max_cutoff()) {
auto r_off = dist - ia_params.ljgen.offset;
#ifdef LJGEN_SOFTCORE
r_off *= r_off;
- r_off += pow(ia_params.ljgen.sig, 2) * (1.0 - ia_params.ljgen.lambda1) *
+ r_off += pow(ia_params.ljgen.sig, 2) * (1.0 - ia_params.ljgen.lambda) *
ia_params.ljgen.softrad;
r_off = sqrt(r_off);
#else
@@ -101,7 +92,7 @@ inline double ljgen_pair_energy(IA_parameters const &ia_params, double dist) {
auto const frac = ia_params.ljgen.sig / r_off;
auto const fac = ia_params.ljgen.eps
#ifdef LJGEN_SOFTCORE
- * ia_params.ljgen.lambda1
+ * ia_params.ljgen.lambda
#endif
* (ia_params.ljgen.b1 * pow(frac, ia_params.ljgen.a1) -
ia_params.ljgen.b2 * pow(frac, ia_params.ljgen.a2) +
@@ -112,4 +103,4 @@ inline double ljgen_pair_energy(IA_parameters const &ia_params, double dist) {
}
#endif // LENNARD_JONES_GENERIC
-#endif // CORE_NB_IA_LJGEN_HPP
+#endif
diff --git a/src/core/nonbonded_interactions/morse.cpp b/src/core/nonbonded_interactions/morse.cpp
index f31d2335be5..a4e4cfe0212 100644
--- a/src/core/nonbonded_interactions/morse.cpp
+++ b/src/core/nonbonded_interactions/morse.cpp
@@ -25,33 +25,23 @@
#include "morse.hpp"
#ifdef MORSE
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
-int morse_set_params(int part_type_a, int part_type_b, double eps, double alpha,
- double rmin, double cut) {
- double add1, add2;
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->morse.eps = eps;
- data->morse.alpha = alpha;
- data->morse.rmin = rmin;
- data->morse.cut = cut;
-
- /* calculate dependent parameter */
- add1 = exp(-2.0 * data->morse.alpha * (data->morse.cut - data->morse.rmin));
- add2 = 2.0 * exp(-data->morse.alpha * (data->morse.cut - data->morse.rmin));
- data->morse.rest = data->morse.eps * (add1 - add2);
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+#include
+
+Morse_Parameters::Morse_Parameters(double eps, double alpha, double rmin,
+ double cutoff)
+ : eps{eps}, alpha{alpha}, rmin{rmin}, cut{cutoff} {
+ if (eps < 0.) {
+ throw std::domain_error("Morse parameter 'eps' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("Morse parameter 'cutoff' has to be >= 0");
+ }
+ auto const add1 = std::exp(-2.0 * alpha * (cut - rmin));
+ auto const add2 = 2.0 * std::exp(-alpha * (cut - rmin));
+ rest = eps * (add1 - add2);
}
-#endif
+#endif // MORSE
diff --git a/src/core/nonbonded_interactions/morse.hpp b/src/core/nonbonded_interactions/morse.hpp
index 4515e2b0837..66b1f3678de 100644
--- a/src/core/nonbonded_interactions/morse.hpp
+++ b/src/core/nonbonded_interactions/morse.hpp
@@ -33,14 +33,10 @@
#include "nonbonded_interaction_data.hpp"
-#include
#include
#include
-int morse_set_params(int part_type_a, int part_type_b, double eps, double alpha,
- double rmin, double cut);
-
/** Calculate Morse force factor */
inline double morse_pair_force_factor(IA_parameters const &ia_params,
double dist) {
@@ -64,5 +60,5 @@ inline double morse_pair_energy(IA_parameters const &ia_params, double dist) {
return 0.0;
}
-#endif /* ifdef MORSE */
-#endif /* ifdef CORE_NB_IA_MORSE_HPP */
+#endif // MORSE
+#endif
diff --git a/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp b/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp
index 5250e802c87..8b1925ba306 100644
--- a/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp
+++ b/src/core/nonbonded_interactions/nonbonded_interaction_data.cpp
@@ -26,21 +26,11 @@
#include "communication.hpp"
#include "electrostatics/coulomb.hpp"
#include "event.hpp"
-#include "serialization/IA_parameters.hpp"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
#include
-#include
-#include
+#include
#include
#include
@@ -48,7 +38,7 @@
* variables
*****************************************/
int max_seen_particle_type = 0;
-std::vector nonbonded_ia_params;
+std::vector> nonbonded_ia_params;
/** Minimal global interaction cutoff. Particles with a distance
* smaller than this are guaranteed to be available on the same node
@@ -60,132 +50,95 @@ static double min_global_cut = INACTIVE_CUTOFF;
* general low-level functions
*****************************************/
-static void mpi_realloc_ia_params_local(int new_size) {
- if (new_size <= max_seen_particle_type)
+void mpi_realloc_ia_params_local(int new_size) {
+ auto const old_size = ::max_seen_particle_type;
+ if (new_size <= old_size)
return;
- auto new_params = std::vector(new_size * (new_size + 1) / 2);
+ auto const n_pairs = new_size * (new_size + 1) / 2;
+ auto new_params = std::vector>(n_pairs);
/* if there is an old field, move entries */
- for (int i = 0; i < max_seen_particle_type; i++)
- for (int j = i; j < max_seen_particle_type; j++) {
- new_params.at(Utils::upper_triangular(i, j, new_size)) =
- std::move(get_ia_param(i, j));
+ for (int i = 0; i < old_size; i++) {
+ for (int j = i; j < old_size; j++) {
+ auto const new_key = Utils::upper_triangular(i, j, new_size);
+ auto const old_key = Utils::upper_triangular(i, j, old_size);
+ new_params[new_key] = std::move(nonbonded_ia_params[old_key]);
+ }
+ }
+ for (auto &ia_params : new_params) {
+ if (ia_params == nullptr) {
+ ia_params = std::make_shared();
}
+ }
- max_seen_particle_type = new_size;
- std::swap(nonbonded_ia_params, new_params);
+ ::max_seen_particle_type = new_size;
+ ::nonbonded_ia_params = std::move(new_params);
}
REGISTER_CALLBACK(mpi_realloc_ia_params_local)
-/** Increase the size of the @ref nonbonded_ia_params vector. */
-static void mpi_realloc_ia_params(int new_size) {
- mpi_call_all(mpi_realloc_ia_params_local, new_size);
-}
-
-static void mpi_bcast_all_ia_params_local() {
- boost::mpi::broadcast(comm_cart, nonbonded_ia_params, 0);
-}
-
-REGISTER_CALLBACK(mpi_bcast_all_ia_params_local)
-
-/** Broadcast @ref nonbonded_ia_params to all nodes. */
-static void mpi_bcast_all_ia_params() {
- mpi_call_all(mpi_bcast_all_ia_params_local);
-}
-
-IA_parameters *get_ia_param_safe(int i, int j) {
- make_particle_type_exist(std::max(i, j));
- return &get_ia_param(i, j);
-}
-
-std::string ia_params_get_state() {
- std::stringstream out;
- boost::archive::binary_oarchive oa(out);
- oa << nonbonded_ia_params;
- oa << max_seen_particle_type;
- return out.str();
-}
-
-void ia_params_set_state(std::string const &state) {
- namespace iostreams = boost::iostreams;
- iostreams::array_source src(state.data(), state.size());
- iostreams::stream ss(src);
- boost::archive::binary_iarchive ia(ss);
- nonbonded_ia_params.clear();
- ia >> nonbonded_ia_params;
- ia >> max_seen_particle_type;
- mpi_realloc_ia_params(max_seen_particle_type);
- mpi_bcast_all_ia_params();
-}
-
static double recalc_maximal_cutoff(const IA_parameters &data) {
auto max_cut_current = INACTIVE_CUTOFF;
#ifdef LENNARD_JONES
- max_cut_current = std::max(max_cut_current, (data.lj.cut + data.lj.offset));
+ max_cut_current = std::max(max_cut_current, data.lj.max_cutoff());
#endif
#ifdef WCA
- max_cut_current = std::max(max_cut_current, data.wca.cut);
+ max_cut_current = std::max(max_cut_current, data.wca.max_cutoff());
#endif
#ifdef DPD
- max_cut_current = std::max(
- max_cut_current, std::max(data.dpd_radial.cutoff, data.dpd_trans.cutoff));
+ max_cut_current = std::max(max_cut_current, data.dpd.max_cutoff());
#endif
#ifdef LENNARD_JONES_GENERIC
- max_cut_current =
- std::max(max_cut_current, (data.ljgen.cut + data.ljgen.offset));
+ max_cut_current = std::max(max_cut_current, data.ljgen.max_cutoff());
#endif
#ifdef SMOOTH_STEP
- max_cut_current = std::max(max_cut_current, data.smooth_step.cut);
+ max_cut_current = std::max(max_cut_current, data.smooth_step.max_cutoff());
#endif
#ifdef HERTZIAN
- max_cut_current = std::max(max_cut_current, data.hertzian.sig);
+ max_cut_current = std::max(max_cut_current, data.hertzian.max_cutoff());
#endif
#ifdef GAUSSIAN
- max_cut_current = std::max(max_cut_current, data.gaussian.cut);
+ max_cut_current = std::max(max_cut_current, data.gaussian.max_cutoff());
#endif
#ifdef BMHTF_NACL
- max_cut_current = std::max(max_cut_current, data.bmhtf.cut);
+ max_cut_current = std::max(max_cut_current, data.bmhtf.max_cutoff());
#endif
#ifdef MORSE
- max_cut_current = std::max(max_cut_current, data.morse.cut);
+ max_cut_current = std::max(max_cut_current, data.morse.max_cutoff());
#endif
#ifdef BUCKINGHAM
- max_cut_current = std::max(max_cut_current, data.buckingham.cut);
+ max_cut_current = std::max(max_cut_current, data.buckingham.max_cutoff());
#endif
#ifdef SOFT_SPHERE
- max_cut_current = std::max(max_cut_current,
- (data.soft_sphere.cut + data.soft_sphere.offset));
+ max_cut_current = std::max(max_cut_current, data.soft_sphere.max_cutoff());
#endif
#ifdef HAT
- max_cut_current = std::max(max_cut_current, data.hat.r);
+ max_cut_current = std::max(max_cut_current, data.hat.max_cutoff());
#endif
#ifdef LJCOS
- max_cut_current =
- std::max(max_cut_current, (data.ljcos.cut + data.ljcos.offset));
+ max_cut_current = std::max(max_cut_current, data.ljcos.max_cutoff());
#endif
#ifdef LJCOS2
- max_cut_current =
- std::max(max_cut_current, (data.ljcos2.cut + data.ljcos2.offset));
+ max_cut_current = std::max(max_cut_current, data.ljcos2.max_cutoff());
#endif
#ifdef GAY_BERNE
- max_cut_current = std::max(max_cut_current, data.gay_berne.cut);
+ max_cut_current = std::max(max_cut_current, data.gay_berne.max_cutoff());
#endif
#ifdef TABULATED
@@ -194,7 +147,7 @@ static double recalc_maximal_cutoff(const IA_parameters &data) {
#ifdef THOLE
// If THOLE is active, use p3m cutoff
- if (data.thole.scaling_coeff != 0)
+ if (data.thole.scaling_coeff != 0.)
max_cut_current = std::max(max_cut_current, Coulomb::cutoff());
#endif
@@ -205,25 +158,20 @@ double maximal_cutoff_nonbonded() {
auto max_cut_nonbonded = INACTIVE_CUTOFF;
for (auto &data : nonbonded_ia_params) {
- data.max_cut = recalc_maximal_cutoff(data);
- max_cut_nonbonded = std::max(max_cut_nonbonded, data.max_cut);
+ data->max_cut = recalc_maximal_cutoff(*data);
+ max_cut_nonbonded = std::max(max_cut_nonbonded, data->max_cut);
}
return max_cut_nonbonded;
}
-void reset_ia_params() {
- boost::fill(nonbonded_ia_params, IA_parameters{});
- mpi_bcast_all_ia_params();
-}
-
bool is_new_particle_type(int type) {
return (type + 1) > max_seen_particle_type;
}
void make_particle_type_exist(int type) {
if (is_new_particle_type(type))
- mpi_realloc_ia_params(type + 1);
+ mpi_call_all(mpi_realloc_ia_params_local, type + 1);
}
void make_particle_type_exist_local(int type) {
diff --git a/src/core/nonbonded_interactions/nonbonded_interaction_data.hpp b/src/core/nonbonded_interactions/nonbonded_interaction_data.hpp
index 2926e7ceb75..a6370f456d5 100644
--- a/src/core/nonbonded_interactions/nonbonded_interaction_data.hpp
+++ b/src/core/nonbonded_interactions/nonbonded_interaction_data.hpp
@@ -28,10 +28,12 @@
#include "config/config.hpp"
#include
+#include
#include
#include
-#include
+#include
+#include
#include
/** Cutoff for deactivated interactions. Must be negative, so that even
@@ -47,6 +49,18 @@ struct LJ_Parameters {
double shift = 0.0;
double offset = 0.0;
double min = 0.0;
+ LJ_Parameters() = default;
+ LJ_Parameters(double epsilon, double sigma, double cutoff, double offset,
+ double min, double shift);
+ double get_auto_shift() const {
+ auto auto_shift = 0.;
+ if (cut != 0.) {
+ auto_shift = Utils::int_pow<6>(sig / cut) - Utils::int_pow<12>(sig / cut);
+ }
+ return auto_shift;
+ }
+ double max_cutoff() const { return cut + offset; }
+ double min_cutoff() const { return min + offset; }
};
/** WCA potential */
@@ -54,6 +68,9 @@ struct WCA_Parameters {
double eps = 0.0;
double sig = 0.0;
double cut = INACTIVE_CUTOFF;
+ WCA_Parameters() = default;
+ WCA_Parameters(double epsilon, double sigma);
+ double max_cutoff() const { return cut; }
};
/** Generic Lennard-Jones with shift */
@@ -63,12 +80,27 @@ struct LJGen_Parameters {
double cut = INACTIVE_CUTOFF;
double shift = 0.0;
double offset = 0.0;
+ double lambda = 1.0;
+ double softrad = 0.0;
double a1 = 0.0;
double a2 = 0.0;
double b1 = 0.0;
double b2 = 0.0;
- double lambda1 = 1.0;
- double softrad = 0.0;
+ LJGen_Parameters() = default;
+ LJGen_Parameters(double epsilon, double sigma, double cutoff, double shift,
+ double offset,
+#ifdef LJGEN_SOFTCORE
+ double lam, double delta,
+#endif
+ double e1, double e2, double b1, double b2);
+ double get_auto_shift() const {
+ auto auto_shift = 0.;
+ if (cut != 0.) {
+ auto_shift = b2 * std::pow(sig / cut, a2) - b1 * std::pow(sig / cut, a1);
+ }
+ return auto_shift;
+ }
+ double max_cutoff() const { return cut + offset; }
};
/** smooth step potential */
@@ -79,12 +111,19 @@ struct SmoothStep_Parameters {
double d = 0.0;
int n = 0;
double k0 = 0.0;
+ SmoothStep_Parameters() = default;
+ SmoothStep_Parameters(double eps, double sig, double cutoff, double d, int n,
+ double k0);
+ double max_cutoff() const { return cut; }
};
/** Hertzian potential */
struct Hertzian_Parameters {
double eps = 0.0;
double sig = INACTIVE_CUTOFF;
+ Hertzian_Parameters() = default;
+ Hertzian_Parameters(double eps, double sig);
+ double max_cutoff() const { return sig; }
};
/** Gaussian potential */
@@ -92,6 +131,9 @@ struct Gaussian_Parameters {
double eps = 0.0;
double sig = 1.0;
double cut = INACTIVE_CUTOFF;
+ Gaussian_Parameters() = default;
+ Gaussian_Parameters(double eps, double sig, double cutoff);
+ double max_cutoff() const { return cut; }
};
/** BMHTF NaCl potential */
@@ -103,15 +145,22 @@ struct BMHTF_Parameters {
double sig = 0.0;
double cut = INACTIVE_CUTOFF;
double computed_shift = 0.0;
+ BMHTF_Parameters() = default;
+ BMHTF_Parameters(double A, double B, double C, double D, double sig,
+ double cut);
+ double max_cutoff() const { return cut; }
};
/** Morse potential */
struct Morse_Parameters {
- double eps = INACTIVE_CUTOFF;
+ double eps = 0.;
double alpha = INACTIVE_CUTOFF;
double rmin = INACTIVE_CUTOFF;
double cut = INACTIVE_CUTOFF;
double rest = INACTIVE_CUTOFF;
+ Morse_Parameters() = default;
+ Morse_Parameters(double eps, double alpha, double rmin, double cutoff);
+ double max_cutoff() const { return cut; }
};
/** Buckingham potential */
@@ -125,6 +174,10 @@ struct Buckingham_Parameters {
double shift = 0.0;
double F1 = 0.0;
double F2 = 0.0;
+ Buckingham_Parameters() = default;
+ Buckingham_Parameters(double a, double b, double c, double d, double cutoff,
+ double discont, double shift);
+ double max_cutoff() const { return cut; }
};
/** soft-sphere potential */
@@ -133,12 +186,18 @@ struct SoftSphere_Parameters {
double n = 0.0;
double cut = INACTIVE_CUTOFF;
double offset = 0.0;
+ SoftSphere_Parameters() = default;
+ SoftSphere_Parameters(double a, double n, double cutoff, double offset);
+ double max_cutoff() const { return cut + offset; }
};
/** hat potential */
struct Hat_Parameters {
double Fmax = 0.0;
double r = INACTIVE_CUTOFF;
+ Hat_Parameters() = default;
+ Hat_Parameters(double F_max, double cutoff);
+ double max_cutoff() const { return r; }
};
/** Lennard-Jones+Cos potential */
@@ -150,6 +209,9 @@ struct LJcos_Parameters {
double alfa = 0.0;
double beta = 0.0;
double rmin = 0.0;
+ LJcos_Parameters() = default;
+ LJcos_Parameters(double epsilon, double sigma, double cutoff, double offset);
+ double max_cutoff() const { return cut + offset; }
};
/** Lennard-Jones with a different Cos potential */
@@ -160,6 +222,9 @@ struct LJcos2_Parameters {
double offset = 0.0;
double w = 0.0;
double rchange = 0.0;
+ LJcos2_Parameters() = default;
+ LJcos2_Parameters(double epsilon, double sigma, double offset, double width);
+ double max_cutoff() const { return cut + offset; }
};
/** Gay-Berne potential */
@@ -173,23 +238,42 @@ struct GayBerne_Parameters {
double nu = 0.0;
double chi1 = 0.0;
double chi2 = 0.0;
+ GayBerne_Parameters() = default;
+ GayBerne_Parameters(double eps, double sig, double cut, double k1, double k2,
+ double mu, double nu);
+ double max_cutoff() const { return cut; }
};
/** Thole potential */
struct Thole_Parameters {
- double scaling_coeff;
- double q1q2;
+ double scaling_coeff = 0.; // inactive cutoff is 0
+ double q1q2 = 0.;
+ Thole_Parameters() = default;
+ Thole_Parameters(double scaling_coeff, double q1q2)
+ : scaling_coeff{scaling_coeff}, q1q2{q1q2} {}
};
/** DPD potential */
struct DPDParameters {
double gamma = 0.;
double k = 1.;
- double cutoff = -1.;
+ double cutoff = INACTIVE_CUTOFF;
int wf = 0;
double pref = 0.0;
};
+struct DPD_Parameters {
+ DPDParameters radial;
+ DPDParameters trans;
+ DPD_Parameters() = default;
+ DPD_Parameters(double gamma, double k, double r_c, int wf, double tgamma,
+ double tr_c, int twf) {
+ radial = DPDParameters{gamma, k, r_c, wf, -1.};
+ trans = DPDParameters{tgamma, k, tr_c, twf, -1.};
+ }
+ double max_cutoff() const { return std::max(radial.cutoff, trans.cutoff); }
+};
+
/** Data structure containing the interaction parameters for non-bonded
* interactions.
* Access via get_ia_param(i, j) with
@@ -263,11 +347,7 @@ struct IA_parameters {
#endif
#ifdef DPD
- /** \name DPD as interaction */
- /**@{*/
- DPDParameters dpd_radial;
- DPDParameters dpd_trans;
- /**@}*/
+ DPD_Parameters dpd;
#endif
#ifdef THOLE
@@ -275,7 +355,7 @@ struct IA_parameters {
#endif
};
-extern std::vector nonbonded_ia_params;
+extern std::vector> nonbonded_ia_params;
/** Maximal particle type seen so far. */
extern int max_seen_particle_type;
@@ -285,6 +365,13 @@ extern int max_seen_particle_type;
*/
double maximal_cutoff_nonbonded();
+inline int get_ia_param_key(int i, int j) {
+ assert(i >= 0 && i < ::max_seen_particle_type);
+ assert(j >= 0 && j < ::max_seen_particle_type);
+ return Utils::upper_triangular(std::min(i, j), std::max(i, j),
+ ::max_seen_particle_type);
+}
+
/**
* @brief Get interaction parameters between particle types i and j
*
@@ -297,26 +384,10 @@ double maximal_cutoff_nonbonded();
* @return Reference to interaction parameters for the type pair.
*/
inline IA_parameters &get_ia_param(int i, int j) {
- assert(i >= 0 && i < max_seen_particle_type);
- assert(j >= 0 && j < max_seen_particle_type);
-
- return nonbonded_ia_params[Utils::upper_triangular(
- std::min(i, j), std::max(i, j), max_seen_particle_type)];
+ return *::nonbonded_ia_params[get_ia_param_key(i, j)];
}
-/** Get interaction parameters between particle types i and j.
- * Slower than @ref get_ia_param, but can also be used on not
- * yet present particle types
- */
-IA_parameters *get_ia_param_safe(int i, int j);
-
-/** @brief Get the state of all non-bonded interactions.
- */
-std::string ia_params_get_state();
-
-/** @brief Set the state of all non-bonded interactions.
- */
-void ia_params_set_state(std::string const &);
+void mpi_realloc_ia_params_local(int new_size);
bool is_new_particle_type(int type);
/** Make sure that ia_params is large enough to cover interactions
@@ -327,11 +398,6 @@ void make_particle_type_exist(int type);
void make_particle_type_exist_local(int type);
-/**
- * @brief Reset all interaction parameters to their defaults.
- */
-void reset_ia_params();
-
/** Check if a non-bonded interaction is defined */
inline bool checkIfInteraction(IA_parameters const &data) {
return data.max_cut != INACTIVE_CUTOFF;
diff --git a/src/core/nonbonded_interactions/nonbonded_tab.cpp b/src/core/nonbonded_interactions/nonbonded_tab.cpp
deleted file mode 100644
index d9cbaef5ebe..00000000000
--- a/src/core/nonbonded_interactions/nonbonded_tab.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2010-2022 The ESPResSo project
- * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
- * Max-Planck-Institute for Polymer Research, Theory Group
- *
- * This file is part of ESPResSo.
- *
- * ESPResSo is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * ESPResSo is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-/** \file
- *
- * Implementation of \ref nonbonded_tab.hpp
- */
-#include "nonbonded_interactions/nonbonded_tab.hpp"
-
-#ifdef TABULATED
-#include "interactions.hpp"
-
-#include
-
-#include
-#include
-
-int tabulated_set_params(int part_type_a, int part_type_b, double min,
- double max, std::vector const &energy,
- std::vector const &force) {
- auto data = get_ia_param_safe(part_type_a, part_type_b);
- assert(max >= min);
- assert((max == min) || force.size() > 1);
- assert(force.size() == energy.size());
-
- data->tab.maxval = max;
- data->tab.minval = min;
- if (max == min)
- data->tab.invstepsize = 0;
- else
- data->tab.invstepsize = static_cast(force.size() - 1) / (max - min);
-
- data->tab.force_tab = force;
- data->tab.energy_tab = energy;
-
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
-}
-
-#endif
diff --git a/src/core/nonbonded_interactions/nonbonded_tab.hpp b/src/core/nonbonded_interactions/nonbonded_tab.hpp
index 85385b1ca05..fa4de64d6ea 100644
--- a/src/core/nonbonded_interactions/nonbonded_tab.hpp
+++ b/src/core/nonbonded_interactions/nonbonded_tab.hpp
@@ -25,7 +25,6 @@
* Routines to calculate the energy and/or force for particle pairs via
* interpolation of lookup tables.
*
- * Implementation in \ref nonbonded_tab.cpp.
* Needs feature TABULATED compiled in (see \ref config.hpp).
*/
@@ -40,21 +39,6 @@
#include
-/** Set the parameters of a non-bonded tabulated potential.
- * ia_params and force/energy tables are communicated to each node
- *
- * @param part_type_a particle type for which the interaction is defined
- * @param part_type_b particle type for which the interaction is defined
- * @param min @copybrief TabulatedPotential::minval
- * @param max @copybrief TabulatedPotential::maxval
- * @param energy @copybrief TabulatedPotential::energy_tab
- * @param force @copybrief TabulatedPotential::force_tab
- * @retval ES_OK
- */
-int tabulated_set_params(int part_type_a, int part_type_b, double min,
- double max, std::vector const &energy,
- std::vector const &force);
-
/** Calculate a non-bonded pair force factor by linear interpolation from a
* table.
*/
@@ -75,6 +59,5 @@ inline double tabulated_pair_energy(IA_parameters const &ia_params,
return 0.0;
}
-#endif
-
+#endif // TABULATED
#endif
diff --git a/src/core/nonbonded_interactions/smooth_step.cpp b/src/core/nonbonded_interactions/smooth_step.cpp
index 34996d91776..6c1b9ee7f93 100644
--- a/src/core/nonbonded_interactions/smooth_step.cpp
+++ b/src/core/nonbonded_interactions/smooth_step.cpp
@@ -25,29 +25,23 @@
#include "smooth_step.hpp"
#ifdef SMOOTH_STEP
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
-int smooth_step_set_params(int part_type_a, int part_type_b, double d, int n,
- double eps, double k0, double sig, double cut) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->smooth_step.eps = eps;
- data->smooth_step.sig = sig;
- data->smooth_step.cut = cut;
- data->smooth_step.d = d;
- data->smooth_step.n = n;
- data->smooth_step.k0 = k0;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+
+SmoothStep_Parameters::SmoothStep_Parameters(double eps, double sig,
+ double cutoff, double d, int n,
+ double k0)
+ : eps{eps}, sig{sig}, cut{cutoff}, d{d}, n{n}, k0{k0} {
+ if (eps < 0.) {
+ throw std::domain_error("SmoothStep parameter 'eps' has to be >= 0");
+ }
+ if (sig < 0.) {
+ throw std::domain_error("SmoothStep parameter 'sig' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("SmoothStep parameter 'cutoff' has to be >= 0");
+ }
}
-#endif
+#endif // SMOOTH_STEP
diff --git a/src/core/nonbonded_interactions/smooth_step.hpp b/src/core/nonbonded_interactions/smooth_step.hpp
index 926be66665f..7789ba48bb4 100644
--- a/src/core/nonbonded_interactions/smooth_step.hpp
+++ b/src/core/nonbonded_interactions/smooth_step.hpp
@@ -38,9 +38,6 @@
#include
-int smooth_step_set_params(int part_type_a, int part_type_b, double d, int n,
- double eps, double k0, double sig, double cut);
-
/** Calculate smooth step force factor */
inline double SmSt_pair_force_factor(IA_parameters const &ia_params,
double dist) {
diff --git a/src/core/nonbonded_interactions/soft_sphere.cpp b/src/core/nonbonded_interactions/soft_sphere.cpp
index ffc13dc9ad6..84812c1f4f0 100644
--- a/src/core/nonbonded_interactions/soft_sphere.cpp
+++ b/src/core/nonbonded_interactions/soft_sphere.cpp
@@ -26,27 +26,22 @@
#include "soft_sphere.hpp"
#ifdef SOFT_SPHERE
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
-int soft_sphere_set_params(int part_type_a, int part_type_b, double a, double n,
- double cut, double offset) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->soft_sphere.a = a;
- data->soft_sphere.n = n;
- data->soft_sphere.cut = cut;
- data->soft_sphere.offset = offset;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+
+SoftSphere_Parameters::SoftSphere_Parameters(double a, double n, double cutoff,
+ double offset)
+ : a{a}, n{n}, cut{cutoff}, offset{offset} {
+ if (a < 0.) {
+ throw std::domain_error("SoftSphere parameter 'a' has to be >= 0");
+ }
+ if (cutoff < 0.) {
+ throw std::domain_error("SoftSphere parameter 'cutoff' has to be >= 0");
+ }
+ if (offset < 0.) {
+ throw std::domain_error("SoftSphere parameter 'offset' has to be >= 0");
+ }
}
-#endif
+#endif // SOFT_SPHERE
diff --git a/src/core/nonbonded_interactions/soft_sphere.hpp b/src/core/nonbonded_interactions/soft_sphere.hpp
index 5a6d8a9291c..09f00aba466 100644
--- a/src/core/nonbonded_interactions/soft_sphere.hpp
+++ b/src/core/nonbonded_interactions/soft_sphere.hpp
@@ -33,17 +33,12 @@
#include "nonbonded_interaction_data.hpp"
-#include
-
#include
-int soft_sphere_set_params(int part_type_a, int part_type_b, double a, double n,
- double cut, double offset);
-
/** Calculate soft-sphere force factor */
inline double soft_pair_force_factor(IA_parameters const &ia_params,
double dist) {
- if (dist < (ia_params.soft_sphere.cut + ia_params.soft_sphere.offset)) {
+ if (dist < ia_params.soft_sphere.max_cutoff()) {
/* normal case: resulting force/energy smaller than zero. */
auto const r_off = dist - ia_params.soft_sphere.offset;
if (r_off > 0.0) {
@@ -56,7 +51,7 @@ inline double soft_pair_force_factor(IA_parameters const &ia_params,
/** Calculate soft-sphere energy */
inline double soft_pair_energy(IA_parameters const &ia_params, double dist) {
- if (dist < (ia_params.soft_sphere.cut + ia_params.soft_sphere.offset)) {
+ if (dist < ia_params.soft_sphere.max_cutoff()) {
auto const r_off = dist - ia_params.soft_sphere.offset;
/* normal case: resulting force/energy smaller than zero. */
return ia_params.soft_sphere.a / std::pow(r_off, ia_params.soft_sphere.n);
@@ -64,5 +59,5 @@ inline double soft_pair_energy(IA_parameters const &ia_params, double dist) {
return 0.0;
}
-#endif /* ifdef SOFT_SPHERE */
+#endif // SOFT_SPHERE
#endif
diff --git a/src/core/nonbonded_interactions/thole.cpp b/src/core/nonbonded_interactions/thole.cpp
deleted file mode 100644
index fb750a9ac51..00000000000
--- a/src/core/nonbonded_interactions/thole.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2010-2022 The ESPResSo project
- * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
- * Max-Planck-Institute for Polymer Research, Theory Group
- *
- * This file is part of ESPResSo.
- *
- * ESPResSo is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * ESPResSo is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-/** \file
- *
- * Implementation of \ref thole.hpp
- */
-#include "thole.hpp"
-
-#ifdef THOLE
-#include "interactions.hpp"
-
-#include
-
-int thole_set_params(int part_type_a, int part_type_b, double scaling_coeff,
- double q1q2) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- if (!data)
- return ES_ERROR;
-
- data->thole.scaling_coeff = scaling_coeff;
- data->thole.q1q2 = q1q2;
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
-}
-#endif
diff --git a/src/core/nonbonded_interactions/thole.hpp b/src/core/nonbonded_interactions/thole.hpp
index 4865850aeb4..2d41c57c298 100644
--- a/src/core/nonbonded_interactions/thole.hpp
+++ b/src/core/nonbonded_interactions/thole.hpp
@@ -23,8 +23,6 @@
/** \file
* Routines to calculate the Thole damping potential between particle pairs.
* See @cite thole81a.
- *
- * Implementation in \ref thole.cpp.
*/
#include "config/config.hpp"
@@ -41,9 +39,6 @@
#include
-int thole_set_params(int part_type_a, int part_type_b, double scaling_coeff,
- double q1q2);
-
/** Calculate Thole force */
inline Utils::Vector3d
thole_pair_force(Particle const &p1, Particle const &p2,
diff --git a/src/core/nonbonded_interactions/wca.cpp b/src/core/nonbonded_interactions/wca.cpp
index 29a4a2d14dd..4de3020b2ed 100644
--- a/src/core/nonbonded_interactions/wca.cpp
+++ b/src/core/nonbonded_interactions/wca.cpp
@@ -23,24 +23,22 @@
#include "wca.hpp"
#ifdef WCA
-#include "interactions.hpp"
#include "nonbonded_interaction_data.hpp"
-#include
-
#include
-
-int wca_set_params(int part_type_a, int part_type_b, double eps, double sig) {
- IA_parameters *data = get_ia_param_safe(part_type_a, part_type_b);
-
- data->wca.eps = eps;
- data->wca.sig = sig;
- data->wca.cut = sig * std::pow(2., 1. / 6.);
-
- /* broadcast interaction parameters */
- mpi_bcast_ia_params(part_type_a, part_type_b);
-
- return ES_OK;
+#include
+
+WCA_Parameters::WCA_Parameters(double epsilon, double sigma)
+ : eps{epsilon}, sig{sigma} {
+ if (epsilon < 0.) {
+ throw std::domain_error("WCA parameter 'epsilon' has to be >= 0");
+ }
+ if (sigma < 0.) {
+ throw std::domain_error("WCA parameter 'sigma' has to be >= 0");
+ }
+ if (sigma != 0.) {
+ cut = sigma * std::pow(2., 1. / 6.);
+ }
}
#endif /* ifdef WCA */
diff --git a/src/core/nonbonded_interactions/wca.hpp b/src/core/nonbonded_interactions/wca.hpp
index 55ff743e0bd..d1209dfda01 100644
--- a/src/core/nonbonded_interactions/wca.hpp
+++ b/src/core/nonbonded_interactions/wca.hpp
@@ -35,8 +35,6 @@
#include
#include
-int wca_set_params(int part_type_a, int part_type_b, double eps, double sig);
-
/** Calculate WCA force factor */
inline double wca_pair_force_factor(IA_parameters const &ia_params,
double dist) {
diff --git a/src/core/serialization/IA_parameters.hpp b/src/core/serialization/IA_parameters.hpp
deleted file mode 100644
index e56e8c1c03a..00000000000
--- a/src/core/serialization/IA_parameters.hpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2010-2022 The ESPResSo project
- *
- * This file is part of ESPResSo.
- *
- * ESPResSo is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * ESPResSo is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-#ifndef SERIALIZATION_IA_PARAMETERS_HPP
-#define SERIALIZATION_IA_PARAMETERS_HPP
-
-#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
-
-namespace boost {
-namespace serialization {
-template
-void load(Archive &ar, IA_parameters &p,
- const unsigned int /* file_version */) {
- ar >> make_array(reinterpret_cast(&p), sizeof(IA_parameters));
-
-#ifdef TABULATED
- TabulatedPotential tab;
- ar >> tab;
-
- new (&(p.tab)) TabulatedPotential(std::move(tab));
-#endif
-}
-
-template
-void save(Archive &ar, IA_parameters const &p,
- const unsigned int /* file_version */) {
- ar << make_array(reinterpret_cast(&p), sizeof(IA_parameters));
-
-#ifdef TABULATED
- ar << p.tab;
-#endif
-}
-
-template
-void serialize(Archive &ar, IA_parameters &p, const unsigned int file_version) {
- split_free(ar, p, file_version);
-}
-} // namespace serialization
-} // namespace boost
-
-#endif
diff --git a/src/core/unit_tests/EspressoSystemStandAlone_test.cpp b/src/core/unit_tests/EspressoSystemStandAlone_test.cpp
index 0366ac86be9..617918717a3 100644
--- a/src/core/unit_tests/EspressoSystemStandAlone_test.cpp
+++ b/src/core/unit_tests/EspressoSystemStandAlone_test.cpp
@@ -37,6 +37,7 @@ namespace utf = boost::unit_test;
#include "electrostatics/p3m.hpp"
#include "electrostatics/registration.hpp"
#include "energy.hpp"
+#include "event.hpp"
#include "galilei/Galilei.hpp"
#include "integrate.hpp"
#include "nonbonded_interactions/lj.hpp"
@@ -130,6 +131,17 @@ static void mpi_set_tuned_p3m(double prefactor) {
}
#endif // P3M
+#ifdef LENNARD_JONES
+void mpi_set_lj_local(int key, double eps, double sig, double cut,
+ double offset, double min, double shift) {
+ LJ_Parameters lj{eps, sig, cut, offset, min, shift};
+ ::nonbonded_ia_params[key]->lj = lj;
+ on_non_bonded_ia_change();
+}
+
+REGISTER_CALLBACK(mpi_set_lj_local)
+#endif // LENNARD_JONES
+
BOOST_FIXTURE_TEST_CASE(espresso_system_stand_alone, ParticleFactory,
*utf::precondition(if_head_node())) {
constexpr auto tol = 100. * std::numeric_limits::epsilon();
@@ -223,9 +235,12 @@ BOOST_FIXTURE_TEST_CASE(espresso_system_stand_alone, ParticleFactory,
auto const offset = 0.1;
auto const min = 0.0;
auto const r_off = dist - offset;
- auto const cut = r_off + 1e-3; // LJ for only 2 pairs: AA BB
- lennard_jones_set_params(type_a, type_b, eps, sig, cut, shift, offset, min);
- lennard_jones_set_params(type_b, type_b, eps, sig, cut, shift, offset, min);
+ auto const cut = r_off + 1e-3; // LJ for only 2 pairs: AB BB
+ make_particle_type_exist(std::max(type_a, type_b));
+ auto const key_ab = get_ia_param_key(type_a, type_b);
+ auto const key_bb = get_ia_param_key(type_b, type_b);
+ mpi_call_all(mpi_set_lj_local, key_ab, eps, sig, cut, offset, min, shift);
+ mpi_call_all(mpi_set_lj_local, key_bb, eps, sig, cut, offset, min, shift);
// matrix indices and reference energy value
auto const max_type = type_b + 1;
diff --git a/src/core/unit_tests/Verlet_list_test.cpp b/src/core/unit_tests/Verlet_list_test.cpp
index 3edecd75d15..6005db3c1f0 100644
--- a/src/core/unit_tests/Verlet_list_test.cpp
+++ b/src/core/unit_tests/Verlet_list_test.cpp
@@ -37,6 +37,7 @@ namespace bdata = boost::unit_test::data;
#include "Particle.hpp"
#include "ParticleFactory.hpp"
#include "communication.hpp"
+#include "event.hpp"
#include "integrate.hpp"
#include "integrators/steepest_descent.hpp"
#include "nonbonded_interactions/lj.hpp"
@@ -145,8 +146,18 @@ struct : public IntegratorHelper {
char const *name() const override { return "VelocityVerletNpT"; }
} velocity_verlet_npt;
#endif // NPT
+
} // namespace Testing
+void mpi_set_lj_local(int key, double eps, double sig, double cut,
+ double offset, double min, double shift) {
+ LJ_Parameters lj{eps, sig, cut, offset, min, shift};
+ ::nonbonded_ia_params[key]->lj = lj;
+ on_non_bonded_ia_change();
+}
+
+REGISTER_CALLBACK(mpi_set_lj_local)
+
inline double get_dist_from_last_verlet_update(Particle const &p) {
return (p.pos() - p.pos_at_last_verlet_update()).norm();
}
@@ -193,7 +204,9 @@ BOOST_DATA_TEST_CASE_F(ParticleFactory, verlet_list_update,
auto const min = 0.0;
auto const r_off = dist - offset;
auto const cut = r_off + 1e-3;
- lennard_jones_set_params(0, 1, eps, sig, cut, shift, offset, min);
+ make_particle_type_exist(1);
+ auto const key = get_ia_param_key(0, 1);
+ mpi_call_all(mpi_set_lj_local, key, eps, sig, cut, offset, min, shift);
// set up velocity-Verlet integrator
auto const time_step = 0.01;
diff --git a/src/python/espressomd/interactions.pxd b/src/python/espressomd/interactions.pxd
deleted file mode 100644
index 009dc267158..00000000000
--- a/src/python/espressomd/interactions.pxd
+++ /dev/null
@@ -1,343 +0,0 @@
-#
-# Copyright (C) 2013-2022 The ESPResSo project
-#
-# This file is part of ESPResSo.
-#
-# ESPResSo is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ESPResSo is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-
-# Handling of interactions
-
-from libcpp.string cimport string
-from libcpp.vector cimport vector
-from libc cimport stdint
-
-from .thermostat cimport thermalized_bond
-
-include "myconfig.pxi"
-
-# force include of config.hpp
-cdef extern from "config/config.hpp":
- pass
-
-cdef extern from "TabulatedPotential.hpp":
- struct TabulatedPotential:
- double maxval
- double minval
- vector[double] energy_tab
- vector[double] force_tab
-
-cdef extern from "nonbonded_interactions/nonbonded_interaction_data.hpp":
- cdef struct LJ_Parameters:
- double eps
- double sig
- double cut
- double shift
- double offset
- double min
-
- cdef struct WCA_Parameters:
- double eps
- double sig
- double cut
-
- cdef struct LJGen_Parameters:
- double eps
- double sig
- double cut
- double shift
- double offset
- double a1
- double a2
- double b1
- double b2
- double lambda1
- double softrad
-
- cdef struct SmoothStep_Parameters:
- double eps
- double sig
- double cut
- double d
- int n
- double k0
-
- cdef struct Hertzian_Parameters:
- double eps
- double sig
-
- cdef struct Gaussian_Parameters:
- double eps
- double sig
- double cut
-
- cdef struct BMHTF_Parameters:
- double A
- double B
- double C
- double D
- double sig
- double cut
- double computed_shift
-
- cdef struct Morse_Parameters:
- double eps
- double alpha
- double rmin
- double cut
- double rest
-
- cdef struct Buckingham_Parameters:
- double A
- double B
- double C
- double D
- double cut
- double discont
- double shift
- double F1
- double F2
-
- cdef struct SoftSphere_Parameters:
- double a
- double n
- double cut
- double offset
-
- cdef struct Hat_Parameters:
- double Fmax
- double r
-
- cdef struct LJcos_Parameters:
- double eps
- double sig
- double cut
- double offset
-
- cdef struct LJcos2_Parameters:
- double eps
- double sig
- double offset
- double w
-
- cdef struct GayBerne_Parameters:
- double eps
- double sig
- double cut
- double k1
- double k2
- double mu
- double nu
-
- cdef struct Thole_Parameters:
- double scaling_coeff
- double q1q2
-
- cdef struct DPDParameters:
- double gamma
- double k
- double cutoff
- int wf
- double pref
-
- cdef struct IA_parameters:
- LJ_Parameters lj
-
- WCA_Parameters wca
-
- LJcos_Parameters ljcos
-
- LJcos2_Parameters ljcos2
-
- LJGen_Parameters ljgen
-
- SoftSphere_Parameters soft_sphere
-
- TabulatedPotential tab
-
- GayBerne_Parameters gay_berne
-
- SmoothStep_Parameters smooth_step
-
- BMHTF_Parameters bmhtf
-
- Morse_Parameters morse
-
- Buckingham_Parameters buckingham
-
- Hertzian_Parameters hertzian
-
- Gaussian_Parameters gaussian
-
- DPDParameters dpd_radial
- DPDParameters dpd_trans
-
- Hat_Parameters hat
-
- Thole_Parameters thole
-
- cdef IA_parameters * get_ia_param_safe(int i, int j)
- cdef string ia_params_get_state()
- cdef void ia_params_set_state(string)
- cdef void reset_ia_params()
-
-IF LENNARD_JONES:
- cdef extern from "nonbonded_interactions/lj.hpp":
- cdef int lennard_jones_set_params(int part_type_a, int part_type_b,
- double eps, double sig, double cut,
- double shift, double offset,
- double min)
-
-IF WCA:
- cdef extern from "nonbonded_interactions/wca.hpp":
- cdef int wca_set_params(int part_type_a, int part_type_b,
- double eps, double sig)
-
-IF LJCOS:
- cdef extern from "nonbonded_interactions/ljcos.hpp":
- cdef int ljcos_set_params(int part_type_a, int part_type_b,
- double eps, double sig,
- double cut, double offset)
-
-IF LJCOS2:
- cdef extern from "nonbonded_interactions/ljcos2.hpp":
- cdef int ljcos2_set_params(int part_type_a, int part_type_b,
- double eps, double sig, double offset,
- double w)
-
-IF GAY_BERNE:
- cdef extern from "nonbonded_interactions/gay_berne.hpp":
- int gay_berne_set_params(int part_type_a, int part_type_b,
- double eps, double sig, double cut,
- double k1, double k2,
- double mu, double nu)
-
-IF THOLE:
- cdef extern from "nonbonded_interactions/thole.hpp":
- int thole_set_params(int part_type_a, int part_type_b, double scaling_coeff, double q1q2)
-
-IF LENNARD_JONES_GENERIC:
- cdef extern from "nonbonded_interactions/ljgen.hpp":
- IF LJGEN_SOFTCORE:
- cdef int ljgen_set_params(int part_type_a, int part_type_b,
- double eps, double sig, double cut,
- double shift, double offset,
- double a1, double a2, double b1, double b2,
- double genlj_lambda, double softrad)
- ELSE:
- cdef int ljgen_set_params(int part_type_a, int part_type_b,
- double eps, double sig, double cut,
- double shift, double offset,
- double a1, double a2, double b1, double b2)
-
-IF SMOOTH_STEP:
- cdef extern from "nonbonded_interactions/smooth_step.hpp":
- int smooth_step_set_params(int part_type_a, int part_type_b,
- double d, int n, double eps,
- double k0, double sig,
- double cut)
-IF BMHTF_NACL:
- cdef extern from "nonbonded_interactions/bmhtf-nacl.hpp":
- int BMHTF_set_params(int part_type_a, int part_type_b,
- double A, double B, double C,
- double D, double sig, double cut)
-
-IF MORSE:
- cdef extern from "nonbonded_interactions/morse.hpp":
- int morse_set_params(int part_type_a, int part_type_b,
- double eps, double alpha,
- double rmin, double cut)
-
-IF BUCKINGHAM:
- cdef extern from "nonbonded_interactions/buckingham.hpp":
- int buckingham_set_params(int part_type_a, int part_type_b,
- double A, double B, double C, double D, double cut,
- double discont, double shift)
-
-IF SOFT_SPHERE:
- cdef extern from "nonbonded_interactions/soft_sphere.hpp":
- int soft_sphere_set_params(int part_type_a, int part_type_b,
- double a, double n, double cut, double offset)
-
-IF HERTZIAN:
- cdef extern from "nonbonded_interactions/hertzian.hpp":
- int hertzian_set_params(int part_type_a, int part_type_b,
- double eps, double sig)
-
-IF GAUSSIAN:
- cdef extern from "nonbonded_interactions/gaussian.hpp":
- int gaussian_set_params(int part_type_a, int part_type_b,
- double eps, double sig, double cut)
-
-IF DPD:
- cdef extern from "dpd.hpp":
- int dpd_set_params(int part_type_a, int part_type_b,
- double gamma, double k, double r_c, int wf,
- double tgamma, double tr_c, int twf)
-
-IF HAT:
- cdef extern from "nonbonded_interactions/hat.hpp":
- int hat_set_params(int part_type_a, int part_type_b,
- double Fmax, double r)
-
-IF SOFT_SPHERE:
- cdef extern from "nonbonded_interactions/soft_sphere.hpp":
- cdef int soft_sphere_set_params(int part_type_a, int part_type_b,
- double a, double n,
- double cut, double offset)
-
-IF TABULATED:
- cdef extern from "nonbonded_interactions/nonbonded_tab.hpp":
- int tabulated_set_params(int part_type_a, int part_type_b,
- double min, double max,
- vector[double] energy,
- vector[double] force)
-
-cdef extern from "script_interface/interactions/bonded.hpp":
- int bonded_ia_params_zero_based_type(int bond_id) except +
-
-# Map the boost::variant type indices to python type identifiers. These enum
-# values must be in the same order as in the definition of the boost::variant.
-cdef enum enum_bonded_interaction:
- BONDED_IA_NONE = 0,
- BONDED_IA_FENE,
- BONDED_IA_HARMONIC,
- BONDED_IA_QUARTIC,
- BONDED_IA_BONDED_COULOMB,
- BONDED_IA_BONDED_COULOMB_SR,
- BONDED_IA_ANGLE_HARMONIC,
- BONDED_IA_ANGLE_COSINE,
- BONDED_IA_ANGLE_COSSQUARE,
- BONDED_IA_DIHEDRAL,
- BONDED_IA_TABULATED_DISTANCE,
- BONDED_IA_TABULATED_ANGLE,
- BONDED_IA_TABULATED_DIHEDRAL,
- BONDED_IA_THERMALIZED_DIST,
- BONDED_IA_RIGID_BOND,
- BONDED_IA_IBM_TRIEL,
- BONDED_IA_IBM_VOLUME_CONSERVATION,
- BONDED_IA_IBM_TRIBEND,
- BONDED_IA_OIF_GLOBAL_FORCES,
- BONDED_IA_OIF_LOCAL_FORCES,
- BONDED_IA_VIRTUAL_BOND
-
-cdef extern from "thermostat.hpp":
- void thermalized_bond_set_rng_counter(stdint.uint64_t counter)
-
-cdef extern from "immersed_boundary/ImmersedBoundaries.hpp":
- cppclass ImmersedBoundaries:
- double get_current_volume(int softID)
-
-cdef extern from "immersed_boundaries.hpp":
- extern ImmersedBoundaries immersed_boundaries
diff --git a/src/python/espressomd/interactions.py b/src/python/espressomd/interactions.py
new file mode 100644
index 00000000000..7ffe575bd62
--- /dev/null
+++ b/src/python/espressomd/interactions.py
@@ -0,0 +1,1627 @@
+#
+# Copyright (C) 2013-2022 The ESPResSo project
+#
+# This file is part of ESPResSo.
+#
+# ESPResSo is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# ESPResSo is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+import abc
+import enum
+from . import utils
+from . import code_features
+from .script_interface import ScriptObjectMap, ScriptInterfaceHelper, script_interface_register
+
+
+class NonBondedInteraction(ScriptInterfaceHelper, metaclass=abc.ABCMeta):
+ """
+ Represents an instance of a non-bonded interaction, such as Lennard-Jones.
+
+ Methods
+ -------
+ deactivate()
+ Reset parameters for the interaction.
+
+ """
+ _so_bind_methods = ("deactivate",)
+
+ def __init__(self, **kwargs):
+ code_features.assert_features(self.__class__.__dict__["_so_feature"])
+ if "sip" in kwargs:
+ super().__init__(**kwargs)
+ else:
+ params = self.default_params()
+ params.update(kwargs)
+ super().__init__(**params)
+
+ def __str__(self):
+ return f'{self.__class__.__name__}({self.get_params()})'
+
+ def set_params(self, **kwargs):
+ """Set new parameters.
+
+ """
+ params = self.default_params()
+ params.update(kwargs)
+
+ err_msg = f"setting {self.__class__.__name__} raised an error"
+ self.call_method("set_params", handle_errors_message=err_msg, **params)
+
+ def __reduce__(self):
+ return (NonBondedInteraction._restore_object,
+ (self.__class__, self.get_params()))
+
+ @classmethod
+ def _restore_object(cls, derived_class, kwargs):
+ return derived_class(**kwargs)
+
+ @abc.abstractmethod
+ def default_params(self):
+ pass
+
+
+@script_interface_register
+class LennardJonesInteraction(NonBondedInteraction):
+ """
+ Standard 6-12 Lennard-Jones potential.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ epsilon : :obj:`float`
+ Magnitude of the interaction.
+ sigma : :obj:`float`
+ Interaction length scale.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+ shift : :obj:`float` or :obj:`str` \{'auto'\}
+ Constant shift of the potential. If ``'auto'``, a default value
+ is computed from ``sigma`` and ``cutoff``. The LJ potential
+ will be shifted by :math:`4\\epsilon\\cdot\\text{shift}`.
+ offset : :obj:`float`, optional
+ Offset distance of the interaction.
+ min : :obj:`float`, optional
+ Restricts the interaction to a minimal distance.
+
+ """
+
+ _so_name = "Interactions::InteractionLJ"
+ _so_feature = "LENNARD_JONES"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"offset": 0., "min": 0.}
+
+
+@script_interface_register
+class WCAInteraction(NonBondedInteraction):
+ """
+ Standard 6-12 Weeks-Chandler-Andersen potential.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ epsilon : :obj:`float`
+ Magnitude of the interaction.
+ sigma : :obj:`float`
+ Interaction length scale.
+
+ """
+
+ _so_name = "Interactions::InteractionWCA"
+ _so_feature = "WCA"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {}
+
+ @property
+ def cutoff(self):
+ return self.call_method("get_cutoff")
+
+
+@script_interface_register
+class GenericLennardJonesInteraction(NonBondedInteraction):
+ """
+ Generalized Lennard-Jones potential.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ epsilon : :obj:`float`
+ Magnitude of the interaction.
+ sigma : :obj:`float`
+ Interaction length scale.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+ shift : :obj:`float` or :obj:`str` \{'auto'\}
+ Constant shift of the potential. If ``'auto'``, a default value
+ is computed from the other parameters. The LJ potential
+ will be shifted by :math:`\\epsilon\\cdot\\text{shift}`.
+ offset : :obj:`float`
+ Offset distance of the interaction.
+ e1 : :obj:`int`
+ Exponent of the repulsion term.
+ e2 : :obj:`int`
+ Exponent of the attraction term.
+ b1 : :obj:`float`
+ Prefactor of the repulsion term.
+ b2 : :obj:`float`
+ Prefactor of the attraction term.
+ delta : :obj:`float`, optional
+ ``LJGEN_SOFTCORE`` parameter delta. Allows control over how
+ smoothly the potential drops to zero as lambda approaches zero.
+ lam : :obj:`float`, optional
+ ``LJGEN_SOFTCORE`` parameter lambda. Tune the strength of the
+ interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionLJGen"
+ _so_feature = "LENNARD_JONES_GENERIC"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ if code_features.has_features("LJGEN_SOFTCORE"):
+ return {"delta": 0., "lam": 1.}
+ return {}
+
+
+@script_interface_register
+class LennardJonesCosInteraction(NonBondedInteraction):
+ """Lennard-Jones cosine interaction.
+
+ Methods
+ -------
+ set_params()
+ Set or update parameters for the interaction.
+ Parameters marked as required become optional once the
+ interaction has been activated for the first time;
+ subsequent calls to this method update the existing values.
+
+ Parameters
+ ----------
+ epsilon : :obj:`float`
+ Magnitude of the interaction.
+ sigma : :obj:`float`
+ Interaction length scale.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+ offset : :obj:`float`, optional
+ Offset distance of the interaction.
+ """
+
+ _so_name = "Interactions::InteractionLJcos"
+ _so_feature = "LJCOS"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"offset": 0.}
+
+
+@script_interface_register
+class LennardJonesCos2Interaction(NonBondedInteraction):
+ """Second variant of the Lennard-Jones cosine interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ epsilon : :obj:`float`
+ Magnitude of the interaction.
+ sigma : :obj:`float`
+ Interaction length scale.
+ offset : :obj:`float`, optional
+ Offset distance of the interaction.
+ width : :obj:`float`
+ Width of interaction.
+ """
+
+ _so_name = "Interactions::InteractionLJcos2"
+ _so_feature = "LJCOS2"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"offset": 0.}
+
+ @property
+ def cutoff(self):
+ return self.call_method("get_cutoff")
+
+
+@script_interface_register
+class HatInteraction(NonBondedInteraction):
+ """Hat interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ F_max : :obj:`float`
+ Magnitude of the interaction.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionHat"
+ _so_feature = "HAT"
+
+ def default_params(self):
+ return {}
+
+
+@script_interface_register
+class GayBerneInteraction(NonBondedInteraction):
+ """Gay--Berne interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ eps : :obj:`float`
+ Potential well depth.
+ sig : :obj:`float`
+ Interaction range.
+ cut : :obj:`float`
+ Cutoff distance of the interaction.
+ k1 : :obj:`float` or :obj:`str`
+ Molecular elongation.
+ k2 : :obj:`float`, optional
+ Ratio of the potential well depths for the side-by-side
+ and end-to-end configurations.
+ mu : :obj:`float`, optional
+ Adjustable exponent.
+ nu : :obj:`float`, optional
+ Adjustable exponent.
+
+ """
+
+ _so_name = "Interactions::InteractionGayBerne"
+ _so_feature = "GAY_BERNE"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class TabulatedNonBonded(NonBondedInteraction):
+ """Tabulated interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ min : :obj:`float`,
+ The minimal interaction distance.
+ max : :obj:`float`,
+ The maximal interaction distance.
+ energy: array_like of :obj:`float`
+ The energy table.
+ force: array_like of :obj:`float`
+ The force table.
+
+ """
+
+ _so_name = "Interactions::InteractionTabulated"
+ _so_feature = "TABULATED"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {}
+
+ @property
+ def cutoff(self):
+ return self.call_method("get_cutoff")
+
+
+@script_interface_register
+class DPDInteraction(NonBondedInteraction):
+ """DPD interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ weight_function : :obj:`int`, \{0, 1\}
+ The distance dependence of the parallel part,
+ either 0 (constant) or 1 (linear)
+ gamma : :obj:`float`
+ Friction coefficient of the parallel part
+ k : :obj:`float`
+ Exponent in the modified weight function
+ r_cut : :obj:`float`
+ Cutoff of the parallel part
+ trans_weight_function : :obj:`int`, \{0, 1\}
+ The distance dependence of the orthogonal part,
+ either 0 (constant) or 1 (linear)
+ trans_gamma : :obj:`float`
+ Friction coefficient of the orthogonal part
+ trans_r_cut : :obj:`float`
+ Cutoff of the orthogonal part
+
+ """
+
+ _so_name = "Interactions::InteractionDPD"
+ _so_feature = "DPD"
+
+ def default_params(self):
+ return {
+ "weight_function": 0,
+ "gamma": 0.0,
+ "k": 1.0,
+ "r_cut": -1.0,
+ "trans_weight_function": 0,
+ "trans_gamma": 0.0,
+ "trans_r_cut": -1.0}
+
+
+@script_interface_register
+class SmoothStepInteraction(NonBondedInteraction):
+ """Smooth step interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ d : :obj:`float`
+ Short range repulsion parameter.
+ n : :obj:`int`, optional
+ Exponent of short range repulsion.
+ eps : :obj:`float`
+ Magnitude of the second (soft) repulsion.
+ k0 : :obj:`float`, optional
+ Exponential factor in second (soft) repulsion.
+ sig : :obj:`float`, optional
+ Length scale of second (soft) repulsion.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionSmoothStep"
+ _so_feature = "SMOOTH_STEP"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"n": 10, "k0": 0., "sig": 0.}
+
+
+@script_interface_register
+class BMHTFInteraction(NonBondedInteraction):
+ """BMHTF interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ a : :obj:`float`
+ Magnitude of exponential part of the interaction.
+ b : :obj:`float`
+ Exponential factor of the interaction.
+ c : :obj:`float`
+ Magnitude of the term decaying with the sixth power of r.
+ d : :obj:`float`
+ Magnitude of the term decaying with the eighth power of r.
+ sig : :obj:`float`
+ Shift in the exponent.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionBMHTF"
+ _so_feature = "BMHTF_NACL"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class MorseInteraction(NonBondedInteraction):
+ """Morse interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ eps : :obj:`float`
+ The magnitude of the interaction.
+ alpha : :obj:`float`
+ Stiffness of the Morse interaction.
+ rmin : :obj:`float`
+ Distance of potential minimum
+ cutoff : :obj:`float`, optional
+ Cutoff distance of the interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionMorse"
+ _so_feature = "MORSE"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"cutoff": 0.}
+
+
+@script_interface_register
+class BuckinghamInteraction(NonBondedInteraction):
+ """Buckingham interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ a : :obj:`float`
+ Magnitude of the exponential part of the interaction.
+ b : :obj:`float`, optional
+ Exponent of the exponential part of the interaction.
+ c : :obj:`float`
+ Prefactor of term decaying with the sixth power of distance.
+ d : :obj:`float`
+ Prefactor of term decaying with the fourth power of distance.
+ discont : :obj:`float`
+ Distance below which the potential is linearly continued.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+ shift: :obj:`float`, optional
+ Constant potential shift.
+
+ """
+
+ _so_name = "Interactions::InteractionBuckingham"
+ _so_feature = "BUCKINGHAM"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"b": 0., "shift": 0.}
+
+
+@script_interface_register
+class SoftSphereInteraction(NonBondedInteraction):
+ """Soft sphere interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ a : :obj:`float`
+ Magnitude of the interaction.
+ n : :obj:`float`
+ Exponent of the power law.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+ offset : :obj:`float`, optional
+ Offset distance of the interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionSoftSphere"
+ _so_feature = "SOFT_SPHERE"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {"offset": 0.}
+
+
+@script_interface_register
+class HertzianInteraction(NonBondedInteraction):
+ """Hertzian interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ eps : :obj:`float`
+ Magnitude of the interaction.
+ sig : :obj:`float`
+ Interaction length scale.
+
+ """
+
+ _so_name = "Interactions::InteractionHertzian"
+ _so_feature = "HERTZIAN"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class GaussianInteraction(NonBondedInteraction):
+ """Gaussian interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ eps : :obj:`float`
+ Overlap energy epsilon.
+ sig : :obj:`float`
+ Variance sigma of the Gaussian interaction.
+ cutoff : :obj:`float`
+ Cutoff distance of the interaction.
+
+ """
+
+ _so_name = "Interactions::InteractionGaussian"
+ _so_feature = "GAUSSIAN"
+
+ def default_params(self):
+ """Python dictionary of default parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class TholeInteraction(NonBondedInteraction):
+ """Thole interaction.
+
+ Methods
+ -------
+ set_params()
+ Set new parameters for the interaction.
+
+ Parameters
+ ----------
+ scaling_coeff : :obj:`float`
+ The factor used in the Thole damping function between
+ polarizable particles i and j. Usually calculated by
+ the polarizabilities :math:`\\alpha_i`, :math:`\\alpha_j`
+ and damping parameters :math:`a_i`, :math:`a_j` via
+ :math:`s_{ij} = \\frac{(a_i+a_j)/2}{((\\alpha_i\\cdot\\alpha_j)^{1/2})^{1/3}}`
+ q1q2: :obj:`float`
+ Charge factor of the involved charges. Has to be set because
+ it acts only on the portion of the Drude core charge that is
+ associated to the dipole of the atom. For charged, polarizable
+ atoms that charge is not equal to the particle charge property.
+
+ """
+
+ _so_name = "Interactions::InteractionThole"
+ _so_feature = "THOLE"
+
+ def default_params(self):
+ return {}
+
+
+@script_interface_register
+class NonBondedInteractionHandle(ScriptInterfaceHelper):
+
+ """
+ Provides access to all non-bonded interactions between two particle types.
+
+ """
+ _so_name = "Interactions::NonBondedInteractionHandle"
+
+ def __getattr__(self, key):
+ obj = super().__getattr__(key)
+ return globals()[obj.__class__.__name__](
+ _types=self.call_method("get_types"), **obj.get_params())
+
+ def _serialize(self):
+ serialized = []
+ for name, obj in self.get_params().items():
+ serialized.append((name, obj.__reduce__()[1]))
+ return serialized
+
+ def reset(self):
+ for key in self._valid_parameters():
+ getattr(self, key).deactivate()
+
+ @classmethod
+ def _restore_object(cls, types, kwargs):
+ objects = {}
+ for name, (obj_class, obj_params) in kwargs:
+ objects[name] = obj_class(**obj_params)
+ return NonBondedInteractionHandle(_types=types, **objects)
+
+ def __reduce__(self):
+ return (NonBondedInteractionHandle._restore_object,
+ (self.call_method("get_types"), self._serialize()))
+
+
+@script_interface_register
+class NonBondedInteractions(ScriptInterfaceHelper):
+ """
+ Access to non-bonded interaction parameters via ``[i,j]``, where ``i, j``
+ are particle types. Returns a :class:`NonBondedInteractionHandle` object.
+
+ Methods
+ -------
+ reset()
+ Reset all interaction parameters to their default values.
+
+ """
+ _so_name = "Interactions::NonBondedInteractions"
+ _so_creation_policy = "GLOBAL"
+ _so_bind_methods = ("reset",)
+
+ def keys(self):
+ return [tuple(x) for x in self.call_method("keys")]
+
+ def _assert_key_type(self, key):
+ if not isinstance(key, tuple) or len(key) != 2 or \
+ not utils.is_valid_type(key[0], int) or not utils.is_valid_type(key[1], int):
+ raise TypeError(
+ "NonBondedInteractions[] expects two particle types as indices.")
+
+ def __getitem__(self, key):
+ self._assert_key_type(key)
+ return NonBondedInteractionHandle(_types=key)
+
+ def __setitem__(self, key, value):
+ self._assert_key_type(key)
+ self.call_method("insert", key=key, object=value)
+
+ def __getstate__(self):
+ n_types = self.call_method("get_n_types")
+ state = []
+ for i in range(n_types):
+ for j in range(i, n_types):
+ handle = NonBondedInteractionHandle(_types=(i, j))
+ state.append(((i, j), handle._serialize()))
+ return {"state": state}
+
+ def __setstate__(self, params):
+ for types, kwargs in params["state"]:
+ obj = NonBondedInteractionHandle._restore_object(types, kwargs)
+ self.call_method("insert", key=types, object=obj)
+
+ @classmethod
+ def _restore_object(cls, so_callback, so_callback_args, state):
+ so = so_callback(*so_callback_args)
+ so.__setstate__(state)
+ return so
+
+ def __reduce__(self):
+ so_callback, (so_name, so_bytestring) = super().__reduce__()
+ return (NonBondedInteractions._restore_object,
+ (so_callback, (so_name, so_bytestring), self.__getstate__()))
+
+
+class BONDED_IA(enum.IntEnum):
+ NONE = 0
+ FENE = enum.auto()
+ HARMONIC = enum.auto()
+ QUARTIC = enum.auto()
+ BONDED_COULOMB = enum.auto()
+ BONDED_COULOMB_SR = enum.auto()
+ ANGLE_HARMONIC = enum.auto()
+ ANGLE_COSINE = enum.auto()
+ ANGLE_COSSQUARE = enum.auto()
+ DIHEDRAL = enum.auto()
+ TABULATED_DISTANCE = enum.auto()
+ TABULATED_ANGLE = enum.auto()
+ TABULATED_DIHEDRAL = enum.auto()
+ THERMALIZED_DIST = enum.auto()
+ RIGID_BOND = enum.auto()
+ IBM_TRIEL = enum.auto()
+ IBM_VOLUME_CONSERVATION = enum.auto()
+ IBM_TRIBEND = enum.auto()
+ OIF_GLOBAL_FORCES = enum.auto()
+ OIF_LOCAL_FORCES = enum.auto()
+ VIRTUAL_BOND = enum.auto()
+
+
+class BondedInteraction(ScriptInterfaceHelper, metaclass=abc.ABCMeta):
+
+ """
+ Base class for bonded interactions.
+
+ Either called with an interaction id, in which case the interaction
+ will represent the bonded interaction as it is defined in ESPResSo core,
+ or called with keyword arguments describing a new interaction.
+
+ """
+
+ _so_name = "Interactions::BondedInteraction"
+ _so_creation_policy = "GLOBAL"
+
+ def __init__(self, **kwargs):
+ feature = self.__class__.__dict__.get("_so_feature")
+ if feature is not None:
+ code_features.assert_features(feature)
+
+ if "sip" not in kwargs:
+ if "bond_id" in kwargs:
+ # create a new script interface object for a bond that already
+ # exists in the core via its id (BondedInteractions getter and
+ # checkpointing constructor #1)
+ bond_id = kwargs["bond_id"]
+ super().__init__(bond_id=bond_id)
+ # Check if the bond type in ESPResSo core matches this class
+ if self.call_method("get_zero_based_type",
+ bond_id=bond_id) != self._type_number:
+ raise RuntimeError(
+ f"The bond with id {bond_id} is not defined as a "
+ f"{self._type_number.name} bond in the ESPResSo core.")
+ self._bond_id = bond_id
+ self._ctor_params = self.get_params()
+ else:
+ # create a new script interface object from bond parameters
+ # (normal bond creation and checkpointing constructor #2)
+ params = self.get_default_params()
+ params.update(kwargs)
+ super().__init__(**params)
+ self._ctor_params = params
+ self._bond_id = -1
+ else:
+ # create a new bond based on a bond in the script interface
+ # (checkpointing constructor #3)
+ super().__init__(**kwargs)
+ self._bond_id = -1
+ self._ctor_params = self.get_params()
+
+ def __reduce__(self):
+ if self._bond_id != -1:
+ # checkpointing constructor #1
+ return (BondedInteraction._restore_object,
+ (self.__class__, {"bond_id": self._bond_id}))
+ else:
+ # checkpointing constructor #2
+ return (BondedInteraction._restore_object,
+ (self.__class__, self._serialize()))
+
+ def _serialize(self):
+ return self._ctor_params.copy()
+
+ @classmethod
+ def _restore_object(cls, derived_class, kwargs):
+ return derived_class(**kwargs)
+
+ def __setattr__(self, attr, value):
+ super().__setattr__(attr, value)
+
+ @property
+ def params(self):
+ return self.get_params()
+
+ @params.setter
+ def params(self, p):
+ raise RuntimeError("Bond parameters are immutable.")
+
+ def __str__(self):
+ return f'{self.__class__.__name__}({self._ctor_params})'
+
+ @abc.abstractmethod
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ pass
+
+ def __repr__(self):
+ return f'<{self}>'
+
+ def __eq__(self, other):
+ return self.__class__ == other.__class__ and self.call_method(
+ "is_same_bond", bond=other)
+
+ def __ne__(self, other):
+ return not self.__eq__(other)
+
+
+@script_interface_register
+class FeneBond(BondedInteraction):
+
+ """
+ FENE bond.
+
+ Parameters
+ ----------
+ k : :obj:`float`
+ Magnitude of the bond interaction.
+ d_r_max : :obj:`float`
+ Maximum stretch and compression length of the bond.
+ r_0 : :obj:`float`, optional
+ Equilibrium bond length.
+
+ """
+
+ _so_name = "Interactions::FeneBond"
+ _type_number = BONDED_IA.FENE
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {"r_0": 0.}
+
+
+@script_interface_register
+class HarmonicBond(BondedInteraction):
+
+ """
+ Harmonic bond.
+
+ Parameters
+ ----------
+ k : :obj:`float`
+ Magnitude of the bond interaction.
+ r_0 : :obj:`float`
+ Equilibrium bond length.
+ r_cut : :obj:`float`, optional
+ Maximum distance beyond which the bond is considered broken.
+
+ """
+
+ _so_name = "Interactions::HarmonicBond"
+ _type_number = BONDED_IA.HARMONIC
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {"r_cut": 0.}
+
+
+@script_interface_register
+class BondedCoulomb(BondedInteraction):
+
+ """
+ Bonded Coulomb bond.
+
+ Parameters
+ ----------
+
+ prefactor : :obj:`float`
+ Coulomb prefactor of the bonded Coulomb interaction.
+ """
+
+ _so_name = "Interactions::BondedCoulomb"
+ _so_feature = "ELECTROSTATICS"
+ _type_number = BONDED_IA.BONDED_COULOMB
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class BondedCoulombSRBond(BondedInteraction):
+
+ """
+ Bonded Coulomb short range bond. Calculates the short range part of
+ Coulomb interactions.
+
+ Parameters
+ ----------
+
+ q1q2 : :obj:`float`
+ Charge factor of the involved particle pair. Note the
+ particle charges are used to allow e.g. only partial subtraction
+ of the involved charges.
+ """
+
+ _so_name = "Interactions::BondedCoulombSR"
+ _so_feature = "ELECTROSTATICS"
+ _type_number = BONDED_IA.BONDED_COULOMB_SR
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class ThermalizedBond(BondedInteraction):
+
+ """
+ Thermalized bond.
+
+ Parameters
+ ----------
+
+ temp_com : :obj:`float`
+ Temperature of the Langevin thermostat for the center of mass of the
+ particle pair.
+ gamma_com: :obj:`float`
+ Friction coefficient of the Langevin thermostat for the center of mass
+ of the particle pair.
+ temp_distance: :obj:`float`
+ Temperature of the Langevin thermostat for the distance vector
+ of the particle pair.
+ gamma_distance: :obj:`float`
+ Friction coefficient of the Langevin thermostat for the
+ distance vector of the particle pair.
+ r_cut: :obj:`float`, optional
+ Maximum distance beyond which the bond is considered broken.
+ seed : :obj:`int`
+ Seed of the philox RNG. Must be positive.
+ Required for the first thermalized bond in the system. Subsequent
+ thermalized bonds don't need a seed; if one is provided nonetheless,
+ it will overwrite the seed of all previously defined thermalized bonds,
+ even if the new bond is not added to the system.
+
+ """
+
+ _so_name = "Interactions::ThermalizedBond"
+ _type_number = BONDED_IA.THERMALIZED_DIST
+
+ def __init__(self, *args, **kwargs):
+ if kwargs and "sip" not in kwargs:
+ kwargs["rng_state"] = kwargs.get("rng_state")
+ super().__init__(*args, **kwargs)
+
+ def _serialize(self):
+ params = self._ctor_params.copy()
+ params["rng_state"] = self.call_method("get_rng_state")
+ return params
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {"r_cut": 0., "seed": None}
+
+
+@script_interface_register
+class RigidBond(BondedInteraction):
+
+ """
+ Rigid bond.
+
+ Parameters
+ ----------
+ r : :obj:`float`
+ Bond length.
+ ptol : :obj:`float`, optional
+ Tolerance for positional deviations.
+ vtop : :obj:`float`, optional
+ Tolerance for velocity deviations.
+
+ """
+
+ _so_name = "Interactions::RigidBond"
+ _so_feature = "BOND_CONSTRAINT"
+ _type_number = BONDED_IA.RIGID_BOND
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ # TODO rationality of Default Parameters has to be checked
+ return {"ptol": 0.001, "vtol": 0.001}
+
+
+@script_interface_register
+class Dihedral(BondedInteraction):
+
+ """
+ Dihedral potential with phase shift.
+
+ Parameters
+ ----------
+ mult : :obj:`int`
+ Multiplicity of the potential (number of minima).
+ bend : :obj:`float`
+ Bending constant.
+ phase : :obj:`float`
+ Angle of the first local minimum in radians.
+
+ """
+
+ _so_name = "Interactions::DihedralBond"
+ _type_number = BONDED_IA.DIHEDRAL
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class TabulatedDistance(BondedInteraction):
+
+ """
+ Tabulated bond length.
+
+ Parameters
+ ----------
+
+ min : :obj:`float`
+ The minimal interaction distance.
+ max : :obj:`float`
+ The maximal interaction distance.
+ energy: array_like of :obj:`float`
+ The energy table.
+ force: array_like of :obj:`float`
+ The force table.
+
+ """
+
+ _so_name = "Interactions::TabulatedDistanceBond"
+ _so_feature = "TABULATED"
+ _type_number = BONDED_IA.TABULATED_DISTANCE
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class TabulatedAngle(BondedInteraction):
+
+ """
+ Tabulated bond angle.
+
+ Parameters
+ ----------
+
+ energy: array_like of :obj:`float`
+ The energy table for the range :math:`0-\\pi`.
+ force: array_like of :obj:`float`
+ The force table for the range :math:`0-\\pi`.
+
+ """
+
+ _so_name = "Interactions::TabulatedAngleBond"
+ _so_feature = "TABULATED"
+ _type_number = BONDED_IA.TABULATED_ANGLE
+
+ pi = 3.14159265358979
+
+ def __init__(self, *args, **kwargs):
+ if len(args) == 0 and "sip" not in kwargs:
+ kwargs.update({"min": 0., "max": self.pi})
+ super().__init__(*args, **kwargs)
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class TabulatedDihedral(BondedInteraction):
+
+ """
+ Tabulated bond dihedral.
+
+ Parameters
+ ----------
+
+ energy: array_like of :obj:`float`
+ The energy table for the range :math:`0-2\\pi`.
+ force: array_like of :obj:`float`
+ The force table for the range :math:`0-2\\pi`.
+
+ """
+
+ _so_name = "Interactions::TabulatedDihedralBond"
+ _so_feature = "TABULATED"
+ _type_number = BONDED_IA.TABULATED_DIHEDRAL
+
+ pi = 3.14159265358979
+
+ def __init__(self, *args, **kwargs):
+ if len(args) == 0 and "sip" not in kwargs:
+ kwargs.update({"min": 0., "max": 2. * self.pi})
+ super().__init__(*args, **kwargs)
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class Virtual(BondedInteraction):
+
+ """
+ Virtual bond.
+ """
+
+ _so_name = "Interactions::VirtualBond"
+ _type_number = BONDED_IA.VIRTUAL_BOND
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class AngleHarmonic(BondedInteraction):
+
+ """
+ Bond-angle-dependent harmonic potential.
+
+ Parameters
+ ----------
+ phi0 : :obj:`float`
+ Equilibrium bond angle in radians.
+ bend : :obj:`float`
+ Magnitude of the bond interaction.
+
+ """
+
+ _so_name = "Interactions::AngleHarmonicBond"
+ _type_number = BONDED_IA.ANGLE_HARMONIC
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class AngleCosine(BondedInteraction):
+
+ """
+ Bond-angle-dependent cosine potential.
+
+ Parameters
+ ----------
+ phi0 : :obj:`float`
+ Equilibrium bond angle in radians.
+ bend : :obj:`float`
+ Magnitude of the bond interaction.
+
+ """
+
+ _so_name = "Interactions::AngleCosineBond"
+ _type_number = BONDED_IA.ANGLE_COSINE
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class AngleCossquare(BondedInteraction):
+
+ """
+ Bond-angle-dependent cosine squared potential.
+
+ Parameters
+ ----------
+ phi0 : :obj:`float`
+ Equilibrium bond angle in radians.
+ bend : :obj:`float`
+ Magnitude of the bond interaction.
+
+ """
+
+ _so_name = "Interactions::AngleCossquareBond"
+ _type_number = BONDED_IA.ANGLE_COSSQUARE
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class IBM_Triel(BondedInteraction):
+
+ """
+ IBM Triel bond.
+
+ See Figure C.1 in :cite:`kruger12a`.
+
+ Parameters
+ ----------
+ ind1, ind2, ind3 : :obj:`int`
+ First, second and third bonding partner. Used for
+ initializing reference state
+ k1 : :obj:`float`
+ Shear elasticity for Skalak and Neo-Hookean
+ k2 : :obj:`float`, optional
+ Area resistance for Skalak
+ maxDist : :obj:`float`
+ Gives an error if an edge becomes longer than maxDist
+ elasticLaw : :obj:`str`, \{'NeoHookean', 'Skalak'\}
+ Type of elastic bond
+
+ """
+
+ _so_name = "Interactions::IBMTriel"
+ _type_number = BONDED_IA.IBM_TRIEL
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {"k2": 0}
+
+
+@script_interface_register
+class IBM_Tribend(BondedInteraction):
+
+ """
+ IBM Tribend bond.
+
+ See Figure C.2 in :cite:`kruger12a`.
+
+ Parameters
+ ----------
+ ind1, ind2, ind3, ind4 : :obj:`int`
+ First, second, third and fourth bonding partner. Used for
+ initializing reference state
+ kb : :obj:`float`
+ Bending modulus
+ refShape : :obj:`str`, optional, \{'Flat', 'Initial'\}
+ Reference shape, default is ``'Flat'``
+
+ """
+
+ _so_name = "Interactions::IBMTribend"
+ _type_number = BONDED_IA.IBM_TRIBEND
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {"refShape": "Flat"}
+
+
+@script_interface_register
+class IBM_VolCons(BondedInteraction):
+
+ """
+ IBM volume conservation bond.
+
+ See Figure C.3 in :cite:`kruger12a`.
+
+ Parameters
+ ----------
+ softID : :obj:`int`
+ Used to identify the object to which this bond belongs. Each object
+ (cell) needs its own ID. For performance reasons, it is best to
+ start from ``softID=0`` and increment by 1 for each subsequent bond.
+ kappaV : :obj:`float`
+ Modulus for volume force
+
+ Methods
+ -------
+ current_volume()
+ Query the current volume of the soft object associated to this bond.
+ The volume is initialized once all :class:`IBM_Triel` bonds have
+ been added and the forces have been recalculated.
+
+ """
+
+ _so_name = "Interactions::IBMVolCons"
+ _so_bind_methods = ("current_volume",)
+ _type_number = BONDED_IA.IBM_VOLUME_CONSERVATION
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class OifGlobalForces(BondedInteraction):
+
+ """
+ Characterize the distribution of the force of the global mesh deformation
+ onto individual vertices of the mesh.
+
+ Part of the :ref:`Object-in-fluid` method.
+
+ Parameters
+ ----------
+ A0_g : :obj:`float`
+ Relaxed area of the mesh
+ ka_g : :obj:`float`
+ Area coefficient
+ V0 : :obj:`float`
+ Relaxed volume of the mesh
+ kv : :obj:`float`
+ Volume coefficient
+
+ """
+
+ _so_name = "Interactions::OifGlobalForcesBond"
+ _type_number = BONDED_IA.OIF_GLOBAL_FORCES
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class OifLocalForces(BondedInteraction):
+
+ """
+ Characterize the deformation of two triangles sharing an edge.
+
+ Part of the :ref:`Object-in-fluid` method.
+
+ Parameters
+ ----------
+ r0 : :obj:`float`
+ Equilibrium bond length of triangle edges
+ ks : :obj:`float`
+ Non-linear stretching coefficient of triangle edges
+ kslin : :obj:`float`
+ Linear stretching coefficient of triangle edges
+ phi0 : :obj:`float`
+ Equilibrium angle between the two triangles
+ kb : :obj:`float`
+ Bending coefficient for the angle between the two triangles
+ A01 : :obj:`float`
+ Equilibrium surface of the first triangle
+ A02 : :obj:`float`
+ Equilibrium surface of the second triangle
+ kal : :obj:`float`
+ Stretching coefficient of a triangle surface
+ kvisc : :obj:`float`
+ Viscous coefficient of the triangle vertices
+
+ """
+
+ _so_name = "Interactions::OifLocalForcesBond"
+ _type_number = BONDED_IA.OIF_LOCAL_FORCES
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class QuarticBond(BondedInteraction):
+
+ """
+ Quartic bond.
+
+ Parameters
+ ----------
+ k0 : :obj:`float`
+ Magnitude of the square term.
+ k1 : :obj:`float`
+ Magnitude of the fourth order term.
+ r : :obj:`float`
+ Equilibrium bond length.
+ r_cut : :obj:`float`
+ Maximum interaction length.
+ """
+
+ _so_name = "Interactions::QuarticBond"
+ _type_number = BONDED_IA.QUARTIC
+
+ def get_default_params(self):
+ """Gets default values of optional parameters.
+
+ """
+ return {}
+
+
+@script_interface_register
+class BondedInteractions(ScriptObjectMap):
+
+ """
+ Represents the bonded interactions list.
+
+ Individual interactions can be accessed using ``BondedInteractions[i]``,
+ where ``i`` is the bond id.
+
+ Methods
+ -------
+ remove()
+ Remove a bond from the list.
+ This is a no-op if the bond does not exist.
+
+ Parameters
+ ----------
+ bond_id : :obj:`int`
+
+ clear()
+ Remove all bonds.
+
+ """
+
+ _so_name = "Interactions::BondedInteractions"
+ _so_creation_policy = "GLOBAL"
+ _bond_classes = {
+ cls._type_number: cls for cls in globals().values()
+ if isinstance(cls, type) and issubclass(cls, BondedInteraction) and cls != BondedInteraction
+ }
+
+ def add(self, *args):
+ """
+ Add a bond to the list.
+
+ Parameters
+ ----------
+ bond: :class:`espressomd.interactions.BondedInteraction`
+ Either a bond object...
+
+ """
+
+ if len(args) == 1 and isinstance(args[0], BondedInteraction):
+ bonded_ia = args[0]
+ else:
+ raise TypeError("A BondedInteraction object needs to be passed.")
+ bond_id = self._insert_bond(None, bonded_ia)
+ return bond_id
+
+ def __getitem__(self, bond_id):
+ self._assert_key_type(bond_id)
+
+ if self.call_method('has_bond', bond_id=bond_id):
+ bond_obj = self.call_method('get_bond', bond_id=bond_id)
+ bond_obj._bond_id = bond_id
+ return bond_obj
+
+ # Find out the type of the interaction from ESPResSo
+ bond_type = self.call_method("get_zero_based_type", bond_id=bond_id)
+
+ # Check if the bonded interaction exists in ESPResSo core
+ if bond_type == BONDED_IA.NONE:
+ raise ValueError(f"The bond with id {bond_id} is not yet defined.")
+
+ # Find the appropriate class representing such a bond
+ bond_class = self._bond_classes[bond_type]
+
+ # Create a new script interface object (i.e. a copy of the shared_ptr)
+ # which links to the bonded interaction object
+ return bond_class(bond_id=bond_id)
+
+ def __setitem__(self, bond_id, bond_obj):
+ self._insert_bond(bond_id, bond_obj)
+
+ def _insert_bond(self, bond_id, bond_obj):
+ """
+ Inserts a new bond. If a ``bond_id`` is given, the bond is inserted at
+ that id. If no id is given, a new id is generated.
+
+ Bonds can only be overwritten if the new bond is of the same type as the
+ old one, e.g. a :class:`~espressomd.interactions.FeneBond` bond can only
+ be overwritten by another :class:`~espressomd.interactions.FeneBond` bond.
+ """
+
+ # Validate arguments
+ if not isinstance(bond_obj, BondedInteraction):
+ raise ValueError(
+ "Only subclasses of BondedInteraction can be assigned.")
+
+ # Send the script interface object pointer to the core
+ if bond_id is None:
+ bond_id = self.call_method("insert", object=bond_obj)
+ else:
+ # Throw error if attempting to overwrite a bond of different type
+ self._assert_key_type(bond_id)
+ if self.call_method("contains", key=bond_id):
+ old_type = self._bond_classes[
+ self.call_method("get_zero_based_type", bond_id=bond_id)]
+ if not isinstance(bond_obj, old_type):
+ raise ValueError(
+ "Bonds can only be overwritten by bonds of equal type.")
+ self.call_method("insert", key=bond_id, object=bond_obj)
+
+ # Save the bond id in the BondedInteraction instance
+ bond_obj._bond_id = bond_id
+
+ return bond_id
+
+ def __len__(self):
+ return self.call_method('get_size')
+
+ # Support iteration over active bonded interactions
+ def __iter__(self):
+ for bond_id in self.call_method('get_bond_ids'):
+ if self.call_method("get_zero_based_type", bond_id=bond_id):
+ yield self[bond_id]
+
+ def __getstate__(self):
+ params = {}
+ for bond_id in self.call_method('get_bond_ids'):
+ if self.call_method("get_zero_based_type", bond_id=bond_id):
+ obj = self[bond_id]
+ if hasattr(obj, "params"):
+ params[bond_id] = (obj._type_number, obj._serialize())
+ return params
+
+ def __setstate__(self, params):
+ for bond_id, (type_number, bond_params) in params.items():
+ self[bond_id] = self._bond_classes[type_number](**bond_params)
diff --git a/src/python/espressomd/interactions.pyx b/src/python/espressomd/interactions.pyx
deleted file mode 100644
index 2344513c14b..00000000000
--- a/src/python/espressomd/interactions.pyx
+++ /dev/null
@@ -1,2948 +0,0 @@
-#
-# Copyright (C) 2013-2022 The ESPResSo project
-#
-# This file is part of ESPResSo.
-#
-# ESPResSo is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# ESPResSo is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-#
-from libcpp.string cimport string
-cimport cpython.object
-import collections
-
-include "myconfig.pxi"
-from . import utils
-from .script_interface import ScriptObjectMap, ScriptInterfaceHelper, script_interface_register
-
-
-cdef class NonBondedInteraction:
- """
- Represents an instance of a non-bonded interaction, such as Lennard-Jones.
- Either called with two particle type id, in which case, the interaction
- will represent the bonded interaction as it is defined in ESPResSo core,
- or called with keyword arguments describing a new interaction.
-
- """
-
- cdef public object _part_types
- cdef public object _params
-
- # init dict to access all user defined nonbonded-inters via
- # user_interactions[type1][type2][parameter]
- cdef public object user_interactions
-
- def __init__(self, *args, **kwargs):
- if self.user_interactions is None:
- self.user_interactions = {}
- # Interaction id as argument
- if len(args) == 2 and utils.is_valid_type(
- args[0], int) and utils.is_valid_type(args[1], int):
- self._part_types = args
-
- # Load the parameters currently set in the ESPResSo core
- self._params = self._get_params_from_es_core()
-
- # Or have we been called with keyword args describing the interaction
- elif len(args) == 0:
- utils.check_required_keys(self.required_keys(), kwargs.keys())
- utils.check_valid_keys(self.valid_keys(), kwargs.keys())
- # Initialize default values
- self._params = self.default_params()
- self._part_types = [-1, -1]
- self._params.update(kwargs)
- self.validate_params()
- else:
- raise Exception(
- "The constructor has to be called either with two particle type ids (as integer), or with a set of keyword arguments describing a new interaction")
-
- def is_valid(self):
- """Check, if the data stored in the instance still matches what is in ESPResSo.
-
- """
- temp_params = self._get_params_from_es_core()
- return self._params == temp_params
-
- def get_params(self):
- """Get interaction parameters.
-
- """
- # If this instance refers to an actual interaction defined in
- # the es core, load current parameters from there
- if self._part_types[0] >= 0 and self._part_types[1] >= 0:
- self._params = self._get_params_from_es_core()
- return self._params
-
- def __str__(self):
- return f'{self.__class__.__name__}({self.get_params()})'
-
- def __getstate__(self):
- odict = collections.OrderedDict()
- odict['user_interactions'] = self.user_interactions
- odict['_part_types'] = self._part_types
- odict['params'] = self.get_params()
- return odict
-
- def __setstate__(self, state):
- self.user_interactions = state['user_interactions']
- self._part_types = state['_part_types']
- self._params = state['params']
-
- def set_params(self, **p):
- """Update the given parameters.
-
- """
- # Check, if any key was passed, which is not known
- utils.check_valid_keys(self.valid_keys(), p.keys())
-
- # When an interaction is newly activated, all required keys must be
- # given
- if not self.is_active():
- utils.check_required_keys(self.required_keys(), p.keys())
-
- # If this instance refers to an interaction defined in the ESPResSo core,
- # load the parameters from there
- is_valid_ia = self._part_types[0] >= 0 and self._part_types[1] >= 0
-
- if is_valid_ia:
- self._params = self._get_params_from_es_core()
-
- # Put in values given by the user
- self._params.update(p)
-
- if is_valid_ia:
- self._set_params_in_es_core()
-
- # update interaction dict when user sets interaction
- if self._part_types[0] not in self.user_interactions:
- self.user_interactions[self._part_types[0]] = {}
- self.user_interactions[self._part_types[0]][self._part_types[1]] = {}
- new_params = self.get_params()
- for p_key in new_params:
- self.user_interactions[self._part_types[0]][
- self._part_types[1]][p_key] = new_params[p_key]
- self.user_interactions[self._part_types[0]][
- self._part_types[1]]['type_name'] = self.type_name()
-
- # defer exception (core and interface must always agree on parameters)
- if is_valid_ia:
- utils.handle_errors(f'setting {self.type_name()} raised an error')
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- pass
-
- def __getattribute__(self, name):
- """Every time _set_params_in_es_core is called, the parameter dict is also updated.
-
- """
- attr = object.__getattribute__(self, name)
- if hasattr(
- attr, '__call__') and attr.__name__ == "_set_params_in_es_core":
- def sync_params(*args, **kwargs):
- result = attr(*args, **kwargs)
- self._params.update(self._get_params_from_es_core())
- return result
- return sync_params
- else:
- return attr
-
- def _get_params_from_es_core(self):
- raise Exception(
- "Subclasses of NonBondedInteraction must define the _get_params_from_es_core() method.")
-
- def _set_params_in_es_core(self):
- raise Exception(
- "Subclasses of NonBondedInteraction must define the _set_params_in_es_core() method.")
-
- def default_params(self):
- """Virtual method.
-
- """
- raise Exception(
- "Subclasses of NonBondedInteraction must define the default_params() method.")
-
- def is_active(self):
- """Virtual method.
-
- """
- # If this instance refers to an actual interaction defined in
- # the es core, load current parameters from there
- if self._part_types[0] >= 0 and self._part_types[1] >= 0:
- self._params = self._get_params_from_es_core()
- raise Exception(
- "Subclasses of NonBondedInteraction must define the is_active() method.")
-
- def type_name(self):
- """Virtual method.
-
- """
- raise Exception(
- "Subclasses of NonBondedInteraction must define the type_name() method.")
-
- def valid_keys(self):
- """Virtual method.
-
- """
- raise Exception(
- "Subclasses of NonBondedInteraction must define the valid_keys() method.")
-
- def required_keys(self):
- """Virtual method.
-
- """
- raise Exception(
- "Subclasses of NonBondedInteraction must define the required_keys() method.")
-
-IF LENNARD_JONES == 1:
-
- cdef class LennardJonesInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- Raises
- ------
- ValueError
- If not true.
- """
- if self._params["epsilon"] < 0:
- raise ValueError("Lennard-Jones epsilon has to be >=0")
- if self._params["sigma"] < 0:
- raise ValueError("Lennard-Jones sigma has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("Lennard-Jones cutoff has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "epsilon": ia_params.lj.eps,
- "sigma": ia_params.lj.sig,
- "cutoff": ia_params.lj.cut,
- "shift": ia_params.lj.shift,
- "offset": ia_params.lj.offset,
- "min": ia_params.lj.min}
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["epsilon"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the Lennard-Jones interaction.
-
- Parameters
- ----------
-
- epsilon : :obj:`float`
- Magnitude of the interaction.
- sigma : :obj:`float`
- Interaction length scale.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
- shift : :obj:`float` or :obj:`str` \{'auto'\}
- Constant shift of the potential. If ``'auto'``, a default value
- is computed from ``sigma`` and ``cutoff``. The LJ potential
- will be shifted by :math:`4\\epsilon\\cdot\\text{shift}`.
- offset : :obj:`float`, optional
- Offset distance of the interaction.
- min : :obj:`float`, optional
- Restricts the interaction to a minimal distance.
-
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- # Handle the case of shift="auto"
- if self._params["shift"] == "auto":
- self._params["shift"] = -((
- self._params["sigma"] / self._params["cutoff"])**12 - (
- self._params["sigma"] / self._params["cutoff"])**6)
-
- if lennard_jones_set_params(
- self._part_types[0], self._part_types[1],
- self._params["epsilon"],
- self._params["sigma"],
- self._params["cutoff"],
- self._params["shift"],
- self._params["offset"],
- self._params["min"]):
- raise Exception("Could not set Lennard-Jones parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {"offset": 0., "min": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "LennardJones"
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"epsilon", "sigma", "cutoff", "shift", "offset", "min"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"epsilon", "sigma", "cutoff", "shift"}
-
-IF WCA == 1:
-
- cdef class WCAInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- Raises
- ------
- ValueError
- If not true.
- """
- if self._params["epsilon"] < 0:
- raise ValueError("WCA eps has to be >=0")
- if self._params["sigma"] < 0:
- raise ValueError("WCA sigma has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "epsilon": ia_params.wca.eps,
- "sigma": ia_params.wca.sig,
- "cutoff": ia_params.wca.cut}
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["epsilon"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the WCA interaction.
-
- Parameters
- ----------
-
- epsilon : :obj:`float`
- Magnitude of the interaction.
- sigma : :obj:`float`
- Interaction length scale.
-
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if wca_set_params(
- self._part_types[0], self._part_types[1],
- self._params["epsilon"],
- self._params["sigma"]):
- raise Exception("Could not set WCA parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "WCA"
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"epsilon", "sigma"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"epsilon", "sigma"}
-
-IF LENNARD_JONES_GENERIC == 1:
-
- cdef class GenericLennardJonesInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- Raises
- ------
- ValueError
- If not true.
- """
- if self._params["epsilon"] < 0:
- raise ValueError("Generic Lennard-Jones epsilon has to be >=0")
- if self._params["sigma"] < 0:
- raise ValueError("Generic Lennard-Jones sigma has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("Generic Lennard-Jones cutoff has to be >=0")
- IF LJGEN_SOFTCORE:
- if self._params["delta"] < 0:
- raise ValueError(
- "Generic Lennard-Jones delta has to be >=0")
- if self._params["lam"] < 0 or self._params["lam"] > 1:
- raise ValueError(
- "Generic Lennard-Jones lam has to be in the range [0,1]")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "epsilon": ia_params.ljgen.eps,
- "sigma": ia_params.ljgen.sig,
- "cutoff": ia_params.ljgen.cut,
- "shift": ia_params.ljgen.shift,
- "offset": ia_params.ljgen.offset,
- "e1": ia_params.ljgen.a1,
- "e2": ia_params.ljgen.a2,
- "b1": ia_params.ljgen.b1,
- "b2": ia_params.ljgen.b2,
- "lam": ia_params.ljgen.lambda1,
- "delta": ia_params.ljgen.softrad
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["epsilon"] > 0)
-
- def _set_params_in_es_core(self):
- # Handle the case of shift="auto"
- if self._params["shift"] == "auto":
- self._params["shift"] = -(
- self._params["b1"] * (self._params["sigma"] / self._params["cutoff"])**self._params["e1"] -
- self._params["b2"] * (self._params["sigma"] / self._params["cutoff"])**self._params["e2"])
- IF LJGEN_SOFTCORE:
- if ljgen_set_params(self._part_types[0], self._part_types[1],
- self._params["epsilon"],
- self._params["sigma"],
- self._params["cutoff"],
- self._params["shift"],
- self._params["offset"],
- self._params["e1"],
- self._params["e2"],
- self._params["b1"],
- self._params["b2"],
- self._params["lam"],
- self._params["delta"]):
- raise Exception(
- "Could not set Generic Lennard-Jones parameters")
- ELSE:
- if ljgen_set_params(self._part_types[0], self._part_types[1],
- self._params["epsilon"],
- self._params["sigma"],
- self._params["cutoff"],
- self._params["shift"],
- self._params["offset"],
- self._params["e1"],
- self._params["e2"],
- self._params["b1"],
- self._params["b2"],
- ):
- raise Exception(
- "Could not set Generic Lennard-Jones parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- IF LJGEN_SOFTCORE:
- return {"delta": 0., "lam": 1.}
- ELSE:
- return {}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "GenericLennardJones"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the generic Lennard-Jones interaction.
-
- Parameters
- ----------
- epsilon : :obj:`float`
- Magnitude of the interaction.
- sigma : :obj:`float`
- Interaction length scale.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
- shift : :obj:`float` or :obj:`str` \{'auto'\}
- Constant shift of the potential. If ``'auto'``, a default value
- is computed from the other parameters. The LJ potential
- will be shifted by :math:`\\epsilon\\cdot\\text{shift}`.
- offset : :obj:`float`
- Offset distance of the interaction.
- e1 : :obj:`int`
- Exponent of the repulsion term.
- e2 : :obj:`int`
- Exponent of the attraction term.
- b1 : :obj:`float`
- Prefactor of the repulsion term.
- b2 : :obj:`float`
- Prefactor of the attraction term.
- delta : :obj:`float`, optional
- ``LJGEN_SOFTCORE`` parameter delta. Allows control over how
- smoothly the potential drops to zero as lambda approaches zero.
- lam : :obj:`float`, optional
- ``LJGEN_SOFTCORE`` parameter lambda. Tune the strength of the
- interaction.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- IF LJGEN_SOFTCORE:
- return {"epsilon", "sigma", "cutoff", "shift",
- "offset", "e1", "e2", "b1", "b2", "delta", "lam"}
- ELSE:
- return {"epsilon", "sigma", "cutoff",
- "shift", "offset", "e1", "e2", "b1", "b2"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"epsilon", "sigma", "cutoff",
- "shift", "offset", "e1", "e2", "b1", "b2"}
-
-IF LJCOS:
-
- cdef class LennardJonesCosInteraction(NonBondedInteraction):
-
- def validate_params(self):
- if self._params["epsilon"] < 0:
- raise ValueError("Lennard-Jones epsilon has to be >=0")
- if self._params["sigma"] < 0:
- raise ValueError("Lennard-Jones sigma has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "epsilon": ia_params.ljcos.eps,
- "sigma": ia_params.ljcos.sig,
- "cutoff": ia_params.ljcos.cut,
- "offset": ia_params.ljcos.offset,
- }
-
- def is_active(self):
- return(self._params["epsilon"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the Lennard-Jones cosine interaction.
-
- Parameters
- ----------
-
- epsilon : :obj:`float`
- Magnitude of the interaction.
- sigma : :obj:`float`
- Interaction length scale.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
- offset : :obj:`float`, optional
- Offset distance of the interaction.
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if ljcos_set_params(self._part_types[0],
- self._part_types[1],
- self._params["epsilon"],
- self._params["sigma"],
- self._params["cutoff"],
- self._params["offset"]):
- raise Exception(
- "Could not set Lennard-Jones Cosine parameters")
-
- def default_params(self):
- return {"offset": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "LennardJonesCos"
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"epsilon", "sigma", "cutoff", "offset"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"epsilon", "sigma", "cutoff"}
-
-IF LJCOS2:
-
- cdef class LennardJonesCos2Interaction(NonBondedInteraction):
-
- def validate_params(self):
- if self._params["epsilon"] < 0:
- raise ValueError("Lennard-Jones epsilon has to be >=0")
- if self._params["sigma"] < 0:
- raise ValueError("Lennard-Jones sigma has to be >=0")
- if self._params["width"] < 0:
- raise ValueError("Parameter width has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return{
- "epsilon": ia_params.ljcos2.eps,
- "sigma": ia_params.ljcos2.sig,
- "offset": ia_params.ljcos2.offset,
- "width": ia_params.ljcos2.w}
-
- def is_active(self):
- return (self._params["epsilon"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the Lennard-Jones cosine squared interaction.
-
- Parameters
- ----------
-
- epsilon : :obj:`float`
- Magnitude of the interaction.
- sigma : :obj:`float`
- Interaction length scale.
- offset : :obj:`float`, optional
- Offset distance of the interaction.
- width : :obj:`float`
- Width of interaction.
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if ljcos2_set_params(self._part_types[0],
- self._part_types[1],
- self._params["epsilon"],
- self._params["sigma"],
- self._params["offset"],
- self._params["width"]):
- raise Exception(
- "Could not set Lennard-Jones Cosine2 parameters")
-
- def default_params(self):
- return {"offset": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "LennardJonesCos2"
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"epsilon", "sigma", "offset", "width"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"epsilon", "sigma", "width"}
-
-IF HAT == 1:
-
- cdef class HatInteraction(NonBondedInteraction):
-
- def validate_params(self):
- if self._params["F_max"] < 0:
- raise ValueError("Hat max force has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("Hat cutoff has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0], self._part_types[1])
- return {
- "F_max": ia_params.hat.Fmax,
- "cutoff": ia_params.hat.r,
- }
-
- def is_active(self):
- return (self._params["F_max"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the Hat interaction.
-
- Parameters
- ----------
- F_max : :obj:`float`
- Magnitude of the interaction.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
-
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if hat_set_params(self._part_types[0], self._part_types[1],
- self._params["F_max"],
- self._params["cutoff"]):
- raise Exception("Could not set Hat parameters")
-
- def default_params(self):
- return {}
-
- def type_name(self):
- return "Hat"
-
- def valid_keys(self):
- return {"F_max", "cutoff"}
-
- def required_keys(self):
- return {"F_max", "cutoff"}
-
-IF GAY_BERNE:
-
- cdef class GayBerneInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- pass
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "eps": ia_params.gay_berne.eps,
- "sig": ia_params.gay_berne.sig,
- "cut": ia_params.gay_berne.cut,
- "k1": ia_params.gay_berne.k1,
- "k2": ia_params.gay_berne.k2,
- "mu": ia_params.gay_berne.mu,
- "nu": ia_params.gay_berne.nu}
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["eps"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the Gay-Berne interaction.
-
- Parameters
- ----------
- eps : :obj:`float`
- Potential well depth.
- sig : :obj:`float`
- Interaction range.
- cut : :obj:`float`
- Cutoff distance of the interaction.
- k1 : :obj:`float` or :obj:`str`
- Molecular elongation.
- k2 : :obj:`float`, optional
- Ratio of the potential well depths for the side-by-side
- and end-to-end configurations.
- mu : :obj:`float`, optional
- Adjustable exponent.
- nu : :obj:`float`, optional
- Adjustable exponent.
-
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if gay_berne_set_params(self._part_types[0],
- self._part_types[1],
- self._params["eps"],
- self._params["sig"],
- self._params["cut"],
- self._params["k1"],
- self._params["k2"],
- self._params["mu"],
- self._params["nu"]):
- raise Exception("Could not set Gay-Berne parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "GayBerne"
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"eps", "sig", "cut", "k1", "k2", "mu", "nu"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"eps", "sig", "cut", "k1", "k2", "mu", "nu"}
-
-IF DPD:
-
- cdef class DPDInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- pass
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0], self._part_types[1])
- return {
- "weight_function": ia_params.dpd_radial.wf,
- "gamma": ia_params.dpd_radial.gamma,
- "k": ia_params.dpd_radial.k,
- "r_cut": ia_params.dpd_radial.cutoff,
- "trans_weight_function": ia_params.dpd_trans.wf,
- "trans_gamma": ia_params.dpd_trans.gamma,
- "trans_r_cut": ia_params.dpd_trans.cutoff
- }
-
- def is_active(self):
- return (self._params["r_cut"] > 0) or (
- self._params["trans_r_cut"] > 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the DPD interaction.
-
- Parameters
- ----------
- weight_function : :obj:`int`, \{0, 1\}
- The distance dependence of the parallel part,
- either 0 (constant) or 1 (linear)
- gamma : :obj:`float`
- Friction coefficient of the parallel part
- k : :obj:`float`
- Exponent in the modified weight function
- r_cut : :obj:`float`
- Cutoff of the parallel part
- trans_weight_function : :obj:`int`, \{0, 1\}
- The distance dependence of the orthogonal part,
- either 0 (constant) or 1 (linear)
- trans_gamma : :obj:`float`
- Friction coefficient of the orthogonal part
- trans_r_cut : :obj:`float`
- Cutoff of the orthogonal part
-
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if dpd_set_params(self._part_types[0],
- self._part_types[1],
- self._params["gamma"],
- self._params["k"],
- self._params["r_cut"],
- self._params["weight_function"],
- self._params["trans_gamma"],
- self._params["trans_r_cut"],
- self._params["trans_weight_function"]):
- raise Exception("Could not set DPD parameters")
-
- def default_params(self):
- return {
- "weight_function": 0,
- "gamma": 0.0,
- "k": 1.0,
- "r_cut": -1.0,
- "trans_weight_function": 0,
- "trans_gamma": 0.0,
- "trans_r_cut": -1.0}
-
- def type_name(self):
- return "DPD"
-
- def valid_keys(self):
- return {"weight_function", "gamma", "k", "r_cut",
- "trans_weight_function", "trans_gamma", "trans_r_cut"}
-
- def required_keys(self):
- return set()
-
-IF SMOOTH_STEP == 1:
-
- cdef class SmoothStepInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["eps"] < 0:
- raise ValueError("Smooth-step eps has to be >=0")
- if self._params["offset"] < 0:
- raise ValueError("Smooth-step offset has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("Smooth-step cutoff has to be >=0")
- if self._params["cap"] < 0:
- raise ValueError("Smooth-step cap has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "d": ia_params.smooth_step.d,
- "n": ia_params.smooth_step.n,
- "eps": ia_params.smooth_step.eps,
- "k0": ia_params.smooth_step.k0,
- "sig": ia_params.smooth_step.sig,
- "cutoff": ia_params.smooth_step.cut
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return ((self._params["eps"] > 0) and (self._params["sig"] > 0))
-
- def _set_params_in_es_core(self):
- if smooth_step_set_params(self._part_types[0],
- self._part_types[1],
- self._params["d"],
- self._params["n"],
- self._params["eps"],
- self._params["k0"],
- self._params["sig"],
- self._params["cutoff"]):
- raise Exception("Could not set smooth-step parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {"n": 10, "k0": 0., "sig": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "SmoothStep"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the smooth-step interaction.
-
- Parameters
- ----------
- d : :obj:`float`
- Short range repulsion parameter.
- n : :obj:`int`, optional
- Exponent of short range repulsion.
- eps : :obj:`float`
- Magnitude of the second (soft) repulsion.
- k0 : :obj:`float`, optional
- Exponential factor in second (soft) repulsion.
- sig : :obj:`float`, optional
- Length scale of second (soft) repulsion.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"d", "n", "eps", "k0", "sig", "cutoff"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"d", "eps", "cutoff"}
-
-IF BMHTF_NACL == 1:
-
- cdef class BMHTFInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["a"] < 0:
- raise ValueError("BMHTF a has to be >=0")
- if self._params["c"] < 0:
- raise ValueError("BMHTF c has to be >=0")
- if self._params["d"] < 0:
- raise ValueError("BMHTF d has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("BMHTF cutoff has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(self._part_types[0],
- self._part_types[1])
- return {
- "a": ia_params.bmhtf.A,
- "b": ia_params.bmhtf.B,
- "c": ia_params.bmhtf.C,
- "d": ia_params.bmhtf.D,
- "sig": ia_params.bmhtf.sig,
- "cutoff": ia_params.bmhtf.cut,
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["a"] > 0) and (
- self._params["c"] > 0) and (self._params["d"] > 0)
-
- def _set_params_in_es_core(self):
- if BMHTF_set_params(self._part_types[0],
- self._part_types[1],
- self._params["a"],
- self._params["b"],
- self._params["c"],
- self._params["d"],
- self._params["sig"],
- self._params["cutoff"]):
- raise Exception("Could not set BMHTF parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "BMHTF"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the BMHTF interaction.
-
- Parameters
- ----------
- a : :obj:`float`
- Magnitude of exponential part of the interaction.
- b : :obj:`float`
- Exponential factor of the interaction.
- c : :obj:`float`
- Magnitude of the term decaying with the sixth power of r.
- d : :obj:`float`
- Magnitude of the term decaying with the eighth power of r.
- sig : :obj:`float`
- Shift in the exponent.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"a", "b", "c", "d", "sig", "cutoff"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"a", "b", "c", "d", "sig", "cutoff"}
-
-IF MORSE == 1:
-
- cdef class MorseInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["eps"] < 0:
- raise ValueError("Morse eps has to be >=0")
- if self._params["offset"] < 0:
- raise ValueError("Morse offset has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("Morse cutoff has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "eps": ia_params.morse.eps,
- "alpha": ia_params.morse.alpha,
- "rmin": ia_params.morse.rmin,
- "cutoff": ia_params.morse.cut
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["eps"] > 0)
-
- def _set_params_in_es_core(self):
- if morse_set_params(self._part_types[0],
- self._part_types[1],
- self._params["eps"],
- self._params["alpha"],
- self._params["rmin"],
- self._params["cutoff"]):
- raise Exception("Could not set Morse parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {"cutoff": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "Morse"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the Morse interaction.
-
- Parameters
- ----------
- eps : :obj:`float`
- The magnitude of the interaction.
- alpha : :obj:`float`
- Stiffness of the Morse interaction.
- rmin : :obj:`float`
- Distance of potential minimum
- cutoff : :obj:`float`, optional
- Cutoff distance of the interaction.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"eps", "alpha", "rmin", "cutoff"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"eps", "alpha", "rmin"}
-
-IF BUCKINGHAM == 1:
-
- cdef class BuckinghamInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["a"] < 0:
- raise ValueError("Buckingham a has to be >=0")
- if self._params["b"] < 0:
- raise ValueError("Buckingham b has to be >=0")
- if self._params["c"] < 0:
- raise ValueError("Buckingham c has to be >=0")
- if self._params["d"] < 0:
- raise ValueError("Buckingham d has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "a": ia_params.buckingham.A,
- "b": ia_params.buckingham.B,
- "c": ia_params.buckingham.C,
- "d": ia_params.buckingham.D,
- "cutoff": ia_params.buckingham.cut,
- "discont": ia_params.buckingham.discont,
- "shift": ia_params.buckingham.shift
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["a"] > 0) or (self._params["b"] > 0) or (
- self._params["d"] > 0) or (self._params["shift"] > 0)
-
- def _set_params_in_es_core(self):
- if buckingham_set_params(self._part_types[0], self._part_types[1],
- self._params["a"],
- self._params["b"],
- self._params["c"],
- self._params["d"],
- self._params["cutoff"],
- self._params["discont"],
- self._params["shift"]):
- raise Exception("Could not set Buckingham parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {"b": 0., "shift": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "Buckingham"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the Buckingham interaction.
-
- Parameters
- ----------
- a : :obj:`float`
- Magnitude of the exponential part of the interaction.
- b : :obj:`float`, optional
- Exponent of the exponential part of the interaction.
- c : :obj:`float`
- Prefactor of term decaying with the sixth power of distance.
- d : :obj:`float`
- Prefactor of term decaying with the fourth power of distance.
- discont : :obj:`float`
- Distance below which the potential is linearly continued.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
- shift: :obj:`float`, optional
- Constant potential shift.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"a", "b", "c", "d", "discont", "cutoff", "shift"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"a", "c", "d", "discont", "cutoff"}
-
-IF SOFT_SPHERE == 1:
-
- cdef class SoftSphereInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["a"] < 0:
- raise ValueError("Soft-sphere a has to be >=0")
- if self._params["offset"] < 0:
- raise ValueError("Soft-sphere offset has to be >=0")
- if self._params["cutoff"] < 0:
- raise ValueError("Soft-sphere cutoff has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(self._part_types[0],
- self._part_types[1])
- return {
- "a": ia_params.soft_sphere.a,
- "n": ia_params.soft_sphere.n,
- "cutoff": ia_params.soft_sphere.cut,
- "offset": ia_params.soft_sphere.offset
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["a"] > 0)
-
- def _set_params_in_es_core(self):
- if soft_sphere_set_params(self._part_types[0],
- self._part_types[1],
- self._params["a"],
- self._params["n"],
- self._params["cutoff"],
- self._params["offset"]):
- raise Exception("Could not set Soft-sphere parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {"offset": 0.}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "SoftSphere"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the Soft-sphere interaction.
-
- Parameters
- ----------
- a : :obj:`float`
- Magnitude of the interaction.
- n : :obj:`float`
- Exponent of the power law.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
- offset : :obj:`float`, optional
- Offset distance of the interaction.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"a", "n", "cutoff", "offset"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"a", "n", "cutoff"}
-
-
-IF HERTZIAN == 1:
-
- cdef class HertzianInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["eps"] < 0:
- raise ValueError("Hertzian eps a has to be >=0")
- if self._params["sig"] < 0:
- raise ValueError("Hertzian sig has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "eps": ia_params.hertzian.eps,
- "sig": ia_params.hertzian.sig
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["eps"] > 0)
-
- def _set_params_in_es_core(self):
- if hertzian_set_params(self._part_types[0],
- self._part_types[1],
- self._params["eps"],
- self._params["sig"]):
- raise Exception("Could not set Hertzian parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "Hertzian"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the Hertzian interaction.
-
- Parameters
- ----------
- eps : :obj:`float`
- Magnitude of the interaction.
- sig : :obj:`float`
- Parameter sigma. Determines the length over which the potential
- decays.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"eps", "sig"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"eps", "sig"}
-
-IF GAUSSIAN == 1:
-
- cdef class GaussianInteraction(NonBondedInteraction):
-
- def validate_params(self):
- """Check that parameters are valid.
-
- """
- if self._params["eps"] < 0:
- raise ValueError("Gaussian eps a has to be >=0")
- if self._params["sig"] < 0:
- raise ValueError("Gaussian sig has to be >=0")
- if self._params["offset"] < 0:
- raise ValueError("Gaussian offset has to be >=0")
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
- return {
- "eps": ia_params.gaussian.eps,
- "sig": ia_params.gaussian.sig,
- "cutoff": ia_params.gaussian.cut
- }
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self._params["eps"] > 0)
-
- def _set_params_in_es_core(self):
- if gaussian_set_params(self._part_types[0],
- self._part_types[1],
- self._params["eps"],
- self._params["sig"],
- self._params["cutoff"]):
- raise Exception(
- "Could not set Gaussian interaction parameters")
-
- def default_params(self):
- """Python dictionary of default parameters.
-
- """
- return {}
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "Gaussian"
-
- def set_params(self, **kwargs):
- """
- Set parameters for the Gaussian interaction.
-
- Parameters
- ----------
- eps : :obj:`float`
- Overlap energy epsilon.
- sig : :obj:`float`
- Variance sigma of the Gaussian interaction.
- cutoff : :obj:`float`
- Cutoff distance of the interaction.
-
- """
- super().set_params(**kwargs)
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"eps", "sig", "cutoff"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"eps", "sig", "cutoff"}
-
-
-class NonBondedInteractionHandle:
-
- """
- Provides access to all non-bonded interactions between two particle types.
-
- """
-
- def __init__(self, _type1, _type2):
- if not (utils.is_valid_type(_type1, int)
- and utils.is_valid_type(_type2, int)):
- raise TypeError("The particle types have to be of type integer.")
-
- # Here, add one line for each nonbonded ia
- IF LENNARD_JONES:
- self.lennard_jones = LennardJonesInteraction(_type1, _type2)
- IF WCA:
- self.wca = WCAInteraction(_type1, _type2)
- IF SOFT_SPHERE:
- self.soft_sphere = SoftSphereInteraction(_type1, _type2)
- IF LENNARD_JONES_GENERIC:
- self.generic_lennard_jones = GenericLennardJonesInteraction(
- _type1, _type2)
- IF LJCOS:
- self.lennard_jones_cos = LennardJonesCosInteraction(_type1, _type2)
- IF LJCOS2:
- self.lennard_jones_cos2 = LennardJonesCos2Interaction(
- _type1, _type2)
- IF SMOOTH_STEP:
- self.smooth_step = SmoothStepInteraction(_type1, _type2)
- IF BMHTF_NACL:
- self.bmhtf = BMHTFInteraction(_type1, _type2)
- IF MORSE:
- self.morse = MorseInteraction(_type1, _type2)
- IF BUCKINGHAM:
- self.buckingham = BuckinghamInteraction(_type1, _type2)
- IF HERTZIAN:
- self.hertzian = HertzianInteraction(_type1, _type2)
- IF GAUSSIAN:
- self.gaussian = GaussianInteraction(_type1, _type2)
- IF TABULATED:
- self.tabulated = TabulatedNonBonded(_type1, _type2)
- IF GAY_BERNE:
- self.gay_berne = GayBerneInteraction(_type1, _type2)
- IF DPD:
- self.dpd = DPDInteraction(_type1, _type2)
- IF HAT:
- self.hat = HatInteraction(_type1, _type2)
- IF THOLE:
- self.thole = TholeInteraction(_type1, _type2)
-
-
-cdef class NonBondedInteractions:
- """
- Access to non-bonded interaction parameters via ``[i,j]``, where ``i, j``
- are particle types. Returns a :class:`NonBondedInteractionHandle` object.
- Also: access to force capping.
-
- """
-
- def __getitem__(self, key):
- if not isinstance(key, tuple):
- raise ValueError(
- "NonBondedInteractions[] expects two particle types as indices.")
- if len(key) != 2 or (not utils.is_valid_type(key[0], int)) or (
- not utils.is_valid_type(key[1], int)):
- raise ValueError(
- "NonBondedInteractions[] expects two particle types as indices.")
- return NonBondedInteractionHandle(key[0], key[1])
-
- def __getstate__(self):
- cdef string core_state
- core_state = ia_params_get_state()
- return core_state
-
- def __setstate__(self, core_state):
- cdef string state = core_state
- ia_params_set_state(state)
-
- def reset(self):
- """
- Reset all interaction parameters to their default values.
- """
-
- reset_ia_params()
-
-
-class BondedInteraction(ScriptInterfaceHelper):
-
- """
- Base class for bonded interactions.
-
- Either called with an interaction id, in which case the interaction
- will represent the bonded interaction as it is defined in ESPResSo core,
- or called with keyword arguments describing a new interaction.
-
- """
-
- _so_name = "Interactions::BondedInteraction"
- _so_creation_policy = "GLOBAL"
-
- def __init__(self, *args, **kwargs):
- if len(args) == 1 and len(kwargs) == 0 and isinstance(args[0], dict):
- # this branch is only visited by checkpointing constructor #2
- kwargs = args[0]
- args = []
-
- if not 'sip' in kwargs:
- if len(args) == 1 and utils.is_valid_type(args[0], int):
- # create a new script interface object for a bond that already
- # exists in the core via bond_id (checkpointing constructor #1)
- bond_id = args[0]
- # Check if the bond type in ESPResSo core matches this class
- if get_bonded_interaction_type_from_es_core(
- bond_id) != self.type_number():
- raise Exception(
- f"The bond with id {bond_id} is not defined as a "
- f"{self.type_name()} bond in the ESPResSo core.")
- super().__init__(bond_id=bond_id)
- self._bond_id = bond_id
- self._ctor_params = self._get_params_from_es_core()
- else:
- # create a bond from bond parameters
- params = self.get_default_params()
- params.update(kwargs)
- self.validate_params(params)
- super().__init__(*args, **params)
- utils.check_valid_keys(self.valid_keys(), kwargs.keys())
- self._ctor_params = params
- self._bond_id = -1
- else:
- # create a new bond based on a bond in the script interface
- # (checkpointing constructor #2 or BondedInteractions getter)
- super().__init__(**kwargs)
- self._bond_id = -1
- self._ctor_params = self._get_params_from_es_core()
-
- def __reduce__(self):
- if self._bond_id != -1:
- # checkpointing constructor #1
- return (self.__class__, (self._bond_id,))
- else:
- # checkpointing constructor #2
- return (self.__class__, (self._ctor_params,))
-
- def __setattr__(self, attr, value):
- super().__setattr__(attr, value)
-
- @property
- def params(self):
- return self._get_params_from_es_core()
-
- @params.setter
- def params(self, p):
- raise RuntimeError("Bond parameters are immutable.")
-
- def validate_params(self, params):
- """Check that parameters are valid.
-
- """
- pass
-
- def _get_params_from_es_core(self):
- return {key: getattr(self, key) for key in self.valid_keys()}
-
- def __str__(self):
- return f'{self.__class__.__name__}({self._ctor_params})'
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- raise Exception(
- "Subclasses of BondedInteraction must define the get_default_params() method.")
-
- def type_number(self):
- raise Exception(
- "Subclasses of BondedInteraction must define the type_number() method.")
-
- def type_name(self):
- """Name of interaction type.
-
- """
- raise Exception(
- "Subclasses of BondedInteraction must define the type_name() method.")
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return set(self._valid_parameters())
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return self.valid_keys().difference(self.get_default_params().keys())
-
- def __repr__(self):
- return f'<{self}>'
-
- def __eq__(self, other):
- return self.__richcmp__(other, cpython.object.Py_EQ)
-
- def __ne__(self, other):
- return self.__richcmp__(other, cpython.object.Py_NE)
-
- def __richcmp__(self, other, op):
- are_equal = self.__class__ == other.__class__ and self.call_method(
- "get_address") == other.call_method("get_address")
- if op == cpython.object.Py_EQ:
- return are_equal
- elif op == cpython.object.Py_NE:
- return not are_equal
- else:
- raise NotImplementedError("only equality comparison is supported")
-
-
-class BondedInteractionNotDefined:
-
- def __init__(self, *args, **kwargs):
- raise Exception(
- self.__class__.__name__ + " not compiled into ESPResSo core")
-
- def type_number(self):
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
- def type_name(self):
- """Name of interaction type.
-
- """
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
- def _get_params_from_es_core(self):
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
- def _set_params_in_es_core(self):
- raise Exception(f"{self.name} has to be defined in myconfig.hpp.")
-
-
-@script_interface_register
-class FeneBond(BondedInteraction):
-
- """
- FENE bond.
-
- Parameters
- ----------
- k : :obj:`float`
- Magnitude of the bond interaction.
- d_r_max : :obj:`float`
- Maximum stretch and compression length of the bond.
- r_0 : :obj:`float`, optional
- Equilibrium bond length.
-
- """
-
- _so_name = "Interactions::FeneBond"
-
- def type_number(self):
- return BONDED_IA_FENE
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "FENE"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {"r_0": 0.}
-
-
-@script_interface_register
-class HarmonicBond(BondedInteraction):
-
- """
- Harmonic bond.
-
- Parameters
- ----------
- k : :obj:`float`
- Magnitude of the bond interaction.
- r_0 : :obj:`float`
- Equilibrium bond length.
- r_cut : :obj:`float`, optional
- Maximum distance beyond which the bond is considered broken.
-
- """
-
- _so_name = "Interactions::HarmonicBond"
-
- def type_number(self):
- return BONDED_IA_HARMONIC
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "HARMONIC"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {"r_cut": 0.}
-
-
-if ELECTROSTATICS:
-
- @script_interface_register
- class BondedCoulomb(BondedInteraction):
-
- """
- Bonded Coulomb bond.
-
- Parameters
- ----------
-
- prefactor : :obj:`float`
- Coulomb prefactor of the bonded Coulomb interaction.
- """
-
- _so_name = "Interactions::BondedCoulomb"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_BONDED_COULOMB
-
- def type_name(self):
- return "BONDED_COULOMB"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-if ELECTROSTATICS:
-
- @script_interface_register
- class BondedCoulombSRBond(BondedInteraction):
-
- """
- Bonded Coulomb short range bond. Calculates the short range part of
- Coulomb interactions.
-
- Parameters
- ----------
-
- q1q2 : :obj:`float`
- Charge factor of the involved particle pair. Note the
- particle charges are used to allow e.g. only partial subtraction
- of the involved charges.
- """
-
- _so_name = "Interactions::BondedCoulombSR"
-
- def type_number(self):
- return BONDED_IA_BONDED_COULOMB_SR
-
- def type_name(self):
- return "BONDED_COULOMB_SR"
-
- def get_default_params(self):
- return {}
-
-
-@script_interface_register
-class ThermalizedBond(BondedInteraction):
-
- """
- Thermalized bond.
-
- Parameters
- ----------
-
- temp_com : :obj:`float`
- Temperature of the Langevin thermostat for the center of mass of the
- particle pair.
- gamma_com: :obj:`float`
- Friction coefficient of the Langevin thermostat for the center of mass
- of the particle pair.
- temp_distance: :obj:`float`
- Temperature of the Langevin thermostat for the distance vector
- of the particle pair.
- gamma_distance: :obj:`float`
- Friction coefficient of the Langevin thermostat for the
- distance vector of the particle pair.
- r_cut: :obj:`float`, optional
- Maximum distance beyond which the bond is considered broken.
- seed : :obj:`int`
- Initial counter value (or seed) of the philox RNG.
- Required on the first thermalized bond in the system. Must be positive.
- If prompted, it does not return the initially set counter value
- (the seed) but the current state of the RNG.
-
- """
-
- _so_name = "Interactions::ThermalizedBond"
-
- def __init__(self, *args, **kwargs):
- counter = None
- # Interaction id as argument
- if len(args) == 2 and isinstance(args[0], (dict, int)):
- counter = args[1]
- args = (args[0],)
- super().__init__(*args, **kwargs)
- if counter is not None:
- thermalized_bond_set_rng_counter(counter)
- if self.params["seed"] is None and thermalized_bond.is_seed_required():
- raise ValueError(
- "A seed has to be given as keyword argument on first activation of the thermalized bond")
-
- def __reduce__(self):
- counter = thermalized_bond.rng_counter()
- if self._bond_id != -1:
- return (self.__class__, (self._bond_id, counter))
- else:
- return (self.__class__, (self._ctor_params, counter))
-
- def type_number(self):
- return BONDED_IA_THERMALIZED_DIST
-
- def type_name(self):
- return "THERMALIZED_DIST"
-
- def validate_params(self, params):
- if params["seed"] is not None:
- utils.check_type_or_throw_except(
- params["seed"], 1, int, "seed must be a positive integer")
- if params["seed"] < 0:
- raise ValueError("seed must be a positive integer")
-
- def get_default_params(self):
- return {"r_cut": 0., "seed": None}
-
-
-IF THOLE:
-
- cdef class TholeInteraction(NonBondedInteraction):
-
- def validate_params(self):
- pass
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params
- ia_params = get_ia_param_safe(self._part_types[0],
- self._part_types[1])
- return {
- "scaling_coeff": ia_params.thole.scaling_coeff,
- "q1q2": ia_params.thole.q1q2
- }
-
- def is_active(self):
- return (self._params["scaling_coeff"] != 0)
-
- def set_params(self, **kwargs):
- """Set parameters for the Thole interaction.
-
- Parameters
- ----------
- scaling_coeff : :obj:`float`
- The factor used in the Thole damping function between
- polarizable particles i and j. Usually calculated by
- the polarizabilities :math:`\\alpha_i`, :math:`\\alpha_j`
- and damping parameters :math:`a_i`, :math:`a_j` via
- :math:`s_{ij} = \\frac{(a_i+a_j)/2}{((\\alpha_i\\cdot\\alpha_j)^{1/2})^{1/3}}`
- q1q2: :obj:`float`
- Charge factor of the involved charges. Has to be set because
- it acts only on the portion of the Drude core charge that is
- associated to the dipole of the atom. For charged, polarizable
- atoms that charge is not equal to the particle charge property.
-
- """
- super().set_params(**kwargs)
-
- def _set_params_in_es_core(self):
- if thole_set_params(self._part_types[0], self._part_types[1],
- self._params["scaling_coeff"],
- self._params["q1q2"]):
- raise Exception("Could not set Thole parameters")
-
- def default_params(self):
- return {}
-
- def type_name(self):
- return "Thole"
-
- def valid_keys(self):
- return {"scaling_coeff", "q1q2"}
-
- def required_keys(self):
- return {"scaling_coeff", "q1q2"}
-
-
-IF BOND_CONSTRAINT == 1:
-
- @script_interface_register
- class RigidBond(BondedInteraction):
-
- """
- Rigid bond.
-
- Parameters
- ----------
- r : :obj:`float`
- Bond length.
- ptol : :obj:`float`, optional
- Tolerance for positional deviations.
- vtop : :obj:`float`, optional
- Tolerance for velocity deviations.
-
- """
-
- _so_name = "Interactions::RigidBond"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_RIGID_BOND
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "RIGID"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- # TODO rationality of Default Parameters has to be checked
- return {"ptol": 0.001, "vtol": 0.001}
-
-ELSE:
- class RigidBond(BondedInteractionNotDefined):
- name = "RIGID"
-
-
-@script_interface_register
-class Dihedral(BondedInteraction):
-
- """
- Dihedral potential with phase shift.
-
- Parameters
- ----------
- mult : :obj:`int`
- Multiplicity of the potential (number of minima).
- bend : :obj:`float`
- Bending constant.
- phase : :obj:`float`
- Angle of the first local minimum in radians.
-
- """
-
- _so_name = "Interactions::DihedralBond"
-
- def type_number(self):
- return BONDED_IA_DIHEDRAL
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "DIHEDRAL"
-
- def validate_params(self, params):
- """Check that parameters are valid.
-
- """
- if params["mult"] is not None:
- utils.check_type_or_throw_except(
- params["mult"], 1, int, "mult must be a positive integer")
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-IF TABULATED:
- class _TabulatedBase(BondedInteraction):
-
- """
- Parent class for tabulated bonds.
-
- Parameters
- ----------
-
- min : :obj:`float`
- The minimal interaction distance. Has to be 0 for angles and dihedrals.
- max : :obj:`float`
- The maximal interaction distance. Has to be pi for angles and 2pi for
- dihedrals.
- energy: array_like of :obj:`float`
- The energy table.
- force: array_like of :obj:`float`
- The force table.
-
- """
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return "BONDED_IA_TABULATED"
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "TABULATED_BOND"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
- @script_interface_register
- class TabulatedDistance(_TabulatedBase):
-
- """
- Tabulated bond length.
-
- Parameters
- ----------
-
- min : :obj:`float`
- The minimal interaction distance.
- max : :obj:`float`
- The maximal interaction distance.
- energy: array_like of :obj:`float`
- The energy table.
- force: array_like of :obj:`float`
- The force table.
-
- """
-
- _so_name = "Interactions::TabulatedDistanceBond"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_TABULATED_DISTANCE
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "TABULATED_DISTANCE"
-
- @script_interface_register
- class TabulatedAngle(_TabulatedBase):
-
- """
- Tabulated bond angle.
-
- Parameters
- ----------
-
- energy: array_like of :obj:`float`
- The energy table for the range :math:`0-\\pi`.
- force: array_like of :obj:`float`
- The force table for the range :math:`0-\\pi`.
-
- """
-
- _so_name = "Interactions::TabulatedAngleBond"
-
- pi = 3.14159265358979
-
- def __init__(self, *args, **kwargs):
- if len(args) == 0:
- kwargs.update({"min": 0., "max": self.pi})
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_TABULATED_ANGLE
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "TABULATED_ANGLE"
-
- def validate_params(self, params):
- """Check that parameters are valid.
-
- """
- phi = [params["min"], params["max"]]
- if abs(phi[0] - 0.) > 1e-5 or abs(phi[1] - self.pi) > 1e-5:
- raise ValueError(f"Tabulated angle expects forces/energies "
- f"within the range [0, pi], got {phi}")
-
- @script_interface_register
- class TabulatedDihedral(_TabulatedBase):
-
- """
- Tabulated bond dihedral.
-
- Parameters
- ----------
-
- energy: array_like of :obj:`float`
- The energy table for the range :math:`0-2\\pi`.
- force: array_like of :obj:`float`
- The force table for the range :math:`0-2\\pi`.
-
- """
-
- _so_name = "Interactions::TabulatedDihedralBond"
-
- pi = 3.14159265358979
-
- def __init__(self, *args, **kwargs):
- if len(args) == 0:
- kwargs.update({"min": 0., "max": 2. * self.pi})
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_TABULATED_DIHEDRAL
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "TABULATED_DIHEDRAL"
-
- def validate_params(self, params):
- """Check that parameters are valid.
-
- """
- phi = [params["min"], params["max"]]
- if abs(phi[0] - 0.) > 1e-5 or abs(phi[1] - 2 * self.pi) > 1e-5:
- raise ValueError(f"Tabulated dihedral expects forces/energies "
- f"within the range [0, 2*pi], got {phi}")
-
- cdef class TabulatedNonBonded(NonBondedInteraction):
-
- cdef int state
-
- def __init__(self, *args, **kwargs):
- self.state = -1
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return "TABULATED_NONBONDED"
-
- def type_name(self):
- """Name of the potential.
-
- """
- return "TABULATED"
-
- def valid_keys(self):
- """All parameters that can be set.
-
- """
- return {"min", "max", "energy", "force"}
-
- def required_keys(self):
- """Parameters that have to be set.
-
- """
- return {"min", "max", "energy", "force"}
-
- def set_params(self, **kwargs):
- """Set parameters for the TabulatedNonBonded interaction.
-
- Parameters
- ----------
-
- min : :obj:`float`,
- The minimal interaction distance.
- max : :obj:`float`,
- The maximal interaction distance.
- energy: array_like of :obj:`float`
- The energy table.
- force: array_like of :obj:`float`
- The force table.
-
- """
- super().set_params(**kwargs)
-
- def set_default_params(self):
- """Set parameters that are not required to their default value.
-
- """
- self._params = {}
-
- def _get_params_from_es_core(self):
- cdef IA_parameters * ia_params = get_ia_param_safe(
- self._part_types[0],
- self._part_types[1])
-
- return {'min': ia_params.tab.minval,
- 'max': ia_params.tab.maxval,
- 'energy': ia_params.tab.energy_tab,
- 'force': ia_params.tab.force_tab}
-
- def _set_params_in_es_core(self):
- self.state = tabulated_set_params(self._part_types[0],
- self._part_types[1],
- self._params["min"],
- self._params["max"],
- self._params["energy"],
- self._params["force"])
-
- def is_active(self):
- """Check if interaction is active.
-
- """
- return (self.state == 0)
-
-
-@script_interface_register
-class Virtual(BondedInteraction):
-
- """
- Virtual bond.
- """
-
- _so_name = "Interactions::VirtualBond"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_VIRTUAL_BOND
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "VIRTUAL"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-@script_interface_register
-class AngleHarmonic(BondedInteraction):
-
- """
- Bond-angle-dependent harmonic potential.
-
- Parameters
- ----------
- phi0 : :obj:`float`
- Equilibrium bond angle in radians.
- bend : :obj:`float`
- Magnitude of the bond interaction.
-
- """
-
- _so_name = "Interactions::AngleHarmonicBond"
-
- def type_number(self):
- return BONDED_IA_ANGLE_HARMONIC
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "ANGLE_HARMONIC"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-@script_interface_register
-class AngleCosine(BondedInteraction):
-
- """
- Bond-angle-dependent cosine potential.
-
- Parameters
- ----------
- phi0 : :obj:`float`
- Equilibrium bond angle in radians.
- bend : :obj:`float`
- Magnitude of the bond interaction.
-
- """
-
- _so_name = "Interactions::AngleCosineBond"
-
- def type_number(self):
- return BONDED_IA_ANGLE_COSINE
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "ANGLE_COSINE"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-@script_interface_register
-class AngleCossquare(BondedInteraction):
-
- """
- Bond-angle-dependent cosine squared potential.
-
- Parameters
- ----------
- phi0 : :obj:`float`
- Equilibrium bond angle in radians.
- bend : :obj:`float`
- Magnitude of the bond interaction.
-
- """
-
- _so_name = "Interactions::AngleCossquareBond"
-
- def type_number(self):
- return BONDED_IA_ANGLE_COSSQUARE
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "ANGLE_COSSQUARE"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-@script_interface_register
-class IBM_Triel(BondedInteraction):
-
- """
- IBM Triel bond.
-
- See Figure C.1 in :cite:`kruger12a`.
-
- Parameters
- ----------
- ind1, ind2, ind3 : :obj:`int`
- First, second and third bonding partner. Used for
- initializing reference state
- k1 : :obj:`float`
- Shear elasticity for Skalak and Neo-Hookean
- k2 : :obj:`float`, optional
- Area resistance for Skalak
- maxDist : :obj:`float`
- Gives an error if an edge becomes longer than maxDist
- elasticLaw : :obj:`str`, \{'NeoHookean', 'Skalak'\}
- Type of elastic bond
-
- """
-
- _so_name = "Interactions::IBMTriel"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_IBM_TRIEL
-
- def type_name(self):
- return "IBM_Triel"
-
- def valid_keys(self):
- return {"ind1", "ind2", "ind3", "k1", "k2", "maxDist", "elasticLaw"}
-
- def validate_params(self, params):
- """Check that parameters are valid.
-
- """
- if params['elasticLaw'] not in {'NeoHookean', 'Skalak'}:
- raise ValueError(f"Unknown elasticLaw: '{params['elasticLaw']}'")
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {"k2": 0}
-
- def _get_params_from_es_core(self):
- return \
- {"maxDist": self.maxDist,
- "k1": self.k1,
- "k2": self.k2,
- "elasticLaw": self.elasticLaw}
-
-
-@script_interface_register
-class IBM_Tribend(BondedInteraction):
-
- """
- IBM Tribend bond.
-
- See Figure C.2 in :cite:`kruger12a`.
-
- Parameters
- ----------
- ind1, ind2, ind3, ind4 : :obj:`int`
- First, second, third and fourth bonding partner. Used for
- initializing reference state
- kb : :obj:`float`
- Bending modulus
- refShape : :obj:`str`, optional, \{'Flat', 'Initial'\}
- Reference shape, default is ``'Flat'``
-
- """
-
- _so_name = "Interactions::IBMTribend"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_IBM_TRIBEND
-
- def type_name(self):
- return "IBM_Tribend"
-
- def valid_keys(self):
- return {"ind1", "ind2", "ind3", "ind4", "kb", "refShape"}
-
- def validate_params(self, params):
- """Check that parameters are valid.
-
- """
- if params['refShape'] not in {'Flat', 'Initial'}:
- raise ValueError(f"Unknown refShape: '{params['refShape']}'")
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {"refShape": "Flat"}
-
- def _get_params_from_es_core(self):
- return {"kb": self.kb, "theta0": self.theta0,
- "refShape": self.refShape}
-
-
-@script_interface_register
-class IBM_VolCons(BondedInteraction):
-
- """
- IBM volume conservation bond.
-
- See Figure C.3 in :cite:`kruger12a`.
-
- Parameters
- ----------
- softID : :obj:`int`
- Used to identify the object to which this bond belongs. Each object
- (cell) needs its own ID. For performance reasons, it is best to
- start from ``softID=0`` and increment by 1 for each subsequent bond.
- kappaV : :obj:`float`
- Modulus for volume force
-
- """
-
- _so_name = "Interactions::IBMVolCons"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_IBM_VOLUME_CONSERVATION
-
- def type_name(self):
- return "IBM_VolCons"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
- def current_volume(self):
- """
- Query the current volume of the soft object associated to this bond.
- The volume is initialized once all :class:`IBM_Triel` bonds have
- been added and the forces have been recalculated.
- """
- return immersed_boundaries.get_current_volume(self.softID)
-
-
-@script_interface_register
-class OifGlobalForces(BondedInteraction):
-
- """
- Characterize the distribution of the force of the global mesh deformation
- onto individual vertices of the mesh.
-
- Part of the :ref:`Object-in-fluid` method.
-
- Parameters
- ----------
- A0_g : :obj:`float`
- Relaxed area of the mesh
- ka_g : :obj:`float`
- Area coefficient
- V0 : :obj:`float`
- Relaxed volume of the mesh
- kv : :obj:`float`
- Volume coefficient
-
- """
-
- _so_name = "Interactions::OifGlobalForcesBond"
-
- def type_number(self):
- return BONDED_IA_OIF_GLOBAL_FORCES
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "OIF_GLOBAL_FORCES"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-@script_interface_register
-class OifLocalForces(BondedInteraction):
-
- """
- Characterize the deformation of two triangles sharing an edge.
-
- Part of the :ref:`Object-in-fluid` method.
-
- Parameters
- ----------
- r0 : :obj:`float`
- Equilibrium bond length of triangle edges
- ks : :obj:`float`
- Non-linear stretching coefficient of triangle edges
- kslin : :obj:`float`
- Linear stretching coefficient of triangle edges
- phi0 : :obj:`float`
- Equilibrium angle between the two triangles
- kb : :obj:`float`
- Bending coefficient for the angle between the two triangles
- A01 : :obj:`float`
- Equilibrium surface of the first triangle
- A02 : :obj:`float`
- Equilibrium surface of the second triangle
- kal : :obj:`float`
- Stretching coefficient of a triangle surface
- kvisc : :obj:`float`
- Viscous coefficient of the triangle vertices
-
- """
-
- _so_name = "Interactions::OifLocalForcesBond"
-
- def type_number(self):
- return BONDED_IA_OIF_LOCAL_FORCES
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "OIF_LOCAL_FORCES"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-@script_interface_register
-class QuarticBond(BondedInteraction):
-
- """
- Quartic bond.
-
- Parameters
- ----------
- k0 : :obj:`float`
- Magnitude of the square term.
- k1 : :obj:`float`
- Magnitude of the fourth order term.
- r : :obj:`float`
- Equilibrium bond length.
- r_cut : :obj:`float`
- Maximum interaction length.
- """
-
- _so_name = "Interactions::QuarticBond"
-
- def __init__(self, *args, **kwargs):
- super().__init__(*args, **kwargs)
-
- def type_number(self):
- return BONDED_IA_QUARTIC
-
- def type_name(self):
- """Name of interaction type.
-
- """
- return "QUARTIC"
-
- def get_default_params(self):
- """Gets default values of optional parameters.
-
- """
- return {}
-
-
-bonded_interaction_classes = {
- int(BONDED_IA_FENE): FeneBond,
- int(BONDED_IA_HARMONIC): HarmonicBond,
- int(BONDED_IA_RIGID_BOND): RigidBond,
- int(BONDED_IA_DIHEDRAL): Dihedral,
- int(BONDED_IA_VIRTUAL_BOND): Virtual,
- int(BONDED_IA_ANGLE_HARMONIC): AngleHarmonic,
- int(BONDED_IA_ANGLE_COSINE): AngleCosine,
- int(BONDED_IA_ANGLE_COSSQUARE): AngleCossquare,
- int(BONDED_IA_OIF_GLOBAL_FORCES): OifGlobalForces,
- int(BONDED_IA_OIF_LOCAL_FORCES): OifLocalForces,
- int(BONDED_IA_IBM_TRIEL): IBM_Triel,
- int(BONDED_IA_IBM_TRIBEND): IBM_Tribend,
- int(BONDED_IA_IBM_VOLUME_CONSERVATION): IBM_VolCons,
- int(BONDED_IA_THERMALIZED_DIST): ThermalizedBond,
- int(BONDED_IA_QUARTIC): QuarticBond,
-}
-IF ELECTROSTATICS:
- bonded_interaction_classes[int(BONDED_IA_BONDED_COULOMB)] = BondedCoulomb
- bonded_interaction_classes[
- int(BONDED_IA_BONDED_COULOMB_SR)] = BondedCoulombSRBond
-IF TABULATED:
- bonded_interaction_classes[
- int(BONDED_IA_TABULATED_DISTANCE)] = TabulatedDistance
- bonded_interaction_classes[
- int(BONDED_IA_TABULATED_ANGLE)] = TabulatedAngle
- bonded_interaction_classes[
- int(BONDED_IA_TABULATED_DIHEDRAL)] = TabulatedDihedral
-
-
-def get_bonded_interaction_type_from_es_core(bond_id):
- return < enum_bonded_interaction > bonded_ia_params_zero_based_type(bond_id)
-
-
-@script_interface_register
-class BondedInteractions(ScriptObjectMap):
-
- """
- Represents the bonded interactions list.
-
- Individual interactions can be accessed using ``BondedInteractions[i]``,
- where ``i`` is the bond id.
-
- Methods
- -------
- remove()
- Remove a bond from the list.
- This is a no-op if the bond does not exist.
-
- Parameters
- ----------
- bond_id : :obj:`int`
-
- clear()
- Remove all bonds.
-
- """
-
- _so_name = "Interactions::BondedInteractions"
- _so_creation_policy = "GLOBAL"
-
- def add(self, *args, **kwargs):
- """
- Add a bond to the list.
-
- Parameters
- ----------
- bond: :class:`espressomd.interactions.BondedInteraction`
- Either a bond object...
- \*\*kwargs : any
- ... or parameters to construct a
- :class:`~espressomd.interactions.BondedInteraction` object
-
- """
-
- if len(args) == 1 and isinstance(args[0], BondedInteraction):
- bonded_ia = args[0]
- else:
- raise TypeError("A BondedInteraction object needs to be passed.")
- bond_id = self._insert_bond(None, bonded_ia)
- return bond_id
-
- def __getitem__(self, bond_id):
- self._assert_key_type(bond_id)
-
- if self.call_method('has_bond', bond_id=bond_id):
- bond_obj = self.call_method('get_bond', bond_id=bond_id)
- bond_obj._bond_id = bond_id
- return bond_obj
-
- # Find out the type of the interaction from ESPResSo
- bond_type = get_bonded_interaction_type_from_es_core(bond_id)
-
- # Check if the bonded interaction exists in ESPResSo core
- if bond_type == BONDED_IA_NONE:
- raise ValueError(f"The bond with id {bond_id} is not yet defined.")
-
- # Find the appropriate class representing such a bond
- bond_class = bonded_interaction_classes[bond_type]
-
- # Create a new script interface object (i.e. a copy of the shared_ptr)
- # which links to the bonded interaction object
- return bond_class(bond_id)
-
- def __setitem__(self, bond_id, bond_obj):
- self._insert_bond(bond_id, bond_obj)
-
- def _insert_bond(self, bond_id, bond_obj):
- """
- Inserts a new bond. If a ``bond_id`` is given, the bond is inserted at
- that id. If no id is given, a new id is generated.
-
- Bonds can only be overwritten if the new bond is of the same type as the
- old one, e.g. a :class:`~espressomd.interactions.FeneBond` bond can only
- be overwritten by another :class:`~espressomd.interactions.FeneBond` bond.
- """
-
- # Validate arguments
- if not isinstance(bond_obj, BondedInteraction):
- raise ValueError(
- "Only subclasses of BondedInteraction can be assigned.")
-
- # Send the script interface object pointer to the core
- if bond_id is None:
- bond_id = self.call_method("insert", object=bond_obj)
- else:
- # Throw error if attempting to overwrite a bond of different type
- self._assert_key_type(bond_id)
- if self.call_method("contains", key=bond_id):
- old_type = bonded_interaction_classes[
- get_bonded_interaction_type_from_es_core(bond_id)]
- if not type(bond_obj) is old_type:
- raise ValueError(
- "Bonds can only be overwritten by bonds of equal type.")
- self.call_method("insert", key=bond_id, object=bond_obj)
-
- # Save the bond id in the BondedInteraction instance
- bond_obj._bond_id = bond_id
-
- return bond_id
-
- def __len__(self):
- return self.call_method('get_size')
-
- # Support iteration over active bonded interactions
- def __iter__(self):
- for bond_id in self.call_method('get_bond_ids'):
- if get_bonded_interaction_type_from_es_core(bond_id):
- yield self[bond_id]
-
- def __getstate__(self):
- params = {}
- for bond_id in self.call_method('get_bond_ids'):
- if get_bonded_interaction_type_from_es_core(bond_id):
- bond_obj = self[bond_id]
- if hasattr(bond_obj, 'params'):
- params[bond_id] = (
- bond_obj._ctor_params, bond_obj.type_number())
- return params
-
- def __setstate__(self, params):
- for bond_id, (bond_params, bond_type) in params.items():
- self[bond_id] = bonded_interaction_classes[bond_type](
- **bond_params)
diff --git a/src/python/espressomd/script_interface.pyx b/src/python/espressomd/script_interface.pyx
index 67a9151e658..176beea6185 100644
--- a/src/python/espressomd/script_interface.pyx
+++ b/src/python/espressomd/script_interface.pyx
@@ -136,7 +136,7 @@ cdef class PScriptInterface:
self.sip = sip
- def call_method(self, method, **kwargs):
+ def call_method(self, method, handle_errors_message=None, **kwargs):
"""
Call a method of the core class.
@@ -144,6 +144,8 @@ cdef class PScriptInterface:
----------
method : Creation policy.
Name of the core method.
+ handle_errors_message : :obj:`str`, optional
+ Custom error message for runtime errors raised in a MPI context.
\*\*kwargs
Arguments for the method.
"""
@@ -156,7 +158,9 @@ cdef class PScriptInterface:
value = self.sip.get().call_method(utils.to_char_pointer(method), parameters)
res = variant_to_python_object(value)
- utils.handle_errors(f'while calling method {method}()')
+ if handle_errors_message is None:
+ handle_errors_message = f"while calling method {method}()"
+ utils.handle_errors(handle_errors_message)
return res
def name(self):
diff --git a/src/script_interface/Context.hpp b/src/script_interface/Context.hpp
index 6a979517c1c..a4640439e71 100644
--- a/src/script_interface/Context.hpp
+++ b/src/script_interface/Context.hpp
@@ -87,6 +87,12 @@ class Context : public std::enable_shared_from_this {
virtual std::shared_ptr
make_shared(std::string const &name, const VariantMap ¶meters) = 0;
+ /**
+ * @copydoc Context::make_shared
+ */
+ virtual std::shared_ptr
+ make_shared_local(std::string const &name, VariantMap const ¶meters) = 0;
+
protected:
/**
* @brief Set the context of an object to this.
diff --git a/src/script_interface/GlobalContext.cpp b/src/script_interface/GlobalContext.cpp
index ed22422e782..c4859b71be9 100644
--- a/src/script_interface/GlobalContext.cpp
+++ b/src/script_interface/GlobalContext.cpp
@@ -88,10 +88,22 @@ void GlobalContext::notify_call_method(const ObjectHandle *o,
cb_call_method(object_id(o), name, pack(arguments));
}
+std::shared_ptr
+GlobalContext::make_shared_local(std::string const &name,
+ VariantMap const ¶meters) {
+ auto sp = m_node_local_context->factory().make(name);
+ set_context(sp.get());
+
+ sp->construct(parameters);
+
+ return sp;
+}
+
std::shared_ptr
GlobalContext::make_shared(std::string const &name,
const VariantMap ¶meters) {
- std::unique_ptr sp = m_node_local_context->factory().make(name);
+ assert(is_head_node());
+ auto sp = m_node_local_context->factory().make(name);
set_context(sp.get());
auto const id = object_id(sp.get());
diff --git a/src/script_interface/GlobalContext.hpp b/src/script_interface/GlobalContext.hpp
index 03f2d0dc329..090c811ef5e 100644
--- a/src/script_interface/GlobalContext.hpp
+++ b/src/script_interface/GlobalContext.hpp
@@ -165,6 +165,9 @@ class GlobalContext : public Context {
*/
std::shared_ptr
make_shared(std::string const &name, const VariantMap ¶meters) override;
+ std::shared_ptr
+ make_shared_local(std::string const &name,
+ VariantMap const ¶meters) override;
boost::string_ref name(const ObjectHandle *o) const override;
diff --git a/src/script_interface/LocalContext.hpp b/src/script_interface/LocalContext.hpp
index 11a79a7a2fb..9f528812533 100644
--- a/src/script_interface/LocalContext.hpp
+++ b/src/script_interface/LocalContext.hpp
@@ -71,6 +71,12 @@ class LocalContext : public Context {
return sp;
}
+ std::shared_ptr
+ make_shared_local(std::string const &name,
+ VariantMap const ¶meters) override {
+ return make_shared(name, parameters);
+ }
+
boost::string_ref name(const ObjectHandle *o) const override {
assert(o);
diff --git a/src/script_interface/analysis/ObservableStat.cpp b/src/script_interface/analysis/ObservableStat.cpp
index c5a0d61ae64..130185f6376 100644
--- a/src/script_interface/analysis/ObservableStat.cpp
+++ b/src/script_interface/analysis/ObservableStat.cpp
@@ -21,8 +21,7 @@
#include "ObservableStat.hpp"
-#include "script_interface/interactions/bonded.hpp"
-
+#include "core/bonded_interactions/bonded_interaction_data.hpp"
#include "core/nonbonded_interactions/nonbonded_interaction_data.hpp"
#include "core/energy.hpp"
@@ -86,7 +85,7 @@ static auto get_summary(Observable_stat const &obs, bool const calc_sp) {
auto const n_bonds = ::bonded_ia_params.get_next_key();
for (std::size_t bond_id = 0; bond_id < n_bonds; ++bond_id) {
- if (bonded_ia_params_zero_based_type(bond_id) != 0) {
+ if (::bonded_ia_params.get_zero_based_type(bond_id) != 0) {
dict["bonded," + std::to_string(bond_id)] =
get_obs_contrib(obs.bonded_contribution(bond_id));
}
diff --git a/src/script_interface/interactions/BondedInteraction.hpp b/src/script_interface/interactions/BondedInteraction.hpp
index 787a8b57a17..46c8b752d6c 100644
--- a/src/script_interface/interactions/BondedInteraction.hpp
+++ b/src/script_interface/interactions/BondedInteraction.hpp
@@ -27,7 +27,9 @@
#define SCRIPT_INTERFACE_INTERACTIONS_BONDED_INTERACTION_HPP
#include "core/bonded_interactions/bonded_interaction_data.hpp"
+#include "core/immersed_boundaries.hpp"
#include "core/thermostat.hpp"
+
#include "script_interface/ScriptInterface.hpp"
#include "script_interface/auto_parameters/AutoParameters.hpp"
#include "script_interface/get_value.hpp"
@@ -35,9 +37,14 @@
#include
#include
+#include
+#include
#include
#include
+#include
+#include
#include
+#include
#include
#include
#include
@@ -45,7 +52,7 @@
namespace ScriptInterface {
namespace Interactions {
-template class BondedInteractionInterface {
+class BondedInteraction : public AutoParameters {
protected:
std::shared_ptr<::Bonded_IA_Parameters> m_bonded_ia;
@@ -54,45 +61,93 @@ template class BondedInteractionInterface {
std::shared_ptr bonded_ia() const {
return m_bonded_ia;
}
-};
-class BondedInteraction : public AutoParameters,
- public BondedInteractionInterface {
+protected:
+ using AutoParameters::context;
+ using AutoParameters::valid_parameters;
+
+ virtual std::set get_valid_parameters() const {
+ auto const vec = valid_parameters();
+ auto valid_keys = std::set();
+ std::transform(vec.begin(), vec.end(),
+ std::inserter(valid_keys, valid_keys.begin()),
+ [](auto const &key) { return std::string{key}; });
+ return valid_keys;
+ }
+
+private:
+ void check_valid_parameters(VariantMap const ¶ms) const {
+ auto const valid_keys = get_valid_parameters();
+ for (auto const &key : valid_keys) {
+ if (params.count(std::string(key)) == 0) {
+ throw std::runtime_error("Parameter '" + key + "' is missing");
+ }
+ }
+ for (auto const &kv : params) {
+ if (valid_keys.count(kv.first) == 0) {
+ throw std::runtime_error("Parameter '" + kv.first +
+ "' is not recognized");
+ }
+ }
+ }
+
void do_construct(VariantMap const ¶ms) override {
// Check if initialization "by id" or "by parameters"
if (params.find("bond_id") != params.end()) {
- m_bonded_ia = ::bonded_ia_params.at(get_value(params, "bond_id"));
+ auto const bond_id = get_value(params, "bond_id");
+ context()->parallel_try_catch([&]() {
+ if (not::bonded_ia_params.contains(bond_id)) {
+ throw std::runtime_error("No bond with id " +
+ std::to_string(bond_id) +
+ " exists in the ESPResSo core");
+ }
+ });
+ m_bonded_ia = ::bonded_ia_params.at(bond_id);
} else {
- construct_bond(params);
+ context()->parallel_try_catch([&]() {
+ check_valid_parameters(params);
+ construct_bond(params);
+ });
}
}
-private:
- virtual void construct_bond(VariantMap const ¶ms) {}
+ virtual void construct_bond(VariantMap const ¶ms) = 0;
public:
- template
- bool operator==(const BondedInteractionInterface &other) {
+ bool operator==(BondedInteraction const &other) {
return m_bonded_ia == other.m_bonded_ia;
}
Variant do_call_method(std::string const &name,
VariantMap const ¶ms) override {
// this feature is needed to compare bonds
- if (name == "get_address") {
- return reinterpret_cast(bonded_ia().get());
+ if (name == "is_same_bond") {
+ auto const bond_so =
+ get_value>(params, "bond");
+ return *this == *bond_so;
}
if (name == "get_num_partners") {
return number_of_partners(*bonded_ia());
}
+ if (name == "get_zero_based_type") {
+ auto const bond_id = get_value(params, "bond_id");
+ return ::bonded_ia_params.get_zero_based_type(bond_id);
+ }
return {};
}
};
-class FeneBond : public BondedInteraction {
- using CoreBondedInteraction = ::FeneBond;
+template class BondedInteractionImpl : public BondedInteraction {
+public:
+ using CoreBondedInteraction = CoreIA;
+ CoreBondedInteraction &get_struct() {
+ return boost::get(*bonded_ia());
+ }
+};
+
+class FeneBond : public BondedInteractionImpl<::FeneBond> {
public:
FeneBond() {
add_parameters({
@@ -110,15 +165,9 @@ class FeneBond : public BondedInteraction {
get_value(params, "d_r_max"),
get_value(params, "r_0")));
}
-
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
};
-class HarmonicBond : public BondedInteraction {
- using CoreBondedInteraction = ::HarmonicBond;
-
+class HarmonicBond : public BondedInteractionImpl<::HarmonicBond> {
public:
HarmonicBond() {
add_parameters({
@@ -136,15 +185,9 @@ class HarmonicBond : public BondedInteraction {
get_value(params, "k"), get_value(params, "r_0"),
get_value(params, "r_cut")));
}
-
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
};
-class QuarticBond : public BondedInteraction {
- using CoreBondedInteraction = ::QuarticBond;
-
+class QuarticBond : public BondedInteractionImpl<::QuarticBond> {
public:
QuarticBond() {
add_parameters({
@@ -164,15 +207,9 @@ class QuarticBond : public BondedInteraction {
get_value(params, "r"),
get_value(params, "r_cut")));
}
-
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
};
-class BondedCoulomb : public BondedInteraction {
- using CoreBondedInteraction = ::BondedCoulomb;
-
+class BondedCoulomb : public BondedInteractionImpl<::BondedCoulomb> {
public:
BondedCoulomb() {
add_parameters({
@@ -181,10 +218,6 @@ class BondedCoulomb : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia = std::make_shared<::Bonded_IA_Parameters>(
@@ -192,9 +225,7 @@ class BondedCoulomb : public BondedInteraction {
}
};
-class BondedCoulombSR : public BondedInteraction {
- using CoreBondedInteraction = ::BondedCoulombSR;
-
+class BondedCoulombSR : public BondedInteractionImpl<::BondedCoulombSR> {
public:
BondedCoulombSR() {
add_parameters({
@@ -203,10 +234,6 @@ class BondedCoulombSR : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia = std::make_shared<::Bonded_IA_Parameters>(
@@ -214,9 +241,7 @@ class BondedCoulombSR : public BondedInteraction {
}
};
-class AngleHarmonicBond : public BondedInteraction {
- using CoreBondedInteraction = ::AngleHarmonicBond;
-
+class AngleHarmonicBond : public BondedInteractionImpl<::AngleHarmonicBond> {
public:
AngleHarmonicBond() {
add_parameters({
@@ -227,10 +252,6 @@ class AngleHarmonicBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia = std::make_shared<::Bonded_IA_Parameters>(
@@ -239,9 +260,7 @@ class AngleHarmonicBond : public BondedInteraction {
}
};
-class AngleCosineBond : public BondedInteraction {
- using CoreBondedInteraction = ::AngleCosineBond;
-
+class AngleCosineBond : public BondedInteractionImpl<::AngleCosineBond> {
public:
AngleCosineBond() {
add_parameters({
@@ -252,10 +271,6 @@ class AngleCosineBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia = std::make_shared<::Bonded_IA_Parameters>(
@@ -264,9 +279,7 @@ class AngleCosineBond : public BondedInteraction {
}
};
-class AngleCossquareBond : public BondedInteraction {
- using CoreBondedInteraction = ::AngleCossquareBond;
-
+class AngleCossquareBond : public BondedInteractionImpl<::AngleCossquareBond> {
public:
AngleCossquareBond() {
add_parameters({
@@ -277,10 +290,6 @@ class AngleCossquareBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia = std::make_shared<::Bonded_IA_Parameters>(
@@ -289,9 +298,7 @@ class AngleCossquareBond : public BondedInteraction {
}
};
-class DihedralBond : public BondedInteraction {
- using CoreBondedInteraction = ::DihedralBond;
-
+class DihedralBond : public BondedInteractionImpl<::DihedralBond> {
public:
DihedralBond() {
add_parameters({
@@ -304,10 +311,6 @@ class DihedralBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -317,9 +320,8 @@ class DihedralBond : public BondedInteraction {
}
};
-class TabulatedDistanceBond : public BondedInteraction {
- using CoreBondedInteraction = ::TabulatedDistanceBond;
-
+class TabulatedDistanceBond
+ : public BondedInteractionImpl<::TabulatedDistanceBond> {
public:
TabulatedDistanceBond() {
add_parameters({
@@ -334,10 +336,6 @@ class TabulatedDistanceBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -348,9 +346,7 @@ class TabulatedDistanceBond : public BondedInteraction {
}
};
-class TabulatedAngleBond : public BondedInteraction {
- using CoreBondedInteraction = ::TabulatedAngleBond;
-
+class TabulatedAngleBond : public BondedInteractionImpl<::TabulatedAngleBond> {
public:
TabulatedAngleBond() {
add_parameters({
@@ -365,10 +361,6 @@ class TabulatedAngleBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -379,9 +371,8 @@ class TabulatedAngleBond : public BondedInteraction {
}
};
-class TabulatedDihedralBond : public BondedInteraction {
- using CoreBondedInteraction = ::TabulatedDihedralBond;
-
+class TabulatedDihedralBond
+ : public BondedInteractionImpl<::TabulatedDihedralBond> {
public:
TabulatedDihedralBond() {
add_parameters({
@@ -396,10 +387,6 @@ class TabulatedDihedralBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -410,9 +397,7 @@ class TabulatedDihedralBond : public BondedInteraction {
}
};
-class ThermalizedBond : public BondedInteraction {
- using CoreBondedInteraction = ::ThermalizedBond;
-
+class ThermalizedBond : public BondedInteractionImpl<::ThermalizedBond> {
public:
ThermalizedBond() {
add_parameters({
@@ -431,8 +416,15 @@ class ThermalizedBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
+ Variant do_call_method(std::string const &name,
+ VariantMap const ¶ms) override {
+ if (name == "get_rng_state") {
+ auto const state = ::thermalized_bond.rng_counter();
+ // check it's safe to forward the current state as an integer
+ assert(state < static_cast(std::numeric_limits::max()));
+ return static_cast(state);
+ }
+ return BondedInteraction::do_call_method(name, params);
}
private:
@@ -443,14 +435,37 @@ class ThermalizedBond : public BondedInteraction {
get_value(params, "temp_distance"),
get_value(params, "gamma_distance"),
get_value(params, "r_cut")));
- thermalized_bond.rng_initialize(
- static_cast(get_value(params, "seed")));
+
+ if (is_none(params.at("seed"))) {
+ if (::thermalized_bond.is_seed_required()) {
+ throw std::invalid_argument("A parameter 'seed' has to be given on "
+ "first activation of a thermalized bond");
+ }
+ } else {
+ auto const seed = get_value(params, "seed");
+ if (seed < 0) {
+ throw std::domain_error("Parameter 'seed' must be >= 0");
+ }
+ ::thermalized_bond.rng_initialize(static_cast(seed));
+ }
+
+ // handle checkpointing
+ if (params.count("rng_state") and not is_none(params.at("rng_state"))) {
+ auto const state = get_value(params, "rng_state");
+ assert(state >= 0);
+ ::thermalized_bond.set_rng_counter(static_cast(state));
+ }
}
-};
-class RigidBond : public BondedInteraction {
- using CoreBondedInteraction = ::RigidBond;
+ std::set get_valid_parameters() const override {
+ auto names =
+ BondedInteractionImpl::get_valid_parameters();
+ names.insert("rng_state");
+ return names;
+ }
+};
+class RigidBond : public BondedInteractionImpl<::RigidBond> {
public:
RigidBond() {
add_parameters({
@@ -463,10 +478,6 @@ class RigidBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -476,17 +487,7 @@ class RigidBond : public BondedInteraction {
}
};
-class IBMTriel : public BondedInteraction {
- using CoreBondedInteraction = ::IBMTriel;
-
-private:
- tElasticLaw str2elastic_law(std::string el) {
- if (boost::iequals(el, "NeoHookean")) {
- return tElasticLaw::NeoHookean;
- }
- return tElasticLaw::Skalak;
- }
-
+class IBMTriel : public BondedInteractionImpl<::IBMTriel> {
public:
IBMTriel() {
add_parameters({
@@ -504,25 +505,37 @@ class IBMTriel : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
+ auto const law_name = get_value(params, "elasticLaw");
+ tElasticLaw elastic_law;
+ if (law_name == "NeoHookean") {
+ elastic_law = tElasticLaw::NeoHookean;
+ } else if (law_name == "Skalak") {
+ elastic_law = tElasticLaw::Skalak;
+ } else {
+ throw std::invalid_argument(
+ "Invalid value for parameter 'elasticLaw': '" + law_name + "'");
+ }
m_bonded_ia =
std::make_shared<::Bonded_IA_Parameters>(CoreBondedInteraction(
get_value(params, "ind1"), get_value(params, "ind2"),
get_value(params, "ind3"),
- get_value(params, "maxDist"),
- str2elastic_law(get_value(params, "elasticLaw")),
+ get_value(params, "maxDist"), elastic_law,
get_value(params, "k1"), get_value(params, "k2")));
}
-};
-class IBMVolCons : public BondedInteraction {
- using CoreBondedInteraction = ::IBMVolCons;
+ std::set get_valid_parameters() const override {
+ auto names =
+ BondedInteractionImpl::get_valid_parameters();
+ names.insert("ind1");
+ names.insert("ind2");
+ names.insert("ind3");
+ return names;
+ }
+};
+class IBMVolCons : public BondedInteractionImpl<::IBMVolCons> {
public:
IBMVolCons() {
add_parameters({
@@ -533,8 +546,12 @@ class IBMVolCons : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
+ Variant do_call_method(std::string const &name,
+ VariantMap const ¶ms) override {
+ if (name == "current_volume") {
+ return ::immersed_boundaries.get_current_volume(get_struct().softID);
+ }
+ return BondedInteraction::do_call_method(name, params);
}
private:
@@ -545,9 +562,7 @@ class IBMVolCons : public BondedInteraction {
}
};
-class IBMTribend : public BondedInteraction {
- using CoreBondedInteraction = ::IBMTribend;
-
+class IBMTribend : public BondedInteractionImpl<::IBMTribend> {
public:
IBMTribend() {
add_parameters({
@@ -561,26 +576,39 @@ class IBMTribend : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
bool m_flat;
void construct_bond(VariantMap const ¶ms) override {
- auto const &refShape = get_value(params, "refShape");
- m_flat = boost::iequals(refShape, "Flat");
+ auto const shape_name = get_value(params, "refShape");
+ if (shape_name == "Flat") {
+ m_flat = true;
+ } else if (shape_name == "Initial") {
+ m_flat = false;
+ } else {
+ throw std::invalid_argument("Invalid value for parameter 'refShape': '" +
+ shape_name + "'");
+ }
m_bonded_ia =
std::make_shared<::Bonded_IA_Parameters>(CoreBondedInteraction(
get_value(params, "ind1"), get_value(params, "ind2"),
get_value(params, "ind3"), get_value(params, "ind4"),
get_value(params, "kb"), m_flat));
}
-};
-class OifGlobalForcesBond : public BondedInteraction {
- using CoreBondedInteraction = ::OifGlobalForcesBond;
+ std::set get_valid_parameters() const override {
+ auto names =
+ BondedInteractionImpl::get_valid_parameters();
+ names.erase("theta0");
+ names.insert("ind1");
+ names.insert("ind2");
+ names.insert("ind3");
+ names.insert("ind4");
+ return names;
+ }
+};
+class OifGlobalForcesBond
+ : public BondedInteractionImpl<::OifGlobalForcesBond> {
public:
OifGlobalForcesBond() {
add_parameters({
@@ -593,10 +621,6 @@ class OifGlobalForcesBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -607,9 +631,7 @@ class OifGlobalForcesBond : public BondedInteraction {
}
};
-class OifLocalForcesBond : public BondedInteraction {
- using CoreBondedInteraction = ::OifLocalForcesBond;
-
+class OifLocalForcesBond : public BondedInteractionImpl<::OifLocalForcesBond> {
public:
OifLocalForcesBond() {
add_parameters({
@@ -631,10 +653,6 @@ class OifLocalForcesBond : public BondedInteraction {
});
}
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
-
private:
void construct_bond(VariantMap const ¶ms) override {
m_bonded_ia =
@@ -648,19 +666,15 @@ class OifLocalForcesBond : public BondedInteraction {
}
};
-class VirtualBond : public BondedInteraction {
- using CoreBondedInteraction = ::VirtualBond;
-
+class VirtualBond : public BondedInteractionImpl<::VirtualBond> {
public:
VirtualBond() {
m_bonded_ia =
std::make_shared<::Bonded_IA_Parameters>(CoreBondedInteraction());
}
-public:
- CoreBondedInteraction &get_struct() {
- return boost::get(*bonded_ia());
- }
+private:
+ void construct_bond(VariantMap const &) override {}
};
} // namespace Interactions
diff --git a/src/script_interface/interactions/BondedInteractions.hpp b/src/script_interface/interactions/BondedInteractions.hpp
index 047c13aaa7d..fe92ef1e196 100644
--- a/src/script_interface/interactions/BondedInteractions.hpp
+++ b/src/script_interface/interactions/BondedInteractions.hpp
@@ -96,6 +96,11 @@ class BondedInteractions : public ObjectMap {
return {m_bonds.at(bond_id)};
}
+ if (name == "get_zero_based_type") {
+ auto const bond_id = get_value(params, "bond_id");
+ return ::bonded_ia_params.get_zero_based_type(bond_id);
+ }
+
return ObjectMap::do_call_method(name, params);
}
diff --git a/src/script_interface/interactions/NonBondedInteraction.hpp b/src/script_interface/interactions/NonBondedInteraction.hpp
new file mode 100644
index 00000000000..6ed08ce4906
--- /dev/null
+++ b/src/script_interface/interactions/NonBondedInteraction.hpp
@@ -0,0 +1,976 @@
+/*
+ * Copyright (C) 2022 The ESPResSo project
+ *
+ * This file is part of ESPResSo.
+ *
+ * ESPResSo is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * ESPResSo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+/** @file
+ * The ScriptInterface counterparts of the non-bonded interactions parameters
+ * structs from the core are defined here.
+ */
+
+#ifndef SCRIPT_INTERFACE_INTERACTIONS_NONBONDED_INTERACTION_HPP
+#define SCRIPT_INTERFACE_INTERACTIONS_NONBONDED_INTERACTION_HPP
+
+#include "script_interface/ScriptInterface.hpp"
+#include "script_interface/auto_parameters/AutoParameters.hpp"
+#include "script_interface/get_value.hpp"
+
+#include "core/event.hpp"
+#include "core/nonbonded_interactions/nonbonded_interaction_data.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace ScriptInterface {
+namespace Interactions {
+
+template
+class InteractionPotentialInterface
+ : public AutoParameters> {
+ /** @brief Particle type pair. */
+ std::array m_types = {-1, -1};
+
+public:
+ using CoreInteraction = CoreIA;
+
+protected:
+ using AutoParameters>::context;
+ using AutoParameters