def __init__(self, atoms, temperature=100 * kB, optimizer=FIRE, fmax=0.1, dr=0.1, logfile='-', trajectory='lowest.traj', optimizer_logfile='-', local_minima_trajectory='local_minima.traj', adjust_cm=True): Dynamics.__init__(self, atoms, logfile, trajectory) self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.lm_trajectory = PickleTrajectory(local_minima_trajectory, 'w', atoms) self.initialize()
def __init__(self, atoms, max_step = 0.5, T= 298.0, accept_ratio=None, one_d_coord =None): self.max_step = max_step self.beta = 1.0 / (T * units.kB) self.accept_ratio = accept_ratio self.one_d_coord = one_d_coord Dynamics.__init__(self, atoms,logfile=None, trajectory=None)
def __init__(self, atoms, timestep, integrator='verlet', trajectory=None, traj_interval=1000, logfile=None, loginterval=100): Dynamics.__init__(self, atoms, None, None) self.dt = timestep if integrator == 'verlet': self.run_style = 'verlet' else: raise RuntimeError('Unknown integrator: %s' % thermostat) if trajectory: if isinstance(trajectory, str): trajectory = PickleTrajectory(trajectory, 'w', atoms) self.attach(trajectory, interval=traj_interval) if logfile: self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile), interval=loginterval) self.fix = None self.cell_relaxed = False
def __init__(self, atoms, timestep, trajectory, logfile=None, loginterval=1, append_trajectory=False): # dt as to be attached _before_ parent class is initialized self.dt = timestep Dynamics.__init__(self, atoms, logfile=None, trajectory=trajectory, append_trajectory=append_trajectory) self.masses = self.atoms.get_masses() self.max_steps = None if 0 in self.masses: warnings.warn('Zero mass encountered in atoms; this will ' 'likely lead to errors if the massless atoms ' 'are unconstrained.') self.masses.shape = (-1, 1) if not self.atoms.has('momenta'): self.atoms.set_momenta(np.zeros([len(self.atoms), 3])) if logfile: self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile), interval=loginterval)
def __init__(self, atoms, timestep, trajectory, logfile=None, loginterval=1): Dynamics.__init__(self, atoms, logfile=None, trajectory=trajectory) self.dt = timestep # Store data locally except on parallel simulations self._localdata = not getattr(atoms, "parallel", False) if logfile: self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile), interval=loginterval)
def __init__(self, atoms, restart=None, logfile=None, trajectory=None, algorithm='cg', relax_cell=False): Dynamics.__init__(self, atoms, logfile, trajectory) self.algorithm = algorithm self.relax_cell = relax_cell
def __init__(self, atoms, timestep, trajectory, logfile=None, loginterval=1): Dynamics.__init__(self, atoms, logfile=None, trajectory=trajectory) self.dt = timestep self.masses = self.atoms.get_masses() self.masses.shape = (-1, 1) if logfile: self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile), interval=loginterval)
def __init__(self, atoms, timestep, trajectory, logfile=None, loginterval=1): Dynamics.__init__(self, atoms, logfile=None, trajectory=trajectory) self.dt = timestep self.masses = self.atoms.get_masses() if 0 in self.masses: warnings.warn('Zero mass encountered in atoms; this will ' 'likely lead to errors if the massless atoms ' 'are unconstrained.') self.masses.shape = (-1, 1) if logfile: self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile), interval=loginterval)
def __init__(self, atoms, temperature=100 * kB, optimizer=SDLBFGS, fmax=0.1, dr=0.1, logfile='-', trajectory=None, optimizer_logfile='-', local_minima_trajectory='local_minima.con', adjust_cm=True, mss=0.2, minenergy=None, distribution='uniform', adjust_step_size=None, adjust_every = None, target_ratio = 0.5, adjust_fraction = 0.05, significant_structure = False, pushapart = 0.4, jumpmax=None ): Dynamics.__init__(self, atoms, logfile, trajectory) self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): tsase.io.write_con(self.lm_trajectory,atoms,w='w') tsase.io.write_con('best_energies.con',atoms,w='w') self.minenergy = minenergy self.distribution = distribution self.adjust_step = adjust_step_size self.adjust_every = adjust_every self.target_ratio = target_ratio self.adjust_fraction = adjust_fraction self.significant_structure = True self.pushapart = pushapart self.jumpmax = jumpmax self.mss = mss self.initialize() self.norm_dists = [None] * len(self.positions) for i in range(len(self.norm_dists)): self.norm_dists[i] = []
def __init__(self, atoms, temperature=100 * kB, optimizer=SDLBFGS, fmax=0.1, dr=0.1, logfile='-', trajectory=None, optimizer_logfile='-', local_minima_trajectory='local_minima.con', mss=0.2, minenergy=None, adjust_step_size=None, adjust_every = None, target_ratio = 0.5, adjust_fraction = 0.05, pushapart = 0.4, jumpmax=2, inertia_weight=.4, method='PSO' ): Dynamics.__init__(self, atoms, logfile, trajectory) self.local_optimizations = 0 self.bcms = 0 self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr self.method = method self.cm = atoms.get_center_of_mass() self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory self.minenergy = minenergy self.energy = 0 self.adjust_step = adjust_step_size self.adjust_every = adjust_every self.target_ratio = target_ratio self.adjust_fraction = adjust_fraction self.pushapart = pushapart self.jumpmax = jumpmax self.mss = mss self.inertia_weight = inertia_weight self.velocity = 0.0 * self.atoms.get_positions() self.initialize()
def __init__(self, atoms, temperature=100 * kB, optimizer=FIRE, fmax=0.1, dr=0.1, logfile='-', trajectory='lowest.traj', optimizer_logfile='-', local_minima_trajectory='local_minima.traj', adjust_cm=True): """Parameters: atoms: Atoms object The Atoms object to operate on. trajectory: string Pickle file used to store trajectory of atomic movement. logfile: file object or str If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. """ self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.db = connect(local_minima_trajectory[:-4] + 'db') self.lm_trajectory = Trajectory(local_minima_trajectory, 'a', atoms) Dynamics.__init__(self, atoms, logfile, trajectory) self.initialize()
def __init__(self, atoms, temperature=100 * kB, optimizer=FIRE, fmax=0.1, dr=0.1, logfile='-', trajectory='lowest.traj', optimizer_logfile='-', local_minima_trajectory='local_minima.traj', adjust_cm=True): """Parameters: atoms: Atoms object The Atoms object to operate on. trajectory: string Pickle file used to store trajectory of atomic movement. logfile: file object or str If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. """ self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.lm_trajectory = Trajectory(local_minima_trajectory, 'w', atoms) Dynamics.__init__(self, atoms, logfile, trajectory) self.initialize()
def __init__(self, atoms, timestep, trajectory, logfile=None, loginterval=1, append_trajectory=False): # dt as to be attached _before_ parent class is initialized self.dt = timestep Dynamics.__init__(self, atoms, logfile=None, trajectory=None) self.masses = self.atoms.get_masses() self.max_steps = None if 0 in self.masses: warnings.warn('Zero mass encountered in atoms; this will ' 'likely lead to errors if the massless atoms ' 'are unconstrained.') self.masses.shape = (-1, 1) if not self.atoms.has('momenta'): self.atoms.set_momenta(np.zeros([len(self.atoms), 3])) # Trajectory is attached here instead of in Dynamics.__init__ # to respect the loginterval argument. if trajectory is not None: if isinstance(trajectory, str): mode = "a" if append_trajectory else "w" trajectory = Trajectory(trajectory, mode=mode, atoms=atoms) self.attach(trajectory, interval=loginterval) if logfile: self.attach(MDLogger(dyn=self, atoms=atoms, logfile=logfile), interval=loginterval)
def __init__(self, # General GO parameters atoms, # ASE atoms object defining the PES temperature = 500, # K, initial temperature optimizer = SDLBFGS, # local optimizer fmax = 0.01, # magnitude of the L2 norm used as the convergence criteria for local optimization adjust_cm = True, # fix the center of mass (True or False) mss = 0.1, # maximum step size for the local optimizer minenergy = None, # the GO algorithm stops when a configuration is found with a lower potential energy than this value pushapart = 0.1, # push atoms apart until all atoms are no closer than this distance keep_minima_arrays = True, # create global_minima and local_minima arrays of length maximum number of Monte Carlo steps (True or False) minima_threshold = 2, # round potential energies to how many decimal places # Logging parameters logfile = '-', trajectory = None, optimizer_logfile = None, #local_minima_trajectory = 'local_minima.con', local_minima_trajectory = None, # Selecting move type move_type = True, # True = basin hopping trial move; False = minima hopping distribution = 'uniform', # The distribution to use in trial move. Make "molecular_dynamics" the distribution for MH trial move # Random move parameters dr = 0.45, # maximum displacement in each degree of freedom for Monte Carlo trial moves adjust_step_size = None, # adjust dr after this many Monte Carlo steps (Default: None; does not adjust dr) target_ratio = 0.5, # specified ratio of Monte Carlo steps adjust_fraction = 0.05, # fraction by which to adjust dr by in order to meet target_ratio significant_structure = True, # displace from minimum at each move (True or False) # Dynamic move parameters (Molecular Dynamics) timestep = 0.1, # fs, molecular dynamics time step mdmin = 2, # number of minima to pass in MD before stopping dimer_method = True, # uses an iterative dimer method before molecular dynamics (True or False) dimer_a = 0.001, # scalar for forces in optimization dimer_d = 0.01, # distance between two images in the dimer dimer_steps = 14, # number of dimer iterations # Occasional jumping parameters jump_distribution = 'uniform', # The distribution to use in OJ move. Same options as distribution flag jumpmax = None, # number of previously rejected MC steps before taking an OJ move; None = no OJ move jmp = 7, # number of consecutive accepted moves taken in OJ global_jump = None, # number of times to visit the same PE before we take an OJ; None = no global jump global_reset = False, # True = reset all of the history counts after a jump (basically delete the history and start fresh) # Select acceptance criteria acceptance_criteria = True, # BH = Tue; MH = False # BH acceptance parameters accept_temp = 8000, # K; separate temperature to use for BH acceptance (None: use temperature parameter instead) adjust_temp = False, # dynamically adjust the temperature in BH acceptance (True or False) history_weight = 0.0, # the weight factor of BH history >= 0 (0.0: no history comparison in BH acceptance) history_num = 0, # limit of previously accepted minima to keep track of for BH history (set to 0 to keep track of all minima) # MH acceptance criteria beta1 = 1.04, # temperature adjustment parameter beta2 = 1.04, # temperature adjustment parameter beta3 = 1.0/1.04, # temperature adjustment parameter Ediff0 = 0.5, # eV, initial energy acceptance threshold alpha1 = 0.98, # energy threshold adjustment parameter alpha2 = 1./0.98, # energy threshold adjustment parameter minimaHopping_history = False, # use history in MH trial move (True or False) # Geometry comparison parameters use_geometry = True, # True = compare geometry of systems when they have the same PE when determining if they are the same atoms configuration eps_r = 0.1, # positional difference to consider atoms in the same location use_get_mapping = True, # from atoms_operator.py use get_mapping if true or rot_match if false to compare geometry neighbor_cutoff = 1.2, # parameter for get_mapping only ): Dynamics.__init__(self, atoms, logfile, trajectory) self.temperature = temperature self.optimizer = optimizer self.fmax = fmax self.dr = dr if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): tsase.io.write_con(self.lm_trajectory,atoms,w='w') self.minenergy = minenergy self.move_type = move_type self.distribution = distribution self.adjust_step = adjust_step_size self.target_ratio = target_ratio self.adjust_fraction = adjust_fraction self.significant_structure = significant_structure self.pushapart = pushapart self.jumpmax = jumpmax self.jmp = jmp self.jump_distribution = jump_distribution self.global_jump = global_jump self.global_reset = global_reset self.dimer_method = dimer_method self.dimer_a = dimer_a self.dimer_d = dimer_d self.dimer_steps = dimer_steps self.timestep = timestep self.mdmin = mdmin self.w = history_weight self.history_num = history_num self.adjust_temp = adjust_temp self.accept_temp = accept_temp self.accept_criteria = acceptance_criteria self.mh_history = minimaHopping_history self.beta1 = beta1 self.beta2 = beta2 self.beta3 = beta3 self.Ediff = Ediff0 self.alpha1 = alpha1 self.alpha2 = alpha2 self.minima_threshold = minima_threshold self.use_geo = use_geometry self.eps_r = eps_r self.use_get_mapping = use_get_mapping self.neighbor_cutoff = neighbor_cutoff self.keep_minima_arrays = keep_minima_arrays self.global_minima = [] # an array of the current global minimum for every MC step self.local_minima = [] # an array of the current local minimum for every MC step self.allTemps = [] self.saveEdiff = [] self.trial_loop = [] self.num_localops = 0 self.num_geo_compare = [] # when a MD sim. has passed a local minimum: self.passedminimum = PassedMinimum() self.mss = mss # for PE comparision # dictionary for found local minima # keys will be the potential energy rounded to self.minima_threshold digits left of the decimal # values will be number of times the potential energy has been visited self.minima = {} # list with fixed size that will store history_num previous minima self.temp_minima = [0] * self.history_num self.temp_positions = [0] * self.history_num # for geometry comparison self.positionsMatrix = [] # count of unique geometries we have accepted so far self.numPositions = 0 # dictionary for geometry comparison # keys = approximate potential energy # values = list of indexes in positionsMatrix with the same PE self.geometries = {} # dictionary with keys = index in positionsMatrix # values = # accepted visits self.geo_history = {} self.current_index = None self.last_index = None # number of Monte Carlo moves that have been accepted in the run self.num_accepted_moves = 0.0 self.initialize()
def __init__(self, atoms, maxstep=0.5, parallel_drift=0.2, energy_target=None, angle_limit=None, force_parallel_step_scale=None, remove_translation=False, use_FS=True, initialize_old=True, initialization_step_scale=1e-2, use_target_shift=True, target_shift_previous_steps=10, seed=19460926, verbose=False, trajectory=None, logfile=None, use_tangent_curvature=False, force_consistent=None, append_trajectory=False, loginterval=1): '''Perpendicular drift breaks orbits like dimer form, so they spin on new axes''' if force_parallel_step_scale is None: # a hureistic guess since most systems will overshoot when there is drift FPSS = 0.9 + 0.5 * parallel_drift else: FPSS = force_parallel_step_scale self.verbose = verbose self.seed = seed self.remove_translation = remove_translation self.use_FS = use_FS self.force_consistent = force_consistent self.kappa = 0.0 # initializing so logging can work self.use_tangent_curvature = use_tangent_curvature #### for FS taylor expansion self.T = None self.Told = None self.N = None self.Nold = None self.r_old = None self.r = None ###### initialize rng self.rng = default_rng(seed) ####### if energy_target is None: self.energy_target = atoms.get_potential_energy( force_consistent=self.force_consistent) else: self.energy_target = energy_target # these need to be initialized before the initialize_old step so it doesn't crash self.previous_energies = np.zeros(target_shift_previous_steps) ## initizing the previous steps at the target energy slows ## target shifting untill the system has had ## 'target_shift_previous_steps' steps to equilibrate ## this should prevent occilations self.previous_energies.fill(self.energy_target) # we need velocities or this won't run and will produce NaNs, # if none are provided we make random ones p = atoms.get_momenta() masses = atoms.get_masses()[:, np.newaxis] v = p / masses from ase import units if np.linalg.norm(v) < 1e-6: # we have to pass dimension since atoms are not yet stored v = self.rand_vect((len(atoms), 3)) atoms.set_momenta(v / masses) print("No Velocities found, random velocities applied") if initialize_old: #self.step_size = maxstep*initialization_step_scale self.maxstep = maxstep * initialization_step_scale self.parallel_drift = 0.0 ## should force_parallel_step_scale be 0.0 for a better initial curvature? ## Or at least smaller than 1.0? doesn't seem to matter much self.force_parallel_step_scale = 1.0 self.use_target_shift = False self.atoms = atoms self.step() #self.step_size = maxstep # this interfers with logging self.maxstep = maxstep self.angle_limit = angle_limit self.parallel_drift = parallel_drift self.force_parallel_step_scale = FPSS self.use_target_shift = use_target_shift ## loginterval exists for the MolecularDynamics class but not the more ## general Dynamics class Dynamics.__init__( self, atoms, logfile, trajectory, #loginterval, append_trajectory=append_trajectory, )
def __init__(self, atoms, timestep, trajectory, logfile=None, loginterval=1, append_trajectory=False): """Molecular Dynamics object. Parameters: atoms: Atoms object The Atoms object to operate on. timestep: float The time step in ASE time units. trajectory: Trajectory object or str Attach trajectory object. If *trajectory* is a string a Trajectory will be constructed. Use *None* for no trajectory. logfile: file object or str (optional) If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. loginterval: int (optional) Only write a log line for every *loginterval* time steps. Default: 1 append_trajectory: boolean (optional) Defaults to False, which causes the trajectory file to be overwriten each time the dynamics is restarted from scratch. If True, the new structures are appended to the trajectory file instead. """ # dt as to be attached _before_ parent class is initialized self.dt = timestep Dynamics.__init__(self, atoms, logfile=None, trajectory=None) self.masses = self.atoms.get_masses() self.max_steps = None if 0 in self.masses: warnings.warn('Zero mass encountered in atoms; this will ' 'likely lead to errors if the massless atoms ' 'are unconstrained.') self.masses.shape = (-1, 1) if not self.atoms.has('momenta'): self.atoms.set_momenta(np.zeros([len(self.atoms), 3])) # Trajectory is attached here instead of in Dynamics.__init__ # to respect the loginterval argument. try: if trajectory is not None: if isinstance(trajectory, str): mode = "a" if append_trajectory else "w" trajectory = self.ensureclose( Trajectory(trajectory, mode=mode, atoms=atoms) ) self.attach(trajectory, interval=loginterval) if logfile: logger = self.ensureclose( MDLogger(dyn=self, atoms=atoms, logfile=logfile)) self.attach(logger, loginterval) except BaseException: self._closefiles() raise
def __init__(self, atoms, maxstep=0.5, parallel_drift=0.1, energy_target=None, angle_limit=20, potentiostat_step_scale=None, remove_translation=False, use_frenet_serret=True, initialization_step_scale=1e-2, use_target_shift=True, target_shift_previous_steps=10, use_tangent_curvature=False, rng=np.random, force_consistent=None, trajectory=None, logfile=None, append_trajectory=False, loginterval=1): """Contour Exploration object. Parameters: atoms: Atoms object The Atoms object to operate on. Atomic velocities are required for the method. If the atoms object does not contain velocities, random ones will be applied. maxstep: float Used to set the maximum distance an atom can move per iteration (default value is 0.5 Å). parallel_drift: float The fraction of the update step that is parallel to the contour but in a random direction. Used to break symmetries. energy_target: float The total system potential energy for that the potentiostat attepts to maintain. (defaults the initial potential energy) angle_limit: float or None Limits the stepsize to a maximum change of direction angle using the curvature. Gives a scale-free means of tuning the stepsize on the fly. Typically less than 30 degrees gives reasonable results but lower angle limits result in higher potentiostatic accuracy. Units of degrees. (default 20°) potentiostat_step_scale: float or None Scales the size of the potentiostat step. The potentiostat step is determined by linear extrapolation from the current potential energy to the target_energy with the current forces. A potentiostat_step_scale > 1.0 overcorrects and < 1.0 undercorrects. By default, a simple heuristic is used to selected the valued based on the parallel_drift. (default None) remove_translation: boolean When True, the net momentum is removed at each step. Improves potentiostatic accuracy slightly for bulk systems but should not be used with constraints. (default False) use_frenet_serret: Bool Controls whether or not the Taylor expansion of the Frenet-Serret formulas for curved path extrapolation are used. Required for using angle_limit based step scalling. (default True) initialization_step_scale: float Controls the scale of the initial step as a multiple of maxstep. (default 1e-2) use_target_shift: boolean Enables shifting of the potentiostat target to compensate for systematic undercorrection or overcorrection by the potentiostat. Uses the average of the *target_shift_previous_steps* to prevent coupled occilations. (default True) target_shift_previous_steps: int The number of pevious steps to average when using use_target_shift. (default 10) use_tangent_curvature: boolean Use the velocity unit tangent rather than the contour normals from forces to compute the curvature. Usually not as accurate. (default False) rng: a random number generator Lets users control the random number generator for the parallel_drift vector. (default numpy.random) force_consistent: boolean (default None) trajectory: Trajectory object or str (optional) Attach trajectory object. If *trajectory* is a string a Trajectory will be constructed. Default: None. logfile: file object or str (optional) If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. Default: None. loginterval: int (optional) Only write a log line for every *loginterval* time steps. Default: 1 append_trajectory: boolean Defaults to False, which causes the trajectory file to be overwriten each time the dynamics is restarted from scratch. If True, the new structures are appended to the trajectory file instead. """ if potentiostat_step_scale is None: # a heuristic guess since most systems will overshoot when there is # drift self.potentiostat_step_scale = 1.1 + 0.6 * parallel_drift else: self.potentiostat_step_scale = potentiostat_step_scale self.rng = rng self.remove_translation = remove_translation self.use_frenet_serret = use_frenet_serret self.force_consistent = force_consistent self.use_tangent_curvature = use_tangent_curvature self.initialization_step_scale = initialization_step_scale self.maxstep = maxstep self.angle_limit = angle_limit self.parallel_drift = parallel_drift self.use_target_shift = use_target_shift # These will be populated once self.step() is called, but could be set # after instantiating with ce = ContourExploration(...) like so: # ce.Nold = Nold # ce.r_old = atoms_old.get_positions() # ce.Told = Told # to resume a previous contour trajectory. self.T = None self.Told = None self.N = None self.Nold = None self.r_old = None self.r = None if energy_target is None: self.energy_target = atoms.get_potential_energy( force_consistent=self.force_consistent) else: self.energy_target = energy_target # Initizing the previous steps at the target energy slows # target_shifting untill the system has had # 'target_shift_previous_steps' steps to equilibrate and should prevent # occilations. These need to be initialized before the initialize_old # step to prevent a crash self.previous_energies = np.full(target_shift_previous_steps, self.energy_target) # these first two are purely for logging, # auto scaling will still occur # and curvature will still be found if use_frenet_serret == True self.step_size = 0.0 self.curvature = 0 # loginterval exists for the MolecularDynamics class but not for # the more general Dynamics class Dynamics.__init__( self, atoms, logfile, trajectory, # loginterval, append_trajectory=append_trajectory, ) # we need velocities or NaNs will be produced, # if none are provided we make random ones velocities = self.atoms.get_velocities() if np.linalg.norm(velocities) < 1e-6: # we have to pass dimension since atoms are not yet stored atoms.set_velocities(self.rand_vect())
def __init__( self, atoms, temperature=1500.0, maximum_temp=None, minimum_temp=None, stop_steps=400, logfile='grandcanonical.log', trajectory='grandcanonical.traj', local_minima_trajectory='local_minima.traj', local_minima_trajecotry_db="local_minima.db", adjust_cm=False, restart=False, chemical_potential=None, bash_script="optimize.sh", files_to_copied=None, ): """Parameters: atoms: Atoms object The Atoms object to operate on. trajectory: string Pickle file used to store trajectory of atomic movement. logfile: file object or str If *logfile* is a string, a file with that name will be opened. Use '-' for stdout. """ self.T = temperature if maximum_temp is None: self.max_T = 1.0 / ((1.0 / self.T) / 1.5) else: self.max_T = max([maximum_temp, self.T]) if minimum_temp is None: self.min_T = 1.0 / ((1.0 / self.T) * 1.5) else: self.min_T = min([minimum_temp, self.T]) self.stop_steps = stop_steps self.restart = restart self.bash_script = bash_script self.copied_files = files_to_copied # some file names and folders are hardcoded self.fn_current_atoms = "Current_atoms.traj" self.fn_status_file = "Current_Status.json" self.opt_folder = "opt_folder" self.structure_modifiers = {} self.adjust_cm = adjust_cm if 0: self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.lm_trajectory = Trajectory(local_minima_trajectory, 'a', atoms) self.lm_trajectory = connect(local_minima_trajecotry_db) # Dynamics.__init__ simply set # self.atoms and # self.logfile and # self.trajectory and # self.nsteps Dynamics.__init__(self, atoms, logfile, trajectory) # print the program logo at the beginning of the output file self.logfile.write("%s\n" % programlogo) self.logfile.flush() # setup the chemical potential for different elements self.mu = {} if chemical_potential is not None and os.path.isfile( chemical_potential): with open(chemical_potential, "r") as fp: for i, istr in enumerate(fp): if istr.strip() == "": continue k, v = istr.split() self.mu[k] = float(v) else: raise RuntimeError("chemical potential file %s is not found" % chemical_potential) for k, v in self.mu.items(): self.dumplog("Chemical potential of %s is %.3f" % (k, v)) # try to read previous result if self.restart: if (not os.path.isfile(self.fn_status_file)) or ( not os.path.isfile(self.fn_current_atoms)): self.dumplog("%s or %s no found, start from scratch\n" % (self.fn_current_atoms, self.fn_status_file)) self.restart = False elif os.path.getsize(self.fn_current_atoms) == 0: self.dumplog("{} is empty, set self.restart=False".format( self.fn_current_atoms)) self.restart = False else: try: atoms = read(self.fn_current_atoms) atoms.get_potential_energy() except PropertyNotImplementedError: self.dumplog( "No energy found in {}, set self.restart=False".format( self.fn_current_atoms)) self.restart = False except RuntimeError as e: self.dumplog( "Error when read {}, set self.restart=False".format(e)) self.restart = False self.energy = None self.free_energy = None self.energy_min = None self.free_energy_min = None self.no_improvement_step = 0 # negative value indicates no on-going structure optimization, otherwise it will be the on-going optimization self.on_optimization = -1 # this is used for adjusting the temperature of Metropolis algorithm self.accept_history = [ ] # a series of 0 and 1, 0 stands for not accpeted, 1 stands for accepted self.max_history = 25 # max length of self.accept_history is 25 if not self.restart: self.initialize() else: self.reload_previous_results()
def __init__( self, atoms, temperature=100 * kB, optimizer=FIRE, optimizer2=FIRE, #which optimizer to use to fmax_mult*fmax fmax_mult=15, #at what multiple of fmax do you want to use second optimizer fmax=0.1, dr=0.1, logfile='-', trajectory='lowest.traj', optimizer_logfile='stdout.log', local_minima_trajectory='temp_local_minima.traj', #local minima found adjust_cm=True, movemode=0, #Pick a way for displacement. 0->random cartesian, 1->delocalized internals, 2->Periodic maxmoves=1000, #Should prevent an issue, where you get stuck in a structure, for which get_energy() fails numdelocmodes=1, #should a LC of modes be applied for the displacement? How many should be combined? adsorbmask=None, #mask that specifies where the adsorbate is located in the atoms object (list of lowest and highest pos) cell_scale=[1.0, 1.0, 1.0], #used for translation in adsorbates constrain=False): #constrain stretches? Dynamics.__init__(self, atoms, logfile, trajectory) if adsorbmask is None: self.adsorbate = (0, len(atoms)) self.ads = False else: self.adsorbate = adsorbmask self.ads = True self.fmax_mult = fmax_mult self.cell_scale = cell_scale self.kT = temperature if numdelocmodes < 1: if self.ads: self.numdelmodes = int( np.round(numdelocmodes * len(atoms[self.adsorbate[0]:self.adsorbate[1]]) * 3)) #3N dis in adsorbates else: self.numdelmodes = int( np.round(numdelocmodes * (len(atoms) * 3 - 6))) #3N-6 dis in gas phase else: self.numdelmodes = int(np.round( numdelocmodes)) #round and int just for you trolls out there self.optimizer = optimizer self.optimizer2 = optimizer2 self.fmax = fmax self.mm = maxmoves self.dr = dr self.lowstep = 0 self.movemode = movemode self.movename = 'Random Cartesian' self.minima = [] self.constr = constrain if movemode == 1: self.movename = 'Delocalized Internals, using %i modes' % self.numdelmodes elif movemode == 2: self.movename = 'Periodic DI' if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.lmfile = local_minima_trajectory self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): self.lm_trajectory = Trajectory(local_minima_trajectory, 'a', atoms) self.startT = datetime.now() self.log(msg='STARTING BASINHOPPING at ' + self.startT.strftime('%Y-%m-%d %H:%M:%S') + ':\n Displacements: ' + self.movename + ' Stepsize: %.3f fmax: %.3f T: %4.2f\n' % (self.dr, self.fmax, self.kT / kB)) self.positions = 0.0 * self.atoms.get_positions() self.Emin = self.get_energy(self.atoms.get_positions()) or 1.e15 self.rmin = self.atoms.get_positions() self.call_observers() self.log(-1, self.Emin, self.Emin)
def __init__( self, atoms, temperature=100 * kB, optimizer=SDLBFGS, fmax=0.1, move_atoms=True, dr=0.1, swap_atoms=False, elements_lib=None, #elements which will be swapped, i.e., elements_lib = ['Au', 'Rh'] active_ratio=1.0, #define the number of atoms moved or swapped each time visited_configs={}, # {'state_number': [energy, atoms, repeats], ...}, comp_eps_e=1.e-4, #criterion to determine if two configurations are identtical in energy comp_eps_r=0.02, #criterion to determine if two configurations are identical in geometry logfile='-', trajectory=None, optimizer_logfile='-', local_minima_trajectory='local_minima.con', adjust_cm=True, mss=0.05, minenergy=None, distribution='uniform', adjust_step_size=None, target_ratio=0.5, adjust_fraction=0.05, significant_structure=False, # displace from minimum if accept # significant_structure2 = False, # displace from global minimum found so far at each move pushapart=0.4, jumpmax=5000): Dynamics.__init__(self, atoms, logfile, trajectory) self.kT = temperature self.optimizer = optimizer self.fmax = fmax self.move_atoms = move_atoms self.dr = dr self.swap_atoms = swap_atoms self.elements_lib = elements_lib self.active_ratio = active_ratio self.visited_configs = visited_configs self.comp_eps_e = comp_eps_e self.comp_eps_r = comp_eps_r if adjust_cm: self.cm = atoms.get_center_of_mass() else: self.cm = None self.optimizer_logfile = optimizer_logfile self.lm_trajectory = local_minima_trajectory if isinstance(local_minima_trajectory, str): tsase.io.write_con(self.lm_trajectory, atoms, w='w') self.minenergy = minenergy self.distribution = distribution self.adjust_step_size = adjust_step_size self.target_ratio = target_ratio self.adjust_fraction = adjust_fraction self.significant_structure = significant_structure # self.significant_structure2 = significant_structure2 self.pushapart = pushapart self.jumpmax = jumpmax self.mss = mss self.initialize()