root / ase / gui / scaling.py @ 4
Historique | Voir | Annoter | Télécharger (14,54 ko)
| 1 | 1 | tkerber | # encoding: utf-8
|
|---|---|---|---|
| 2 | 1 | tkerber | |
| 3 | 1 | tkerber | "Module for homogeneous deformation and calculations of elastic constants."
|
| 4 | 1 | tkerber | |
| 5 | 1 | tkerber | import gtk |
| 6 | 1 | tkerber | from ase.gui.simulation import Simulation |
| 7 | 1 | tkerber | from ase.gui.minimize import MinimizeMixin |
| 8 | 1 | tkerber | from ase.gui.energyforces import OutputFieldMixin |
| 9 | 1 | tkerber | from ase.gui.widgets import oops, pack, AseGuiCancelException |
| 10 | 1 | tkerber | import ase |
| 11 | 1 | tkerber | import numpy as np |
| 12 | 1 | tkerber | |
| 13 | 1 | tkerber | scaling_txt = """\
|
| 14 | 1 | tkerber | This module is intended for calculating elastic constants by homogeneously
|
| 15 | 1 | tkerber | deforming a system."""
|
| 16 | 1 | tkerber | |
| 17 | 1 | tkerber | class HomogeneousDeformation(Simulation, MinimizeMixin, OutputFieldMixin): |
| 18 | 1 | tkerber | "Window for homogeneous deformation and elastic constants."
|
| 19 | 1 | tkerber | |
| 20 | 1 | tkerber | def __init__(self, gui): |
| 21 | 1 | tkerber | Simulation.__init__(self, gui)
|
| 22 | 1 | tkerber | self.set_title("Homogeneous scaling") |
| 23 | 1 | tkerber | vbox = gtk.VBox() |
| 24 | 1 | tkerber | self.packtext(vbox, scaling_txt)
|
| 25 | 1 | tkerber | self.packimageselection(vbox, txt1="", txt2="") |
| 26 | 1 | tkerber | self.start_radio_nth.set_active(True) |
| 27 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
| 28 | 1 | tkerber | |
| 29 | 1 | tkerber | # Radio buttons for choosing deformation mode.
|
| 30 | 1 | tkerber | tbl = gtk.Table(4,3) |
| 31 | 1 | tkerber | for i, l in enumerate(('3D', '2D', '1D')): |
| 32 | 1 | tkerber | l = l + " deformation "
|
| 33 | 1 | tkerber | lbl = gtk.Label(l) |
| 34 | 1 | tkerber | tbl.attach(lbl, i, i+1, 0, 1) |
| 35 | 1 | tkerber | self.radio_bulk = gtk.RadioButton(None, "Bulk") |
| 36 | 1 | tkerber | tbl.attach(self.radio_bulk, 0, 1, 1, 2) |
| 37 | 1 | tkerber | self.radio_xy = gtk.RadioButton(self.radio_bulk, "xy-plane") |
| 38 | 1 | tkerber | tbl.attach(self.radio_xy, 1, 2, 1, 2) |
| 39 | 1 | tkerber | self.radio_xz = gtk.RadioButton(self.radio_bulk, "xz-plane") |
| 40 | 1 | tkerber | tbl.attach(self.radio_xz, 1, 2, 2, 3) |
| 41 | 1 | tkerber | self.radio_yz = gtk.RadioButton(self.radio_bulk, "yz-plane") |
| 42 | 1 | tkerber | tbl.attach(self.radio_yz, 1, 2, 3, 4) |
| 43 | 1 | tkerber | self.radio_x = gtk.RadioButton(self.radio_bulk, "x-axis") |
| 44 | 1 | tkerber | tbl.attach(self.radio_x, 2, 3, 1, 2) |
| 45 | 1 | tkerber | self.radio_y = gtk.RadioButton(self.radio_bulk, "y-axis") |
| 46 | 1 | tkerber | tbl.attach(self.radio_y, 2, 3, 2, 3) |
| 47 | 1 | tkerber | self.radio_z = gtk.RadioButton(self.radio_bulk, "z-axis") |
| 48 | 1 | tkerber | tbl.attach(self.radio_z, 2, 3, 3, 4) |
| 49 | 1 | tkerber | tbl.show_all() |
| 50 | 1 | tkerber | pack(vbox, [tbl]) |
| 51 | 1 | tkerber | self.deformtable = [
|
| 52 | 1 | tkerber | (self.radio_bulk, (1,1,1)), |
| 53 | 1 | tkerber | (self.radio_xy, (1,1,0)), |
| 54 | 1 | tkerber | (self.radio_xz, (1,0,1)), |
| 55 | 1 | tkerber | (self.radio_yz, (0,1,1)), |
| 56 | 1 | tkerber | (self.radio_x, (1,0,0)), |
| 57 | 1 | tkerber | (self.radio_y, (0,1,0)), |
| 58 | 1 | tkerber | (self.radio_z, (0,0,1))] |
| 59 | 1 | tkerber | self.deform_label = gtk.Label("") |
| 60 | 1 | tkerber | pack(vbox, [self.deform_label])
|
| 61 | 1 | tkerber | self.choose_possible_deformations(first=True) |
| 62 | 1 | tkerber | |
| 63 | 1 | tkerber | # Parameters for the deformation
|
| 64 | 1 | tkerber | framedef = gtk.Frame("Deformation:")
|
| 65 | 1 | tkerber | vbox2 = gtk.VBox() |
| 66 | 1 | tkerber | vbox2.show() |
| 67 | 1 | tkerber | framedef.add(vbox2) |
| 68 | 1 | tkerber | self.max_scale = gtk.Adjustment(0.010, 0.001, 10.0, 0.001) |
| 69 | 1 | tkerber | max_scale_spin = gtk.SpinButton(self.max_scale, 10.0, 3) |
| 70 | 1 | tkerber | pack(vbox2, [gtk.Label("Maximal scale factor: "), max_scale_spin])
|
| 71 | 1 | tkerber | self.scale_offset = gtk.Adjustment(0.0, -10.0, 10.0, 0.001) |
| 72 | 1 | tkerber | scale_offset_spin = gtk.SpinButton(self.scale_offset, 10.0, 3) |
| 73 | 1 | tkerber | pack(vbox2, [gtk.Label("Scale offset: "), scale_offset_spin])
|
| 74 | 1 | tkerber | self.nsteps = gtk.Adjustment(5, 3, 100, 1) |
| 75 | 1 | tkerber | nsteps_spin = gtk.SpinButton(self.nsteps, 1, 0) |
| 76 | 1 | tkerber | pack(vbox2, [gtk.Label("Number of steps: "), nsteps_spin])
|
| 77 | 1 | tkerber | |
| 78 | 1 | tkerber | # Atomic relaxations
|
| 79 | 1 | tkerber | framerel = gtk.Frame("Atomic relaxations:")
|
| 80 | 1 | tkerber | vbox2 = gtk.VBox() |
| 81 | 1 | tkerber | vbox2.show() |
| 82 | 1 | tkerber | framerel.add(vbox2) |
| 83 | 1 | tkerber | self.radio_relax_on = gtk.RadioButton(None, "On ") |
| 84 | 1 | tkerber | self.radio_relax_off = gtk.RadioButton(self.radio_relax_on, "Off") |
| 85 | 1 | tkerber | self.radio_relax_off.set_active(True) |
| 86 | 1 | tkerber | pack(vbox2, [self.radio_relax_on, self.radio_relax_off]) |
| 87 | 1 | tkerber | self.make_minimize_gui(vbox2)
|
| 88 | 1 | tkerber | for r in (self.radio_relax_on, self.radio_relax_off): |
| 89 | 1 | tkerber | r.connect("toggled", self.relax_toggled) |
| 90 | 1 | tkerber | self.relax_toggled()
|
| 91 | 1 | tkerber | pack(vbox, [framedef, gtk.Label(" "), framerel])
|
| 92 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
| 93 | 1 | tkerber | |
| 94 | 1 | tkerber | # Results
|
| 95 | 1 | tkerber | pack(vbox, [gtk.Label("Results:")])
|
| 96 | 1 | tkerber | self.radio_results_optimal = gtk.RadioButton(
|
| 97 | 1 | tkerber | None, "Load optimal configuration") |
| 98 | 1 | tkerber | self.radio_results_all = gtk.RadioButton(
|
| 99 | 1 | tkerber | self.radio_results_optimal, "Load all configurations") |
| 100 | 1 | tkerber | self.radio_results_optimal.set_active(True) |
| 101 | 1 | tkerber | pack(vbox, [self.radio_results_optimal])
|
| 102 | 1 | tkerber | pack(vbox, [self.radio_results_all])
|
| 103 | 1 | tkerber | |
| 104 | 1 | tkerber | # Output field
|
| 105 | 1 | tkerber | outframe = self.makeoutputfield(None) |
| 106 | 1 | tkerber | fitframe = gtk.Frame("Fit:")
|
| 107 | 1 | tkerber | vbox2 = gtk.VBox() |
| 108 | 1 | tkerber | vbox2.show() |
| 109 | 1 | tkerber | fitframe.add(vbox2) |
| 110 | 1 | tkerber | self.radio_fit_2 = gtk.RadioButton(None, "2nd") |
| 111 | 1 | tkerber | self.radio_fit_3 = gtk.RadioButton(self.radio_fit_2, "3rd") |
| 112 | 1 | tkerber | self.radio_fit_2.connect("toggled", self.change_fit) |
| 113 | 1 | tkerber | self.radio_fit_3.connect("toggled", self.change_fit) |
| 114 | 1 | tkerber | self.radio_fit_3.set_active(True) |
| 115 | 1 | tkerber | pack(vbox2, [gtk.Label("Order of fit: "), self.radio_fit_2, |
| 116 | 1 | tkerber | self.radio_fit_3])
|
| 117 | 1 | tkerber | pack(vbox2, [gtk.Label("")])
|
| 118 | 1 | tkerber | scrwin = gtk.ScrolledWindow() |
| 119 | 1 | tkerber | scrwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
| 120 | 1 | tkerber | self.fit_output = gtk.TextBuffer()
|
| 121 | 1 | tkerber | txtview = gtk.TextView(self.fit_output)
|
| 122 | 1 | tkerber | txtview.set_editable(False)
|
| 123 | 1 | tkerber | scrwin.add(txtview) |
| 124 | 1 | tkerber | scrwin.show_all() |
| 125 | 1 | tkerber | self.fit_win = scrwin
|
| 126 | 1 | tkerber | print "SIZE RQ:", scrwin.size_request() |
| 127 | 1 | tkerber | vbox2.pack_start(scrwin, True, True, 0) |
| 128 | 1 | tkerber | hbox = gtk.HBox(homogeneous=True)
|
| 129 | 1 | tkerber | for w in [outframe, fitframe]: |
| 130 | 1 | tkerber | hbox.pack_start(w) |
| 131 | 1 | tkerber | w.show() |
| 132 | 1 | tkerber | pack(vbox, hbox) |
| 133 | 1 | tkerber | pack(vbox, gtk.Label(""))
|
| 134 | 1 | tkerber | |
| 135 | 1 | tkerber | # Status field
|
| 136 | 1 | tkerber | self.status_label = gtk.Label("") |
| 137 | 1 | tkerber | pack(vbox, [self.status_label])
|
| 138 | 1 | tkerber | |
| 139 | 1 | tkerber | # Run buttons etc.
|
| 140 | 1 | tkerber | self.makebutbox(vbox)
|
| 141 | 1 | tkerber | vbox.show() |
| 142 | 1 | tkerber | self.add(vbox)
|
| 143 | 1 | tkerber | self.show()
|
| 144 | 1 | tkerber | self.gui.register_vulnerable(self) |
| 145 | 1 | tkerber | |
| 146 | 1 | tkerber | def choose_possible_deformations(self, first=False): |
| 147 | 1 | tkerber | """Turn on sensible radio buttons.
|
| 148 | 1 | tkerber |
|
| 149 | 1 | tkerber | Only radio buttons corresponding to deformations in directions
|
| 150 | 1 | tkerber | with periodic boundary conditions should be turned on.
|
| 151 | 1 | tkerber | """
|
| 152 | 1 | tkerber | if self.setup_atoms(): |
| 153 | 1 | tkerber | pbc = self.atoms.get_pbc()
|
| 154 | 1 | tkerber | else:
|
| 155 | 1 | tkerber | pbc = [False, False, False] |
| 156 | 1 | tkerber | for radio, requirement in self.deformtable: |
| 157 | 1 | tkerber | ok = True
|
| 158 | 1 | tkerber | for i in range(3): |
| 159 | 1 | tkerber | if requirement[i] and not pbc[i]: |
| 160 | 1 | tkerber | ok = False
|
| 161 | 1 | tkerber | radio.set_sensitive(ok) |
| 162 | 1 | tkerber | if first and ok: |
| 163 | 1 | tkerber | # The first acceptable choice, choose it to prevent
|
| 164 | 1 | tkerber | # inconsistent state.
|
| 165 | 1 | tkerber | radio.set_active(True)
|
| 166 | 1 | tkerber | first = False
|
| 167 | 1 | tkerber | |
| 168 | 1 | tkerber | def relax_toggled(self, *args): |
| 169 | 1 | tkerber | "Turn minimization widgets on or off."
|
| 170 | 1 | tkerber | state = self.radio_relax_on.get_active()
|
| 171 | 1 | tkerber | for widget in (self.algo, self.fmax_spin, self.steps_spin): |
| 172 | 1 | tkerber | widget.set_sensitive(state) |
| 173 | 1 | tkerber | |
| 174 | 1 | tkerber | def notify_atoms_changed(self): |
| 175 | 1 | tkerber | "When atoms have changed, check for the number of images."
|
| 176 | 1 | tkerber | self.setupimageselection()
|
| 177 | 1 | tkerber | self.choose_possible_deformations()
|
| 178 | 1 | tkerber | |
| 179 | 1 | tkerber | def get_deformation_axes(self): |
| 180 | 1 | tkerber | """Return which axes the user wants to deform along."""
|
| 181 | 1 | tkerber | for but, deform in self.deformtable: |
| 182 | 1 | tkerber | if but.get_active():
|
| 183 | 1 | tkerber | return np.array(deform)
|
| 184 | 1 | tkerber | # No deformation chosen!
|
| 185 | 1 | tkerber | oops("No deformation chosen: Please choose a deformation mode.")
|
| 186 | 1 | tkerber | return False |
| 187 | 1 | tkerber | |
| 188 | 1 | tkerber | def run(self, *args): |
| 189 | 1 | tkerber | """Make the deformation."""
|
| 190 | 1 | tkerber | self.output.set_text("") |
| 191 | 1 | tkerber | if not self.setup_atoms(): |
| 192 | 1 | tkerber | return
|
| 193 | 1 | tkerber | deform_axes = self.get_deformation_axes()
|
| 194 | 1 | tkerber | if deform_axes is False: |
| 195 | 1 | tkerber | return #Nothing to do! |
| 196 | 1 | tkerber | |
| 197 | 1 | tkerber | # Prepare progress bar
|
| 198 | 1 | tkerber | if self.radio_relax_on.get_active(): |
| 199 | 1 | tkerber | fmax = self.fmax.value
|
| 200 | 1 | tkerber | mininame = self.minimizers[self.algo.get_active()] |
| 201 | 1 | tkerber | self.begin(mode="scale/min", algo=mininame, fmax=fmax, |
| 202 | 1 | tkerber | steps=self.steps.value, scalesteps=self.nsteps.value) |
| 203 | 1 | tkerber | else:
|
| 204 | 1 | tkerber | self.begin(mode="scale", scalesteps=self.nsteps.value) |
| 205 | 1 | tkerber | try:
|
| 206 | 1 | tkerber | logger_func = self.gui.simulation['progress'].get_logger_stream |
| 207 | 1 | tkerber | except (KeyError, AttributeError): |
| 208 | 1 | tkerber | logger = None
|
| 209 | 1 | tkerber | else:
|
| 210 | 1 | tkerber | logger = logger_func() # Don't catch errors in the function.
|
| 211 | 1 | tkerber | |
| 212 | 1 | tkerber | # Display status message
|
| 213 | 1 | tkerber | self.status_label.set_text("Running ...") |
| 214 | 1 | tkerber | self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 215 | 1 | tkerber | gtk.gdk.color_parse('#AA0000'))
|
| 216 | 1 | tkerber | while gtk.events_pending():
|
| 217 | 1 | tkerber | gtk.main_iteration() |
| 218 | 1 | tkerber | |
| 219 | 1 | tkerber | # Do the scaling
|
| 220 | 1 | tkerber | scale = self.max_scale.value
|
| 221 | 1 | tkerber | steps = np.linspace(-scale, scale, self.nsteps.value)
|
| 222 | 1 | tkerber | steps += self.scale_offset.value
|
| 223 | 1 | tkerber | undef_cell = self.atoms.get_cell()
|
| 224 | 1 | tkerber | results = [] |
| 225 | 1 | tkerber | txt = "Strain\t\tEnergy [eV]\n"
|
| 226 | 1 | tkerber | # If we load all configurations, prepare it.
|
| 227 | 1 | tkerber | if self.radio_results_all.get_active(): |
| 228 | 1 | tkerber | self.prepare_store_atoms()
|
| 229 | 1 | tkerber | |
| 230 | 1 | tkerber | try:
|
| 231 | 1 | tkerber | # Now, do the deformation
|
| 232 | 1 | tkerber | for i, d in enumerate(steps): |
| 233 | 1 | tkerber | deformation = np.diag(1.0 + d * deform_axes)
|
| 234 | 1 | tkerber | self.atoms.set_cell(np.dot(undef_cell, deformation),
|
| 235 | 1 | tkerber | scale_atoms=True)
|
| 236 | 1 | tkerber | if self.gui.simulation.has_key('progress'): |
| 237 | 1 | tkerber | self.gui.simulation['progress'].set_scale_progress(i) |
| 238 | 1 | tkerber | if self.radio_relax_on.get_active(): |
| 239 | 1 | tkerber | algo = getattr(ase.optimize, mininame)
|
| 240 | 1 | tkerber | minimizer = algo(self.atoms, logfile=logger)
|
| 241 | 1 | tkerber | minimizer.run(fmax=fmax, steps=self.steps.value)
|
| 242 | 1 | tkerber | e = self.atoms.get_potential_energy()
|
| 243 | 1 | tkerber | results.append((d, e)) |
| 244 | 1 | tkerber | txt = txt + ("%.3f\t\t%.3f\n" % (d, e))
|
| 245 | 1 | tkerber | self.output.set_text(txt)
|
| 246 | 1 | tkerber | if self.radio_results_all.get_active(): |
| 247 | 1 | tkerber | self.store_atoms()
|
| 248 | 1 | tkerber | except AseGuiCancelException:
|
| 249 | 1 | tkerber | # Update display to reflect cancellation of simulation.
|
| 250 | 1 | tkerber | self.status_label.set_text("Calculation CANCELLED.") |
| 251 | 1 | tkerber | self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 252 | 1 | tkerber | gtk.gdk.color_parse('#AA4000'))
|
| 253 | 1 | tkerber | except MemoryError: |
| 254 | 1 | tkerber | self.status_label.set_text("Out of memory, consider using LBFGS instead") |
| 255 | 1 | tkerber | self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 256 | 1 | tkerber | gtk.gdk.color_parse('#AA4000'))
|
| 257 | 1 | tkerber | |
| 258 | 1 | tkerber | else:
|
| 259 | 1 | tkerber | # Update display to reflect succesful end of simulation.
|
| 260 | 1 | tkerber | self.status_label.set_text("Calculation completed.") |
| 261 | 1 | tkerber | self.status_label.modify_fg(gtk.STATE_NORMAL,
|
| 262 | 1 | tkerber | gtk.gdk.color_parse('#007700'))
|
| 263 | 1 | tkerber | |
| 264 | 1 | tkerber | if results:
|
| 265 | 1 | tkerber | self.do_fit(np.array(results))
|
| 266 | 1 | tkerber | if self.radio_results_optimal.get_active(): |
| 267 | 1 | tkerber | if self.minimum_ok: |
| 268 | 1 | tkerber | deformation = np.diag(1.0 + self.x0 * deform_axes) |
| 269 | 1 | tkerber | self.atoms.set_cell(np.dot(undef_cell, deformation),
|
| 270 | 1 | tkerber | scale_atoms=True)
|
| 271 | 1 | tkerber | if self.radio_relax_on.get_active(): |
| 272 | 1 | tkerber | if self.gui.simulation.has_key('progress'): |
| 273 | 1 | tkerber | self.gui.simulation['progress'].set_scale_progress( |
| 274 | 1 | tkerber | len(steps))
|
| 275 | 1 | tkerber | algo = getattr(ase.optimize, mininame)
|
| 276 | 1 | tkerber | minimizer = algo(self.atoms, logfile=logger)
|
| 277 | 1 | tkerber | minimizer.run(fmax=fmax, steps=self.steps.value)
|
| 278 | 1 | tkerber | # Store the optimal configuration.
|
| 279 | 1 | tkerber | self.prepare_store_atoms()
|
| 280 | 1 | tkerber | self.store_atoms()
|
| 281 | 1 | tkerber | else:
|
| 282 | 1 | tkerber | oops("No trustworthy minimum: Old configuration kept.")
|
| 283 | 1 | tkerber | self.activate_output()
|
| 284 | 1 | tkerber | self.gui.notify_vulnerable()
|
| 285 | 1 | tkerber | self.end()
|
| 286 | 1 | tkerber | |
| 287 | 1 | tkerber | # If we store all configurations: Open movie window and energy graph
|
| 288 | 1 | tkerber | if self.gui.images.nimages > 1: |
| 289 | 1 | tkerber | self.gui.movie()
|
| 290 | 1 | tkerber | assert not np.isnan(self.gui.images.E[0]) |
| 291 | 1 | tkerber | if not self.gui.plot_graphs_newatoms(): |
| 292 | 1 | tkerber | expr = 'i, e - E[-1]'
|
| 293 | 1 | tkerber | self.gui.plot_graphs(expr=expr)
|
| 294 | 1 | tkerber | # Continuations should use the best image
|
| 295 | 1 | tkerber | nbest = np.argmin(np.array(results)[:,1])
|
| 296 | 1 | tkerber | self.start_nth_adj.value = nbest
|
| 297 | 1 | tkerber | |
| 298 | 1 | tkerber | |
| 299 | 1 | tkerber | def change_fit(self, widget): |
| 300 | 1 | tkerber | "Repeat the fitting if the order is changed."
|
| 301 | 1 | tkerber | # It may be called both for the button being turned on and the
|
| 302 | 1 | tkerber | # one being turned off. But we only want to call do_fit once.
|
| 303 | 1 | tkerber | # And only if there are already cached results (ie. if the
|
| 304 | 1 | tkerber | # order is changed AFTER the calculation is done).
|
| 305 | 1 | tkerber | if widget.get_active() and getattr(self, "results", None) is not None: |
| 306 | 1 | tkerber | self.do_fit(None) |
| 307 | 1 | tkerber | |
| 308 | 1 | tkerber | def do_fit(self, results): |
| 309 | 1 | tkerber | "Fit the results to a polynomial"
|
| 310 | 1 | tkerber | if results is None: |
| 311 | 1 | tkerber | results = self.results # Use cached results |
| 312 | 1 | tkerber | else:
|
| 313 | 1 | tkerber | self.results = results # Keep for next time |
| 314 | 1 | tkerber | self.minimum_ok = False |
| 315 | 1 | tkerber | if self.radio_fit_3.get_active(): |
| 316 | 1 | tkerber | order = 3
|
| 317 | 1 | tkerber | else:
|
| 318 | 1 | tkerber | order = 2
|
| 319 | 1 | tkerber | |
| 320 | 1 | tkerber | if len(results) < 3: |
| 321 | 1 | tkerber | txt = ("Insufficent data for a fit\n(only %i data points)\n"
|
| 322 | 1 | tkerber | % (len(results),) )
|
| 323 | 1 | tkerber | order = 0
|
| 324 | 1 | tkerber | elif len(results) == 3 and order == 3: |
| 325 | 1 | tkerber | txt = "REVERTING TO 2ND ORDER FIT\n(only 3 data points)\n\n"
|
| 326 | 1 | tkerber | order = 2
|
| 327 | 1 | tkerber | else:
|
| 328 | 1 | tkerber | txt = ""
|
| 329 | 1 | tkerber | |
| 330 | 1 | tkerber | if order > 0: |
| 331 | 1 | tkerber | fit0 = np.poly1d(np.polyfit(results[:,0], results[:,1], order)) |
| 332 | 1 | tkerber | fit1 = np.polyder(fit0, 1)
|
| 333 | 1 | tkerber | fit2 = np.polyder(fit1, 1)
|
| 334 | 1 | tkerber | |
| 335 | 1 | tkerber | x0 = None
|
| 336 | 1 | tkerber | for t in np.roots(fit1): |
| 337 | 1 | tkerber | if fit2(t) > 0: |
| 338 | 1 | tkerber | x0 = t |
| 339 | 1 | tkerber | break
|
| 340 | 1 | tkerber | if x0 is None: |
| 341 | 1 | tkerber | txt = txt + "No minimum found!"
|
| 342 | 1 | tkerber | else:
|
| 343 | 1 | tkerber | e0 = fit0(x0) |
| 344 | 1 | tkerber | e2 = fit2(x0) |
| 345 | 1 | tkerber | txt += "E = "
|
| 346 | 1 | tkerber | if order == 3: |
| 347 | 1 | tkerber | txt += "A(x - x0)³ + "
|
| 348 | 1 | tkerber | txt += "B(x - x0)² + C\n\n"
|
| 349 | 1 | tkerber | txt += "B = %.5g eV\n" % (e2,)
|
| 350 | 1 | tkerber | txt += "C = %.5g eV\n" % (e0,)
|
| 351 | 1 | tkerber | txt += "x0 = %.5g\n" % (x0,)
|
| 352 | 1 | tkerber | lowest = self.scale_offset.value - self.max_scale.value |
| 353 | 1 | tkerber | highest = self.scale_offset.value + self.max_scale.value |
| 354 | 1 | tkerber | if x0 < lowest or x0 > highest: |
| 355 | 1 | tkerber | txt += "\nWARNING: Minimum is outside interval\n"
|
| 356 | 1 | tkerber | txt += "It is UNRELIABLE!\n"
|
| 357 | 1 | tkerber | else:
|
| 358 | 1 | tkerber | self.minimum_ok = True |
| 359 | 1 | tkerber | self.x0 = x0
|
| 360 | 1 | tkerber | self.fit_output.set_text(txt)
|