def evaluate_(self, crdin, force=False): """ Utility function for computing energy and forces using AMBER. Inputs: crdin: AMBER .mdcrd file name. force: Switch for parsing the force. (Currently it always calculates the forces.) Outputs: Result: Dictionary containing energies (and optionally) forces. """ force_mdin = """Loop over conformations and compute energy and force (use ioutfnm=1 for netcdf, ntb=0 for no box) &cntrl imin = 5, ntb = 0, cut=9, nstlim = 0, nsnb = 0 / &debugf do_debugf = 1, dumpfrc = 1 / """ with wopen("%s-force.mdin" % self.name) as f: print >> f, force_mdin ## This line actually runs AMBER. self.leap(delcheck=True) self.callamber( "sander -i %s-force.mdin -o %s-force.mdout -p %s.prmtop -c %s.inpcrd -y %s -O" % (self.name, self.name, self.name, self.name, crdin)) ParseMode = 0 Result = {} Energies = [] Forces = [] Force = [] for line in open('forcedump.dat'): line = line.strip() sline = line.split() if ParseMode == 1: if len(sline) == 1 and isfloat(sline[0]): Energies.append(float(sline[0]) * 4.184) ParseMode = 0 if ParseMode == 2: if len(sline) == 3 and all( isfloat(sline[i]) for i in range(3)): Force += [float(sline[i]) * 4.184 * 10 for i in range(3)] if len(Force) == 3 * self.qmatoms: Forces.append(np.array(Force)) Force = [] ParseMode = 0 if line == '0 START of Energies': ParseMode = 1 elif line == '1 Total Force': ParseMode = 2 Result["Energy"] = np.array(Energies[1:]) Result["Force"] = np.array(Forces[1:]) return Result
def evaluate_(self, crdin, force=False): """ Utility function for computing energy and forces using AMBER. Inputs: crdin: AMBER .mdcrd file name. force: Switch for parsing the force. (Currently it always calculates the forces.) Outputs: Result: Dictionary containing energies (and optionally) forces. """ force_mdin="""Loop over conformations and compute energy and force (use ioutfnm=1 for netcdf, ntb=0 for no box) &cntrl imin = 5, ntb = 0, cut=9, nstlim = 0, nsnb = 0 / &debugf do_debugf = 1, dumpfrc = 1 / """ with wopen("%s-force.mdin" % self.name) as f: print >> f, force_mdin ## This line actually runs AMBER. self.leap(delcheck=True) self.callamber("sander -i %s-force.mdin -o %s-force.mdout -p %s.prmtop -c %s.inpcrd -y %s -O" % (self.name, self.name, self.name, self.name, crdin)) ParseMode = 0 Result = {} Energies = [] Forces = [] Force = [] for line in open('forcedump.dat'): line = line.strip() sline = line.split() if ParseMode == 1: if len(sline) == 1 and isfloat(sline[0]): Energies.append(float(sline[0]) * 4.184) ParseMode = 0 if ParseMode == 2: if len(sline) == 3 and all(isfloat(sline[i]) for i in range(3)): Force += [float(sline[i]) * 4.184 * 10 for i in range(3)] if len(Force) == 3*self.qmatoms: Forces.append(np.array(Force)) Force = [] ParseMode = 0 if line == '0 START of Energies': ParseMode = 1 elif line == '1 Total Force': ParseMode = 2 Result["Energy"] = np.array(Energies[1:]) Result["Force"] = np.array(Forces[1:]) return Result
def is_mol2_atom(line): s = line.split() if len(s) < 9: return False return all([ isint(s[0]), isfloat(s[2]), isfloat(s[3]), isfloat(s[4]), isfloat(s[8]) ])
def __init__(self, options, tgt_opts, forcefield): super(THCDF_Psi4, self).__init__(options, tgt_opts, forcefield) # Parse the input.dat file to figure out the elements and molecules MolSection = False ElemList = [] self.Molecules = [] self.throw_outs = [] for line in open(os.path.join(self.root, self.tgtdir, "input.dat")).readlines(): line = line.strip() s = line.split() if len(s) >= 3 and s[0].lower() == 'molecule' and s[2] == '{': MolSection = True self.Molecules.append(s[1]) elif len(s) >= 1 and s[0] == '}': MolSection = False elif MolSection and len(s) >= 4 and match( "^[A-Za-z]+$", s[0]) and isfloat(s[1]) and isfloat( s[2]) and isfloat(s[3]): ElemList.append(s[0].capitalize()) self.Elements = set(ElemList) xgrad = [] for p in self.pgrad: Pelem = [] for pid in self.FF.plist[p].split(): # Extract the chemical element. Pelem.append(pid.split(':')[1].split(',')[0].split('=')[1]) Pelem = set(Pelem) if len(self.Elements.intersection(Pelem)) == 0: xgrad.append(p) for p in xgrad: self.pgrad.remove(p) ## Psi4 basis set file gbslist = [i for i in self.FF.fnms if os.path.splitext(i)[1] == '.gbs'] if len(gbslist) != 1: warn_press_key( "In %s, you should only have exactly one .gbs file in the list of force field files!" % __file__) self.GBSfnm = gbslist[0] ## Psi4 input file for calculation of linear dependencies ## This is actually a file in 'forcefield' until we can figure out a better system if CheckBasis(): datlist = [ i for i in self.FF.fnms if os.path.splitext(i)[1] == '.dat' ] if len(datlist) != 1: warn_press_key( "In %s, you should only have exactly one .dat file in the list of force field files!" % __file__) self.DATfnm = datlist[0] ## Prepare the temporary directory self.prepare_temp_directory(options, tgt_opts)
def __init__(self, options, tgt_opts, forcefield): super(RDVR3_Psi4, self).__init__(options, tgt_opts, forcefield) #======================================# # Variables which are set here # #======================================# ## Which parameters are differentiated? self.objfiles = OrderedDict() self.objvals = OrderedDict() self.elements = OrderedDict() self.molecules = OrderedDict() self.callderivs = OrderedDict() self.factor = 1e6 self.bidirect = False for d in sorted(os.listdir(self.tgtdir)): if os.path.isdir(os.path.join(self.tgtdir, d)) and os.path.exists( os.path.join(self.tgtdir, d, 'objective.dat')): self.callderivs[d] = [True for i in range(forcefield.np)] self.objfiles[d] = open( os.path.join(self.tgtdir, d, 'objective.dat')).readlines() ElemList = [] Molecules = [] for line in self.objfiles[d]: line = line.strip() s = line.split() if len(s) >= 3 and s[0].lower( ) == 'molecule' and s[2] == '{': MolSection = True Molecules.append(s[1]) elif len(s) >= 1 and s[0] == '}': MolSection = False elif MolSection and len(s) >= 4 and match( "^[A-Za-z]+$", s[0]) and isfloat(s[1]) and isfloat( s[2]) and isfloat(s[3]): ElemList.append(s[0].capitalize()) self.elements[d] = set(ElemList) self.molecules[d] = Molecules for p in range(self.FF.np): Pelem = [] for pid in self.FF.plist[p].split(): # Extract the chemical element. Pelem.append( pid.split(':')[1].split(',')[0].split('=')[1]) Pelem = set(Pelem) if len(self.elements[d].intersection(Pelem)) == 0: self.callderivs[d][p] = False
def normal_modes(self, shot=0, optimize=True): logger.error('Normal modes are not yet implemented in AMBER interface') raise NotImplementedError # Copied from tinkerio.py if optimize: self.optimize(shot, crit=1e-6) o = self.calltinker("vibrate %s.xyz_2 a" % (self.name)) else: warn_once("Asking for normal modes without geometry optimization?") self.mol[shot].write('%s.xyz' % self.name, ftype="tinker") o = self.calltinker("vibrate %s.xyz a" % (self.name)) # Read the TINKER output. The vibrational frequencies are ordered. # The six modes with frequencies closest to zero are ignored readev = False calc_eigvals = [] calc_eigvecs = [] for line in o: s = line.split() if "Vibrational Normal Mode" in line: freq = float(s[-2]) readev = False calc_eigvals.append(freq) calc_eigvecs.append([]) elif "Atom" in line and "Delta X" in line: readev = True elif readev and len(s) == 4 and all( [isint(s[0]), isfloat(s[1]), isfloat(s[2]), isfloat(s[3])]): calc_eigvecs[-1].append([float(i) for i in s[1:]]) calc_eigvals = np.array(calc_eigvals) calc_eigvecs = np.array(calc_eigvecs) # Sort by frequency absolute value and discard the six that are closest to zero calc_eigvecs = calc_eigvecs[np.argsort(np.abs(calc_eigvals))][6:] calc_eigvals = calc_eigvals[np.argsort(np.abs(calc_eigvals))][6:] # Sort again by frequency calc_eigvecs = calc_eigvecs[np.argsort(calc_eigvals)] calc_eigvals = calc_eigvals[np.argsort(calc_eigvals)] os.system("rm -rf *.xyz_* *.[0-9][0-9][0-9]") return calc_eigvals, calc_eigvecs
def read_reference_data(self): """ Read the reference hydrational data from a file. """ # Read the HFE data file. This is a very simple file format: self.IDs = [] self.expval = OrderedDict() self.experr = OrderedDict() self.nicknames = OrderedDict() # We don't need every single line to be the same. This # indicates whether *any* molecule has a nickname for printing # out the nickname column. self.have_nicks = False # Again for experimental errors. Note that we're NOT using them in the optimization at this time. self.have_experr = False for line in open(self.datafile).readlines(): s = line.expandtabs().strip().split('#')[0].split() if len(s) == 0: continue ID = s[0] self.IDs.append(ID) # Dynamic field number for the experimental data. nxt = 1 # If the next field is a string, then it's the "nickname" if not isfloat(s[1]): self.have_nicks = True self.nicknames[ID] = s[1] nxt += 1 else: # We don't need nicknames on every single line. self.nicknames[ID] = ID # Read the experimental value. self.expval[ID] = float(s[nxt]) # Read the experimental error bar, or use a default value of 0.6 (from Mobley). if len(s) > (nxt + 1): self.have_experr = True self.experr[ID] = float(s[nxt + 1]) else: self.experr[ID] = 0.6 self.molecules = OrderedDict([ (i, os.path.abspath( os.path.join(self.root, self.tgtdir, 'molecules', i + self.crdsfx))) for i in self.IDs ]) for fnm, path in self.molecules.items(): if not os.path.isfile(path): logger.error( 'Coordinate file %s does not exist!\nMake sure coordinate files are in the right place\n' % path) raise RuntimeError if self.subset is not None: subset = uncommadash(self.subset) self.whfe = np.array( [1 if i in subset else 0 for i in range(len(self.IDs))]) else: self.whfe = np.ones(len(self.IDs))
def feed(self, line, linindep=False): """ Feed in a line. @param[in] line The line of data """ if linindep: if match('^ *!', line): self.destroy = True else: self.destroy = False line = sub('^ *!', '', line) line = line.split('!')[0].strip() s = line.split() self.ln += 1 # No sense in doing anything for an empty line or a comment line. if len(s) == 0 or match('^ *!', line): return None, None # Now go through all the cases. if match('^[A-Za-z][A-Za-z]? +[0-9]$', line): # This is supposed to match the element line. For example 'Li 0' self.element = s[0].capitalize() self.isdata = False self.destroy = False elif len(s) == 3 and match('[SPDFGH]+', s[0]) and isint( s[1]) and isfloat(s[2]): self.amom = s[0] if self.amom == self.last_amom: self.basis_number[self.element] += 1 else: self.basis_number[self.element] = 0 self.last_amom = self.amom self.contraction_number = -1 self.isdata = True # This is supposed to match a line like 'P 1 1.00' elif len(s) == 2 and isfloat(s[0]) and isfloat(s[1]): self.contraction_number += 1 self.isdata = True else: self.isdata = False self.destroy = False
def feed(self, line, linindep=False): """ Feed in a line. @param[in] line The line of data """ if linindep: if match('^ *!',line): self.destroy = True else: self.destroy = False line = sub('^ *!','',line) line = line.split('!')[0].strip() s = line.split() self.ln += 1 # No sense in doing anything for an empty line or a comment line. if len(s) == 0 or match('^ *!',line): return None, None # Now go through all the cases. if match('^[A-Za-z][A-Za-z]? +[0-9]$',line): # This is supposed to match the element line. For example 'Li 0' self.element = capitalize(s[0]) self.isdata = False self.destroy = False elif len(s) == 3 and match('[SPDFGH]+',s[0]) and isint(s[1]) and isfloat(s[2]): self.amom = s[0] if self.amom == self.last_amom: self.basis_number[self.element] += 1 else: self.basis_number[self.element] = 0 self.last_amom = self.amom self.contraction_number = -1 self.isdata = True # This is supposed to match a line like 'P 1 1.00' elif len(s) == 2 and isfloat(s[0]) and isfloat(s[1]): self.contraction_number += 1 self.isdata = True else: self.isdata = False self.destroy = False
def normal_modes(self, shot=0, optimize=True): logger.error('Normal modes are not yet implemented in AMBER interface') raise NotImplementedError # Copied from tinkerio.py if optimize: self.optimize(shot, crit=1e-6) o = self.calltinker("vibrate %s.xyz_2 a" % (self.name)) else: warn_once("Asking for normal modes without geometry optimization?") self.mol[shot].write('%s.xyz' % self.name, ftype="tinker") o = self.calltinker("vibrate %s.xyz a" % (self.name)) # Read the TINKER output. The vibrational frequencies are ordered. # The six modes with frequencies closest to zero are ignored readev = False calc_eigvals = [] calc_eigvecs = [] for line in o: s = line.split() if "Vibrational Normal Mode" in line: freq = float(s[-2]) readev = False calc_eigvals.append(freq) calc_eigvecs.append([]) elif "Atom" in line and "Delta X" in line: readev = True elif readev and len(s) == 4 and all([isint(s[0]), isfloat(s[1]), isfloat(s[2]), isfloat(s[3])]): calc_eigvecs[-1].append([float(i) for i in s[1:]]) calc_eigvals = np.array(calc_eigvals) calc_eigvecs = np.array(calc_eigvecs) # Sort by frequency absolute value and discard the six that are closest to zero calc_eigvecs = calc_eigvecs[np.argsort(np.abs(calc_eigvals))][6:] calc_eigvals = calc_eigvals[np.argsort(np.abs(calc_eigvals))][6:] # Sort again by frequency calc_eigvecs = calc_eigvecs[np.argsort(calc_eigvals)] calc_eigvals = calc_eigvals[np.argsort(calc_eigvals)] os.system("rm -rf *.xyz_* *.[0-9][0-9][0-9]") return calc_eigvals, calc_eigvecs
def energy_force_driver_all_external_(self): ## Create the run input files (inpcrd, prmtop) from the force field file. ## Note that the frcmod and mol2 files are required. ## This is like 'grompp' in GROMACS. _exec("tleap -f stage.leap", print_to_screen=False, print_command=False) ## This line actually runs AMBER. _exec("sander -i force.mdin -o force.mdout -p prmtop -c inpcrd -y all.mdcrd -O", print_to_screen=False, print_command=False) ## Simple parser for ParseMode = 0 Energies = [] Forces = [] Force = [] for line in open('forcedump.dat'): line = line.strip() sline = line.split() if ParseMode == 1: if len(sline) == 1 and isfloat(sline[0]): Energies.append(float(sline[0]) * 4.184) ParseMode = 0 if ParseMode == 2: if len(sline) == 3 and all(isfloat(sline[i]) for i in range(3)): Force += [float(sline[i]) * 4.184 * 10 for i in range(3)] if len(Force) == 3*self.qmatoms: Forces.append(np.array(Force)) Force = [] ParseMode = 0 if line == '0 START of Energies': ParseMode = 1 elif line == '1 Total Force': ParseMode = 2 Energies = np.array(Energies[1:]) Forces = np.array(Forces[1:]) M = np.hstack((Energies.reshape(-1,1), Forces)) return M
def read_reference_data(self): """ Read the reference hydrational data from a file. """ # Read the HFE data file. This is a very simple file format: self.IDs = [] self.expval = OrderedDict() self.experr = OrderedDict() self.nicknames = OrderedDict() # We don't need every single line to be the same. This # indicates whether *any* molecule has a nickname for printing # out the nickname column. self.have_nicks = False # Again for experimental errors. Note that we're NOT using them in the optimization at this time. self.have_experr = False for line in open(self.datafile).readlines(): s = line.expandtabs().strip().split('#')[0].split() if len(s) == 0: continue ID = s[0] self.IDs.append(ID) # Dynamic field number for the experimental data. nxt = 1 # If the next field is a string, then it's the "nickname" if not isfloat(s[1]): self.have_nicks = True self.nicknames[ID] = s[1] nxt += 1 else: # We don't need nicknames on every single line. self.nicknames[ID] = ID # Read the experimental value. self.expval[ID] = float(s[nxt]) # Read the experimental error bar, or use a default value of 0.6 (from Mobley). if len(s) > (nxt+1): self.have_experr = True self.experr[ID] = float(s[nxt+1]) else: self.experr[ID] = 0.6 self.molecules = OrderedDict([(i, os.path.abspath(os.path.join(self.root, self.tgtdir, 'molecules', i+self.crdsfx))) for i in self.IDs]) for fnm, path in self.molecules.items(): if not os.path.isfile(path): logger.error('Coordinate file %s does not exist!\nMake sure coordinate files are in the right place\n' % path) raise RuntimeError if self.subset != None: subset = uncommadash(self.subset) self.whfe = np.array([1 if i in subset else 0 for i in range(len(self.IDs))]) else: self.whfe = np.ones(len(self.IDs))
def __init__(self,options,tgt_opts,forcefield): super(THCDF_Psi4,self).__init__(options,tgt_opts,forcefield) # Parse the input.dat file to figure out the elements and molecules MolSection = False ElemList = [] self.Molecules = [] self.throw_outs = [] for line in open(os.path.join(self.root,self.tgtdir,"input.dat")).readlines(): line = line.strip() s = line.split() if len(s) >= 3 and s[0].lower() == 'molecule' and s[2] == '{': MolSection = True self.Molecules.append(s[1]) elif len(s) >= 1 and s[0] == '}': MolSection = False elif MolSection and len(s) >= 4 and match("^[A-Za-z]+$",s[0]) and isfloat(s[1]) and isfloat(s[2]) and isfloat(s[3]): ElemList.append(capitalize(s[0])) self.Elements = set(ElemList) xgrad = [] for p in self.pgrad: Pelem = [] for pid in self.FF.plist[p].split(): # Extract the chemical element. Pelem.append(pid.split(':')[1].split(',')[0].split('=')[1]) Pelem = set(Pelem) if len(self.Elements.intersection(Pelem)) == 0: xgrad.append(p) for p in xgrad: self.pgrad.remove(p) ## Psi4 basis set file gbslist = [i for i in self.FF.fnms if os.path.splitext(i)[1] == '.gbs'] if len(gbslist) != 1: warn_press_key("In %s, you should only have exactly one .gbs file in the list of force field files!" % __file__) self.GBSfnm = gbslist[0] ## Psi4 input file for calculation of linear dependencies ## This is actually a file in 'forcefield' until we can figure out a better system if CheckBasis(): datlist = [i for i in self.FF.fnms if os.path.splitext(i)[1] == '.dat'] if len(datlist) != 1: warn_press_key("In %s, you should only have exactly one .dat file in the list of force field files!" % __file__) self.DATfnm = datlist[0] ## Prepare the temporary directory self.prepare_temp_directory(options,tgt_opts)
def feed(self, line, linindep=False): """ Feed in a line. @param[in] line The line of data """ line = line.split('!')[0].strip() s = line.split() self.ln += 1 # No sense in doing anything for an empty line or a comment line. if len(s) == 0 or match('^ *!',line): return None, None # Now go through all the cases. if match('^[A-Za-z][A-Za-z]? +[0-9]$',line): # This is supposed to match the element line. For example 'Li 0' self.element = capitalize(s[0]) self.radii[self.element] = float(s[1]) self.isdata = False self.point = 0 elif len(s) >= 2 and isint(s[0]) and isfloat(s[1]): self.point += 1 self.isdata = True else: self.isdata = False
def feed(self, line, linindep=False): """ Feed in a line. @param[in] line The line of data """ line = line.split('!')[0].strip() s = line.split() self.ln += 1 # No sense in doing anything for an empty line or a comment line. if len(s) == 0 or match('^ *!', line): return None, None # Now go through all the cases. if match('^[A-Za-z][A-Za-z]? +[0-9]$', line): # This is supposed to match the element line. For example 'Li 0' self.element = s[0].capitalize() self.radii[self.element] = float(s[1]) self.isdata = False self.point = 0 elif len(s) >= 2 and isint(s[0]) and isfloat(s[1]): self.point += 1 self.isdata = True else: self.isdata = False
def read_psi_xyzesp(psiout): # Read Psi4 ESP output file for geometries, ESP values and grid points. XMode = 0 EMode = 0 ESPMode = 0 xyzs = [] xyz = [] elem = [] espxyz = [] espval = [] for line in open(psiout): s = line.split() if XMode == 1: if len(s) == 4 and isfloat(s[1]) and isfloat(s[2]) and isfloat( s[3]): e = s[0] xyz.append([float(i) for i in s[1:4]]) if EMode == 1: elem.append(e) elif len(xyz) > 0: xyzs.append(np.array(xyz)) xyz = [] XMode = 0 if ESPMode == 1: if len(s) == 4 and isfloat(s[0]) and isfloat(s[1]) and isfloat( s[2]) and isfloat(s[3]): espxyz.append([float(i) for i in s[:3]]) espval.append(float(s[3])) elif len(espxyz) > 0: # After reading in a block of ESPs, don't read any more. ESPMode = -1 if line.strip().startswith("Geometry (in Angstrom)"): XMode = 1 EMode = len(elem) == 0 if 'Electrostatic Potential' in line.strip() and ESPMode == 0: ESPMode = 1 if len(xyzs) == 0: raise Exception('%s has length zero' % psiout) return xyzs, elem, espxyz, espval
def read_psi_xyzesp(psiout): # Read Psi4 ESP output file for geometries, ESP values and grid points. XMode = 0 EMode = 0 ESPMode = 0 xyzs = [] xyz = [] elem = [] espxyz = [] espval = [] for line in open(psiout): s = line.split() if XMode == 1: if len(s) == 4 and isfloat(s[1]) and isfloat(s[2]) and isfloat(s[3]): e = s[0] xyz.append([float(i) for i in s[1:4]]) if EMode == 1: elem.append(e) elif len(xyz) > 0: xyzs.append(np.array(xyz)) xyz = [] XMode = 0 if ESPMode == 1: if len(s) == 4 and isfloat(s[0]) and isfloat(s[1]) and isfloat(s[2]) and isfloat(s[3]): espxyz.append([float(i) for i in s[:3]]) espval.append(float(s[3])) elif len(espxyz) > 0: # After reading in a block of ESPs, don't read any more. ESPMode = -1 if line.strip().startswith("Geometry (in Angstrom)"): XMode = 1 EMode = len(elem) == 0 if 'Electrostatic Potential' in line.strip() and ESPMode == 0: ESPMode = 1 if len(xyzs) == 0: raise Exception('%s has length zero' % psiout) return xyzs, elem, espxyz, espval
def get_monomer_properties(print_stuff=0): # Multiply a quantity in nm to convert to a0 nm_to_a0 = 1./0.05291772108 # Multiply a quantity in e*a0 to convert to Debye ea0_to_debye = 0.393430307 os.system("rm -rf *.log \#*") _exec(["./grompp"], print_command=False) _exec(["./mdrun"], outfnm="mdrun.txt", print_command=False) _exec("./trjconv -f traj.trr -o confout.gro -ndec 6".split(), stdin="0\n", print_command=False) x = [] q = [] for line in open("confout.gro").readlines(): sline = line.split() if len(sline) >= 6 and isfloat(sline[3]) and isfloat(sline[4]) and isfloat(sline[5]): x.append([float(i) for i in sline[3:6]]) for line in open("charges.log").readlines(): sline = line.split() if 'AtomNr' in line: q.append(float(sline[5])) mode = 0 a = [] for line in open("mdrun.txt").readlines(): if mode == 1: sline = line.split() if len(sline) == 3: if isfloat(sline[0]) and isfloat(sline[1]) and isfloat(sline[2]): a.append([float(i) for i in sline]) elif any(["nan" in s for s in sline[:3]]): a.append([1e10,1e10,1e10]) if "Computing the polarizability tensor" in line: mode = 1 x = Np.array(x) q = Np.array(q) a = Np.array(a) Dip = Np.zeros(3,dtype=float) QuadXX = 0.0 QuadYY = 0.0 QuadZZ = 0.0 OctXXZ = 0.0 OctYYZ = 0.0 OctZZZ = 0.0 for i in range(q.shape[0]): Dip += x[i]*q[i]*nm_to_a0/ea0_to_debye xx = x[i,0]*x[i,0] yy = x[i,1]*x[i,1] zz = x[i,2]*x[i,2] z = x[i,2] r2 = Np.dot(x[i,:],x[i,:]) QuadXX += 0.5*q[i]*(2*xx - yy - zz) * 10 * nm_to_a0 / ea0_to_debye QuadYY += 0.5*q[i]*(2*yy - xx - zz) * 10 * nm_to_a0 / ea0_to_debye QuadZZ += 0.5*q[i]*(2*zz - xx - yy) * 10 * nm_to_a0 / ea0_to_debye OctXXZ += 0.5*q[i]*z*(5*xx-r2) * 100 * nm_to_a0 / ea0_to_debye OctYYZ += 0.5*q[i]*z*(5*yy-r2) * 100 * nm_to_a0 / ea0_to_debye OctZZZ += 0.5*q[i]*z*(5*zz-3*r2) * 100 * nm_to_a0 / ea0_to_debye DipZ = Dip[2] AlphaXX = a[0,0] AlphaYY = a[1,1] AlphaZZ = a[2,2] # Quantities taken from Niu (2001) and Berne (1994) DipZ0 = 1.855 QuadXX0 = 2.51 QuadYY0 = -2.63 QuadZZ0 = 0.11 Quad0 = Np.sqrt((QuadXX0**2 + QuadYY0**2 + QuadZZ0**2)/3) OctXXZ0 = 2.58 OctYYZ0 = -1.24 OctZZZ0 = -1.35 Oct0 = Np.sqrt((OctXXZ0**2 + OctYYZ0**2 + OctZZZ0**2)/3) AlphaXX0 = 10.32 AlphaYY0 = 9.56 AlphaZZ0 = 9.91 Alpha0 = Np.sqrt((AlphaXX0**2 + AlphaYY0**2 + AlphaZZ0**2)/3) Err_DipZ = ((DipZ-DipZ0)/DipZ0)**2 Err_QuadXX = ((QuadXX-QuadXX0)/Quad0)**2 Err_QuadYY = ((QuadYY-QuadYY0)/Quad0)**2 Err_QuadZZ = ((QuadZZ-QuadZZ0)/Quad0)**2 Err_OctXXZ = ((OctXXZ-OctXXZ0)/Oct0)**2 Err_OctYYZ = ((OctYYZ-OctYYZ0)/Oct0)**2 Err_OctZZZ = ((OctZZZ-OctZZZ0)/Oct0)**2 Err_AlphaXX = ((AlphaXX-AlphaXX0)/Alpha0)**2 Err_AlphaYY = ((AlphaYY-AlphaYY0)/Alpha0)**2 Err_AlphaZZ = ((AlphaZZ-AlphaZZ0)/Alpha0)**2 Objective = Err_DipZ + (Err_QuadXX + Err_QuadYY + Err_QuadZZ)/3 + (Err_AlphaXX + Err_AlphaYY + Err_AlphaZZ)/3 if print_stuff: #print "\rvalues (errors): mu_z = % .3f (%.3f) q_xx = % .3f (%.3f) q_yy = % .3f (%.3f) q_zz = % .3f (%.3f) o_xxz = % .3f (%.3f) o_yyz = % .3f (%.3f) o_zzz = % .3f (%.3f) a_xx = % .3f (%.3f) a_yy = % .3f (%.3f) a_zz = % .3f (%.3f)" % (DipZ,Err_DipZ,QuadXX,Err_QuadXX,QuadYY,Err_QuadYY,QuadZZ,Err_QuadZZ,OctXXZ,Err_OctXXZ,OctYYZ,Err_OctYYZ,OctZZZ,Err_OctZZZ,AlphaXX,Err_AlphaXX,AlphaYY,Err_AlphaYY,AlphaZZ,Err_AlphaZZ) logger.info("\rvalues (errors): mu_z = % .3f (%.3f) q = % .3f % .3f % .3f (% .3f % .3f % .3f) o = % .3f % .3f % .3f (% .3f % .3f % .3f) a = %.3f %.3f %.3f (%.3f %.3f %.3f) x2 = % .4f\n" % (DipZ,Err_DipZ,QuadXX,QuadYY,QuadZZ,Err_QuadXX,Err_QuadYY,Err_QuadZZ,OctXXZ,OctYYZ,OctZZZ,Err_OctXXZ,Err_OctYYZ,Err_OctZZZ,AlphaXX,AlphaYY,AlphaZZ,Err_AlphaXX,Err_AlphaYY,Err_AlphaZZ,Objective)) #Objective = Err_DipZ + (Err_QuadXX + Err_QuadYY + Err_QuadZZ)/3 + (Err_OctXXZ + Err_OctYYZ + Err_OctZZZ)/3 + (Err_AlphaXX + Err_AlphaYY + Err_AlphaZZ)/3 Properties = OrderedDict() Properties['DipZ'] = DipZ Properties['QuadXX'] = QuadXX Properties['QuadYY'] = QuadYY Properties['QuadZZ'] = QuadZZ Properties['OctXXZ'] = OctXXZ Properties['OctYYZ'] = OctYYZ Properties['OctZZZ'] = OctZZZ Properties['AlphaXX'] = AlphaXX Properties['AlphaYY'] = AlphaYY Properties['AlphaZZ'] = AlphaZZ return Properties
def molecular_dynamics(self, nsteps, timestep, temperature=None, pressure=None, nequil=0, nsave=1000, minimize=True, anisotropic=False, threads=1, verbose=False, **kwargs): """ Method for running a molecular dynamics simulation. Required arguments: nsteps = (int) Number of total time steps timestep = (float) Time step in FEMTOSECONDS temperature = (float) Temperature control (Kelvin) pressure = (float) Pressure control (atmospheres) nequil = (int) Number of additional time steps at the beginning for equilibration nsave = (int) Step interval for saving and printing data minimize = (bool) Perform an energy minimization prior to dynamics threads = (int) Specify how many OpenMP threads to use Returns simulation data: Rhos = (array) Density in kilogram m^-3 Potentials = (array) Potential energies Kinetics = (array) Kinetic energies Volumes = (array) Box volumes Dips = (3xN array) Dipole moments EComps = (dict) Energy components """ logger.error( 'Molecular dynamics not yet implemented in AMBER interface') raise NotImplementedError md_defs = OrderedDict() md_opts = OrderedDict() # Print out averages only at the end. md_opts["printout"] = nsave md_opts["openmp-threads"] = threads # Langevin dynamics for temperature control. if temperature != None: md_defs["integrator"] = "stochastic" else: md_defs["integrator"] = "beeman" md_opts["thermostat"] = None # Periodic boundary conditions. if self.pbc: md_opts["vdw-correction"] = '' if temperature != None and pressure != None: md_defs["integrator"] = "beeman" md_defs["thermostat"] = "bussi" md_defs["barostat"] = "montecarlo" if anisotropic: md_opts["aniso-pressure"] = '' elif pressure != None: warn_once( "Pressure is ignored because temperature is turned off.") else: if pressure != None: warn_once("Pressure is ignored because pbc is set to False.") # Use stochastic dynamics for the gas phase molecule. # If we use the regular integrators it may miss # six degrees of freedom in calculating the kinetic energy. md_opts["barostat"] = None eq_opts = deepcopy(md_opts) if self.pbc and temperature != None and pressure != None: eq_opts["integrator"] = "beeman" eq_opts["thermostat"] = "bussi" eq_opts["barostat"] = "berendsen" if minimize: if verbose: logger.info("Minimizing the energy...") self.optimize(method="bfgs", crit=1) os.system("mv %s.xyz_2 %s.xyz" % (self.name, self.name)) if verbose: logger.info("Done\n") # Run equilibration. if nequil > 0: write_key("%s-eq.key" % self.name, eq_opts, "%s.key" % self.name, md_defs) if verbose: printcool("Running equilibration dynamics", color=0) if self.pbc and pressure != None: self.calltinker( "dynamic %s -k %s-eq %i %f %f 4 %f %f" % (self.name, self.name, nequil, timestep, float(nsave * timestep) / 1000, temperature, pressure), print_to_screen=verbose) else: self.calltinker("dynamic %s -k %s-eq %i %f %f 2 %f" % (self.name, self.name, nequil, timestep, float(nsave * timestep) / 1000, temperature), print_to_screen=verbose) os.system("rm -f %s.arc" % (self.name)) # Run production. if verbose: printcool("Running production dynamics", color=0) write_key("%s-md.key" % self.name, md_opts, "%s.key" % self.name, md_defs) if self.pbc and pressure != None: odyn = self.calltinker( "dynamic %s -k %s-md %i %f %f 4 %f %f" % (self.name, self.name, nsteps, timestep, float(nsave * timestep / 1000), temperature, pressure), print_to_screen=verbose) else: odyn = self.calltinker( "dynamic %s -k %s-md %i %f %f 2 %f" % (self.name, self.name, nsteps, timestep, float(nsave * timestep / 1000), temperature), print_to_screen=verbose) # Gather information. os.system("mv %s.arc %s-md.arc" % (self.name, self.name)) self.md_trajectory = "%s-md.arc" % self.name edyn = [] kdyn = [] temps = [] for line in odyn: s = line.split() if 'Current Potential' in line: edyn.append(float(s[2])) if 'Current Kinetic' in line: kdyn.append(float(s[2])) if len(s) > 0 and s[0] == 'Temperature' and s[2] == 'Kelvin': temps.append(float(s[1])) # Potential and kinetic energies converted to kJ/mol. edyn = np.array(edyn) * 4.184 kdyn = np.array(kdyn) * 4.184 temps = np.array(temps) if verbose: logger.info("Post-processing to get the dipole moments\n") oanl = self.calltinker("analyze %s-md.arc" % self.name, stdin="G,E,M", print_to_screen=False) # Read potential energy and dipole from file. eanl = [] dip = [] mass = 0.0 ecomp = OrderedDict() havekeys = set() first_shot = True for ln, line in enumerate(oanl): strip = line.strip() s = line.split() if 'Total System Mass' in line: mass = float(s[-1]) if 'Total Potential Energy : ' in line: eanl.append(float(s[4])) if 'Dipole X,Y,Z-Components :' in line: dip.append([float(s[i]) for i in range(-3, 0)]) if first_shot: for key in eckeys: if strip.startswith(key): if key in ecomp: ecomp[key].append(float(s[-2]) * 4.184) else: ecomp[key] = [float(s[-2]) * 4.184] if key in havekeys: first_shot = False havekeys.add(key) else: for key in havekeys: if strip.startswith(key): if key in ecomp: ecomp[key].append(float(s[-2]) * 4.184) else: ecomp[key] = [float(s[-2]) * 4.184] for key in ecomp: ecomp[key] = np.array(ecomp[key]) ecomp["Potential Energy"] = edyn ecomp["Kinetic Energy"] = kdyn ecomp["Temperature"] = temps ecomp["Total Energy"] = edyn + kdyn # Energies in kilojoules per mole eanl = np.array(eanl) * 4.184 # Dipole moments in debye dip = np.array(dip) # Volume of simulation boxes in cubic nanometers # Conversion factor derived from the following: # In [22]: 1.0 * gram / mole / (1.0 * nanometer)**3 / AVOGADRO_CONSTANT_NA / (kilogram/meter**3) # Out[22]: 1.6605387831627252 conv = 1.6605387831627252 if self.pbc: vol = np.array([BuildLatticeFromLengthsAngles(*[float(j) for j in line.split()]).V \ for line in open("%s-md.arc" % self.name).readlines() \ if (len(line.split()) == 6 and isfloat(line.split()[1]) \ and all([isfloat(i) for i in line.split()[:6]]))]) / 1000 rho = conv * mass / vol else: vol = None rho = None prop_return = OrderedDict() prop_return.update({ 'Rhos': rho, 'Potentials': edyn, 'Kinetics': kdyn, 'Volumes': vol, 'Dips': dip, 'Ecomps': ecomp }) return prop_return
def __init__(self,options,tgt_opts,forcefield): super(RDVR3_Psi4,self).__init__(options,tgt_opts,forcefield) #======================================# # Variables which are set here # #======================================# ## Which parameters are differentiated? self.objfiles = OrderedDict() self.objvals = OrderedDict() self.elements = OrderedDict() self.molecules = OrderedDict() self.callderivs = OrderedDict() self.factor = 1e6 self.bidirect = False for d in sorted(os.listdir(self.tgtdir)): if os.path.isdir(os.path.join(self.tgtdir,d)) and os.path.exists(os.path.join(self.tgtdir,d,'objective.dat')): self.callderivs[d] = [True for i in range(forcefield.np)] self.objfiles[d] = open(os.path.join(self.tgtdir,d,'objective.dat')).readlines() ElemList = [] Molecules = [] for line in self.objfiles[d]: line = line.strip() s = line.split() if len(s) >= 3 and s[0].lower() == 'molecule' and s[2] == '{': MolSection = True Molecules.append(s[1]) elif len(s) >= 1 and s[0] == '}': MolSection = False elif MolSection and len(s) >= 4 and match("^[A-Za-z]+$",s[0]) and isfloat(s[1]) and isfloat(s[2]) and isfloat(s[3]): ElemList.append(capitalize(s[0])) self.elements[d] = set(ElemList) self.molecules[d] = Molecules for p in range(self.FF.np): Pelem = [] for pid in self.FF.plist[p].split(): # Extract the chemical element. Pelem.append(pid.split(':')[1].split(',')[0].split('=')[1]) Pelem = set(Pelem) if len(self.elements[d].intersection(Pelem)) == 0: self.callderivs[d][p] = False
def molecular_dynamics(self, nsteps, timestep, temperature=None, pressure=None, nequil=0, nsave=1000, minimize=True, anisotropic=False, threads=1, verbose=False, **kwargs): """ Method for running a molecular dynamics simulation. Required arguments: nsteps = (int) Number of total time steps timestep = (float) Time step in FEMTOSECONDS temperature = (float) Temperature control (Kelvin) pressure = (float) Pressure control (atmospheres) nequil = (int) Number of additional time steps at the beginning for equilibration nsave = (int) Step interval for saving and printing data minimize = (bool) Perform an energy minimization prior to dynamics threads = (int) Specify how many OpenMP threads to use Returns simulation data: Rhos = (array) Density in kilogram m^-3 Potentials = (array) Potential energies Kinetics = (array) Kinetic energies Volumes = (array) Box volumes Dips = (3xN array) Dipole moments EComps = (dict) Energy components """ logger.error('Molecular dynamics not yet implemented in AMBER interface') raise NotImplementedError md_defs = OrderedDict() md_opts = OrderedDict() # Print out averages only at the end. md_opts["printout"] = nsave md_opts["openmp-threads"] = threads # Langevin dynamics for temperature control. if temperature != None: md_defs["integrator"] = "stochastic" else: md_defs["integrator"] = "beeman" md_opts["thermostat"] = None # Periodic boundary conditions. if self.pbc: md_opts["vdw-correction"] = '' if temperature != None and pressure != None: md_defs["integrator"] = "beeman" md_defs["thermostat"] = "bussi" md_defs["barostat"] = "montecarlo" if anisotropic: md_opts["aniso-pressure"] = '' elif pressure != None: warn_once("Pressure is ignored because temperature is turned off.") else: if pressure != None: warn_once("Pressure is ignored because pbc is set to False.") # Use stochastic dynamics for the gas phase molecule. # If we use the regular integrators it may miss # six degrees of freedom in calculating the kinetic energy. md_opts["barostat"] = None eq_opts = deepcopy(md_opts) if self.pbc and temperature != None and pressure != None: eq_opts["integrator"] = "beeman" eq_opts["thermostat"] = "bussi" eq_opts["barostat"] = "berendsen" if minimize: if verbose: logger.info("Minimizing the energy...") self.optimize(method="bfgs", crit=1) os.system("mv %s.xyz_2 %s.xyz" % (self.name, self.name)) if verbose: logger.info("Done\n") # Run equilibration. if nequil > 0: write_key("%s-eq.key" % self.name, eq_opts, "%s.key" % self.name, md_defs) if verbose: printcool("Running equilibration dynamics", color=0) if self.pbc and pressure != None: self.calltinker("dynamic %s -k %s-eq %i %f %f 4 %f %f" % (self.name, self.name, nequil, timestep, float(nsave*timestep)/1000, temperature, pressure), print_to_screen=verbose) else: self.calltinker("dynamic %s -k %s-eq %i %f %f 2 %f" % (self.name, self.name, nequil, timestep, float(nsave*timestep)/1000, temperature), print_to_screen=verbose) os.system("rm -f %s.arc" % (self.name)) # Run production. if verbose: printcool("Running production dynamics", color=0) write_key("%s-md.key" % self.name, md_opts, "%s.key" % self.name, md_defs) if self.pbc and pressure != None: odyn = self.calltinker("dynamic %s -k %s-md %i %f %f 4 %f %f" % (self.name, self.name, nsteps, timestep, float(nsave*timestep/1000), temperature, pressure), print_to_screen=verbose) else: odyn = self.calltinker("dynamic %s -k %s-md %i %f %f 2 %f" % (self.name, self.name, nsteps, timestep, float(nsave*timestep/1000), temperature), print_to_screen=verbose) # Gather information. os.system("mv %s.arc %s-md.arc" % (self.name, self.name)) self.md_trajectory = "%s-md.arc" % self.name edyn = [] kdyn = [] temps = [] for line in odyn: s = line.split() if 'Current Potential' in line: edyn.append(float(s[2])) if 'Current Kinetic' in line: kdyn.append(float(s[2])) if len(s) > 0 and s[0] == 'Temperature' and s[2] == 'Kelvin': temps.append(float(s[1])) # Potential and kinetic energies converted to kJ/mol. edyn = np.array(edyn) * 4.184 kdyn = np.array(kdyn) * 4.184 temps = np.array(temps) if verbose: logger.info("Post-processing to get the dipole moments\n") oanl = self.calltinker("analyze %s-md.arc" % self.name, stdin="G,E,M", print_to_screen=False) # Read potential energy and dipole from file. eanl = [] dip = [] mass = 0.0 ecomp = OrderedDict() havekeys = set() first_shot = True for ln, line in enumerate(oanl): strip = line.strip() s = line.split() if 'Total System Mass' in line: mass = float(s[-1]) if 'Total Potential Energy : ' in line: eanl.append(float(s[4])) if 'Dipole X,Y,Z-Components :' in line: dip.append([float(s[i]) for i in range(-3,0)]) if first_shot: for key in eckeys: if strip.startswith(key): if key in ecomp: ecomp[key].append(float(s[-2])*4.184) else: ecomp[key] = [float(s[-2])*4.184] if key in havekeys: first_shot = False havekeys.add(key) else: for key in havekeys: if strip.startswith(key): if key in ecomp: ecomp[key].append(float(s[-2])*4.184) else: ecomp[key] = [float(s[-2])*4.184] for key in ecomp: ecomp[key] = np.array(ecomp[key]) ecomp["Potential Energy"] = edyn ecomp["Kinetic Energy"] = kdyn ecomp["Temperature"] = temps ecomp["Total Energy"] = edyn+kdyn # Energies in kilojoules per mole eanl = np.array(eanl) * 4.184 # Dipole moments in debye dip = np.array(dip) # Volume of simulation boxes in cubic nanometers # Conversion factor derived from the following: # In [22]: 1.0 * gram / mole / (1.0 * nanometer)**3 / AVOGADRO_CONSTANT_NA / (kilogram/meter**3) # Out[22]: 1.6605387831627252 conv = 1.6605387831627252 if self.pbc: vol = np.array([BuildLatticeFromLengthsAngles(*[float(j) for j in line.split()]).V \ for line in open("%s-md.arc" % self.name).readlines() \ if (len(line.split()) == 6 and isfloat(line.split()[1]) \ and all([isfloat(i) for i in line.split()[:6]]))]) / 1000 rho = conv * mass / vol else: vol = None rho = None prop_return = OrderedDict() prop_return.update({'Rhos': rho, 'Potentials': edyn, 'Kinetics': kdyn, 'Volumes': vol, 'Dips': dip, 'Ecomps': ecomp}) return prop_return
def is_mol2_atom(line): s = line.split() if len(s) < 9: return False return all([isint(s[0]), isfloat(s[2]), isfloat(s[3]), isfloat(s[4]), isfloat(s[8])])