def example_1(): # In this example, we will generate a smooth CNH-HCN isomerization # guessed pathway # Step 1 - Generate the bad initial guess print("Step 1 - Generate the bad initial guess...") H_coords = [(2, 0), (2, 1), (1, 1), (0, 1), (-1, 1), (-1, 0)] CNH_frames = [[ structures.Atom("C", 0, 0, 0), structures.Atom("N", 1, 0, 0), structures.Atom("H", x, y, 0) ] for x, y in H_coords] # Further, randomly rotate the atoms CNH_frames = [ geometry.perturbate(frame, dx=0.0, dr=360) for frame in CNH_frames ] files.write_xyz(CNH_frames, "rotated_pathway.xyz") # Step 2 - Use procrustes to remove rotations print("Step 2 - Use Procrustes to remove rotations...") geometry.procrustes(CNH_frames) files.write_xyz(CNH_frames, "procrustes_pathway.xyz") # Step 3 - Smooth out the band by minimizing the RMS atomic motion between # consecutive frames until it is below 0.1 (with a max of 50 frames). print("Step 3 - Smooth out the band...") CNH_frames = geometry.smooth_xyz(CNH_frames, R_max=0.1, F_max=50, use_procrustes=True) # Save smoothed band files.write_xyz(CNH_frames, "smoothed_pathway.xyz")
rmax = float(argv[argv.index('-rmax') + 1]) if "-fmax" in argv[2:]: fmax = int(argv[argv.index('-fmax') + 1]) frames = files.read_xyz(path + file_name + ".xyz") if interpolate: frames_hold = [copy.deepcopy(f) for f in frames] if b_start is not None: frames = frames[b_start:b_stop] frames = geometry.smooth_xyz(frames, R_MAX=rmax, F_MAX=fmax, PROCRUSTES=True, N_FRAMES=nframes) if b_start is not None: a = frames_hold[:b_start] b = frames c = frames_hold[b_stop - 1:] if not isinstance(a[0], list): a = [a] if not isinstance(b[0], list): b = [b] if not isinstance(c[0], list): c = [c] frames = a + b + c _ = geometry.procrustes(frames) files.write_xyz(frames, path + file_name + append + ".xyz")
# Squid imports from squid import files from squid import geometry # First we want to read in the manually made iterations fptrs = [int(f.split(".xyz")[0]) for f in os.listdir("reaction_coordinate")] fptrs.sort() # Now, we loop through all files in numerical order and append to our reaction coordinate rxn = [] for f in fptrs: rxn.append(files.read_xyz("reaction_coordinate/%d.xyz" % f)) # Save an example of this rough reaction we made files.write_xyz(rxn, "reaction_coordinate_rough") # Now, we smooth it out. There are many ways of doing so. We'll only show the main two methods here # Here we just make a copy of the frames for the second method held_rough_reaction = copy.deepcopy(rxn) # Method 1 - Procrustes to minimize rotations and translations between consecutive frames geometry.procrustes(rxn) files.write_xyz(rxn, "reaction_coordinate_procrustes") # Method 2 - Procrustes plus linear interpolation # Note, R_MAX is the maximum average change in atomic positions between adjacent frames (in angstroms) # F_MAX is the maximum number of frames we want in the final reaction coordinate rxn = copy.deepcopy(held_rough_reaction) # Grab the previously rough reaction geometry.smooth_xyz(rxn, R_MAX=0.1,
def job(run_name, atoms, ecut, ecutrho=None, atom_units="Ang", route=None, pseudopotentials=None, periodic_distance=15, dumps="dump End Ecomponents ElecDensity", queue=None, walltime="00:30:00", procs=1, threads=None, redundancy=False, previous=None, mem=2000, priority=None, xhost=None, allocation=None): ''' Wrapper to submitting a JDFTx simulation. **Parameters** run_name: *str* Name of the simulation to be run. atoms: *list,* :class:`squid.structures.atom.Atom` *, or str* A list of atoms for the simulation. If a string is passed, it is assumed to be an xyz file (relative or full path). If None is passed, then it is assumed that previous was specified. ecut: *float* The planewave cutoff energy in Hartree. ecutrho: *float, optional* The charge density cutoff in Hartree. By default this is 4 * ecut. atom_units: *str, optional* What units your atoms are in. JDFTx expects bohr; however, typically most work in Angstroms. Whatever units are converted to bohr here. route: *str, optional* Any additional script to add to the JDFTx simulation. pseudopotentials: *list, str, optional* The pseudopotentials to use in this simulation. If nothing is passed, a default set of ultra-soft pseudo potentials will be chosen. periodic_distance: *float, optional* The periodic box distance in Bohr. dumps: *str, optional* The outputs for this simulation. queue: *str, optional* What queue to run the simulation on (queueing system dependent). procs: *int, optional* How many processors to run the simulation on. threads: *int, optional* How many threads to run the simulation on. By default this is procs. redundancy: *bool, optional* With redundancy on, if the job is submitted and unique_name is on, then if another job of the same name is running, a pointer to that job will instead be returned. previous: *str, optional* Name of a previous simulation for which to try reading in information using the MORead method. mem: *float, optional* Amount of memory per processor that is available (in MB). priority: *int, optional* Priority of the simulation (queueing system dependent). Priority ranges (in NBS) from a low of 1 (start running whenever) to a high of 255 (start running ASAP). xhost: *list, str or str, optional* Which processor to run the simulation on(queueing system dependent). allocation: *str, optional* Whether to use a slurm allocation for this job or not. If so, specify the name. **Returns** job: :class:`squid.jobs.container.JobObject` Teturn the job container. ''' raise Exception("NEEDS TO BE DONE!") if len(run_name) > 31 and queue is not None: raise Exception("Job name too long (%d) for NBS. \ Max character length is 31." % len(run_name)) jdftx_path, jdftx_path_scripts = get_jdftx_obj() # Generate the orca input file os.system('mkdir -p jdftx/%s' % run_name) if previous is not None: shutil.copyfile( "jdftx/%s/%s.xyz" % (previous, previous), "jdftx/%s/%s.xyz" % (run_name, previous)) shutil.copyfile( "jdftx/%s/%s.xyz" % (previous, previous), "jdftx/%s/%s.xyz" % (run_name, run_name)) shutil.copyfile( "jdftx/%s/%s.ionpos" % (previous, previous), "jdftx/%s/%s.ionpos" % (run_name, previous)) shutil.copyfile( "jdftx/%s/%s.lattice" % (previous, previous), "jdftx/%s/%s.lattice" % (run_name, previous)) os.chdir('jdftx/%s' % run_name) # Start from a blank output file if os.path.isfile("%s.out" % run_name): os.system("mv %s.out %s_prev.out" % (run_name, run_name)) if threads is None: threads = procs if jdftx_path.endswith("/"): jdftx_path = jdftx_path[:-1] if jdftx_path_scripts.endswith("/"): jdftx_path_scripts = jdftx_path_scripts[:-1] if atoms is not None: if not isinstance(atoms, str): for a in atoms: a.element = units.elem_i2s(a.element) files.write_xyz(atoms, "%s.xyz" % run_name) else: atoms = files.read_xyz(atoms) for a in atoms: a.element = units.elem_i2s(a.element) files.write_xyz(atoms, "%s.xyz" % run_name) if run_name.endswith(".xyz"): run_name = run_name.split(".xyz")[0] # NOTE! xyzToIonposOpt will convert xyz Angstroms to Bohr os.system("%s/xyzToIonposOpt %s.xyz %d > xyzToIonpos.log" % (jdftx_path_scripts, run_name, periodic_distance)) previous_name = None if previous: previous_name = previous previous = "initial-state %s.$VAR" % previous # First, read in the xyz file to determine unique elements if pseudopotentials is None and atoms is not None: pseudopotentials = [] elements = geometry.reduce_list([a.element.lower() for a in atoms]) all_pps = [fname for fname in os.listdir( "%s/pseudopotentials/GBRV" % jdftx_path) if fname.endswith("uspp") and "pbe" in fname] for e in elements: potential_pps = [] for pp in all_pps: if pp.startswith("%s_" % e): potential_pps.append(pp) if len(potential_pps) < 1: raise Exception( "Unable to automatically grab potential for element %s." % e) else: # In theory this should be the "largest" number based on # the naming convention. potential_pps.sort() pseudopotentials.append("GBRV/" + potential_pps[0]) if atoms is None: pseudopotentials = '''ion-species GBRV/$ID_pbe_v1.2.uspp ion-species GBRV/$ID_pbe_v1.01.uspp ion-species GBRV/$ID_pbe_v1.uspp''' else: pseudopotentials = "\n".join([ "ion-species %s" % pp for pp in pseudopotentials]) script = ''' # --------------- Molecular Structure ---------------- $$ATOMS$$ coords-type cartesian $$PREVIOUS$$ # --------------- System Parameters ---------------- elec-cutoff $$ECUT$$ $$ECUTRHO$$ # Specify the pseudopotentials (this defines species O and H): $$PSEUDOPOTENTIALS$$ # --------------- Outputs ---------------- dump-name $$NAME$$.$VAR #Filename pattern for outputs $$DUMPS$$ #Output energy components and electron density at the end ''' atom_str = '''include $$NAME$$.lattice include $$NAME$$.ionpos''' if atoms is not None: atom_str = atom_str.replace("$$NAME$$", run_name) else: if previous_name is None: raise Exception("Forgot to specify previous when atoms is None!") atom_str = atom_str.replace("$$NAME$$", previous_name) script = script.replace("$$ATOMS$$", atom_str) while "$$NAME$$" in script: script = script.replace("$$NAME$$", run_name) if ecutrho is None: ecutrho = "" while "$$ECUTRHO$$" in script: script = script.replace("$$ECUTRHO$$", str(ecutrho)) while "$$ECUT$$" in script: script = script.replace("$$ECUT$$", str(ecut)) while "$$PSEUDOPOTENTIALS$$" in script: script = script.replace("$$PSEUDOPOTENTIALS$$", pseudopotentials) if previous is not None: script = script.replace("$$PREVIOUS$$", previous) else: script = script.replace("$$PREVIOUS$$", "") script = script.replace("$$DUMPS$$", dumps) if route is not None: script += "\n# --------------- Outputs ----------------\n\n" script += route.strip() + "\n\n" fptr = open("%s.in" % run_name, 'w') fptr.write(script) fptr.close() # Run the simulation if queue is None: process_handle = subprocess.Popen( "%s/jdftx -i %s.in -o %s.out" % (jdftx_path, run_name, run_name), shell=True ) elif queue == 'debug': print('Would run %s' % run_name) else: job_to_submit =\ "source ~/.zshrc\nmpirun -n %d jdftx -c %d -i %s.in -o %s.out"\ % (procs, threads, run_name, run_name) jobs.submit_job(run_name, job_to_submit, procs=procs, queue=queue, mem=mem, priority=priority, walltime=walltime, xhosts=xhost, redundancy=redundancy, unique_name=True, allocation=allocation) time.sleep(0.5) # Copy run script fname = sys.argv[0] if '/' in fname: fname = fname.split('/')[-1] try: shutil.copyfile('../../%s' % fname, fname) except IOError: # Submitted a job oddly enough that sys.argv[0] # is not the original python file name, so don't do this pass # Return to the appropriate directory os.chdir('../..') if queue is None: return jobs.Job(run_name, process_handle=process_handle) else: return jobs.Job(run_name)
def ovito_xyz_to_gif(frames, scratch, fname="image", camera_pos=(10, 0, 0), camera_dir=(-1, 0, 0), size=(800, 600), delay=10, display_cell=False, renderer="OpenGLRenderer", renderer_settings={}, overwrite=False): ''' This function will, using the ovito python api, generate either a single image or a gif of the input frames. Note, a gif is only generated when more than one frame exists. **Parameters** frames: *str* or *list,* :class:`squid.structures.atom.Atom` A list of frames you wish to generate an image for, or a path to an xyz file. scratch: *str* A directory you want to have each image saved to. fname: *str, optional* The prefix for the image names. camera_pos: *tuple, float, optional* A tuple of x, y, and z coordinates for the camera to be positioned. camera_dir: *tuple, float, optional* The direction the camera is facing. size: *tuple, int, optional* Image size (width, height). delay: *int, optional* In the event of a gif, how long it should play for. display_cell: *bool, optional* Whether to display the box around the system or not. renderer: *str, optional* What kind of renderer you wish to use: OpenGL or Tachyon. renderer_settings: *dict, optional* Here you can change specific renderer settings. overwrite: *bool, optional* Whether to delete any files already existing in the scratch dir. **Returns** None ''' convert_path = which("convert") assert convert_path is not None,\ "Error - Cannot find convert in the PATH env var." if fname.endswith(".gif"): fname.replace(".gif", "") # First ensure we have frames and things in the correct format if isinstance(frames, str): frames = open(frames) if not isinstance(frames[0], list): frames = [frames] if not scratch.endswith("/"): scratch += "/" # Next, ensure scratch exists if not os.path.exists(scratch): os.system("mkdir -p %s" % scratch) elif len(os.listdir(scratch)) > 0: if overwrite: os.system("rm %s/*.png" % scratch) else: raise Exception("Error - Scratch directory is not empty!") # For each frame, generate an image for i, frame in enumerate(frames): write_xyz(frame, "tmp.xyz") ovito_xyz_to_image("tmp.xyz", scratch, fname="%04d" % i, camera_pos=camera_pos, camera_dir=camera_dir, size=size, renderer=renderer, renderer_settings=renderer_settings, display_cell=display_cell) os.system("rm tmp.xyz") # If more than one frame exists, compile to gif if len(frames) > 1: cmd = "convert -delay $DELAY -loop 0 $(ls -v $PATH/*.png) output.gif" holders = [("$PATH", str(scratch)), ("$DELAY", str(delay))] for s_id, val in holders: cmd = cmd.replace(s_id, val) os.system(cmd) os.rename("output.gif", fname + ".gif")
# Step 1 - Find how many frames exist fptrs = [ f for f in os.listdir("lammps") if f.startswith("%s-%d-" % (name, index)) ] if index == 0: fptrs = fptrs[1:-1] start = files.read_xyz("lammps/%s-0-0/%s_0.xyz" % (name, name)) end = files.read_xyz("lammps/%s-0-%d/%s_%d.xyz" % (name, len(fptrs) + 1, name, len(fptrs) + 1)) if only is not None: start = [s for i, s in enumerate(start) if i in only] end = [s for i, s in enumerate(end) if i in only] frames = [start] for i, f in enumerate(fptrs): frame = files.read_xyz("lammps/%s-%d-%d/%s_%d.xyz" % (name, index, i + 1, name, i + 1)) if only is not None: frame = [s for j, s in enumerate(frame) if j in only] frames.append(frame) frames.append(end) return frames for i in [3]: files.write_xyz(compile("solv_box", i), "%d_chk.xyz" % i) #files.write_xyz(compile("solv_box", i, only=range(24)), "%d_chk.xyz" % i)
def get_optimized_geometry(): optimized_CNH_start = orca.read("CNH_start").frames[-1] optimized_CNH_end = orca.read("CNH_end").frames[-1] files.write_xyz(optimized_CNH_start, "CNH_start_opt") files.write_xyz(optimized_CNH_end, "CNH_end_opt")
def scanDFT(): # DEFAULTS ARE HERE (dft, u1, u2, scale, step, out_name, comp, neb_force) = ('orca', 'Ha', 'kT_300', 1.0, 1, 'out', None, None) (title, x_label, y_label, x_range, y_range, x_vals) = ('Energy Landscape', 'X-Axis', 'Y-Axis', None, None, None) peak = [] spline = None p_vals = False save = False dft_list = [dft, 'orca'] # HELP SCREEN HERE help_info = ''' scanDFT --------- A command to view the energy landscape over several configurations. There are two ways to implement this: 1. Note, the START STOP range is inclusive on either end. scanDFT [Sim_Name%%d] START STOP [Options] 2. scanDFT Sim_Name The first method is useful when utilizing flags. The second method will prompt the user for information. Note, in the second instance it will assume an appendage of -%%d-%%d, describing the iteration and frame. It also assumes and NEB scan is desired. Flag Default Description -help, -h : : Print this help menu -dft : orca : Specify what type of dft simulation you want to get the energy landscape of. Other options include 'orca'. -units, -u : kT_300 : Specify the units you want the output to be in. -scale : 1.0 : Scale all energies by this value. Applied AFTER unit conversion from simulation units ('Ha') to -units. -out, -o : out : Make an output file with this name holding all xyz coordinates of what you're scanning over. -step : 1.0 : Steps to take between your start and stop range -c : : Compile multiple energy landscapes on the same graph. Takes three arguments, separated by commas with no spaces: char,start,stop The character is a unique identifier in the Sim_Name that will be replaced with values from start to stop (inclusive) -neb : : In NEB calculations, each iteration after the first does not include the first and last energies. Giving this flag and a run name for the first in the NEB list will tack on these energies to the rest of the simulations. -title, -t : : Title for the output graph -lx : : Label for the x-axis -ly : : Label for the y-axis -xrange : : Set the x-axis range -yrange : : Set the y-axis range -xvals : : Set a custom label for x-axis (comma separated). -print, -p : : Print out the values that are plotted. -save, -s : : Whether to save the graph to out.png (True) or not (False). Note, when saving it will not display the graph. ex: scanDFT water ex: scanDFT water_ 1 10 ex: scanDFT water_%d 1 10 ex: scanDFT water%d_opt 1 10 ex: scanDFT water_^_%d 1 10 -c ^,0,4 -dft orca ex: scanDFT water_^_%d 1 10 -c ^,2,4 -dft orca -neb water_0_0,water_0_10 ex: scanDFT water_opt_%d 1 10 -t "Water Optimization" -xrange 0,5 ''' ########################################################################## # READ IN FLAGS HERE ########################################################################## if '-h' in sys.argv or '-help' in sys.argv or len(sys.argv) < 2: print(help_info) sys.exit() # READ IN DATA run_name = sys.argv[1] # Check if we shall prompt user if len(sys.argv) < 3: dft = input( "What method of dft was used (orca/g09, default orca)? " ).lower().strip() if dft == 'g09': directory = "gaussian" read = g09.read elif dft == 'orca' or dft == '': directory = "orca" read = orca.read else: print("Error - Cannot proceed with DFT as %s." % dft) sys.exit() # Determine the number of iterations and frames print("Determining number of successful iterations and frames... "), N, M = 0, 0 if dft == 'g09': while os.path.isfile( "%s/%s-%d-%d.chk" % (directory, run_name, N, M)): M += 1 max_frame = M - 1 while os.path.isfile("%s/%s-%d-1.chk" % (directory, run_name, N)): N += 1 max_iter = N - 1 # Verify the last iteration did indeed succeed success = True for i in range(1, max_frame): try: _ = read("%s-%d-%d" % (run_name, max_iter, i)) except: peak.append(i) if len(peak) == 1: peak = float(peak[0]) spline = 'y' elif len(peak) > 1: success = False else: pass if not success: max_iter -= 1 if max_iter < 0: print( "\nError - Final iteration that succeeded is less than 0.") sys.exit() else: while os.path.isfile( "%s/%s-0-%d/%s-0-%d.out" % (directory, run_name, M, run_name, M)): M += 1 max_frame = M - 1 while os.path.isfile("%s/%s-%d-1/%s-%d-1.out" % (directory, run_name, N, run_name, N)): N += 1 max_iter = N - 1 # Verify the last iteration did indeed succeed success = True for i in range(1, max_frame): try: _ = read("%s-%d-%d" % (run_name, max_iter, i)).energies[-1] except: peak.append(i) if len(peak) == 1: peak = float(peak[0]) spline = 'y' elif len(peak) > 1: success = False else: pass if not success: max_iter -= 1 if max_iter < 0: print( "\nError - Final iteration that succeeded is less than 0.") sys.exit() print("Done") print("\tThere are a total of %d iterations of %d frames each.\n" % (max_iter, max_frame)) plot_all = input( "Would you like to plot them all (y/n)? ").lower() if plot_all in ['y', 'yes', 'sure', 'ok', 'do it', 'i dare you']: iterations_to_plot = list(range(max_iter + 1)) frames_to_plot = list(range(max_frame + 1)) else: try: iterations_to_plot = eval(input( "\nWhich iterations would you like to \ plot? Input as a python range (ex. range(3,6) for iterations 3,4,5): ")) except: print("\tDefaulting, only plotting last iteration...\n") iterations_to_plot = [max_iter] frames_to_plot = list(range(max_frame + 1)) if type(iterations_to_plot) is not list: print("Error - iterations_to_plot must be a list!") sys.exit() if type(frames_to_plot) is not list: print("Error - frames_to_plot must be a list!") sys.exit() # Now we can ask for plotting requests plotting_flags = input("\nUnits (%s): " % u2).strip() if plotting_flags != "": u2 = plotting_flags plotting_flags = input("\nScale (%lg): " % scale).strip() if plotting_flags != "": scale = float(plotting_flags) plotting_flags = input("\nPlot Title (%s): " % title).strip() if plotting_flags != "": title = plotting_flags try: plotting_flags = input("\nX Axis Title: ").strip() if plotting_flags != "": x_label = plotting_flags except: print("\tDefaulting, X Axis label is \"%s\"...\n" % x_label) try: plotting_flags = input("\nY Axis Title: ").strip() if plotting_flags != "": y_label = plotting_flags except: print("\tDefaulting, Y Axis label is \"%s\"...\n" % y_label) x_range, y_range = None, None try: plotting_flags = eval(input( "\nX Range as an inclusive tuple (xmin,xmax): ")) x_range = plotting_flags except: print("\tDefaulting, X Range is [0:%d]...\n" % max_frame) try: plotting_flags = eval(input( "\nY Range as an inclusive tuple (ymin,ymax): ")) y_range = plotting_flags except: print("\tDefaulting, Y Range is [min_E, max_E*1.05]...\n") try: plotting_flags = input("\nOutput xyz filename? ").strip() if plotting_flags != "": out_name = plotting_flags except: print("\tDefaulting, xyz filename is \"%s.xyz\"...\n" % out_name) if ".xyz" in out_name: out_name = out_name.split(".xyz")[0] try: plotting_flags = input("\nSave plot to a png file instead of display \ (y/N)? ") if plotting_flags != "": save = plotting_flags.strip().lower() == "y" except: print("\tDefaulting, will display and not save.") # At this point we have all the information we need from the user. # We can now get the starting and ending energies of the NEB first_E, peak_E, last_E = None, None, None first_frame, peak_frame, last_frame = None, None, None first_E = read("%s-0-0" % run_name).energies[-1] first_frame = read("%s-0-0" % run_name).atoms last_E = read("%s-0-%d" % (run_name, max_frame)).energies[-1] last_frame = read("%s-0-%d" % (run_name, max_frame)).atoms if spline == 'y': peak_E = read("%s-0-%d" % (run_name, peak)).energies[-1] peak_frame = read("%s-0-%d" % (run_name, peak)).atoms else: pass # Loop through all the iterations requested full_energy_list, energies, pathway = [], [], [] for iteration in iterations_to_plot: energies = [] pathway = [] for frame in frames_to_plot: if frame == 0: energy = first_E atoms = first_frame elif frame == max_frame: energy = last_E atoms = last_frame elif frame == peak and spline == 'y': energy = peak_E atoms = peak_frame else: energy = read( "%s-%d-%d" % (run_name, iteration, frame) ).energies[-1] atoms = read( "%s-%d-%d" % (run_name, iteration, frame) ).atoms energies.append( units.convert_energy(u1, u2, energy - first_E) * scale ) pathway.append(atoms) full_energy_list.append(energies) # Save the final iteration xyz files.write_xyz(pathway, "%s" % out_name) # Plot the graph plot(full_energy_list, iterations_to_plot[0], x_label, y_label, title, x_range, y_range, x_low=frames_to_plot[0], save=save, x_vals=x_vals, u2=u2) else: start = int(sys.argv[2]) stop = int(sys.argv[3]) if '-dft' in sys.argv: dft = sys.argv[sys.argv.index('-dft') + 1].lower() if dft not in dft_list: print("Error - %s not recognized for dft." % dft) sys.exit() if [s for s in ['-units', '-u'] if s in sys.argv]: s = '-u' if '-u' in sys.argv else '-units' u2 = sys.argv[sys.argv.index(s) + 1] if u2 not in constants.ENERGY: print("Error - Energy unit not available. \ Consider using -scale.") sys.exit() if '-scale' in sys.argv: scale = float(sys.argv[sys.argv.index('-scale') + 1]) if '-step' in sys.argv: step = int(sys.argv[sys.argv.index('-step') + 1]) if [s for s in ['-o', '-out'] if s in sys.argv]: s = '-o' if '-o' in sys.argv else '-out' out_name = sys.argv[sys.argv.index(s) + 1].replace(' ', '_') if len(out_name) < 5 or out_name[-4:] != '.xyz': out_name += '.xyz' if '-c' in sys.argv: comp = sys.argv[sys.argv.index('-c') + 1].split(',') if '-neb' in sys.argv: neb_force = sys.argv[sys.argv.index('-neb') + 1].split(',') if [s for s in ['-t', '-title'] if s in sys.argv]: s = '-t' if '-t' in sys.argv else '-title' title = sys.argv[sys.argv.index(s) + 1] if '-lx' in sys.argv: x_label = sys.argv[sys.argv.index('-lx') + 1] if '-ly' in sys.argv: y_label = sys.argv[sys.argv.index('-ly') + 1] x_range, y_range = None, None if '-xrange' in sys.argv: x_range = sys.argv[sys.argv.index('-xrange') + 1].split(',') x_range = [float(x) for x in x_range] if '-yrange' in sys.argv: y_range = sys.argv[sys.argv.index('-yrange') + 1].split(',') y_range = [float(y) for y in y_range] if '-xvals' in sys.argv: x_vals = sys.argv[sys.argv.index('-xvals') + 1].split(',') x_vals = [float(x) for x in x_vals] if [s for s in ['-p', '-print'] if s in sys.argv]: p_vals = True if [s for s in ['-s', '-save'] if s in sys.argv]: save = True # BEGIN MAKING ENERGY LANDSCAPE if dft == 'g09': read = g09.read elif dft == 'orca': read = orca.read else: print("Error - Cannot proceed with DFT as %s." % dft) sys.exit() ###################################################################### first_E, last_E = None, None first_frame, last_frame = None, None if neb_force is not None: first_E = read(neb_force[0]).energies[-1] first_frame = read(neb_force[0]).atoms last_E = read(neb_force[1]).energies[-1] last_frame = read(neb_force[1]).atoms energies, frames = [], [] # Loop through energies if comp is None: comp = [None, 0, 0] for c in range(int(comp[1]), int(comp[2]) + 1): run_hold = run_name.replace( comp[0], str(c) ) if comp[0] is not None else run_name tmp_E, tmp_frames = [], [] if neb_force is not None: tmp_frames.append(first_frame) tmp_E.append(first_E) for i in range(start, stop + 1, step): # Get run name for this iteration chk = run_hold.find('%') == -1 run = run_hold + str(i) if chk else run_hold % i data = read(run) tmp_E.append(data.energies[-1]) tmp_frames.append(data.atoms) if neb_force is not None: tmp_frames.append(last_frame) tmp_E.append(last_E) energies.append(tmp_E) frames = tmp_frames # Adjust energies E_offset = energies[0][0] for i in range(len(energies)): for j, e in enumerate(energies[i]): energies[i][j] = units.convert_energy( u1, u2, e - E_offset) * scale if comp[0] is not None: start -= 1 plot(energies, start, x_label, y_label, title, x_range, y_range, save=save, x_vals=x_vals, u2=u2) # Write files files.write_xyz(frames, out_name[:-4]) # Print out values if desired if p_vals: for y in energies: print(str(y))
def procrustes(): # Default Documentation help_info = ''' procrustes --------- A command line tool to run procrustes along an xyz file. procrustes [file.xyz] [Options] Flag Default Description -help, -h : : Print this help menu -overwrite, -o : : Overwrite the initial file -append, -a : _proc : Change the appended name alteration -interpolate, -i : : This will turn on linear interpolation -rmax : 0.5 : The default max rms for interpolation -fmax : 25 : The default max number of frames for interpolation -nframes, -n : : If specified, interpolate to exactly n frames. -between, -b : : If specified, then interpolation is only run between the two frames. Note, this is [x, y) inclusive. Default behaviour is to use procrustes on an xyz to best align the coordinates, and then to save a new xyz file with the name OLD_proc.xyz (where OLD is the original xyz file name). NOTE! If you specify -o and -a, then appending will occur instead of overwritting. Ex. procrustes demo.xyz procrustes demo.xyz -i -n 20 procrustes demo.xyz -i -rmax 0.1 -fmax 30 procrustes demo.xyz -i -b 5 8 -n 6 ''' # Parse Arguments if '-h' in argv or '-help' in argv or len(argv) < 2: print(help_info) exit() # Parse Arguments append = "_proc" path = os.getcwd() if not path.endswith("/"): path += "/" file_name = argv[1] interpolate = False rmax = 0.5 fmax = 25 nframes = None b_start, b_stop = None, None if ".xyz" in file_name: file_name = file_name.split(".xyz")[0] if "-o" in argv[2:]: append = "" elif "-overwrite" in argv[2:]: append = "" if "-i" in argv[2:]: interpolate = True elif "-interpolate" in argv[2:]: interpolate = True if "-a" in argv[2:]: append = argv[argv.index('-a') + 1] elif "-append" in argv[2:]: append = argv[argv.index('-append') + 1] if "-n" in argv[2:]: nframes = int(argv[argv.index('-n') + 1]) elif "-nframes" in argv[2:]: nframes = int(argv[argv.index('-nframes') + 1]) if "-b" in argv[2:]: b_start = int(argv[argv.index('-b') + 1]) b_stop = int(argv[argv.index('-b') + 2]) elif "-between" in argv[2:]: b_start = int(argv[argv.index('-between') + 1]) b_stop = int(argv[argv.index('-between') + 2]) assert b_start >= 0, "b_start must be >= 0." assert b_stop >= 2 + b_start, "b_stop must be >= 2 + b_start." if "-rmax" in argv[2:]: rmax = float(argv[argv.index('-rmax') + 1]) if "-fmax" in argv[2:]: fmax = int(argv[argv.index('-fmax') + 1]) frames = files.read_xyz(path + file_name + ".xyz") if interpolate: frames_hold = [copy.deepcopy(f) for f in frames] if b_start is not None: frames = frames[b_start:b_stop] frames = geometry.smooth_xyz(frames, R_max=rmax, F_max=fmax, N_frames=nframes, use_procrustes=True) if b_start is not None: a = frames_hold[:b_start] b = frames c = frames_hold[b_stop - 1:] if not isinstance(a[0], list): a = [a] if not isinstance(b[0], list): b = [b] if not isinstance(c[0], list): c = [c] frames = a + b + c _ = geometry.procrustes(frames) files.write_xyz(frames, path + file_name + append + ".xyz")
if __name__ == "__main__": # In this example we will generate the full CNH-HCN isomerization using # only squid. Then we optimize the endpoints in DFT, smooth the frames, # and subsequently run NEB # Step 1 - Generate the bad initial guess print("Step 1 - Generate the bad initial guess...") H_coords = [(2, 0), (2, 0.5), (1, 1), (0, 1), (-1, 0.5), (-1, 0)] CNH_frames = [[ structures.Atom("C", 0, 0, 0), structures.Atom("N", 1, 0, 0), structures.Atom("H", x, y, 0) ] for x, y in H_coords] # Save initial frames files.write_xyz(CNH_frames, "bad_guess.xyz") # Step 2 - Optimize the endpoints print("Step 2 - Optimize endpoints...") frame_start_job = orca.job("frame_start", "! HF-3c Opt", atoms=CNH_frames[0], queue=None) frame_last_job = orca.job("frame_last", "! HF-3c Opt", atoms=CNH_frames[-1], queue=None) # Wait frame_start_job.wait() frame_last_job.wait()
atom.fy = units.convert("kcal/ang", "Ha/ang", float(atom.extras['fy'])) atom.fz = units.convert("kcal/ang", "Ha/ang", float(atom.extras['fz'])) energy = open("lammps/solv_box-%d-%d/energy.profile" % (step_to_use, i), 'r').read().strip().split("\n")[-1] new_energy = float(energy.strip().split()[-1].strip()) # Add the forces onto our state for a, b in zip(state, new_atoms): a.fx, a.fy, a.fz = b.fx, b.fy, b.fz return units.convert_energy("kcal/mol", "Ha", new_energy), new_atoms frames = generate_frames() files.write_xyz(frames, "neb_initial_configuration.xyz") sim = neb.NEB( 'benzene', frames, ('water.cml', 1.0), #('CH3OH.cml', 0.8), DFT="None", opt="LBFGS", queue="short", procs=4, start_job=run_simulation, get_results=read_simulation, no_energy=False) sim.optimize()
energy = last_E atoms = last_frame elif frame == peak and spline == 'y': energy = peak_E atoms = peak_frame else: energy = read("%s-%d-%d" % (run_name, iteration, frame)).energies[-1] atoms = read("%s-%d-%d" % (run_name, iteration, frame)).atoms energies.append( units.convert_energy(u1, u2, energy - first_E) * scale) pathway.append(atoms) full_energy_list.append(energies) # Save the final iteration xyz files.write_xyz(pathway, "%s" % out_name) # Plot the graph plot(full_energy_list, iterations_to_plot[0], x_label, y_label, title, x_range, y_range, x_low=frames_to_plot[0], save=save) else: start = int(sys.argv[2]) stop = int(sys.argv[3])
dash = '\n' + ''.join(['-'] * length) + '\n' try: head2 = data.route.strip() + "\n" + data.extra_section.strip() head2 = head2.strip() except AttributeError: head2 = "" if body != '': print(dash + head + dash + head2 + dash + body + dash + tail + dash) else: print(dash + head + dash + head2 + dash + tail + dash) try: if len(data.frames) > 0: if me: me = '/fs/home/%s/' % USERNAME else: me = '' files.write_xyz(data.frames, me + out_name[:-4]) if vmd: os.system('"' + sysconst.vmd_path + '" ' + me + out_name) elif ovito: os.system('"' + sysconst.ovito_path + '" ' + me + out_name) except TypeError: print("No atomic coordinates available yet...") except: print("An unexpected error has occurred.") sys.exit()
def chkDFT(): USERNAME = getuser() # One can easily change defaults here (if they do, probably change the # help text below accordingly). dft, u1, u2, out_name, vmd, ovito, me =\ 'orca', 'Ha', 'Ha', 'out', False, False, False dft_list = [dft, 'orca', 'jdftx'] if '-h' in sys.argv or '-help' in sys.argv or len(sys.argv) < 2: print(''' chkDFT --------- A command to quickly get a glimpse of a DFT simulation. chkDFT [Sim_Name] [Options] Flag Default Description -help, -h : : Print this help menu -dft : orca : Specify what type of dft simulation you want to parse. By default it is 'g09', but can be 'orca' or 'jdftx'. -units, -u : Ha : Specify the units you want the output to be in. By default this is Hartree. -scale : 1.0 : Scale all energies by this value -out, -o : out : Make an output file with this name holding all xyz coordinates. If no xyz data is available this will not run. Default output name is 'out.xyz' but user can choose their own using this command. -vmd, -v : : Opens output xyz file in vmd. Flag turns on. -ovito, -ov : : Opens output xyz file in ovito. Flag turns on. -me : : Forces the .xyz file to be saved to ~/out.xyz ex. chkDFT water -dft orca -u kT_300 ''') sys.exit() # Get simulation name run_name = sys.argv[1] # Get the dft type if '-dft' in sys.argv: dft = sys.argv[sys.argv.index('-dft') + 1].lower() if dft not in dft_list: print("Error - %s not recognized for dft." % dft) sys.exit() # Get units if '-u' in sys.argv or '-units' in sys.argv: s = '-u' if '-u' in sys.argv else '-units' u2 = sys.argv[sys.argv.index(s) + 1] if u2 not in constants.ENERGY: print("Error - Energy unit not available. Consider using -scale.") sys.exit() # Get output name if '-out' in sys.argv or '-o' in sys.argv: s = '-o' if '-o' in sys.argv else '-out' out_name = sys.argv[sys.argv.index(s) + 1].replace(' ', '_') if len(out_name) < 5 or out_name[-4:] != '.xyz': out_name += '.xyz' # Get VMD display status if '-vmd' in sys.argv or '-v' in sys.argv: vmd = True # Get ovito display status if '-ovito' in sys.argv or '-ov' in sys.argv: ovito = True # Check if me is forced if '-me' in sys.argv: me = True # Read in data if dft == 'g09': try: data = g09.read(run_name) except IOError: print("Error - g09 simulation %s does not exist. \ Are you sure -dft g09 is correct?" % run_name) sys.exit() elif dft == 'orca': try: data = orca.read(run_name) except IOError: print("Error - orca simulation %s does not exist. \ Are you sure -dft orca is correct?" % run_name) sys.exit() elif dft == "jdftx": try: data = jdftx.read(run_name) except IOError: print("Error - jdftx simulation %s does not exist. \ Are you sure -dft jdftx is correct?" % run_name) sys.exit() else: print("DFT type %s not available..." % dft) sys.exit() # Get the header information head = 'Job Name: %s\n' % run_name head += 'DFT calculation via %s\n' % dft head += 'Energy Data Points: %d\n' % len(data.energies) if len(data.energies) > 2: Ener = str( units.convert_energy(u1, u2, data.energies[-2] - data.energies[-3])) head += 'dE 2nd last = %s %s\n' % (Ener, u2) if len(data.energies) > 1: Ener = str( units.convert_energy(u1, u2, data.energies[-1] - data.energies[-2])) head += 'dE last = %s %s\n' % (Ener, u2) if len(data.energies) > 0: Ener = str(units.convert_energy(u1, u2, data.energies[-1])) head += 'Last Energy = %s %s' % (Ener, u2) body, tail = '', '' if data.convergence is not None: for line in data.convergence: body += '\t'.join([str(ss) for ss in line]) + '\n' body = print_helper.spaced_print(body, delim='\t') finished = "" if data.finished: finished = "(finished) " if data.converged: tail = 'Job %sconverged in %.2e seconds' % (finished, data.time) else: tail = 'Job %shas not converged.' % finished length = max([len(tmp) for tmp in head.split('\n')] + [len(tmp) for tmp in body.split('\n')] + [len(tmp) for tmp in tail.split('\n')]) dash = '\n' + ''.join(['-'] * length) + '\n' try: head2 = data.route.strip() + "\n" + data.extra_section.strip() head2 = head2.strip() except AttributeError: head2 = "" if body != '': print(dash + head + dash + head2 + dash + body + dash + tail + dash) else: print(dash + head + dash + head2 + dash + tail + dash) try: if len(data.frames) > 0: if me: me = '/fs/home/%s/' % USERNAME else: me = '' files.write_xyz(data.frames, me + out_name[:-4]) if vmd: vmd_path = which("vmd") assert vmd_path is not None,\ "Error - Cannot find VMD in PATH env var." os.system('"' + vmd_path + '" ' + me + out_name) elif ovito: ovito_path = which("ovito") assert ovito_path is not None,\ "Error - Cannot find ovito in PATH env var." os.system('"' + ovito_path + '" ' + me + out_name) except TypeError: print("No atomic coordinates available yet...") except: print("An unexpected error has occurred.") sys.exit()