Statistiques
| Révision :

root / ase / calculators / qmx.py @ 2

Historique | Voir | Annoter | Télécharger (3,69 ko)

1 2 tkerber
""" This is a QM:MM embedded system for ASE
2 2 tkerber

3 2 tkerber
torsten.kerber@ens-lyon.fr
4 2 tkerber
"""
5 2 tkerber
6 2 tkerber
import ase
7 2 tkerber
import ase.atoms
8 2 tkerber
import numpy as np
9 2 tkerber
from general import Calculator
10 2 tkerber
from ase.embed import Embed
11 2 tkerber
12 2 tkerber
import sys, os
13 2 tkerber
14 2 tkerber
class Qmx(Calculator):
15 2 tkerber
    def __init__(self, calculator_low, calculator_high):
16 2 tkerber
        self.string_params = {}
17 2 tkerber
18 2 tkerber
        self.forces=np.zeros((2,2))
19 2 tkerber
        self._constraints=None
20 2 tkerber
21 2 tkerber
        self.calculator_low = calculator_low
22 2 tkerber
        self.calculator_high = calculator_high
23 2 tkerber
24 2 tkerber
    def get_energy_subsystem(self, path, calculator, atoms, force_consistent):
25 2 tkerber
        os.chdir(path)
26 2 tkerber
        calculator.set_atoms(atoms)
27 2 tkerber
        energy = calculator.get_potential_energy(atoms)
28 2 tkerber
        os.chdir("..")
29 2 tkerber
        return energy
30 2 tkerber
31 2 tkerber
    def get_forces_subsystem(self, path, calculator, atoms):
32 2 tkerber
        os.chdir(path)
33 2 tkerber
        calculator.set_atoms(atoms)
34 2 tkerber
        forces = calculator.get_forces(atoms)
35 2 tkerber
        os.chdir("..")
36 2 tkerber
        return forces
37 2 tkerber
38 2 tkerber
39 2 tkerber
    def get_potential_energy(self, embed, force_consistent=False):
40 2 tkerber
        # perform energy calculations
41 2 tkerber
        e_sys_lo = self.get_energy_subsystem("system.low-level", self.calculator_low, embed.get_system(), force_consistent)
42 2 tkerber
        e_cl_lo  = self.get_energy_subsystem("cluster.low-level", self.calculator_low, embed.get_cluster(), force_consistent)
43 2 tkerber
        e_cl_hi  = self.get_energy_subsystem("cluster.high-level", self.calculator_high, embed.get_cluster(), force_consistent)
44 2 tkerber
        # calculate energies
45 2 tkerber
        energy = e_sys_lo - e_cl_lo + e_cl_hi
46 2 tkerber
        print "%20s=%15s - %15s + %15s" %("E(C:S)", "E(S-MM)", "E(C-MM)", "E(C-QM)")
47 2 tkerber
        print "%20f=%15f - %15f + %15f" %(energy, e_sys_lo, e_cl_lo, e_cl_hi)
48 2 tkerber
        if force_consistent:
49 2 tkerber
            self.energy_free = energy
50 2 tkerber
            return self.energy_free
51 2 tkerber
        else:
52 2 tkerber
            self.energy_zero = energy
53 2 tkerber
            return self.energy_zero
54 2 tkerber
55 2 tkerber
    def get_forces(self, embed):
56 2 tkerber
        atom_map_sys_cl = embed.atom_map_sys_cl
57 2 tkerber
        # get forces for the three systems
58 2 tkerber
        f_sys_lo = self.get_forces_subsystem("system.low-level", self.calculator_low, embed.get_system())
59 2 tkerber
        f_cl_lo  = self.get_forces_subsystem("cluster.low-level", self.calculator_low, embed.get_cluster())
60 2 tkerber
        f_cl_hi  = self.get_forces_subsystem("cluster.high-level", self.calculator_high, embed.get_cluster())
61 2 tkerber
        # forces correction for the atoms
62 2 tkerber
        f_cl = f_cl_hi - f_cl_lo
63 2 tkerber
        #number of atoms
64 2 tkerber
        nat_sys = len(embed)
65 2 tkerber
        # lo-sys + (hi-lo)
66 2 tkerber
        for iat_sys in xrange(nat_sys):
67 2 tkerber
            iat_cl = atom_map_sys_cl[iat_sys]
68 2 tkerber
            if iat_cl > -1:
69 2 tkerber
                f_sys_lo[iat_sys] += f_cl[iat_cl]
70 2 tkerber
71 2 tkerber
        # correct gradients
72 2 tkerber
        # Reference: Eichler, Koelmel, Sauer, J. of Comput. Chem., 18(4). 1997, 463-477.
73 2 tkerber
        for cell_L, iat_cl, iat_sys, r, iat_link in embed.linkatoms:
74 2 tkerber
            # calculate the bond distance (r_bond) at the border
75 2 tkerber
            xyz = embed[iat_sys].get_position() - embed.get_cluster()[iat_cl].get_position() + cell_L
76 2 tkerber
77 2 tkerber
            # calculate the bond lenght and the factor f
78 2 tkerber
            rbond = np.sqrt(np.dot(xyz, xyz))
79 2 tkerber
            f = r / rbond
80 2 tkerber
            #normalize xyz
81 2 tkerber
            xyz /= rbond
82 2 tkerber
83 2 tkerber
            # receive the gradients for the link atom
84 2 tkerber
            fH = f_cl[iat_link]
85 2 tkerber
            # Skalarprodukt fH, xyz
86 2 tkerber
            fs = np.dot(xyz, fH)
87 2 tkerber
88 2 tkerber
            for idir in xrange(3):
89 2 tkerber
                # correct the atom in the system
90 2 tkerber
                f_sys_lo[iat_sys][idir] += f*fH[idir] - f*fs*xyz[idir]
91 2 tkerber
                # correct the atom in the cluster
92 2 tkerber
                f_sys_lo[iat_cl][idir] += (1-f)*fH[idir] + f*fs*xyz[idir]
93 2 tkerber
        return f_sys_lo
94 2 tkerber
95 2 tkerber
    def set_atoms(self, atoms):
96 2 tkerber
        return
97 2 tkerber
98 2 tkerber