Révision 3

ase/optimize/optimize.py (revision 3)
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/embed.py (revision 3)
9 9
        super(Embed, self).__init__()
10 10
        # define the atom map
11 11
        self.atom_map_sys_cl = []
12
        self.atom_map_cl_sys = []
12 13
        self.linkatoms = []
13 14
        # cluster dimensions
14 15
        self.xyz_cl_min = None
15 16
        self.xyz_cl_max = None
16 17
        # set the search radius for link atoms
17
        self.d = 10        
18
        self.d = 10
18 19
        # define the systems for calculations
19 20
        self.set_system(system)
20 21
        self.set_cluster(cluster)
21 22
        #
22 23
        self.set_cell([10, 10, 10])
23 24
        return
24
                
25
    #--- set the cluster ---        
25

  
26
    #--- set the cluster ---
26 27
    def set_cluster(self, atoms):
27 28
        import copy
28 29
        # set the min/max cluster dimensions
......
38 39
                    self.xyz_cl_min[i] = xyz[i]
39 40
                if xyz[i] > self.xyz_cl_max[i]:
40 41
                    self.xyz_cl_max[i] = xyz[i]
41
                
42

  
42 43
        # add self.d around min/max cluster dimensions
43 44
        self.xyz_cl_min -= [self.d, self.d, self.d]
44
        self.xyz_cl_max += [self.d, self.d, self.d]       
45
        self.xyz_cl_max += [self.d, self.d, self.d]
45 46
        # set the cluster for low and high level calculation
46 47
        self.atoms_cluster = atoms
47 48
        return
48 49

  
49 50
    #--- set the system ---
50 51
    def set_system(self, atoms):
51
        self.atoms_system = atoms        
52
        self.atoms_system = atoms
52 53
        # assign the label "Cluster (10)" in atom.TAG
53 54
        for atom in atoms:
54 55
            atom.set_tag(0)
......
60 61
                dx = r
61 62
        self.d = dx * 2.1
62 63
        return
63
        
64

  
64 65
    #--- return cluster ---
65 66
    def get_cluster(self):
66 67
        return self.atoms_cluster
67
        
68

  
68 69
    def get_system(self):
69 70
        return self.atoms_system
70
        
71

  
71 72
    #--- Embedding ---
72 73
    def embed(self):
73 74
        # is the cluster and the host system definied ?
......
87 88
        xyzs_sys=[]
88 89
        for atom_sys in self.atoms_system:
89 90
            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                
91

  
92
        self.atom_map_sys_cl = np.zeros(len(self.atoms_system), int)
93
        self.atom_map_cl_sys = np.zeros(len(self.atoms_cluster), int)
94
        # loop over cluster atoms atom_sys
93 95
        for iat_sys in xrange(len(self.atoms_system)):
94 96
            # get the coordinates of the system atom atom_sys
95 97
            xyz_sys = xyzs_sys[iat_sys]
......
104 106
                    # set tag (CLUSTER+HOST: 10) to atom_sys
105 107
                    self.atoms_system[iat_sys].set_tag(10)
106 108
                    # map the atom in the atom list
107
                    self.atom_map_sys_cl[iat_sys]=iat_cl
109
                    self.atom_map_sys_cl[iat_sys] = iat_cl
110
                    self.atom_map_cl_sys[iat_cl] = iat_sys
108 111
                    # atom has been identified
109 112
                    bSysOnly = False
110 113
                    break
......
118 121
            xyzs_cl.append(atom_cl.get_position())
119 122
        xyzs_sys=[]
120 123
        for atom_sys in self.atoms_system:
121
            xyzs_sys.append(atom_sys.get_position())        
124
            xyzs_sys.append(atom_sys.get_position())
122 125
        # FIXME: mapping does not work when cluster atoms are outside of the box
123 126
        # set the standard link atom
124 127
        if linkAtom is None:
......
127 130
        nat_cl=len(self.atoms_cluster)
128 131
        nat_sys=len(self.atoms_system)
129 132
        # system has pbc?
130
        pbc = self.get_pbc()        
133
        pbc = self.get_pbc()
131 134
        # set the bond table
132 135
        bonds = []
133 136
        # set the 27 cell_vec, starting with the (0,0,0) vector for the unit cell
......
157 160
            # xyz coordinates and covalent radius of the cluster atom iat_cl
158 161
            xyz_cl = xyzs_cl[iat_cl]
159 162
            r_cl = covalent_radii[atom_cl.get_atomic_number()]
160
            
163

  
161 164
            # sum over system atoms (iat_sys)
162 165
            for iat_sys in xrange(nat_sys):
163 166
                # avoid cluster atoms
......
170 173
                    # go only in distance self.d around the cluster
171 174
                    lcont = True
172 175
                    for i in xrange(3):
173
                        if (xyz_sys[i] < self.xyz_cl_min[i] or 
176
                        if (xyz_sys[i] < self.xyz_cl_min[i] or
174 177
                            xyz_sys[i] > self.xyz_cl_max[i]):
175 178
                            lcont = False
176 179
                            break
......
189 192
                        print "Distance ", f
190 193
                        print "tol = ",(1+tol/100.),(1-tol/100.),(1-2*tol/100.)
191 194
                    if f <= (1+tol/100.) and f >= (1-2*tol/100.):
192
                        s = cell_L, iat_cl, iat_sys, r_cl
195
                        s = cell_L, self.atom_map_cl_sys[iat_cl], iat_sys, r_cl
193 196
                        bonds.append(s)
194 197
                        break
195 198
                    if f <= (1-2*tol/100.):
196 199
                        raise RuntimeError("QMX: The cluster atom", iat_cl, " and the system atom", iat_sys, "came too close")
197
        
200

  
198 201
        r_h = covalent_radii[atomic_numbers[linkAtom]]
199 202
        for bond in bonds:
200
            cell_L, iat_cl, iat_sys, r_cl = bond
203
            cell_L, iat_cl_sys, iat_sys, r_cl = bond
201 204
            # assign the tags for the border atoms
202 205
            atom_sys.set_tag(1)
203 206
            atom_cl.set_tag(11)
204 207
            #difference vector for the link atom, scaling
205
            xyz_diff = xyzs_sys[iat_sys] + cell_L - xyzs_cl[iat_cl]
208
            xyz_diff = xyzs_sys[iat_sys] + cell_L - xyzs_sys[iat_cl_sys]
206 209
            r = (r_cl + r_h)
207 210
            xyz_diff *=  r / np.sqrt(np.dot(xyz_diff, xyz_diff))
208 211
            # determine position of the link atom
209
            xyz_diff += xyzs_cl[iat_cl]
212
            xyz_diff += xyzs_sys[iat_cl_sys]
210 213
            # create link atom
211 214
            atom = Atom(symbol=linkAtom, position=xyz_diff, tag=50)
212 215
            # add atom to cluster
213 216
            self.atoms_cluster.append(atom)
214 217
            # add atom to the linkatoms
215
            s = cell_L, iat_cl, iat_sys, r, len(self.atoms_cluster)-1
218
            s = cell_L, iat_cl_sys, iat_sys, r, len(self.atoms_cluster)-1
216 219
            self.linkatoms.append(s)
217 220
        return
218
        
221

  
219 222
    def set_positions(self, positions_new):
220 223
        # number of atoms
221 224
        nat_sys=len(self.atoms_system)
......
226 229
            self.atoms_system[iat_sys].set_position(xyz)
227 230
            if iat_cl > -1:
228 231
                self.atoms_cluster[iat_cl].set_position(xyz)
229
                
230
        for cell_L, iat_cl, iat_sys, r, iat in self.linkatoms:
232

  
233
        for cell_L, iat_cl_sys, iat_sys, r, iat in self.linkatoms:
231 234
            # determine position of the link atom
232
            xyz_cl = self.atoms_cluster[iat_cl].get_position()
235
            xyz_cl = self.atoms_system[iat_cl_sys].get_position()
233 236
            xyz = self.atoms_system[iat_sys].get_position() - xyz_cl + cell_L
234 237
            xyz *= r / np.sqrt(np.dot(xyz, xyz))
235 238
            xyz += xyz_cl
236 239
            # update xyz coordinates of the cluster
237 240
            self.atoms_cluster[iat].set_position(xyz)
238
            
241

  
239 242
    def __getitem__(self, i):
240 243
        return self.atoms_system.__getitem__(i)
241 244

  
242 245
    def get_positions(self):
243 246
        return self.atoms_system.get_positions()
244
        
247

  
245 248
    def __add__(self, other):
246 249
        return self.atoms_system.__add__(other)
247
        
250

  
248 251
    def __delitem__(self, i):
249 252
        return self.atoms_system.__delitem__(i)
250
    
253

  
251 254
    def __len__(self):
252 255
        return self.atoms_system.__len__()
256
        
257
    def get_chemical_symbols(self, reduce=False):
258
        return self.atoms_system.get_chemical_symbols(reduce)
ase/atoms.py (revision 3)
584 584
    def copy(self):
585 585
        """Return a copy."""
586 586
        import copy
587
        atoms = self.__class__(cell=self._cell, pbc=self._pbc)
587
        atoms = Atoms(cell=self._cell, pbc=self._pbc)
588 588

  
589 589
        atoms.arrays = {}
590 590
        for name, a in self.arrays.items():
ase/calculators/lammps.py (revision 3)
1
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2
<html xmlns="http://www.w3.org/1999/xhtml">
3
  
4
  
5

  
6

  
7
  <head>
8
    <title>
9
      lammps.py in trunk/ase/calculators
10
     – ase
11
    </title>
12
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
13
        <link rel="search" href="/projects/ase/search" />
14
        <link rel="help" href="/projects/ase/wiki/TracGuide" />
15
        <link rel="alternate" href="/projects/ase/browser/trunk/ase/calculators/lammps.py?format=txt" type="text/plain" title="Plain Text" /><link rel="alternate" href="/projects/ase/export/2073/trunk/ase/calculators/lammps.py" type="text/x-python; charset=iso-8859-15" title="Original Format" />
16
        <link rel="start" href="/projects/ase/wiki" />
17
        <link rel="stylesheet" href="/projects/ase/chrome/common/css/trac.css" type="text/css" /><link rel="stylesheet" href="/projects/ase/chrome/common/css/code.css" type="text/css" /><link rel="stylesheet" href="/projects/ase/chrome/common/css/browser.css" type="text/css" />
18
        <link rel="prev" href="/projects/ase/browser/trunk/ase/calculators/lammps.py?rev=2022" title="Revision 2022" />
19
        <link rel="shortcut icon" href="/projects/ase/chrome/common/trac.ico" type="image/x-icon" />
20
        <link rel="icon" href="/projects/ase/chrome/common/trac.ico" type="image/x-icon" />
21
      <link type="application/opensearchdescription+xml" rel="search" href="/projects/ase/search/opensearch" title="Search ase" />
22
    <script type="text/javascript" src="/projects/ase/chrome/common/js/jquery.js"></script><script type="text/javascript" src="/projects/ase/chrome/common/js/babel.js"></script><script type="text/javascript" src="/projects/ase/chrome/common/js/trac.js"></script><script type="text/javascript" src="/projects/ase/chrome/common/js/search.js"></script>
23
    <!--[if lt IE 7]>
24
    <script type="text/javascript" src="/projects/ase/chrome/common/js/ie_pre7_hacks.js"></script>
25
    <![endif]-->
26
    <script type="text/javascript" src="/projects/ase/chrome/common/js/folding.js"></script><script type="text/javascript">
27
      jQuery(document).ready(function($) {
28
        $(".trac-toggledeleted").show().click(function() {
29
                  $(this).siblings().find(".trac-deleted").toggle();
30
                  return false;
31
        }).click();
32
        $("#jumploc input").hide();
33
        $("#jumploc select").change(function () {
34
          this.parentNode.parentNode.submit();
35
        });
36
          $('#preview table.code').enableCollapsibleColumns($('#preview table.code thead th.content'));
37
      });
38
    </script>
39
  </head>
40
  <body>
41
    <div id="banner">
42
      <div id="header">
43
        <a id="logo" href="https://trac.fysik.dtu.dk/projects/ase"><img src="https://svn.fysik.dtu.dk/projects/ase/trunk/doc/_static/ase_trac.png" alt="" /></a>
44
      </div>
45
      <form id="search" action="/projects/ase/search" method="get">
46
        <div>
47
          <label for="proj-search">Search:</label>
48
          <input type="text" id="proj-search" name="q" size="18" value="" />
49
          <input type="submit" value="Search" />
50
        </div>
51
      </form>
52
      <div id="metanav" class="nav">
53
    <ul>
54
      <li class="first"><a href="/projects/ase/login">Login</a></li><li><a href="/projects/ase/wiki/TracGuide">Help/Guide</a></li><li><a href="/projects/ase/about">About Trac</a></li><li class="last"><a href="/projects/ase/prefs">Preferences</a></li>
55
    </ul>
56
  </div>
57
    </div>
58
    <div id="mainnav" class="nav">
59
    <ul>
60
      <li class="first"><a href="/projects/ase/wiki">Wiki</a></li><li><a href="/projects/ase/timeline">Timeline</a></li><li><a href="/projects/ase/roadmap">Roadmap</a></li><li class="active"><a href="/projects/ase/browser">Browse Source</a></li><li><a href="/projects/ase/report">View Tickets</a></li><li class="last"><a href="/projects/ase/search">Search</a></li>
61
    </ul>
62
  </div>
63
    <div id="main">
64
      <div id="ctxtnav" class="nav">
65
        <h2>Context Navigation</h2>
66
          <ul>
67
              <li class="first"><span>&larr; <a class="prev" href="/projects/ase/browser/trunk/ase/calculators/lammps.py?rev=2022" title="Revision 2022">Previous Revision</a></span></li><li><span class="missing">Next Revision &rarr;</span></li><li><a href="/projects/ase/browser/trunk/ase/calculators/lammps.py?annotate=blame&amp;rev=2023" title="Annotate each line with the last changed revision (this can be time consuming...)">Annotate</a></li><li class="last"><a href="/projects/ase/log/trunk/ase/calculators/lammps.py">Revision Log</a></li>
68
          </ul>
69
        <hr />
70
      </div>
71
    <div id="content" class="browser">
72
          <h1>
73
<a class="pathentry first" href="/projects/ase/browser?order=name" title="Go to repository root">source:</a>
74
<a class="pathentry" href="/projects/ase/browser/trunk?order=name" title="View trunk">trunk</a><span class="pathentry sep">/</span><a class="pathentry" href="/projects/ase/browser/trunk/ase?order=name" title="View ase">ase</a><span class="pathentry sep">/</span><a class="pathentry" href="/projects/ase/browser/trunk/ase/calculators?order=name" title="View calculators">calculators</a><span class="pathentry sep">/</span><a class="pathentry" href="/projects/ase/browser/trunk/ase/calculators/lammps.py?order=name" title="View lammps.py">lammps.py</a>
75
<span class="pathentry sep">@</span>
76
  <a class="pathentry" href="/projects/ase/changeset/2023" title="View changeset 2023">2023</a>
77
<br style="clear: both" />
78
</h1>
79
        <div id="jumprev">
80
          <form action="" method="get">
81
            <div>
82
              <label for="rev">
83
                View revision:</label>
84
              <input type="text" id="rev" name="rev" size="6" />
85
            </div>
86
          </form>
87
        </div>
88
        <div id="jumploc">
89
          <form action="" method="get">
90
            <div class="buttons">
91
              <label for="preselected">Visit:</label>
92
              <select id="preselected" name="preselected">
93
                <option selected="selected"></option>
94
                <optgroup label="branches">
95
                  <option value="/projects/ase/browser/trunk">trunk</option><option value="/projects/ase/browser/branches/dacapo">branches/dacapo</option><option value="/projects/ase/browser/branches/elements">branches/elements</option><option value="/projects/ase/browser/branches/usertags">branches/usertags</option>
96
                </optgroup><optgroup label="tags">
97
                  <option value="/projects/ase/browser/tags/3.0.0?rev=657">tags/3.0.0</option><option value="/projects/ase/browser/tags/3.1.0?rev=846">tags/3.1.0</option><option value="/projects/ase/browser/tags/3.2.0?rev=1121">tags/3.2.0</option><option value="/projects/ase/browser/tags/3.3.0?rev=1376">tags/3.3.0</option><option value="/projects/ase/browser/tags/3.3.1?rev=1389">tags/3.3.1</option><option value="/projects/ase/browser/tags/3.4.0?rev=1574">tags/3.4.0</option><option value="/projects/ase/browser/tags/3.4.1?rev=1765">tags/3.4.1</option>
98
                </optgroup>
99
              </select>
100
              <input type="submit" value="Go!" title="Jump to the chosen preselected path" />
101
            </div>
102
          </form>
103
        </div>
104
      <table id="info" summary="Revision info">
105
        <tr>
106
          <th scope="col">Revision <a href="/projects/ase/changeset/2023">2023</a>,
107
            <span title="23511 bytes">23.0 KB</span>
108
            checked in by jensj, <a class="timeline" href="/projects/ase/timeline?from=2011-02-23T08%3A39%3A36%2B01%3A00&amp;precision=second" title="2011-02-23T08:39:36+01:00 in Timeline">4 weeks</a> ago
109
            (<a href="/projects/ase/changeset/2023/trunk/ase/calculators/lammps.py">diff</a>)</th>
110
        </tr>
111
        <tr>
112
          <td class="message searchable">
113
              <p>
114
Python 2.4 compatibility.<br />
115
</p>
116
          </td>
117
        </tr>
118
      </table>
119
      <div id="preview" class="searchable">
120
        
121
  <table class="code"><thead><tr><th class="lineno" title="Line numbers">Line</th><th class="content"> </th></tr></thead><tbody><tr><th id="L1"><a href="#L1">1</a></th><td>#!/usr//bin/env python</td></tr><tr><th id="L2"><a href="#L2">2</a></th><td></td></tr><tr><th id="L3"><a href="#L3">3</a></th><td># lammps.py (2011/02/22)</td></tr><tr><th id="L4"><a href="#L4">4</a></th><td># An ASE calculator for the LAMMPS classical MD code available from</td></tr><tr><th id="L5"><a href="#L5">5</a></th><td>#       http://lammps.sandia.gov/</td></tr><tr><th id="L6"><a href="#L6">6</a></th><td># The environment variable LAMMPS_COMMAND must be defined to point to the LAMMPS binary.</td></tr><tr><th id="L7"><a href="#L7">7</a></th><td>#</td></tr><tr><th id="L8"><a href="#L8">8</a></th><td># Copyright (C) 2009 - 2011 Joerg Meyer, joerg.meyer@ch.tum.de</td></tr><tr><th id="L9"><a href="#L9">9</a></th><td>#</td></tr><tr><th id="L10"><a href="#L10">10</a></th><td># This library is free software; you can redistribute it and/or</td></tr><tr><th id="L11"><a href="#L11">11</a></th><td># modify it under the terms of the GNU Lesser General Public</td></tr><tr><th id="L12"><a href="#L12">12</a></th><td># License as published by the Free Software Foundation; either</td></tr><tr><th id="L13"><a href="#L13">13</a></th><td># version 2.1 of the License, or (at your option) any later version.</td></tr><tr><th id="L14"><a href="#L14">14</a></th><td>#</td></tr><tr><th id="L15"><a href="#L15">15</a></th><td># This library is distributed in the hope that it will be useful,</td></tr><tr><th id="L16"><a href="#L16">16</a></th><td># but WITHOUT ANY WARRANTY; without even the implied warranty of</td></tr><tr><th id="L17"><a href="#L17">17</a></th><td># MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU</td></tr><tr><th id="L18"><a href="#L18">18</a></th><td># Lesser General Public License for more details.</td></tr><tr><th id="L19"><a href="#L19">19</a></th><td>#</td></tr><tr><th id="L20"><a href="#L20">20</a></th><td># You should have received a copy of the GNU Lesser General Public</td></tr><tr><th id="L21"><a href="#L21">21</a></th><td># License along with this file; if not, write to the Free Software</td></tr><tr><th id="L22"><a href="#L22">22</a></th><td># Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA</td></tr><tr><th id="L23"><a href="#L23">23</a></th><td># or see &lt;http://www.gnu.org/licenses/&gt;.</td></tr><tr><th id="L24"><a href="#L24">24</a></th><td></td></tr><tr><th id="L25"><a href="#L25">25</a></th><td>import os</td></tr><tr><th id="L26"><a href="#L26">26</a></th><td>import shutil</td></tr><tr><th id="L27"><a href="#L27">27</a></th><td>import time</td></tr><tr><th id="L28"><a href="#L28">28</a></th><td>import math</td></tr><tr><th id="L29"><a href="#L29">29</a></th><td>import decimal as dec</td></tr><tr><th id="L30"><a href="#L30">30</a></th><td>import numpy as np</td></tr><tr><th id="L31"><a href="#L31">31</a></th><td>from ase import Atoms</td></tr><tr><th id="L32"><a href="#L32">32</a></th><td>from ase.parallel import paropen</td></tr><tr><th id="L33"><a href="#L33">33</a></th><td></td></tr><tr><th id="L34"><a href="#L34">34</a></th><td></td></tr><tr><th id="L35"><a href="#L35">35</a></th><td>class LAMMPS:</td></tr><tr><th id="L36"><a href="#L36">36</a></th><td></td></tr><tr><th id="L37"><a href="#L37">37</a></th><td>    def __init__(self, label="lammps", dir="LAMMPS", parameters={}, files=[], always_triclinic=False):</td></tr><tr><th id="L38"><a href="#L38">38</a></th><td>        self.label = label</td></tr><tr><th id="L39"><a href="#L39">39</a></th><td>        self.dir = dir</td></tr><tr><th id="L40"><a href="#L40">40</a></th><td>        self.parameters = parameters</td></tr><tr><th id="L41"><a href="#L41">41</a></th><td>        self.files = files</td></tr><tr><th id="L42"><a href="#L42">42</a></th><td>        self.always_triclinic = always_triclinic</td></tr><tr><th id="L43"><a href="#L43">43</a></th><td>        self.calls = 0</td></tr><tr><th id="L44"><a href="#L44">44</a></th><td>        self.potential_energy = None</td></tr><tr><th id="L45"><a href="#L45">45</a></th><td>        self.forces = None</td></tr><tr><th id="L46"><a href="#L46">46</a></th><td></td></tr><tr><th id="L47"><a href="#L47">47</a></th><td>        if os.path.isdir(self.dir):</td></tr><tr><th id="L48"><a href="#L48">48</a></th><td>            if (os.listdir(self.dir) == []):</td></tr><tr><th id="L49"><a href="#L49">49</a></th><td>                os.rmdir(self.dir)</td></tr><tr><th id="L50"><a href="#L50">50</a></th><td>            else:</td></tr><tr><th id="L51"><a href="#L51">51</a></th><td>                os.rename(self.dir, self.dir + ".bak-" + time.strftime("%Y%m%d-%H%M%S"))</td></tr><tr><th id="L52"><a href="#L52">52</a></th><td>        os.mkdir(self.dir, 0755)</td></tr><tr><th id="L53"><a href="#L53">53</a></th><td>        </td></tr><tr><th id="L54"><a href="#L54">54</a></th><td>        for f in files:</td></tr><tr><th id="L55"><a href="#L55">55</a></th><td>            shutil.copy(f, os.path.join(self.dir, f))</td></tr><tr><th id="L56"><a href="#L56">56</a></th><td></td></tr><tr><th id="L57"><a href="#L57">57</a></th><td>    def clean(self, force=False):</td></tr><tr><th id="L58"><a href="#L58">58</a></th><td>        if os.path.isdir(self.dir):</td></tr><tr><th id="L59"><a href="#L59">59</a></th><td>            files_in_dir = os.listdir(self.dir)</td></tr><tr><th id="L60"><a href="#L60">60</a></th><td>            files_copied = self.files</td></tr><tr><th id="L61"><a href="#L61">61</a></th><td>            if (len(files_in_dir) == 0):</td></tr><tr><th id="L62"><a href="#L62">62</a></th><td>                os.rmdir(self.dir)</td></tr><tr><th id="L63"><a href="#L63">63</a></th><td>            elif (set(files_in_dir).issubset(set(files_copied)) or force):</td></tr><tr><th id="L64"><a href="#L64">64</a></th><td>                shutil.rmtree(self.dir)</td></tr><tr><th id="L65"><a href="#L65">65</a></th><td></td></tr><tr><th id="L66"><a href="#L66">66</a></th><td>    def get_potential_energy(self, atoms):</td></tr><tr><th id="L67"><a href="#L67">67</a></th><td>        self.update(atoms)</td></tr><tr><th id="L68"><a href="#L68">68</a></th><td>        return self.potential_energy</td></tr><tr><th id="L69"><a href="#L69">69</a></th><td></td></tr><tr><th id="L70"><a href="#L70">70</a></th><td>    def get_forces(self, atoms):</td></tr><tr><th id="L71"><a href="#L71">71</a></th><td>        self.update(atoms)</td></tr><tr><th id="L72"><a href="#L72">72</a></th><td>        return self.forces.copy()</td></tr><tr><th id="L73"><a href="#L73">73</a></th><td></td></tr><tr><th id="L74"><a href="#L74">74</a></th><td>    def get_stress(self, atoms):</td></tr><tr><th id="L75"><a href="#L75">75</a></th><td>        raise NotImplementedError</td></tr><tr><th id="L76"><a href="#L76">76</a></th><td></td></tr><tr><th id="L77"><a href="#L77">77</a></th><td>    def update(self, atoms):</td></tr><tr><th id="L78"><a href="#L78">78</a></th><td>        # TODO: check if (re-)calculation is necessary</td></tr><tr><th id="L79"><a href="#L79">79</a></th><td>        self.calculate(atoms)</td></tr><tr><th id="L80"><a href="#L80">80</a></th><td></td></tr><tr><th id="L81"><a href="#L81">81</a></th><td>    def calculate(self, atoms):</td></tr><tr><th id="L82"><a href="#L82">82</a></th><td>        self.atoms = atoms.copy()</td></tr><tr><th id="L83"><a href="#L83">83</a></th><td>        self.run()</td></tr><tr><th id="L84"><a href="#L84">84</a></th><td></td></tr><tr><th id="L85"><a href="#L85">85</a></th><td>    def run(self):</td></tr><tr><th id="L86"><a href="#L86">86</a></th><td>        """Method which explicitely runs LAMMPS."""</td></tr><tr><th id="L87"><a href="#L87">87</a></th><td></td></tr><tr><th id="L88"><a href="#L88">88</a></th><td>        self.calls += 1</td></tr><tr><th id="L89"><a href="#L89">89</a></th><td></td></tr><tr><th id="L90"><a href="#L90">90</a></th><td>        # set LAMMPS command from environment variable</td></tr><tr><th id="L91"><a href="#L91">91</a></th><td>        if os.environ.has_key('LAMMPS_COMMAND'):</td></tr><tr><th id="L92"><a href="#L92">92</a></th><td>            lammps_command = os.path.abspath(os.environ['LAMMPS_COMMAND'])</td></tr><tr><th id="L93"><a href="#L93">93</a></th><td>        else:</td></tr><tr><th id="L94"><a href="#L94">94</a></th><td>            self.clean()</td></tr><tr><th id="L95"><a href="#L95">95</a></th><td>            raise RuntimeError('Please set LAMMPS_COMMAND environment variable')</td></tr><tr><th id="L96"><a href="#L96">96</a></th><td>        if os.environ.has_key('LAMMPS_OPTIONS'):</td></tr><tr><th id="L97"><a href="#L97">97</a></th><td>            lammps_options = os.environ['LAMMPS_OPTIONS']</td></tr><tr><th id="L98"><a href="#L98">98</a></th><td>        else:</td></tr><tr><th id="L99"><a href="#L99">99</a></th><td>            lammps_options = "-echo log -screen none"</td></tr><tr><th id="L100"><a href="#L100">100</a></th><td></td></tr><tr><th id="L101"><a href="#L101">101</a></th><td>        # change into subdirectory for LAMMPS calculations</td></tr><tr><th id="L102"><a href="#L102">102</a></th><td>        cwd = os.getcwd()</td></tr><tr><th id="L103"><a href="#L103">103</a></th><td>        os.chdir(self.dir)</td></tr><tr><th id="L104"><a href="#L104">104</a></th><td></td></tr><tr><th id="L105"><a href="#L105">105</a></th><td>        # setup file names for LAMMPS calculation</td></tr><tr><th id="L106"><a href="#L106">106</a></th><td>        label = "%s-%06d" % (self.label, self.calls)</td></tr><tr><th id="L107"><a href="#L107">107</a></th><td>        lammps_data = "data." + label</td></tr><tr><th id="L108"><a href="#L108">108</a></th><td>        lammps_in = "in." + label</td></tr><tr><th id="L109"><a href="#L109">109</a></th><td>        lammps_trj = label + ".lammpstrj"</td></tr><tr><th id="L110"><a href="#L110">110</a></th><td>        lammps_log = label + ".log"</td></tr><tr><th id="L111"><a href="#L111">111</a></th><td></td></tr><tr><th id="L112"><a href="#L112">112</a></th><td>        # write LAMMPS input files</td></tr><tr><th id="L113"><a href="#L113">113</a></th><td>        self.write_lammps_data(lammps_data=lammps_data)</td></tr><tr><th id="L114"><a href="#L114">114</a></th><td>        self.write_lammps_in(lammps_in=lammps_in, lammps_data=lammps_data, lammps_trj=lammps_trj, parameters=self.parameters)</td></tr><tr><th id="L115"><a href="#L115">115</a></th><td></td></tr><tr><th id="L116"><a href="#L116">116</a></th><td>        # run LAMMPS</td></tr><tr><th id="L117"><a href="#L117">117</a></th><td>        # TODO: check for successful completion (based on output files?!) of LAMMPS call...</td></tr><tr><th id="L118"><a href="#L118">118</a></th><td>        exitcode = os.system("%s %s -in %s -log %s" % (lammps_command, lammps_options, lammps_in, lammps_log))</td></tr><tr><th id="L119"><a href="#L119">119</a></th><td>        if exitcode != 0:</td></tr><tr><th id="L120"><a href="#L120">120</a></th><td>            cwd = os.getcwd()</td></tr><tr><th id="L121"><a href="#L121">121</a></th><td>            raise RuntimeError("LAMMPS exited in %s with exit code: %d.  " % (cwd,exitcode))</td></tr><tr><th id="L122"><a href="#L122">122</a></th><td></td></tr><tr><th id="L123"><a href="#L123">123</a></th><td>        # read LAMMPS output files</td></tr><tr><th id="L124"><a href="#L124">124</a></th><td>        self.read_lammps_log(lammps_log=lammps_log)</td></tr><tr><th id="L125"><a href="#L125">125</a></th><td>        self.read_lammps_trj(lammps_trj=lammps_trj)</td></tr><tr><th id="L126"><a href="#L126">126</a></th><td></td></tr><tr><th id="L127"><a href="#L127">127</a></th><td>        # change back to previous working directory</td></tr><tr><th id="L128"><a href="#L128">128</a></th><td>        os.chdir(cwd)</td></tr><tr><th id="L129"><a href="#L129">129</a></th><td></td></tr><tr><th id="L130"><a href="#L130">130</a></th><td>    def write_lammps_data(self, lammps_data=None):</td></tr><tr><th id="L131"><a href="#L131">131</a></th><td>        """Method which writes a LAMMPS data file with atomic structure."""</td></tr><tr><th id="L132"><a href="#L132">132</a></th><td>        if (lammps_data == None):</td></tr><tr><th id="L133"><a href="#L133">133</a></th><td>            lammps_data = "data." + self.label</td></tr><tr><th id="L134"><a href="#L134">134</a></th><td>        write_lammps(lammps_data, self.atoms, force_skew=self.always_triclinic)</td></tr><tr><th id="L135"><a href="#L135">135</a></th><td></td></tr><tr><th id="L136"><a href="#L136">136</a></th><td>    def write_lammps_in(self, lammps_in=None, lammps_data=None, lammps_trj=None, parameters={}):</td></tr><tr><th id="L137"><a href="#L137">137</a></th><td>        """Method which writes a LAMMPS in file with run parameters and settings."""</td></tr><tr><th id="L138"><a href="#L138">138</a></th><td>        if (lammps_in == None):</td></tr><tr><th id="L139"><a href="#L139">139</a></th><td>            lammps_in = "in." + self.label</td></tr><tr><th id="L140"><a href="#L140">140</a></th><td>        if (lammps_data == None):</td></tr><tr><th id="L141"><a href="#L141">141</a></th><td>            lammps_data = "data." + self.label</td></tr><tr><th id="L142"><a href="#L142">142</a></th><td>        if (lammps_trj == None):</td></tr><tr><th id="L143"><a href="#L143">143</a></th><td>            lammps_trj = self.label + ".lammpstrj"</td></tr><tr><th id="L144"><a href="#L144">144</a></th><td></td></tr><tr><th id="L145"><a href="#L145">145</a></th><td>        f = paropen(lammps_in, 'w')</td></tr><tr><th id="L146"><a href="#L146">146</a></th><td>        f.write("# " + f.name + " (written by ASE) \n")</td></tr><tr><th id="L147"><a href="#L147">147</a></th><td>        f.write("\n")</td></tr><tr><th id="L148"><a href="#L148">148</a></th><td></td></tr><tr><th id="L149"><a href="#L149">149</a></th><td>        f.write("### variables \n")</td></tr><tr><th id="L150"><a href="#L150">150</a></th><td>        f.write("variable data_file index \"%s\" \n" % lammps_data)</td></tr><tr><th id="L151"><a href="#L151">151</a></th><td>        f.write("variable dump_file index \"%s\" \n" % lammps_trj)</td></tr><tr><th id="L152"><a href="#L152">152</a></th><td>        f.write("\n\n")</td></tr><tr><th id="L153"><a href="#L153">153</a></th><td></td></tr><tr><th id="L154"><a href="#L154">154</a></th><td>        pbc = self.atoms.get_pbc()</td></tr><tr><th id="L155"><a href="#L155">155</a></th><td>        f.write("### simulation box \n")</td></tr><tr><th id="L156"><a href="#L156">156</a></th><td>        f.write("units metal \n")</td></tr><tr><th id="L157"><a href="#L157">157</a></th><td>        if ("boundary" in parameters):</td></tr><tr><th id="L158"><a href="#L158">158</a></th><td>            f.write("boundary %s \n" % parameters["boundary"])</td></tr><tr><th id="L159"><a href="#L159">159</a></th><td>        else:</td></tr><tr><th id="L160"><a href="#L160">160</a></th><td>            f.write("boundary %c %c %c \n" % tuple('sp'[x] for x in pbc))</td></tr><tr><th id="L161"><a href="#L161">161</a></th><td>        f.write("atom_modify sort 0 0.0 \n")</td></tr><tr><th id="L162"><a href="#L162">162</a></th><td>        for key in ("neighbor" ,"newton"):</td></tr><tr><th id="L163"><a href="#L163">163</a></th><td>            if key in parameters:</td></tr><tr><th id="L164"><a href="#L164">164</a></th><td>                f.write("%s %s \n" % (key, parameters[key]))</td></tr><tr><th id="L165"><a href="#L165">165</a></th><td>        f.write("\n")</td></tr><tr><th id="L166"><a href="#L166">166</a></th><td>        f.write("read_data ${data_file} \n")</td></tr><tr><th id="L167"><a href="#L167">167</a></th><td>        f.write("\n\n")</td></tr><tr><th id="L168"><a href="#L168">168</a></th><td></td></tr><tr><th id="L169"><a href="#L169">169</a></th><td>        f.write("### interactions \n")</td></tr><tr><th id="L170"><a href="#L170">170</a></th><td>        if ( ("pair_style" in parameters) and ("pair_coeff" in parameters) ):</td></tr><tr><th id="L171"><a href="#L171">171</a></th><td>            pair_style = parameters["pair_style"]</td></tr><tr><th id="L172"><a href="#L172">172</a></th><td>            f.write("pair_style %s \n" % pair_style)</td></tr><tr><th id="L173"><a href="#L173">173</a></th><td>            for pair_coeff in parameters["pair_coeff"]:</td></tr><tr><th id="L174"><a href="#L174">174</a></th><td>                f.write("pair_coeff %s \n" % pair_coeff)</td></tr><tr><th id="L175"><a href="#L175">175</a></th><td>            if "mass" in parameters:</td></tr><tr><th id="L176"><a href="#L176">176</a></th><td>                for mass in parameters["mass"]:</td></tr><tr><th id="L177"><a href="#L177">177</a></th><td>                    f.write("mass %s \n" % mass)</td></tr><tr><th id="L178"><a href="#L178">178</a></th><td>        else:</td></tr><tr><th id="L179"><a href="#L179">179</a></th><td>            # simple default parameters that should always make the LAMMPS calculation run</td></tr><tr><th id="L180"><a href="#L180">180</a></th><td>            #    pair_style     lj/cut 2.5</td></tr><tr><th id="L181"><a href="#L181">181</a></th><td>            #    pair_coeff     * * 1 1</td></tr><tr><th id="L182"><a href="#L182">182</a></th><td>            #    mass           * 1.0        else:</td></tr><tr><th id="L183"><a href="#L183">183</a></th><td>            f.write("pair_style lj/cut 2.5 \n")</td></tr><tr><th id="L184"><a href="#L184">184</a></th><td>            f.write("pair_coeff * * 1 1 \n")</td></tr><tr><th id="L185"><a href="#L185">185</a></th><td>            f.write("mass * 1.0 \n")</td></tr><tr><th id="L186"><a href="#L186">186</a></th><td>        f.write("\n")</td></tr><tr><th id="L187"><a href="#L187">187</a></th><td></td></tr><tr><th id="L188"><a href="#L188">188</a></th><td>        f.write("### run \n")</td></tr><tr><th id="L189"><a href="#L189">189</a></th><td>        f.write("fix fix_nve all nve \n")</td></tr><tr><th id="L190"><a href="#L190">190</a></th><td>        f.write("\n")</td></tr><tr><th id="L191"><a href="#L191">191</a></th><td>        f.write("dump dump_all all custom 1 ${dump_file} id type x y z vx vy vz fx fy fz \n")</td></tr><tr><th id="L192"><a href="#L192">192</a></th><td>        f.write("\n")</td></tr><tr><th id="L193"><a href="#L193">193</a></th><td>        f.write("thermo_style custom step temp ke pe etotal cpu \n")</td></tr><tr><th id="L194"><a href="#L194">194</a></th><td>        f.write("thermo_modify format 1 %4d format 2 %9.3f format 3 %20.6f format 4 %20.6f format 5 %20.6f format 6 %9.3f \n")</td></tr><tr><th id="L195"><a href="#L195">195</a></th><td>        f.write("thermo 1 \n")</td></tr><tr><th id="L196"><a href="#L196">196</a></th><td>        f.write("\n")</td></tr><tr><th id="L197"><a href="#L197">197</a></th><td>        if ("minimize" in parameters):</td></tr><tr><th id="L198"><a href="#L198">198</a></th><td>            f.write("minimize %s \n" % parameters["minimize"])</td></tr><tr><th id="L199"><a href="#L199">199</a></th><td>        if ("run" in parameters):</td></tr><tr><th id="L200"><a href="#L200">200</a></th><td>            f.write("run %s \n" % parameters["run"])</td></tr><tr><th id="L201"><a href="#L201">201</a></th><td>        if not ( ("minimize" in parameters) or ("run" in parameters) ):</td></tr><tr><th id="L202"><a href="#L202">202</a></th><td>            f.write("run 0 \n")</td></tr><tr><th id="L203"><a href="#L203">203</a></th><td></td></tr><tr><th id="L204"><a href="#L204">204</a></th><td>        f.close()</td></tr><tr><th id="L205"><a href="#L205">205</a></th><td></td></tr><tr><th id="L206"><a href="#L206">206</a></th><td>    def read_lammps_log(self, lammps_log=None):</td></tr><tr><th id="L207"><a href="#L207">207</a></th><td>        """Method which reads a LAMMPS output log file."""</td></tr><tr><th id="L208"><a href="#L208">208</a></th><td>        if (lammps_log == None):</td></tr><tr><th id="L209"><a href="#L209">209</a></th><td>            lammps_log = self.label + ".log"</td></tr><tr><th id="L210"><a href="#L210">210</a></th><td></td></tr><tr><th id="L211"><a href="#L211">211</a></th><td>        epot = 0.0</td></tr><tr><th id="L212"><a href="#L212">212</a></th><td></td></tr><tr><th id="L213"><a href="#L213">213</a></th><td>        f = paropen(lammps_log, 'r')</td></tr><tr><th id="L214"><a href="#L214">214</a></th><td>        while True:</td></tr><tr><th id="L215"><a href="#L215">215</a></th><td>            line = f.readline()</td></tr><tr><th id="L216"><a href="#L216">216</a></th><td>            if not line:</td></tr><tr><th id="L217"><a href="#L217">217</a></th><td>                break</td></tr><tr><th id="L218"><a href="#L218">218</a></th><td>            # get potential energy of first step (if more are done)</td></tr><tr><th id="L219"><a href="#L219">219</a></th><td>            if "PotEng" in line:</td></tr><tr><th id="L220"><a href="#L220">220</a></th><td>                i = line.split().index("PotEng")</td></tr><tr><th id="L221"><a href="#L221">221</a></th><td>                line = f.readline()</td></tr><tr><th id="L222"><a href="#L222">222</a></th><td>                epot = float(line.split()[i])</td></tr><tr><th id="L223"><a href="#L223">223</a></th><td>        f.close()</td></tr><tr><th id="L224"><a href="#L224">224</a></th><td></td></tr><tr><th id="L225"><a href="#L225">225</a></th><td>#        print epot</td></tr><tr><th id="L226"><a href="#L226">226</a></th><td></td></tr><tr><th id="L227"><a href="#L227">227</a></th><td>        self.potential_energy = epot</td></tr><tr><th id="L228"><a href="#L228">228</a></th><td></td></tr><tr><th id="L229"><a href="#L229">229</a></th><td>    def read_lammps_trj(self, lammps_trj=None, set_atoms=False):</td></tr><tr><th id="L230"><a href="#L230">230</a></th><td>        """Method which reads a LAMMPS dump file."""</td></tr><tr><th id="L231"><a href="#L231">231</a></th><td>        if (lammps_trj == None):</td></tr><tr><th id="L232"><a href="#L232">232</a></th><td>            lammps_trj = self.label + ".lammpstrj"</td></tr><tr><th id="L233"><a href="#L233">233</a></th><td></td></tr><tr><th id="L234"><a href="#L234">234</a></th><td>        f = paropen(lammps_trj, 'r')</td></tr><tr><th id="L235"><a href="#L235">235</a></th><td>        while True:</td></tr><tr><th id="L236"><a href="#L236">236</a></th><td>            line = f.readline()</td></tr><tr><th id="L237"><a href="#L237">237</a></th><td></td></tr><tr><th id="L238"><a href="#L238">238</a></th><td>            if not line:</td></tr><tr><th id="L239"><a href="#L239">239</a></th><td>                break</td></tr><tr><th id="L240"><a href="#L240">240</a></th><td></td></tr><tr><th id="L241"><a href="#L241">241</a></th><td>            #TODO: extend to proper dealing with multiple steps in one trajectory file</td></tr><tr><th id="L242"><a href="#L242">242</a></th><td>            if "ITEM: TIMESTEP" in line:</td></tr><tr><th id="L243"><a href="#L243">243</a></th><td>                n_atoms = 0</td></tr><tr><th id="L244"><a href="#L244">244</a></th><td>                lo = [] ; hi = [] ; tilt = []</td></tr><tr><th id="L245"><a href="#L245">245</a></th><td>                id = [] ; type = []</td></tr><tr><th id="L246"><a href="#L246">246</a></th><td>                positions = [] ; velocities = [] ; forces = []</td></tr><tr><th id="L247"><a href="#L247">247</a></th><td></td></tr><tr><th id="L248"><a href="#L248">248</a></th><td>            if "ITEM: NUMBER OF ATOMS" in line:</td></tr><tr><th id="L249"><a href="#L249">249</a></th><td>                line = f.readline()</td></tr><tr><th id="L250"><a href="#L250">250</a></th><td>                n_atoms = int(line.split()[0])</td></tr><tr><th id="L251"><a href="#L251">251</a></th><td>            </td></tr><tr><th id="L252"><a href="#L252">252</a></th><td>            if "ITEM: BOX BOUNDS" in line:</td></tr><tr><th id="L253"><a href="#L253">253</a></th><td>                # save labels behind "ITEM: BOX BOUNDS" in triclinic case (&gt;=lammps-7Jul09)</td></tr><tr><th id="L254"><a href="#L254">254</a></th><td>                tilt_items = line.split()[3:]</td></tr><tr><th id="L255"><a href="#L255">255</a></th><td>                for i in range(3):</td></tr><tr><th id="L256"><a href="#L256">256</a></th><td>                    line = f.readline()</td></tr><tr><th id="L257"><a href="#L257">257</a></th><td>                    fields = line.split()</td></tr><tr><th id="L258"><a href="#L258">258</a></th><td>                    lo.append(float(fields[0]))</td></tr><tr><th id="L259"><a href="#L259">259</a></th><td>                    hi.append(float(fields[1]))</td></tr><tr><th id="L260"><a href="#L260">260</a></th><td>                    if (len(fields) &gt;= 3):</td></tr><tr><th id="L261"><a href="#L261">261</a></th><td>                        tilt.append(float(fields[2]))</td></tr><tr><th id="L262"><a href="#L262">262</a></th><td>            </td></tr><tr><th id="L263"><a href="#L263">263</a></th><td>            if "ITEM: ATOMS" in line:</td></tr><tr><th id="L264"><a href="#L264">264</a></th><td>                # (reliably) identify values by labels behind "ITEM: ATOMS" - requires &gt;=lammps-7Jul09</td></tr><tr><th id="L265"><a href="#L265">265</a></th><td>                # create corresponding index dictionary before iterating over atoms to (hopefully) speed up lookups...</td></tr><tr><th id="L266"><a href="#L266">266</a></th><td>                atom_attributes = {}</td></tr><tr><th id="L267"><a href="#L267">267</a></th><td>                for (i, x) in enumerate(line.split()[2:]):</td></tr><tr><th id="L268"><a href="#L268">268</a></th><td>                    atom_attributes[x] = i</td></tr><tr><th id="L269"><a href="#L269">269</a></th><td>                for n in range(n_atoms):</td></tr><tr><th id="L270"><a href="#L270">270</a></th><td>                    line = f.readline()</td></tr><tr><th id="L271"><a href="#L271">271</a></th><td>                    fields = line.split()</td></tr><tr><th id="L272"><a href="#L272">272</a></th><td>                    id.append( int(fields[atom_attributes['id']]) )</td></tr><tr><th id="L273"><a href="#L273">273</a></th><td>                    type.append( int(fields[atom_attributes['type']]) )</td></tr><tr><th id="L274"><a href="#L274">274</a></th><td>                    positions.append( [ float(fields[atom_attributes[x]]) for x in ['x', 'y', 'z'] ] )</td></tr><tr><th id="L275"><a href="#L275">275</a></th><td>                    velocities.append( [ float(fields[atom_attributes[x]]) for x in ['vx', 'vy', 'vz'] ] )</td></tr><tr><th id="L276"><a href="#L276">276</a></th><td>                    forces.append( [ float(fields[atom_attributes[x]]) for x in ['fx', 'fy', 'fz'] ] )</td></tr><tr><th id="L277"><a href="#L277">277</a></th><td>        f.close()</td></tr><tr><th id="L278"><a href="#L278">278</a></th><td></td></tr><tr><th id="L279"><a href="#L279">279</a></th><td>        # determine cell tilt (triclinic case!)</td></tr><tr><th id="L280"><a href="#L280">280</a></th><td>        if (len(tilt) &gt;= 3):</td></tr><tr><th id="L281"><a href="#L281">281</a></th><td>            # for &gt;=lammps-7Jul09 use labels behind "ITEM: BOX BOUNDS" to assign tilt (vector) elements ...</td></tr><tr><th id="L282"><a href="#L282">282</a></th><td>            if (len(tilt_items) &gt;= 3):</td></tr><tr><th id="L283"><a href="#L283">283</a></th><td>                xy = tilt[tilt_items.index('xy')]</td></tr><tr><th id="L284"><a href="#L284">284</a></th><td>                xz = tilt[tilt_items.index('xz')]</td></tr><tr><th id="L285"><a href="#L285">285</a></th><td>                yz = tilt[tilt_items.index('yz')]</td></tr><tr><th id="L286"><a href="#L286">286</a></th><td>            # ... otherwise assume default order in 3rd column (if the latter was present)</td></tr><tr><th id="L287"><a href="#L287">287</a></th><td>            else:</td></tr><tr><th id="L288"><a href="#L288">288</a></th><td>                xy = tilt[0]</td></tr><tr><th id="L289"><a href="#L289">289</a></th><td>                xz = tilt[1]</td></tr><tr><th id="L290"><a href="#L290">290</a></th><td>                yz = tilt[2]</td></tr><tr><th id="L291"><a href="#L291">291</a></th><td>        else:</td></tr><tr><th id="L292"><a href="#L292">292</a></th><td>            xy = xz = yz = 0</td></tr><tr><th id="L293"><a href="#L293">293</a></th><td>        xhilo = (hi[0] - lo[0]) - xy - xz</td></tr><tr><th id="L294"><a href="#L294">294</a></th><td>        yhilo = (hi[1] - lo[1]) - yz</td></tr><tr><th id="L295"><a href="#L295">295</a></th><td>        zhilo = (hi[2] - lo[2])</td></tr><tr><th id="L296"><a href="#L296">296</a></th><td>        </td></tr><tr><th id="L297"><a href="#L297">297</a></th><td>        # The simulation box bounds are included in each snapshot and if the box is triclinic (non-orthogonal), </td></tr><tr><th id="L298"><a href="#L298">298</a></th><td>        # then the tilt factors are also printed; see the region prism command for a description of tilt factors. </td></tr><tr><th id="L299"><a href="#L299">299</a></th><td>        # For triclinic boxes the box bounds themselves (first 2 quantities on each line) are a true "bounding box" </td></tr><tr><th id="L300"><a href="#L300">300</a></th><td>        # around the simulation domain, which means they include the effect of any tilt.</td></tr><tr><th id="L301"><a href="#L301">301</a></th><td>        # [ http://lammps.sandia.gov/doc/dump.html , lammps-7Jul09 ]</td></tr><tr><th id="L302"><a href="#L302">302</a></th><td>        #</td></tr><tr><th id="L303"><a href="#L303">303</a></th><td>        # This *should* extract the lattice vectors that LAMMPS uses from the true "bounding box" printed in the dump file</td></tr><tr><th id="L304"><a href="#L304">304</a></th><td>        # It might fail in some cases (negative tilts?!) due to the MIN / MAX construction of these box corners:</td></tr><tr><th id="L305"><a href="#L305">305</a></th><td>        #</td></tr><tr><th id="L306"><a href="#L306">306</a></th><td>        #       void Domain::set_global_box() </td></tr><tr><th id="L307"><a href="#L307">307</a></th><td>        #       [...]</td></tr><tr><th id="L308"><a href="#L308">308</a></th><td>        #         if (triclinic) {</td></tr><tr><th id="L309"><a href="#L309">309</a></th><td>        #           [...]</td></tr><tr><th id="L310"><a href="#L310">310</a></th><td>        #           boxlo_bound[0] = MIN(boxlo[0],boxlo[0]+xy);</td></tr><tr><th id="L311"><a href="#L311">311</a></th><td>        #           boxlo_bound[0] = MIN(boxlo_bound[0],boxlo_bound[0]+xz);</td></tr><tr><th id="L312"><a href="#L312">312</a></th><td>        #           boxlo_bound[1] = MIN(boxlo[1],boxlo[1]+yz);</td></tr><tr><th id="L313"><a href="#L313">313</a></th><td>        #           boxlo_bound[2] = boxlo[2];</td></tr><tr><th id="L314"><a href="#L314">314</a></th><td>        #</td></tr><tr><th id="L315"><a href="#L315">315</a></th><td>        #           boxhi_bound[0] = MAX(boxhi[0],boxhi[0]+xy);</td></tr><tr><th id="L316"><a href="#L316">316</a></th><td>        #           boxhi_bound[0] = MAX(boxhi_bound[0],boxhi_bound[0]+xz);</td></tr><tr><th id="L317"><a href="#L317">317</a></th><td>        #           boxhi_bound[1] = MAX(boxhi[1],boxhi[1]+yz);</td></tr><tr><th id="L318"><a href="#L318">318</a></th><td>        #           boxhi_bound[2] = boxhi[2];</td></tr><tr><th id="L319"><a href="#L319">319</a></th><td>        #         }</td></tr><tr><th id="L320"><a href="#L320">320</a></th><td>        # [ lammps-7Jul09/src/domain.cpp ]</td></tr><tr><th id="L321"><a href="#L321">321</a></th><td>        #</td></tr><tr><th id="L322"><a href="#L322">322</a></th><td>        cell = [[xhilo,0,0],[xy,yhilo,0],[xz,yz,zhilo]]</td></tr><tr><th id="L323"><a href="#L323">323</a></th><td></td></tr><tr><th id="L324"><a href="#L324">324</a></th><td>#       print n_atoms</td></tr><tr><th id="L325"><a href="#L325">325</a></th><td>#       print lo</td></tr><tr><th id="L326"><a href="#L326">326</a></th><td>#       print hi</td></tr><tr><th id="L327"><a href="#L327">327</a></th><td>#       print id</td></tr><tr><th id="L328"><a href="#L328">328</a></th><td>#       print type</td></tr><tr><th id="L329"><a href="#L329">329</a></th><td>#       print positions</td></tr><tr><th id="L330"><a href="#L330">330</a></th><td>#       print velocities</td></tr><tr><th id="L331"><a href="#L331">331</a></th><td>#       print forces</td></tr><tr><th id="L332"><a href="#L332">332</a></th><td></td></tr><tr><th id="L333"><a href="#L333">333</a></th><td>        # assume that LAMMPS does not reorder atoms internally</td></tr><tr><th id="L334"><a href="#L334">334</a></th><td>#        print np.array(positions)</td></tr><tr><th id="L335"><a href="#L335">335</a></th><td>#        print self.atoms.get_positions()</td></tr><tr><th id="L336"><a href="#L336">336</a></th><td>#        print np.array(positions) - self.atoms.get_positions()</td></tr><tr><th id="L337"><a href="#L337">337</a></th><td></td></tr><tr><th id="L338"><a href="#L338">338</a></th><td>        cell_atoms = np.array(cell)</td></tr><tr><th id="L339"><a href="#L339">339</a></th><td>        type_atoms = np.array(type)</td></tr><tr><th id="L340"><a href="#L340">340</a></th><td>#      velocities_atoms = np.array(velocities)</td></tr><tr><th id="L341"><a href="#L341">341</a></th><td>        positions_atoms = np.array(positions)</td></tr><tr><th id="L342"><a href="#L342">342</a></th><td>        forces_atoms = np.array(forces)</td></tr><tr><th id="L343"><a href="#L343">343</a></th><td></td></tr><tr><th id="L344"><a href="#L344">344</a></th><td>        if self.atoms:</td></tr><tr><th id="L345"><a href="#L345">345</a></th><td>            cell_atoms = self.atoms.get_cell()</td></tr><tr><th id="L346"><a href="#L346">346</a></th><td></td></tr><tr><th id="L347"><a href="#L347">347</a></th><td>            rotation_lammps2ase = np.dot(np.linalg.inv(np.array(cell)), cell_atoms)</td></tr><tr><th id="L348"><a href="#L348">348</a></th><td>#           print "rotation_lammps2ase:"</td></tr><tr><th id="L349"><a href="#L349">349</a></th><td>#           print rotation_lammps2ase</td></tr><tr><th id="L350"><a href="#L350">350</a></th><td>#           print np.transpose(rotation_lammps2ase)</td></tr><tr><th id="L351"><a href="#L351">351</a></th><td>#           print np.linalg.det(rotation_lammps2ase)                                            # check for orthogonality of matrix 'rotation'</td></tr><tr><th id="L352"><a href="#L352">352</a></th><td>#           print np.dot(rotation_lammps2ase, np.transpose(rotation_lammps2ase))                # check for orthogonality of matrix 'rotation'</td></tr><tr><th id="L353"><a href="#L353">353</a></th><td></td></tr><tr><th id="L354"><a href="#L354">354</a></th><td>            type_atoms = self.atoms.get_atomic_numbers()</td></tr><tr><th id="L355"><a href="#L355">355</a></th><td>            positions_atoms = np.array( [np.dot(np.array(r), rotation_lammps2ase) for r in positions] )</td></tr><tr><th id="L356"><a href="#L356">356</a></th><td>            velocities_atoms = np.array( [np.dot(np.array(v), rotation_lammps2ase) for v in velocities] )</td></tr><tr><th id="L357"><a href="#L357">357</a></th><td>            forces_atoms = np.array( [np.dot(np.array(f), rotation_lammps2ase) for f in forces] )</td></tr><tr><th id="L358"><a href="#L358">358</a></th><td></td></tr><tr><th id="L359"><a href="#L359">359</a></th><td>        if (set_atoms):</td></tr><tr><th id="L360"><a href="#L360">360</a></th><td>            # assume periodic boundary conditions here (like also below in write_lammps) &lt;- TODO:?!</td></tr><tr><th id="L361"><a href="#L361">361</a></th><td>            self.atoms = Atoms(type_atoms, positions=positions_atoms, cell=cell_atoms, pbc=True)</td></tr><tr><th id="L362"><a href="#L362">362</a></th><td></td></tr><tr><th id="L363"><a href="#L363">363</a></th><td>        self.forces = forces_atoms</td></tr><tr><th id="L364"><a href="#L364">364</a></th><td></td></tr><tr><th id="L365"><a href="#L365">365</a></th><td></td></tr><tr><th id="L366"><a href="#L366">366</a></th><td># could perhaps go into io.lammps in the future...</td></tr><tr><th id="L367"><a href="#L367">367</a></th><td>#from ase.parallel import paropen</td></tr><tr><th id="L368"><a href="#L368">368</a></th><td>def write_lammps(fileobj, atoms, force_skew=False):</td></tr><tr><th id="L369"><a href="#L369">369</a></th><td>    """Method which writes atomic structure data to a LAMMPS data file."""</td></tr><tr><th id="L370"><a href="#L370">370</a></th><td>    if isinstance(fileobj, file):</td></tr><tr><th id="L371"><a href="#L371">371</a></th><td>        f = fileobj</td></tr><tr><th id="L372"><a href="#L372">372</a></th><td>    elif isinstance(fileobj, str):</td></tr><tr><th id="L373"><a href="#L373">373</a></th><td>        f = paropen(fileobj, 'w')</td></tr><tr><th id="L374"><a href="#L374">374</a></th><td>    else :</td></tr><tr><th id="L375"><a href="#L375">375</a></th><td>        raise TypeError('fileobj is not of type file or str!')</td></tr><tr><th id="L376"><a href="#L376">376</a></th><td></td></tr><tr><th id="L377"><a href="#L377">377</a></th><td>    if isinstance(atoms, list):</td></tr><tr><th id="L378"><a href="#L378">378</a></th><td>        if len(atoms) &gt; 1:</td></tr><tr><th id="L379"><a href="#L379">379</a></th><td>            raise ValueError('Can only write one configuration to a lammps data file!')</td></tr><tr><th id="L380"><a href="#L380">380</a></th><td>        atoms = atoms[0]</td></tr><tr><th id="L381"><a href="#L381">381</a></th><td></td></tr><tr><th id="L382"><a href="#L382">382</a></th><td>    f.write(f.name + " (written by ASE) \n\n")</td></tr><tr><th id="L383"><a href="#L383">383</a></th><td></td></tr><tr><th id="L384"><a href="#L384">384</a></th><td>    symbols = atoms.get_chemical_symbols()</td></tr><tr><th id="L385"><a href="#L385">385</a></th><td>    n_atoms = len(symbols)</td></tr><tr><th id="L386"><a href="#L386">386</a></th><td>    f.write("%d \t atoms \n" % n_atoms)</td></tr><tr><th id="L387"><a href="#L387">387</a></th><td></td></tr><tr><th id="L388"><a href="#L388">388</a></th><td>    # Uniqify 'symbols' list and sort to a new list 'species'.</td></tr><tr><th id="L389"><a href="#L389">389</a></th><td>    # Sorting is important in case of multi-component systems:</td></tr><tr><th id="L390"><a href="#L390">390</a></th><td>    # This way it is assured that LAMMPS atom types are always</td></tr><tr><th id="L391"><a href="#L391">391</a></th><td>    # assigned predictively according to the alphabetic order </td></tr><tr><th id="L392"><a href="#L392">392</a></th><td>    # of the species present in the current system. </td></tr><tr><th id="L393"><a href="#L393">393</a></th><td>    # (Hence e.g. the mapping in interaction statements for alloy</td></tr><tr><th id="L394"><a href="#L394">394</a></th><td>    #  potentials depending on the order of the elements in the</td></tr><tr><th id="L395"><a href="#L395">395</a></th><td>    #  external potential can also be safely adjusted accordingly.)</td></tr><tr><th id="L396"><a href="#L396">396</a></th><td>    species = sorted(list(set(symbols)))</td></tr><tr><th id="L397"><a href="#L397">397</a></th><td>    n_atom_types = len(species)</td></tr><tr><th id="L398"><a href="#L398">398</a></th><td>    f.write("%d \t atom types \n" % n_atom_types)</td></tr><tr><th id="L399"><a href="#L399">399</a></th><td></td></tr><tr><th id="L400"><a href="#L400">400</a></th><td></td></tr><tr><th id="L401"><a href="#L401">401</a></th><td>    ### cell -&gt; bounding box for LAMMPS</td></tr><tr><th id="L402"><a href="#L402">402</a></th><td></td></tr><tr><th id="L403"><a href="#L403">403</a></th><td>    ## A) simple version</td></tr><tr><th id="L404"><a href="#L404">404</a></th><td>    # - For orthogonal cells which are properly aligned with the reference coordinate system only.</td></tr><tr><th id="L405"><a href="#L405">405</a></th><td>#    cell = atoms.get_cell()</td></tr><tr><th id="L406"><a href="#L406">406</a></th><td>#    lo = [0.0, 0.0, 0.0]</td></tr><tr><th id="L407"><a href="#L407">407</a></th><td>#    hi = sum(cell[0:3])</td></tr><tr><th id="L408"><a href="#L408">408</a></th><td>#    f.write("%15.8f %15.8f \t xlo xhi \n" % (lo[0], hi[0]))</td></tr><tr><th id="L409"><a href="#L409">409</a></th><td>#    f.write("%15.8f %15.8f \t ylo yhi \n" % (lo[1], hi[1]))</td></tr><tr><th id="L410"><a href="#L410">410</a></th><td>#    f.write("%15.8f %15.8f \t zlo zhi \n" % (lo[2], hi[2]))</td></tr><tr><th id="L411"><a href="#L411">411</a></th><td>#    f.write("\n\n")</td></tr><tr><th id="L412"><a href="#L412">412</a></th><td></td></tr><tr><th id="L413"><a href="#L413">413</a></th><td>    ## B) convert to (perhaps) triclinic cells in LAMMPS</td></tr><tr><th id="L414"><a href="#L414">414</a></th><td>    </td></tr><tr><th id="L415"><a href="#L415">415</a></th><td>    # B.1) calculate lengths of and angles between cell vectors</td></tr><tr><th id="L416"><a href="#L416">416</a></th><td>    #     (conventional crystallographic nomenclature)</td></tr><tr><th id="L417"><a href="#L417">417</a></th><td>    cell = atoms.get_cell()</td></tr><tr><th id="L418"><a href="#L418">418</a></th><td>    a = np.linalg.norm(cell[0])</td></tr><tr><th id="L419"><a href="#L419">419</a></th><td>    b = np.linalg.norm(cell[1])</td></tr><tr><th id="L420"><a href="#L420">420</a></th><td>    c = np.linalg.norm(cell[2])</td></tr><tr><th id="L421"><a href="#L421">421</a></th><td>    alpha = np.arccos( np.vdot(cell[1], cell[2]) / (b * c) )</td></tr><tr><th id="L422"><a href="#L422">422</a></th><td>    beta = np.arccos( np.vdot(cell[0], cell[2]) / (a * c) )</td></tr><tr><th id="L423"><a href="#L423">423</a></th><td>    gamma = np.arccos( np.vdot(cell[0], cell[1]) / (a * b) )</td></tr><tr><th id="L424"><a href="#L424">424</a></th><td>#    print [a, b, c]</td></tr><tr><th id="L425"><a href="#L425">425</a></th><td>#    print map(np.degrees, [alpha, beta, gamma])</td></tr><tr><th id="L426"><a href="#L426">426</a></th><td></td></tr><tr><th id="L427"><a href="#L427">427</a></th><td>    # B.2) construct bounding box edges and skew vector of </td></tr><tr><th id="L428"><a href="#L428">428</a></th><td>    #     corresponding (perhaps rotated!) LAMMPS cell</td></tr><tr><th id="L429"><a href="#L429">429</a></th><td>    # http://lammps.sandia.gov/doc/read_data.html :</td></tr><tr><th id="L430"><a href="#L430">430</a></th><td>    #   a_LAMMPS = (xhi-xlo,0,0); b_LAMMPS = (xy,yhi-ylo,0); c_LAMMPS = (xz,yz,zhi-zlo)</td></tr><tr><th id="L431"><a href="#L431">431</a></th><td>    xlo = ylo = zlo = 0.0</td></tr><tr><th id="L432"><a href="#L432">432</a></th><td>    # this choice of origin simplifies things:</td></tr><tr><th id="L433"><a href="#L433">433</a></th><td>    #   a_LAMMPS = (xhi,0,0); b_LAMMPS = (xy,yhi,0); c_LAMMPS = (xz,yz,zhi)</td></tr><tr><th id="L434"><a href="#L434">434</a></th><td>    xhi = a                     # a_LAMMPS</td></tr><tr><th id="L435"><a href="#L435">435</a></th><td>    xy = np.cos(gamma) * b      # b_LAMMPS</td></tr><tr><th id="L436"><a href="#L436">436</a></th><td>    yhi = np.sin(gamma) * b</td></tr><tr><th id="L437"><a href="#L437">437</a></th><td>    xz = np.cos(beta) * c       # c_LAMMPS</td></tr><tr><th id="L438"><a href="#L438">438</a></th><td>    yz = ( b * c * np.cos(alpha) - xy * xz ) / yhi</td></tr><tr><th id="L439"><a href="#L439">439</a></th><td>    zhi = np.sqrt( c**2 - xz**2 - yz**2 )</td></tr><tr><th id="L440"><a href="#L440">440</a></th><td>    </td></tr><tr><th id="L441"><a href="#L441">441</a></th><td>    # B.3) obtain rotation of original cell with respect to LAMMPS cell</td></tr><tr><th id="L442"><a href="#L442">442</a></th><td>    #     to properly tranform the atoms contained within (see below!)</td></tr><tr><th id="L443"><a href="#L443">443</a></th><td>    # IMPORTANT: use same convention as in cell of ASE atoms object, i.e.</td></tr><tr><th id="L444"><a href="#L444">444</a></th><td>    #            cell vectors are ROW VECTORS in numpy array</td></tr><tr><th id="L445"><a href="#L445">445</a></th><td>    cell_lammps = np.array([[xhi-xlo,0,0],[xy,yhi-ylo,0],[xz,yz,zhi-zlo]])</td></tr><tr><th id="L446"><a href="#L446">446</a></th><td>#    a_lammps = np.linalg.norm(cell_lammps[0])</td></tr><tr><th id="L447"><a href="#L447">447</a></th><td>#    b_lammps = np.linalg.norm(cell_lammps[1])</td></tr><tr><th id="L448"><a href="#L448">448</a></th><td>#    c_lammps = np.linalg.norm(cell_lammps[2])</td></tr><tr><th id="L449"><a href="#L449">449</a></th><td>#    alpha_lammps = np.arccos( np.vdot(cell_lammps[1], cell_lammps[2]) / (b_lammps * c_lammps) )</td></tr><tr><th id="L450"><a href="#L450">450</a></th><td>#    beta_lammps = np.arccos( np.vdot(cell_lammps[0], cell_lammps[2]) / (a_lammps * c_lammps) )</td></tr><tr><th id="L451"><a href="#L451">451</a></th><td>#    gamma_lammps = np.arccos( np.vdot(cell_lammps[0], cell_lammps[1]) / (a_lammps * b_lammps) )</td></tr><tr><th id="L452"><a href="#L452">452</a></th><td>#    print [a_lammps, b_lammps, c_lammps]</td></tr><tr><th id="L453"><a href="#L453">453</a></th><td>#    print map(np.degrees, [alpha_lammps, beta_lammps, gamma_lammps])</td></tr><tr><th id="L454"><a href="#L454">454</a></th><td>    # IMPORTANT: need vector-(rotation-)matrix product (instead of matrix-vector product) here,</td></tr><tr><th id="L455"><a href="#L455">455</a></th><td>    #            cell vectors are ROW VECTORS (also see above)</td></tr><tr><th id="L456"><a href="#L456">456</a></th><td>    rotation = np.dot(np.linalg.inv(cell), cell_lammps)</td></tr><tr><th id="L457"><a href="#L457">457</a></th><td>#    print rotation</td></tr><tr><th id="L458"><a href="#L458">458</a></th><td>#    print np.transpose(rotation)</td></tr><tr><th id="L459"><a href="#L459">459</a></th><td>#    print np.linalg.det(rotation)                              # check for orthogonality of matrix 'rotation'</td></tr><tr><th id="L460"><a href="#L460">460</a></th><td>#    print np.dot(rotation, np.transpose(rotation))             # check for orthogonality of matrix 'rotation'</td></tr><tr><th id="L461"><a href="#L461">461</a></th><td>#    print np.dot(rotation, cell[0])</td></tr><tr><th id="L462"><a href="#L462">462</a></th><td>#    print np.dot(rotation, cell[1])</td></tr><tr><th id="L463"><a href="#L463">463</a></th><td>#    print np.dot(rotation, cell[2])</td></tr><tr><th id="L464"><a href="#L464">464</a></th><td></td></tr><tr><th id="L465"><a href="#L465">465</a></th><td>    # B.4.1) write bounding box edges</td></tr><tr><th id="L466"><a href="#L466">466</a></th><td>    f.write("%15.8f %15.8f \t\t\t xlo xhi \n" % (xlo, xhi))</td></tr><tr><th id="L467"><a href="#L467">467</a></th><td>    f.write("%15.8f %15.8f \t\t\t ylo yhi \n" % (ylo, yhi))</td></tr><tr><th id="L468"><a href="#L468">468</a></th><td>    f.write("%15.8f %15.8f \t\t\t zlo zhi \n" % (zlo, zhi))</td></tr><tr><th id="L469"><a href="#L469">469</a></th><td>    </td></tr><tr><th id="L470"><a href="#L470">470</a></th><td>    # B.4.2) sanitize and write skew vector (if necessary)</td></tr><tr><th id="L471"><a href="#L471">471</a></th><td>    # The too simple version </td></tr><tr><th id="L472"><a href="#L472">472</a></th><td>    #    f.write("%20.10f %20.10f %20.10f \t xy xz yz \n" % (xy, xz, yz))    </td></tr><tr><th id="L473"><a href="#L473">473</a></th><td>    # can make LAMMPS (easily) reject the definition of a triclinic box because</td></tr><tr><th id="L474"><a href="#L474">474</a></th><td>    #   a) skew vector components calculated above are outside the respective ranges </td></tr><tr><th id="L475"><a href="#L475">475</a></th><td>    #      which LAMMPS expects as described here</td></tr><tr><th id="L476"><a href="#L476">476</a></th><td>    #           http://lammps.sandia.gov/doc/read_data.html</td></tr><tr><th id="L477"><a href="#L477">477</a></th><td>    #      and coded here</td></tr><tr><th id="L478"><a href="#L478">478</a></th><td>    #           domain.cpp -&gt; Domain::set_initial_box()</td></tr><tr><th id="L479"><a href="#L479">479</a></th><td>    #   b) rounding up in the skew vector output can make the result violate those </td></tr><tr><th id="L480"><a href="#L480">480</a></th><td>    #      ranges for purely numeric reasons (perhaps even more frequent problem than a)</td></tr><tr><th id="L481"><a href="#L481">481</a></th><td>    #      and definitely more stupid!)</td></tr><tr><th id="L482"><a href="#L482">482</a></th><td>    # More elaborate solution addressing the issues described above:</td></tr><tr><th id="L483"><a href="#L483">483</a></th><td>    # -&gt; a):</td></tr><tr><th id="L484"><a href="#L484">484</a></th><td>    # Fold back skew vector components calculated above to equivalent ones complying with</td></tr><tr><th id="L485"><a href="#L485">485</a></th><td>    # what LAMMPS expects (see references above) and describing another ("less skewed") </td></tr><tr><th id="L486"><a href="#L486">486</a></th><td>    # unit cell for the same lattice:</td></tr><tr><th id="L487"><a href="#L487">487</a></th><td>    #           t -&gt; t_folded in [-period/2, +period/2]</td></tr><tr><th id="L488"><a href="#L488">488</a></th><td>    def fold_skew_dec(t, period) :</td></tr><tr><th id="L489"><a href="#L489">489</a></th><td>        t_dec = dec.Decimal(repr(t))</td></tr><tr><th id="L490"><a href="#L490">490</a></th><td>        period_dec = dec.Decimal(repr(period))</td></tr><tr><th id="L491"><a href="#L491">491</a></th><td>        # dec.ROUND_HALF_DOWN leaves all t in [-period/2, +period/2] unchanged whereas</td></tr><tr><th id="L492"><a href="#L492">492</a></th><td>        # dec.ROUND_HALF_UP does the same for all t in (-period/2, +period/2) but</td></tr><tr><th id="L493"><a href="#L493">493</a></th><td>        # swaps the boundary values: </td></tr><tr><th id="L494"><a href="#L494">494</a></th><td>        #       t=-period/2 -&gt; t_folded=+period/2</td></tr><tr><th id="L495"><a href="#L495">495</a></th><td>        #       t=+period/2 -&gt; t_folded=-period/2</td></tr><tr><th id="L496"><a href="#L496">496</a></th><td>        t_folded_dec = t_dec - period_dec * (t_dec/period_dec).to_integral_value(dec.ROUND_HALF_DOWN)</td></tr><tr><th id="L497"><a href="#L497">497</a></th><td>        return t_folded_dec</td></tr><tr><th id="L498"><a href="#L498">498</a></th><td>    skew_folded_dec = [ fold_skew_dec(xy, xhi-xlo), fold_skew_dec(xz, xhi-xlo), fold_skew_dec(yz, yhi-ylo) ]</td></tr><tr><th id="L499"><a href="#L499">499</a></th><td>    # -&gt; b):</td></tr><tr><th id="L500"><a href="#L500">500</a></th><td>    # This should be kept in sync with the accuracy used for writing the bounding box edges above</td></tr><tr><th id="L501"><a href="#L501">501</a></th><td>    prec_dec = dec.Decimal('1E-8')</td></tr><tr><th id="L502"><a href="#L502">502</a></th><td>    # Make sure to always round down and hence avoid numerical problems with skew vector in LAMMPS.</td></tr><tr><th id="L503"><a href="#L503">503</a></th><td>    skew_folded_and_rounded_dec = [ d.quantize(prec_dec, dec.ROUND_DOWN) for d in skew_folded_dec ]</td></tr><tr><th id="L504"><a href="#L504">504</a></th><td>    # Do not write zero skew vector. </td></tr><tr><th id="L505"><a href="#L505">505</a></th><td>    # (I.e. calculate orthogonal cell with LAMMPS in that case!)</td></tr><tr><th id="L506"><a href="#L506">506</a></th><td>    has_skew = any( [not d.is_zero() for d in skew_folded_and_rounded_dec] )</td></tr><tr><th id="L507"><a href="#L507">507</a></th><td>    if force_skew or has_skew:</td></tr><tr><th id="L508"><a href="#L508">508</a></th><td>        f.write( "%15s %15s %15s \t xy xz yz \n" % tuple( str(d) for d in skew_folded_and_rounded_dec ) )</td></tr><tr><th id="L509"><a href="#L509">509</a></th><td>    f.write("\n\n")</td></tr><tr><th id="L510"><a href="#L510">510</a></th><td></td></tr><tr><th id="L511"><a href="#L511">511</a></th><td></td></tr><tr><th id="L512"><a href="#L512">512</a></th><td>    ### atoms</td></tr><tr><th id="L513"><a href="#L513">513</a></th><td></td></tr><tr><th id="L514"><a href="#L514">514</a></th><td>    ## A) simple version</td></tr><tr><th id="L515"><a href="#L515">515</a></th><td>    # - For orthogonal cells which are properly aligned with the reference coordinate system only.</td></tr><tr><th id="L516"><a href="#L516">516</a></th><td>#    f.write("Atoms \n\n")</td></tr><tr><th id="L517"><a href="#L517">517</a></th><td>#    for i, (x, y, z) in enumerate(atoms.get_positions()):</td></tr><tr><th id="L518"><a href="#L518">518</a></th><td>#        s = species.index(symbols[i]) + 1</td></tr><tr><th id="L519"><a href="#L519">519</a></th><td>#        f.write("%6d %3d %22.15f %22.15f %22.15f \n" % (i+1, s, x, y, z))</td></tr><tr><th id="L520"><a href="#L520">520</a></th><td></td></tr><tr><th id="L521"><a href="#L521">521</a></th><td>    ## B) convert to (perhaps) triclinic cells in LAMMPS:</td></tr><tr><th id="L522"><a href="#L522">522</a></th><td>    # - Apply rotation determined above for this case.</td></tr><tr><th id="L523"><a href="#L523">523</a></th><td>    # - Lattice translation in case of a folded skew vector above should not be necessary,</td></tr><tr><th id="L524"><a href="#L524">524</a></th><td>    #   since the resulting (perhaps) new unit cell does describe the same lattice.</td></tr><tr><th id="L525"><a href="#L525">525</a></th><td>    #   Therefore the (rotated) atoms are still at correct lattice sites, only some of them</td></tr><tr><th id="L526"><a href="#L526">526</a></th><td>    #   probably are outside of that new unit cell, which LAMMPS can hopefully deal with.</td></tr><tr><th id="L527"><a href="#L527">527</a></th><td>    f.write("Atoms \n\n")</td></tr><tr><th id="L528"><a href="#L528">528</a></th><td>    for i, r in enumerate(atoms.get_positions()):</td></tr><tr><th id="L529"><a href="#L529">529</a></th><td>        s = species.index(symbols[i]) + 1</td></tr><tr><th id="L530"><a href="#L530">530</a></th><td>        [x, y, z] = np.dot(r, rotation)</td></tr><tr><th id="L531"><a href="#L531">531</a></th><td>#        print r, [x, y, z]</td></tr><tr><th id="L532"><a href="#L532">532</a></th><td>        f.write("%6d %3d %22.15f %22.15f %22.15f \n" % (i+1, s, x, y, z))</td></tr><tr><th id="L533"><a href="#L533">533</a></th><td></td></tr><tr><th id="L534"><a href="#L534">534</a></th><td>    f.close()</td></tr><tr><th id="L535"><a href="#L535">535</a></th><td></td></tr><tr><th id="L536"><a href="#L536">536</a></th><td></td></tr><tr><th id="L537"><a href="#L537">537</a></th><td>if __name__ == "__main__":</td></tr><tr><th id="L538"><a href="#L538">538</a></th><td></td></tr><tr><th id="L539"><a href="#L539">539</a></th><td>    pair_style = "eam"</td></tr><tr><th id="L540"><a href="#L540">540</a></th><td>    Pd_eam_file = "Pd_u3.eam"</td></tr><tr><th id="L541"><a href="#L541">541</a></th><td>    pair_coeff = [ "* * " + Pd_eam_file ]</td></tr><tr><th id="L542"><a href="#L542">542</a></th><td>    parameters = { "pair_style" : pair_style, "pair_coeff" : pair_coeff }</td></tr><tr><th id="L543"><a href="#L543">543</a></th><td>    files = [ Pd_eam_file ]</td></tr><tr><th id="L544"><a href="#L544">544</a></th><td>    calc = LAMMPS(parameters=parameters, files=files)</td></tr><tr><th id="L545"><a href="#L545">545</a></th><td></td></tr><tr><th id="L546"><a href="#L546">546</a></th><td>    from ase import Atoms</td></tr><tr><th id="L547"><a href="#L547">547</a></th><td>    a0 = 3.93</td></tr><tr><th id="L548"><a href="#L548">548</a></th><td>    b0 = a0 / 2.0</td></tr><tr><th id="L549"><a href="#L549">549</a></th><td>    if True:</td></tr><tr><th id="L550"><a href="#L550">550</a></th><td>        bulk = Atoms(['Pd']*4,</td></tr><tr><th id="L551"><a href="#L551">551</a></th><td>                     positions=[(0,0,0),(b0,b0,0),(b0,0,b0),(0,b0,b0)],</td></tr><tr><th id="L552"><a href="#L552">552</a></th><td>                     cell=[a0]*3,</td></tr><tr><th id="L553"><a href="#L553">553</a></th><td>                     pbc=True)</td></tr><tr><th id="L554"><a href="#L554">554</a></th><td>        # test get_forces</td></tr><tr><th id="L555"><a href="#L555">555</a></th><td>        print "forces for a = %f" % a0</td></tr><tr><th id="L556"><a href="#L556">556</a></th><td>        print calc.get_forces(bulk)</td></tr><tr><th id="L557"><a href="#L557">557</a></th><td>        # single points for various lattice constants</td></tr><tr><th id="L558"><a href="#L558">558</a></th><td>        bulk.set_calculator(calc)</td></tr><tr><th id="L559"><a href="#L559">559</a></th><td>        for n in range(-5,5,1):</td></tr><tr><th id="L560"><a href="#L560">560</a></th><td>            a = a0 * (1 + n/100.0)</td></tr><tr><th id="L561"><a href="#L561">561</a></th><td>            bulk.set_cell([a]*3)</td></tr><tr><th id="L562"><a href="#L562">562</a></th><td>            print "a : %f , total energy : %f" % (a, bulk.get_potential_energy())</td></tr><tr><th id="L563"><a href="#L563">563</a></th><td></td></tr><tr><th id="L564"><a href="#L564">564</a></th><td>#    calc.clean(force=True)</td></tr><tr><th id="L565"><a href="#L565">565</a></th><td>    calc.clean()</td></tr><tr><th id="L566"><a href="#L566">566</a></th><td></td></tr><tr><th id="L567"><a href="#L567">567</a></th><td></td></tr><tr><th id="L568"><a href="#L568">568</a></th><td></td></tr></tbody></table>
122

  
123
      </div>
124
      <div id="help"><strong>Note:</strong> See <a href="/projects/ase/wiki/TracBrowser">TracBrowser</a>
125
        for help on using the repository browser.</div>
126
      <div id="anydiff">
127
        <form action="/projects/ase/diff" method="get">
128
          <div class="buttons">
129
            <input type="hidden" name="new_path" value="/trunk/ase/calculators/lammps.py" />
130
            <input type="hidden" name="old_path" value="/trunk/ase/calculators/lammps.py" />
131
            <input type="hidden" name="new_rev" />
132
            <input type="hidden" name="old_rev" />
133
            <input type="submit" value="View changes..." title="Select paths and revs for Diff" />
134
          </div>
135
        </form>
136
      </div>
137
    </div>
138
    <div id="altlinks">
139
      <h3>Download in other formats:</h3>
140
      <ul>
141
        <li class="first">
142
          <a rel="nofollow" href="/projects/ase/browser/trunk/ase/calculators/lammps.py?format=txt">Plain Text</a>
143
        </li><li class="last">
144
          <a rel="nofollow" href="/projects/ase/export/2073/trunk/ase/calculators/lammps.py">Original Format</a>
145
        </li>
146
      </ul>
147
    </div>
148
    </div>
149
    <div id="footer" lang="en" xml:lang="en"><hr />
150
      <a id="tracpowered" href="http://trac.edgewall.org/"><img src="/projects/ase/chrome/common/trac_logo_mini.png" height="30" width="107" alt="Trac Powered" /></a>
151
      <p class="left">Powered by <a href="/projects/ase/about"><strong>Trac 0.12</strong></a><br />
152
        By <a href="http://www.edgewall.org/">Edgewall Software</a>.</p>
153
      <p class="right">Visit the Trac open source project at<br /><a href="http://trac.edgewall.org/">http://trac.edgewall.org/</a></p>
154
    </div>
155
  </body>
156
</html>
ase/calculators/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

  
ase/calculators/turbomole.py (revision 3)
2 2

  
3 3
http://www.turbomole.com/
4 4
"""
5

  
6

  
7 5
import os, sys, string
8 6

  
9
from ase.data import chemical_symbols
10 7
from ase.units import Hartree, Bohr
11 8
from ase.io.turbomole import write_turbomole
12
from general import Calculator
9
from ase.calculators.general import Calculator
13 10

  
14 11
import numpy as np
15 12

  
16 13
class Turbomole(Calculator):
17 14
    """Class for doing Turbomole calculations.
18 15
    """
19
    def __init__(self, label='turbomole'):
16
    def __init__(self, label='turbomole', calculate_energy="dscf", calculate_forces="grad", post_HF = False):
20 17
        """Construct TURBOMOLE-calculator object.
21 18

  
22 19
        Parameters
......
59 56
        e = a.get_potential_energy()
60 57
        
61 58
        """
62
        
63
        # get names of executables for turbomole energy and forces
64
        # get the path
65

  
66
        os.system('rm -f sysname.file; sysname > sysname.file')
67
        f = open('sysname.file')
68
        architechture = f.readline()[:-1]
69
        f.close()
70
        tmpath = os.environ['TURBODIR']
71
        pre = tmpath + '/bin/' + architechture + '/'
72

  
73

  
74
        if os.path.isfile('control'):
75
            f = open('control')
76
        else:
77
            print 'File control is missing'
78
            raise RuntimeError, \
79
                'Please run Turbomole define and come thereafter back'
80
        lines = f.readlines()
81
        f.close()
82
        self.tm_program_energy=pre+'dscf'
83
        self.tm_program_forces=pre+'grad'        
84
        for line in lines:
85
            if line.startswith('$ricore'):
86
                self.tm_program_energy=pre+'ridft'
87
                self.tm_program_forces=pre+'rdgrad'
88

  
59
       
89 60
        self.label = label
90 61
        self.converged = False
91
        #clean up turbomole energy file
92
        os.system('rm -f energy; touch energy')
62
        
63
        # set calculators for energy and forces
64
        self.calculate_energy = calculate_energy
65
        self.calculate_forces = calculate_forces
93 66

  
94
        #turbomole has no stress
67
        # turbomole has no stress
95 68
        self.stress = np.empty((3, 3))
96 69
        
70
        # storage for energy and forces
71
        self.e_total = None
72
        self.forces = None
73
        self.updated = False
74
        
75
        # atoms must be set
76
        self.atoms = None
77
        
78
        # POST-HF method 
79
        self.post_HF  = post_HF
97 80

  
98
    def update(self, atoms):
99
        """Energy and forces are calculated when atoms have moved
100
        by calling self.calculate
101
        """
102
        if (not self.converged or
103
            len(self.numbers) != len(atoms) or
104
            (self.numbers != atoms.get_atomic_numbers()).any()):
105
            self.initialize(atoms)
106
            self.calculate(atoms)
107
        elif ((self.positions != atoms.get_positions()).any() or
108
              (self.pbc != atoms.get_pbc()).any() or
109
              (self.cell != atoms.get_cell()).any()):
110
            self.calculate(atoms)
111

  
112 81
    def initialize(self, atoms):
113 82
        self.numbers = atoms.get_atomic_numbers().copy()
114 83
        self.species = []
......
116 85
            self.species.append(Z)
117 86
        self.converged = False
118 87
        
88
    def execute(self, command):
89
        from subprocess import Popen, PIPE
90
        try:
91
            proc = Popen([command], shell=True, stderr=PIPE)
92
            error = proc.communicate()[1]
93
            if "abnormally" in error:
94
                raise OSError(error)
95
            print "TM command: ", command, "successfully executed"
96
        except OSError, e:
97
            print >>sys.stderr, "Execution failed:", e
98
            sys.exit(1)
99

  
119 100
    def get_potential_energy(self, atoms):
120
        self.update(atoms)
121
        return self.etotal
101
        # update atoms
102
        self.set_atoms(atoms)
103
        # if update of energy is neccessary
104
        if self.update_energy:
105
            # calculate energy
106
            self.execute(self.calculate_energy + " > ASE.TM.energy.out")
107
            # check for convergence of dscf cycle
108
            if os.path.isfile('dscf_problem'):
109
                print 'Turbomole scf energy calculation did not converge'
110
                raise RuntimeError, \
111
                    'Please run Turbomole define and come thereafter back'
112
            # read energy
113
            self.read_energy()
114
        else :
115
            print "taking old values (E)"
116
        self.update_energy = False
117
        return self.e_total
122 118

  
123 119
    def get_forces(self, atoms):
124
        self.update(atoms)
120
        # update atoms
121
        self.set_atoms(atoms)
122
        # complete energy calculations
123
        if self.update_energy:
124
            self.get_potential_energy(atoms)
125
        # if update of forces is neccessary
126
        if self.update_forces:
127
            # calculate forces
128
            self.execute(self.calculate_forces + " > ASE.TM.forces.out")
129
            # read forces
130
            self.read_forces()
131
        else :
132
            print "taking old values (F)"
133
        self.update_forces = False
125 134
        return self.forces.copy()
126 135
    
127 136
    def get_stress(self, atoms):
128
        self.update(atoms)
129 137
        return self.stress.copy()
130

  
131
    def calculate(self, atoms):
132
        """Total Turbomole energy is calculated (to file 'energy'
133
        also forces are calculated (to file 'gradient')
134
        """
135
        self.positions = atoms.get_positions().copy()
136
        self.cell = atoms.get_cell().copy()
137
        self.pbc = atoms.get_pbc().copy()
138

  
139
        #write current coordinates to file 'coord' for Turbomole
138
        
139
    def set_atoms(self, atoms):
140
        if self.atoms == atoms:
141
            return
142
        # performs an update of the atoms 
143
        super(Turbomole, self).set_atoms(atoms)
140 144
        write_turbomole('coord', atoms)
141

  
142

  
143
        #Turbomole energy calculation
144
        os.system('rm -f output.energy.dummy; \
145
                      '+ self.tm_program_energy +'> output.energy.dummy')
146

  
147
        #check that the energy run converged
148
        if os.path.isfile('dscf_problem'):
149
            print 'Turbomole scf energy calculation did not converge'
150
            print 'issue command t2x -c > last.xyz'
151
            print 'and check geometry last.xyz and job.xxx or statistics'
152
            raise RuntimeError, \
153
                'Please run Turbomole define and come thereafter back'
154

  
155

  
156
        self.read_energy()
157

  
158
        #Turbomole atomic forces calculation
159
        #killing the previous gradient file because 
160
        #turbomole gradients are affected by the previous values
161
        os.system('rm -f gradient; rm -f output.forces.dummy; \
162
                      '+ self.tm_program_forces +'> output.forces.dummy')
163

  
164
        self.read_forces(atoms)
165

  
166
        self.converged = True
167

  
145
        # energy and forces must be re-calculated
146
        self.update_energy = True
147
        self.update_forces = True
168 148
        
169 149
    def read_energy(self):
170 150
        """Read Energy from Turbomole energy file."""
......
178 158
            elif line.startswith('$'):
179 159
                pass
180 160
            else:
181
                #print 'LINE',line
161
                # print 'LINE',line
182 162
                energy_tmp = float(line.split()[1])
183
        #print 'energy_tmp',energy_tmp
184
        self.etotal = energy_tmp * Hartree
163
                if self.post_HF:
164
                    energy_tmp += float(line.split()[4])
165
        self.e_total = energy_tmp * Hartree
166
        
185 167

  
186

  
187
    def read_forces(self,atoms):
168
    def read_forces(self):
188 169
        """Read Forces from Turbomole gradient file."""
189

  
190 170
        file = open('gradient','r')
191
        line=file.readline()
192
        line=file.readline()
193
        tmpforces = np.array([[0, 0, 0]])
194
        while line:
195
            if 'cycle' in line:
196
                for i, dummy in enumerate(atoms):
197
                            line=file.readline()
198
                forces_tmp=[]
199
                for i, dummy in enumerate(atoms):
200
                            line=file.readline()
201
                            line2=string.replace(line,'D','E')
202
                            #tmp=np.append(forces_tmp,np.array\
203
                            #      ([[float(f) for f in line2.split()[0:3]]]))
204
                            tmp=np.array\
205
                                ([[float(f) for f in line2.split()[0:3]]])
206
                            tmpforces=np.concatenate((tmpforces,tmp))  
207
            line=file.readline()
208
            
171
        lines=file.readlines()
172
        file.close()
209 173

  
210
        #note the '-' sign for turbomole, to get forces
211
        self.forces = (-np.delete(tmpforces, np.s_[0:1], axis=0))*Hartree/Bohr
174
        forces = np.array([[0, 0, 0]])
175
        
176
        nline = len(lines)
177
        iline = -1
178
        
179
        for i in xrange(nline):
180
            if 'cycle' in lines[i]:
181
                iline = i
182
        
183
        if iline < 0:
184
            print 'Gradients not found'
185
            raise RuntimeError("Please check TURBOMOLE gradients")
212 186

  
213
        #print 'forces', self.forces
214

  
215
    def read(self):
216
        """Dummy stress for turbomole"""
217
        self.stress = np.empty((3, 3))
187
        iline += len(self.atoms) + 1
188
        nline -= 1
189
        for i in xrange(iline, nline):
190
            line = string.replace(lines[i],'D','E')
191
            #tmp=np.append(forces_tmp,np.array\
192
            #      ([[float(f) for f in line.split()[0:3]]]))
193
            tmp=np.array([[float(f) for f in line.split()[0:3]]])
194
            forces=np.concatenate((forces,tmp))  
195
        #note the '-' sign for turbomole, to get forces
196
        self.forces = (-np.delete(forces, np.s_[0:1], axis=0))*Hartree/Bohr
ase/calculators/general.py (revision 3)
1

  
2
class Calculator:
1
class Calculator(object):
3 2
    def __init__(self):
4 3
        return
5 4

  

Formats disponibles : Unified diff