def GULPRelaxation(inputStr): ##for gulp to work. gulp folder must be in the same folder as the script environ["GULP_LIB"] = "\"" + getcwd() + "/Gulp_40/Libraries/\"" environ["ASE_GULP_COMMAND"] = "\"" + getcwd( ) + "/Gulp_40/Exe/gulp.exe\" < PREFIX.gin > PREFIX.got" ##takes string inputStr and turns it into stepNb, shouldRestartFromScratch listOfAtoms if len(inputStr) % 4 != 2: print("Args nb " + str(len(inputStr))) print(inputStr) print( "Not enough args. Args order : stepNb, shouldRestartFromScratch (0 or 1), \n atom list formatted as Name Xpos Ypos Zpos for each atom (example CO2 would be C 0 0 0 O 0 1 1 O 0 1 -1)" ) return "", False atomNames = [] atomXYZ = [] stepNb = int(inputStr[0]) shouldRestartFromScratch = int(inputStr[1]) #if restart from scratch, destroy previously known trajectory if (shouldRestartFromScratch == 1): my_file = Path('tmp.pckl') if my_file.is_file(): remove('tmp.pckl') #create Atoms object to optimize for i in range(0, math.floor(len(inputStr) / 4)): atomNames.append(inputStr[4 * i + 2]) atomXYZ.append((float(inputStr[4 * i + 3]), float(inputStr[4 * i + 4]), float(inputStr[4 * i + 5]))) atoms = Atoms(atomNames, positions=atomXYZ) c = Conditions(atoms) #attach calculator calc = GULP(keywords='conp', library="./Gulp_40/Libraries/reaxff.lib") atoms.calc = calc calc.set(keywords='conp opti') #optimize opt = calc.get_optimizer(atoms) opt.run(fmax=0.05) #io.write('../MoleculeLibrary/tmp.xyz', atoms, format='xyz') pos = atoms.get_positions() outStr = "" for i in range(0, len(atomNames)): outStr += atomNames[i] + " " outStr += str(pos[i][0]) + " " outStr += str(pos[i][1]) + " " outStr += str(pos[i][2]) + " " return outStr, True
def test_gulp(): # flake8: noqa from ase.calculators.gulp import GULP, Conditions from ase import Atoms import numpy as np cluster = Atoms(symbols='O4SiOSiO2SiO2SiO2SiOSiO2SiO3SiO3H8', pbc=np.array([False, False, False], dtype=bool), cell=np.array( [[ 0., 0., 0.], [ 0., 0., 0.], [ 0., 0., 0.]]), positions=np.array( [[-1.444348, -0.43209 , -2.054785], [-0.236947, 2.98731 , 1.200025], [ 3.060238, -1.05911 , 0.579909], [ 2.958277, -3.289076, 2.027579], [-0.522747, 0.847624, -2.47521 ], [-2.830486, -2.7236 , -2.020633], [-0.764328, -1.251141, 1.402431], [ 3.334801, 0.041643, -4.168601], [-1.35204 , -2.009562, 0.075892], [-1.454655, -1.985635, -1.554533], [ 0.85504 , 0.298129, -3.159972], [ 1.75833 , 1.256026, 0.690171], [ 2.376446, -0.239522, -2.881245], [ 1.806515, -4.484208, -2.686456], [-0.144193, -2.74503 , -2.177778], [ 0.167583, 1.582976, 0.47998 ], [-1.30716 , 1.796853, -3.542121], [ 1.441364, -3.072993, -1.958788], [-1.694171, -1.558913, 2.704219], [ 4.417516, 1.263796, 0.563573], [ 3.066366, 0.49743 , 0.071898], [-0.704497, 0.351869, 1.102318], [ 2.958884, 0.51505 , -1.556651], [ 1.73983 , -3.161794, -0.356577], [ 2.131519, -2.336982, 0.996026], [ 0.752313, -1.788039, 1.687183], [-0.142347, 1.685301, -1.12086 ], [ 2.32407 , -1.845905, -2.588202], [-2.571557, -1.937877, 2.604727], [ 2.556369, -4.551103, -3.2836 ], [ 3.032586, 0.591698, -4.896276], [-1.67818 , 2.640745, -3.27092 ], [ 5.145483, 0.775188, 0.95687 ], [-2.81059 , -3.4492 , -2.650319], [ 2.558023, -3.594544, 2.845928], [ 0.400993, 3.469148, 1.733289]])) c = Conditions(cluster) c.min_distance_rule('O', 'H', 'O2', 'H', 'O1') cluster.calc = GULP( keywords='opti conp phon noden distance molq compare angle nono', shel=['O1','O2'], conditions=c) print(cluster.get_potential_energy())
def set_calc(self): keywords_ = ['conp full nosymm linmin'] keywords_.append(self.name) if len(self.keywords): self.keywords = keywords_ + self.keywords self.keywords = ' '.join(self.keywords) calc = GULP(keywords=self.keywords, options=self.options, library=self.library) self.atoms.set_calculator(calc)
def main(directory, seedname): ''' Read an extended .xyz file, run it through Gulp, and produce an electronic_structure.dat file. N.B. this requires ASE 3.19 or later, as earlier versions have problems reading forces from Gulp. N.B. the environment variable GULP_LIB must point to the Libraries directory in Gulp. ''' # Set up the calculator. # This can be replaced with any other ASE calculator. # N.B. this reads from Caesar's root working directory, # so only one settings file is needed. keywords, library, options, has_forces, has_stress = read_gulp_file( '{0}.gin'.format(seedname)) calculator = GULP(keywords=keywords, library=library, options=options) # Change to the directory where calculations should be run. os.chdir(directory) # Read the atomic positions and lattice from the extended .xyz file. atoms = ase.io.read('{0}.xyz'.format(seedname)) # Run the calculation and get the results. atoms.set_calculator(calculator) energy = atoms.get_potential_energy() if has_forces: forces = atoms.get_forces() else: forces = None if has_stress: stress = atoms.get_stress() else: stress = None # Construct the electronic_structrue.dat file. write_electronic_structure('electronic_structure.dat', energy, forces=forces, stress=stress)
def test_gulp_opt(): import numpy as np from ase.calculators.gulp import GULP from ase.optimize import BFGS from ase.build import molecule, bulk from ase.constraints import ExpCellFilter # GULP optmization test atoms = molecule('H2O') atoms1 = atoms.copy() atoms1.calc = GULP(library='reaxff.lib') with BFGS(atoms1) as opt1: opt1.run(fmax=0.005) atoms2 = atoms.copy() calc2 = GULP(keywords='opti conp', library='reaxff.lib') with calc2.get_optimizer(atoms2) as opt2: opt2.run() print(np.abs(opt1.atoms.positions - opt2.atoms.positions)) assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5 # GULP optimization test using stress atoms = bulk('Au', 'bcc', a=2.7, cubic=True) atoms1 = atoms.copy() atoms1.calc = GULP(keywords='conp gradient stress_out', library='reaxff_general.lib') atoms1f = ExpCellFilter(atoms1) with BFGS(atoms1f) as opt1: opt1.run(fmax=0.005) atoms2 = atoms.copy() calc2 = GULP(keywords='opti conp', library='reaxff_general.lib') with calc2.get_optimizer(atoms2) as opt2: opt2.run() print(np.abs(opt1.atoms.positions - opt2.atoms.positions)) assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5
def test_run_gulp_exception(STO_atoms, gulp_keywords, gulp_options, gulp_shells, gulp_library, gulp_conditions, expected_output, monkeypatch): """ GIVEN a structure and a set of gulp options, including shells WHEN we run a gulp calculation, but do not have a restart file THEN we raise an exception. Parameters ---------- STO_atoms : ASE atoms An ASE atoms object containing SrTiO_{3} and five vacancies. gulp_keywords : list, optional List of GULP keywords. gulp_options : list, optional List of GULP options. gulp_shells : list, optional List of each atomic species to have a shell attached. gulp_library : string, optional The library file containing the forcefield to be used in the calculation. gulp_setups : list, optional A list of symbols for each atom if they are not wanted to be the same as in the original atoms object --------------------------------------------------------------------------- Paul Sharp 18/01/2018 """ # Make sure we follow path where the restart file does not exist monkeypatch.setattr(os.path, 'isfile', lambda x: False) STO_atoms.set_calculator(GULP()) with pytest.raises(RuntimeError): chemdash.gulp_calc.run_gulp(STO_atoms, "gulp", "", gulp_keywords, gulp_options, gulp_shells, gulp_library, gulp_conditions)
def run_gulp(atoms='', shel=None, kwds='', opts='', lib='', produce_steps='', gulp_command='gulp < gulp.gin > gulp.got'): iat = len(atoms) converged = False if os.path.isfile("temp.res"): os.remove("temp.res") if produce_steps == True: try: files = glob.glob("atoms*.cif") for z in range(len(files)): os.remove(files[z]) except: pass for i in range(len(kwds)): if i == 0: if not 'dump temp.res\n' in opts[i]: opts[i].append('dump temp.res\n') if shel == None: calc = GULP(keywords=kwds[i], options=opts[i], library=lib) else: calc = GULP(keywords=kwds[i], options=opts[i], library=lib, shel=shel) atoms.set_calculator(calc) atoms.get_calculator().optimized = False try: energy = atoms.get_potential_energy() if len(atoms) != iat: converged = False break try: if glob.glob("gulptmp*") != []: if platform.system() == 'Windows': files = glob.glob("gulptmp*") for z in range(len(files)): os.remove(files[z]) if platform.system() == 'Linux': os.system("rm gulptmp*") except: pass except: f = open("gulp.gin", 'r') f2 = f.readlines() cell = re.findall("\d+\.\d+", f2[6]) for i in range(len(cell)): cell[i] = cell[i][:10] f.close() f3 = open("gulp.gin", 'w') f2[6] = str( str(cell[0]) + " " + str(cell[1]) + " " + str(cell[2]) + " " + str(cell[3]) + " " + str(cell[4]) + " " + str(cell[5]) + "\n") for i in range(len(f2)): f3.write(f2[i]) f3.close() atoms = read_gulp("gulp.gin") atoms.set_calculator(calc) try: energy = atoms.get_potential_energy() if len(atoms) != iat: converged = False break if glob.glob("gulptmp*") != []: if platform.system() == 'Windows': os.system("del gulptmp*") if platform.system() == 'Linux': os.system("rm gulptmp*") except: #except(ValueError): energy = 1.0e20 # break if atoms.get_calculator().optimized == True: if atoms.calc.Gnorm <= 0.01: #converged = True #try: # atoms = read_gulp("temp.res") #except: # converged = False # pass ### add in extra check to see if the calculation has REALLY converged f4 = open("gulp.got", 'r').readlines() if 'opti' in kwds[i]: if ' **** Optimisation achieved ****' in f4: converged = True else: converged = False if 'sing' in kwds[i]: converged = True if produce_steps == True: label = str("atoms" + str(i + 1) + ".cif") write(label, atoms) #os.remove("gulp.got") #os.remove("gulp.gin") if i > 0: try: f = open("temp.res", 'r').readlines() new_file = open("gulp.gin", 'w') for j in f: if "title" in j: start = f.index(j) - 1 if "totalenergy" in j: end = f.index(j) new_file.write(kwds[i]) new_file.write("\n") for j in opts[i]: new_file.write(j) new_file.write("\n") new_file.write(str("library " + str(lib))) new_file.write("\n") cp = f[start:end] for j in cp: new_file.write(j) new_file.close() os.system(gulp_command) output = open("gulp.got", 'r').readlines() if 'opti' in kwds[i]: converged = ' **** Optimisation achieved ****\n' in output if 'sing' in kwds[i]: converged = True for j in output: if "Total lattice energy" in j: if "eV" in j: e_line = j energy = float( e_line[e_line.index('-'):e_line.index('eV') - 1]) atoms = read_gulp("temp.res") if 'sing' not in kwds[i]: try: for j in output: if "Final energy" in j: e_line = j break energy = float( e_line[e_line.index('-'):e_line.index('eV') - 1]) atoms = read_gulp("temp.res") except: converged = False energy = 1.0e20 except: converged = False energy = 1.0e20 if converged == True: try: atoms = read_gulp("temp.res") except: pass else: converged = False energy = 1.0e20 #view(atoms) return atoms, energy, converged
[-0.144193, -2.74503, -2.177778], [0.167583, 1.582976, 0.47998], [-1.30716, 1.796853, -3.542121], [1.441364, -3.072993, -1.958788], [-1.694171, -1.558913, 2.704219], [4.417516, 1.263796, 0.563573], [3.066366, 0.49743, 0.071898], [-0.704497, 0.351869, 1.102318], [2.958884, 0.51505, -1.556651], [1.73983, -3.161794, -0.356577], [2.131519, -2.336982, 0.996026], [0.752313, -1.788039, 1.687183], [-0.142347, 1.685301, -1.12086], [2.32407, -1.845905, -2.588202], [-2.571557, -1.937877, 2.604727], [2.556369, -4.551103, -3.2836], [3.032586, 0.591698, -4.896276], [-1.67818, 2.640745, -3.27092], [5.145483, 0.775188, 0.95687], [-2.81059, -3.4492, -2.650319], [2.558023, -3.594544, 2.845928], [0.400993, 3.469148, 1.733289]])) c = Conditions(cluster) c.min_distance_rule('O', 'H', 'O2', 'H', 'O1') cluster.set_calculator( GULP(keywords='opti conp phon noden distance molq compare angle nono', shel=['O1', 'O2'], conditions=c)) print(cluster.get_potential_energy())
def run_gulp(structure, gulp_file, previous_restart_file="", gulp_keywords=["conp gradients"], gulp_options=[], gulp_shells=[], gulp_library="", gulp_conditions=None): """ Run GULP in order to perform any stage of a split calculation. The calculation is run either by using an ASE calculator or as a system command depending on whether or not we have shells present -- if so, the system approach is required in order to preserve the positions of atomic shells. Parts of this routine are based on the "restart_gulp" routine, written by Chris Collins, and the section that runs GULP as a system command is taken from ASE-GULP. Parameters ---------- structure : ASE atoms The structure used in the GULP calculation gulp_file : string Used to construct input and output files for GULP previous_restart_file : string, optional Restart file for previous GULP calculation -- used to construct new input file. gulp_keywords : list, optional List of GULP keywords. Default is "sing" for a single point energy calculation. gulp_options : list, optional List of GULP options. Default is None. gulp_shells : dictionary, optional List of each atomic species to have a shell attached. gulp_library : string, optional The library file containing the forcefield to be used in the calculation. gulp_conditions : ASE Conditions, optional The conditions used to determine the label given to particular atoms if the forcefield has different atom types. Returns ------- structure : ase atoms The structure after performing this calculation. energy : float Energy of the structure in eV/atom. result : string The result of the GULP calculation, either "converged", "unconverged", "gulp failure", or "timed out" calc_files : dict The input, output and restart files for this GULP calculation. --------------------------------------------------------------------------- Paul Sharp 02/08/2018 """ # Set files for calculation calc_files = { "input": gulp_file + ".gin", "output": gulp_file + ".got", "restart": gulp_file + ".res", } energy = "" gnorm = "" result = "" timeout_outcome = "CPU limit has been exceeded - restart optimisation " # Determine how to do the second calculation depending on whether or not we have shells present if (gulp_shells == []) or (structure.get_calculator() is None): # Use ASE calculator -- set keywords and options for this calculation calc = (GULP(label=gulp_file, keywords=gulp_keywords, options=gulp_options, shel=gulp_shells, library=gulp_library, conditions=gulp_conditions)) structure.set_calculator(calc) # Run calculation try: energy = structure.get_potential_energy() except: pass else: gnorm = structure.calc.get_Gnorm() else: # Run as system command -- need to construct the GULP input file from the ".res" file of the previous calculation if os.path.isfile(previous_restart_file): create_input_file_from_restart_file(calc_files["input"], previous_restart_file, structure.get_cell(), gulp_keywords, gulp_options, gulp_library) execute_gulp_command_or_script(gulp_file, calc_files["output"]) # Read energy from output file if os.path.isfile(calc_files["output"]): energy = read_energy(calc_files["output"]) gnorm = read_gnorm(calc_files["output"]) else: raise RuntimeError( 'ERROR in "gulp_calc.run_gulp()" -- shells are used in this GULP calculation, but a ".res" file was not generated in the previous stage of the calculation.\n' 'This means that the positions of the shells cannot be tracked accurately. Please specify "dump <restart>.res" in the "gulp_options".' ) if not os.path.isfile(calc_files["output"]): result = "gulp failure" # The calculation can timeout either within GULP or via the bash timeout command elif read_outcome( calc_files["output"]) == timeout_outcome or check_timed_out( calc_files["output"]): result = "timed out" # Convert energy to units of eV/atom try: energy /= float(len(strip_vacancies(structure.copy()))) except (TypeError, ValueError): pass return structure, energy, gnorm, result, calc_files
import numpy as np from ase.calculators.gulp import GULP from ase.optimize import BFGS from ase.build import molecule atoms = molecule('H2O') atoms1 = atoms.copy() atoms1.calc = GULP(library='reaxff.lib') opt1 = BFGS(atoms1,trajectory='bfgs.traj') opt1.run(fmax=0.005) atoms2 = atoms.copy() calc2 = GULP(keywords='opti conp', library='reaxff.lib') opt2 = calc2.get_optimizer(atoms2) opt2.run() print(np.abs(opt1.atoms.positions - opt2.atoms.positions)) assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5
[ 2.958884, 0.51505 , -1.556651], [ 1.73983 , -3.161794, -0.356577], [ 2.131519, -2.336982, 0.996026], [ 0.752313, -1.788039, 1.687183], [-0.142347, 1.685301, -1.12086 ], [ 2.32407 , -1.845905, -2.588202], [-2.571557, -1.937877, 2.604727], [ 2.556369, -4.551103, -3.2836 ], [ 3.032586, 0.591698, -4.896276], [-1.67818 , 2.640745, -3.27092 ], [ 5.145483, 0.775188, 0.95687 ], [-2.81059 , -3.4492 , -2.650319], [ 2.558023, -3.594544, 2.845928], [ 0.400993, 3.469148, 1.733289]])) c = Conditions(cluster) c.min_distance_rule('O', 'H', ifcloselabel1='O2', ifcloselabel2='H', elselabel1='O1') calc = GULP(keywords='conp', shel=['O1', 'O2'], conditions=c) # Single point calculation cluster.calc = calc print(cluster.get_potential_energy()) # Optimization using the internal optimizer of GULP calc.set(keywords='conp opti') opt = calc.get_optimizer(cluster) opt.run(fmax=0.05) print(cluster.get_potential_energy())
import numpy as np from ase.calculators.gulp import GULP from ase.optimize import BFGS from ase.build import molecule, bulk from ase.constraints import ExpCellFilter # GULP optmization test atoms = molecule('H2O') atoms1 = atoms.copy() atoms1.calc = GULP(library='reaxff.lib') opt1 = BFGS(atoms1, trajectory='bfgs.traj') opt1.run(fmax=0.005) atoms2 = atoms.copy() calc2 = GULP(keywords='opti conp', library='reaxff.lib') opt2 = calc2.get_optimizer(atoms2) opt2.run() print(np.abs(opt1.atoms.positions - opt2.atoms.positions)) assert np.abs(opt1.atoms.positions - opt2.atoms.positions).max() < 1e-5 # GULP optimization test using stress atoms = bulk('Au', 'bcc', a=2.7, cubic=True) atoms1 = atoms.copy() atoms1.calc = GULP(keywords='conp gradient stress_out', library='reaxff_general.lib') atoms1f = ExpCellFilter(atoms1) opt1 = BFGS(atoms1f, trajectory='bfgs.traj') opt1.run(fmax=0.005) atoms2 = atoms.copy()