Source code for pressomancy.object_classes.multicore_particle

import inspect
import numpy as np
from pressomancy.object_classes.object_class import ObjectConfigParams
from pressomancy.object_classes.rigid_obj import GenericRigidObj
from pressomancy.helper_functions import PartDictSafe
from pressomancy.helper_functions import MissingFeature

[docs] class MulticorePart(GenericRigidObj): ''' Class that contains relevant paramaters and methods. At construction one must pass an espresso handle becaouse the class manages parameters that are both internal and external to espresso. It is assumed that in any simulation instanse there will be only one type of a Quadriplex. Therefore many relevant parameters are class specific, not instance specific. ''' numInstances = 0 part_types = PartDictSafe() config=ObjectConfigParams( alias='multicore' ) def __init__(self, config: ObjectConfigParams): super().__init__(config) self.who_am_i = MulticorePart.numInstances MulticorePart.numInstances += 1
[docs] def add_dipole_moments_to_virtuals(self, dip_moments, selection='random', anisotropy={'kind':'infinite','params': {}}): """ Assign magnetic dipole moments to selected virtual particles. Parameters ---------- dip_moments : array_like, shape (N, 3) Dipole vectors to assign (in simulation units). Each selected virtual particle receives one 3-vector. If more dipole vectors are provided than available virtual particles, the extras are ignored; if fewer are provided, only that many particles are selected. selection : {'random'}, optional Particle selection strategy. Currently only ``'random'`` is supported: choose ``N`` distinct virtual particles uniformly at random, where ``N`` is the number of dipole vectors provided. Default is ``'random'``. anisotropy : dict, optional Anisotropy model to apply to the selected particles. Must be a dict with keys: - ``'kind'`` : {'infinite', 'finite_egg'} * ``'infinite'`` — no extra parameters required; dipoles are assigned directly to particles. * ``'finite_egg'`` — uses ESPResSo's Egg model; requires params ``'egg_gamma'`` and ``'aniso_energy'``. - ``'params'`` : dict For ``'finite_egg'``: ``{'egg_gamma': float, 'aniso_energy': float}``. Default is ``{'kind': 'infinite', 'params': {}}``. Returns ------- None Raises ------ MissingFeature If ``anisotropy['kind'] == 'finite_egg'`` but the ESPResSo build lacks the ``EGG_MODEL`` feature. AssertionError If an unsupported anisotropy kind is specified or required Egg-model parameters are missing. ValueError If ``dip_moments`` cannot be coerced to a ``(N, 3)`` array. Notes ----- - Operates only on particles of type ``'virt'`` in ``self.type_part_dict['virt']``. - Selection uses NumPy's RNG for shuffling (uniform without replacement). - For the Egg model, selected particles are retyped to a ``'yolk'`` part type. """ assert anisotropy['kind'] in ['infinite', 'finite_egg'],'Supporting infinite anisotropy and finite anisotropy via the Egg model' dip_moments=np.atleast_2d(dip_moments) part_handles = self.type_part_dict['virt'] num_parts = len(part_handles) if selection == 'random': take_index = np.arange(num_parts) np.random.shuffle(take_index) take_index = take_index[:len(dip_moments)] part_handles = np.array(part_handles)[take_index] else: raise NotImplementedError('Only random subsampling of cores implemented is currently') if anisotropy['kind']=='infinite': for x,dip_mom_per_part in zip(part_handles, dip_moments): x.dip = dip_mom_per_part if anisotropy['kind']=='finite_egg': if not self.sys.api_agnostic_feature_check('EGG_MODEL'): name = f"{type(self).__name__}.{inspect.currentframe().f_code.co_name}" raise MissingFeature(f"{name} requires EGG_MODEL. Please enable it in your ESPResSo installation.") MulticorePart.part_types.update({'yolk': 11}) assert ['egg_gamma','aniso_energy'] in anisotropy['params'], "Finite anisotropy is realised with the Egg model, which requires 'egg_gamma' and 'aniso_energy' parameters to be specified" for x,dip_mom_per_part in zip(part_handles, dip_moments): x.dip = dip_mom_per_part x.egg_model_params = (True, anisotropy['params']['egg_gamma'], anisotropy['params']['aniso_energy']) self.change_part_type(x,'yolk')