Source code for lattice_mc.simulation

from lattice_mc import init_lattice, species, lookup_table

[docs]class Simulation: """ Simulation class """ def __init__( self ): """ Initialise a Simulation object. Args: None Returns: None Notes: Simulation parameters need to be set using their corresponding setter methods. """ self.lattice = None self.number_of_atoms = None self.number_of_jumps = None self.for_time = None self.number_of_equilibration_jumps = 0 self.atoms = None self.has_run = False
[docs] def reset( self ): """ Reset all counters for this simulation. Args: None Returns: None """ self.lattice.reset() for atom in self.atoms.atoms: atom.reset()
[docs] def set_number_of_atoms( self, n, selected_sites=None ): """ Set the number of atoms for the simulation, and populate the simulation lattice. Args: n (Int): Number of atoms for this simulation. selected_sites (:obj:(List|Set|String), optional): Selects a subset of site types to be populated with atoms. Defaults to None. Returns: None """ self.number_of_atoms = n self.atoms = species.Species( self.lattice.populate_sites( self.number_of_atoms, selected_sites=selected_sites ) )
[docs] def set_number_of_jumps( self, n ): """ Set the number of jumps for this simulation. Args: n (Int): number of jumps Returns: None """ self.number_of_jumps = n
[docs] def set_number_of_equilibration_jumps( self, n ): """ Set the number of equilibration jumps for this simulation. Args: n (Int): number of equilibration jumps Returns: None """ self.number_of_equilibration_jumps = n
[docs] def define_lattice_from_file( self, filename, cell_lengths ): """ Set up the simulation lattice from a file containing site data. Uses `init_lattice.lattice_from_sites_file`, which defines the site file spec. Args: filename (Str): sites file filename. cell_lengths (List(x,y,z)): cell lengths for the simulation cell. Returns: None """ self.lattice = init_lattice.lattice_from_sites_file( filename, cell_lengths = cell_lengths )
[docs] def set_nn_energy( self, nn_energy ): """ Set the nearest-neighbour energy for this simulation. Args: nn_energy (Float): nearest-neigbour energy. Returns: None """ if nn_energy: self.lattice.set_nn_energy( nn_energy )
[docs] def set_cn_energies( self, cn_energies ): """ Set the coordination-number dependent energies for this simulation. Args: cn_energies (Dict(Str:Dict(Int:Float))): Dict of Dicts specficying the coordination-number dependent energies. e.g. { 'A' : { 0 : 0.0, 1: 0.5 }, 'B' : { 0 : -0.5, 1 : -2.0 } } Returns: None """ if cn_energies: self.lattice.set_cn_energies( cn_energies )
[docs] def set_site_energies( self, site_energies ): """ Set the on-site energies for this simulation. Args: site_energies (Dict(Str:Float)): Dict of energies for each site type. e.g. { 'A' : 0.0,. 'B' : 1.0 } Returns: None """ if site_energies: self.lattice.set_site_energies( site_energies )
[docs] def is_initialised( self ): """ Check whether the simulation has been initialised. Args: None Returns: None """ if not self.lattice: raise AttributeError('Running a simulation needs the lattice to be initialised') if not self.atoms: raise AttributeError('Running a simulation needs the atoms to be initialised') if not self.number_of_jumps and not self.for_time: raise AttributeError('Running a simulation needs number_of_jumps or for_time to be set')
[docs] def run( self, for_time=None ): """ Run the simulation. Args: for_time (:obj:Float, optional): If `for_time` is set, then run the simulation until a set amount of time has passed. Otherwise, run the simulation for a set number of jumps. Defaults to None. Returns: None """ self.for_time = for_time try: self.is_initialised() except AttributeError: raise if self.number_of_equilibration_jumps > 0: for step in range( self.number_of_equilibration_jumps ): self.lattice.jump() self.reset() if self.for_time: self.number_of_jumps = 0 while self.lattice.time < self.for_time: self.lattice.jump() self.number_of_jumps += 1 else: for step in range( self.number_of_jumps ): self.lattice.jump() self.has_run = True
@property def old_tracer_correlation( self ): """ Deprecated tracer correlation factor for this simulation. Args: None Returns: (Float): The tracer correlation factor, f. Notes: This function assumes that the jump distance between sites has been normalised to a=1. If the jump distance is not equal to 1 then the value returned by this function should be divided by a^2. Even better, use `self.tracer_correlation`. """ if self.has_run: return self.atoms.sum_dr_squared() / float( self.number_of_jumps ) else: return None @property def tracer_correlation( self ): """ Tracer correlation factor, f. Args: None Returns: (Float): The tracer correlation factor, f. """ if self.has_run: return self.atoms.tracer_correlation() else: return None @property def tracer_diffusion_coefficient( self ): """ Tracer diffusion coefficient, D*. Args: None Returns: (Float): The tracer diffusion coefficient, D*. """ if self.has_run: return self.atoms.sum_dr_squared() / ( 6.0 * float( self.number_of_atoms ) * self.lattice.time ) else: return None @property def old_collective_correlation( self ): """ Returns the collective correlation factor, f_I Args: None Returns: (Float): The collective correlation factor, f_I. Notes: This function assumes that the jump distance between sites has been normalised to a=1. If the jumps distance is not equal to 1 then the value returned by this function should be divided by a^2. Even better, use self.collective_correlation """ if self.has_run: return self.atoms.collective_dr_squared() / float( self.number_of_jumps ) else: return None @property def collective_correlation( self ): """ Returns the collective correlation factor, f_I Args: None Returns: (Float): The collective correlation factor, f_I. """ if self.has_run: return self.atoms.collective_correlation() else: return None @property def collective_diffusion_coefficient( self ): """ Returns the collective or "jump" diffusion coefficient, D_J. Args: None Returns: (Float): The collective diffusion coefficient, D_J. """ if self.has_run: return self.atoms.collective_dr_squared() / ( 6.0 * self.lattice.time ) else: return None @property def collective_diffusion_coefficient_per_atom( self ): """ The collective diffusion coefficient per atom. D_J / n_atoms. Args: None Returns: (Float): The collective diffusion coefficient per atom, D_J / n_atoms. """ if self.has_run: return self.collective_diffusion_coefficient / float( self.number_of_atoms ) else: return None @property def average_site_occupations( self ): """ Average site occupation numbers. Args: None Returns: (Dict(Str:Float)): Average site occupation numbers for each site label, e.g. { 'A' : 12.4, 'B' : 231.2 } """ return self.lattice.site_occupation_statistics()
[docs] def setup_lookup_table( self, hamiltonian='nearest-neighbour' ): """ Create a jump-probability look-up table corresponding to the appropriate Hamiltonian. Args: hamiltonian (Str, optional): String specifying the simulation Hamiltonian. valid values are 'nearest-neighbour' (default) and 'coordination_number'. Returns: None """ expected_hamiltonian_values = [ 'nearest-neighbour', 'coordination_number' ] if hamiltonian not in expected_hamiltonian_values: raise ValueError self.lattice.jump_lookup_table = lookup_table.LookupTable( self.lattice, hamiltonian )