Révision 2
ase/optimize/optimize.py (revision 2) | ||
---|---|---|
9 | 9 |
import numpy as np |
10 | 10 |
|
11 | 11 |
from ase.parallel import rank, barrier |
12 |
from ase.io.trajectory import PickleTrajectory |
|
12 |
#from ase.io.trajectory import PickleTrajectory
|
|
13 | 13 |
|
14 | 14 |
|
15 | 15 |
class Dynamics: |
ase/svnversion.py (revision 2) | ||
---|---|---|
1 |
svnversion = "1765" |
|
1 |
svnversion = "4M" |
ase/embed.py (revision 2) | ||
---|---|---|
1 |
from ase import Atom, Atoms |
|
2 |
from ase.data import covalent_radii, atomic_numbers |
|
3 |
|
|
4 |
import numpy as np |
|
5 |
|
|
6 |
class Embed(Atoms): |
|
7 |
#--- constructor of the Embed class --- |
|
8 |
def __init__(self, system=None, cluster=None): |
|
9 |
super(Embed, self).__init__() |
|
10 |
# define the atom map |
|
11 |
self.atom_map_sys_cl = [] |
|
12 |
self.linkatoms = [] |
|
13 |
# cluster dimensions |
|
14 |
self.xyz_cl_min = None |
|
15 |
self.xyz_cl_max = None |
|
16 |
# set the search radius for link atoms |
|
17 |
self.d = 10 |
|
18 |
# define the systems for calculations |
|
19 |
self.set_system(system) |
|
20 |
self.set_cluster(cluster) |
|
21 |
# |
|
22 |
self.set_cell([10, 10, 10]) |
|
23 |
return |
|
24 |
|
|
25 |
#--- set the cluster --- |
|
26 |
def set_cluster(self, atoms): |
|
27 |
import copy |
|
28 |
# set the min/max cluster dimensions |
|
29 |
self.xyz_cl_min = atoms[0].get_position() |
|
30 |
self.xyz_cl_max = atoms[0].get_position() |
|
31 |
for atom in atoms: |
|
32 |
# assign the label "Cluster (10)" in atom.TAG |
|
33 |
atom.set_tag(10) |
|
34 |
xyz=atom.get_position() |
|
35 |
for i in xrange(3): |
|
36 |
# set the min/max cluster dimensions |
|
37 |
if xyz[i] < self.xyz_cl_min[i]: |
|
38 |
self.xyz_cl_min[i] = xyz[i] |
|
39 |
if xyz[i] > self.xyz_cl_max[i]: |
|
40 |
self.xyz_cl_max[i] = xyz[i] |
|
41 |
|
|
42 |
# add self.d around min/max cluster dimensions |
|
43 |
self.xyz_cl_min -= [self.d, self.d, self.d] |
|
44 |
self.xyz_cl_max += [self.d, self.d, self.d] |
|
45 |
# set the cluster for low and high level calculation |
|
46 |
self.atoms_cluster = atoms |
|
47 |
return |
|
48 |
|
|
49 |
#--- set the system --- |
|
50 |
def set_system(self, atoms): |
|
51 |
self.atoms_system = atoms |
|
52 |
# assign the label "Cluster (10)" in atom.TAG |
|
53 |
for atom in atoms: |
|
54 |
atom.set_tag(0) |
|
55 |
# update search radius for link atoms |
|
56 |
dx = 0 |
|
57 |
for atom in atoms: |
|
58 |
r = covalent_radii[atom.get_atomic_number()] |
|
59 |
if (r > dx): |
|
60 |
dx = r |
|
61 |
self.d = dx * 2.1 |
|
62 |
return |
|
63 |
|
|
64 |
#--- return cluster --- |
|
65 |
def get_cluster(self): |
|
66 |
return self.atoms_cluster |
|
67 |
|
|
68 |
def get_system(self): |
|
69 |
return self.atoms_system |
|
70 |
|
|
71 |
#--- Embedding --- |
|
72 |
def embed(self): |
|
73 |
# is the cluster and the host system definied ? |
|
74 |
if self.atoms_cluster is None or self.atoms_system is None: |
|
75 |
return |
|
76 |
self.find_cluster() |
|
77 |
self.set_linkatoms() |
|
78 |
print "link atoms found: ", len(self.linkatoms) |
|
79 |
|
|
80 |
def find_cluster(self): |
|
81 |
# set tolerance |
|
82 |
d = 0.001 |
|
83 |
#atoms |
|
84 |
xyzs_cl=[] |
|
85 |
for atom_cl in self.atoms_cluster: |
|
86 |
xyzs_cl.append(atom_cl.get_position()) |
|
87 |
xyzs_sys=[] |
|
88 |
for atom_sys in self.atoms_system: |
|
89 |
xyzs_sys.append(atom_sys.get_position()) |
|
90 |
|
|
91 |
self.atom_map_sys_cl=np.zeros(len(self.atoms_system), int) |
|
92 |
# loop over cluster atoms atom_sys |
|
93 |
for iat_sys in xrange(len(self.atoms_system)): |
|
94 |
# get the coordinates of the system atom atom_sys |
|
95 |
xyz_sys = xyzs_sys[iat_sys] |
|
96 |
# bSysOnly: no identical atom has been found |
|
97 |
bSysOnly = True |
|
98 |
# loop over system atoms atom_cl |
|
99 |
for iat_cl in xrange(len(self.atoms_cluster)): |
|
100 |
# difference vector between both atoms |
|
101 |
xyz_diff = np.abs(xyzs_sys[iat_sys]-xyzs_cl[iat_cl]) |
|
102 |
# identical atoms |
|
103 |
if xyz_diff[0] < d and xyz_diff[1] < d and xyz_diff[2] < d: |
|
104 |
# set tag (CLUSTER+HOST: 10) to atom_sys |
|
105 |
self.atoms_system[iat_sys].set_tag(10) |
|
106 |
# map the atom in the atom list |
|
107 |
self.atom_map_sys_cl[iat_sys]=iat_cl |
|
108 |
# atom has been identified |
|
109 |
bSysOnly = False |
|
110 |
break |
|
111 |
if bSysOnly: |
|
112 |
self.atom_map_sys_cl[iat_sys] = -1 |
|
113 |
|
|
114 |
def set_linkatoms(self, tol=15., linkAtom=None, debug=False): |
|
115 |
# local copies of xyz coordinates to avoid massive copying of xyz objects |
|
116 |
xyzs_cl=[] |
|
117 |
for atom_cl in self.atoms_cluster: |
|
118 |
xyzs_cl.append(atom_cl.get_position()) |
|
119 |
xyzs_sys=[] |
|
120 |
for atom_sys in self.atoms_system: |
|
121 |
xyzs_sys.append(atom_sys.get_position()) |
|
122 |
# FIXME: mapping does not work when cluster atoms are outside of the box |
|
123 |
# set the standard link atom |
|
124 |
if linkAtom is None: |
|
125 |
linkAtom ='H' |
|
126 |
# number of atoms in the cluster and the system |
|
127 |
nat_cl=len(self.atoms_cluster) |
|
128 |
nat_sys=len(self.atoms_system) |
|
129 |
# system has pbc? |
|
130 |
pbc = self.get_pbc() |
|
131 |
# set the bond table |
|
132 |
bonds = [] |
|
133 |
# set the 27 cell_vec, starting with the (0,0,0) vector for the unit cell |
|
134 |
cells_L = [(0.0, 0.0, 0.0)] |
|
135 |
# get the cell vectors |
|
136 |
cell = self.get_cell() |
|
137 |
# TODO: check 0D, 1D, 2D, 3D |
|
138 |
if False: |
|
139 |
for ix in xrange(-1, 2): |
|
140 |
for iy in xrange(-1, 2): |
|
141 |
for iz in xrange(-1, 2): |
|
142 |
if ix == 0 and iy == 0 and iz == 0: |
|
143 |
continue |
|
144 |
|
|
145 |
cells_L.append(np.dot([ix, iy, iz], cell)) |
|
146 |
# save the radius of system atoms |
|
147 |
rs_sys = [] |
|
148 |
for atom in self.atoms_system: |
|
149 |
rs_sys.append(covalent_radii[atom.get_atomic_number()]) |
|
150 |
# sum over cluster atoms (iat_cl) |
|
151 |
for iat_cl in xrange(nat_cl): |
|
152 |
# get the cluster atom |
|
153 |
atom_cl=self.atoms_cluster[iat_cl] |
|
154 |
# ignore link atoms |
|
155 |
if atom_cl.get_tag() == 50: |
|
156 |
continue |
|
157 |
# xyz coordinates and covalent radius of the cluster atom iat_cl |
|
158 |
xyz_cl = xyzs_cl[iat_cl] |
|
159 |
r_cl = covalent_radii[atom_cl.get_atomic_number()] |
|
160 |
|
|
161 |
# sum over system atoms (iat_sys) |
|
162 |
for iat_sys in xrange(nat_sys): |
|
163 |
# avoid cluster atoms |
|
164 |
if self.atoms_system[iat_sys].get_tag()==10: |
|
165 |
continue |
|
166 |
# sum over all cell_L |
|
167 |
for cell_L in cells_L: |
|
168 |
# xyz coordinates and covalent radius of the system atom iat_sys |
|
169 |
xyz_sys = xyzs_sys[iat_sys]+cell_L |
|
170 |
# go only in distance self.d around the cluster |
|
171 |
lcont = True |
|
172 |
for i in xrange(3): |
|
173 |
if (xyz_sys[i] < self.xyz_cl_min[i] or |
|
174 |
xyz_sys[i] > self.xyz_cl_max[i]): |
|
175 |
lcont = False |
|
176 |
break |
|
177 |
if not lcont: |
|
178 |
continue |
|
179 |
# xyz coordinates and covalent radius of the system atom iat_sys |
|
180 |
r_sys = rs_sys[iat_sys] |
|
181 |
# diff vector |
|
182 |
xyz_diff = xyz_sys - xyz_cl |
|
183 |
# distance between the atoms |
|
184 |
r = np.sqrt(np.dot(xyz_diff, xyz_diff)) |
|
185 |
# ratio of the distance to the sum of covalent radius |
|
186 |
f = r / (r_cl + r_sys) |
|
187 |
if debug: |
|
188 |
print "Covalent radii = ",r_cl, r_sys |
|
189 |
print "Distance ", f |
|
190 |
print "tol = ",(1+tol/100.),(1-tol/100.),(1-2*tol/100.) |
|
191 |
if f <= (1+tol/100.) and f >= (1-2*tol/100.): |
|
192 |
s = cell_L, iat_cl, iat_sys, r_cl |
|
193 |
bonds.append(s) |
|
194 |
break |
|
195 |
if f <= (1-2*tol/100.): |
|
196 |
raise RuntimeError("QMX: The cluster atom", iat_cl, " and the system atom", iat_sys, "came too close") |
|
197 |
|
|
198 |
r_h = covalent_radii[atomic_numbers[linkAtom]] |
|
199 |
for bond in bonds: |
|
200 |
cell_L, iat_cl, iat_sys, r_cl = bond |
|
201 |
# assign the tags for the border atoms |
|
202 |
atom_sys.set_tag(1) |
|
203 |
atom_cl.set_tag(11) |
|
204 |
#difference vector for the link atom, scaling |
|
205 |
xyz_diff = xyzs_sys[iat_sys] + cell_L - xyzs_cl[iat_cl] |
|
206 |
r = (r_cl + r_h) |
|
207 |
xyz_diff *= r / np.sqrt(np.dot(xyz_diff, xyz_diff)) |
|
208 |
# determine position of the link atom |
|
209 |
xyz_diff += xyzs_cl[iat_cl] |
|
210 |
# create link atom |
|
211 |
atom = Atom(symbol=linkAtom, position=xyz_diff, tag=50) |
|
212 |
# add atom to cluster |
|
213 |
self.atoms_cluster.append(atom) |
|
214 |
# add atom to the linkatoms |
|
215 |
s = cell_L, iat_cl, iat_sys, r, len(self.atoms_cluster)-1 |
|
216 |
self.linkatoms.append(s) |
|
217 |
return |
|
218 |
|
|
219 |
def set_positions(self, positions_new): |
|
220 |
# number of atoms |
|
221 |
nat_sys=len(self.atoms_system) |
|
222 |
# go over all pairs of atoms |
|
223 |
for iat_sys in xrange(nat_sys): |
|
224 |
xyz = positions_new[iat_sys] |
|
225 |
iat_cl = self.atom_map_sys_cl[iat_sys] |
|
226 |
self.atoms_system[iat_sys].set_position(xyz) |
|
227 |
if iat_cl > -1: |
|
228 |
self.atoms_cluster[iat_cl].set_position(xyz) |
|
229 |
|
|
230 |
for cell_L, iat_cl, iat_sys, r, iat in self.linkatoms: |
|
231 |
# determine position of the link atom |
|
232 |
xyz_cl = self.atoms_cluster[iat_cl].get_position() |
|
233 |
xyz = self.atoms_system[iat_sys].get_position() - xyz_cl + cell_L |
|
234 |
xyz *= r / np.sqrt(np.dot(xyz, xyz)) |
|
235 |
xyz += xyz_cl |
|
236 |
# update xyz coordinates of the cluster |
|
237 |
self.atoms_cluster[iat].set_position(xyz) |
|
238 |
|
|
239 |
def __getitem__(self, i): |
|
240 |
return self.atoms_system.__getitem__(i) |
|
241 |
|
|
242 |
def get_positions(self): |
|
243 |
return self.atoms_system.get_positions() |
|
244 |
|
|
245 |
def __add__(self, other): |
|
246 |
return self.atoms_system.__add__(other) |
|
247 |
|
|
248 |
def __delitem__(self, i): |
|
249 |
return self.atoms_system.__delitem__(i) |
|
250 |
|
|
251 |
def __len__(self): |
|
252 |
return self.atoms_system.__len__() |
ase/atoms.py (revision 2) | ||
---|---|---|
285 | 285 |
"""Add new array. |
286 | 286 |
|
287 | 287 |
If *shape* is not *None*, the shape of *a* will be checked.""" |
288 |
|
|
289 | 288 |
if dtype is not None: |
290 | 289 |
a = np.array(a, dtype) |
291 | 290 |
else: |
... | ... | |
311 | 310 |
|
312 | 311 |
Returns a copy unless the optional argument copy is false. |
313 | 312 |
""" |
313 |
|
|
314 | 314 |
if copy: |
315 | 315 |
return self.arrays[name].copy() |
316 | 316 |
else: |
ase/calculators/__init__.py (revision 2) | ||
---|---|---|
14 | 14 |
from ase.calculators.dftb import Dftb |
15 | 15 |
from ase.calculators.singlepoint import SinglePointCalculator |
16 | 16 |
from ase.calculators.test import numeric_force, numeric_forces, TestPotential |
17 |
from ase.calculators.qmx import Qmx |
|
17 | 18 |
|
18 | 19 |
if _deprecate_things_from_ase_module: |
19 | 20 |
from ase.utils.deprecate import Deprecate |
20 | 21 |
_locals = locals() |
21 | 22 |
for name in ['LennardJones', 'EMT', 'Siesta', 'Dacapo', 'Vasp', |
22 |
'Aims', 'AimsCube', 'Turbomole', 'Exciting', 'Dftb', |
|
23 |
'Aims', 'AimsCube', 'Turbomole', 'Exciting', 'Dftb', 'Qmx',
|
|
23 | 24 |
'SinglePointCalculator', 'numeric_force', 'numeric_forces', |
24 | 25 |
'TestPotential']: |
25 | 26 |
obj = _locals[name] |
ase/calculators/qmx.py (revision 2) | ||
---|---|---|
1 |
""" This is a QM:MM embedded system for ASE |
|
2 |
|
|
3 |
torsten.kerber@ens-lyon.fr |
|
4 |
""" |
|
5 |
|
|
6 |
import ase |
|
7 |
import ase.atoms |
|
8 |
import numpy as np |
|
9 |
from general import Calculator |
|
10 |
from ase.embed import Embed |
|
11 |
|
|
12 |
import sys, os |
|
13 |
|
|
14 |
class Qmx(Calculator): |
|
15 |
def __init__(self, calculator_low, calculator_high): |
|
16 |
self.string_params = {} |
|
17 |
|
|
18 |
self.forces=np.zeros((2,2)) |
|
19 |
self._constraints=None |
|
20 |
|
|
21 |
self.calculator_low = calculator_low |
|
22 |
self.calculator_high = calculator_high |
|
23 |
|
|
24 |
def get_energy_subsystem(self, path, calculator, atoms, force_consistent): |
|
25 |
os.chdir(path) |
|
26 |
calculator.set_atoms(atoms) |
|
27 |
energy = calculator.get_potential_energy(atoms) |
|
28 |
os.chdir("..") |
|
29 |
return energy |
|
30 |
|
|
31 |
def get_forces_subsystem(self, path, calculator, atoms): |
|
32 |
os.chdir(path) |
|
33 |
calculator.set_atoms(atoms) |
|
34 |
forces = calculator.get_forces(atoms) |
|
35 |
os.chdir("..") |
|
36 |
return forces |
|
37 |
|
|
38 |
|
|
39 |
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 |
e_cl_hi = self.get_energy_subsystem("cluster.high-level", self.calculator_high, embed.get_cluster(), force_consistent) |
|
44 |
# calculate energies |
|
45 |
energy = e_sys_lo - e_cl_lo + e_cl_hi |
|
46 |
print "%20s=%15s - %15s + %15s" %("E(C:S)", "E(S-MM)", "E(C-MM)", "E(C-QM)") |
|
47 |
print "%20f=%15f - %15f + %15f" %(energy, e_sys_lo, e_cl_lo, e_cl_hi) |
|
48 |
if force_consistent: |
|
49 |
self.energy_free = energy |
|
50 |
return self.energy_free |
|
51 |
else: |
|
52 |
self.energy_zero = energy |
|
53 |
return self.energy_zero |
|
54 |
|
|
55 |
def get_forces(self, embed): |
|
56 |
atom_map_sys_cl = embed.atom_map_sys_cl |
|
57 |
# 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()) |
|
60 |
f_cl_hi = self.get_forces_subsystem("cluster.high-level", self.calculator_high, embed.get_cluster()) |
|
61 |
# forces correction for the atoms |
|
62 |
f_cl = f_cl_hi - f_cl_lo |
|
63 |
#number of atoms |
|
64 |
nat_sys = len(embed) |
|
65 |
# lo-sys + (hi-lo) |
|
66 |
for iat_sys in xrange(nat_sys): |
|
67 |
iat_cl = atom_map_sys_cl[iat_sys] |
|
68 |
if iat_cl > -1: |
|
69 |
f_sys_lo[iat_sys] += f_cl[iat_cl] |
|
70 |
|
|
71 |
# correct gradients |
|
72 |
# 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: |
|
74 |
# 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 |
|
76 |
|
|
77 |
# calculate the bond lenght and the factor f |
|
78 |
rbond = np.sqrt(np.dot(xyz, xyz)) |
|
79 |
f = r / rbond |
|
80 |
#normalize xyz |
|
81 |
xyz /= rbond |
|
82 |
|
|
83 |
# 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 |
for idir in xrange(3): |
|
89 |
# correct the atom in the system |
|
90 |
f_sys_lo[iat_sys][idir] += f*fH[idir] - f*fs*xyz[idir] |
|
91 |
# correct the atom in the cluster |
|
92 |
f_sys_lo[iat_cl][idir] += (1-f)*fH[idir] + f*fs*xyz[idir] |
|
93 |
return f_sys_lo |
|
94 |
|
|
95 |
def set_atoms(self, atoms): |
|
96 |
return |
|
97 |
|
|
98 |
|
|
99 |
|
ase/calculators/turbomole.py (revision 2) | ||
---|---|---|
9 | 9 |
from ase.data import chemical_symbols |
10 | 10 |
from ase.units import Hartree, Bohr |
11 | 11 |
from ase.io.turbomole import write_turbomole |
12 |
from general import Calculator |
|
12 | 13 |
|
13 | 14 |
import numpy as np |
14 | 15 |
|
15 |
class Turbomole: |
|
16 |
class Turbomole(Calculator):
|
|
16 | 17 |
"""Class for doing Turbomole calculations. |
17 | 18 |
""" |
18 | 19 |
def __init__(self, label='turbomole'): |
ase/calculators/vasp.py (revision 2) | ||
---|---|---|
149 | 149 |
] |
150 | 150 |
|
151 | 151 |
class Vasp(Calculator): |
152 |
def __init__(self, restart=None, output_template='vasp', track_output=False, |
|
152 |
def __init__(self, restart=None, output_template='vasp', track_output=False, write_input = True,
|
|
153 | 153 |
**kwargs): |
154 |
self.bool_write_input = write_input |
|
154 | 155 |
self.name = 'Vasp' |
155 | 156 |
self.float_params = {} |
156 | 157 |
self.exp_params = {} |
... | ... | |
358 | 359 |
from ase.io.vasp import write_vasp |
359 | 360 |
self.initialize(atoms) |
360 | 361 |
write_vasp('POSCAR', self.atoms_sorted, symbol_count = self.symbol_count) |
361 |
self.write_incar(atoms) |
|
362 |
self.write_potcar() |
|
363 |
self.write_kpoints() |
|
362 |
if self.bool_write_input: |
|
363 |
self.write_incar(atoms) |
|
364 |
self.write_potcar() |
|
365 |
self.write_kpoints() |
|
364 | 366 |
self.write_sort_file() |
365 | 367 |
|
366 | 368 |
# Execute VASP |
ase/__init__.py (revision 2) | ||
---|---|---|
6 | 6 |
|
7 | 7 |
from ase.atom import Atom |
8 | 8 |
from ase.atoms import Atoms |
9 |
from ase.embed import Embed |
|
9 | 10 |
|
10 | 11 |
_deprecate_things_from_ase_module = True |
11 | 12 |
|
Formats disponibles : Unified diff