def _get_solute_index(fpl_obj): try: xyz = fpl_obj.data[-1] except TypeError: xyz = [fpl_obj.data.atoms] system = fpl_obj.system ## Store end of last LAMMPs simulation to system.atoms variable for a, b in zip(system.atoms, xyz[-1]): a.x, a.y, a.z = b.x, b.y, b.z if any([np.isnan(x) for x in (a.x, a.y, a.z)]): return None ## Grab only molecules we're interested in. Here we find relative distances to the solute in question molecules_in_cluster = [] m_solute = None if fpl_obj.solute: m_solute = structures.Molecule(fpl_constants.cml_dir + fpl_obj.solute, test_charges=False, allow_errors=True) diffs = [] for molec in system.molecules: # NOTE, ORDER MATTERS! As procrustes WILL change the atomic positions of the # second list of atoms to best match the first. We don't care if m_solute # changes, but if everything else overlaps with m_solute then we have an issue. chk = [molec.atoms, m_solute.atoms] if len(chk[0]) != len(chk[1]): continue #chk = [copy.deepcopy(molec.atoms), copy.deepcopy(m_solute.atoms)] geometry.procrustes(chk) diffs.append(geometry.motion_per_frame(chk)[-1]) index_of_solute = diffs.index(min(diffs)) else: index_of_solute = 0 return index_of_solute
def align_coordinates(self, r, B=None, H=None, return_matrix=False): ''' Get a rotation matrix A that will remove rigid rotation from the new coordinates r. Further, if another vector needs rotating by the same matrix A, it should be passed in B and will be rotated. If a matrix also needs rotating, it can be passed as H and also be rotated. *Parameters* r: *list, float* 1D array of atomic coordinates to be rotated by procrustes matrix A. B: *list, list, float, optional* A list of vectors that may also be rotated by the same matrix as *r*. H: *list, list, float, optional* A matrix that should also be rotated via: H = R * H * R.T return_matrix: *bool, optional* Whether to also return the rotation matrix used or not. *Returns* rotations: *dict* A dictionary holding 'A', the rotation matrix, 'r', the rotated new coordinates, 'B', a list of all other vectors that were rotated, and 'H', a rotated matrix. ''' # Prevent rotation or translation coord_count = 0 st = self.states for s in st[1:-1]: for a in s: a.x, a.y, a.z = r[coord_count:coord_count + 3] coord_count += 3 # Translate and rotate each frame to fit its neighbor # Note, procrustes will change st[-1] which is fine as we need this # for spring force calculations A = geometry.procrustes(st) coord_count = 0 for s in st[1:-1]: for a in s: r[coord_count:coord_count + 3] = [a.x, a.y, a.z] coord_count += 3 C = [] R = block_diag(*A[0:-len(st[0])]) if B is not None: for b in B: # Validation code that a 1D array here works the same way. # shape = b.shape # b2 = b.flatten().dot(R) # C.append(b2.reshape(shape)) C.append(np.dot(b, R)) if C == []: C = None if H is not None: # Note, to transform the Hessian matrix, it's not like a normal # vector (as above) H = R * H * R.T return_this = {'A': A, 'r': r, 'B': C, 'H': H} return return_this
def __init__( self, name, states, theory, extra_section='', initial_guess=None, spring_atoms=None, procs=1, queue=None, mem=2000, priority=None, disp=0, k=0.00367453, # 0.1 eV/A in Ha/A charge=0, fit_rigid=True, DFT='orca', opt='LBFGS', start_job=None, get_results=None, new_opt_params={}, new_auto_opt_params={}, callback=None, ci_ANEB=False, ci_N=5, ANEB_Nsim=5, ANEB_Nmax=15, add_by_energy=False): self.name = name self.states = states self.all_states = copy.deepcopy(self.states) self.theory = theory self.extra_section = extra_section self.initial_guess = initial_guess self.spring_atoms = spring_atoms self.procs = procs self.queue = queue self.mem = mem self.priority = priority self.disp = disp self.k = [k for i in states[:-1]] self.k_all = copy.deepcopy(self.k) self.k_0 = k self.charge = charge self.DFT = DFT self.opt = opt.lower() self.fit_rigid = fit_rigid self.start_job = start_job self.get_results = get_results self.ci_ANEB = ci_ANEB self.ci_img = None self.ci_N = ci_N self.add_by_energy = add_by_energy self.ANEB_Nsim = ANEB_Nsim self.ANEB_Nmax = ANEB_Nmax self.energy_gaps = None self.debug = False self.new_opt_params = new_opt_params if 'fit_rigid' not in new_opt_params: new_opt_params['fit_rigid'] = fit_rigid self.new_auto_opt_params = new_auto_opt_params if 'fit_rigid' not in new_auto_opt_params: new_auto_opt_params['fit_rigid'] = fit_rigid # Other starting parameters self.prv_RMS = None self.prv_MAX = None self.prv_MAX_E = None self.nframes = len(states) self.RMS_force = float('inf') self.MAX_force = float('inf') self.MAX_energy = float('inf') self.step = 0 self.calls_to_calculate = 0 self.calls_to_force = 0 self.callback = callback self.DFT = DFT.lower().strip() if self.DFT == 'orca': self.start_job = orca_start_job self.get_results = orca_results if self.DFT == 'g09': self.start_job = g09_start_job self.get_results = g09_results if (self.start_job is None or self.get_results is None): raise Exception( "Error - You need to either specify DFT as orca or \ g09. If not, you need to manually specify start_job and get_results.") # Ensure we have ANEB_Nsim at minimum while len(self.states) < self.ANEB_Nsim: add_frame(self) if self.fit_rigid: geometry.procrustes(self.states) # In all cases, optimize the path via rigid rotations first # Set to only if fit_rigid for comparison purposes if self.fit_rigid: geometry.procrustes(self.states) self.all_states = copy.deepcopy(self.states) # Load initial coordinates into flat array for optimizer self.flattened_states = flattened(self.states) # Raise warnings if odd starting parameters used if self.ci_ANEB and "linesearch" in self.new_opt_params and self.new_opt_params[ "linesearch"] is not None: print( "\nWARNING\nYou have chosen to have climbing image with a linesearch." ) print( "It is recommended to set linesearch to None, as at times this prevents the climbing image to" ) print("increase the energy as needed.") elif self.ci_ANEB and "linesearch" not in self.new_opt_params and self.opt in [ "BFGS", "LBFGS", "CG", "SD" ]: print( "\nWARNING\nYou have chosen to have climbing image. Beware that the default parameters for the" ) print( "optimizer you chose may have a linesearch set. It is recommended to set linesearch to None," ) print( "as at times this prevents the climbing image to increase the energy as needed." )
def __init__( self, name, states, theory, extra_section='', initial_guess=None, spring_atoms=None, procs=1, queue=None, mem=2000, priority=None, disp=0, k=0.00367453, # 0.1 eV/A in Ha/A charge=0, multiplicity=1, fit_rigid=True, DFT='orca', opt='LBFGS', start_job=None, get_results=None, new_opt_params={}, callback=None, ci_neb=False, ci_N=5, no_energy=False, orca4=True): self.name = name self.states = states self.theory = theory self.extra_section = extra_section self.initial_guess = initial_guess self.spring_atoms = spring_atoms self.procs = procs self.queue = queue self.mem = mem self.priority = priority self.disp = disp self.k = k self.charge = charge self.multiplicity = multiplicity self.DFT = DFT self.opt = opt.lower() self.fit_rigid = fit_rigid self.start_job = start_job self.get_results = get_results self.ci_neb = ci_neb self.ci_img = None self.ci_N = ci_N self.no_energy = no_energy self.new_opt_params = new_opt_params if 'fit_rigid' not in new_opt_params: new_opt_params['fit_rigid'] = fit_rigid # Other starting parameters self.prv_RMS = None self.prv_MAX = None self.prv_MAX_E = None self.nframes = len(states) self.RMS_force = float('inf') self.MAX_force = float('inf') self.MAX_energy = float('inf') self.step = 0 self.calls_to_force = 0 self.calls_to_calculate = 0 self.callback = callback self.job_hang_time = None self.DFT = DFT.lower().strip() if self.DFT == 'orca': self.start_job = orca_start_job self.get_results = orca_results if self.DFT == 'g09': self.start_job = g09_start_job self.get_results = g09_results if (self.start_job is None or self.get_results is None): raise Exception( "Error - You need to either specify DFT as orca or \ g09. If not, you need to manually specify start_job and get_results.") # In all cases, optimize the path via rigid rotations first # Set to only if fit_rigid for comparison purposes if self.fit_rigid: geometry.procrustes(self.states) # Load initial coordinates into flat array for optimizer self.coords_start = [] for s in states[1:-1]: for a in s: self.coords_start += [a.x, a.y, a.z] # Raise warnings if odd starting parameters used if self.ci_neb and "linesearch" in self.new_opt_params and self.new_opt_params[ "linesearch"] is not None: print( "\nWARNING\nYou have chosen to have climbing image with a linesearch." ) print( "It is recommended to set linesearch to None, as at times this prevents the climbing image to" ) print("increase the energy as needed.") elif self.ci_neb and "linesearch" not in self.new_opt_params and self.opt in [ "BFGS", "LBFGS", "CG", "SD" ]: print( "\nWARNING\nYou have chosen to have climbing image. Beware that the default parameters for the" ) print( "optimizer you chose may have a linesearch set. It is recommended to set linesearch to None," ) print( "as at times this prevents the climbing image to increase the energy as needed." ) if self.ci_neb and self.no_energy: raise Exception( "\nERROR\nUnable to do climbing image without energy. Let no_energy be False." ) # Setup extra_keywords variable self.extra_keywords = {"orca4": orca4}
def __init__(self, name, states, theory, extra_section='', charge=0, initial_guess=None, spring_atoms=None, procs=1, queue=None, mem=2000, priority=None, disp=0, k_max=0.1837, gamma=0.2, fit_rigid=True, DFT='orca', opt='LBFGS', start_job=None, get_results=None, new_opt_params={}, callback=None): self.name = name self.states = states self.theory = theory self.extra_section = extra_section self.charge = charge self.initial_guess = initial_guess self.spring_atoms = spring_atoms self.procs = procs self.queue = queue self.mem = mem self.priority = priority self.disp = disp self.peak = 0 self.k_max = k_max self.k = [] self.gamma = gamma self.DFT = DFT self.opt = opt.lower() self.fit_rigid = fit_rigid self.start_job = start_job self.get_results = get_results self.new_opt_params = new_opt_params if 'fit_rigid' not in new_opt_params: new_opt_params['fit_rigid'] = fit_rigid # Other starting parameters self.prv_RMS = None self.prv_MAX = None self.prv_MAX_E = None self.nframes = len(states) self.RMS_force = float('inf') self.MAX_force = float('inf') self.MAX_energy = float('inf') self.step = 0 self.initialize = True self.calls_to_calculate = 0 self.callback = callback self.DFT = DFT.lower().strip() if self.DFT == 'orca': self.start_job = orca_start_job self.get_results = orca_results if self.DFT == 'g09': self.start_job = g09_start_job self.get_results = g09_results if (self.start_job is None or self.get_results is None): raise Exception( "Error - You need to either specify DFT as orca or \ g09. If not, you need to manually specify start_job and get_results.") # In all cases, optimize the path via rigid rotations first # Set to only if fit_rigid for comparison purposes if self.fit_rigid: geometry.procrustes(self.states) # Load initial coordinates into flat array for optimizer self.coords_start = [] for s in states[1:-1]: for a in s: self.coords_start += [a.x, a.y, a.z]