def capped_uff_nanotube(cnt,NcapN=0, NcapS=0, optimize_uff=1, out_xyz="/tmp/cnt.xyz"): """ build capped nanotube and optimize it with UFF """ nC,nT = cnt.NrCapAtoms() print "Expected number of Thomson points nT = %s" % nT print "If the caps have holes or very close atoms, you should try increasing" print "or reducing the number of Thomson points (by changing the options NcapN or NcapS)" if NcapN == 0: NcapN = nT if NcapS == 0: NcapS = nT """ Different number of Thomson points are tested to find a pair (NcapN,NcapS) """ dcap = [] dnmin=0 dnmax=1 ntrial=5 for dnN in range(dnmin, dnmax): for dnS in range(dnmin, dnmax): # try for 5 times for n in range(0, ntrial): dcap.append( (dnN,dnS) ) dcap = sorted(dcap, key=lambda (a,b): abs(a)+abs(b)) for (dnN,dnS) in dcap: print "north cap: %s points, south cap: %s points" % (NcapN+dnN,NcapS+dnS) atomlist_carbons = capped_nanotube(cnt,NcapN+dnN,NcapS+dnS) if optimize_uff == 1: print "CNT will be optimized further with the Universal Force Field of G09" tmp_dir="/tmp" com_file = join(tmp_dir, "cnt_uff_opt.com") chk_file = join(tmp_dir, "cnt_uff_opt.chk") fchk_file = chk_file.replace(".chk", ".fchk") Gaussian.write_input(com_file, atomlist_carbons, \ route="# UFF Opt", \ title="Optimize (%s,%s)-Nanotube with UFF" % (cnt.n1,cnt.n2), chk=chk_file,mem=1000) try: Gaussian.run(com_file) # format checkpoint file Gaussian.formchk(chk_file, fchk_file) Data = Checkpoint.parseCheckpointFile(fchk_file) pos = Data["_Current_cartesian_coordinates"] atomlist_uff = XYZ.vector2atomlist(pos, atomlist_carbons) atomlist_carbons = atomlist_uff except Gaussian.GaussianError: print "UFF-optimization failed!" continue if check_connectivity(atomlist_carbons) == True: # no holes, correct connectivity break XYZ.write_xyz("/tmp/trials.xyz", [atomlist_carbons], mode="a") else: print "" XYZ.write_xyz(expandvars(expanduser(out_xyz)), [atomlist_carbons]) print "Geometry of capped CNT written to %s" % out_xyz
def run_gaussian(atomlist, directory="."): """ run Gaussian input script in `neb.gjf` and read energy and gradient from checkpoing file `grad.fchk`. Parameters ---------- atomlist: list of tuples with atomic numbers and cartesian positions (Zat,[x,y,z]) for each atom directory: directory where the calculation should be performed Returns ------- en : total energies of ground state (in Hartree) grad : gradient of total energy (in a.u.) """ # create directory if it does not exist already os.system("mkdir -p %s" % directory) os.system("cp neb.gjf %s/neb.gjf" % directory) # update geometry XYZ.write_xyz("%s/geometry.xyz" % directory, [atomlist]) # remove number of atoms and comment os.system("cd %s; tail -n +3 geometry.xyz > geom" % directory) # calculate electronic structure ret = os.system(r"cd %s; g09 < neb.gjf > neb.out" % directory) ret &= os.system(r"cd %s; formchk grad.chk >> neb.out" % directory) assert ret == 0, "Return status = %s, error in Gaussian calculation, see %s/neb.out!" % ( ret, directory) # read checkpoint files data = Checkpoint.parseCheckpointFile("%s/grad.fchk" % directory) en = data["_Total_Energy"] grad = data["_Cartesian_Gradient"] return en, grad
def wigner_from_G09_hessian(g09_file, Nsample=100, zero_threshold=1.0e-9): """ create Wigner ensemble based on hessian matrix from Gaussian 09 calculation """ suffix = g09_file.split(".")[-1] if suffix in ["out", "log"]: print("Reading Gaussian 09 log file %s" % g09_file) atomlist = Gaussian.read_geometry(g09_file) forces = Gaussian.read_forces(g09_file) hess = Gaussian.read_force_constants(g09_file) elif suffix in ["fchk"]: print("Reading formatted Gaussian 09 checkpoint file %s" % g09_file) Data = Checkpoint.parseCheckpointFile(g09_file) # cartesian coordinates pos = Data["_Current_cartesian_coordinates"] atnos = Data["_Atomic_numbers"] # forces frc = -Data["_Cartesian_Gradient"] atomlist = [] forces = [] for i, Zi in enumerate(atnos): atomlist.append((Zi, tuple(pos[3 * i:3 * (i + 1)]))) forces.append((Zi, tuple(frc[3 * i:3 * (i + 1)]))) # Hessian hess = Data["_Cartesian_Force_Constants"] masses = np.array(AtomicData.atomlist2masses(atomlist)) x0 = XYZ.atomlist2vector(atomlist) x0 = shift_to_com(x0, masses) grad = -XYZ.atomlist2vector(forces) grad_nrm = la.norm(grad) print(" gradient norm = %s" % grad_nrm) # assert grad_nrm < 1.0e-3, "Gradient norm too large for minimum!" vib_freq, vib_modes = vibrational_analysis(hess, masses, zero_threshold=zero_threshold) Aw, Bw = wigner_distribution(x0, hess, masses, zero_threshold=zero_threshold) gw = GaussianWavepacket.Gaussian(Aw, Bw) qs, ps = gw.sample(Nsample) mx = np.outer(masses, np.ones(Nsample)) * qs avg_com = np.mean(np.sum(mx[::3, :], axis=0)), np.mean( np.sum(mx[1::3, :], axis=0)), np.mean(np.sum(mx[2::3, :], axis=0)) print(avg_com) geometries = [ XYZ.vector2atomlist(qs[:, i], atomlist) for i in range(0, Nsample) ] return geometries
parser = optparse.OptionParser(usage) parser.add_option("--n1", dest="n1", help="Chiral index n1 [default: %default]", default=6, type=int) parser.add_option("--n2", dest="n2", help="Chiral index n2 [default: %default]", default=5, type=int) parser.add_option("--L", dest="L", help="Length of CNT in bohr [default: %default]", default=100.0, type=int) parser.add_option("--NcapN", dest="NcapN", help="Number of Thomson points on the northern cap, if set to 0 the number is estimated from the density of carbon atoms in graphene [default: %default]", default=0, type=int) parser.add_option("--NcapS", dest="NcapS", help="Number of Thomson points on the southern cap, if set to 0 the number is estimated from the density of carbon atoms in graphene [default: %default]", default=0, type=int) parser.add_option("--out_xyz", dest="out_xyz", help="Save the CNT geometry to this xyz-file [default: %default]", default="/tmp/cnt.xyz") parser.add_option("--optimize_uff", dest="optimize_uff", help="Optimize the built CNT with the UFF force field. This requires that the program g09 is installed. [default: %default]", default=1, type=int) (opts,args) = parser.parse_args() atomlist_carbons = capped_nanotube(opts.n1,opts.n2,opts.L,NcapN=opts.NcapN, NcapS=opts.NcapS) if opts.optimize_uff == 1: print("CNT will be optimized further with the Universal Force Field of G09") tmp_dir="/tmp" com_file = join(tmp_dir, "cnt_uff_opt.com") chk_file = join(tmp_dir, "cnt_uff_opt.chk") fchk_file = chk_file.replace(".chk", ".fchk") Gaussian.write_input(com_file, atomlist_carbons, \ route="# UFF Opt", title="Optimize (%s,%s)-Nanotube with UFF" % (opts.n1,opts.n2), chk=chk_file,mem=1000) Gaussian.run(com_file) # format checkpoint file Gaussian.formchk(chk_file, fchk_file) Data = Checkpoint.parseCheckpointFile(fchk_file) pos = Data["_Current_cartesian_coordinates"] atomlist_uff = XYZ.vector2atomlist(pos, atomlist_carbons) atomlist_carbons = atomlist_uff XYZ.write_xyz(opts.out_xyz, [atomlist_carbons]) print("Geometry of capped CNT written to %s" % opts.out_xyz)