def __init__(self, atoms=None): """ Parameters: atoms: ASE Atoms The full system. You can later on define it with set_atoms, or provide it directly in get_potential_energy()/get_forces(). """ self.total_timer = Timer(["total"]) self.total_timer.start("total") self.subsystem_energies = {} self.subsystems = {} self.subsystem_interactions = {} self.subsystem_info = {} self.interaction_info = {} self.forces = None self.stress = None self.potential_energy = None self.system_initialized = False if atoms is not None: self.atoms = atoms.copy() else: self.atoms = None
def __init__( self, full_system, primary_subsystem, secondary_subsystem, info): """ Parameters: full_system: ASE Atoms primary_subsystem: :class:`~pysic.subsystem.SubSystem` secondary_subsystem: :class:`~pysic.subsystem.SubSystem` info: :class:`~pysic.interaction.Interaction` """ self.info = info self.full_system = full_system self.primary_subsystem = primary_subsystem self.secondary_subsystem = secondary_subsystem self.uncorrected_interaction_energy = None self.uncorrected_interaction_forces = None self.link_atom_correction_energy = None self.link_atom_correction_forces = None self.interaction_energy = None self.interaction_forces = None # Determine if any potentials have been set self.has_interaction_potentials = False if self.info.comb_potential_enabled: self.has_interaction_potentials = True if self.info.coulomb_potential_enabled: self.has_interaction_potentials = True if len(self.info.potentials) != 0: self.has_interaction_potentials = True self.calculator = Pysic() self.pbc_calculator = Pysic() self.timer = Timer([ "Interaction", "Interaction (PBC)", "Forces", "Forces (PBC)", "Link atom correction energy", "Link atom correction forces"]) # The interaction needs to know if PBC:s are on pbc = primary_subsystem.atoms_for_interaction.get_pbc() if pbc[0] or pbc[1] or pbc[2]: self.has_pbc = True else: self.has_pbc = False # Initialize hydrogen links self.link_atoms = None self.setup_hydrogen_links(info.links) # Store the number of atoms in different systems self.n_primary = len(primary_subsystem.atoms_for_interaction) self.n_secondary = len(secondary_subsystem.atoms_for_interaction) self.n_full = self.n_primary + self.n_secondary if self.link_atoms is not None: self.n_links = len(self.link_atoms) else: self.n_links = 0 # Initialize the COMB potential first (set_potentials(COMB) is used, # because it isn' the same as add_potential(COMB)) if info.comb_potential_enabled: self.setup_comb_potential() # Initialize the coulomb interaction if info.electrostatic_parameters is not None: self.setup_coulomb_potential() # Add the other potentials self.setup_potentials() # Can't enable link atom correction on system without link atoms if len(info.links) == 0: self.info.link_atom_correction_enabled = False
def __init__(self, atoms, info, index_map, reverse_index_map, n_atoms): """ Parameters: atoms: ASE Atoms The subsystem atoms. info: SubSystem object Contains all the information about the subsystem index_map: dictionary of int to int The keys are the atom indices in the full system, values are indices in the subssystem. reverse_index_map: dicitonary of int to int The keys are the atom indices in the subsystem, values are the keys in the full system. n_atoms: int Number of atoms in the full system. """ # Extract data from info self.name = info.name self.calculator = copy.copy(info.calculator) self.cell_size_optimization_enabled = info.cell_size_optimization_enabled self.cell_padding = info.cell_padding self.charge_calculation_enabled = info.charge_calculation_enabled self.charge_source = info.charge_source self.division = info.division self.gridrefinement = info.gridrefinement self.n_atoms = n_atoms self.atoms_for_interaction = atoms.copy() self.atoms_for_subsystem = atoms.copy() self.index_map = index_map self.reverse_index_map = reverse_index_map self.potential_energy = None self.forces = None self.density_grid = None self.pseudo_density = None self.link_atom_indices = [] self.timer = Timer([ "Bader charge calculation", "van Der Waals charge calculation", "Energy", "Forces", "Density grid update", "Cell minimization" ]) # The older ASE versions do not support get_initial_charges() try: charges = np.array(atoms.get_initial_charges()) except: charges = np.array(atoms.get_charges()) self.initial_charges = charges ## Can't enable charge calculation on non-DFT calculator self.dft_system = hasattr(self.calculator, "get_pseudo_density") if self.charge_calculation_enabled is True and not self.dft_system: error("Can't enable charge calculation on non-DFT calculator!") # If the cell size minimization flag has been enabled, then try to reduce the # cell size if self.cell_size_optimization_enabled: pbc = atoms.get_pbc() if pbc[0] or pbc[1] or pbc[2]: warn(("Cannot optimize cell size when periodic boundary" "condition have been enabled, disabling optimization."), 2) self.cell_size_optimization_enabled = False else: self.optimize_cell()