def test_orca(): from ase.optimize import BFGS from ase.atoms import Atoms from ase.calculators.orca import ORCA atoms = Atoms('OHH', positions=[(0, 0, 0), (1, 0, 0), (0, 1, 0)]) atoms.calc = ORCA(label='water', orcasimpleinput='BLYP def2-SVP') opt = BFGS(atoms) opt.run(fmax=0.05) final_energy = atoms.get_potential_energy() print(final_energy) assert abs(final_energy + 2077.24420) < 1.0
def test_orca_qmmm(): from ase.calculators.tip4p import TIP4P, epsilon0, sigma0 from ase.calculators.orca import ORCA from ase.calculators.qmmm import EIQMMM, LJInteractions from ase.data import s22 atoms = s22.create_s22_system('Water_dimer') qmcalc = ORCA(label='water', orcasimpleinput='BLYP def2-SVP') lj = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) atoms.calc = EIQMMM(selection=[0, 1, 2], qmcalc=qmcalc, mmcalc=TIP4P(), interaction=lj, output='orca_qmmm.log') e = atoms.get_potential_energy() assert abs(e + 2077.45445852) < 1.0
def main(): """Run main procedure.""" parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "commands", metavar="input_file", nargs="?", type=argparse.FileType("r"), default="-", help="input text file with commands", ) parser.add_argument( "-O", "--output-file", type=argparse.FileType("w"), default="-", help="output coordinates file", ) parser.add_argument( "--no-final-neb", dest="final_neb", action="store_false", help="piecewise nudged-elastic band only", ) parser.add_argument("--no-opt", dest="opt", action="store_false", help="use final states as given") args = parser.parse_args() n = 0 auto_n = True images = [] method, theory = "linear", None for line in args.commands: for command in line.split(): command = command.strip() if command == "linear": method, theory = "linear", None elif command == "idpp": method, theory = "idpp", None elif command in {"pm3", "am1", "xtb2"}: # method == "idpp" theory = command elif command == "auto": auto_n = True else: try: structure = io.read(command) except FileNotFoundError: try: n = int(command) except ValueError: parser.error( f"could not understand command or find file: '{command}'" ) continue if len(images) > 0 and (auto_n or n > 0): if auto_n: rmsd = calc_rmsd(images[-1].get_positions(), structure.get_positions()) n = max(1, int(rmsd / 0.3)) pieces = [images[-1]] pieces += [images[-1].copy() for _ in range(n)] pieces += [structure] if method == "idpp": neb = NEB(pieces, remove_rotation_and_translation=False, **neb_kwargs) else: neb = NEB(pieces, remove_rotation_and_translation=True, **neb_kwargs) neb.interpolate(method) if theory is not None: # TODO(schneiderfelipe): avoid repeat the code for NEB orcablocks = "" if theory not in {"pm3", "am1"}: orcablocks = f"%pal nprocs {os.cpu_count()} end" for piece in pieces[1:-1]: piece.calc = ORCA( orcasimpleinput=f"{theory} loosescf nososcf", orcablocks=orcablocks, **calc_kwargs, ) if n < 5: # best for 2 and 4 structures opt = FIRE(neb, **opt_kwargs) else: # best for 3 and 10 structures opt = LBFGS(neb, **opt_kwargs) opt.run(**run_kwargs) images = images[:-1] + pieces else: images.append(structure) run_kwargs.update({"fmax": run_kwargs["fmax"] / 5}) if args.opt and theory is not None: # TODO(schneiderfelipe): avoid repeat the code for NEB orcablocks = "" if theory not in {"pm3", "am1"}: orcablocks = f"%pal nprocs {os.cpu_count()} end" images[0].calc = ORCA( orcasimpleinput=f"{theory} loosescf nososcf", orcablocks=orcablocks, **calc_kwargs, ) images[-1].calc = ORCA( orcasimpleinput=f"{theory} loosescf nososcf", orcablocks=orcablocks, **calc_kwargs, ) opt = LBFGS(images[0], **opt_kwargs) opt.run(**run_kwargs) opt = LBFGS(images[-1], **opt_kwargs) opt.run(**run_kwargs) if args.final_neb and theory is not None and len(images) > 2: neb = NEB(images, remove_rotation_and_translation=True, **neb_kwargs) # TODO(schneiderfelipe): avoid repeat the code for NEB orcablocks = "" if theory not in {"pm3", "am1"}: orcablocks = f"%pal nprocs {os.cpu_count()} end" for image in images[1:-1]: image.calc = ORCA( orcasimpleinput=f"{theory} loosescf nososcf", orcablocks=orcablocks, **calc_kwargs, ) if len(images) < 5: # best for 2 and 4 structures opt = FIRE(neb, **opt_kwargs) else: # best for 3 and 10 structures opt = LBFGS(neb, **opt_kwargs) opt.run(**run_kwargs) with redirect_stdout(args.output_file): io.write("-", images, format="xyz", plain=True) # some programs (e.g., Chemcraft) won't read without a newline at the end # but even with this, Chemcraft won't read if there are only 2 strucures args.output_file.write("\n")
def main(): """Run main procedure.""" parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("logfile") # TODO(schneiderfelipe): set charge and multiplicity parser.add_argument( "-a", "--acc", help="accuracy for SCC calculation, lower is better", type=float, default=1.0, ) parser.add_argument( "--iterations", help="number of iterations in SCC", type=int, default=250, ) parser.add_argument( "--gfn", help="specify parametrisation of GFN-xTB", type=int ) parser.add_argument( "--etemp", help="electronic temperature", type=float, default=300.0 ) parser.add_argument( "-s", "--solvent", help=("solvent (SMD/GBSA implicit solvation models)"), default="none", ) parser.add_argument( "--do-not-cache-api", dest="cache_api", help="Do not reuse generate API objects (not recommended)", action="store_false", ) parser.add_argument( "--pm3", help="use PM3", action="store_true", ) parser.add_argument( "--b97-3c", help="use B97-3c", action="store_true", ) parser.add_argument( "--minimize", action="store_true", ) parser.add_argument( "--transition-state", action="store_true", ) parser.add_argument("--max-omega", type=float, default=1.0) parser.add_argument("--tol", type=float, default=1e-3) parser.add_argument("--nprocs", type=int, default=4) args = parser.parse_args() print(args) data = ccopen(args.logfile).parse() initial_positions = data.atomcoords[-1] atoms = Atoms(numbers=data.atomnos, positions=initial_positions) if args.gfn: method = f"GFN{args.gfn}-xTB" solvent = smd2gbsa[args.solvent.lower()] calc = XTB( method=method, accuracy=args.acc, electronic_temperature=args.etemp, max_iterations=args.iterations, solvent=solvent, cache_api=args.cache_api, ) else: if args.b97_3c: method = "B97-3c D3BJ def2-SV(P)" elif args.pm3: method = "PM3" else: def allow_keyword(keyword): for forbidden in {"freq", "opt", "irc", "print"}: if forbidden in keyword.lower(): return False return True keywords = [ keyword for keyword in data.metadata["keywords"] if allow_keyword(keyword) ] method = " ".join(keywords) solvent = args.solvent blocks = f"%pal\n nprocs {args.nprocs}\nend\n%scf\n maxiter {args.iterations}\nend" if solvent != "none" and not args.pm3: blocks += f'\n%cpcm\n smd true\n smdsolvent "{solvent}"\nend' if "ORCA_COMMAND" not in os.environ: # For parallel runs ORCA has to be called with full pathname os.environ["ORCA_COMMAND"] = shutil.which("orca") calc = ORCA( label="012345_swing", orcasimpleinput=method, orcablocks=blocks ) print(f"*** {method} ***") print(f" : solvent: {solvent}") atoms.set_calculator(calc) potential_min = atoms.get_potential_energy() print(f"@ potential energy: {potential_min} eV") indices = np.where(data.vibfreqs < 0)[0] n_indices = len(indices) print(f"@ imaginary frequencies: {data.vibfreqs[indices]}") if not n_indices: print(" : nothing to be done, bye") return ignoring = None if args.transition_state: ignoring = 0 print(" : transition state: ignoring first imaginary frequency") omegas = [] potentials = [] def f(omega): atoms.set_positions( initial_positions + np.einsum("i,ijk->jk", omega, data.vibdisps[indices]) ) potential = 1e3 * (atoms.get_potential_energy() - potential_min) omegas.append(omega) potentials.append(potential) print(f" : omega: {omega}") print(f" : potential: {potential} meV") return potential if args.minimize: guesses = [np.zeros_like(indices, dtype=float)] for i in indices: if ignoring is not None and i == ignoring: continue print(f"@ searching in direction #{i}") def g(w): z = np.zeros_like(indices, dtype=float) z[i] = w return f(z) if args.minimize: res = minimize_scalar( g, method="bounded", bounds=(-args.max_omega, args.max_omega), tol=args.tol, ) print(res) guess = np.zeros_like(indices, dtype=float) guess[i] = res.x guesses.append(guess) else: dx = args.max_omega / 100 x = [-dx, 0.0, dx] y = [g(-dx), 0.0, g(dx)] # p[0] * x**2 + p[1] * x + p[2] == k * (x - x0)**2 == k * x**2 - 2 * x0 * k * x + k * x0**2 p = np.polyfit(x, y, 2) print(p) print(np.roots(p)) dp = np.polyder(p) print(dp) r = np.roots(dp) print(r) # k = p[0] # x0 = np.sqrt(p[2] / k) # print(k, x0) # print(root(lambda z: [p[0] - z[0], p[1] + 2 * z[0] * z[1], p[2] - z[0] * z[1] ** 2], [k, x0])) best_positions = initial_positions + np.einsum( "i,ijk->jk", r, data.vibdisps[indices] ) if args.minimize: print("@ choosing initial guess for global search") if n_indices > 1: guesses.append(np.sum(guesses, axis=0)) x0 = guesses[np.argmin([f(guess) for guess in guesses])] print("@ searching in all directions") constraints = () if args.transition_state and ignoring is not None: constraints = ( {"type": "eq", "fun": lambda omega: omega[ignoring]}, ) res = minimize( f, x0=x0, bounds=n_indices * [(-args.max_omega, args.max_omega)], constraints=constraints, tol=args.tol, ) print(res) best_positions = initial_positions + np.einsum( "i,ijk->jk", res.x, data.vibdisps[indices] ) # TODO(schneiderfelipe): correct for when using --transition-state omegas = np.array(omegas) fig, ax = plt.subplots(n_indices, 1) if n_indices == 1: ax = [ax] xlim = (-args.max_omega - 0.05, args.max_omega + 0.05) ylim = (np.min(potentials) - 2.0, 40.0) for i in indices: if ignoring is not None and i == ignoring: continue ax[i].plot(omegas[:, i], potentials, "o") ax[i].set_title(f"view of normal mode #{i}") ax[i].set_ylabel(r"potential energy (meV)") ax[i].set_xlabel(rf"$\omega_{i}$") ax[i].set_ylim(ylim) ax[i].set_xlim(xlim) plt.tight_layout() plt.show() print("@ writing best geometry to swinged.xyz") # TODO(schneiderfelipe): print a RMSD between initial and final structures atoms.set_positions(best_positions) atoms.write("swinged.xyz", format="xyz", plain=True)
def get_ase_calc(embedder): ''' Attach the correct ASE calculator to the ASE Atoms object. embedder: either a TSCoDe embedder object or a 4-element strings tuple containing (calculator, method, procs, solvent) ''' if isinstance(embedder, tuple): calculator, method, procs, solvent = embedder else: calculator = embedder.options.calculator method = embedder.options.theory_level procs = embedder.options.procs solvent = embedder.options.solvent if calculator == 'XTB': try: from xtb.ase.calculator import XTB except ImportError: raise Exception( ('Cannot import xtb python bindings. Install them with:\n' '>>> conda install -c conda-forge xtb-python\n' '(See https://github.com/grimme-lab/xtb-python)')) from tscode.solvents import (solvent_synonyms, xtb_solvents, xtb_supported) solvent = solvent_synonyms[ solvent] if solvent in solvent_synonyms else solvent solvent = 'none' if solvent is None else solvent if solvent not in xtb_solvents: raise Exception( f'Solvent \'{solvent}\' not supported by XTB. Supported solvents are:\n{xtb_supported}' ) return XTB(method=method, solvent=solvent) command = COMMANDS[calculator] if calculator == 'MOPAC': if solvent is not None: method = method + ' ' + get_solvent_line(solvent, calculator, method) return MOPAC(label='temp', command=f'{command} temp.mop > temp.cmdlog 2>&1', method=method + ' GEO-OK') if calculator == 'ORCA': orcablocks = '' if procs > 1: orcablocks += f'%pal nprocs {procs} end' if solvent is not None: orcablocks += get_solvent_line(solvent, calculator, method) return ORCA(label='temp', command=f'{command} temp.inp > temp.out 2>&1', orcasimpleinput=method, orcablocks=orcablocks) if calculator == 'GAUSSIAN': if solvent is not None: method = method + ' ' + get_solvent_line(solvent, calculator, method) mem = str(MEM_GB) + 'GB' if MEM_GB >= 1 else str(int(1000 * MEM_GB)) + 'MB' calc = Gaussian( label='temp', command=f'{command} temp.com', method=method, nprocshared=procs, mem=mem, ) if 'g09' in command: from ase.io import read def g09_read_results(self=calc): output = read(self.label + '.out', format='gaussian-out') self.calc = output.calc self.results = output.calc.results calc.read_results = g09_read_results # Adapting for g09 outputting .out files instead of g16 .log files. # This is a bad fix and the issue should be corrected in the ASE # source code: merge request on GitHub pending to be written return calc
from ase import io from ase.calculators.orca import ORCA from ase.optimize.fire import FIRE from ase.optimize.bfgs import BFGS #Optimise molecule ethan = io.read('xyz_files/ethan.xyz') orca_calc= ORCA( label="orca", maxiter=200, task="gradient", orcasimpleinput="HF-3c" ) ethan.set_calculator(orca_calc) #opt = FIRE(ethan, trajectory='ethan.traj') #opt.run(fmax=0.00241) opt = BFGS(ethan, trajectory='ethan.traj') opt.run(fmax=0.0005)
frgchg = np.zeros(len(fragments), dtype='int') frgmlt = np.ones(len(fragments), dtype='int') frgchg[0] = 1 frgmlt[0] = 2 cutoff = 0.0 neu_label = 'large-cut_neutral_' for basis in ['STO-3G', '6-31G*']: for xc in ['PBE', 'BHandHLYP']: #### neutral ##### calc = ORCA(xc=xc, basis=basis, charges=charges, raw=raw) gebf = GEBF(atoms, molecules=True, fragments=fragments, subsyscalc=calc, cutoff=cutoff, label=neu_label, printlevel=1, econv=1.e-4, qconv=1.e-2, around_solute=around_solute) atoms.set_calculator(gebf) neutral = atoms.get_potential_energy()