Source code for atsim.potentials.config._tabulation_factories

import logging

import collections

try:
  import collections.abc
[docs] Mapping = collections.abc.Mapping
except ImportError: Mapping = collections.Mapping from ..pair_tabulation import DLPoly_PairTabulation, LAMMPS_PairTabulation, GULP_PairTabulation, Excel_PairTabulation from ..eam_tabulation import SetFL_EAMTabulation, SetFL_FS_EAMTabulation, TABEAM_EAMTabulation, TABEAM_FinnisSinclair_EAMTabulation, Excel_EAMTabulation, Excel_FinnisSinclair_EAMTabulation, ADP_EAMTabulation from ._common import ConfigurationException from ._potential_form_registry import Potential_Form_Registry from ._modifier_registry import Modifier_Registry from ._pair_potential_builder import Pair_Potential_Builder, Pair_Potentials_From_Tuples_Builder from ._eam_potential_builder import EAM_Potential_Builder, EAM_Potential_Builder_FS from ..referencedata import Reference_Data
[docs]RCutoffTuple = collections.namedtuple('RCutoffTuple', ['cutoff', 'nr'])
[docs]R_Rho_CutoffTuple = collections.namedtuple('R_Rho_CutoffTuple', ['cutoff', 'nr', 'cutoff_rho', 'nrho'])
def _create_pair_objects(potential_form_registry, modifier_registry, cp): potbuilder = Pair_Potential_Builder(cp, potential_form_registry, modifier_registry) pots = potbuilder.potentials return pots
[docs]class PairTabulationFactory(object): """Factory class for Tabulation objects such as those in the atsim.potentials.pair_tabulation module. The role of this class is to extract data from an atsim.potentials.config.ConfigParser and together with other builder classes, create atsim.potentials.Potential objects and extract the cutoff values that can be used to instantiate a Tabulation object. The key method for clients of this object is .create_tabulation(). Other public methods are provided to allow customisation in sub-classes. """ def __init__(self, tabulation_target, tabulation_class): self.tabulation_target = tabulation_target self.tabulation_class = tabulation_class self.tabulation_type = "pair-potential" def _log_cutoffs(self, logger, r_cutoff, **kwargs): logger.info(" * cutoff: {}".format(r_cutoff.cutoff)) logger.info(" * nr: {}".format(r_cutoff.nr)) def _log_extra_tabulation_details(self, logger, r_cutoff, potobjs, **kwargs): pass def _log_pair_potentials(self, logger, potobjs, **kwargs): logger.info(" * Tabulation will contain the following pair-potentials:") for pot in potobjs: logger.info(" + {}-{}".format(pot.speciesA, pot.speciesB)) def _log_more(self, logger, r_cutoff, potobjs, **kwargs): pass def _log_tabulation_details(self, r_cutoff, potobjs, **kwargs): logger = logging.getLogger(__name__).getChild("PairTabulationFactory._log_tabulation_details") logger.info("Creating {tabulation_type} tabulation with following properties:".format(tabulation_type = self.tabulation_type)) logger.info(" * tabulation-target : {}".format(self.tabulation_target)) self._log_cutoffs(logger, r_cutoff, **kwargs) self._log_extra_tabulation_details(logger,r_cutoff, potobjs, **kwargs) self._log_pair_potentials(logger, potobjs, **kwargs) self._log_more(logger, r_cutoff, potobjs, **kwargs)
[docs] def extract_cutoffs(self, cp): """Called by .create_tabulation() to determine the maximum separation cutoff for the tabulation. :param cp: atsim.potentials.config.ConfigParser instance representing parsed configuration file. :return: RCutoffTuple (or object providing .cutoff and .nr properties)""" logger = logging.getLogger(__name__).getChild("PairTabulationFactory.extract_cutoffs") # Get cutoff and gridpoints if cp.tabulation.cutoff is None: cutoff = 10.0 logger.warning("Cutoff not specified using a default of {}".format(cutoff)) else: cutoff = cp.tabulation.cutoff if cp.tabulation.nr is None: nr = 1001 logger.warning("nr not specified using a default of {}".format(nr)) else: nr = cp.tabulation.nr return RCutoffTuple(cutoff, nr)
[docs] def extract_potential_objects(self, cp, potential_form_registry, modifier_registry): """Method called by .create_tabulation() to create a list of atsim.potentials.Potential objects. :param cp: atsim.potentials.config.ConfigParser instance representing parsed configuration file. :param potential_form_registry: atsim.potentials.config.Potential_Form_Registry object. :param modifier_registry: atsim.potentials.config.Modifier_Registry instance. :return: List of atsim.potentials.Potential objects. """ potobjs = _create_pair_objects(potential_form_registry,modifier_registry, cp) return potobjs
[docs] def extract_tabulation_args(self, cp, r_cutoff, potobjs, potential_form_registry, modifier_registry): """Extract and prepare arguments to be passed to Tabulation class constructor. Returns a list of arguments suitable for passing to Tabulation class constructor. Typically these are: ``[potobjs, cutoff, nr]`` Where: * ``potobjs`` is a list of :class:`atsim.potentials.Potential` instances. * ``cutoff`` is a float giving the maximum separation for the tabulation. * ``nr`` the number of rows to be used in the tabulation. :param cp: atsim.potentials.config.ConfigParser instance representing parsed configuration file. :param r_cutoff: Float giving the maximum separation for tabulation (as extracted from configuration). :param potobjs: List of atsim.potentials.Potential objects to be tabulated. :param potential_form_registry: atsim.potentials.config.Potential_Form_Registry object. :param modifier_registry: atsim.potentials.config.Modifier_Registry instance. :return: List containing Tabulation class constructor arguments. """ return [potobjs, r_cutoff.cutoff, r_cutoff.nr]
[docs] def create_tabulation(self,cp): # logger = logging.getLogger(__name__).getChild("PairTabulationFactory.create_tabulation") r_cutoff = self.extract_cutoffs(cp) # Get pair potentials potential_form_registry = Potential_Form_Registry(cp, register_standard = True, register_pymath_functions = True) modifier_registry = Modifier_Registry() potobjs = self.extract_potential_objects(cp, potential_form_registry, modifier_registry) self._log_tabulation_details(r_cutoff, potobjs) tabulationargs = self.extract_tabulation_args(cp, r_cutoff, potobjs, potential_form_registry, modifier_registry) tabulation = self.tabulation_class(*tabulationargs) return tabulation
[docs]class EAMTabulationFactory(PairTabulationFactory): """Tabulation factory for setfl (LAMMPS eam/alloy) potentials""" def __init__(self, tabulation_target, tabulation_class, eam_builder_class = EAM_Potential_Builder): super(EAMTabulationFactory, self).__init__(tabulation_target, tabulation_class) self.eam_builder_class = eam_builder_class self.tabulation_type = "EAM"
[docs] def extract_cutoffs(self, cp): logger = logging.getLogger(__name__).getChild("EAMTabulationFactory._get_cutoffs") r_cutoff = super(EAMTabulationFactory, self).extract_cutoffs(cp) # Get cutoff and gridpoints if cp.tabulation.cutoff_rho is None: cutoff_rho = 100.0 logger.warning("cutoff_rho not specified using a default of {}".format(cutoff_rho)) else: cutoff_rho = cp.tabulation.cutoff_rho if cp.tabulation.nrho is None: nrho = 1001 logger.warning("nrho not specified using a default of {}".format(nrho)) else: nrho = cp.tabulation.nrho return R_Rho_CutoffTuple(r_cutoff.cutoff, r_cutoff.nr, cutoff_rho, nrho)
def _create_reference_data(self, cp): extra_rd = cp.species rd = Reference_Data(extra_rd) return rd
[docs] def extract_tabulation_args(self, cp, r_cutoff, potobjs, potential_form_registry, modifier_registry): logger = logging.getLogger(__name__).getChild("EAMTabulationFactory._make_tabulation_args") rd = self._create_reference_data(cp) eam_builder = self.eam_builder_class(cp, potential_form_registry, modifier_registry, rd) eam_potentials = eam_builder.eam_potentials logger.info(" * Tabulation will contain following EAM species:") any_dict = False for eam_potential in eam_potentials: logger.info(" + {}".format(eam_potential.species)) if isinstance(eam_potential.electronDensityFunction, Mapping): any_dict = True if any_dict: logger.info(" * Tabulation will contain the folowing density functions:") for eam_potential in eam_potentials: if isinstance(eam_potential.electronDensityFunction, Mapping): other_species = sorted(eam_potential.electronDensityFunction.keys()) for s in other_species: logger.info(" + {}->{}".format(eam_potential.species, s)) else: logger.info(" + {}".format(eam_potential.species)) args = [potobjs, eam_potentials, r_cutoff.cutoff, r_cutoff.nr, r_cutoff.cutoff_rho, r_cutoff.nrho] return args
def _log_cutoffs(self, logger, r_cutoff, **kwargs): super(EAMTabulationFactory, self)._log_cutoffs(logger, r_cutoff, **kwargs) logger.info(" * cutoff_rho: {}".format(r_cutoff.cutoff_rho)) logger.info(" * nrho: {}".format(r_cutoff.nrho))
[docs]class DLPOLY_PairTabulationFactory(PairTabulationFactory): """PairTabulationFactory that performs extra checks required by DL_POLY TABLEs and raises ConfigException if errors are found"""
[docs] def extract_cutoffs(self, cp): cutoffs = super(DLPOLY_PairTabulationFactory, self).extract_cutoffs(cp) if cutoffs.nr % 4 != 0: raise ConfigurationException("The number of rows in a DL_POLY TABLE file needs to be divisible by 4. Number of rows specified = {} ".format(cutoffs.nr)) return cutoffs
[docs]class ADP_EAMTabulationFactory(EAMTabulationFactory): """EAMTabulationFactory which creates the additional dipole and quadrupole objects required by the ADP EAM extension""" def _extract_pots(self, cp, pfr, mr, section_name): tuples = cp.parse_pair_like(section_name) pot_builder = Pair_Potentials_From_Tuples_Builder(tuples, pfr, mr, section_name ) return pot_builder.potentials
[docs] def extract_dipoles(self, cp, potential_form_registry, modifier_registry): return self._extract_pots(cp, potential_form_registry, modifier_registry, "EAM-ADP-Dipole")
[docs] def extract_quadrupoles(self, cp, potential_form_registry, modifier_registry): return self._extract_pots(cp, potential_form_registry, modifier_registry, "EAM-ADP-Quadrupole")
[docs] def extract_tabulation_args(self, cp, r_cutoff, potobjs, potential_form_registry, modifier_registry): (potobjs, eam_potentials, cutoff_r, nr, cutoff_rho, nrho) = super().extract_tabulation_args(cp, r_cutoff, potobjs, potential_form_registry, modifier_registry) dipoles = self.extract_dipoles(cp, potential_form_registry, modifier_registry) quadrupoles = self.extract_quadrupoles(cp, potential_form_registry, modifier_registry) args = [potobjs, eam_potentials, dipoles, quadrupoles, cutoff_r, nr, cutoff_rho, nrho] return args
"""Target name to factory objects"""
[docs]TABULATION_FACTORIES = { "LAMMPS" : PairTabulationFactory("LAMMPS", LAMMPS_PairTabulation), "DLPOLY" : DLPOLY_PairTabulationFactory("DLPOLY", DLPoly_PairTabulation), "GULP" : PairTabulationFactory("GULP", GULP_PairTabulation), "excel" : PairTabulationFactory("excel", Excel_PairTabulation), "setfl" : EAMTabulationFactory("setfl/lammps_eam_alloy", SetFL_EAMTabulation), "setfl_fs" : EAMTabulationFactory("setfl/lammps_eam_fs", SetFL_FS_EAMTabulation, EAM_Potential_Builder_FS), "DL_POLY_EAM" : EAMTabulationFactory("DL_POLY_EAM", TABEAM_EAMTabulation), "DL_POLY_EAM_fs" : EAMTabulationFactory("DL_POLY_EAM_fs", TABEAM_FinnisSinclair_EAMTabulation, EAM_Potential_Builder_FS), "excel_eam" : EAMTabulationFactory("excel_eam", Excel_EAMTabulation), "excel_eam_fs" : EAMTabulationFactory("excel_eam_fs", Excel_FinnisSinclair_EAMTabulation, EAM_Potential_Builder_FS), "eam_adp" : ADP_EAMTabulationFactory("eam_adp", ADP_EAMTabulation)
}