Example #1
0
def test_qmmm_acn():
    import numpy as np

    import ase.units as units
    from ase import Atoms
    from ase.calculators.acn import (ACN, m_me, r_cn, r_mec,
                                     sigma_me, sigma_c, sigma_n,
                                     epsilon_me, epsilon_c, epsilon_n)
    from ase.calculators.qmmm import SimpleQMMM, LJInteractionsGeneral, EIQMMM
    from ase.constraints import FixLinearTriatomic
    from ase.optimize import BFGS

    # From https://www.sciencedirect.com/science/article/pii/S0166128099002079
    eref = 4.9 * units.kcal / units.mol
    dref = 3.368
    aref = 79.1

    sigma = np.array([sigma_me, sigma_c, sigma_n])
    epsilon = np.array([epsilon_me, epsilon_c, epsilon_n])
    inter = LJInteractionsGeneral(sigma, epsilon, sigma, epsilon, 3)

    for calc in [ACN(),
                 SimpleQMMM([0, 1, 2], ACN(), ACN(), ACN()),
                 SimpleQMMM([0, 1, 2], ACN(), ACN(), ACN(), vacuum=3.0),
                 EIQMMM([0, 1, 2], ACN(), ACN(), inter),
                 EIQMMM([0, 1, 2], ACN(), ACN(), inter, vacuum=3.0),
                 EIQMMM([3, 4, 5], ACN(), ACN(), inter, vacuum=3.0)]:
        dimer = Atoms('CCNCCN',
                      [(-r_mec, 0, 0),
                       (0, 0, 0),
                       (r_cn, 0, 0),
                       (r_mec, 3.7, 0),
                       (0, 3.7, 0),
                       (-r_cn, 3.7, 0)])

        masses = dimer.get_masses()
        masses[::3] = m_me
        dimer.set_masses(masses)

        dimer.calc = calc

        fixd = FixLinearTriatomic(triples=[(0, 1, 2), (3, 4, 5)])

        dimer.set_constraint(fixd)

        opt = BFGS(dimer, maxstep=0.04,
                   trajectory=calc.name + '.traj', logfile=calc.name + 'd.log')
        opt.run(0.001, steps=1000)

        e0 = dimer.get_potential_energy()
        d0 = dimer.get_distance(1, 4)
        a0 = dimer.get_angle(2, 1, 4)
        fmt = '{0:>25}: {1:.3f} {2:.3f} {3:.1f}'
        print(fmt.format(calc.name, -e0, d0, a0))
        assert abs(e0 + eref) < 0.013
        assert abs(d0 - dref) < 0.224
        assert abs(a0 - aref) < 2.9

    print(fmt.format('reference', eref, dref, aref))
def test_rattle_linear():
    """Test RATTLE and QM/MM for rigid linear acetonitrile."""

    import numpy as np

    from ase import Atoms
    from ase.calculators.acn import (ACN, m_me, r_cn, r_mec, sigma_me, sigma_c,
                                     sigma_n, epsilon_me, epsilon_c, epsilon_n)
    from ase.calculators.qmmm import SimpleQMMM, EIQMMM, LJInteractionsGeneral
    from ase.md.verlet import VelocityVerlet
    from ase.constraints import FixLinearTriatomic
    import ase.units as units

    sigma = np.array([sigma_me, sigma_c, sigma_n])
    epsilon = np.array([epsilon_me, epsilon_c, epsilon_n])
    i = LJInteractionsGeneral(sigma, epsilon, sigma, epsilon, 3)

    for calc in [
            ACN(),
            SimpleQMMM([0, 1, 2], ACN(), ACN(), ACN()),
            EIQMMM([0, 1, 2], ACN(), ACN(), i)
    ]:

        dimer = Atoms('CCNCCN', [(-r_mec, 0, 0), (0, 0, 0), (r_cn, 0, 0),
                                 (r_mec, 3.7, 0), (0, 3.7, 0),
                                 (-r_cn, 3.7, 0)])

        masses = dimer.get_masses()
        masses[::3] = m_me
        dimer.set_masses(masses)

        fixd = FixLinearTriatomic(triples=[(0, 1, 2), (3, 4, 5)])

        dimer.set_constraint(fixd)

        dimer.calc = calc

        d1 = dimer[:3].get_all_distances()
        d2 = dimer[3:].get_all_distances()
        e = dimer.get_potential_energy()

        md = VelocityVerlet(dimer,
                            2.0 * units.fs,
                            trajectory=calc.name + '.traj',
                            logfile=calc.name + '.log',
                            loginterval=20)
        md.run(100)

        de = dimer.get_potential_energy() - e

        assert np.all(abs(dimer[:3].get_all_distances() - d1) < 1e-10)
        assert np.all(abs(dimer[3:].get_all_distances() - d2) < 1e-10)
        assert abs(de - -0.005) < 0.001
Example #3
0
    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]
Example #4
0
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))
Example #5
0
"""Test RATTLE and QM/MM for rigid linear acetonitrile."""

import numpy as np

from ase import Atoms
from ase.calculators.acn import (ACN, m_me, r_cn, r_mec, sigma_me, sigma_c,
                                 sigma_n, epsilon_me, epsilon_c, epsilon_n)
from ase.calculators.qmmm import SimpleQMMM, EIQMMM, LJInteractionsGeneral
from ase.md.verlet import VelocityVerlet
from ase.constraints import FixLinearTriatomic
import ase.units as units

sigma = np.array([sigma_me, sigma_c, sigma_n])
epsilon = np.array([epsilon_me, epsilon_c, epsilon_n])
i = LJInteractionsGeneral(sigma, epsilon, sigma, epsilon, 3)

for calc in [
        ACN(),
        SimpleQMMM([0, 1, 2], ACN(), ACN(), ACN()),
        EIQMMM([0, 1, 2], ACN(), ACN(), i)
]:

    dimer = Atoms('CCNCCN', [(-r_mec, 0, 0), (0, 0, 0), (r_cn, 0, 0),
                             (r_mec, 3.7, 0), (0, 3.7, 0), (-r_cn, 3.7, 0)])

    masses = dimer.get_masses()
    masses[::3] = m_me
    dimer.set_masses(masses)

    fixd = FixLinearTriatomic(triples=[(0, 1, 2), (3, 4, 5)])
Example #6
0
# From http://dx.doi.org/10.1063/1.445869
eexp = 6.50 * units.kcal / units.mol
dexp = 2.74
aexp = 27

D = np.linspace(2.5, 3.5, 30)

i = LJInteractions({('O', 'O'): (epsilon0, sigma0)})

# General LJ interaction object
sigma_mm = np.array([0, 0, sigma0])
epsilon_mm = np.array([0, 0, epsilon0])
sigma_qm = np.array([0, 0, sigma0])
epsilon_qm = np.array([0, 0, epsilon0])
ig = LJInteractionsGeneral(sigma_qm, epsilon_qm, sigma_mm, epsilon_mm, 3)

for calc in [TIP3P(),
             SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P()),
             SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P(), vacuum=3.0),
             EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i),
             EIQMMM([3, 4, 5], TIP3P(), TIP3P(), i, vacuum=3.0),
             EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i, vacuum=3.0),
             EIQMMM([0, 1, 2], TIP3P(), TIP3P(), ig),
             EIQMMM([3, 4, 5], TIP3P(), TIP3P(), ig, vacuum=3.0),
             EIQMMM([0, 1, 2], TIP3P(), TIP3P(), ig, vacuum=3.0)]:
    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),
Example #7
0
def test_qmmm(testdir):
    r = rOH
    a = angleHOH * pi / 180

    # From https://doi.org/10.1063/1.445869
    eexp = 6.50 * units.kcal / units.mol
    dexp = 2.74
    aexp = 27

    D = np.linspace(2.5, 3.5, 30)

    i = LJInteractions({('O', 'O'): (epsilon0, sigma0)})

    # General LJ interaction object
    sigma_mm = np.array([0, 0, sigma0])
    epsilon_mm = np.array([0, 0, epsilon0])
    sigma_qm = np.array([0, 0, sigma0])
    epsilon_qm = np.array([0, 0, epsilon0])
    ig = LJInteractionsGeneral(sigma_qm, epsilon_qm, sigma_mm, epsilon_mm, 3)

    for calc in [
            TIP3P(),
            SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P()),
            SimpleQMMM([0, 1, 2], TIP3P(), TIP3P(), TIP3P(), vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i),
            EIQMMM([3, 4, 5], TIP3P(), TIP3P(), i, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), i, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), ig),
            EIQMMM([3, 4, 5], TIP3P(), TIP3P(), ig, vacuum=3.0),
            EIQMMM([0, 1, 2], TIP3P(), TIP3P(), ig, vacuum=3.0)
    ]:
        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.calc = calc

        E = []
        F = []
        for d in D:
            dimer.positions[3:, 0] += d - dimer.positions[5, 0]
            E.append(dimer.get_potential_energy())
            F.append(dimer.get_forces())

        F = np.array(F)

        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, 2)), (r, (1, 2)),
                                                (r, (3, 5)), (r, (4, 5))],
                                         angles_deg=[
                                             (np.degrees(a), (0, 2, 1)),
                                             (np.degrees(a), (3, 5, 4))
                                         ])
        opt = GPMin(dimer,
                    trajectory=calc.name + '.traj',
                    logfile=calc.name + 'd.log')
        opt.run(0.01)

        e0 = dimer.get_potential_energy()
        d0 = dimer.get_distance(2, 5)
        R = dimer.positions
        v1 = R[1] - R[5]
        v2 = R[5] - (R[3] + 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:>20}: {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.01
        assert abs(a0 - aexp) < 4

    print(fmt.format('reference', 9.999, eexp, dexp, aexp))
Example #8
0
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