Source code for vasp_step.tk_optimization

# -*- coding: utf-8 -*-

"""The graphical part of a Optimization step"""

import tkinter as tk

from .tk_energy import TkEnergy
import seamm_widgets as sw


[docs] class TkOptimization(TkEnergy): """ The graphical part of a Optimization step in a flowchart. Attributes ---------- tk_flowchart : TkFlowchart = None The flowchart that we belong to. node : Node = None The corresponding node of the non-graphical flowchart canvas: tkCanvas = None The Tk Canvas to draw on dialog : Dialog The Pmw dialog object x : int = None The x-coordinate of the center of the picture of the node y : int = None The y-coordinate of the center of the picture of the node w : int = 200 The width in pixels of the picture of the node h : int = 50 The height in pixels of the picture of the node self[widget] : dict A dictionary of tk widgets built using the information contained in Optimization_parameters.py See Also -------- Optimization, TkOptimization, OptimizationParameters, """ def __init__( self, tk_flowchart=None, node=None, canvas=None, x=None, y=None, w=200, h=50, ): """ Initialize a graphical node. Parameters ---------- tk_flowchart: Tk_Flowchart The graphical flowchart that we are in. node: Node The non-graphical node for this step. namespace: str The stevedore namespace for finding sub-nodes. canvas: Canvas The Tk canvas to draw on. x: float The x position of the nodes center on the canvas. y: float The y position of the nodes cetner on the canvas. w: float The nodes graphical width, in pixels. h: float The nodes graphical height, in pixels. Returns ------- None """ self.dialog = None super().__init__( tk_flowchart=tk_flowchart, node=node, canvas=canvas, x=x, y=y, w=w, h=h, )
[docs] def create_dialog(self, title="Optimization"): """ Create the dialog. A set of widgets will be chosen by default based on what is specified in the Optimization_parameters module. Parameters ---------- None Returns ------- None See Also -------- TkOptimization.reset_dialog """ super().create_dialog(title=title) # Shortcut for parameters P = self.node.parameters calculation_frame = self["calculation frame"] calculation_frame.config(text="Optimization Control") # Then create the widgets for key in ( "optimize atom positions", "optimize cell shape", "optimize cell volume", "optimization method", "number of steps", "convergence cutoff", "step scale factor", "iteration history length", "damped MD approach", "force scale factor", "velocity scale factor", "velocity quenching factor", ): self[key] = P[key].widget(calculation_frame) for key in ( "optimize cell shape", "optimize cell volume", "optimization method", "damped MD approach", ): self[key].bind("<<ComboboxSelected>>", self.reset_calculation_frame) self[key].bind("<Return>", self.reset_calculation_frame) self[key].bind("<FocusOut>", self.reset_calculation_frame) # Top level needs to call reset_dialog to layout the dialog if self.node.calculation == "energy": self.reset_dialog()
[docs] def reset_calculation_frame(self, widget=None): """Layout the widgets in the calculation frame. Parameters ---------- widget : Tk Widget = None Returns ------- None """ # Remove any widgets previously packed frame = self["calculation frame"] for slave in frame.grid_slaves(): slave.grid_forget() # Place the control in the left column method = self["optimization method"].get() row = 0 widgets = [] keys = [] keys.append("optimization method") keys.append("number of steps") keys.append("convergence cutoff") if self.is_expr(method): keys.append("step scale factor") keys.append("iteration history length") keys.append("damped MD approach") elif method == "Damped MD": pass elif method == "RMM-DIIS": keys.append("step scale factor") keys.append("iteration history length") else: keys.append("step scale factor") if self.is_expr(method) or method == "Damped MD": damping_approach = self["damped MD approach"].get() keys.append("damped MD approach") if self.is_expr(damping_approach): keys.append("force scale factor") keys.append("velocity scale factor") keys.append("velocity quenching factor") elif damping_approach == "damping": keys.append("force scale factor") keys.append("velocity scale factor") else: keys.append("velocity quenching factor") row = 0 widgets = [] for key in keys: self[key].grid(row=row, column=0, sticky=tk.EW) widgets.append(self[key]) row += 1 # Align the labels sw.align_labels(widgets, sticky=tk.E) # Add the cell constraints in the second column shape = self["optimize cell shape"].get() == "yes" volume = self["optimize cell volume"].get() == "yes" keys = [ "optimize atom positions", "optimize cell shape", "optimize cell volume", ] if not shape and not volume: keys.append("calculate stress") keys.append("save gradients") # Place in the second column row = 0 widgets = [] for key in keys: self[key].grid(row=row, column=1, sticky=tk.EW) widgets.append(self[key]) row += 1 # Align the labels sw.align_labels(widgets, sticky=tk.E)
[docs] def right_click(self, event): """ Handles the right click event on the node. Parameters ---------- event : Tk Event Returns ------- None See Also -------- TkOptimization.edit """ super().right_click(event) self.popup_menu.add_command(label="Edit..", command=self.edit) self.popup_menu.tk_popup(event.x_root, event.y_root, 0)