Révision 3 ase/calculators/qmx.py

qmx.py (revision 3)
8 8
import numpy as np
9 9
from general import Calculator
10 10
from ase.embed import Embed
11
from ase.units import Hartree
11 12

  
13
from copy import deepcopy
14

  
12 15
import sys, os
13 16

  
14 17
class Qmx(Calculator):
15
    def __init__(self, calculator_low, calculator_high):
16
        self.string_params = {}
17
        
18
        self.forces=np.zeros((2,2))
18
    def __init__(self, calculator_high,  calculator_low):
19 19
        self._constraints=None
20
        
21
        self.calculator_low = calculator_low
22
        self.calculator_high = calculator_high
23
                
20
        self.calculator_low_cluster = calculator_low
21
        self.calculator_low_system = deepcopy(calculator_low)
22
        self.calculator_high = calculator_high            
23

  
24 24
    def get_energy_subsystem(self, path, calculator, atoms, force_consistent):
25
        # go to directory and calculate energies
26
        print "running energy in: ", path
25 27
        os.chdir(path)
26
        calculator.set_atoms(atoms)
27
        energy = calculator.get_potential_energy(atoms)
28
        atoms.set_calculator(calculator)
29
        energy = atoms.get_potential_energy()
28 30
        os.chdir("..")
29 31
        return energy
30
        
32

  
31 33
    def get_forces_subsystem(self, path, calculator, atoms):
34
        # go to directory and calculate forces
35
        print "running forces in: ", path
32 36
        os.chdir(path)
33
        calculator.set_atoms(atoms)
34
        forces = calculator.get_forces(atoms)
37
        atoms.set_calculator(calculator)
38
        forces = atoms.get_forces()
35 39
        os.chdir("..")
36 40
        return forces
37
        
38
        
41

  
39 42
    def get_potential_energy(self, embed, force_consistent=False):
40
        # perform energy calculations 
41
        e_sys_lo = self.get_energy_subsystem("system.low-level", self.calculator_low, embed.get_system(), force_consistent)
42
        e_cl_lo  = self.get_energy_subsystem("cluster.low-level", self.calculator_low, embed.get_cluster(), force_consistent)
43
        # perform energy calculations
44
        e_sys_lo = self.get_energy_subsystem("system.low-level", self.calculator_low_system, embed.get_system(), force_consistent)
45
        e_cl_lo  = self.get_energy_subsystem("cluster.low-level", self.calculator_low_cluster, embed.get_cluster(), force_consistent)
43 46
        e_cl_hi  = self.get_energy_subsystem("cluster.high-level", self.calculator_high, embed.get_cluster(), force_consistent)
44 47
        # calculate energies
45 48
        energy = e_sys_lo - e_cl_lo + e_cl_hi
49
        # print energies
46 50
        print "%20s=%15s - %15s + %15s" %("E(C:S)", "E(S-MM)", "E(C-MM)", "E(C-QM)")
47 51
        print "%20f=%15f - %15f + %15f" %(energy, e_sys_lo, e_cl_lo, e_cl_hi)
52
        # set energies and return
48 53
        if force_consistent:
49 54
            self.energy_free = energy
50 55
            return self.energy_free
......
55 60
    def get_forces(self, embed):
56 61
        atom_map_sys_cl = embed.atom_map_sys_cl
57 62
        # get forces for the three systems
58
        f_sys_lo = self.get_forces_subsystem("system.low-level", self.calculator_low, embed.get_system())
59
        f_cl_lo  = self.get_forces_subsystem("cluster.low-level", self.calculator_low, embed.get_cluster())
63
        f_sys_lo = self.get_forces_subsystem("system.low-level", self.calculator_low_system, embed.get_system())
64
        f_cl_lo  = self.get_forces_subsystem("cluster.low-level", self.calculator_low_cluster, embed.get_cluster())
60 65
        f_cl_hi  = self.get_forces_subsystem("cluster.high-level", self.calculator_high, embed.get_cluster())
61 66
        # forces correction for the atoms
62 67
        f_cl = f_cl_hi - f_cl_lo
63
        #number of atoms
68
        # number of atoms
64 69
        nat_sys = len(embed)
65 70
        # lo-sys + (hi-lo)
66 71
        for iat_sys in xrange(nat_sys):
67 72
            iat_cl = atom_map_sys_cl[iat_sys]
68 73
            if iat_cl > -1:
69 74
                f_sys_lo[iat_sys] += f_cl[iat_cl]
70
        
75

  
71 76
        # correct gradients
72 77
        # Reference: Eichler, Koelmel, Sauer, J. of Comput. Chem., 18(4). 1997, 463-477.
73
        for cell_L, iat_cl, iat_sys, r, iat_link in embed.linkatoms:
78
        for cell_L, iat_cl_sys, iat_sys, r, iat_link in embed.linkatoms:
74 79
            # calculate the bond distance (r_bond) at the border
75
            xyz = embed[iat_sys].get_position() - embed.get_cluster()[iat_cl].get_position() + cell_L
80
            xyz = embed[iat_sys].get_position() - embed[iat_cl_sys].get_position() + cell_L
76 81
            
77 82
            # calculate the bond lenght and the factor f
78 83
            rbond = np.sqrt(np.dot(xyz, xyz))
79 84
            f = r / rbond
80 85
            #normalize xyz
81 86
            xyz /= rbond
82
            
83 87
            # receive the gradients for the link atom
84
            fH = f_cl[iat_link]
85
            # Skalarprodukt fH, xyz
86
            fs = np.dot(xyz, fH)
87
            
88
            fL = f_cl[iat_link]
89
            # dot product fL, xyz
90
            fs = np.dot(xyz, fL)
91
            # apply corrections for each direction
88 92
            for idir in xrange(3):
89 93
                # correct the atom in the system
90
                f_sys_lo[iat_sys][idir] += f*fH[idir] - f*fs*xyz[idir]
94
                f_sys_lo[iat_sys][idir] += f*fL[idir] - f*fs*xyz[idir]
91 95
                # correct the atom in the cluster
92
                f_sys_lo[iat_cl][idir] += (1-f)*fH[idir] + f*fs*xyz[idir]
96
                f_sys_lo[iat_cl_sys][idir] += (1-f)*fL[idir] + f*fs*xyz[idir]
93 97
        return f_sys_lo
94

  
95
    def set_atoms(self, atoms):
96
        return
97
           
98
            
99

  

Formats disponibles : Unified diff