Statistiques
| Révision :

root / ase / calculators / qmx.py @ 13

Historique | Voir | Annoter | Télécharger (5,99 ko)

1 13 tkerber
"""
2 13 tkerber
This module is the EMBED module for ASE
3 13 tkerber
implemented by T. Kerber
4 2 tkerber

5 13 tkerber
Torsten Kerber, ENS LYON: 2011, 07, 11
6 13 tkerber

7 13 tkerber
This work is supported by Award No. UK-C0017, made by King Abdullah
8 13 tkerber
University of Science and Technology (KAUST)
9 2 tkerber
"""
10 2 tkerber
import ase
11 2 tkerber
import ase.atoms
12 2 tkerber
import numpy as np
13 2 tkerber
from general import Calculator
14 2 tkerber
from ase.embed import Embed
15 3 tkerber
from ase.units import Hartree
16 2 tkerber
17 3 tkerber
from copy import deepcopy
18 3 tkerber
19 2 tkerber
import sys, os
20 2 tkerber
21 2 tkerber
class Qmx(Calculator):
22 5 tkerber
    def __init__(self, calculator_high_cluster,  calculator_low_cluster,  calculator_low_system=None,  print_forces=False):
23 2 tkerber
        self._constraints=None
24 5 tkerber
25 5 tkerber
        self.calculator_low_cluster = calculator_low_cluster
26 5 tkerber
        self.calculator_low_system = calculator_low_system
27 5 tkerber
        if self.calculator_low_system is None:
28 5 tkerber
            self.calculator_low_system = deepcopy(calculator_low_cluster)
29 5 tkerber
        self.calculator_high_cluster = calculator_high_cluster
30 5 tkerber
        self.print_forces = print_forces
31 3 tkerber
32 2 tkerber
    def get_energy_subsystem(self, path, calculator, atoms, force_consistent):
33 3 tkerber
        # go to directory and calculate energies
34 3 tkerber
        print "running energy in: ", path
35 2 tkerber
        os.chdir(path)
36 3 tkerber
        atoms.set_calculator(calculator)
37 3 tkerber
        energy = atoms.get_potential_energy()
38 2 tkerber
        os.chdir("..")
39 2 tkerber
        return energy
40 3 tkerber
41 2 tkerber
    def get_forces_subsystem(self, path, calculator, atoms):
42 3 tkerber
        # go to directory and calculate forces
43 3 tkerber
        print "running forces in: ", path
44 2 tkerber
        os.chdir(path)
45 3 tkerber
        atoms.set_calculator(calculator)
46 3 tkerber
        forces = atoms.get_forces()
47 2 tkerber
        os.chdir("..")
48 2 tkerber
        return forces
49 3 tkerber
50 2 tkerber
    def get_potential_energy(self, embed, force_consistent=False):
51 3 tkerber
        # perform energy calculations
52 3 tkerber
        e_sys_lo = self.get_energy_subsystem("system.low-level", self.calculator_low_system, embed.get_system(), force_consistent)
53 3 tkerber
        e_cl_lo  = self.get_energy_subsystem("cluster.low-level", self.calculator_low_cluster, embed.get_cluster(), force_consistent)
54 5 tkerber
        e_cl_hi  = self.get_energy_subsystem("cluster.high-level", self.calculator_high_cluster, embed.get_cluster(), force_consistent)
55 2 tkerber
        # calculate energies
56 2 tkerber
        energy = e_sys_lo - e_cl_lo + e_cl_hi
57 3 tkerber
        # print energies
58 5 tkerber
        print "%20s = %15s - %15s + %15s" %("E(C:S)", "E(S-MM)", "E(C-MM)", "E(C-QM)")
59 5 tkerber
        print "%20f = %15f - %15f + %15f" %(energy, e_sys_lo, e_cl_lo, e_cl_hi)
60 3 tkerber
        # set energies and return
61 2 tkerber
        if force_consistent:
62 2 tkerber
            self.energy_free = energy
63 2 tkerber
            return self.energy_free
64 2 tkerber
        else:
65 2 tkerber
            self.energy_zero = energy
66 2 tkerber
            return self.energy_zero
67 2 tkerber
68 2 tkerber
    def get_forces(self, embed):
69 2 tkerber
        atom_map_sys_cl = embed.atom_map_sys_cl
70 2 tkerber
        # get forces for the three systems
71 3 tkerber
        f_sys_lo = self.get_forces_subsystem("system.low-level", self.calculator_low_system, embed.get_system())
72 3 tkerber
        f_cl_lo  = self.get_forces_subsystem("cluster.low-level", self.calculator_low_cluster, embed.get_cluster())
73 5 tkerber
        f_cl_hi  = self.get_forces_subsystem("cluster.high-level", self.calculator_high_cluster, embed.get_cluster())
74 5 tkerber
75 2 tkerber
        # forces correction for the atoms
76 2 tkerber
        f_cl = f_cl_hi - f_cl_lo
77 5 tkerber
78 5 tkerber
        if self.print_forces:
79 5 tkerber
            cluster=embed.get_cluster()
80 5 tkerber
            print "Forces: System LOW - Cluster LOW + Cluster HIGH"
81 5 tkerber
            for iat_sys in xrange(len(embed)):
82 5 tkerber
                print "%-2s (" % embed[iat_sys].get_symbol(),
83 5 tkerber
                for idir in xrange(3):
84 5 tkerber
                    print "%10.6f" % f_sys_lo[iat_sys][idir],
85 5 tkerber
                print ") <system LOW>"
86 5 tkerber
87 5 tkerber
                iat_cl = atom_map_sys_cl[iat_sys]
88 5 tkerber
                if iat_cl > -1:
89 5 tkerber
                    print "%s" % "-  (",
90 5 tkerber
                    for idir in xrange(3):
91 5 tkerber
                        print "%10.6f" % f_cl_lo[iat_cl][idir],
92 5 tkerber
                    print ") <cluster LOW>"
93 5 tkerber
                    print "%s" % "+  (",
94 5 tkerber
                    for idir in xrange(3):
95 5 tkerber
                        print "%10.6f" % f_cl_hi[iat_cl][idir],
96 5 tkerber
                    print ") <cluster HIGH>"
97 5 tkerber
                print
98 5 tkerber
            print
99 5 tkerber
100 2 tkerber
        # lo-sys + (hi-lo)
101 5 tkerber
        for iat_sys in xrange(len(embed)):
102 2 tkerber
            iat_cl = atom_map_sys_cl[iat_sys]
103 2 tkerber
            if iat_cl > -1:
104 2 tkerber
                f_sys_lo[iat_sys] += f_cl[iat_cl]
105 5 tkerber
        # some settings for the output
106 5 tkerber
        i_change = np.zeros(len(embed), int)
107 5 tkerber
        if self.print_forces:
108 5 tkerber
            f_sys_lo_orig = f_sys_lo.copy()
109 2 tkerber
        # correct gradients
110 2 tkerber
        # Reference: Eichler, Koelmel, Sauer, J. of Comput. Chem., 18(4). 1997, 463-477.
111 3 tkerber
        for cell_L, iat_cl_sys, iat_sys, r, iat_link in embed.linkatoms:
112 2 tkerber
            # calculate the bond distance (r_bond) at the border
113 3 tkerber
            xyz = embed[iat_sys].get_position() - embed[iat_cl_sys].get_position() + cell_L
114 2 tkerber
            # calculate the bond lenght and the factor f
115 2 tkerber
            rbond = np.sqrt(np.dot(xyz, xyz))
116 2 tkerber
            f = r / rbond
117 2 tkerber
            #normalize xyz
118 2 tkerber
            xyz /= rbond
119 2 tkerber
            # receive the gradients for the link atom
120 3 tkerber
            fL = f_cl[iat_link]
121 3 tkerber
            # dot product fL, xyz
122 5 tkerber
            fs = np.dot(fL, xyz)
123 3 tkerber
            # apply corrections for each direction
124 5 tkerber
            i_change[iat_sys] = 1
125 5 tkerber
            i_change[iat_cl_sys] = 1
126 2 tkerber
            for idir in xrange(3):
127 2 tkerber
                # correct the atom in the system
128 5 tkerber
                f_sys_lo[iat_sys][idir] = f_sys_lo[iat_sys][idir] + f*fL[idir] - f*fs*xyz[idir]
129 2 tkerber
                # correct the atom in the cluster
130 5 tkerber
                f_sys_lo[iat_cl_sys][idir] = f_sys_lo[iat_cl_sys][idir] + (1-f)*fL[idir] + f*fs*xyz[idir]
131 5 tkerber
132 5 tkerber
        if self.print_forces:
133 5 tkerber
            print " TOTAL FORCE (uncorrected : corrected) for link atoms"
134 5 tkerber
            for iat_sys in xrange(len(embed)):
135 5 tkerber
                print "%-2s (" % embed[iat_sys].get_symbol(),
136 5 tkerber
                for idir in xrange(3):
137 5 tkerber
                    print "%10.6f" % f_sys_lo_orig[iat_sys][idir],
138 5 tkerber
                print ") : (",
139 5 tkerber
                for idir in xrange(3):
140 5 tkerber
                    print "%10.6f" % f_sys_lo[iat_sys][idir],
141 5 tkerber
                print ")",
142 5 tkerber
                if i_change[iat_sys]:
143 5 tkerber
                    print " *",
144 5 tkerber
                print
145 5 tkerber
            print
146 5 tkerber
147 2 tkerber
        return f_sys_lo