Source code for espressomd.magnetostatics

#
# 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 <http://www.gnu.org/licenses/>.
#

from . import utils
from .script_interface import ScriptInterfaceHelper, script_interface_register
from .code_features import has_features


[docs]class MagnetostaticInteraction(ScriptInterfaceHelper): """ Common interface for magnetostatics solvers. Parameters ---------- prefactor : :obj:`float` Magnetostatics prefactor :math:`\\frac{\\mu_0\\mu}{4\\pi}` """ _so_creation_policy = "GLOBAL" def __init__(self, **kwargs): self._check_required_features() if 'sip' not in kwargs: for key in self.required_keys(): if key not in kwargs: raise RuntimeError(f"Parameter '{key}' is missing") utils.check_required_keys(self.required_keys(), kwargs.keys()) params = self.default_params() params.update(kwargs) self.validate_params(params) super().__init__(**params) for key in params: if key not in self._valid_parameters(): raise RuntimeError( f"Parameter '{key}' is not a valid parameter") else: super().__init__(**kwargs) def _check_required_features(self): if not has_features("DIPOLES"): raise NotImplementedError("Feature DIPOLES not compiled in")
[docs] def validate_params(self, params): """Check validity of given parameters. """ utils.check_type_or_throw_except( params["prefactor"], 1, float, "Parameter 'prefactor' should be a float")
[docs] def default_params(self): raise NotImplementedError("Derived classes must implement this method")
[docs] def required_keys(self): raise NotImplementedError("Derived classes must implement this method")
def _activate(self): self.call_method("activate") utils.handle_errors("Dipolar actor activation failed") def _deactivate(self): self.call_method("deactivate") utils.handle_errors("Dipolar actor deactivation failed")
[docs] def get_magnetostatics_prefactor(self): """ Get the magnetostatics prefactor """ return self.prefactor
[docs]@script_interface_register class DipolarP3M(MagnetostaticInteraction): """ Calculate magnetostatic interactions using the dipolar P3M method. See :ref:`Dipolar P3M` for more details. Parameters ---------- prefactor : :obj:`float` Magnetostatics prefactor (:math:`\\mu_0/(4\\pi)`) accuracy : :obj:`float` P3M tunes its parameters to provide this target accuracy. alpha : :obj:`float` Ewald parameter. cao : :obj:`int` Charge-assignment order, an integer between 1 and 7. mesh : :obj:`int` or (3,) array_like of :obj:`int` The number of mesh points in x, y and z direction. Use a single value for cubic boxes. mesh_off : (3,) array_like of :obj:`float`, optional Mesh offset. r_cut : :obj:`float` Real space cutoff. tune : :obj:`bool`, optional Activate/deactivate the tuning method on activation (default is ``True``, i.e., activated). timings : :obj:`int` Number of force calculations during tuning. """ _so_name = "Dipoles::DipolarP3M" def _check_required_features(self): if not has_features("DP3M"): raise NotImplementedError("Feature DP3M not compiled in")
[docs] def validate_params(self, params): """Check validity of parameters. """ super().validate_params(params) if utils.is_valid_type(params["mesh"], int): params["mesh"] = 3 * [params["mesh"]] else: utils.check_type_or_throw_except( params["mesh"], 3, int, "Parameter 'mesh' has to be an integer or integer list of length 3") if params["epsilon"] == "metallic": params["epsilon"] = 0.0 utils.check_type_or_throw_except( params["epsilon"], 1, float, "Parameter 'epsilon' has to be a float or 'metallic'") utils.check_type_or_throw_except( params["mesh_off"], 3, float, "Parameter 'mesh_off' has to be a (3,) array_like of values between 0.0 and 1.0") if not utils.is_valid_type(params["timings"], int): raise TypeError("Parameter 'timings' has to be an integer") if not utils.is_valid_type(params["tune"], bool): raise TypeError("Parameter 'tune' has to be a boolean")
[docs] def required_keys(self): return {"accuracy"}
[docs] def default_params(self): return {"cao": -1, "r_cut": -1, "alpha": -1, "accuracy": -1, "mesh": [-1, -1, -1], "epsilon": 0.0, "mesh_off": [0.5, 0.5, 0.5], "prefactor": 0., "tune": True, "timings": 10, "verbose": True}
[docs]@script_interface_register class DipolarDirectSumCpu(MagnetostaticInteraction): """ Calculate magnetostatic interactions by direct summation over all pairs. See :ref:`Dipolar direct sum` for more details. If the system has periodic boundaries, the minimum image convention is applied in the respective directions when no replicas are used. When replicas are used, ``n_replicas`` copies of the system are taken into account in the respective directions, and a spherical cutoff is applied. Parameters ---------- prefactor : :obj:`float` Magnetostatics prefactor (:math:`\\mu_0/(4\\pi)`) n_replicas : :obj:`int`, optional Number of replicas to be taken into account at periodic boundaries. """ _so_name = "Dipoles::DipolarDirectSumCpu"
[docs] def default_params(self): return {"n_replicas": 0}
[docs] def required_keys(self): return {"prefactor"}
[docs]@script_interface_register class Scafacos(MagnetostaticInteraction): """ Calculate the dipolar interaction using dipoles-capable methods from the ScaFaCoS library. See :ref:`ScaFaCoS magnetostatics` for more details. Parameters ---------- prefactor : :obj:`float` Magnetostatics prefactor (:math:`\\mu_0/(4\\pi)`). method_name : :obj:`str` Name of the ScaFaCoS method to use. method_params : :obj:`dict` Dictionary with the key-value pairs of the method parameters as defined in ScaFaCoS. Note that the values are cast to strings to match ScaFaCoS' interface. Methods ------- get_available_methods() List long-range methods available in the ScaFaCoS library. """ _so_name = "Dipoles::DipolarScafacos" _so_creation_policy = "GLOBAL" _so_bind_methods = MagnetostaticInteraction._so_bind_methods + \ ("get_available_methods", ) def _check_required_features(self): if not has_features("DIPOLES"): raise NotImplementedError("Feature DIPOLES not compiled in") if not has_features("SCAFACOS_DIPOLES"): raise NotImplementedError( "Feature SCAFACOS_DIPOLES not compiled in")
[docs] def default_params(self): return {}
[docs] def required_keys(self): return {"method_name", "method_params", "prefactor"}
[docs]@script_interface_register class DipolarDirectSumGpu(MagnetostaticInteraction): """ Calculate magnetostatic interactions by direct summation over all pairs. See :ref:`Dipolar direct sum` for more details. If the system has periodic boundaries, the minimum image convention is applied in the respective directions. This is the GPU version of :class:`espressomd.magnetostatics.DipolarDirectSumCpu` but uses floating point precision. Requires feature ``DIPOLAR_DIRECT_SUM``, which depends on ``DIPOLES`` and ``CUDA``. Parameters ---------- prefactor : :obj:`float` Magnetostatics prefactor (:math:`\\mu_0/(4\\pi)`) """ _so_name = "Dipoles::DipolarDirectSumGpu" _so_creation_policy = "GLOBAL" def _check_required_features(self): if not has_features("DIPOLAR_DIRECT_SUM"): raise NotImplementedError( "Features CUDA and DIPOLES not compiled in")
[docs] def default_params(self): return {}
[docs] def required_keys(self): return {"prefactor"}
[docs]@script_interface_register class DipolarBarnesHutGpu(MagnetostaticInteraction): """ Calculates magnetostatic interactions by direct summation over all pairs. See :ref:`Barnes-Hut octree sum on GPU` for more details. TODO: If the system has periodic boundaries, the minimum image convention is applied. Requires feature ``DIPOLAR_BARNES_HUT``, which depends on ``DIPOLES`` and ``CUDA``. Parameters ---------- epssq : :obj:`float`, optional Squared skin of the octant cells. itolsq : :obj:`float`, optional Squared inverse fraction of the octant cells. """ _so_name = "Dipoles::DipolarBarnesHutGpu" _so_creation_policy = "GLOBAL" def _check_required_features(self): if not has_features("DIPOLAR_BARNES_HUT"): raise NotImplementedError( "Features CUDA and DIPOLES not compiled in")
[docs] def default_params(self): return {"epssq": 100.0, "itolsq": 4.0}
[docs] def required_keys(self): return {"prefactor"}
[docs]@script_interface_register class DLC(MagnetostaticInteraction): """ Electrostatics solver for systems with two periodic dimensions. See :ref:`Dipolar Layer Correction (DLC)` for more details. Notes ----- At present, the empty gap (volume without any particles), is assumed to be along the z-axis. As a reference for the DLC method, see :cite:`brodka04a`. Parameters ---------- gap_size : :obj:`float` The gap size gives the height :math:`h` of the empty region between the system box and the neighboring artificial images. |es| checks that the gap is empty and will throw an error if it isn't. Therefore you should really make sure that the gap region is empty (e.g. with wall constraints). maxPWerror : :obj:`float` Maximal pairwise error of the potential and force. far_cut : :obj:`float`, optional Cutoff of the exponential sum. """ _so_name = "Dipoles::DipolarLayerCorrection" _so_creation_policy = "GLOBAL"
[docs] def validate_params(self, params): utils.check_type_or_throw_except( params["maxPWerror"], 1, float, "Parameter 'maxPWerror' has to be a float") utils.check_type_or_throw_except( params["gap_size"], 1, float, "Parameter 'gap_size' has to be a float") utils.check_type_or_throw_except( params["far_cut"], 1, float, "Parameter 'far_cut' has to be a float")
[docs] def default_params(self): return {"far_cut": -1.}
[docs] def required_keys(self): return {"actor", "maxPWerror", "gap_size"}