def xtb_calc(elements,cartesians,coordinates,args,log,ase_metal,ase_metal_idx): if args.metal_complex: # passing charges metal present ase_molecule = ase.Atoms(elements, positions=coordinates.tolist()[0],calculator=XTB(method="GFN2-xTB")) #define ase molecule using GFN2 Calculator if os.path.splitext(args.input)[1] == '.csv' or os.path.splitext(args.input)[1] == '.cdx' or os.path.splitext(args.input)[1] == '.smi': for i,atom in enumerate(ase_molecule): if i in ase_metal: ase_charge = args.charge[args.metal_idx.index(ase_metal_idx[ase_metal.index(i)])] # will update only for cdx, smi, and csv formats. atom.charge = ase_charge else: atom.charge = args.charge_default if args.verbose: log.write('o The Overall charge is read from the .com file ') else: ase_molecule = ase.Atoms(elements, positions=coordinates.tolist()[0],calculator=XTB(method="GFN2-xTB")) #define ase molecule using GFN2 Calculator optimizer = ase.optimize.BFGS(ase_molecule, trajectory='xTB_opt.traj',logfile='xtb.opt') optimizer.run(fmax=args.opt_fmax, steps=args.opt_steps) if len(ase.io.Trajectory('xTB_opt.traj', mode='r')) != (args.opt_steps+1): species_coords = ase_molecule.get_positions().tolist() coordinates = torch.tensor([species_coords], requires_grad=True, device=device) # Now let's compute energy: xtb_energy = ase_molecule.get_potential_energy() sqm_energy = (xtb_energy / Hartree)* hartree_to_kcal return sqm_energy, coordinates
def minimize( atomno, coord, method="GFN2-xTB", accuracy=1.0, electronic_temperature=300.0, max_iterations=250, solvent="water", cache_api=True, constraints=None, ): atoms = Atoms(numbers=atomno, positions=coord) calc = XTB( method=method, accuracy=accuracy, electronic_temperature=electronic_temperature, max_iterations=max_iterations, solvent=solvent, cache_api=cache_api, ) atoms.set_calculator(calc) if constraints is not None: for c in constraints: atoms.set_constraint(c) opt = BFGS(atoms) opt.run(fmax=0.05) return atoms.numbers, atoms.get_positions()
def test_gfn1_xtb_3d(): """Test ASE interface to GFN1-xTB""" thr = 5.0e-6 atoms = Atoms( symbols='C4O8', positions=np.array([ [0.9441259872, 0.9437851680, 0.9543505632], [3.7179966528, 0.9556570368, 3.7316862240], [3.7159517376, 3.7149292800, 0.9692330016], [0.9529872864, 3.7220864832, 3.7296981120], [1.6213905408, 1.6190616096, 1.6313879040], [0.2656685664, 0.2694175776, 0.2776540416], [4.3914553920, 1.6346256864, 3.0545920000], [3.0440834880, 0.2764611744, 4.4080419264], [4.3910577696, 3.0416409504, 0.2881058304], [3.0399936576, 4.3879335936, 1.6497353376], [0.2741322432, 4.4003734944, 3.0573754368], [1.6312174944, 3.0434586528, 4.4023048032], ]), cell=np.array([5.68032, 5.68032, 5.68032]), pbc=np.array([True, True, True]), ) forces = np.array([ [0.05008078, 0.06731033, 0.06324782], [-0.03885473, 0.07550136, -0.06667888], [-0.06455676, -0.04199831, 0.06908718], [0.04672903, -0.06303119, -0.06002863], [-1.9460667, -1.94514641, -1.94923488], [1.92953942, 1.91109506, 1.92038457], [-1.91269913, -1.95500822, 1.94675148], [1.94009239, 1.91238163, -1.93489981], [-1.90757165, 1.94211445, 1.94655816], [1.94283273, -1.90965163, -1.95863335], [1.91207771, -1.94256232, 1.9337591], [-1.95160309, 1.94899525, -1.91031277], ]) charges = np.array([ 0.74256902, 0.74308482, 0.74305612, 0.74300613, -0.37010244, -0.37234708, -0.37134504, -0.37177066, -0.37176288, -0.37133667, -0.37178059, -0.37127074, ]) calc = XTB(method="GFN1-xTB") atoms.set_calculator(calc) assert atoms.pbc.all() assert approx(atoms.get_potential_energy(), abs=thr) == -1256.768167202048 assert approx(atoms.get_forces(), abs=thr) == forces assert approx(atoms.get_charges(), abs=thr) == charges
def test_ase_energy(ctx): from ase.build import molecule from xtb.ase.calculator import XTB water = molecule("H2O") water.calc = XTB() target = ASEEnergy(ASEBridge(water, 300.)) pos = torch.tensor(0.1 * water.positions, **ctx) e = target.energy(pos) f = target.force(pos)
def test_ase_vs_xtb(ctx): # to make sure that unit conversion is the same, etc. from ase.build import molecule from xtb.ase.calculator import XTB water = molecule("H2O") water.calc = XTB() target1 = ASEEnergy(ASEBridge(water, 300.)) target2 = XTBEnergy(XTBBridge(water.numbers, 300.)) pos = torch.tensor(0.1 * water.positions[None, ...], **ctx) assert torch.allclose(target1.energy(pos), target2.energy(pos)) assert torch.allclose(target1.force(pos), target2.force(pos), atol=1e-6)
def opt_xtb_lbfgs(atoms): from xtb.ase.calculator import XTB from ase.optimize.lbfgs import LBFGS tmpAtoms = atoms.copy() tmpAtoms.calc = XTB(method='GFN1-xTB') geomOpt = LBFGS( tmpAtoms, maxstep=0.1, trajectory=None, # logfile=None ) geomOpt.run(fmax=0.05, steps=400) return tmpAtoms
def test_gfn2_xtb_3d(): """Test ASE interface to GFN2-xTB, should fail""" thr = 5.0e-6 atoms = Atoms( symbols='C4O8', positions=np.array([ [0.9441259872, 0.9437851680, 0.9543505632], [3.7179966528, 0.9556570368, 3.7316862240], [3.7159517376, 3.7149292800, 0.9692330016], [0.9529872864, 3.7220864832, 3.7296981120], [1.6213905408, 1.6190616096, 1.6313879040], [0.2656685664, 0.2694175776, 0.2776540416], [4.3914553920, 1.6346256864, 3.0545920000], [3.0440834880, 0.2764611744, 4.4080419264], [4.3910577696, 3.0416409504, 0.2881058304], [3.0399936576, 4.3879335936, 1.6497353376], [0.2741322432, 4.4003734944, 3.0573754368], [1.6312174944, 3.0434586528, 4.4023048032], ]), cell=np.array([5.68032, 5.68032, 5.68032]), pbc=np.array([True, True, True]), ) calc = XTB(method="GFN2-xTB") atoms.set_calculator(calc) with raises(CalculationFailed): atoms.get_potential_energy() # make structure molecular atoms.set_pbc(False) assert approx(atoms.get_potential_energy(), abs=thr) == -1121.9196707084955 with raises(InputError): atoms.positions = np.zeros((len(atoms), 3)) calc.calculate(atoms=atoms, system_changes=["positions"])
def test_gfn2xtb_velocityverlet(): """Perform molecular dynamics with GFN2-xTB and Velocity Verlet Integrator""" thr = 1.0e-5 atoms = Atoms( symbols="NHCHC2H3OC2H3ONHCH3", positions=np.array([ [1.40704587284727, -1.26605342016611, -1.93713466561923], [1.85007200612454, -0.46824072777417, -1.50918242392545], [-0.03362432532150, -1.39269245193812, -1.74003582081606], [-0.56857009928108, -1.01764444489068, -2.61263467107342], [-0.44096297340282, -2.84337808903410, -1.48899734014499], [-0.47991761226058, -0.55230954385212, -0.55520222968656], [-1.51566045903090, -2.89187354810876, -1.32273881320610], [-0.18116520746778, -3.45187805987944, -2.34920431470368], [0.06989722340461, -3.23298998903001, -0.60872832703814], [-1.56668253918793, 0.00552120970194, -0.52884675001441], [1.99245341064342, -1.73097165236442, -3.08869239114486], [3.42884244212567, -1.30660069291348, -3.28712665743189], [3.87721962540768, -0.88843123009431, -2.38921453037869], [3.46548545761151, -0.56495308290988, -4.08311788302584], [4.00253374168514, -2.16970938132208, -3.61210068365649], [1.40187968630565, -2.43826111827818, -3.89034127398078], [0.40869198386066, -0.49101709352090, 0.47992424955574], [1.15591901335007, -1.16524842262351, 0.48740266650199], [0.00723492494701, 0.11692276177442, 1.73426297572793], [0.88822128447468, 0.28499001838229, 2.34645658013686], [-0.47231557768357, 1.06737634000561, 1.52286682546986], [-0.70199987915174, -0.50485938116399, 2.28058247845421], ]), ) calc = XTB(method="GFN2-xTB", cache_api=False) atoms.set_calculator(calc) dyn = VelocityVerlet(atoms, timestep=1.0 * fs) dyn.run(20) assert approx(atoms.get_potential_energy(), thr) == -896.9772346260584 assert approx(atoms.get_kinetic_energy(), thr) == 0.022411127028842362 atoms.calc.set(cache_api=True) dyn.run(20) assert approx(atoms.get_potential_energy(), thr) == -896.9913862530841 assert approx(atoms.get_kinetic_energy(), thr) == 0.036580471363852810
def test_gfn2xtb_lbfgs(): """Perform geometry optimization with GFN2-xTB and L-BFGS""" thr = 1.0e-5 atoms = Atoms( symbols="NHCHC2H3OC2H3ONHCH3", positions=np.array([ [1.40704587284727, -1.26605342016611, -1.93713466561923], [1.85007200612454, -0.46824072777417, -1.50918242392545], [-0.03362432532150, -1.39269245193812, -1.74003582081606], [-0.56857009928108, -1.01764444489068, -2.61263467107342], [-0.44096297340282, -2.84337808903410, -1.48899734014499], [-0.47991761226058, -0.55230954385212, -0.55520222968656], [-1.51566045903090, -2.89187354810876, -1.32273881320610], [-0.18116520746778, -3.45187805987944, -2.34920431470368], [0.06989722340461, -3.23298998903001, -0.60872832703814], [-1.56668253918793, 0.00552120970194, -0.52884675001441], [1.99245341064342, -1.73097165236442, -3.08869239114486], [3.42884244212567, -1.30660069291348, -3.28712665743189], [3.87721962540768, -0.88843123009431, -2.38921453037869], [3.46548545761151, -0.56495308290988, -4.08311788302584], [4.00253374168514, -2.16970938132208, -3.61210068365649], [1.40187968630565, -2.43826111827818, -3.89034127398078], [0.40869198386066, -0.49101709352090, 0.47992424955574], [1.15591901335007, -1.16524842262351, 0.48740266650199], [0.00723492494701, 0.11692276177442, 1.73426297572793], [0.88822128447468, 0.28499001838229, 2.34645658013686], [-0.47231557768357, 1.06737634000561, 1.52286682546986], [-0.70199987915174, -0.50485938116399, 2.28058247845421], ]), ) calc = XTB(method="GFN2-xTB", solvent="water", accuracy=0.1) atoms.set_calculator(calc) opt = LBFGS(atoms) opt.run(fmax=0.1) assert approx(atoms.get_potential_energy(), thr) == -897.4533662470938 assert approx(np.linalg.norm(atoms.get_forces(), ord=2), thr) == 0.19359647527783497
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
# Fix cycloprop. rings init_atoms = fix_cyclopropenyl(init_atoms, mol) # Detect the dihedral angles dihedrals = detect_dihedrals(mol) logger.info(f'Detected {len(dihedrals)} dihedral angles') # Save the initial guess with out_dir.joinpath('initial.xyz').open('w') as fp: simple_write_xyz(fp, [init_atoms]) # Set up the optimization problem if args.level == 'ani': calc = torchani.models.ANI2x().ase() elif args.level == 'xtb': calc = XTB() elif args.level == 'b3lyp': calc = Psi4(method='b3lyp', basis='3-21g', num_threads=4, multiplicity=1, charge=1) else: raise ValueError(f'Unrecognized QC level: {args.level}') final_atoms = run_optimization(init_atoms, dihedrals, args.num_steps, calc, args.init_steps, out_dir, relax=args.relax)
def test_invalid_method(): """GFN-xTB without method number is invalid, should raise an input error""" with raises(InputError): calc = XTB(method="GFN-xTB")
def test_gfn1_xtb_0d(): """Test ASE interface to GFN1-xTB""" thr = 1.0e-5 atoms = Atoms( symbols='CHOCH2CH4CH2OH', positions=np.array([ [1.578385, 0.147690, 0.343809], [1.394750, 0.012968, 1.413545], [1.359929, -1.086203, -0.359782], [0.653845, 1.215099, -0.221322], [1.057827, 2.180283, 0.093924], [0.729693, 1.184864, -1.311438], [-0.817334, 1.152127, 0.208156], [-1.303525, 2.065738, -0.145828], [-0.883765, 1.159762, 1.299260], [1.984120, -1.734446, -0.021385], [2.616286, 0.458948, 0.206544], [-1.627725, -0.034052, -0.311301], [-2.684229, 0.151015, -0.118566], [-1.501868, -0.118146, -1.397506], [-1.324262, -1.260154, 0.333377], [-0.417651, -1.475314, 0.076637], ]), ) forces = np.array([[-0.37070590, -0.51067739, -0.27981764], [-0.04339461, -0.09290876, 0.22940156], [0.11141234, 0.46678720, 0.24552625], [0.04255709, 0.19019316, -0.23531997], [-0.01897377, 0.10810803, 0.05314982], [-0.07150720, -0.05182148, -0.08413638], [0.06631826, 0.10587709, 0.29833479], [-0.01062355, 0.02301460, -0.04964730], [0.06610108, -0.02724994, 0.09234280], [0.06519070, -0.19311773, -0.01152205], [0.23879786, 0.09871398, -0.04009526], [-0.04381577, -0.49997745, 0.08672818], [-0.23259608, 0.13735636, 0.06783414], [0.08297636, -0.09566973, -0.20602954], [-0.23686052, 0.57454371, -0.17194215], [0.35512370, -0.23317164, 0.00519275]]) charges = np.array([ 0.19494678, 0.01759972, -0.57108503, -0.05371086, 0.02458495, 0.03915074, -0.06889977, 0.02521441, 0.03350058, 0.34380081, 0.01442221, 0.20053193, 0.02454679, 0.01011690, -0.58349877, 0.34877861, ]) dipole_moment = np.array([0.76943477, 0.33021928, 0.05670150]) atoms.calc = XTB(method="GFN1-xTB") assert approx(atoms.get_potential_energy(), abs=thr) == -632.7363734598027 assert approx(atoms.get_forces(), abs=thr) == forces assert approx(atoms.get_charges(), abs=thr) == charges assert approx(atoms.get_dipole_moment(), abs=thr) == dipole_moment
big_slab = slab * repeats nbig_slab = len(big_slab) ts_estimate = adsorbed[nbig_slab:] start = datetime.datetime.now() with open(prefix + '_time.log', 'w+') as f: f.write(str(start)) f.write("\n") f.close() adsplacer = AdsorbatePlacer( big_slab, ts_estimate, bonds, av_dists_tuple, trajectory=traj_path ) adsplacer.ads_ref.set_calculator(XTB(method="GFN1-xTB")) opt = adsplacer.optimize() # visualize initial point of each trajectory write(geom[:-4] + '_initial.png', read(geom)) # visualize end point of each trajectory write(traj_path[:-5] + '_final.png', read(traj_path)) write(traj_path[:-5] + '_final.xyz', read(traj_path)) end = datetime.datetime.now() with open(prefix + '_time.log', 'a+') as f: f.write(str(end)) f.write("\n") f.write(str(end - start)) f.write("\n") f.close()
import sys from ase.io import read, write from ase.units import Hartree from ase.optimize.lbfgs import LBFGS from xtb.ase.calculator import XTB from ase.db import connect inpName = sys.argv[1] slab = read(inpName) slab.calc = XTB(method='GFN1-xTB', max_iterations=1000) relax = LBFGS( slab, maxstep=0.1, # logfile=None, # trajectory='ase.traj' ) relax.run(fmax=0.05) # get the final single point energy e = slab.get_potential_energy() print("Final energy: eV, Eh", e, e/Hartree) # write final geometry to file write('out-'+inpName, slab)
def test_gfn2_xtb_0d(): """Test ASE interface to GFN2-xTB""" thr = 1.0e-5 atoms = Atoms( symbols='CHOCH2CH4CH2OH', positions=np.array([ [1.578385, 0.147690, 0.343809], [1.394750, 0.012968, 1.413545], [1.359929, -1.086203, -0.359782], [0.653845, 1.215099, -0.221322], [1.057827, 2.180283, 0.093924], [0.729693, 1.184864, -1.311438], [-0.817334, 1.152127, 0.208156], [-1.303525, 2.065738, -0.145828], [-0.883765, 1.159762, 1.299260], [1.984120, -1.734446, -0.021385], [2.616286, 0.458948, 0.206544], [-1.627725, -0.034052, -0.311301], [-2.684229, 0.151015, -0.118566], [-1.501868, -0.118146, -1.397506], [-1.324262, -1.260154, 0.333377], [-0.417651, -1.475314, 0.076637], ]), ) forces = np.array([ [-0.28561158, -0.48592026, -0.28392327], [-0.05526158, -0.07403455, 0.09665539], [0.18824950, 0.39170140, 0.33881928], [-0.01166074, 0.24653252, -0.16779606], [-0.05367503, 0.03368063, 0.05115422], [-0.09605262, -0.10000389, 0.01097286], [0.09423300, 0.18573616, 0.17797438], [0.02651896, -0.04073849, -0.03655980], [0.07886359, -0.05806479, 0.00649360], [-0.00780520, -0.07979390, -0.03175697], [0.13328595, 0.03209283, -0.04638514], [0.08197778, -0.39157299, 0.12107401], [-0.11453823, -0.01485088, 0.09974068], [0.09786017, -0.09130861, -0.05738675], [-0.26643400, 0.47603727, -0.27856705], [0.19005003, -0.02949244, -0.00050938], ]) charges = np.array([ 0.08239823, 0.03066406, -0.44606929, -0.06139043, 0.03610596, 0.05389499, -0.06991855, 0.03384415, 0.04665524, 0.28688538, 0.02246569, 0.08251610, 0.03810481, 0.01883776, -0.46691965, 0.31192554, ]) dipole_moment = np.array([0.62120710, 0.28006659, 0.04465985]) calc = XTB(method="GFN2-xTB", atoms=atoms) assert approx(atoms.get_potential_energy(), abs=thr) == -592.6794366990786 assert approx(atoms.get_forces(), abs=thr) == forces assert approx(atoms.get_charges(), abs=thr) == charges assert approx(atoms.get_dipole_moment(), abs=thr) == dipole_moment atoms.calc.set( accuracy=0.1, electronic_temperature=500.0, max_iterations=20, solvent="ch2cl2", ) assert approx(atoms.get_potential_energy(), abs=thr) == -592.9940608761889