root / ase / gui / minimize.py @ 4
Historique | Voir | Annoter | Télécharger (4,39 ko)
| 1 |
# encoding: utf-8
|
|---|---|
| 2 |
|
| 3 |
"Module for performing energy minimization."
|
| 4 |
|
| 5 |
import gtk |
| 6 |
from ase.gui.simulation import Simulation |
| 7 |
from ase.gui.widgets import oops, pack, AseGuiCancelException |
| 8 |
import ase |
| 9 |
import numpy as np |
| 10 |
|
| 11 |
class MinimizeMixin: |
| 12 |
minimizers = ('BFGS', 'BFGSLineSearch', 'LBFGS', 'LBFGSLineSearch', 'MDMin', 'FIRE') |
| 13 |
def make_minimize_gui(self, box): |
| 14 |
self.algo = gtk.combo_box_new_text()
|
| 15 |
for m in self.minimizers: |
| 16 |
self.algo.append_text(m)
|
| 17 |
self.algo.set_active(0) |
| 18 |
pack(box, [gtk.Label("Algorithm: "), self.algo]) |
| 19 |
|
| 20 |
self.fmax = gtk.Adjustment(0.05, 0.00, 10.0, 0.01) |
| 21 |
self.fmax_spin = gtk.SpinButton(self.fmax, 0, 3) |
| 22 |
lbl = gtk.Label() |
| 23 |
lbl.set_markup("Convergence criterion: F<sub>max</sub> = ")
|
| 24 |
pack(box, [lbl, self.fmax_spin])
|
| 25 |
|
| 26 |
self.steps = gtk.Adjustment(100, 1, 1000000, 1) |
| 27 |
self.steps_spin = gtk.SpinButton(self.steps, 0, 0) |
| 28 |
pack(box, [gtk.Label("Max. number of steps: "), self.steps_spin]) |
| 29 |
|
| 30 |
class Minimize(Simulation, MinimizeMixin): |
| 31 |
"Window for performing energy minimization."
|
| 32 |
|
| 33 |
def __init__(self, gui): |
| 34 |
Simulation.__init__(self, gui)
|
| 35 |
self.set_title("Energy minimization") |
| 36 |
|
| 37 |
vbox = gtk.VBox() |
| 38 |
self.packtext(vbox,
|
| 39 |
"Minimize the energy with respect to the positions.")
|
| 40 |
self.packimageselection(vbox)
|
| 41 |
pack(vbox, gtk.Label(""))
|
| 42 |
|
| 43 |
self.make_minimize_gui(vbox)
|
| 44 |
|
| 45 |
pack(vbox, gtk.Label(""))
|
| 46 |
self.status_label = gtk.Label("") |
| 47 |
pack(vbox, [self.status_label])
|
| 48 |
self.makebutbox(vbox)
|
| 49 |
vbox.show() |
| 50 |
self.add(vbox)
|
| 51 |
self.show()
|
| 52 |
self.gui.register_vulnerable(self) |
| 53 |
|
| 54 |
def run(self, *args): |
| 55 |
"User has pressed [Run]: run the minimization."
|
| 56 |
if not self.setup_atoms(): |
| 57 |
return
|
| 58 |
fmax = self.fmax.value
|
| 59 |
steps = self.steps.value
|
| 60 |
mininame = self.minimizers[self.algo.get_active()] |
| 61 |
self.begin(mode="min", algo=mininame, fmax=fmax, steps=steps) |
| 62 |
algo = getattr(ase.optimize, mininame)
|
| 63 |
try:
|
| 64 |
logger_func = self.gui.simulation['progress'].get_logger_stream |
| 65 |
except (KeyError, AttributeError): |
| 66 |
logger = None
|
| 67 |
else:
|
| 68 |
logger = logger_func() # Don't catch errors in the function.
|
| 69 |
|
| 70 |
# Display status message
|
| 71 |
self.status_label.set_text("Running ...") |
| 72 |
self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 73 |
gtk.gdk.color_parse('#AA0000'))
|
| 74 |
while gtk.events_pending():
|
| 75 |
gtk.main_iteration() |
| 76 |
|
| 77 |
self.prepare_store_atoms()
|
| 78 |
minimizer = algo(self.atoms, logfile=logger)
|
| 79 |
minimizer.attach(self.store_atoms)
|
| 80 |
try:
|
| 81 |
minimizer.run(fmax=fmax, steps=steps) |
| 82 |
except AseGuiCancelException:
|
| 83 |
# Update display to reflect cancellation of simulation.
|
| 84 |
self.status_label.set_text("Minimization CANCELLED after %i steps." |
| 85 |
% (self.count_steps,))
|
| 86 |
self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 87 |
gtk.gdk.color_parse('#AA4000'))
|
| 88 |
except MemoryError: |
| 89 |
self.status_label.set_text("Out of memory, consider using LBFGS instead") |
| 90 |
self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 91 |
gtk.gdk.color_parse('#AA4000'))
|
| 92 |
|
| 93 |
else:
|
| 94 |
# Update display to reflect succesful end of simulation.
|
| 95 |
self.status_label.set_text("Minimization completed in %i steps." |
| 96 |
% (self.count_steps,))
|
| 97 |
self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 98 |
gtk.gdk.color_parse('#007700'))
|
| 99 |
|
| 100 |
self.end()
|
| 101 |
if self.count_steps: |
| 102 |
# Notify other windows that atoms have changed.
|
| 103 |
# This also notifies this window!
|
| 104 |
self.gui.notify_vulnerable()
|
| 105 |
|
| 106 |
# Open movie window and energy graph
|
| 107 |
if self.gui.images.nimages > 1: |
| 108 |
self.gui.movie()
|
| 109 |
assert not np.isnan(self.gui.images.E[0]) |
| 110 |
if not self.gui.plot_graphs_newatoms(): |
| 111 |
expr = 'i, e - E[-1]'
|
| 112 |
self.gui.plot_graphs(expr=expr)
|
| 113 |
|
| 114 |
def notify_atoms_changed(self): |
| 115 |
"When atoms have changed, check for the number of images."
|
| 116 |
self.setupimageselection()
|
| 117 |
|