def __init__(self, repeat): nmol = repeat[0] * repeat[1] * repeat[2] r = rOH a = angleHOH * pi / 180 # From https://doi.org/10.1063/1.445869 eexp = 6.24 * units.kcal / units.mol dexp = 2.75 aexp = 46 D = np.linspace(2.5, 3.5, 30) x = angleHOH * np.pi / 180 / 2 pos = [[0, 0, 0], [0, rOH * np.cos(x), rOH * np.sin(x)], [0, rOH * np.cos(x), -rOH * np.sin(x)]] calc = TIP4P() self.h2o = Atoms('OH2', [(0, 0, 0), (r * cos(a), 0, r * sin(a)), (r, 0, 0)]) vol = ((18.01528 / 6.022140857e23) / (0.9982 / 1e24))**(1 / 3.) self.h2o.set_cell((1.1 * r, 1.1 * r, 1.1 * r)) self.h2o = self.h2o.repeat(repeat) self.h2o.set_cell((0, 0, 0)) nmol = int(self.h2o.positions.shape[0] / 3) bonds = [(3 * i, 3 * i + 1) for i in range(nmol)] for i in range(nmol): bonds.append((3 * i, 3 * i + 2)) bonds_rOH = [] for bond in bonds: bonds_rOH.append((rOH, (bond))) angles = [(a, (3 * i + 2, 3 * i, 3 * i + 1)) for i in range(nmol)] self.h2o.constraints = FixInternals(bonds=bonds_rOH, angles=angles, epsilon=epsilon0) calc = TIP4P() self.h2o.calc = calc
def test_tip4p(): """Test TIP4P forces.""" from math import cos, sin from ase import Atoms from ase.calculators.tip4p import TIP4P, rOH, angleHOH r = rOH a = angleHOH dimer = Atoms('H2OH2O', [(r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0), (r * cos(a / 2), r * sin(a / 2), 0), (r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0)]) # tip4p sequence OHH, OHH, .. dimer = dimer[[2]] + dimer[:2] + dimer[[-1]] + dimer[3:5] dimer.positions[3:, 0] += 2.8 dimer.calc = TIP4P(rc=4.0, width=2.0) # put O-O distance in the cutoff range F = dimer.get_forces() print(F) dF = dimer.calc.calculate_numerical_forces(dimer) - F print(dF) assert abs(dF).max() < 2e-6
def __init__(self, nmol=5, size=3): r = rOH a = angleHOH * pi / 180 # From https://doi.org/10.1063/1.445869 eexp = 6.24 * units.kcal / units.mol dexp = 2.75 aexp = 46 D = np.linspace(2.5, 3.5, 30) x = angleHOH * np.pi / 180 / 2 pos = [[0, 0, 0], [0, rOH * np.cos(x), rOH * np.sin(x)], [0, rOH * np.cos(x), -rOH * np.sin(x)]] pos = pos * nmol calc = TIP4P() self.h2o = Atoms('OH2' * nmol, pos) disp = np.random.uniform(-size, size, (nmol, 3)) final_dis = [] for i in range(nmol): d = disp[i].tolist() for i in range(3): final_dis.append(d) self.h2o.set_positions(pos + np.array(final_dis)) #vol = ((18.01528 / 6.022140857e23) / (0.9982 / 1e24))**(1 / 3.) #self.h2o.set_cell((1.1*r , 1.1*r , 1.1*r )) #nmol = int(self.h2o.positions.shape[0] / 3) bonds = [(3 * i, 3 * i + 1) for i in range(nmol)] for i in range(nmol): bonds.append((3 * i, 3 * i + 2)) bonds_rOH = [] for bond in bonds: bonds_rOH.append((rOH, (bond))) angles = [(a, (3 * i + 2, 3 * i, 3 * i + 1)) for i in range(nmol)] self.h2o.constraints = FixInternals(bonds=bonds_rOH, angles=angles, epsilon=epsilon0) calc = TIP4P() self.h2o.calc = calc
def add_tip4p_const(water): nmol = int(water.positions.shape[0] / 3) a = angleHOH * pi / 180 bonds = [(3 * i, 3 * i + 1) for i in range(nmol)] for i in range(nmol): bonds.append((3 * i, 3 * i + 2)) bonds_rOH = [] for bond in bonds: bonds_rOH.append((rOH, (bond))) angles = [(a, (3 * i + 2, 3 * i, 3 * i + 1)) for i in range(nmol)] water.constraints = FixInternals(bonds=bonds_rOH, angles=angles, epsilon=epsilon0) calc = TIP4P() water.calc = calc return water
def saddlepoint(min1, min2, name): images=[LM[min1]] images += [LM[min1].copy() for i in range(5)] images += [LM[min2]] for image in images: image.set_calculator(TIP4P()) add_tip4p_const(image) neb = NEB(images, climb=True, parallel=True) try: neb.interpolate() except: try: print("try idpp interpolate") neb.interpolate(method="idpp") except: return optimize(neb, name)
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
epsilon, rc=rc, width=1.0) F2 = dimer.get_forces() dF = F1 - F2 print(TIPnP) print(dF) assert abs(dF).max() < 1e-8 # Also check a TIP3P/TIP4P combination against numerical forces: eps1 = np.array([eps3, 0, 0]) sig1 = np.array([sig3, 0, 0]) eps2 = np.array([eps4, 0, 0]) sig2 = np.array([sig4, 0, 0]) dimer.calc = CombineMM([0, 1, 2], 3, 3, TIP3P(rc, 1.0), TIP4P(rc, 1.0), sig1, eps1, sig2, eps2, rc, 1.0) F2 = dimer.get_forces() Fn = dimer.calc.calculate_numerical_forces(dimer, 1e-7) dF = F2 - Fn print('TIP3P/TIP4P') print(dF) assert abs(dF).max() < 1e-8 # LJInteractionsGeneral with CombineMM. # As it is used within EIQMMM, but avoiding long calculations for tests. # Total system is a unit test system comprised of: # 2 Na ions playing the role of a 'QM' subsystem # 2 Na ions as the 'Counterions' # 2 Water molecules
def test_qmmm_tip4p(): from math import cos, sin, pi import numpy as np #import matplotlib.pyplot as plt import ase.units as units from ase import Atoms from ase.calculators.tip4p import TIP4P, epsilon0, sigma0, rOH, angleHOH from ase.calculators.qmmm import (SimpleQMMM, EIQMMM, LJInteractions, LJInteractionsGeneral) from ase.constraints import FixInternals from ase.optimize import BFGS r = rOH a = angleHOH * pi / 180 # From https://doi.org/10.1063/1.445869 eexp = 6.24 * units.kcal / units.mol dexp = 2.75 aexp = 46 D = np.linspace(2.5, 3.5, 30) i = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) # General LJ interaction object sigma_mm = np.array([sigma0, 0, 0]) epsilon_mm = np.array([epsilon0, 0, 0]) sigma_qm = np.array([sigma0, 0, 0]) epsilon_qm = np.array([epsilon0, 0, 0]) ig = LJInteractionsGeneral(sigma_qm, epsilon_qm, sigma_mm, epsilon_mm, 3) for calc in [ TIP4P(), SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P()), SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P(), vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), i), EIQMMM([3, 4, 5], TIP4P(), TIP4P(), i, vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), i, vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), ig), EIQMMM([3, 4, 5], TIP4P(), TIP4P(), ig, vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), ig, vacuum=3.0) ]: dimer = Atoms('OH2OH2', [(0, 0, 0), (r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0), (r * cos(a / 2), r * sin(a / 2), 0), (r * cos(a / 2), -r * sin(a / 2), 0)]) dimer.calc = calc E = [] F = [] for d in D: dimer.positions[3:, 0] += d - dimer.positions[3, 0] E.append(dimer.get_potential_energy()) F.append(dimer.get_forces()) F = np.array(F) #plt.plot(D, E) F1 = np.polyval(np.polyder(np.polyfit(D, E, 7)), D) F2 = F[:, :3, 0].sum(1) error = abs(F1 - F2).max() assert error < 0.01 dimer.constraints = FixInternals(bonds=[(r, (0, 1)), (r, (0, 2)), (r, (3, 4)), (r, (3, 5))], angles=[(a, (2, 0, 1)), (a, (5, 3, 4))]) opt = BFGS(dimer, maxstep=0.04, trajectory=calc.name + '.traj', logfile=calc.name + 'd.log') opt.run(0.01) e0 = dimer.get_potential_energy() d0 = dimer.get_distance(0, 3) R = dimer.positions v1 = R[2] - R[3] v2 = R[3] - (R[5] + R[4]) / 2 a0 = np.arccos( np.dot(v1, v2) / (np.dot(v1, v1) * np.dot(v2, v2))**0.5) / np.pi * 180 fmt = '{0:>23}: {1:.3f} {2:.3f} {3:.3f} {4:.1f}' print(fmt.format(calc.name, -min(E), -e0, d0, a0)) assert abs(e0 + eexp) < 0.002 assert abs(d0 - dexp) < 0.006 assert abs(a0 - aexp) < 2.5 print(fmt.format('reference', 9.999, eexp, dexp, aexp))
interaction = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) for selection in [[0, 1, 2], [3, 4, 5]]: name = ''.join(str(i) for i in selection) dimer = Atoms('OH2OH2', [(0, 0, 0), (-r * cos(a / 2), r * sin(a / 2), 0), (-r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0), (-r * cos(a), 0, r * sin(a)), (-r, 0, 0)]) dimer.positions[3:, 0] += 2.8 dimer.constraints = FixBondLengths([ ((selection[i] + 3) % 6, (selection[i - 1] + 3) % 6) for i in range(3) ]) dimer.calc = EIQMMM(selection, GPAW(txt=name + '.txt', h=0.16), TIP4P(), interaction, vacuum=4, embedding=Embedding(rc=0.2, rc2=20, width=1), output=name + '.out') opt = LBFGS(dimer, trajectory=name + '.traj') opt.run(0.02) monomer = dimer[selection] monomer.center(vacuum=4) monomer.calc = GPAW(txt=name + 'M.txt', h=0.16) opt = PreconLBFGS(monomer, precon=Exp(A=3), trajectory=name + 'M.traj') opt.run(0.02) e0 = monomer.get_potential_energy() be = dimer.get_potential_energy() - e0 d = dimer.get_distance(0, 3)
def test_combine_mm(): """Test CombineMM forces by combining tip3p and tip4p with them selves, and by combining tip3p with tip4p and testing against numerical forces. Also test LJInterationsGeneral with CombineMM """ from math import cos, sin, pi import numpy as np from ase import Atoms from ase import units from ase.calculators.counterions import AtomicCounterIon as ACI from ase.calculators.combine_mm import CombineMM from ase.calculators.qmmm import LJInteractionsGeneral from ase.calculators.tip3p import TIP3P, rOH, angleHOH from ase.calculators.tip4p import TIP4P from ase.calculators.tip3p import epsilon0 as eps3 from ase.calculators.tip3p import sigma0 as sig3 from ase.calculators.tip4p import epsilon0 as eps4 from ase.calculators.tip4p import sigma0 as sig4 def make_atoms(): r = rOH a = angleHOH * pi / 180 dimer = Atoms('H2OH2O', [(r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0), (r * cos(a / 2), r * sin(a / 2), 0), (r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0)]) dimer = dimer[[2, 0, 1, 5, 3, 4]] # put O-O distance in the cutoff range dimer.positions[3:, 0] += 2.8 return dimer dimer = make_atoms() rc = 3.0 for (TIPnP, (eps, sig), nm) in zip([TIP3P, TIP4P], ((eps3, sig3), (eps4, sig4)), [3, 3]): dimer.calc = TIPnP(rc=rc, width=1.0) F1 = dimer.get_forces() sigma = np.array([sig, 0, 0]) epsilon = np.array([eps, 0, 0]) dimer.calc = CombineMM([0, 1, 2], nm, nm, TIPnP(rc=rc, width=1.0), TIPnP(rc=rc, width=1.0), sigma, epsilon, sigma, epsilon, rc=rc, width=1.0) F2 = dimer.get_forces() dF = F1 - F2 print(TIPnP) print(dF) assert abs(dF).max() < 1e-8 # Also check a TIP3P/TIP4P combination against numerical forces: eps1 = np.array([eps3, 0, 0]) sig1 = np.array([sig3, 0, 0]) eps2 = np.array([eps4, 0, 0]) sig2 = np.array([sig4, 0, 0]) dimer.calc = CombineMM([0, 1, 2], 3, 3, TIP3P(rc, 1.0), TIP4P(rc, 1.0), sig1, eps1, sig2, eps2, rc, 1.0) F2 = dimer.get_forces() Fn = dimer.calc.calculate_numerical_forces(dimer, 1e-7) dF = F2 - Fn print('TIP3P/TIP4P') print(dF) assert abs(dF).max() < 1e-8 # LJInteractionsGeneral with CombineMM. # As it is used within EIQMMM, but avoiding long calculations for tests. # Total system is a unit test system comprised of: # 2 Na ions playing the role of a 'QM' subsystem # 2 Na ions as the 'Counterions' # 2 Water molecules dimer.calc = [] faux_qm = Atoms('2Na', positions=np.array([[1.4, -4, 0], [1.4, 4, 0]])) ions = Atoms('2Na', positions=np.array([[1.4, 0, -4], [1.4, 0, 4]])) mmatoms = ions + dimer sigNa = 1.868 * (1.0 / 2.0)**(1.0 / 6.0) * 10 epsNa = 0.00277 * units.kcal / units.mol # ACI for atoms 0 and 1 of the MM subsystem (2 and 3 for the total system) # 1 atom 'per molecule'. The rest is TIP4P, 3 atoms per molecule: calc = CombineMM( [0, 1], 1, 3, ACI(1, epsNa, sigNa), # calc 1 TIP4P(), # calc 2 [sigNa], [epsNa], # LJs for subsystem 1 sig2, eps2, # arrays for TIP4P from earlier rc=7.5) mmatoms.calc = calc mmatoms.calc.initialize(mmatoms) # LJ arrays for the 'QM' subsystem sig_qm = np.array([sigNa, sigNa]) eps_qm = np.array([epsNa, epsNa]) # For the MM subsystem, tuple of arrays (counterion, water) sig_mm = (np.array([sigNa]), sig2) eps_mm = (np.array([epsNa]), eps2) lj = LJInteractionsGeneral(sig_qm, eps_qm, sig_mm, eps_mm, 2) ecomb, fcomb1, fcomb2 = lj.calculate(faux_qm, mmatoms, np.array([0, 0, 0])) # This should give the same result as if not using CombineMM, on a sum # of these systems: # A: All the Na atoms in the 'QM' region # B: LJInteractions between the 'QM' Na and the 'MM' Na # C: -LJinteractions between the 'MM' Na and the 'MM' Water # A: mmatoms = dimer mmatoms.calc = [] sig_qm = np.concatenate((sig_qm, sig_qm)) eps_qm = np.concatenate((eps_qm, eps_qm)) sig_mm = sig_mm[1] eps_mm = eps_mm[1] lj = LJInteractionsGeneral(sig_qm, eps_qm, sig_mm, eps_mm, 4) ea, fa1, fa2 = lj.calculate(faux_qm + ions, mmatoms, np.array([0, 0, 0])) # B: lj = LJInteractionsGeneral(sig_qm[:2], eps_qm[:2], sig_qm[:2], eps_qm[:2], 2, 2) eb, fb1, fb2, = lj.calculate(faux_qm, ions, np.array([0, 0, 0])) # C: lj = LJInteractionsGeneral(sig_qm[:2], eps_qm[:2], sig_mm, eps_mm, 2, 3) ec, fc1, fc2, = lj.calculate(ions, dimer, np.array([0, 0, 0])) assert ecomb - (ea + eb) + ec == 0
from ase.optimize import BFGS r = rOH a = angleHOH * np.pi / 180 # From http://dx.doi.org/10.1063/1.445869 eexp = 6.24 * units.kcal / units.mol dexp = 2.75 aexp = 46 D = np.linspace(2.5, 3.5, 30) inter = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) for calc in [ TIP4P(), SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P()), SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P(), vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), inter), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), inter, vacuum=3.0), EIQMMM([3, 4, 5], TIP4P(), TIP4P(), inter, vacuum=3.0) ]: dimer = Atoms('OH2OH2', [(0, 0, 0), (r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0), (r * cos(a / 2), r * sin(a / 2), 0), (r * cos(a / 2), -r * sin(a / 2), 0)]) dimer.calc = calc E = [] F = [] for d in D: dimer.positions[3:, 0] += d - dimer.positions[3, 0] E.append(dimer.get_potential_energy())
dexp = 2.75 aexp = 46 D = np.linspace(2.5, 3.5, 30) i = LJInteractions({('O', 'O'): (epsilon0, sigma0)}) # General LJ interaction object sigma_mm = np.array([sigma0, 0, 0]) epsilon_mm = np.array([epsilon0, 0, 0]) sigma_qm = np.array([sigma0, 0, 0]) epsilon_qm = np.array([epsilon0, 0, 0]) ig = LJInteractionsGeneral(sigma_qm, epsilon_qm, sigma_mm, epsilon_mm, 3) for calc in [ TIP4P(), SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P()), SimpleQMMM([0, 1, 2], TIP4P(), TIP4P(), TIP4P(), vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), i), EIQMMM([3, 4, 5], TIP4P(), TIP4P(), i, vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), i, vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), ig), EIQMMM([3, 4, 5], TIP4P(), TIP4P(), ig, vacuum=3.0), EIQMMM([0, 1, 2], TIP4P(), TIP4P(), ig, vacuum=3.0) ]: dimer = Atoms('OH2OH2', [(0, 0, 0), (r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0), (r * cos(a / 2), r * sin(a / 2), 0), (r * cos(a / 2), -r * sin(a / 2), 0)]) dimer.calc = calc E = []
"""Test TIP4P forces.""" from math import cos, sin from ase import Atoms from ase.calculators.tip4p import TIP4P, rOH, angleHOH r = rOH a = angleHOH dimer = Atoms('H2OH2O', [(r * cos(a), 0, r * sin(a)), (r, 0, 0), (0, 0, 0), (r * cos(a / 2), r * sin(a / 2), 0), (r * cos(a / 2), -r * sin(a / 2), 0), (0, 0, 0)]) # tip4p sequence OHH, OHH, .. dimer = dimer[[2]]+dimer[:2]+dimer[[-1]]+dimer[3:5] dimer.positions[3:, 0] += 2.8 dimer.calc = TIP4P(rc=4.0, width=2.0) # put O-O distance in the cutoff range F = dimer.get_forces() print(F) dF = dimer.calc.calculate_numerical_forces(dimer) - F print(dF) assert abs(dF).max() < 2e-6