Statistiques
| Révision :

root / ase / calculators / qmx.py @ 16

Historique | Voir | Annoter | Télécharger (6,23 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 16 tkerber
        # writing output
34 16 tkerber
        line = "running energy in: " + path + "\n"
35 16 tkerber
        sys.stderr.write(line)
36 3 tkerber
        # go to directory and calculate energies
37 2 tkerber
        os.chdir(path)
38 3 tkerber
        atoms.set_calculator(calculator)
39 3 tkerber
        energy = atoms.get_potential_energy()
40 16 tkerber
        # return path and result
41 2 tkerber
        os.chdir("..")
42 2 tkerber
        return energy
43 3 tkerber
44 2 tkerber
    def get_forces_subsystem(self, path, calculator, atoms):
45 16 tkerber
        # writing output
46 16 tkerber
        line = "running forces in: " + path + "\n"
47 16 tkerber
        sys.stderr.write(line)
48 3 tkerber
        # go to directory and calculate forces
49 2 tkerber
        os.chdir(path)
50 3 tkerber
        atoms.set_calculator(calculator)
51 3 tkerber
        forces = atoms.get_forces()
52 16 tkerber
        # return path and result
53 2 tkerber
        os.chdir("..")
54 2 tkerber
        return forces
55 3 tkerber
56 2 tkerber
    def get_potential_energy(self, embed, force_consistent=False):
57 3 tkerber
        # perform energy calculations
58 3 tkerber
        e_sys_lo = self.get_energy_subsystem("system.low-level", self.calculator_low_system, embed.get_system(), force_consistent)
59 3 tkerber
        e_cl_lo  = self.get_energy_subsystem("cluster.low-level", self.calculator_low_cluster, embed.get_cluster(), force_consistent)
60 5 tkerber
        e_cl_hi  = self.get_energy_subsystem("cluster.high-level", self.calculator_high_cluster, embed.get_cluster(), force_consistent)
61 2 tkerber
        # calculate energies
62 2 tkerber
        energy = e_sys_lo - e_cl_lo + e_cl_hi
63 3 tkerber
        # print energies
64 16 tkerber
        print "%20s = %15s - %15s + %15s" %("E(C:S)", "E(S,LL)", "E(C,LL)", "E(C,HL)")
65 5 tkerber
        print "%20f = %15f - %15f + %15f" %(energy, e_sys_lo, e_cl_lo, e_cl_hi)
66 3 tkerber
        # set energies and return
67 2 tkerber
        if force_consistent:
68 2 tkerber
            self.energy_free = energy
69 2 tkerber
            return self.energy_free
70 2 tkerber
        else:
71 2 tkerber
            self.energy_zero = energy
72 2 tkerber
            return self.energy_zero
73 2 tkerber
74 2 tkerber
    def get_forces(self, embed):
75 2 tkerber
        atom_map_sys_cl = embed.atom_map_sys_cl
76 2 tkerber
        # get forces for the three systems
77 3 tkerber
        f_sys_lo = self.get_forces_subsystem("system.low-level", self.calculator_low_system, embed.get_system())
78 3 tkerber
        f_cl_lo  = self.get_forces_subsystem("cluster.low-level", self.calculator_low_cluster, embed.get_cluster())
79 5 tkerber
        f_cl_hi  = self.get_forces_subsystem("cluster.high-level", self.calculator_high_cluster, embed.get_cluster())
80 5 tkerber
81 2 tkerber
        # forces correction for the atoms
82 2 tkerber
        f_cl = f_cl_hi - f_cl_lo
83 5 tkerber
84 5 tkerber
        if self.print_forces:
85 5 tkerber
            cluster=embed.get_cluster()
86 5 tkerber
            print "Forces: System LOW - Cluster LOW + Cluster HIGH"
87 5 tkerber
            for iat_sys in xrange(len(embed)):
88 5 tkerber
                print "%-2s (" % embed[iat_sys].get_symbol(),
89 5 tkerber
                for idir in xrange(3):
90 5 tkerber
                    print "%10.6f" % f_sys_lo[iat_sys][idir],
91 5 tkerber
                print ") <system LOW>"
92 5 tkerber
93 5 tkerber
                iat_cl = atom_map_sys_cl[iat_sys]
94 5 tkerber
                if iat_cl > -1:
95 5 tkerber
                    print "%s" % "-  (",
96 5 tkerber
                    for idir in xrange(3):
97 5 tkerber
                        print "%10.6f" % f_cl_lo[iat_cl][idir],
98 5 tkerber
                    print ") <cluster LOW>"
99 5 tkerber
                    print "%s" % "+  (",
100 5 tkerber
                    for idir in xrange(3):
101 5 tkerber
                        print "%10.6f" % f_cl_hi[iat_cl][idir],
102 5 tkerber
                    print ") <cluster HIGH>"
103 5 tkerber
                print
104 5 tkerber
            print
105 5 tkerber
106 2 tkerber
        # lo-sys + (hi-lo)
107 5 tkerber
        for iat_sys in xrange(len(embed)):
108 2 tkerber
            iat_cl = atom_map_sys_cl[iat_sys]
109 2 tkerber
            if iat_cl > -1:
110 2 tkerber
                f_sys_lo[iat_sys] += f_cl[iat_cl]
111 5 tkerber
        # some settings for the output
112 5 tkerber
        i_change = np.zeros(len(embed), int)
113 5 tkerber
        if self.print_forces:
114 5 tkerber
            f_sys_lo_orig = f_sys_lo.copy()
115 2 tkerber
        # correct gradients
116 2 tkerber
        # Reference: Eichler, Koelmel, Sauer, J. of Comput. Chem., 18(4). 1997, 463-477.
117 3 tkerber
        for cell_L, iat_cl_sys, iat_sys, r, iat_link in embed.linkatoms:
118 2 tkerber
            # calculate the bond distance (r_bond) at the border
119 3 tkerber
            xyz = embed[iat_sys].get_position() - embed[iat_cl_sys].get_position() + cell_L
120 2 tkerber
            # calculate the bond lenght and the factor f
121 2 tkerber
            rbond = np.sqrt(np.dot(xyz, xyz))
122 2 tkerber
            f = r / rbond
123 2 tkerber
            #normalize xyz
124 2 tkerber
            xyz /= rbond
125 2 tkerber
            # receive the gradients for the link atom
126 3 tkerber
            fL = f_cl[iat_link]
127 3 tkerber
            # dot product fL, xyz
128 5 tkerber
            fs = np.dot(fL, xyz)
129 3 tkerber
            # apply corrections for each direction
130 5 tkerber
            i_change[iat_sys] = 1
131 5 tkerber
            i_change[iat_cl_sys] = 1
132 2 tkerber
            for idir in xrange(3):
133 2 tkerber
                # correct the atom in the system
134 5 tkerber
                f_sys_lo[iat_sys][idir] = f_sys_lo[iat_sys][idir] + f*fL[idir] - f*fs*xyz[idir]
135 2 tkerber
                # correct the atom in the cluster
136 5 tkerber
                f_sys_lo[iat_cl_sys][idir] = f_sys_lo[iat_cl_sys][idir] + (1-f)*fL[idir] + f*fs*xyz[idir]
137 5 tkerber
138 5 tkerber
        if self.print_forces:
139 5 tkerber
            print " TOTAL FORCE (uncorrected : corrected) for link atoms"
140 5 tkerber
            for iat_sys in xrange(len(embed)):
141 5 tkerber
                print "%-2s (" % embed[iat_sys].get_symbol(),
142 5 tkerber
                for idir in xrange(3):
143 5 tkerber
                    print "%10.6f" % f_sys_lo_orig[iat_sys][idir],
144 5 tkerber
                print ") : (",
145 5 tkerber
                for idir in xrange(3):
146 5 tkerber
                    print "%10.6f" % f_sys_lo[iat_sys][idir],
147 5 tkerber
                print ")",
148 5 tkerber
                if i_change[iat_sys]:
149 5 tkerber
                    print " *",
150 5 tkerber
                print
151 5 tkerber
            print
152 5 tkerber
153 2 tkerber
        return f_sys_lo
154 16 tkerber
155 16 tkerber
    def get_stress(self, atoms):
156 16 tkerber
            return None