root / ase / gui / calculator.py @ 16
Historique | Voir | Annoter | Télécharger (67,5 ko)
1 | 1 | tkerber | # encoding: utf-8
|
---|---|---|---|
2 | 1 | tkerber | "calculator.py - module for choosing a calculator."
|
3 | 1 | tkerber | |
4 | 1 | tkerber | import gtk |
5 | 1 | tkerber | import os |
6 | 1 | tkerber | import numpy as np |
7 | 1 | tkerber | from copy import copy |
8 | 1 | tkerber | from ase.gui.setupwindow import SetupWindow |
9 | 1 | tkerber | from ase.gui.progress import DefaultProgressIndicator, GpawProgressIndicator |
10 | 1 | tkerber | from ase.gui.widgets import pack, oops, cancel_apply_ok |
11 | 1 | tkerber | from ase import Atoms |
12 | 1 | tkerber | from ase.data import chemical_symbols |
13 | 1 | tkerber | import ase |
14 | 1 | tkerber | |
15 | 1 | tkerber | # Asap and GPAW may be imported if selected.
|
16 | 1 | tkerber | |
17 | 1 | tkerber | introtext = """\
|
18 | 1 | tkerber | To make most calculations on the atoms, a Calculator object must first
|
19 | 1 | tkerber | be associated with it. ASE supports a number of calculators, supporting
|
20 | 1 | tkerber | different elements, and implementing different physical models for the
|
21 | 1 | tkerber | interatomic interactions.\
|
22 | 1 | tkerber | """
|
23 | 1 | tkerber | |
24 | 1 | tkerber | # Informational text about the calculators
|
25 | 1 | tkerber | lj_info_txt = """\
|
26 | 1 | tkerber | The Lennard-Jones pair potential is one of the simplest
|
27 | 1 | tkerber | possible models for interatomic interactions, mostly
|
28 | 1 | tkerber | suitable for noble gasses and model systems.
|
29 | 1 | tkerber |
|
30 | 1 | tkerber | Interactions are described by an interaction length and an
|
31 | 1 | tkerber | interaction strength.\
|
32 | 1 | tkerber | """
|
33 | 1 | tkerber | |
34 | 1 | tkerber | emt_info_txt = """\
|
35 | 1 | tkerber | The EMT potential is a many-body potential, giving a
|
36 | 1 | tkerber | good description of the late transition metals crystalling
|
37 | 1 | tkerber | in the FCC crystal structure. The elements described by the
|
38 | 1 | tkerber | main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and
|
39 | 1 | tkerber | Au, the Al potential is however not suitable for materials
|
40 | 1 | tkerber | science application, as the stacking fault energy is wrong.
|
41 | 1 | tkerber |
|
42 | 1 | tkerber | A number of parameter sets are provided.
|
43 | 1 | tkerber |
|
44 | 1 | tkerber | <b>Default parameters:</b>
|
45 | 1 | tkerber |
|
46 | 1 | tkerber | The default EMT parameters, as published in K. W. Jacobsen,
|
47 | 1 | tkerber | P. Stoltze and J. K. Nørskov, <i>Surf. Sci.</i> <b>366</b>, 394 (1996).
|
48 | 1 | tkerber |
|
49 | 1 | tkerber | <b>Alternative Cu, Ag and Au:</b>
|
50 | 1 | tkerber |
|
51 | 1 | tkerber | An alternative set of parameters for Cu, Ag and Au,
|
52 | 1 | tkerber | reoptimized to experimental data including the stacking
|
53 | 1 | tkerber | fault energies by Torben Rasmussen (partly unpublished).
|
54 | 1 | tkerber |
|
55 | 1 | tkerber | <b>Ruthenium:</b>
|
56 | 1 | tkerber |
|
57 | 1 | tkerber | Parameters for Ruthenium, as published in J. Gavnholt and
|
58 | 1 | tkerber | J. Schiøtz, <i>Phys. Rev. B</i> <b>77</b>, 035404 (2008).
|
59 | 1 | tkerber |
|
60 | 1 | tkerber | <b>Metallic glasses:</b>
|
61 | 1 | tkerber |
|
62 | 1 | tkerber | Parameters for MgCu and CuZr metallic glasses. MgCu
|
63 | 1 | tkerber | parameters are in N. P. Bailey, J. Schiøtz and
|
64 | 1 | tkerber | K. W. Jacobsen, <i>Phys. Rev. B</i> <b>69</b>, 144205 (2004).
|
65 | 1 | tkerber | CuZr in A. Paduraru, A. Kenoufi, N. P. Bailey and
|
66 | 1 | tkerber | J. Schiøtz, <i>Adv. Eng. Mater.</i> <b>9</b>, 505 (2007).
|
67 | 1 | tkerber | """
|
68 | 1 | tkerber | |
69 | 1 | tkerber | aseemt_info_txt = """\
|
70 | 1 | tkerber | The EMT potential is a many-body potential, giving a
|
71 | 1 | tkerber | good description of the late transition metals crystalling
|
72 | 1 | tkerber | in the FCC crystal structure. The elements described by the
|
73 | 1 | tkerber | main set of EMT parameters are Al, Ni, Cu, Pd, Ag, Pt, and
|
74 | 1 | tkerber | Au. In addition, this implementation allows for the use of
|
75 | 1 | tkerber | H, N, O and C adatoms, although the description of these is
|
76 | 1 | tkerber | most likely not very good.
|
77 | 1 | tkerber |
|
78 | 1 | tkerber | <b>This is the ASE implementation of EMT.</b> For large
|
79 | 1 | tkerber | simulations the ASAP implementation is more suitable; this
|
80 | 1 | tkerber | implementation is mainly to make EMT available when ASAP is
|
81 | 1 | tkerber | not installed.
|
82 | 1 | tkerber | """
|
83 | 1 | tkerber | |
84 | 1 | tkerber | brenner_info_txt = """\
|
85 | 1 | tkerber | The Brenner potential is a reactive bond-order potential for
|
86 | 1 | tkerber | carbon and hydrocarbons. As a bond-order potential, it takes
|
87 | 1 | tkerber | into account that carbon orbitals can hybridize in different
|
88 | 1 | tkerber | ways, and that carbon can form single, double and triple
|
89 | 1 | tkerber | bonds. That the potential is reactive means that it can
|
90 | 1 | tkerber | handle gradual changes in the bond order as chemical bonds
|
91 | 1 | tkerber | are formed or broken.
|
92 | 1 | tkerber |
|
93 | 1 | tkerber | The Brenner potential is implemented in Asap, based on a
|
94 | 1 | tkerber | C implentation published at http://www.rahul.net/pcm/brenner/ .
|
95 | 1 | tkerber |
|
96 | 1 | tkerber | The potential is documented here:
|
97 | 1 | tkerber | Donald W Brenner, Olga A Shenderova, Judith A Harrison,
|
98 | 1 | tkerber | Steven J Stuart, Boris Ni and Susan B Sinnott:
|
99 | 1 | tkerber | "A second-generation reactive empirical bond order (REBO)
|
100 | 1 | tkerber | potential energy expression for hydrocarbons",
|
101 | 1 | tkerber | J. Phys.: Condens. Matter 14 (2002) 783-802.
|
102 | 1 | tkerber | doi: 10.1088/0953-8984/14/4/312
|
103 | 1 | tkerber | """
|
104 | 1 | tkerber | |
105 | 1 | tkerber | |
106 | 1 | tkerber | gpaw_info_txt = """\
|
107 | 1 | tkerber | GPAW implements Density Functional Theory using a
|
108 | 1 | tkerber | <b>G</b>rid-based real-space representation of the wave
|
109 | 1 | tkerber | functions, and the <b>P</b>rojector <b>A</b>ugmented <b>W</b>ave
|
110 | 1 | tkerber | method for handling the core regions.
|
111 | 1 | tkerber | """
|
112 | 1 | tkerber | |
113 | 1 | tkerber | aims_info_txt = """\
|
114 | 1 | tkerber | FHI-aims is an external package implementing density
|
115 | 1 | tkerber | functional theory and quantum chemical methods using
|
116 | 1 | tkerber | all-electron methods and a numeric local orbital basis set.
|
117 | 1 | tkerber | For full details, see http://www.fhi-berlin.mpg.de/aims/
|
118 | 1 | tkerber | or Comp. Phys. Comm. v180 2175 (2009). The ASE
|
119 | 1 | tkerber | documentation contains information on the keywords and
|
120 | 1 | tkerber | functionalities available within this interface.
|
121 | 1 | tkerber | """
|
122 | 1 | tkerber | |
123 | 1 | tkerber | aims_pbc_warning_text = """\
|
124 | 1 | tkerber | WARNING:
|
125 | 1 | tkerber | Your system seems to have more than zero but less than
|
126 | 1 | tkerber | three periodic dimensions. Please check that this is
|
127 | 1 | tkerber | really what you want to compute. Assuming full
|
128 | 1 | tkerber | 3D periodicity for this calculator."""
|
129 | 1 | tkerber | |
130 | 1 | tkerber | vasp_info_txt = """\
|
131 | 1 | tkerber | VASP is an external package implementing density
|
132 | 1 | tkerber | functional functional theory using pseudopotentials
|
133 | 1 | tkerber | or the projector-augmented wave method together
|
134 | 1 | tkerber | with a plane wave basis set. For full details, see
|
135 | 1 | tkerber | http://cms.mpi.univie.ac.at/vasp/vasp/
|
136 | 1 | tkerber | """
|
137 | 1 | tkerber | |
138 | 1 | tkerber | emt_parameters = ( |
139 | 1 | tkerber | ("Default (Al, Ni, Cu, Pd, Ag, Pt, Au)", None), |
140 | 1 | tkerber | ("Alternative Cu, Ag and Au", "EMTRasmussenParameters"), |
141 | 1 | tkerber | ("Ruthenium", "EMThcpParameters"), |
142 | 1 | tkerber | ("CuMg and CuZr metallic glass", "EMTMetalGlassParameters") |
143 | 1 | tkerber | ) |
144 | 1 | tkerber | |
145 | 1 | tkerber | class SetCalculator(SetupWindow): |
146 | 1 | tkerber | "Window for selecting a calculator."
|
147 | 1 | tkerber | |
148 | 1 | tkerber | # List the names of the radio button attributes
|
149 | 1 | tkerber | radios = ("none", "lj", "emt", "aseemt", "brenner", "gpaw", "aims", "vasp") |
150 | 1 | tkerber | # List the names of the parameter dictionaries
|
151 | 1 | tkerber | paramdicts = ("lj_parameters",)
|
152 | 1 | tkerber | # The name used to store parameters on the gui object
|
153 | 1 | tkerber | classname = "SetCalculator"
|
154 | 1 | tkerber | |
155 | 1 | tkerber | def __init__(self, gui): |
156 | 1 | tkerber | SetupWindow.__init__(self)
|
157 | 1 | tkerber | self.set_title("Select calculator") |
158 | 1 | tkerber | vbox = gtk.VBox() |
159 | 1 | tkerber | |
160 | 1 | tkerber | # Intoductory text
|
161 | 1 | tkerber | self.packtext(vbox, introtext)
|
162 | 1 | tkerber | |
163 | 1 | tkerber | pack(vbox, [gtk.Label("Calculator:")])
|
164 | 1 | tkerber | |
165 | 1 | tkerber | # No calculator (the default)
|
166 | 1 | tkerber | self.none_radio = gtk.RadioButton(None, "None") |
167 | 1 | tkerber | pack(vbox, [self.none_radio])
|
168 | 1 | tkerber | |
169 | 1 | tkerber | # Lennard-Jones
|
170 | 1 | tkerber | self.lj_radio = gtk.RadioButton(self.none_radio, "Lennard-Jones (ASAP)") |
171 | 1 | tkerber | self.lj_setup = gtk.Button("Setup") |
172 | 1 | tkerber | self.lj_info = InfoButton(lj_info_txt)
|
173 | 1 | tkerber | self.lj_setup.connect("clicked", self.lj_setup_window) |
174 | 1 | tkerber | self.pack_line(vbox, self.lj_radio, self.lj_setup, self.lj_info) |
175 | 1 | tkerber | |
176 | 1 | tkerber | # EMT
|
177 | 1 | tkerber | self.emt_radio = gtk.RadioButton(
|
178 | 1 | tkerber | self.none_radio, "EMT - Effective Medium Theory (ASAP)") |
179 | 1 | tkerber | self.emt_setup = gtk.combo_box_new_text()
|
180 | 1 | tkerber | self.emt_param_info = {}
|
181 | 1 | tkerber | for p in emt_parameters: |
182 | 1 | tkerber | self.emt_setup.append_text(p[0]) |
183 | 1 | tkerber | self.emt_param_info[p[0]] = p[1] |
184 | 1 | tkerber | self.emt_setup.set_active(0) |
185 | 1 | tkerber | self.emt_info = InfoButton(emt_info_txt)
|
186 | 1 | tkerber | self.pack_line(vbox, self.emt_radio, self.emt_setup, self.emt_info) |
187 | 1 | tkerber | |
188 | 1 | tkerber | # EMT (ASE implementation)
|
189 | 1 | tkerber | self.aseemt_radio = gtk.RadioButton(
|
190 | 1 | tkerber | self.none_radio, "EMT - Effective Medium Theory (ASE)") |
191 | 1 | tkerber | self.aseemt_info = InfoButton(aseemt_info_txt)
|
192 | 1 | tkerber | self.pack_line(vbox, self.aseemt_radio, None, self.aseemt_info) |
193 | 1 | tkerber | |
194 | 1 | tkerber | # Brenner potential
|
195 | 1 | tkerber | self.brenner_radio = gtk.RadioButton(
|
196 | 1 | tkerber | self.none_radio, "Brenner Potential (ASAP)") |
197 | 1 | tkerber | self.brenner_info = InfoButton(brenner_info_txt)
|
198 | 1 | tkerber | self.pack_line(vbox, self.brenner_radio, None, self.brenner_info) |
199 | 1 | tkerber | |
200 | 1 | tkerber | # GPAW
|
201 | 1 | tkerber | self.gpaw_radio = gtk.RadioButton(self.none_radio, |
202 | 1 | tkerber | "Density Functional Theory (GPAW)")
|
203 | 1 | tkerber | self.gpaw_setup = gtk.Button("Setup") |
204 | 1 | tkerber | self.gpaw_info = InfoButton(gpaw_info_txt)
|
205 | 1 | tkerber | self.gpaw_setup.connect("clicked", self.gpaw_setup_window) |
206 | 1 | tkerber | self.pack_line(vbox, self.gpaw_radio, self.gpaw_setup, self.gpaw_info) |
207 | 1 | tkerber | |
208 | 1 | tkerber | # FHI-aims
|
209 | 1 | tkerber | self.aims_radio = gtk.RadioButton(self.none_radio, |
210 | 1 | tkerber | "Density Functional Theory (FHI-aims)")
|
211 | 1 | tkerber | self.aims_setup = gtk.Button("Setup") |
212 | 1 | tkerber | self.aims_info = InfoButton(aims_info_txt)
|
213 | 1 | tkerber | self.aims_setup.connect("clicked", self.aims_setup_window) |
214 | 1 | tkerber | self.pack_line(vbox, self.aims_radio, self.aims_setup, self.aims_info) |
215 | 1 | tkerber | |
216 | 1 | tkerber | # VASP
|
217 | 1 | tkerber | self.vasp_radio = gtk.RadioButton(self.none_radio, |
218 | 1 | tkerber | "Density Functional Theory (VASP)")
|
219 | 1 | tkerber | self.vasp_setup = gtk.Button("Setup") |
220 | 1 | tkerber | self.vasp_info = InfoButton(vasp_info_txt)
|
221 | 1 | tkerber | self.vasp_setup.connect("clicked", self.vasp_setup_window) |
222 | 1 | tkerber | self.pack_line(vbox, self.vasp_radio, self.vasp_setup, self.vasp_info) |
223 | 1 | tkerber | |
224 | 1 | tkerber | # Buttons etc.
|
225 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
226 | 1 | tkerber | buts = cancel_apply_ok(cancel=lambda widget: self.destroy(), |
227 | 1 | tkerber | apply=self.apply,
|
228 | 1 | tkerber | ok=self.ok)
|
229 | 1 | tkerber | pack(vbox, [buts], end=True, bottom=True) |
230 | 1 | tkerber | self.check = gtk.CheckButton("Check that the calculator is reasonable.") |
231 | 1 | tkerber | self.check.set_active(True) |
232 | 1 | tkerber | fr = gtk.Frame() |
233 | 1 | tkerber | fr.add(self.check)
|
234 | 1 | tkerber | fr.show_all() |
235 | 1 | tkerber | pack(vbox, [fr], end=True, bottom=True) |
236 | 1 | tkerber | |
237 | 1 | tkerber | # Finalize setup
|
238 | 1 | tkerber | self.add(vbox)
|
239 | 1 | tkerber | vbox.show() |
240 | 1 | tkerber | self.show()
|
241 | 1 | tkerber | self.gui = gui
|
242 | 1 | tkerber | self.load_state()
|
243 | 1 | tkerber | |
244 | 1 | tkerber | def pack_line(self, box, radio, setup, info): |
245 | 1 | tkerber | hbox = gtk.HBox() |
246 | 1 | tkerber | hbox.pack_start(radio, 0, 0) |
247 | 1 | tkerber | hbox.pack_start(gtk.Label(" "), 0, 0) |
248 | 1 | tkerber | hbox.pack_end(info, 0, 0) |
249 | 1 | tkerber | if setup is not None: |
250 | 1 | tkerber | radio.connect("toggled", self.radio_toggled, setup) |
251 | 1 | tkerber | setup.set_sensitive(False)
|
252 | 1 | tkerber | hbox.pack_end(setup, 0, 0) |
253 | 1 | tkerber | hbox.show_all() |
254 | 1 | tkerber | box.pack_start(hbox, 0, 0) |
255 | 1 | tkerber | |
256 | 1 | tkerber | def radio_toggled(self, radio, button): |
257 | 1 | tkerber | button.set_sensitive(radio.get_active()) |
258 | 1 | tkerber | |
259 | 1 | tkerber | def lj_setup_window(self, widget): |
260 | 1 | tkerber | if not self.get_atoms(): |
261 | 1 | tkerber | return
|
262 | 1 | tkerber | lj_param = getattr(self, "lj_parameters", None) |
263 | 1 | tkerber | LJ_Window(self, lj_param, "lj_parameters") |
264 | 1 | tkerber | # When control is retuned, self.lj_parameters has been set.
|
265 | 1 | tkerber | |
266 | 1 | tkerber | def gpaw_setup_window(self, widget): |
267 | 1 | tkerber | if not self.get_atoms(): |
268 | 1 | tkerber | return
|
269 | 1 | tkerber | gpaw_param = getattr(self, "gpaw_parameters", None) |
270 | 1 | tkerber | GPAW_Window(self, gpaw_param, "gpaw_parameters") |
271 | 1 | tkerber | # When control is retuned, self.gpaw_parameters has been set.
|
272 | 1 | tkerber | |
273 | 1 | tkerber | def aims_setup_window(self, widget): |
274 | 1 | tkerber | if not self.get_atoms(): |
275 | 1 | tkerber | return
|
276 | 1 | tkerber | aims_param = getattr(self, "aims_parameters", None) |
277 | 1 | tkerber | AIMS_Window(self, aims_param, "aims_parameters") |
278 | 1 | tkerber | # When control is retuned, self.aims_parameters has been set.
|
279 | 1 | tkerber | |
280 | 1 | tkerber | def vasp_setup_window(self, widget): |
281 | 1 | tkerber | if not self.get_atoms(): |
282 | 1 | tkerber | return
|
283 | 1 | tkerber | vasp_param = getattr(self, "vasp_parameters", None) |
284 | 1 | tkerber | VASP_Window(self, vasp_param, "vasp_parameters") |
285 | 1 | tkerber | # When control is retuned, self.vasp_parameters has been set.
|
286 | 1 | tkerber | |
287 | 1 | tkerber | def get_atoms(self): |
288 | 1 | tkerber | "Make an atoms object from the active image"
|
289 | 1 | tkerber | images = self.gui.images
|
290 | 1 | tkerber | if images.natoms < 1: |
291 | 1 | tkerber | oops("No atoms present")
|
292 | 1 | tkerber | return False |
293 | 1 | tkerber | self.atoms = Atoms(positions=images.P[0], symbols=images.Z, |
294 | 1 | tkerber | cell=images.A[0], pbc=images.pbc)
|
295 | 1 | tkerber | if not images.dynamic.all(): |
296 | 1 | tkerber | from ase.constraints import FixAtoms |
297 | 1 | tkerber | self.atoms.set_constraint(FixAtoms(mask=1-images.dynamic)) |
298 | 1 | tkerber | return True |
299 | 1 | tkerber | |
300 | 1 | tkerber | def apply(self, *widget): |
301 | 1 | tkerber | if self.do_apply(): |
302 | 1 | tkerber | self.save_state()
|
303 | 1 | tkerber | return True |
304 | 1 | tkerber | else:
|
305 | 1 | tkerber | return False |
306 | 1 | tkerber | |
307 | 1 | tkerber | def do_apply(self): |
308 | 1 | tkerber | nochk = not self.check.get_active() |
309 | 1 | tkerber | self.gui.simulation["progress"] = DefaultProgressIndicator() |
310 | 1 | tkerber | if self.none_radio.get_active(): |
311 | 1 | tkerber | self.gui.simulation['calc'] = None |
312 | 1 | tkerber | return True |
313 | 1 | tkerber | elif self.lj_radio.get_active(): |
314 | 1 | tkerber | if nochk or self.lj_check(): |
315 | 1 | tkerber | self.choose_lj()
|
316 | 1 | tkerber | return True |
317 | 1 | tkerber | elif self.emt_radio.get_active(): |
318 | 1 | tkerber | if nochk or self.emt_check(): |
319 | 1 | tkerber | self.choose_emt()
|
320 | 1 | tkerber | return True |
321 | 1 | tkerber | elif self.aseemt_radio.get_active(): |
322 | 1 | tkerber | if nochk or self.aseemt_check(): |
323 | 1 | tkerber | self.choose_aseemt()
|
324 | 1 | tkerber | return True |
325 | 1 | tkerber | elif self.brenner_radio.get_active(): |
326 | 1 | tkerber | if nochk or self.brenner_check(): |
327 | 1 | tkerber | self.choose_brenner()
|
328 | 1 | tkerber | return True |
329 | 1 | tkerber | elif self.gpaw_radio.get_active(): |
330 | 1 | tkerber | if nochk or self.gpaw_check(): |
331 | 1 | tkerber | self.choose_gpaw()
|
332 | 1 | tkerber | return True |
333 | 1 | tkerber | elif self.aims_radio.get_active(): |
334 | 1 | tkerber | if nochk or self.aims_check(): |
335 | 1 | tkerber | self.choose_aims()
|
336 | 1 | tkerber | return True |
337 | 1 | tkerber | elif self.vasp_radio.get_active(): |
338 | 1 | tkerber | if nochk or self.vasp_check(): |
339 | 1 | tkerber | self.choose_vasp()
|
340 | 1 | tkerber | return True |
341 | 1 | tkerber | return False |
342 | 1 | tkerber | |
343 | 1 | tkerber | def ok(self, *widget): |
344 | 1 | tkerber | if self.apply(): |
345 | 1 | tkerber | self.destroy()
|
346 | 1 | tkerber | |
347 | 1 | tkerber | def save_state(self): |
348 | 1 | tkerber | state = {} |
349 | 1 | tkerber | for r in self.radios: |
350 | 1 | tkerber | radiobutton = getattr(self, r+"_radio") |
351 | 1 | tkerber | if radiobutton.get_active():
|
352 | 1 | tkerber | state["radio"] = r
|
353 | 1 | tkerber | state["emtsetup"] = self.emt_setup.get_active() |
354 | 1 | tkerber | state["check"] = self.check.get_active() |
355 | 1 | tkerber | for p in self.paramdicts: |
356 | 1 | tkerber | if hasattr(self, p): |
357 | 1 | tkerber | state[p] = getattr(self, p) |
358 | 1 | tkerber | self.gui.module_state[self.classname] = state |
359 | 1 | tkerber | |
360 | 1 | tkerber | def load_state(self): |
361 | 1 | tkerber | try:
|
362 | 1 | tkerber | state = self.gui.module_state[self.classname] |
363 | 1 | tkerber | except KeyError: |
364 | 1 | tkerber | return
|
365 | 1 | tkerber | r = state["radio"]
|
366 | 1 | tkerber | radiobutton = getattr(self, r+"_radio") |
367 | 1 | tkerber | radiobutton.set_active(True)
|
368 | 1 | tkerber | self.emt_setup.set_active(state["emtsetup"]) |
369 | 1 | tkerber | self.check.set_active(state["check"]) |
370 | 1 | tkerber | for p in self.paramdicts: |
371 | 1 | tkerber | if state.has_key(p):
|
372 | 1 | tkerber | setattr(self, p, state[p]) |
373 | 1 | tkerber | |
374 | 1 | tkerber | def lj_check(self): |
375 | 1 | tkerber | try:
|
376 | 1 | tkerber | import asap3 |
377 | 1 | tkerber | except ImportError: |
378 | 1 | tkerber | oops("ASAP is not installed. (Failed to import asap3)")
|
379 | 1 | tkerber | return False |
380 | 1 | tkerber | if not hasattr(self, "lj_parameters"): |
381 | 1 | tkerber | oops("You must set up the Lennard-Jones parameters")
|
382 | 1 | tkerber | return False |
383 | 1 | tkerber | try:
|
384 | 1 | tkerber | self.atoms.set_calculator(asap3.LennardJones(**self.lj_parameters)) |
385 | 1 | tkerber | except (asap3.AsapError, TypeError, ValueError), e: |
386 | 1 | tkerber | oops("Could not create useful Lennard-Jones calculator.",
|
387 | 1 | tkerber | str(e))
|
388 | 1 | tkerber | return False |
389 | 1 | tkerber | return True |
390 | 1 | tkerber | |
391 | 1 | tkerber | def choose_lj(self): |
392 | 1 | tkerber | # Define a function on the fly!
|
393 | 1 | tkerber | import asap3 |
394 | 1 | tkerber | def lj_factory(p=self.lj_parameters, lj=asap3.LennardJones): |
395 | 1 | tkerber | return lj(**p)
|
396 | 1 | tkerber | self.gui.simulation["calc"] = lj_factory |
397 | 1 | tkerber | |
398 | 1 | tkerber | def emt_get(self): |
399 | 1 | tkerber | import asap3 |
400 | 1 | tkerber | provider_name = self.emt_setup.get_active_text()
|
401 | 1 | tkerber | provider = self.emt_param_info[provider_name]
|
402 | 1 | tkerber | if provider is not None: |
403 | 1 | tkerber | provider = getattr(asap3, provider)
|
404 | 1 | tkerber | return (asap3.EMT, provider, asap3)
|
405 | 1 | tkerber | |
406 | 1 | tkerber | def emt_check(self): |
407 | 1 | tkerber | if not self.get_atoms(): |
408 | 1 | tkerber | return False |
409 | 1 | tkerber | try:
|
410 | 1 | tkerber | emt, provider, asap3 = self.emt_get()
|
411 | 1 | tkerber | except ImportError: |
412 | 1 | tkerber | oops("ASAP is not installed. (Failed to import asap3)")
|
413 | 1 | tkerber | return False |
414 | 1 | tkerber | try:
|
415 | 1 | tkerber | if provider is not None: |
416 | 1 | tkerber | self.atoms.set_calculator(emt(provider()))
|
417 | 1 | tkerber | else:
|
418 | 1 | tkerber | self.atoms.set_calculator(emt())
|
419 | 1 | tkerber | except (asap3.AsapError, TypeError, ValueError), e: |
420 | 1 | tkerber | oops("Could not attach EMT calculator to the atoms.",
|
421 | 1 | tkerber | str(e))
|
422 | 1 | tkerber | return False |
423 | 1 | tkerber | return True |
424 | 1 | tkerber | |
425 | 1 | tkerber | def choose_emt(self): |
426 | 1 | tkerber | emt, provider, asap3 = self.emt_get()
|
427 | 1 | tkerber | if provider is None: |
428 | 1 | tkerber | emt_factory = emt |
429 | 1 | tkerber | else:
|
430 | 1 | tkerber | def emt_factory(emt=emt, prov=provider): |
431 | 1 | tkerber | return emt(prov())
|
432 | 1 | tkerber | self.gui.simulation["calc"] = emt_factory |
433 | 1 | tkerber | |
434 | 1 | tkerber | def aseemt_check(self): |
435 | 1 | tkerber | return self.element_check("ASE EMT", ['H', 'Al', 'Cu', 'Ag', 'Au', |
436 | 1 | tkerber | 'Ni', 'Pd', 'Pt', 'C', 'N', 'O']) |
437 | 1 | tkerber | |
438 | 1 | tkerber | def choose_aseemt(self): |
439 | 1 | tkerber | self.gui.simulation["calc"] = ase.EMT |
440 | 1 | tkerber | ase.EMT.disabled = False # In case Asap has been imported. |
441 | 1 | tkerber | |
442 | 1 | tkerber | def brenner_check(self): |
443 | 1 | tkerber | try:
|
444 | 1 | tkerber | import asap3 |
445 | 1 | tkerber | except ImportError: |
446 | 1 | tkerber | oops("ASAP is not installed. (Failed to import asap3)")
|
447 | 1 | tkerber | return False |
448 | 1 | tkerber | return self.element_check("Brenner potential", ['H', 'C', 'Si']) |
449 | 1 | tkerber | |
450 | 1 | tkerber | def choose_brenner(self): |
451 | 1 | tkerber | import asap3 |
452 | 1 | tkerber | self.gui.simulation["calc"] = asap3.BrennerPotential |
453 | 1 | tkerber | |
454 | 1 | tkerber | def choose_aseemt(self): |
455 | 1 | tkerber | self.gui.simulation["calc"] = ase.EMT |
456 | 1 | tkerber | ase.EMT.disabled = False # In case Asap has been imported. |
457 | 1 | tkerber | |
458 | 1 | tkerber | def gpaw_check(self): |
459 | 1 | tkerber | try:
|
460 | 1 | tkerber | import gpaw |
461 | 1 | tkerber | except ImportError: |
462 | 1 | tkerber | oops("GPAW is not installed. (Failed to import gpaw)")
|
463 | 1 | tkerber | return False |
464 | 1 | tkerber | if not hasattr(self, "gpaw_parameters"): |
465 | 1 | tkerber | oops("You must set up the GPAW parameters")
|
466 | 1 | tkerber | return False |
467 | 1 | tkerber | return True |
468 | 1 | tkerber | |
469 | 1 | tkerber | def choose_gpaw(self): |
470 | 1 | tkerber | # This reuses the same GPAW object.
|
471 | 1 | tkerber | try:
|
472 | 1 | tkerber | import gpaw |
473 | 1 | tkerber | except ImportError: |
474 | 1 | tkerber | oops("GPAW is not installed. (Failed to import gpaw)")
|
475 | 1 | tkerber | return False |
476 | 1 | tkerber | p = self.gpaw_parameters
|
477 | 1 | tkerber | use = ["xc", "kpts", "mode"] |
478 | 1 | tkerber | if p["use_h"]: |
479 | 1 | tkerber | use.append("h")
|
480 | 1 | tkerber | else:
|
481 | 1 | tkerber | use.append("gpts")
|
482 | 1 | tkerber | if p["mode"] == "lcao": |
483 | 1 | tkerber | use.append("basis")
|
484 | 1 | tkerber | gpaw_param = {} |
485 | 1 | tkerber | for s in use: |
486 | 1 | tkerber | gpaw_param[s] = p[s] |
487 | 1 | tkerber | if p["use mixer"]: |
488 | 1 | tkerber | mx = getattr(gpaw, p["mixer"]) |
489 | 1 | tkerber | mx_args = {} |
490 | 1 | tkerber | mx_arg_n = ["beta", "nmaxold", "weight"] |
491 | 1 | tkerber | if p["mixer"] == "MixerDiff": |
492 | 1 | tkerber | mx_arg_n.extend(["beta_m", "nmaxold_m", "weight_m"]) |
493 | 1 | tkerber | for s in mx_arg_n: |
494 | 1 | tkerber | mx_args[s] = p[s] |
495 | 1 | tkerber | gpaw_param["mixer"] = mx(**mx_args)
|
496 | 1 | tkerber | progress = GpawProgressIndicator() |
497 | 1 | tkerber | self.gui.simulation["progress"] = progress |
498 | 1 | tkerber | gpaw_param["txt"] = progress.get_gpaw_stream()
|
499 | 1 | tkerber | gpaw_calc = gpaw.GPAW(**gpaw_param) |
500 | 1 | tkerber | def gpaw_factory(calc = gpaw_calc): |
501 | 1 | tkerber | return calc
|
502 | 1 | tkerber | self.gui.simulation["calc"] = gpaw_factory |
503 | 1 | tkerber | |
504 | 1 | tkerber | def aims_check(self): |
505 | 1 | tkerber | if not hasattr(self, "aims_parameters"): |
506 | 1 | tkerber | oops("You must set up the FHI-aims parameters")
|
507 | 1 | tkerber | return False |
508 | 1 | tkerber | return True |
509 | 1 | tkerber | |
510 | 1 | tkerber | def choose_aims(self): |
511 | 1 | tkerber | param = self.aims_parameters
|
512 | 1 | tkerber | from ase.calculators.aims import Aims |
513 | 1 | tkerber | calc_aims = Aims(**param) |
514 | 1 | tkerber | def aims_factory(calc = calc_aims): |
515 | 1 | tkerber | return calc
|
516 | 1 | tkerber | self.gui.simulation["calc"] = aims_factory |
517 | 1 | tkerber | |
518 | 1 | tkerber | def vasp_check(self): |
519 | 1 | tkerber | if not hasattr(self, "vasp_parameters"): |
520 | 1 | tkerber | oops("You must set up the VASP parameters")
|
521 | 1 | tkerber | return False |
522 | 1 | tkerber | return True |
523 | 1 | tkerber | |
524 | 1 | tkerber | def choose_vasp(self): |
525 | 1 | tkerber | param = self.vasp_parameters
|
526 | 1 | tkerber | from ase.calculators.vasp import Vasp |
527 | 1 | tkerber | calc_vasp = Vasp(**param) |
528 | 1 | tkerber | def vasp_factory(calc = calc_vasp): |
529 | 1 | tkerber | return calc
|
530 | 1 | tkerber | self.gui.simulation["calc"] = vasp_factory |
531 | 1 | tkerber | |
532 | 1 | tkerber | def element_check(self, name, elements): |
533 | 1 | tkerber | "Check that all atoms are allowed"
|
534 | 1 | tkerber | elements = [ase.data.atomic_numbers[s] for s in elements] |
535 | 1 | tkerber | elements_dict = {} |
536 | 1 | tkerber | for e in elements: |
537 | 1 | tkerber | elements_dict[e] = True
|
538 | 1 | tkerber | if not self.get_atoms(): |
539 | 1 | tkerber | return False |
540 | 1 | tkerber | try:
|
541 | 1 | tkerber | for e in self.atoms.get_atomic_numbers(): |
542 | 1 | tkerber | elements_dict[e] |
543 | 1 | tkerber | except KeyError: |
544 | 1 | tkerber | oops("Element %s is not allowed by the '%s' calculator"
|
545 | 1 | tkerber | % (ase.data.chemical_symbols[e], name)) |
546 | 1 | tkerber | return False |
547 | 1 | tkerber | return True |
548 | 1 | tkerber | |
549 | 1 | tkerber | class InfoButton(gtk.Button): |
550 | 1 | tkerber | def __init__(self, txt): |
551 | 1 | tkerber | gtk.Button.__init__(self, "Info") |
552 | 1 | tkerber | self.txt = txt
|
553 | 1 | tkerber | self.connect('clicked', self.run) |
554 | 1 | tkerber | |
555 | 1 | tkerber | def run(self, widget): |
556 | 1 | tkerber | dialog = gtk.MessageDialog(flags=gtk.DIALOG_MODAL, |
557 | 1 | tkerber | type=gtk.MESSAGE_INFO, |
558 | 1 | tkerber | buttons=gtk.BUTTONS_CLOSE) |
559 | 1 | tkerber | dialog.set_markup(self.txt)
|
560 | 1 | tkerber | dialog.connect('response', lambda x, y: dialog.destroy()) |
561 | 1 | tkerber | dialog.show() |
562 | 1 | tkerber | |
563 | 1 | tkerber | |
564 | 1 | tkerber | class LJ_Window(gtk.Window): |
565 | 1 | tkerber | def __init__(self, owner, param, attrname): |
566 | 1 | tkerber | gtk.Window.__init__(self)
|
567 | 1 | tkerber | self.set_title("Lennard-Jones parameters") |
568 | 1 | tkerber | self.owner = owner
|
569 | 1 | tkerber | self.attrname = attrname
|
570 | 1 | tkerber | atoms = owner.atoms |
571 | 1 | tkerber | atnos = atoms.get_atomic_numbers() |
572 | 1 | tkerber | found = {} |
573 | 1 | tkerber | for z in atnos: |
574 | 1 | tkerber | found[z] = True
|
575 | 1 | tkerber | self.present = found.keys()
|
576 | 1 | tkerber | self.present.sort() # Sorted list of atomic numbers |
577 | 1 | tkerber | nelem = len(self.present) |
578 | 1 | tkerber | vbox = gtk.VBox() |
579 | 1 | tkerber | label = gtk.Label("Specify the Lennard-Jones parameters here")
|
580 | 1 | tkerber | pack(vbox, [label]) |
581 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
582 | 1 | tkerber | pack(vbox, [gtk.Label("Epsilon (eV):")])
|
583 | 1 | tkerber | tbl, self.epsilon_adj = self.makematrix(self.present) |
584 | 1 | tkerber | pack(vbox, [tbl]) |
585 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
586 | 1 | tkerber | pack(vbox, [gtk.Label("Sigma (Å):")])
|
587 | 1 | tkerber | tbl, self.sigma_adj = self.makematrix(self.present) |
588 | 1 | tkerber | pack(vbox, [tbl]) |
589 | 1 | tkerber | self.modif = gtk.CheckButton("Shift to make smooth at cutoff") |
590 | 1 | tkerber | self.modif.set_active(True) |
591 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
592 | 1 | tkerber | pack(vbox, self.modif)
|
593 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
594 | 1 | tkerber | butbox = gtk.HButtonBox() |
595 | 1 | tkerber | cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL) |
596 | 1 | tkerber | cancel_but.connect('clicked', lambda widget: self.destroy()) |
597 | 1 | tkerber | ok_but = gtk.Button(stock=gtk.STOCK_OK) |
598 | 1 | tkerber | ok_but.connect('clicked', self.ok) |
599 | 1 | tkerber | butbox.pack_start(cancel_but, 0, 0) |
600 | 1 | tkerber | butbox.pack_start(ok_but, 0, 0) |
601 | 1 | tkerber | butbox.show_all() |
602 | 1 | tkerber | pack(vbox, [butbox], end=True, bottom=True) |
603 | 1 | tkerber | vbox.show() |
604 | 1 | tkerber | self.add(vbox)
|
605 | 1 | tkerber | |
606 | 1 | tkerber | # Now, set the parameters
|
607 | 1 | tkerber | if param and param['elements'] == self.present: |
608 | 1 | tkerber | self.set_param(self.epsilon_adj, param["epsilon"], nelem) |
609 | 1 | tkerber | self.set_param(self.sigma_adj, param["sigma"], nelem) |
610 | 1 | tkerber | self.modif.set_active(param["modified"]) |
611 | 1 | tkerber | |
612 | 1 | tkerber | self.show()
|
613 | 1 | tkerber | self.grab_add() # Lock all other windows |
614 | 1 | tkerber | |
615 | 1 | tkerber | def makematrix(self, present): |
616 | 1 | tkerber | nelem = len(present)
|
617 | 1 | tkerber | adjdict = {} |
618 | 1 | tkerber | tbl = gtk.Table(2+nelem, 2+nelem) |
619 | 1 | tkerber | for i in range(nelem): |
620 | 1 | tkerber | s = chemical_symbols[present[i]] |
621 | 1 | tkerber | tbl.attach(gtk.Label(" " + str(present[i])), 0, 1, i, i+1) |
622 | 1 | tkerber | tbl.attach(gtk.Label(" "+s+" "), 1, 2, i, i+1) |
623 | 1 | tkerber | tbl.attach(gtk.Label(str(present[i])), i+2, i+3, 1+nelem, 2+nelem) |
624 | 1 | tkerber | tbl.attach(gtk.Label(s), i+2, i+3, nelem, 1+nelem) |
625 | 1 | tkerber | for j in range(i+1): |
626 | 1 | tkerber | adj = gtk.Adjustment(1.0, 0.0, 100.0, 0.1) |
627 | 1 | tkerber | spin = gtk.SpinButton(adj, 0.1, 3) |
628 | 1 | tkerber | tbl.attach(spin, 2+j, 3+j, i, i+1) |
629 | 1 | tkerber | adjdict[(i,j)] = adj |
630 | 1 | tkerber | tbl.show_all() |
631 | 1 | tkerber | return tbl, adjdict
|
632 | 1 | tkerber | |
633 | 1 | tkerber | def set_param(self, adj, params, n): |
634 | 1 | tkerber | for i in range(n): |
635 | 1 | tkerber | for j in range(n): |
636 | 1 | tkerber | if j <= i:
|
637 | 1 | tkerber | adj[(i,j)].value = params[i,j] |
638 | 1 | tkerber | |
639 | 1 | tkerber | def get_param(self, adj, params, n): |
640 | 1 | tkerber | for i in range(n): |
641 | 1 | tkerber | for j in range(n): |
642 | 1 | tkerber | if j <= i:
|
643 | 1 | tkerber | params[i,j] = params[j,i] = adj[(i,j)].value |
644 | 1 | tkerber | |
645 | 1 | tkerber | |
646 | 1 | tkerber | def destroy(self): |
647 | 1 | tkerber | self.grab_remove()
|
648 | 1 | tkerber | gtk.Window.destroy(self)
|
649 | 1 | tkerber | |
650 | 1 | tkerber | def ok(self, *args): |
651 | 1 | tkerber | params = {} |
652 | 1 | tkerber | params["elements"] = copy(self.present) |
653 | 1 | tkerber | n = len(self.present) |
654 | 1 | tkerber | eps = np.zeros((n,n)) |
655 | 1 | tkerber | self.get_param(self.epsilon_adj, eps, n) |
656 | 1 | tkerber | sigma = np.zeros((n,n)) |
657 | 1 | tkerber | self.get_param(self.sigma_adj, sigma, n) |
658 | 1 | tkerber | params["epsilon"] = eps
|
659 | 1 | tkerber | params["sigma"] = sigma
|
660 | 1 | tkerber | params["modified"] = self.modif.get_active() |
661 | 1 | tkerber | setattr(self.owner, self.attrname, params) |
662 | 1 | tkerber | self.destroy()
|
663 | 1 | tkerber | |
664 | 1 | tkerber | |
665 | 1 | tkerber | class GPAW_Window(gtk.Window): |
666 | 1 | tkerber | gpaw_xc_list = ['LDA', 'PBE', 'RPBE', 'revPBE'] |
667 | 1 | tkerber | gpaw_xc_default = 'PBE'
|
668 | 1 | tkerber | def __init__(self, owner, param, attrname): |
669 | 1 | tkerber | gtk.Window.__init__(self)
|
670 | 1 | tkerber | self.set_title("GPAW parameters") |
671 | 1 | tkerber | self.owner = owner
|
672 | 1 | tkerber | self.attrname = attrname
|
673 | 1 | tkerber | atoms = owner.atoms |
674 | 1 | tkerber | self.ucell = atoms.get_cell()
|
675 | 1 | tkerber | self.size = tuple([self.ucell[i,i] for i in range(3)]) |
676 | 1 | tkerber | self.pbc = atoms.get_pbc()
|
677 | 1 | tkerber | self.orthogonal = self.isorthogonal(self.ucell) |
678 | 1 | tkerber | self.natoms = len(atoms) |
679 | 1 | tkerber | |
680 | 1 | tkerber | vbox = gtk.VBox() |
681 | 1 | tkerber | #label = gtk.Label("Specify the GPAW parameters here")
|
682 | 1 | tkerber | #pack(vbox, [label])
|
683 | 1 | tkerber | |
684 | 1 | tkerber | # Print some info
|
685 | 1 | tkerber | txt = "%i atoms.\n" % (self.natoms,) |
686 | 1 | tkerber | if self.orthogonal: |
687 | 1 | tkerber | txt += "Orthogonal unit cell: %.2f x %.2f x %.2f Å." % self.size |
688 | 1 | tkerber | else:
|
689 | 1 | tkerber | txt += "Non-orthogonal unit cell:\n"
|
690 | 1 | tkerber | txt += str(self.ucell) |
691 | 1 | tkerber | pack(vbox, [gtk.Label(txt)]) |
692 | 1 | tkerber | |
693 | 1 | tkerber | # XC potential
|
694 | 1 | tkerber | self.xc = gtk.combo_box_new_text()
|
695 | 1 | tkerber | for i, x in enumerate(self.gpaw_xc_list): |
696 | 1 | tkerber | self.xc.append_text(x)
|
697 | 1 | tkerber | if x == self.gpaw_xc_default: |
698 | 1 | tkerber | self.xc.set_active(i)
|
699 | 1 | tkerber | pack(vbox, [gtk.Label("Exchange-correlation functional: "),
|
700 | 1 | tkerber | self.xc])
|
701 | 1 | tkerber | |
702 | 1 | tkerber | # Grid spacing
|
703 | 1 | tkerber | self.radio_h = gtk.RadioButton(None, "Grid spacing") |
704 | 1 | tkerber | self.h = gtk.Adjustment(0.18, 0.0, 1.0, 0.01) |
705 | 1 | tkerber | self.h_spin = gtk.SpinButton(self.h, 0, 2) |
706 | 1 | tkerber | pack(vbox, [self.radio_h, gtk.Label(" h = "), self.h_spin, |
707 | 1 | tkerber | gtk.Label("Å")])
|
708 | 1 | tkerber | self.radio_gpts = gtk.RadioButton(self.radio_h, "Grid points") |
709 | 1 | tkerber | self.gpts = []
|
710 | 1 | tkerber | self.gpts_spin = []
|
711 | 1 | tkerber | for i in range(3): |
712 | 1 | tkerber | g = gtk.Adjustment(4, 4, 1000, 4) |
713 | 1 | tkerber | s = gtk.SpinButton(g, 0, 0) |
714 | 1 | tkerber | self.gpts.append(g)
|
715 | 1 | tkerber | self.gpts_spin.append(s)
|
716 | 1 | tkerber | self.gpts_hlabel = gtk.Label("") |
717 | 1 | tkerber | self.gpts_hlabel_format = "h<sub>eff</sub> = (%.3f, %.3f, %.3f) Å" |
718 | 1 | tkerber | pack(vbox, [self.radio_gpts, gtk.Label(" gpts = ("), self.gpts_spin[0], |
719 | 1 | tkerber | gtk.Label(", "), self.gpts_spin[1], gtk.Label(", "), |
720 | 1 | tkerber | self.gpts_spin[2], gtk.Label(") "), self.gpts_hlabel]) |
721 | 1 | tkerber | self.radio_h.connect("toggled", self.radio_grid_toggled) |
722 | 1 | tkerber | self.radio_gpts.connect("toggled", self.radio_grid_toggled) |
723 | 1 | tkerber | self.radio_grid_toggled(None) |
724 | 1 | tkerber | for g in self.gpts: |
725 | 1 | tkerber | g.connect("value-changed", self.gpts_changed) |
726 | 1 | tkerber | self.h.connect("value-changed", self.h_changed) |
727 | 1 | tkerber | |
728 | 1 | tkerber | # K-points
|
729 | 1 | tkerber | self.kpts = []
|
730 | 1 | tkerber | self.kpts_spin = []
|
731 | 1 | tkerber | for i in range(3): |
732 | 1 | tkerber | if self.pbc[i] and self.orthogonal: |
733 | 1 | tkerber | default = np.ceil(20.0 / self.size[i]) |
734 | 1 | tkerber | else:
|
735 | 1 | tkerber | default = 1
|
736 | 1 | tkerber | g = gtk.Adjustment(default, 1, 100, 1) |
737 | 1 | tkerber | s = gtk.SpinButton(g, 0, 0) |
738 | 1 | tkerber | self.kpts.append(g)
|
739 | 1 | tkerber | self.kpts_spin.append(s)
|
740 | 1 | tkerber | if not self.pbc[i]: |
741 | 1 | tkerber | s.set_sensitive(False)
|
742 | 1 | tkerber | g.connect("value-changed", self.k_changed) |
743 | 1 | tkerber | pack(vbox, [gtk.Label("k-points k = ("), self.kpts_spin[0], |
744 | 1 | tkerber | gtk.Label(", "), self.kpts_spin[1], gtk.Label(", "), |
745 | 1 | tkerber | self.kpts_spin[2], gtk.Label(")")]) |
746 | 1 | tkerber | self.kpts_label = gtk.Label("") |
747 | 1 | tkerber | self.kpts_label_format = "k-points x size: (%.1f, %.1f, %.1f) Å" |
748 | 1 | tkerber | pack(vbox, [self.kpts_label])
|
749 | 1 | tkerber | self.k_changed()
|
750 | 1 | tkerber | |
751 | 1 | tkerber | # Spin polarized
|
752 | 1 | tkerber | self.spinpol = gtk.CheckButton("Spin polarized") |
753 | 1 | tkerber | pack(vbox, [self.spinpol])
|
754 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
755 | 1 | tkerber | |
756 | 1 | tkerber | # Mode and basis functions
|
757 | 1 | tkerber | self.mode = gtk.combo_box_new_text()
|
758 | 1 | tkerber | self.mode.append_text("FD - Finite Difference (grid) mode") |
759 | 1 | tkerber | self.mode.append_text("LCAO - Linear Combination of Atomic Orbitals") |
760 | 1 | tkerber | self.mode.set_active(0) |
761 | 1 | tkerber | pack(vbox, [gtk.Label("Mode: "), self.mode]) |
762 | 1 | tkerber | self.basis = gtk.combo_box_new_text()
|
763 | 1 | tkerber | self.basis.append_text("sz - Single Zeta") |
764 | 1 | tkerber | self.basis.append_text("szp - Single Zeta polarized") |
765 | 1 | tkerber | self.basis.append_text("dzp - Double Zeta polarized") |
766 | 1 | tkerber | self.basis.set_active(2) # dzp |
767 | 1 | tkerber | pack(vbox, [gtk.Label("Basis functions: "), self.basis]) |
768 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
769 | 1 | tkerber | self.mode.connect("changed", self.mode_changed) |
770 | 1 | tkerber | self.mode_changed()
|
771 | 1 | tkerber | |
772 | 1 | tkerber | # Mixer
|
773 | 1 | tkerber | self.use_mixer = gtk.CheckButton("Non-standard mixer parameters") |
774 | 1 | tkerber | pack(vbox, [self.use_mixer])
|
775 | 1 | tkerber | self.radio_mixer = gtk.RadioButton(None, "Mixer ") |
776 | 1 | tkerber | self.radio_mixersum = gtk.RadioButton(self.radio_mixer, "MixerSum ") |
777 | 1 | tkerber | self.radio_mixerdiff = gtk.RadioButton(self.radio_mixer, "MixerDiff") |
778 | 1 | tkerber | pack(vbox, [self.radio_mixer, self.radio_mixersum, |
779 | 1 | tkerber | self.radio_mixerdiff])
|
780 | 1 | tkerber | self.beta_adj = gtk.Adjustment(0.25, 0.0, 1.0, 0.05) |
781 | 1 | tkerber | self.beta_spin = gtk.SpinButton(self.beta_adj, 0, 2) |
782 | 1 | tkerber | self.nmaxold_adj = gtk.Adjustment(3, 1, 10, 1) |
783 | 1 | tkerber | self.nmaxold_spin = gtk.SpinButton(self.nmaxold_adj, 0, 0) |
784 | 1 | tkerber | self.weight_adj = gtk.Adjustment(50, 1, 500, 1) |
785 | 1 | tkerber | self.weight_spin = gtk.SpinButton(self.weight_adj, 0, 0) |
786 | 1 | tkerber | pack(vbox, [gtk.Label("beta = "), self.beta_spin, |
787 | 1 | tkerber | gtk.Label(" nmaxold = "), self.nmaxold_spin, |
788 | 1 | tkerber | gtk.Label(" weight = "), self.weight_spin]) |
789 | 1 | tkerber | self.beta_m_adj = gtk.Adjustment(0.70, 0.0, 1.0, 0.05) |
790 | 1 | tkerber | self.beta_m_spin = gtk.SpinButton(self.beta_m_adj, 0, 2) |
791 | 1 | tkerber | self.nmaxold_m_adj = gtk.Adjustment(2, 1, 10, 1) |
792 | 1 | tkerber | self.nmaxold_m_spin = gtk.SpinButton(self.nmaxold_m_adj, 0, 0) |
793 | 1 | tkerber | self.weight_m_adj = gtk.Adjustment(10, 1, 500, 1) |
794 | 1 | tkerber | self.weight_m_spin = gtk.SpinButton(self.weight_m_adj, 0, 0) |
795 | 1 | tkerber | pack(vbox, [gtk.Label("beta_m = "), self.beta_m_spin, |
796 | 1 | tkerber | gtk.Label(" nmaxold_m = "), self.nmaxold_m_spin, |
797 | 1 | tkerber | gtk.Label(" weight_m = "), self.weight_m_spin]) |
798 | 1 | tkerber | for but in (self.spinpol, self.use_mixer, self.radio_mixer, |
799 | 1 | tkerber | self.radio_mixersum, self.radio_mixerdiff): |
800 | 1 | tkerber | but.connect("clicked", self.mixer_changed) |
801 | 1 | tkerber | self.mixer_changed()
|
802 | 1 | tkerber | |
803 | 1 | tkerber | # Eigensolver
|
804 | 1 | tkerber | # Poisson-solver
|
805 | 1 | tkerber | |
806 | 1 | tkerber | vbox.show() |
807 | 1 | tkerber | self.add(vbox)
|
808 | 1 | tkerber | |
809 | 1 | tkerber | # Buttons at the bottom
|
810 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
811 | 1 | tkerber | butbox = gtk.HButtonBox() |
812 | 1 | tkerber | cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL) |
813 | 1 | tkerber | cancel_but.connect('clicked', lambda widget: self.destroy()) |
814 | 1 | tkerber | ok_but = gtk.Button(stock=gtk.STOCK_OK) |
815 | 1 | tkerber | ok_but.connect('clicked', self.ok) |
816 | 1 | tkerber | butbox.pack_start(cancel_but, 0, 0) |
817 | 1 | tkerber | butbox.pack_start(ok_but, 0, 0) |
818 | 1 | tkerber | butbox.show_all() |
819 | 1 | tkerber | pack(vbox, [butbox], end=True, bottom=True) |
820 | 1 | tkerber | |
821 | 1 | tkerber | # Set stored parameters
|
822 | 1 | tkerber | if param:
|
823 | 1 | tkerber | self.xc.set_active(param["xc#"]) |
824 | 1 | tkerber | if param["use_h"]: |
825 | 1 | tkerber | self.radio_h.set_active(True) |
826 | 1 | tkerber | else:
|
827 | 1 | tkerber | self.radio_gpts.set_active(True) |
828 | 1 | tkerber | for i in range(3): |
829 | 1 | tkerber | self.gpts[i].value = param["gpts"][i] |
830 | 1 | tkerber | self.kpts[i].value = param["kpts"][i] |
831 | 1 | tkerber | self.spinpol.set_active(param["spinpol"]) |
832 | 1 | tkerber | self.mode.set_active(param["mode#"]) |
833 | 1 | tkerber | self.basis.set_active(param["basis#"]) |
834 | 1 | tkerber | self.use_mixer.set_active(param["use mixer"]) |
835 | 1 | tkerber | getattr(self, "radio_"+param["mixer"].lower()).set_active(True) |
836 | 1 | tkerber | for t in ("beta", "nmaxold", "weight", "beta_m", "nmaxold_m", |
837 | 1 | tkerber | "weight_m"):
|
838 | 1 | tkerber | getattr(self, t+"_adj").value = param[t] |
839 | 1 | tkerber | |
840 | 1 | tkerber | self.show()
|
841 | 1 | tkerber | self.grab_add() # Lock all other windows |
842 | 1 | tkerber | |
843 | 1 | tkerber | def radio_grid_toggled(self, widget): |
844 | 1 | tkerber | hmode = self.radio_h.get_active()
|
845 | 1 | tkerber | self.h_spin.set_sensitive(hmode)
|
846 | 1 | tkerber | for s in self.gpts_spin: |
847 | 1 | tkerber | s.set_sensitive(not hmode)
|
848 | 1 | tkerber | self.gpts_changed()
|
849 | 1 | tkerber | |
850 | 1 | tkerber | def gpts_changed(self, *args): |
851 | 1 | tkerber | if self.radio_gpts.get_active(): |
852 | 1 | tkerber | g = np.array([int(g.value) for g in self.gpts]) |
853 | 1 | tkerber | size = np.array([self.ucell[i,i] for i in range(3)]) |
854 | 1 | tkerber | txt = self.gpts_hlabel_format % tuple(size / g) |
855 | 1 | tkerber | self.gpts_hlabel.set_markup(txt)
|
856 | 1 | tkerber | else:
|
857 | 1 | tkerber | self.gpts_hlabel.set_markup("") |
858 | 1 | tkerber | |
859 | 1 | tkerber | def h_changed(self, *args): |
860 | 1 | tkerber | h = self.h.value
|
861 | 1 | tkerber | for i in range(3): |
862 | 1 | tkerber | g = 4 * round(self.ucell[i,i] / (4*h)) |
863 | 1 | tkerber | self.gpts[i].value = g
|
864 | 1 | tkerber | |
865 | 1 | tkerber | def k_changed(self, *args): |
866 | 1 | tkerber | if self.orthogonal: |
867 | 1 | tkerber | size = [self.kpts[i].value * self.size[i] for i in range(3)] |
868 | 1 | tkerber | self.kpts_label.set_text(self.kpts_label_format % tuple(size)) |
869 | 1 | tkerber | |
870 | 1 | tkerber | def mode_changed(self, *args): |
871 | 1 | tkerber | self.basis.set_sensitive(self.mode.get_active() == 1) |
872 | 1 | tkerber | |
873 | 1 | tkerber | def mixer_changed(self, *args): |
874 | 1 | tkerber | radios = (self.radio_mixer, self.radio_mixersum, self.radio_mixerdiff) |
875 | 1 | tkerber | spin1 = (self.beta_spin, self.nmaxold_spin, self.weight_spin) |
876 | 1 | tkerber | spin2 = (self.beta_m_spin, self.nmaxold_m_spin, self.weight_m_spin) |
877 | 1 | tkerber | if self.use_mixer.get_active(): |
878 | 1 | tkerber | # Mixer parameters can be specified.
|
879 | 1 | tkerber | if self.spinpol.get_active(): |
880 | 1 | tkerber | self.radio_mixer.set_sensitive(False) |
881 | 1 | tkerber | self.radio_mixersum.set_sensitive(True) |
882 | 1 | tkerber | self.radio_mixerdiff.set_sensitive(True) |
883 | 1 | tkerber | if self.radio_mixer.get_active(): |
884 | 1 | tkerber | self.radio_mixersum.set_active(True) |
885 | 1 | tkerber | else:
|
886 | 1 | tkerber | self.radio_mixer.set_sensitive(True) |
887 | 1 | tkerber | self.radio_mixersum.set_sensitive(False) |
888 | 1 | tkerber | self.radio_mixerdiff.set_sensitive(False) |
889 | 1 | tkerber | self.radio_mixer.set_active(True) |
890 | 1 | tkerber | if self.radio_mixerdiff.get_active(): |
891 | 1 | tkerber | active = spin1 + spin2 |
892 | 1 | tkerber | passive = () |
893 | 1 | tkerber | else:
|
894 | 1 | tkerber | active = spin1 |
895 | 1 | tkerber | passive = spin2 |
896 | 1 | tkerber | for widget in active: |
897 | 1 | tkerber | widget.set_sensitive(True)
|
898 | 1 | tkerber | for widget in passive: |
899 | 1 | tkerber | widget.set_sensitive(False)
|
900 | 1 | tkerber | else:
|
901 | 1 | tkerber | # No mixer parameters
|
902 | 1 | tkerber | for widget in radios + spin1 + spin2: |
903 | 1 | tkerber | widget.set_sensitive(False)
|
904 | 1 | tkerber | |
905 | 1 | tkerber | def isorthogonal(self, matrix): |
906 | 1 | tkerber | ortho = True
|
907 | 1 | tkerber | for i in range(3): |
908 | 1 | tkerber | for j in range(3): |
909 | 1 | tkerber | if i != j and matrix[i][j] != 0.0: |
910 | 1 | tkerber | ortho = False
|
911 | 1 | tkerber | return ortho
|
912 | 1 | tkerber | |
913 | 1 | tkerber | def ok(self, *args): |
914 | 1 | tkerber | param = {} |
915 | 1 | tkerber | param["xc"] = self.xc.get_active_text() |
916 | 1 | tkerber | param["xc#"] = self.xc.get_active() |
917 | 1 | tkerber | param["use_h"] = self.radio_h.get_active() |
918 | 1 | tkerber | param["h"] = self.h.value |
919 | 1 | tkerber | param["gpts"] = [int(g.value) for g in self.gpts] |
920 | 1 | tkerber | param["kpts"] = [int(k.value) for k in self.kpts] |
921 | 1 | tkerber | param["spinpol"] = self.spinpol.get_active() |
922 | 1 | tkerber | param["mode"] = self.mode.get_active_text().split()[0].lower() |
923 | 1 | tkerber | param["mode#"] = self.mode.get_active() |
924 | 1 | tkerber | param["basis"] = self.basis.get_active_text().split()[0].lower() |
925 | 1 | tkerber | param["basis#"] = self.basis.get_active() |
926 | 1 | tkerber | param["use mixer"] = self.use_mixer.get_active() |
927 | 1 | tkerber | if self.radio_mixer.get_active(): |
928 | 1 | tkerber | m = "Mixer"
|
929 | 1 | tkerber | elif self.radio_mixersum.get_active(): |
930 | 1 | tkerber | m = "MixerSum"
|
931 | 1 | tkerber | else:
|
932 | 1 | tkerber | assert self.radio_mixerdiff.get_active() |
933 | 1 | tkerber | m = "MixerDiff"
|
934 | 1 | tkerber | param["mixer"] = m
|
935 | 1 | tkerber | for t in ("beta", "nmaxold", "weight", "beta_m", "nmaxold_m", |
936 | 1 | tkerber | "weight_m"):
|
937 | 1 | tkerber | param[t] = getattr(self, t+"_adj").value |
938 | 1 | tkerber | setattr(self.owner, self.attrname, param) |
939 | 1 | tkerber | self.destroy()
|
940 | 1 | tkerber | |
941 | 1 | tkerber | class AIMS_Window(gtk.Window): |
942 | 1 | tkerber | aims_xc_cluster = ['pw-lda','pz-lda','pbe','pbesol','rpbe','revpbe', |
943 | 1 | tkerber | 'blyp','am05','b3lyp','hse03','hse06','pbe0','pbesol0', |
944 | 1 | tkerber | 'hf','mp2'] |
945 | 1 | tkerber | aims_xc_periodic = ['pw-lda','pz-lda','pbe','pbesol','rpbe','revpbe', |
946 | 1 | tkerber | 'blyp','am05'] |
947 | 1 | tkerber | aims_xc_default = 'pbe'
|
948 | 1 | tkerber | aims_relativity_list = ['none','atomic_zora','zora'] |
949 | 1 | tkerber | aims_keyword_gui_list = ['xc','vdw_correction_hirshfeld','k_grid','spin','charge','relativistic', |
950 | 1 | tkerber | 'sc_accuracy_etot','sc_accuracy_eev','sc_accuracy_rho','sc_accuracy_forces', |
951 | 1 | tkerber | 'compute_forces','run_command','species_dir'] |
952 | 1 | tkerber | def __init__(self, owner, param, attrname): |
953 | 1 | tkerber | self.owner = owner
|
954 | 1 | tkerber | self.attrname = attrname
|
955 | 1 | tkerber | atoms = owner.atoms |
956 | 1 | tkerber | self.periodic = atoms.get_pbc().all()
|
957 | 1 | tkerber | if not self.periodic and atoms.get_pbc().any(): |
958 | 1 | tkerber | aims_periodic_warning = True
|
959 | 1 | tkerber | self.periodic = True |
960 | 1 | tkerber | else:
|
961 | 1 | tkerber | aims_periodic_warning = False
|
962 | 1 | tkerber | from ase.calculators.aims import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,input_keys |
963 | 1 | tkerber | self.aims_keyword_list =float_keys+exp_keys+string_keys+int_keys+bool_keys+list_keys+input_keys
|
964 | 1 | tkerber | self.expert_keywords = []
|
965 | 1 | tkerber | |
966 | 1 | tkerber | natoms = len(atoms)
|
967 | 1 | tkerber | gtk.Window.__init__(self)
|
968 | 1 | tkerber | self.set_title("FHI-aims parameters") |
969 | 1 | tkerber | vbox = gtk.VBox() |
970 | 1 | tkerber | # Print some info
|
971 | 1 | tkerber | txt = "%i atoms.\n" % (natoms)
|
972 | 1 | tkerber | if self.periodic: |
973 | 1 | tkerber | self.ucell = atoms.get_cell()
|
974 | 1 | tkerber | txt += "Periodic geometry, unit cell is: \n"
|
975 | 1 | tkerber | for i in range(3): |
976 | 1 | tkerber | txt += "(%8.3f %8.3f %8.3f)\n" % (self.ucell[i][0], self.ucell[i][1], self.ucell[i][2]) |
977 | 1 | tkerber | self.xc_list = self.aims_xc_periodic |
978 | 1 | tkerber | else:
|
979 | 1 | tkerber | txt += "Non-periodic geometry. \n"
|
980 | 1 | tkerber | self.xc_list = self.aims_xc_cluster |
981 | 1 | tkerber | pack(vbox, [gtk.Label(txt)]) |
982 | 1 | tkerber | |
983 | 1 | tkerber | # XC functional & dispersion correction
|
984 | 1 | tkerber | self.xc = gtk.combo_box_new_text()
|
985 | 1 | tkerber | self.xc_setup = False |
986 | 1 | tkerber | self.TS = gtk.CheckButton("Hirshfeld-based dispersion correction") |
987 | 1 | tkerber | pack(vbox, [gtk.Label("Exchange-correlation functional: "),self.xc]) |
988 | 1 | tkerber | pack(vbox, [self.TS])
|
989 | 1 | tkerber | pack(vbox, [gtk.Label("")])
|
990 | 1 | tkerber | |
991 | 1 | tkerber | # k-grid?
|
992 | 1 | tkerber | if self.periodic: |
993 | 1 | tkerber | self.kpts = []
|
994 | 1 | tkerber | self.kpts_spin = []
|
995 | 1 | tkerber | for i in range(3): |
996 | 1 | tkerber | default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i]))) |
997 | 1 | tkerber | g = gtk.Adjustment(default, 1, 100, 1) |
998 | 1 | tkerber | s = gtk.SpinButton(g, 0, 0) |
999 | 1 | tkerber | self.kpts.append(g)
|
1000 | 1 | tkerber | self.kpts_spin.append(s)
|
1001 | 1 | tkerber | g.connect("value-changed", self.k_changed) |
1002 | 1 | tkerber | pack(vbox, [gtk.Label("k-points k = ("), self.kpts_spin[0], |
1003 | 1 | tkerber | gtk.Label(", "), self.kpts_spin[1], gtk.Label(", "), |
1004 | 1 | tkerber | self.kpts_spin[2], gtk.Label(")")]) |
1005 | 1 | tkerber | self.kpts_label = gtk.Label("") |
1006 | 1 | tkerber | self.kpts_label_format = "k-points x size: (%.1f, %.1f, %.1f) Å" |
1007 | 1 | tkerber | pack(vbox, [self.kpts_label])
|
1008 | 1 | tkerber | self.k_changed()
|
1009 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1010 | 1 | tkerber | |
1011 | 1 | tkerber | # Spin polarized, charge, relativity
|
1012 | 1 | tkerber | self.spinpol = gtk.CheckButton("Spin polarized") |
1013 | 1 | tkerber | self.charge = gtk.Adjustment(0,-100,100,0.1) |
1014 | 1 | tkerber | self.charge_spin = gtk.SpinButton(self.charge, 0, 0) |
1015 | 1 | tkerber | self.charge_spin.set_digits(2) |
1016 | 1 | tkerber | self.relativity_type = gtk.combo_box_new_text()
|
1017 | 1 | tkerber | for i, x in enumerate(self.aims_relativity_list): |
1018 | 1 | tkerber | self.relativity_type.append_text(x)
|
1019 | 1 | tkerber | self.relativity_type.connect('changed',self.relativity_changed) |
1020 | 1 | tkerber | self.relativity_threshold = gtk.Entry(max=8) |
1021 | 1 | tkerber | self.relativity_threshold.set_text('1.00e-12') |
1022 | 1 | tkerber | self.relativity_threshold.set_sensitive(False) |
1023 | 1 | tkerber | pack(vbox, [self.spinpol,
|
1024 | 1 | tkerber | gtk.Label(" Charge"),
|
1025 | 1 | tkerber | self.charge_spin,
|
1026 | 1 | tkerber | gtk.Label(" Relativity"),
|
1027 | 1 | tkerber | self.relativity_type,
|
1028 | 1 | tkerber | gtk.Label(" Threshold"),
|
1029 | 1 | tkerber | self.relativity_threshold])
|
1030 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1031 | 1 | tkerber | |
1032 | 1 | tkerber | # self-consistency criteria
|
1033 | 1 | tkerber | pack(vbox,[gtk.Label("Self-consistency convergence:")])
|
1034 | 1 | tkerber | self.sc_tot_energy = gtk.Adjustment(1e-6, 1e-6, 1e0, 1e-6) |
1035 | 1 | tkerber | self.sc_tot_energy_spin = gtk.SpinButton(self.sc_tot_energy, 0, 0) |
1036 | 1 | tkerber | self.sc_tot_energy_spin.set_digits(6) |
1037 | 1 | tkerber | self.sc_tot_energy_spin.set_numeric(True) |
1038 | 1 | tkerber | self.sc_sum_eigenvalue = gtk.Adjustment(1e-3, 1e-6, 1e0, 1e-6) |
1039 | 1 | tkerber | self.sc_sum_eigenvalue_spin = gtk.SpinButton(self.sc_sum_eigenvalue, 0, 0) |
1040 | 1 | tkerber | self.sc_sum_eigenvalue_spin.set_digits(6) |
1041 | 1 | tkerber | self.sc_sum_eigenvalue_spin.set_numeric(True) |
1042 | 1 | tkerber | self.sc_density = gtk.Adjustment(1e-4, 1e-6, 1e0, 1e-6) |
1043 | 1 | tkerber | self.sc_density_spin = gtk.SpinButton(self.sc_density, 0, 0) |
1044 | 1 | tkerber | self.sc_density_spin.set_digits(6) |
1045 | 1 | tkerber | self.sc_density_spin.set_numeric(True) |
1046 | 1 | tkerber | self.compute_forces = gtk.CheckButton("Compute forces") |
1047 | 1 | tkerber | self.compute_forces.set_active(True) |
1048 | 1 | tkerber | self.compute_forces.connect("toggled", self.compute_forces_toggled,"") |
1049 | 1 | tkerber | self.sc_forces = gtk.Adjustment(1e-4, 1e-6, 1e0, 1e-6) |
1050 | 1 | tkerber | self.sc_forces_spin = gtk.SpinButton(self.sc_forces, 0, 0) |
1051 | 1 | tkerber | self.sc_forces_spin.set_numeric(True) |
1052 | 1 | tkerber | self.sc_forces_spin.set_digits(6) |
1053 | 1 | tkerber | pack(vbox, [gtk.Label("Energy: "),
|
1054 | 1 | tkerber | self.sc_tot_energy_spin,
|
1055 | 1 | tkerber | gtk.Label(" eV Sum of eigenvalues: "),
|
1056 | 1 | tkerber | self.sc_sum_eigenvalue_spin,
|
1057 | 1 | tkerber | gtk.Label(" eV")])
|
1058 | 1 | tkerber | pack(vbox, [gtk.Label("Electron density: "),
|
1059 | 1 | tkerber | self.sc_density_spin,
|
1060 | 1 | tkerber | gtk.Label(" Force convergence: "),
|
1061 | 1 | tkerber | self.sc_forces_spin,
|
1062 | 1 | tkerber | gtk.Label(" eV/Ang ")])
|
1063 | 1 | tkerber | |
1064 | 1 | tkerber | pack(vbox, [self.compute_forces])
|
1065 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1066 | 1 | tkerber | |
1067 | 1 | tkerber | self.expert_keyword_set = gtk.Entry(max = 55) |
1068 | 1 | tkerber | self.expert_keyword_add = gtk.Button(stock = gtk.STOCK_ADD)
|
1069 | 1 | tkerber | self.expert_keyword_add.connect("clicked", self.expert_keyword_import) |
1070 | 1 | tkerber | self.expert_keyword_set.connect("activate", self.expert_keyword_import) |
1071 | 1 | tkerber | pack(vbox,[gtk.Label("Additional keywords: "),
|
1072 | 1 | tkerber | self.expert_keyword_set,
|
1073 | 1 | tkerber | self.expert_keyword_add])
|
1074 | 1 | tkerber | self.expert_vbox = gtk.VBox()
|
1075 | 1 | tkerber | pack(vbox, self.expert_vbox)
|
1076 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1077 | 1 | tkerber | |
1078 | 1 | tkerber | # run command and species defaults:
|
1079 | 1 | tkerber | pack(vbox, gtk.Label('FHI-aims execution command: '))
|
1080 | 1 | tkerber | self.run_command = pack(vbox, gtk.Entry(max=0)) |
1081 | 1 | tkerber | pack(vbox, gtk.Label('Directory for species defaults: '))
|
1082 | 1 | tkerber | self.species_defaults = pack(vbox, gtk.Entry(max=0)) |
1083 | 1 | tkerber | |
1084 | 1 | tkerber | # set defaults from previous instance of the calculator, if applicable:
|
1085 | 1 | tkerber | if param is not None: |
1086 | 1 | tkerber | self.set_param(param)
|
1087 | 1 | tkerber | else:
|
1088 | 1 | tkerber | self.set_defaults()
|
1089 | 1 | tkerber | |
1090 | 1 | tkerber | # Buttons at the bottom
|
1091 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1092 | 1 | tkerber | butbox = gtk.HButtonBox() |
1093 | 1 | tkerber | default_but = gtk.Button("Set Defaults")
|
1094 | 1 | tkerber | default_but.connect("clicked",self.set_defaults) |
1095 | 1 | tkerber | import_control_but = gtk.Button("Import control.in")
|
1096 | 1 | tkerber | import_control_but.connect("clicked",self.import_control) |
1097 | 1 | tkerber | export_control_but = gtk.Button("Export control.in")
|
1098 | 1 | tkerber | export_control_but.connect("clicked", self.export_control) |
1099 | 1 | tkerber | cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL) |
1100 | 1 | tkerber | cancel_but.connect('clicked', lambda widget: self.destroy()) |
1101 | 1 | tkerber | ok_but = gtk.Button(stock=gtk.STOCK_OK) |
1102 | 1 | tkerber | ok_but.connect('clicked', self.ok) |
1103 | 1 | tkerber | butbox.pack_start(default_but, 0, 0) |
1104 | 1 | tkerber | butbox.pack_start(import_control_but, 0, 0) |
1105 | 1 | tkerber | butbox.pack_start(export_control_but, 0, 0) |
1106 | 1 | tkerber | butbox.pack_start(cancel_but, 0, 0) |
1107 | 1 | tkerber | butbox.pack_start(ok_but, 0, 0) |
1108 | 1 | tkerber | butbox.show_all() |
1109 | 1 | tkerber | pack(vbox, [butbox], end=True, bottom=True) |
1110 | 1 | tkerber | self.expert_vbox.show()
|
1111 | 1 | tkerber | vbox.show() |
1112 | 1 | tkerber | self.add(vbox)
|
1113 | 1 | tkerber | self.show()
|
1114 | 1 | tkerber | self.grab_add()
|
1115 | 1 | tkerber | if aims_periodic_warning:
|
1116 | 1 | tkerber | oops(aims_pbc_warning_text) |
1117 | 1 | tkerber | |
1118 | 1 | tkerber | def set_defaults(self, *args): |
1119 | 1 | tkerber | atoms = self.owner.atoms.copy()
|
1120 | 1 | tkerber | if not self.xc_setup: |
1121 | 1 | tkerber | self.xc_setup = True |
1122 | 1 | tkerber | for i, x in enumerate(self.xc_list): |
1123 | 1 | tkerber | self.xc.append_text(x)
|
1124 | 1 | tkerber | for i, x in enumerate(self.xc_list): |
1125 | 1 | tkerber | if x == self.aims_xc_default: |
1126 | 1 | tkerber | self.xc.set_active(i)
|
1127 | 1 | tkerber | self.TS.set_active(False) |
1128 | 1 | tkerber | if self.periodic: |
1129 | 1 | tkerber | self.ucell = atoms.get_cell()
|
1130 | 1 | tkerber | for i in range(3): |
1131 | 1 | tkerber | default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i]))) |
1132 | 1 | tkerber | self.kpts_spin[i].set_value(default)
|
1133 | 1 | tkerber | self.spinpol.set_active(False) |
1134 | 1 | tkerber | self.charge.set_value(0) |
1135 | 1 | tkerber | aims_relativity_default = 'none'
|
1136 | 1 | tkerber | for a in atoms: |
1137 | 1 | tkerber | if a.get_atomic_number() > 20: |
1138 | 1 | tkerber | aims_relativity_default = 'atomic_zora'
|
1139 | 1 | tkerber | for i, x in enumerate(self.aims_relativity_list): |
1140 | 1 | tkerber | if x == aims_relativity_default:
|
1141 | 1 | tkerber | self.relativity_type.set_active(i)
|
1142 | 1 | tkerber | self.sc_tot_energy.set_value(1e-6) |
1143 | 1 | tkerber | self.sc_sum_eigenvalue.set_value(1e-3) |
1144 | 1 | tkerber | self.sc_density.set_value(1e-4) |
1145 | 1 | tkerber | self.sc_forces.set_value(1e-4) |
1146 | 1 | tkerber | for key in self.expert_keywords: |
1147 | 1 | tkerber | key[0].destroy()
|
1148 | 1 | tkerber | key[1].destroy()
|
1149 | 1 | tkerber | key[2].destroy()
|
1150 | 1 | tkerber | key[3] = False |
1151 | 1 | tkerber | if os.environ.has_key('AIMS_COMMAND'): |
1152 | 1 | tkerber | text = os.environ['AIMS_COMMAND']
|
1153 | 1 | tkerber | else:
|
1154 | 1 | tkerber | text = ""
|
1155 | 1 | tkerber | self.run_command.set_text(text)
|
1156 | 1 | tkerber | if os.environ.has_key('AIMS_SPECIES_DIR'): |
1157 | 1 | tkerber | text = os.environ['AIMS_SPECIES_DIR']
|
1158 | 1 | tkerber | else:
|
1159 | 1 | tkerber | text = ""
|
1160 | 1 | tkerber | self.species_defaults.set_text(text)
|
1161 | 1 | tkerber | |
1162 | 1 | tkerber | def set_attributes(self, *args): |
1163 | 1 | tkerber | param = {} |
1164 | 1 | tkerber | param["xc"] = self.xc.get_active_text() |
1165 | 1 | tkerber | if self.periodic: |
1166 | 1 | tkerber | param["k_grid"] = (int(self.kpts[0].value), |
1167 | 1 | tkerber | int(self.kpts[1].value), |
1168 | 1 | tkerber | int(self.kpts[2].value)) |
1169 | 1 | tkerber | if self.spinpol.get_active(): |
1170 | 1 | tkerber | param["spin"] = "collinear" |
1171 | 1 | tkerber | else:
|
1172 | 1 | tkerber | param["spin"] = "none" |
1173 | 1 | tkerber | param["vdw_correction_hirshfeld"] = self.TS.get_active() |
1174 | 1 | tkerber | param["charge"] = self.charge.value |
1175 | 1 | tkerber | param["relativistic"] = self.relativity_type.get_active_text() |
1176 | 1 | tkerber | if param["relativistic"] == 'atomic_zora': |
1177 | 1 | tkerber | param["relativistic"] += " scalar " |
1178 | 1 | tkerber | if param["relativistic"] == 'zora': |
1179 | 1 | tkerber | param["relativistic"] += " scalar "+self.relativity_threshold.get_text() |
1180 | 1 | tkerber | param["sc_accuracy_etot"] = self.sc_tot_energy.value |
1181 | 1 | tkerber | param["sc_accuracy_eev"] = self.sc_sum_eigenvalue.value |
1182 | 1 | tkerber | param["sc_accuracy_rho"] = self.sc_density.value |
1183 | 1 | tkerber | param["compute_forces"] = self.compute_forces.get_active() |
1184 | 1 | tkerber | param["sc_accuracy_forces"] = self.sc_forces.value |
1185 | 1 | tkerber | param["run_command"] = self.run_command.get_text() |
1186 | 1 | tkerber | param["species_dir"] = self.species_defaults.get_text() |
1187 | 1 | tkerber | from ase.calculators.aims import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,input_keys |
1188 | 1 | tkerber | for option in self.expert_keywords: |
1189 | 1 | tkerber | if option[3]: # set type of parameter accoding to which list it is in |
1190 | 1 | tkerber | key = option[0].get_text().strip()
|
1191 | 1 | tkerber | val = option[1].get_text().strip()
|
1192 | 1 | tkerber | if key == 'output': |
1193 | 1 | tkerber | if param.has_key('output'): |
1194 | 1 | tkerber | param[key] += [val] |
1195 | 1 | tkerber | else:
|
1196 | 1 | tkerber | param[key] = [val] |
1197 | 1 | tkerber | elif key in float_keys or key in exp_keys: |
1198 | 1 | tkerber | param[key] = float(val)
|
1199 | 1 | tkerber | elif key in list_keys or key in string_keys or key in input_keys: |
1200 | 1 | tkerber | param[key] = val |
1201 | 1 | tkerber | elif key in int_keys: |
1202 | 1 | tkerber | param[key] = int(val)
|
1203 | 1 | tkerber | elif key in bool_keys: |
1204 | 1 | tkerber | param[key] = bool(val)
|
1205 | 1 | tkerber | setattr(self.owner, self.attrname, param) |
1206 | 1 | tkerber | |
1207 | 1 | tkerber | def set_param(self, param): |
1208 | 1 | tkerber | if param["xc"] is not None: |
1209 | 1 | tkerber | for i, x in enumerate(self.xc_list): |
1210 | 1 | tkerber | if x == param["xc"]: |
1211 | 1 | tkerber | self.xc.set_active(i)
|
1212 | 1 | tkerber | if isinstance(param["vdw_correction_hirshfeld"],bool): |
1213 | 1 | tkerber | self.TS.set_active(param["vdw_correction_hirshfeld"]) |
1214 | 1 | tkerber | if self.periodic and param["k_grid"] is not None: |
1215 | 1 | tkerber | self.kpts[0].value = int(param["k_grid"][0]) |
1216 | 1 | tkerber | self.kpts[1].value = int(param["k_grid"][1]) |
1217 | 1 | tkerber | self.kpts[2].value = int(param["k_grid"][2]) |
1218 | 1 | tkerber | if param["spin"] is not None: |
1219 | 1 | tkerber | self.spinpol.set_active(param["spin"] == "collinear") |
1220 | 1 | tkerber | if param["charge"] is not None: |
1221 | 1 | tkerber | self.charge.value = param["charge"] |
1222 | 1 | tkerber | if param["relativistic"] is not None: |
1223 | 1 | tkerber | if isinstance(param["relativistic"],(tuple,list)): |
1224 | 1 | tkerber | rel = param["relativistic"]
|
1225 | 1 | tkerber | else:
|
1226 | 1 | tkerber | rel = param["relativistic"].split()
|
1227 | 1 | tkerber | for i, x in enumerate(self.aims_relativity_list): |
1228 | 1 | tkerber | if x == rel[0]: |
1229 | 1 | tkerber | self.relativity_type.set_active(i)
|
1230 | 1 | tkerber | if x == 'zora': |
1231 | 1 | tkerber | self.relativity_threshold.set_text(rel[2]) |
1232 | 1 | tkerber | self.relativity_threshold.set_sensitive(True) |
1233 | 1 | tkerber | if param["sc_accuracy_etot"] is not None: |
1234 | 1 | tkerber | self.sc_tot_energy.value = param["sc_accuracy_etot"] |
1235 | 1 | tkerber | if param["sc_accuracy_eev"] is not None: |
1236 | 1 | tkerber | self.sc_sum_eigenvalue.value = param["sc_accuracy_eev"] |
1237 | 1 | tkerber | if param["sc_accuracy_rho"] is not None: |
1238 | 1 | tkerber | self.sc_density.value = param["sc_accuracy_rho"] |
1239 | 1 | tkerber | if param["compute_forces"] is not None: |
1240 | 1 | tkerber | if param["compute_forces"]: |
1241 | 1 | tkerber | if param["sc_accuracy_forces"] is not None: |
1242 | 1 | tkerber | self.sc_forces.value = param["sc_accuracy_forces"] |
1243 | 1 | tkerber | self.compute_forces.set_active(param["compute_forces"]) |
1244 | 1 | tkerber | else:
|
1245 | 1 | tkerber | self.compute_forces.set_active(False) |
1246 | 1 | tkerber | if param["run_command"] is not None: |
1247 | 1 | tkerber | self.run_command.set_text(param["run_command"]) |
1248 | 1 | tkerber | if param["species_dir"] is not None: |
1249 | 1 | tkerber | self.species_defaults.set_text(param["species_dir"]) |
1250 | 1 | tkerber | for (key,val) in param.items(): |
1251 | 1 | tkerber | if key in self.aims_keyword_list and key not in self.aims_keyword_gui_list: |
1252 | 1 | tkerber | if val is not None: # = existing "expert keyword" |
1253 | 1 | tkerber | if key == 'output': # 'output' can be used more than once |
1254 | 1 | tkerber | options = val |
1255 | 1 | tkerber | if isinstance(options,str): options = [options] |
1256 | 1 | tkerber | for arg in options: |
1257 | 1 | tkerber | self.expert_keyword_create([key]+[arg])
|
1258 | 1 | tkerber | else:
|
1259 | 1 | tkerber | if isinstance(val,str): |
1260 | 1 | tkerber | arg = [key]+val.split() |
1261 | 1 | tkerber | elif isinstance(val,(tuple,list)): |
1262 | 1 | tkerber | arg = [key]+[str(a) for a in val] |
1263 | 1 | tkerber | else:
|
1264 | 1 | tkerber | arg = [key]+[str(val)]
|
1265 | 1 | tkerber | self.expert_keyword_create(arg)
|
1266 | 1 | tkerber | |
1267 | 1 | tkerber | def ok(self, *args): |
1268 | 1 | tkerber | self.set_attributes(*args)
|
1269 | 1 | tkerber | self.destroy()
|
1270 | 1 | tkerber | |
1271 | 1 | tkerber | def export_control(self, *args): |
1272 | 1 | tkerber | filename = "control.in"
|
1273 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
1274 | 1 | tkerber | 'Export parameters ... ', None, gtk.FILE_CHOOSER_ACTION_SAVE, |
1275 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
1276 | 1 | tkerber | gtk.STOCK_SAVE, gtk.RESPONSE_OK)) |
1277 | 1 | tkerber | chooser.set_filename(filename) |
1278 | 1 | tkerber | save = chooser.run() |
1279 | 1 | tkerber | if save == gtk.RESPONSE_OK or save == gtk.RESPONSE_SAVE: |
1280 | 1 | tkerber | filename = chooser.get_filename() |
1281 | 1 | tkerber | self.set_attributes(*args)
|
1282 | 1 | tkerber | param = getattr(self.owner, "aims_parameters") |
1283 | 1 | tkerber | from ase.calculators.aims import Aims |
1284 | 1 | tkerber | calc_temp = Aims(**param) |
1285 | 1 | tkerber | atoms_temp = self.owner.atoms.copy()
|
1286 | 1 | tkerber | atoms_temp.set_calculator(calc_temp) |
1287 | 1 | tkerber | atoms_temp.calc.write_control(file = filename) |
1288 | 1 | tkerber | atoms_temp.calc.write_species(file = filename) |
1289 | 1 | tkerber | chooser.destroy() |
1290 | 1 | tkerber | |
1291 | 1 | tkerber | def import_control(self, *args): |
1292 | 1 | tkerber | filename = "control.in"
|
1293 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
1294 | 1 | tkerber | 'Import control.in file ... ', None, gtk.FILE_CHOOSER_ACTION_SAVE, |
1295 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
1296 | 1 | tkerber | gtk.STOCK_SAVE, gtk.RESPONSE_OK)) |
1297 | 1 | tkerber | chooser.set_filename(filename) |
1298 | 1 | tkerber | save = chooser.run() |
1299 | 1 | tkerber | if save == gtk.RESPONSE_OK:
|
1300 | 1 | tkerber | self.set_defaults()
|
1301 | 1 | tkerber | filename = chooser.get_filename() |
1302 | 1 | tkerber | control = open(filename,'r') |
1303 | 1 | tkerber | while True: |
1304 | 1 | tkerber | line = control.readline() |
1305 | 1 | tkerber | if not line: |
1306 | 1 | tkerber | break
|
1307 | 1 | tkerber | if "List of parameters used to initialize the calculator:" in line: |
1308 | 1 | tkerber | control.readline() |
1309 | 1 | tkerber | from ase.io.aims import read_aims_calculator |
1310 | 1 | tkerber | calc = read_aims_calculator(control) |
1311 | 1 | tkerber | found_aims_calculator = True
|
1312 | 1 | tkerber | control.close() |
1313 | 1 | tkerber | if found_aims_calculator:
|
1314 | 1 | tkerber | param = calc.float_params |
1315 | 1 | tkerber | for key in calc.exp_params: |
1316 | 1 | tkerber | param[key] = calc.exp_params[key] |
1317 | 1 | tkerber | for key in calc.string_params: |
1318 | 1 | tkerber | param[key] = calc.string_params[key] |
1319 | 1 | tkerber | for key in calc.int_params: |
1320 | 1 | tkerber | param[key] = calc.int_params[key] |
1321 | 1 | tkerber | for key in calc.bool_params: |
1322 | 1 | tkerber | param[key] = calc.bool_params[key] |
1323 | 1 | tkerber | for key in calc.list_params: |
1324 | 1 | tkerber | param[key] = calc.list_params[key] |
1325 | 1 | tkerber | for key in calc.input_parameters: |
1326 | 1 | tkerber | param[key] = calc.input_parameters[key] |
1327 | 1 | tkerber | self.set_defaults()
|
1328 | 1 | tkerber | self.set_param(param)
|
1329 | 1 | tkerber | chooser.destroy() |
1330 | 1 | tkerber | |
1331 | 1 | tkerber | def k_changed(self, *args): |
1332 | 1 | tkerber | size = [self.kpts[i].value * np.sqrt(np.vdot(self.ucell[i],self.ucell[i])) for i in range(3)] |
1333 | 1 | tkerber | self.kpts_label.set_text(self.kpts_label_format % tuple(size)) |
1334 | 1 | tkerber | |
1335 | 1 | tkerber | def compute_forces_toggled(self, *args): |
1336 | 1 | tkerber | self.sc_forces_spin.set_sensitive(self.compute_forces.get_active()) |
1337 | 1 | tkerber | |
1338 | 1 | tkerber | def relativity_changed(self, *args): |
1339 | 1 | tkerber | self.relativity_threshold.set_sensitive(self.relativity_type.get_active() == 2) |
1340 | 1 | tkerber | |
1341 | 1 | tkerber | def expert_keyword_import(self, *args): |
1342 | 1 | tkerber | command = self.expert_keyword_set.get_text().split()
|
1343 | 1 | tkerber | if len(command) > 0 and command[0] in self.aims_keyword_list and not command[0] in self.aims_keyword_gui_list: |
1344 | 1 | tkerber | self.expert_keyword_create(command)
|
1345 | 1 | tkerber | elif command[0] in self.aims_keyword_gui_list: |
1346 | 1 | tkerber | oops("Please use the facilities provided in this window to manipulate "+
|
1347 | 1 | tkerber | "the keyword:" + command[0] + "!") |
1348 | 1 | tkerber | else:
|
1349 | 1 | tkerber | oops("Don't know this keyword:" + command[0] |
1350 | 1 | tkerber | + "\nPlease check!\n\n"
|
1351 | 1 | tkerber | + "If you really think it should be available, "
|
1352 | 1 | tkerber | + "please add it to the top of ase/calculators/aims.py.")
|
1353 | 1 | tkerber | self.expert_keyword_set.set_text("") |
1354 | 1 | tkerber | |
1355 | 1 | tkerber | def expert_keyword_create(self, command): |
1356 | 1 | tkerber | key = command[0]
|
1357 | 1 | tkerber | argument = command[1]
|
1358 | 1 | tkerber | if len(command) > 2: |
1359 | 1 | tkerber | for a in command[2:]: |
1360 | 1 | tkerber | argument += ' '+a
|
1361 | 1 | tkerber | index = len(self.expert_keywords) |
1362 | 1 | tkerber | self.expert_keywords += [[gtk.Label(" " +key+" "), |
1363 | 1 | tkerber | gtk.Entry(max=45),
|
1364 | 1 | tkerber | ExpertDeleteButton(index), |
1365 | 1 | tkerber | True]]
|
1366 | 1 | tkerber | self.expert_keywords[index][1].set_text(argument) |
1367 | 1 | tkerber | self.expert_keywords[index][2].connect('clicked',self.expert_keyword_delete) |
1368 | 1 | tkerber | pack(self.expert_vbox, [self.expert_keywords[index][0], |
1369 | 1 | tkerber | self.expert_keywords[index][1], |
1370 | 1 | tkerber | self.expert_keywords[index][2]]) |
1371 | 1 | tkerber | |
1372 | 1 | tkerber | def expert_keyword_delete(self, button, *args): |
1373 | 1 | tkerber | index = button.index # which one to kill
|
1374 | 1 | tkerber | for i in [0,1,2]: |
1375 | 1 | tkerber | self.expert_keywords[index][i].destroy()
|
1376 | 1 | tkerber | self.expert_keywords[index][3] = False |
1377 | 1 | tkerber | |
1378 | 1 | tkerber | |
1379 | 1 | tkerber | class ExpertDeleteButton(gtk.Button): |
1380 | 1 | tkerber | def __init__(self, index): |
1381 | 1 | tkerber | gtk.Button.__init__(self, stock=gtk.STOCK_DELETE)
|
1382 | 1 | tkerber | alignment = self.get_children()[0] |
1383 | 1 | tkerber | hbox = alignment.get_children()[0]
|
1384 | 1 | tkerber | image, label = hbox.get_children() |
1385 | 1 | tkerber | if image is not None: |
1386 | 1 | tkerber | label.set_text('')
|
1387 | 1 | tkerber | self.index = index
|
1388 | 1 | tkerber | |
1389 | 1 | tkerber | |
1390 | 1 | tkerber | class VASP_Window(gtk.Window): |
1391 | 1 | tkerber | vasp_xc_list = ['PW91', 'PBE', 'LDA'] |
1392 | 1 | tkerber | vasp_xc_default = 'PBE'
|
1393 | 1 | tkerber | vasp_prec_default = 'Normal'
|
1394 | 1 | tkerber | def __init__(self, owner, param, attrname): |
1395 | 1 | tkerber | self.owner = owner
|
1396 | 1 | tkerber | self.attrname = attrname
|
1397 | 1 | tkerber | atoms = owner.atoms |
1398 | 1 | tkerber | self.periodic = atoms.get_pbc().all()
|
1399 | 1 | tkerber | self.vasp_keyword_gui_list = ['ediff','encut', 'ismear', 'ispin', 'prec', 'sigma'] |
1400 | 1 | tkerber | from ase.calculators.vasp import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,special_keys |
1401 | 1 | tkerber | self.vasp_keyword_list = float_keys+exp_keys+string_keys+int_keys+bool_keys+list_keys+special_keys
|
1402 | 1 | tkerber | self.expert_keywords = []
|
1403 | 1 | tkerber | natoms = len(atoms)
|
1404 | 1 | tkerber | gtk.Window.__init__(self)
|
1405 | 1 | tkerber | self.set_title("VASP parameters") |
1406 | 1 | tkerber | vbox = gtk.VBox() |
1407 | 1 | tkerber | # Print some info
|
1408 | 1 | tkerber | txt = "%i atoms.\n" % (natoms)
|
1409 | 1 | tkerber | self.ucell = atoms.get_cell()
|
1410 | 1 | tkerber | txt += "Periodic geometry, unit cell is: \n"
|
1411 | 1 | tkerber | for i in range(3): |
1412 | 1 | tkerber | txt += "(%8.3f %8.3f %8.3f)\n" % (self.ucell[i][0], self.ucell[i][1], self.ucell[i][2]) |
1413 | 1 | tkerber | pack(vbox, [gtk.Label(txt)]) |
1414 | 1 | tkerber | |
1415 | 1 | tkerber | # XC functional ()
|
1416 | 1 | tkerber | self.xc = gtk.combo_box_new_text()
|
1417 | 1 | tkerber | for i, x in enumerate(self.vasp_xc_list): |
1418 | 1 | tkerber | self.xc.append_text(x)
|
1419 | 1 | tkerber | if x == self.vasp_xc_default: |
1420 | 1 | tkerber | self.xc.set_active(i)
|
1421 | 1 | tkerber | |
1422 | 1 | tkerber | # Spin polarized
|
1423 | 1 | tkerber | self.spinpol = gtk.CheckButton("Spin polarized") |
1424 | 1 | tkerber | |
1425 | 1 | tkerber | pack(vbox, [gtk.Label("Exchange-correlation functional: "),
|
1426 | 1 | tkerber | self.xc,
|
1427 | 1 | tkerber | gtk.Label(" "),
|
1428 | 1 | tkerber | self.spinpol])
|
1429 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1430 | 1 | tkerber | |
1431 | 1 | tkerber | # k-grid
|
1432 | 1 | tkerber | self.kpts = []
|
1433 | 1 | tkerber | self.kpts_spin = []
|
1434 | 1 | tkerber | for i in range(3): |
1435 | 1 | tkerber | default = np.ceil(20.0 / np.sqrt(np.vdot(self.ucell[i],self.ucell[i]))) |
1436 | 1 | tkerber | g = gtk.Adjustment(default, 1, 100, 1) |
1437 | 1 | tkerber | s = gtk.SpinButton(g, 0, 0) |
1438 | 1 | tkerber | self.kpts.append(g)
|
1439 | 1 | tkerber | self.kpts_spin.append(s)
|
1440 | 1 | tkerber | g.connect("value-changed", self.k_changed) |
1441 | 1 | tkerber | |
1442 | 1 | tkerber | # Precision of calculation
|
1443 | 1 | tkerber | self.prec = gtk.combo_box_new_text()
|
1444 | 1 | tkerber | for i, x in enumerate(['Low', 'Normal', 'Accurate']): |
1445 | 1 | tkerber | self.prec.append_text(x)
|
1446 | 1 | tkerber | if x == self.vasp_prec_default: |
1447 | 1 | tkerber | self.prec.set_active(i)
|
1448 | 1 | tkerber | |
1449 | 1 | tkerber | # cutoff energy
|
1450 | 1 | tkerber | if os.environ.has_key('VASP_PP_PATH'): |
1451 | 1 | tkerber | self.encut_min_default, self.encut_max_default = self.get_min_max_cutoff() |
1452 | 1 | tkerber | else:
|
1453 | 1 | tkerber | self.encut_max_default = 400.0 |
1454 | 1 | tkerber | self.encut_min_default = 100.0 |
1455 | 1 | tkerber | self.encut = gtk.Adjustment(self.encut_max_default, 0, 9999, 10) |
1456 | 1 | tkerber | self.encut_spin = gtk.SpinButton(self.encut, 0, 0) |
1457 | 1 | tkerber | self.encut_spin.set_digits(2) |
1458 | 1 | tkerber | self.encut_spin.connect("value-changed",self.check_encut_warning) |
1459 | 1 | tkerber | self.encut_warning = gtk.Label("") |
1460 | 1 | tkerber | |
1461 | 1 | tkerber | pack(vbox, [gtk.Label("k-points k = ("), self.kpts_spin[0], |
1462 | 1 | tkerber | gtk.Label(", "), self.kpts_spin[1], gtk.Label(", "), |
1463 | 1 | tkerber | self.kpts_spin[2], |
1464 | 1 | tkerber | gtk.Label(") Cutoff: "),self.encut_spin, |
1465 | 1 | tkerber | gtk.Label(" Precision: "),self.prec]) |
1466 | 1 | tkerber | self.kpts_label = gtk.Label("") |
1467 | 1 | tkerber | self.kpts_label_format = "k-points x size: (%.1f, %.1f, %.1f) Å " |
1468 | 1 | tkerber | pack(vbox, [self.kpts_label, self.encut_warning]) |
1469 | 1 | tkerber | self.k_changed()
|
1470 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1471 | 1 | tkerber | |
1472 | 1 | tkerber | self.ismear = gtk.combo_box_new_text()
|
1473 | 1 | tkerber | for x in ['Fermi', 'Gauss', 'Methfessel-Paxton']: |
1474 | 1 | tkerber | self.ismear.append_text(x)
|
1475 | 1 | tkerber | self.ismear.set_active(2) |
1476 | 1 | tkerber | self.smearing_order = gtk.Adjustment(2,0,9,1) |
1477 | 1 | tkerber | self.smearing_order_spin = gtk.SpinButton(self.smearing_order,0,0) |
1478 | 1 | tkerber | self.smearing_order_spin.set_digits(0) |
1479 | 1 | tkerber | self.ismear.connect("changed", self.check_ismear_changed) |
1480 | 1 | tkerber | self.sigma = gtk.Adjustment(0.1, 0.001, 9.0, 0.1) |
1481 | 1 | tkerber | self.sigma_spin = gtk.SpinButton(self.sigma,0,0) |
1482 | 1 | tkerber | self.sigma_spin.set_digits(3) |
1483 | 1 | tkerber | pack(vbox, [gtk.Label("Smearing: "),
|
1484 | 1 | tkerber | self.ismear,
|
1485 | 1 | tkerber | gtk.Label(" order: "),
|
1486 | 1 | tkerber | self.smearing_order_spin,
|
1487 | 1 | tkerber | gtk.Label(" width: "),
|
1488 | 1 | tkerber | self.sigma_spin])
|
1489 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1490 | 1 | tkerber | |
1491 | 1 | tkerber | self.ediff = gtk.Adjustment(1e-4, 1e-6, 1e0, 1e-4) |
1492 | 1 | tkerber | self.ediff_spin = gtk.SpinButton(self.ediff, 0, 0) |
1493 | 1 | tkerber | self.ediff_spin.set_digits(6) |
1494 | 1 | tkerber | pack(vbox,[gtk.Label("Self-consistency convergence: "),
|
1495 | 1 | tkerber | self.ediff_spin,
|
1496 | 1 | tkerber | gtk.Label(" eV")])
|
1497 | 1 | tkerber | pack(vbox,gtk.Label(""))
|
1498 | 1 | tkerber | |
1499 | 1 | tkerber | self.expert_keyword_set = gtk.Entry(max = 55) |
1500 | 1 | tkerber | self.expert_keyword_add = gtk.Button(stock = gtk.STOCK_ADD)
|
1501 | 1 | tkerber | self.expert_keyword_add.connect("clicked", self.expert_keyword_import) |
1502 | 1 | tkerber | self.expert_keyword_set.connect("activate", self.expert_keyword_import) |
1503 | 1 | tkerber | pack(vbox,[gtk.Label("Additional keywords: "),
|
1504 | 1 | tkerber | self.expert_keyword_set,
|
1505 | 1 | tkerber | self.expert_keyword_add])
|
1506 | 1 | tkerber | self.expert_vbox = gtk.VBox()
|
1507 | 1 | tkerber | pack(vbox, self.expert_vbox)
|
1508 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1509 | 1 | tkerber | |
1510 | 1 | tkerber | # run command and location of POTCAR files:
|
1511 | 1 | tkerber | pack(vbox, gtk.Label('VASP execution command: '))
|
1512 | 1 | tkerber | self.run_command = pack(vbox, gtk.Entry(max=0)) |
1513 | 1 | tkerber | if os.environ.has_key('VASP_COMMAND'): |
1514 | 1 | tkerber | self.run_command.set_text(os.environ['VASP_COMMAND']) |
1515 | 1 | tkerber | pack(vbox, gtk.Label('Directory for species defaults: '))
|
1516 | 1 | tkerber | self.pp_path = pack(vbox, gtk.Entry(max=0)) |
1517 | 1 | tkerber | if os.environ.has_key('VASP_PP_PATH'): |
1518 | 1 | tkerber | self.pp_path.set_text(os.environ['VASP_PP_PATH']) |
1519 | 1 | tkerber | |
1520 | 1 | tkerber | # Buttons at the bottom
|
1521 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
1522 | 1 | tkerber | butbox = gtk.HButtonBox() |
1523 | 1 | tkerber | export_vasp_but = gtk.Button("Export VASP files")
|
1524 | 1 | tkerber | export_vasp_but.connect("clicked", self.export_vasp_files) |
1525 | 1 | tkerber | cancel_but = gtk.Button(stock=gtk.STOCK_CANCEL) |
1526 | 1 | tkerber | cancel_but.connect('clicked', lambda widget: self.destroy()) |
1527 | 1 | tkerber | ok_but = gtk.Button(stock=gtk.STOCK_OK) |
1528 | 1 | tkerber | ok_but.connect('clicked', self.ok) |
1529 | 1 | tkerber | butbox.pack_start(export_vasp_but, 0, 0) |
1530 | 1 | tkerber | butbox.pack_start(cancel_but, 0, 0) |
1531 | 1 | tkerber | butbox.pack_start(ok_but, 0, 0) |
1532 | 1 | tkerber | butbox.show_all() |
1533 | 1 | tkerber | pack(vbox, [butbox], end=True, bottom=True) |
1534 | 1 | tkerber | vbox.show() |
1535 | 1 | tkerber | self.add(vbox)
|
1536 | 1 | tkerber | self.show()
|
1537 | 1 | tkerber | self.grab_add() # Lock all other windows |
1538 | 1 | tkerber | |
1539 | 1 | tkerber | def set_attributes(self, *args): |
1540 | 1 | tkerber | self.param = {}
|
1541 | 1 | tkerber | self.param["xc"] = self.xc.get_active_text() |
1542 | 1 | tkerber | self.param["prec"] = self.prec.get_active_text() |
1543 | 1 | tkerber | self.param["kpts"] = (int(self.kpts[0].value), |
1544 | 1 | tkerber | int(self.kpts[1].value), |
1545 | 1 | tkerber | int(self.kpts[2].value)) |
1546 | 1 | tkerber | self.param["encut"] = self.encut.value |
1547 | 1 | tkerber | self.param["ediff"] = self.ediff.value |
1548 | 1 | tkerber | self.param["ismear"] = self.get_ismear() |
1549 | 1 | tkerber | self.param["sigma"] = self.sigma.value |
1550 | 1 | tkerber | if self.spinpol.get_active(): |
1551 | 1 | tkerber | self.param["ispin"] = 2 |
1552 | 1 | tkerber | else:
|
1553 | 1 | tkerber | self.param["ispin"] = 1 |
1554 | 1 | tkerber | from ase.calculators.vasp import float_keys,exp_keys,string_keys,int_keys,bool_keys,list_keys,special_keys |
1555 | 1 | tkerber | for option in self.expert_keywords: |
1556 | 1 | tkerber | if option[3]: # set type of parameter accoding to which list it is in |
1557 | 1 | tkerber | key = option[0].get_text().strip()
|
1558 | 1 | tkerber | val = option[1].get_text().strip()
|
1559 | 1 | tkerber | if key in float_keys or key in exp_keys: |
1560 | 1 | tkerber | self.param[key] = float(val) |
1561 | 1 | tkerber | elif key in list_keys or key in string_keys: |
1562 | 1 | tkerber | self.param[key] = val
|
1563 | 1 | tkerber | elif key in int_keys: |
1564 | 1 | tkerber | self.param[key] = int(val) |
1565 | 1 | tkerber | elif key in bool_keys: |
1566 | 1 | tkerber | self.param[key] = bool(val) |
1567 | 1 | tkerber | setattr(self.owner, self.attrname, self.param) |
1568 | 1 | tkerber | os.environ['VASP_COMMAND'] = self.run_command.get_text() |
1569 | 1 | tkerber | os.environ['VASP_PP_PATH'] = self.pp_path.get_text() |
1570 | 1 | tkerber | |
1571 | 1 | tkerber | def ok(self, *args): |
1572 | 1 | tkerber | self.set_attributes(*args)
|
1573 | 1 | tkerber | self.destroy()
|
1574 | 1 | tkerber | |
1575 | 1 | tkerber | def get_min_max_cutoff(self, *args): |
1576 | 1 | tkerber | # determine the recommended energy cutoff limits
|
1577 | 1 | tkerber | from ase.calculators.vasp import Vasp |
1578 | 1 | tkerber | calc_temp = Vasp() |
1579 | 1 | tkerber | atoms_temp = self.owner.atoms.copy()
|
1580 | 1 | tkerber | calc_temp.initialize(atoms_temp) |
1581 | 1 | tkerber | calc_temp.write_potcar(suffix = '.check_energy_cutoff')
|
1582 | 1 | tkerber | enmin = -1e6
|
1583 | 1 | tkerber | enmax = -1e6
|
1584 | 1 | tkerber | for line in open("POTCAR.check_energy_cutoff",'r').readlines(): |
1585 | 1 | tkerber | if "ENMIN" in line: |
1586 | 1 | tkerber | enmax = max(enmax,float(line.split()[2].split(';')[0])) |
1587 | 1 | tkerber | enmin = max(enmin,float(line.split()[5])) |
1588 | 1 | tkerber | from os import system |
1589 | 1 | tkerber | system("rm POTCAR.check_energy_cutoff")
|
1590 | 1 | tkerber | return enmin, enmax
|
1591 | 1 | tkerber | |
1592 | 1 | tkerber | def k_changed(self, *args): |
1593 | 1 | tkerber | size = [self.kpts[i].value * np.sqrt(np.vdot(self.ucell[i],self.ucell[i])) for i in range(3)] |
1594 | 1 | tkerber | self.kpts_label.set_text(self.kpts_label_format % tuple(size)) |
1595 | 1 | tkerber | |
1596 | 1 | tkerber | def check_encut_warning(self,*args): |
1597 | 1 | tkerber | if self.encut.value < self.encut_min_default: |
1598 | 1 | tkerber | self.encut_warning.set_markup("<b>WARNING:</b> cutoff energy is lower than recommended minimum!") |
1599 | 1 | tkerber | else:
|
1600 | 1 | tkerber | self.encut_warning.set_markup("") |
1601 | 1 | tkerber | |
1602 | 1 | tkerber | def check_ismear_changed(self,*args): |
1603 | 1 | tkerber | if self.ismear.get_active_text() == 'Methfessel-Paxton': |
1604 | 1 | tkerber | self.smearing_order_spin.set_sensitive(True) |
1605 | 1 | tkerber | else:
|
1606 | 1 | tkerber | self.smearing_order_spin.set_sensitive(False) |
1607 | 1 | tkerber | |
1608 | 1 | tkerber | def get_ismear(self,*args): |
1609 | 1 | tkerber | type = self.ismear.get_active_text()
|
1610 | 1 | tkerber | if type == 'Methfessel-Paxton': |
1611 | 1 | tkerber | ismear_value = self.smearing_order.value
|
1612 | 1 | tkerber | elif type == 'Fermi': |
1613 | 1 | tkerber | ismear_value = -1
|
1614 | 1 | tkerber | else:
|
1615 | 1 | tkerber | ismear_value = 0
|
1616 | 1 | tkerber | return ismear_value
|
1617 | 1 | tkerber | |
1618 | 1 | tkerber | def destroy(self): |
1619 | 1 | tkerber | self.grab_remove()
|
1620 | 1 | tkerber | gtk.Window.destroy(self)
|
1621 | 1 | tkerber | |
1622 | 1 | tkerber | def export_vasp_files(self, *args): |
1623 | 1 | tkerber | filename = ""
|
1624 | 1 | tkerber | chooser = gtk.FileChooserDialog( |
1625 | 1 | tkerber | 'Export VASP input files: choose directory ... ',
|
1626 | 1 | tkerber | None, gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
1627 | 1 | tkerber | (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, |
1628 | 1 | tkerber | gtk.STOCK_SAVE, gtk.RESPONSE_OK)) |
1629 | 1 | tkerber | chooser.set_filename(filename) |
1630 | 1 | tkerber | save = chooser.run() |
1631 | 1 | tkerber | if save == gtk.RESPONSE_OK or save == gtk.RESPONSE_SAVE: |
1632 | 1 | tkerber | filename = chooser.get_filename() |
1633 | 1 | tkerber | from os import chdir |
1634 | 1 | tkerber | chdir(filename) |
1635 | 1 | tkerber | self.set_attributes(*args)
|
1636 | 1 | tkerber | param = getattr(self.owner, "vasp_parameters") |
1637 | 1 | tkerber | from ase.calculators.vasp import Vasp |
1638 | 1 | tkerber | calc_temp = Vasp(**param) |
1639 | 1 | tkerber | atoms_temp = self.owner.atoms.copy()
|
1640 | 1 | tkerber | atoms_temp.set_calculator(calc_temp) |
1641 | 1 | tkerber | calc_temp.initialize(atoms_temp) |
1642 | 1 | tkerber | calc_temp.write_incar(atoms_temp) |
1643 | 1 | tkerber | calc_temp.write_potcar() |
1644 | 1 | tkerber | calc_temp.write_kpoints() |
1645 | 1 | tkerber | calc_temp.write_sort_file() |
1646 | 1 | tkerber | from ase.io.vasp import write_vasp |
1647 | 1 | tkerber | write_vasp('POSCAR', calc_temp.atoms_sorted, symbol_count = calc_temp.symbol_count)
|
1648 | 1 | tkerber | chooser.destroy() |
1649 | 1 | tkerber | |
1650 | 1 | tkerber | def expert_keyword_import(self, *args): |
1651 | 1 | tkerber | command = self.expert_keyword_set.get_text().split()
|
1652 | 1 | tkerber | if len(command) > 0 and command[0] in self.vasp_keyword_list and not command[0] in self.vasp_keyword_gui_list: |
1653 | 1 | tkerber | self.expert_keyword_create(command)
|
1654 | 1 | tkerber | elif command[0] in self.vasp_keyword_gui_list: |
1655 | 1 | tkerber | oops("Please use the facilities provided in this window to manipulate "+
|
1656 | 1 | tkerber | "the keyword: " + command[0] + "!") |
1657 | 1 | tkerber | else:
|
1658 | 1 | tkerber | oops("Don't know this keyword: " + command[0] |
1659 | 1 | tkerber | + "\nPlease check!\n\n"
|
1660 | 1 | tkerber | + "If you really think it should be available, "
|
1661 | 1 | tkerber | + "please add it to the top of ase/calculators/vasp.py.")
|
1662 | 1 | tkerber | self.expert_keyword_set.set_text("") |
1663 | 1 | tkerber | |
1664 | 1 | tkerber | def expert_keyword_create(self, command): |
1665 | 1 | tkerber | key = command[0]
|
1666 | 1 | tkerber | if command[1] == "=": |
1667 | 1 | tkerber | command.remove("=")
|
1668 | 1 | tkerber | argument = command[1]
|
1669 | 1 | tkerber | if len(command) > 2: |
1670 | 1 | tkerber | for a in command[2:]: |
1671 | 1 | tkerber | argument += ' '+a
|
1672 | 1 | tkerber | index = len(self.expert_keywords) |
1673 | 1 | tkerber | self.expert_keywords += [[gtk.Label(" " +key+" = "), |
1674 | 1 | tkerber | gtk.Entry(max=45),
|
1675 | 1 | tkerber | ExpertDeleteButton(index), |
1676 | 1 | tkerber | True]]
|
1677 | 1 | tkerber | self.expert_keywords[index][1].set_text(argument) |
1678 | 1 | tkerber | self.expert_keywords[index][2].connect('clicked',self.expert_keyword_delete) |
1679 | 1 | tkerber | pack(self.expert_vbox, [self.expert_keywords[index][0], |
1680 | 1 | tkerber | self.expert_keywords[index][1], |
1681 | 1 | tkerber | self.expert_keywords[index][2]]) |
1682 | 1 | tkerber | |
1683 | 1 | tkerber | def expert_keyword_delete(self, button, *args): |
1684 | 1 | tkerber | index = button.index # which one to kill
|
1685 | 1 | tkerber | for i in [0,1,2]: |
1686 | 1 | tkerber | self.expert_keywords[index][i].destroy()
|
1687 | 1 | tkerber | self.expert_keywords[index][3] = False |