def load_native_output(self, filename='output.dat'): """ Load the optimized geometry and energy into a new molecule object and return """ found_opt_result = False found_final_geo = False final_energy, elems, coords = None, [], [] with open(filename) as outfile: for line in outfile: line = line.strip() if line.startswith('Final energy is'): final_energy = float(line.split()[-1]) elif line.startswith('Final optimized geometry and variables'): found_opt_result = True elif found_opt_result == True: ls = line.split() if len(ls) == 4 and check_all_float(ls[1:]): elems.append(ls[0]) coords.append(ls[1:4]) if final_energy == None: raise RuntimeError("Final energy not found in %s" % filename) if len(elems) == 0 or len(coords) == 0: raise RuntimeError("Final geometry not found in %s" % filename) m = Molecule() m.elem = elems m.xyzs = [np.array(coords, dtype=np.float64)] m.qm_energies = [final_energy] m.build_topology() return m
def load_native_output(self, filename='output.dat'): """ Load the optimized geometry and energy into a new molecule object and return """ found_opt_result = False final_energy, elems, coords = None, [], [] with open(filename) as outfile: for line in outfile: line = line.strip() if line.startswith('Final energy is'): final_energy = float(line.split()[-1]) elif line.startswith('Final optimized geometry and variables'): found_opt_result = True elif found_opt_result: ls = line.split() if len(ls) == 4 and check_all_float(ls[1:]): elems.append(ls[0]) coords.append(ls[1:4]) if final_energy is None: raise RuntimeError("Final energy not found in %s" % filename) if len(elems) == 0 or len(coords) == 0: raise RuntimeError("Final geometry not found in %s" % filename) m = Molecule() m.elem = elems m.xyzs = [np.array(coords, dtype=float)] m.qm_energies = [final_energy] m.build_topology() return m
def launch_opt_jobs(self): """ Mimicing DihedralScanner.launch_opt_jobs, """ assert hasattr(self, 'next_jobs') and hasattr( self, 'current_finished_job_results') while len(self.opt_queue) > 0: m, from_grid_id, to_grid_id = self.opt_queue.pop() # check if this job already exists m_geo_key = get_geo_key(m.xyzs[0]) if m_geo_key in self.task_cache[to_grid_id]: final_geo, final_energy, job_folder = self.task_cache[ to_grid_id][m_geo_key] result_m = Molecule() result_m.elem = list(m.elem) result_m.xyzs = [final_geo] result_m.qm_energies = [final_energy] result_m.build_topology() grid_id = self.get_dihedral_id(result_m, check_grid_id=to_grid_id) if grid_id is None: print( f"Cached result from {job_folder} is ignored because optimized geometry is far from grid id {to_grid_id}" ) else: self.current_finished_job_results.push((result_m, grid_id), priority=job_folder) else: # append the job to self.next_jobs, which is the output of torsiondrive-API self.next_jobs[to_grid_id].append(m.xyzs[0].copy())
def load_geomeTRIC_output(self): """ Load the optimized geometry and energy into a new molecule object and return """ # the name of the file is consistent with the --prefix tdrive option, # this also requires the input file NOT be named to sth like tdrive.in # otherwise the output will become tdrive_optim.xyz if not os.path.isfile('tdrive.xyz'): raise OSError("geomeTRIC output tdrive.xyz file not found") m = Molecule('tdrive.xyz')[-1] m.qm_energies = [float(m.comms[0].rsplit(maxsplit=1)[-1])] return m
def load_native_output(self, filename='ligand.fchk', filename2='gaussian.log'): """ Load the optimized geometry and energy into a new molecule object and return """ # Check the log file to see if the optimization was successful opt_result = False final_energy, elems, coords = None, [], [] with open(filename2) as logfile: for line in logfile: # Accept both # Optimization completed. # Optimization completed on the basis of negligible forces. if 'Optimization completed' in line: opt_result = True break if not opt_result: raise RuntimeError("Geometry optimization failed in %s" % filename2) # Now we want to get the optimized structure from the fchk file as this is more reliable end_xyz_pos = None with open(filename) as outfile: for i, line in enumerate(outfile): if 'Current cartesian coordinates' in line: num_xyz = int(line.split()[5]) end_xyz_pos = int(np.ceil(num_xyz / 5) + i + 1) elif end_xyz_pos is not None and i < end_xyz_pos: coords.extend([ float(num) * 0.529177 for num in line.strip('\n').split() ]) elif 'Total Energy' in line: final_energy = float(line.split()[3]) if end_xyz_pos is None: raise RuntimeError( 'Cannot locate coordinates in ligand.fchk file.') # Make sure we have all of the coordinates assert len( coords) == num_xyz, "Could not extract the optimised geometry" if final_energy is None: raise RuntimeError("Final energy not found in %s" % filename) m = Molecule() m.elem = self.M.elem m.xyzs = [np.reshape(coords, (int(len(m.elem)), 3))] m.qm_energies = [final_energy] m.build_topology() return m
def finish(self): """ Write qdata.txt and scan.xyz file based on converged scan results """ m = Molecule() m.elem = list(self.engine.M.elem) m.qm_energies, m.xyzs, m.comms = [], [], [] for gid in self.grid_ids: m.qm_energies.append(self.grid_energies[gid]) m.xyzs.append(self.grid_final_geometries[gid]) m.comms.append("Dihedral %s Energy %.9f" % (str(gid), self.grid_energies[gid])) m.write('qdata.txt') print("Final scan energies are written to qdata.txt") m.write('scan.xyz') print("Final scan energies are written to scan.xyz")
def load_native_output(self, filename='lig.fchk', filename2='gaussian.log'): """ Load the optimized geometry and energy into a new molecule object and return """ found_opt_result = False final_energy, elems, coords = None, [], [] with open(filename2) as logfile: logfile = logfile.readlines() for counter, line in enumerate(logfile): line = line.strip() if line.startswith('Optimization completed'): found_opt_result = True if found_opt_result is not True: raise RuntimeError("Geometry optimisation failed in %s" % filename2) with open(filename) as outfile: outfile = outfile.readlines() for counter, line in enumerate(outfile): if line.startswith('Current cartesian coordinates'): start_xyz_pos = int(counter + 1) num_xyz = int(line.split()[5]) end_xyz_pos = int(np.ceil(num_xyz / 5) + start_xyz_pos) if line.startswith('Total Energy'): energy_pos = counter if not start_xyz_pos and end_xyz_pos: raise EOFError('Cannot locate coordinates in lig.fchk file.') for line in outfile[start_xyz_pos:end_xyz_pos]: coords.extend( [float(num) * 0.529177 for num in line.strip('\n').split()]) # Make sure we have all of the coordinates assert len( coords) == num_xyz, "Could not extract the optimised geometry" final_energy = float(outfile[energy_pos].split()[3]) if final_energy is None: raise RuntimeError("Final energy not found in %s" % filename) if len(coords) == 0: raise RuntimeError("Final geometry not found in %s" % filename) m = Molecule() m.elem = self.M.elem m.xyzs = [np.reshape(coords, (int(len(m.elem)), 3))] m.qm_energies = [final_energy] m.build_topology() return m
def finish(self): """ Write qdata.txt and scan.xyz file based on converged scan results """ m = Molecule() m.elem = list(self.engine.M.elem) m.qm_energies, m.xyzs, m.comms = [], [], [] # only print grid with energies for gid in sorted(self.grid_energies.keys()): m.qm_energies.append(self.grid_energies[gid]) m.xyzs.append(self.grid_final_geometries[gid]) m.comms.append("Dihedral %s Energy %.9f" % (str(gid), self.grid_energies[gid])) m.write('qdata.txt') print("Final scan energies are written to qdata.txt") m.write('scan.xyz') print("Final scan energies are written to scan.xyz")
def export_torsiondrive_data(molecule: "Ligand", tdrive_data: "TorsionDriveData") -> None: """ Export the stored torsiondrive data object to a scan.xyz file and qdata.txt file required for ForceBalance. Method taken from <https://github.com/lpwgroup/torsiondrive/blob/ac33066edf447e25e4beaf21c098e52ca0fc6649/torsiondrive/dihedral_scanner.py#L655> Args: molecule: The molecule object which contains the topology. tdrive_data: The results of a torsiondrive on the input molecule. """ from geometric.molecule import Molecule as GEOMol mol = GEOMol() mol.elem = [atom.atomic_symbol for atom in molecule.atoms] mol.qm_energies, mol.xyzs, mol.comms = [], [], [] for angle, grid_data in sorted(tdrive_data.reference_data.items()): mol.qm_energies.append(grid_data.energy) mol.xyzs.append(grid_data.geometry) mol.comms.append(f"Dihedral ({angle},) Energy {grid_data.energy}") mol.write("qdata.txt") mol.write("scan.xyz")
def launch_opt_jobs(self): """ Launch constrained optimizations for molecules in opt_queue Tasks current opt_queue will be popped in order. If a task exist in self.task_cache, the cached result will be checked, then put into self.current_finished_job_results Else, the task will be launched by self.launch_constrained_opt, and information is saved as self.running_job_path_info[job_path] = m, from_grid_id, to_grid_id """ assert hasattr(self, 'running_job_path_info') and hasattr( self, 'current_finished_job_results') while len(self.opt_queue) > 0: m, from_grid_id, to_grid_id = self.opt_queue.pop() # check if this job already exists m_geo_key = get_geo_key(m.xyzs[0]) if m_geo_key in self.task_cache[to_grid_id]: final_geo, final_energy, final_gradient, job_folder = self.task_cache[ to_grid_id][m_geo_key] result_m = Molecule() result_m.elem = list(m.elem) result_m.xyzs = [final_geo] result_m.qm_energies = [final_energy] if final_gradient is not None: result_m.qm_grads = [final_gradient] result_m.build_topology() grid_id = self.get_dihedral_id(result_m, check_grid_id=to_grid_id) if grid_id is None: print( f"Cached result from {job_folder} is ignored because optimized geometry is far from grid id {to_grid_id}" ) else: self.current_finished_job_results.push((result_m, grid_id), priority=job_folder) #self.grid_status[to_grid_id].append((m.xyzs[0], final_geo, final_energy)) else: job_path = self.launch_constrained_opt(m, to_grid_id) self.running_job_path_info[ job_path] = m, from_grid_id, to_grid_id
def launch_opt_jobs(self): """ Launch constrained optimizations for molecules in opt_queue The current opt_queue will be cleaned up Return a dictionary that contains path and grid_ids: { path: (from_grid_id, to_grid_id) } """ assert hasattr(self, 'running_job_path_info') and hasattr(self, 'current_finished_job_results') while len(self.opt_queue) > 0: m, from_grid_id, to_grid_id = self.opt_queue.pop() # check if this job already exists m_geo_key = get_geo_key(m.xyzs[0]) if m_geo_key in self.task_cache[to_grid_id]: final_geo, final_energy, job_folder = self.task_cache[to_grid_id][m_geo_key] result_m = Molecule() result_m.elem = list(m.elem) result_m.xyzs = [final_geo] result_m.qm_energies = [final_energy] result_m.build_topology() grid_id = self.get_dihedral_id(result_m, check_grid_id=to_grid_id) self.current_finished_job_results.push((result_m, grid_id), priority=job_folder) #self.grid_status[to_grid_id].append((m.xyzs[0], final_geo, final_energy)) else: job_path = self.launch_constrained_opt(m, to_grid_id) self.running_job_path_info[job_path] = m, from_grid_id, to_grid_id
def finish(self): """ Write qdata.txt and scan.xyz file based on converged scan results """ m = Molecule() m.elem = list(self.engine.M.elem) m.qm_energies, m.xyzs, m.comms = [], [], [] # optionally writing qm gradients into qdata.txt if avilable writing_gradients = False if len(self.grid_final_gradients) == len(self.grid_final_geometries): m.qm_grads = [] writing_gradients = True # only print grid with energies for gid in sorted(self.grid_energies.keys()): m.qm_energies.append(self.grid_energies[gid]) m.xyzs.append(self.grid_final_geometries[gid]) if writing_gradients: m.qm_grads.append(self.grid_final_gradients[gid]) m.comms.append("Dihedral %s Energy %.9f" % (str(gid), self.grid_energies[gid])) m.write('qdata.txt') print( f"Final scan energies{' and gradients' if writing_gradients else ''} are written to qdata.txt" ) m.write('scan.xyz') print("Final scan energies are written to scan.xyz")
def load_native_output(self): """ Load the optimized geometry and energy into a new molecule object and return """ m = Molecule('scr/optim.xyz')[-1] # read the energy from optim.xyz comment line m.qm_energies = [float(m.comms[0].split(maxsplit=1)[0])] return m
def load_geomeTRIC_output(self): """ Load the optimized geometry and energy into a new molecule object and return """ m = Molecule('opt.xyz') with open('energy.txt') as infile: m.qm_energies = [float(infile.read())] return m
def load_native_output(self): """ Load the optimized geometry and energy into a new molecule object and return """ m = Molecule('scr/optim.xyz')[-1] # read the energy from optim.xyz comment line m.qm_energies = [float(m.comms[0].split(None, 1)[0])] return m