Source code for vasp_step.tk_energy

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

"""The graphical part of a Energy step"""

import json
from pathlib import Path
import pprint  # noqa: F401
import tkinter as tk
import tkinter.ttk as ttk

import vasp_step  # noqa: F401, E999
import seamm
from seamm_util import ureg, Q_, units_class, CompactJSONEncoder  # noqa: F401, E999
import seamm_widgets as sw

default_potentials = {
    "potpaw_PBE.64": {
        "H": "H",
        "He": "He",
        "Li": "Li_sv",
        "Be": "Be",
        "B": "B",
        "C": "C",
        "N": "N",
        "O": "O",
        "F": "F",
        "Ne": "Ne",
        "Na": "Na_pv",
        "Mg": "Mg",
        "Al": "Al",
        "Si": "Si",
        "P": "P",
        "S": "S",
        "Cl": "Cl",
        "Ar": "Ar",
        "K": "K_sv",
        "Ca": "Ca_sv",
        "Sc": "Sc_sv",
        "Ti": "Ti_sv",
        "V": "V_sv",
        "Cr": "Cr_pv",
        "Mn": "Mn_pv",
        "Fe": "Fe",
        "Co": "Co",
        "Ni": "Ni",
        "Cu": "Cu",
        "Zn": "Zn",
        "Ga": "Ga_d",
        "Ge": "Ge_d",
        "As": "As",
        "Se": "Se",
        "Br": "Br",
        "Kr": "Kr",
        "Rb": "Rb_sv",
        "Sr": "Sr_sv",
        "Y": "Y_sv",
        "Zr": "Zr_sv",
        "Nb": "Nb_sv",
        "Mo": "Mo_sv",
        "Tc": "Tc_pv",
        "Ru": "Ru_pv",
        "Rh": "Rh_pv",
        "Pd": "Pd",
        "Ag": "Ag",
        "Cd": "Cd",
        "In": "In_d",
        "Sn": "Sn_d",
        "Sb": "Sb",
        "Te": "Te",
        "I": "I",
        "Xe": "Xe",
        "Cs": "Cs_sv",
        "Ba": "Ba_sv",
        "La": "La",
        "Ce": "Ce",
        "Pr": "Pr_3",
        "Nd": "Nd_3",
        "Pm": "Pm_3",
        "Sm": "Sm_3",
        "Eu": "Eu_2",
        "Gd": "Gd_3",
        "Tb": "Tb_3",
        "Dy": "Dy_3",
        "Ho": "Ho_3",
        "Er": "Er_3",
        "Tm": "Tm_3",
        "Yb": "Yb_2",
        "Lu": "Lu_3",
        "Hf": "Hf_pv",
        "Ta": "Ta_pv",
        "W": "W_sv",
        "Re": "Re",
        "Os": "Os",
        "Ir": "Ir",
        "Pt": "Pt",
        "Au": "Au",
        "Hg": "Hg",
        "Tl": "Tl_d",
        "Pb": "Pb_d",
        "Bi": "Bi_d",
        "Po": "Po_d",
        "At": "At",
        "Rn": "Rn",
        "Fr": "Fr_sv",
        "Ra": "Ra_sv",
        "Ac": "Ac",
        "Th": "Th",
        "Pa": "Pa",
        "U": "U",
        "Np": "Np",
        "Pu": "Pu",
        "Am": "Am",
        "Cm": "Cm",
        "Cf": "Cf",
    },
    "potpaw_LDA.64": {
        "H": "H",
        "He": "He",
        "Li": "Li_sv",
        "Be": "Be",
        "B": "B",
        "C": "C",
        "N": "N",
        "O": "O",
        "F": "F",
        "Ne": "Ne",
        "Na": "Na_pv",
        "Mg": "Mg",
        "Al": "Al",
        "Si": "Si",
        "P": "P",
        "S": "S",
        "Cl": "Cl",
        "Ar": "Ar",
        "K": "K_sv",
        "Ca": "Ca_sv",
        "Sc": "Sc_sv",
        "Ti": "Ti_sv",
        "V": "V_sv",
        "Cr": "Cr_pv",
        "Mn": "Mn_pv",
        "Fe": "Fe",
        "Co": "Co",
        "Ni": "Ni",
        "Cu": "Cu",
        "Zn": "Zn",
        "Ga": "Ga_d",
        "Ge": "Ge_d",
        "As": "As",
        "Se": "Se",
        "Br": "Br",
        "Kr": "Kr",
        "Rb": "Rb_sv",
        "Sr": "Sr_sv",
        "Y": "Y_sv",
        "Zr": "Zr_sv",
        "Nb": "Nb_sv",
        "Mo": "Mo_sv",
        "Tc": "Tc_pv",
        "Ru": "Ru_pv",
        "Rh": "Rh_pv",
        "Pd": "Pd",
        "Ag": "Ag",
        "Cd": "Cd",
        "In": "In_d",
        "Sn": "Sn_d",
        "Sb": "Sb",
        "Te": "Te",
        "I": "I",
        "Xe": "Xe",
        "Cs": "Cs_sv",
        "Ba": "Ba_sv",
        "La": "La",
        "Ce": "Ce",
        "Pr": "Pr_3",
        "Nd": "Nd_3",
        "Pm": "Pm_3",
        "Sm": "Sm_3",
        "Eu": "Eu_2",
        "Gd": "Gd_3",
        "Tb": "Tb_3",
        "Dy": "Dy_3",
        "Ho": "Ho_3",
        "Er": "Er_3",
        "Tm": "Tm_3",
        "Yb": "Yb_2",
        "Lu": "Lu_3",
        "Hf": "Hf_pv",
        "Ta": "Ta_pv",
        "W": "W_sv",
        "Re": "Re",
        "Os": "Os",
        "Ir": "Ir",
        "Pt": "Pt",
        "Au": "Au",
        "Hg": "Hg",
        "Tl": "Tl_d",
        "Pb": "Pb_d",
        "Bi": "Bi_d",
        "Po": "Po_d",
        "At": "At",
        "Rn": "Rn",
        "Fr": "Fr_sv",
        "Ra": "Ra_sv",
        "Ac": "Ac",
        "Th": "Th",
        "Pa": "Pa",
        "U": "U",
        "Np": "Np",
        "Pu": "Pu",
        "Am": "Am",
        "Cm": "Cm",
        "Cf": "Cf",
    },
    "potpaw_PBE.64_GW": {
        "H": "H_GW",
        "He": "He_GW",
        "Li": "Li_sv_GW",
        "Be": "Be_sv_GW",
        "B": "B_GW",
        "C": "C_GW",
        "N": "N_GW",
        "O": "O_GW",
        "F": "F_GW",
        "Ne": "Ne_GW",
        "Na": "Na_sv_GW",
        "Mg": "Mg_sv_GW",
        "Al": "Al_GW",
        "Si": "Si_GW",
        "P": "P_GW",
        "S": "S_GW",
        "Cl": "Cl_GW",
        "Ar": "Ar_GW",
        "K": "K_sv_GW",
        "Ca": "Ca_sv_GW",
        "Sc": "Sc_sv_GW",
        "Ti": "Ti_sv_GW",
        "V": "V_sv_GW",
        "Cr": "Cr_sv_GW",
        "Mn": "Mn_sv_GW",
        "Fe": "Fe_sv_GW",
        "Co": "Co_sv_GW",
        "Ni": "Ni_sv_GW",
        "Cu": "Cu_sv_GW",
        "Zn": "Zn_sv_GW",
        "Ga": "Ga_d_GW",
        "Ge": "Ge_d_GW",
        "As": "As_GW",
        "Se": "Se_GW",
        "Br": "Br_GW",
        "Kr": "Kr_GW",
        "Rb": "Rb_sv_GW",
        "Sr": "Sr_sv_GW",
        "Y": "Y_sv_GW",
        "Zr": "Zr_sv_GW",
        "Nb": "Nb_sv_GW",
        "Mo": "Mo_sv_GW",
        "Tc": "Tc_sv_GW",
        "Ru": "Ru_sv_GW",
        "Rh": "Rh_sv_GW",
        "Pd": "Pd_sv_GW",
        "Ag": "Ag_sv_GW",
        "Cd": "Cd_sv_GW",
        "In": "In_d_GW",
        "Sn": "Sn_d_GW",
        "Sb": "Sb_d_GW",
        "Te": "Te_GW",
        "I": "I_GW",
        "Xe": "Xe_GW",
        "Cs": "Cs_sv_GW",
        "Ba": "Ba_sv_GW",
        "La": "La_GW",
        "Ce": "Ce_GW",
        "Hf": "Hf_sv_GW",
        "Ta": "Ta_sv_GW",
        "W": "W_sv_GW",
        "Re": "Re_sv_GW",
        "Os": "Os_sv_GW",
        "Ir": "Ir_sv_GW",
        "Pt": "Pt_sv_GW",
        "Au": "Au_sv_GW",
        "Hg": "Hg_sv_GW",
        "Tl": "Tl_d_GW",
        "Pb": "Pb_d_GW",
        "Bi": "Bi_d_GW",
        "Po": "Po_d_GW",
        "At": "At_d_GW",
        "Rn": "Rn_d_GW",
    },
    "potpaw_LDA.64_GW": {
        "H": "H_GW",
        "He": "He_GW",
        "Li": "Li_sv_GW",
        "Be": "Be_sv_GW",
        "B": "B_GW",
        "C": "C_GW",
        "N": "N_GW",
        "O": "O_GW",
        "F": "F_GW",
        "Ne": "Ne_GW",
        "Na": "Na_sv_GW",
        "Mg": "Mg_sv_GW",
        "Al": "Al_GW",
        "Si": "Si_GW",
        "P": "P_GW",
        "S": "S_GW",
        "Cl": "Cl_GW",
        "Ar": "Ar_GW",
        "K": "K_sv_GW",
        "Ca": "Ca_sv_GW",
        "Sc": "Sc_sv_GW",
        "Ti": "Ti_sv_GW",
        "V": "V_sv_GW",
        "Cr": "Cr_sv_GW",
        "Mn": "Mn_sv_GW",
        "Fe": "Fe_sv_GW",
        "Co": "Co_sv_GW",
        "Ni": "Ni_sv_GW",
        "Cu": "Cu_sv_GW",
        "Zn": "Zn_sv_GW",
        "Ga": "Ga_d_GW",
        "Ge": "Ge_d_GW",
        "As": "As_GW",
        "Se": "Se_GW",
        "Br": "Br_GW",
        "Kr": "Kr_GW",
        "Rb": "Rb_sv_GW",
        "Sr": "Sr_sv_GW",
        "Y": "Y_sv_GW",
        "Zr": "Zr_sv_GW",
        "Nb": "Nb_sv_GW",
        "Mo": "Mo_sv_GW",
        "Tc": "Tc_sv_GW",
        "Ru": "Ru_sv_GW",
        "Rh": "Rh_sv_GW",
        "Pd": "Pd_sv_GW",
        "Ag": "Ag_sv_GW",
        "Cd": "Cd_sv_GW",
        "In": "In_d_GW",
        "Sn": "Sn_d_GW",
        "Sb": "Sb_d_GW",
        "Te": "Te_GW",
        "I": "I_GW",
        "Xe": "Xe_GW",
        "Cs": "Cs_sv_GW",
        "Ba": "Ba_sv_GW",
        "La": "La_GW",
        "Ce": "Ce_GW",
        "Hf": "Hf_sv_GW",
        "Ta": "Ta_sv_GW",
        "W": "W_sv_GW",
        "Re": "Re_sv_GW",
        "Os": "Os_sv_GW",
        "Ir": "Ir_sv_GW",
        "Pt": "Pt_sv_GW",
        "Au": "Au_sv_GW",
        "Hg": "Hg_sv_GW",
        "Tl": "Tl_d_GW",
        "Pb": "Pb_d_GW",
        "Bi": "Bi_d_GW",
        "Po": "Po_d_GW",
        "At": "At_d_GW",
        "Rn": "Rn_d_GW",
    },
    "potpaw_PBE.54": {
        "H": "H",
        "He": "He",
        "Li": "Li_sv",
        "Be": "Be",
        "B": "B",
        "C": "C",
        "N": "N",
        "O": "O",
        "F": "F",
        "Ne": "Ne",
        "Na": "Na_pv",
        "Mg": "Mg",
        "Al": "Al",
        "Si": "Si",
        "P": "P",
        "S": "S",
        "Cl": "Cl",
        "Ar": "Ar",
        "K": "K_sv",
        "Ca": "Ca_sv",
        "Sc": "Sc_sv",
        "Ti": "Ti_sv",
        "V": "V_sv",
        "Cr": "Cr_pv",
        "Mn": "Mn_pv",
        "Fe": "Fe",
        "Co": "Co",
        "Ni": "Ni",
        "Cu": "Cu",
        "Zn": "Zn",
        "Ga": "Ga_d",
        "Ge": "Ge_d",
        "As": "As",
        "Se": "Se",
        "Br": "Br",
        "Kr": "Kr",
        "Rb": "Rb_sv",
        "Sr": "Sr_sv",
        "Y": "Y_sv",
        "Zr": "Zr_sv",
        "Nb": "Nb_sv",
        "Mo": "Mo_sv",
        "Tc": "Tc_pv",
        "Ru": "Ru_pv",
        "Rh": "Rh_pv",
        "Pd": "Pd",
        "Ag": "Ag",
        "Cd": "Cd",
        "In": "In_d",
        "Sn": "Sn_d",
        "Sb": "Sb",
        "Te": "Te",
        "I": "I",
        "Xe": "Xe",
        "Cs": "Cs_sv",
        "Ba": "Ba_sv",
        "La": "La",
        "Ce": "Ce",
        "Pr": "Pr_3",
        "Nd": "Nd_3",
        "Pm": "Pm_3",
        "Sm": "Sm_3",
        "Eu": "Eu_2",
        "Gd": "Gd_3",
        "Tb": "Tb_3",
        "Dy": "Dy_3",
        "Ho": "Ho_3",
        "Er": "Er_3",
        "Tm": "Tm_3",
        "Yb": "Yb_2",
        "Lu": "Lu_3",
        "Hf": "Hf_pv",
        "Ta": "Ta_pv",
        "W": "W_sv",
        "Re": "Re",
        "Os": "Os",
        "Ir": "Ir",
        "Pt": "Pt",
        "Au": "Au",
        "Hg": "Hg",
        "Tl": "Tl_d",
        "Pb": "Pb_d",
        "Bi": "Bi_d",
        "Po": "Po_d",
        "At": "At",
        "Rn": "Rn",
        "Fr": "Fr_sv",
        "Ra": "Ra_sv",
        "Ac": "Ac",
        "Th": "Th",
        "Pa": "Pa",
        "U": "U",
        "Np": "Np",
        "Pu": "Pu",
        "Am": "Am",
        "Cm": "Cm",
        "Cf": "Cf",
    },
    "potpaw_LDA.54": {
        "H": "H",
        "He": "He",
        "Li": "Li_sv",
        "Be": "Be",
        "B": "B",
        "C": "C",
        "N": "N",
        "O": "O",
        "F": "F",
        "Ne": "Ne",
        "Na": "Na_pv",
        "Mg": "Mg",
        "Al": "Al",
        "Si": "Si",
        "P": "P",
        "S": "S",
        "Cl": "Cl",
        "Ar": "Ar",
        "K": "K_sv",
        "Ca": "Ca_sv",
        "Sc": "Sc_sv",
        "Ti": "Ti_sv",
        "V": "V_sv",
        "Cr": "Cr_pv",
        "Mn": "Mn_pv",
        "Fe": "Fe",
        "Co": "Co",
        "Ni": "Ni",
        "Cu": "Cu",
        "Zn": "Zn",
        "Ga": "Ga_d",
        "Ge": "Ge_d",
        "As": "As",
        "Se": "Se",
        "Br": "Br",
        "Kr": "Kr",
        "Rb": "Rb_sv",
        "Sr": "Sr_sv",
        "Y": "Y_sv",
        "Zr": "Zr_sv",
        "Nb": "Nb_sv",
        "Mo": "Mo_sv",
        "Tc": "Tc_pv",
        "Ru": "Ru_pv",
        "Rh": "Rh_pv",
        "Pd": "Pd",
        "Ag": "Ag",
        "Cd": "Cd",
        "In": "In_d",
        "Sn": "Sn_d",
        "Sb": "Sb",
        "Te": "Te",
        "I": "I",
        "Xe": "Xe",
        "Cs": "Cs_sv",
        "Ba": "Ba_sv",
        "La": "La",
        "Ce": "Ce",
        "Hf": "Hf_pv",
        "Ta": "Ta_pv",
        "W": "W_sv",
        "Re": "Re",
        "Os": "Os",
        "Ir": "Ir",
        "Pt": "Pt",
        "Au": "Au",
        "Hg": "Hg",
        "Tl": "Tl_d",
        "Pb": "Pb_d",
        "Bi": "Bi_d",
        "Po": "Po_d",
        "At": "At",
        "Rn": "Rn",
        "Fr": "Fr_sv",
        "Ra": "Ra_sv",
        "Ac": "Ac",
        "Th": "Th",
        "Pa": "Pa",
        "U": "U",
        "Np": "Np",
        "Pu": "Pu",
        "Am": "Am",
        "Cm": "Cm",
    },
    "potpaw_PBE.54_GW": {
        "H": "H_GW",
        "He": "He_GW",
        "Li": "Li_sv_GW",
        "Be": "Be_sv_GW",
        "B": "B_GW",
        "C": "C_GW",
        "N": "N_GW",
        "O": "O_GW",
        "F": "F_GW",
        "Ne": "Ne_GW",
        "Na": "Na_sv_GW",
        "Mg": "Mg_sv_GW",
        "Al": "Al_GW",
        "Si": "Si_GW",
        "P": "P_GW",
        "S": "S_GW",
        "Cl": "Cl_GW",
        "Ar": "Ar_GW",
        "K": "K_sv_GW",
        "Ca": "Ca_sv_GW",
        "Sc": "Sc_sv_GW",
        "Ti": "Ti_sv_GW",
        "V": "V_sv_GW",
        "Cr": "Cr_sv_GW",
        "Mn": "Mn_sv_GW",
        "Fe": "Fe_sv_GW",
        "Co": "Co_sv_GW",
        "Ni": "Ni_sv_GW",
        "Cu": "Cu_sv_GW",
        "Zn": "Zn_sv_GW",
        "Ga": "Ga_d_GW",
        "Ge": "Ge_d_GW",
        "As": "As_GW",
        "Se": "Se_GW",
        "Br": "Br_GW",
        "Kr": "Kr_GW",
        "Rb": "Rb_sv_GW",
        "Sr": "Sr_sv_GW",
        "Y": "Y_sv_GW",
        "Zr": "Zr_sv_GW",
        "Nb": "Nb_sv_GW",
        "Mo": "Mo_sv_GW",
        "Tc": "Tc_sv_GW",
        "Ru": "Ru_sv_GW",
        "Rh": "Rh_sv_GW",
        "Pd": "Pd_sv_GW",
        "Ag": "Ag_sv_GW",
        "Cd": "Cd_sv_GW",
        "In": "In_d_GW",
        "Sn": "Sn_d_GW",
        "Sb": "Sb_d_GW",
        "Te": "Te_GW",
        "I": "I_GW",
        "Xe": "Xe_GW",
        "Cs": "Cs_sv_GW",
        "Ba": "Ba_sv_GW",
        "La": "La_GW",
        "Ce": "Ce_GW",
        "Hf": "Hf_sv_GW",
        "Ta": "Ta_sv_GW",
        "W": "W_sv_GW",
        "Re": "Re_sv_GW",
        "Os": "Os_sv_GW",
        "Ir": "Ir_sv_GW",
        "Pt": "Pt_sv_GW",
        "Au": "Au_sv_GW",
        "Hg": "Hg_sv_GW",
        "Tl": "Tl_d_GW",
        "Pb": "Pb_d_GW",
        "Bi": "Bi_d_GW",
        "Po": "Po_d_GW",
        "At": "At_d_GW",
        "Rn": "Rn_d_GW",
    },
    "potpaw_LDA.54_GW": {
        "H": "H_GW",
        "He": "He_GW",
        "Li": "Li_sv_GW",
        "Be": "Be_sv_GW",
        "B": "B_GW",
        "C": "C_GW",
        "N": "N_GW",
        "O": "O_GW",
        "F": "F_GW",
        "Ne": "Ne_GW",
        "Na": "Na_sv_GW",
        "Mg": "Mg_sv_GW",
        "Al": "Al_GW",
        "Si": "Si_GW",
        "P": "P_GW",
        "S": "S_GW",
        "Cl": "Cl_GW",
        "Ar": "Ar_GW",
        "K": "K_sv_GW",
        "Ca": "Ca_sv_GW",
        "Sc": "Sc_sv_GW",
        "Ti": "Ti_sv_GW",
        "V": "V_sv_GW",
        "Cr": "Cr_sv_GW",
        "Mn": "Mn_sv_GW",
        "Fe": "Fe_sv_GW",
        "Co": "Co_sv_GW",
        "Ni": "Ni_sv_GW",
        "Cu": "Cu_sv_GW",
        "Zn": "Zn_sv_GW",
        "Ga": "Ga_d_GW",
        "Ge": "Ge_d_GW",
        "As": "As_GW",
        "Se": "Se_GW",
        "Br": "Br_GW",
        "Kr": "Kr_GW",
        "Rb": "Rb_sv_GW",
        "Sr": "Sr_sv_GW",
        "Y": "Y_sv_GW",
        "Zr": "Zr_sv_GW",
        "Nb": "Nb_sv_GW",
        "Mo": "Mo_sv_GW",
        "Tc": "Tc_sv_GW",
        "Ru": "Ru_sv_GW",
        "Rh": "Rh_sv_GW",
        "Pd": "Pd_sv_GW",
        "Ag": "Ag_sv_GW",
        "Cd": "Cd_sv_GW",
        "In": "In_d_GW",
        "Sn": "Sn_d_GW",
        "Sb": "Sb_d_GW",
        "Te": "Te_GW",
        "I": "I_GW",
        "Xe": "Xe_GW",
        "Cs": "Cs_sv_GW",
        "Ba": "Ba_sv_GW",
        "La": "La_GW",
        "Ce": "Ce_GW",
        "Hf": "Hf_sv_GW",
        "Ta": "Ta_sv_GW",
        "W": "W_sv_GW",
        "Re": "Re_sv_GW",
        "Os": "Os_sv_GW",
        "Ir": "Ir_sv_GW",
        "Pt": "Pt_sv_GW",
        "Au": "Au_sv_GW",
        "Hg": "Hg_sv_GW",
        "Tl": "Tl_d_GW",
        "Pb": "Pb_d_GW",
        "Bi": "Bi_d_GW",
        "Po": "Po_d_GW",
        "At": "At_d_GW",
        "Rn": "Rn_d_GW",
    },
}

element_layout = [
    [
        "H",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "He",
    ],  # noqa: E501, E201
    [
        "Li",
        "Be",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "B",
        "C",
        "N",
        "O",
        "F",
        "Ne",
    ],  # noqa: E501
    [
        "Na",
        "Mg",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "",
        "Al",
        "Si",
        "P",
        "S",
        "Cl",
        "Ar",
    ],  # noqa: E501
    [
        "K",
        "Ca",
        "",
        "Sc",
        "Ti",
        "V",
        "Cr",
        "Mn",
        "Fe",
        "Co",
        "Ni",
        "Cu",
        "Zn",
        "Ga",
        "Ge",
        "As",
        "Se",
        "Br",
        "Kr",
    ],  # noqa: E501, E201
    [
        "Rb",
        "Sr",
        "",
        "Y",
        "Zr",
        "Nb",
        "Mo",
        "Tc",
        "Ru",
        "Rh",
        "Pd",
        "Ag",
        "Cd",
        "In",
        "Sn",
        "Sb",
        "Te",
        "I",
        "Xe",
    ],  # noqa: E501
    [
        "Cs",
        "Ba",
        "",
        "Lu",
        "Hf",
        "Ta",
        "W",
        "Re",
        "Os",
        "Ir",
        "Pt",
        "Au",
        "Hg",
        "Tl",
        "Pb",
        "Bi",
        "Po",
        "At",
        "Rn",
    ],  # noqa: E501
    [
        "Fr",
        "Ra",
        "",
        "Lr",
        "Rf",
        "Db",
        "Sg",
        "Bh",
        "Hs",
        "Mt",
        "Ds",
        "Rg",
        "Cn",
        "Nh",
        "Fl",
        "Mc",
        "Lv",
        "Ts",
        "Og",
    ],  # noqa: E501
    [],
    [
        "",
        "",
        "",
        "La",
        "Ce",
        "Pr",
        "Nd",
        "Pm",
        "Sm",
        "Eu",
        "Gd",
        "Tb",
        "Dy",
        "Ho",
        "Er",
        "Tm",
        "Yb",
    ],  # noqa: E501, E201
    [
        "",
        "",
        "",
        "Ac",
        "Th",
        "Pa",
        "U",
        "Np",
        "Pu",
        "Am",
        "Cm",
        "Bk",
        "Cf",
        "Es",
        "Fm",
        "Md",
        "No",
    ],  # noqa: E501, E201
]  # yapf: disable


[docs] class TkEnergy(seamm.TkNode): """ The graphical part of a Energy 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 Energy_parameters.py See Also -------- Energy, TkEnergy, EnergyParameters, """ 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 self.available = {} # The available potentials for the current set self.current_potential_set = None self.default_potential = {} super().__init__( tk_flowchart=tk_flowchart, node=node, canvas=canvas, x=x, y=y, w=w, h=h, ) # Make sure we have the information about the PAW potentials directory = Path("~/SEAMM/Parameters/VASP").expanduser() index = directory / "index.json" if index.exists(): with index.open() as fd: self.potential_metadata = json.load(fd) else: self.potential_metadata = self.node.parent.catalog_potentials() with index.open("w") as fd: json.dump( self.potential_metadata, fd, indent=4, sort_keys=True, cls=CompactJSONEncoder, ) print(f"Wrote the index to {index}")
[docs] def create_dialog(self, title="Energy"): """ Create the dialog. A set of widgets will be chosen by default based on what is specified in the Energy_parameters module. Parameters ---------- None Returns ------- None See Also -------- TkEnergy.reset_dialog """ # Shortcut for parameters P = self.node.parameters frame = super().create_dialog(title=title, default_number_values=1) # Make scrollable in case contents too large self["scrolled frame"] = sw.ScrolledFrame(frame) self["scrolled frame"].grid(row=0, column=0, sticky=tk.NSEW) frame.rowconfigure(0, weight=1) frame.columnconfigure(0, weight=1) main_frame = self["main frame"] = self["scrolled frame"].interior() # Then create the widgets for key in ( "input only", "use hdf5 files", "calculate stress", "save gradients", ): self[key] = P[key].widget(main_frame) # Frame to isolate widgets for the calculation definition calculation_frame = self["calculation frame"] = ttk.LabelFrame( main_frame, borderwidth=4, relief="sunken", text="Single-Point Energy Control", labelanchor="n", padding=10, ) # Then create the widgets and place them row = 0 widgets = [] for key in ("calculate stress", "save gradients"): w = self[key] = P[key].widget(calculation_frame) w.grid(row=row, column=0, sticky="ew") row += 1 widgets.append(w) sw.align_labels(widgets, sticky="e") # Frame to isolate widgets e_frame = self["model frame"] = ttk.LabelFrame( main_frame, borderwidth=4, relief="sunken", text="Electronic Structure Definition", labelanchor="n", padding=10, ) # Then create the widgets for key in ("model", "submodel", "spin polarization", "nonspherical PAW"): self[key] = P[key].widget(e_frame) try: self[key].configure(width=45) except Exception: pass for key in ("model", "submodel"): self[key].bind("<<ComboboxSelected>>", self.reset_model_frame) self[key].bind("<Return>", self.reset_model_frame) self[key].bind("<FocusOut>", self.reset_model_frame) # Frame for the control of the electronic minimization scf_frame = self["scf frame"] = ttk.LabelFrame( main_frame, borderwidth=4, relief="sunken", text="Electronic Minimization", labelanchor="n", padding=10, ) # Then create the widgets and place them row = 0 widgets = [] for key in ( "electronic method", "nelm", "nelmin", "ediff", "precision", "initial wavefunction", ): w = self[key] = P[key].widget(scf_frame) w.grid(row=row, column=0, sticky="ew") row += 1 widgets.append(w) sw.align_labels(widgets, sticky="e") for key in ("electronic method",): self[key].bind("<<ComboboxSelected>>", self.reset_performance_frame) self[key].bind("<Return>", self.reset_performance_frame) self[key].bind("<FocusOut>", self.reset_performance_frame) # The k-space integration k_frame = self["k-space frame"] = ttk.LabelFrame( main_frame, borderwidth=4, relief="sunken", text="K-space Integration", labelanchor="n", padding=10, ) for key in vasp_step.EnergyParameters.kspace_parameters: self[key] = P[key].widget(k_frame) for key in ("na", "nb", "nc"): self[key].entry.configure(width=4) for key in ("k-grid method", "occupation type"): self[key].bind("<<ComboboxSelected>>", self.reset_kspace_frame) self[key].bind("<Return>", self.reset_kspace_frame) self[key].bind("<FocusOut>", self.reset_kspace_frame) # Frame for the performance parameters performance_frame = self["performance frame"] = ttk.LabelFrame( main_frame, borderwidth=4, relief="sunken", text="Performance Parameters", labelanchor="n", padding=10, ) # Then create the widgets for key in ( "np", "ncore", "kpar", "lplane", "lreal", "lscalapack", "lscalu", "nsim", ): self[key] = P[key].widget(performance_frame) s_frame = self["structure frame"] = ttk.LabelFrame( main_frame, borderwidth=4, relief="sunken", text="Configuration Handling", labelanchor="n", padding=10, ) row = 0 widgets = [] for key in ("structure handling", "system name", "configuration name"): self[key] = P[key].widget(s_frame) self[key].grid(row=row, column=0, sticky=tk.EW) widgets.append(self[key]) row += 1 sw.align_labels(widgets, sticky=tk.E) # Top level needs to call reset_dialog to layout the dialog if self.node.calculation == "energy": self.reset_dialog() self.create_potentials_tab()
[docs] def create_potentials_tab(self): """Add a tab with a periodic table for setting the potentials.""" # Shortcut for parameters P = self.node.parameters notebook = self["notebook"] potentials_frame = ttk.Frame(notebook) self["potentials frame"] = potentials_frame notebook.insert( self["results frame"], potentials_frame, text="Potentials", sticky="nsew", ) row = 0 widgets = [] for key in ("set of potentials", "plane-wave cutoff"): self[key] = P[key].widget(potentials_frame) self[key].grid(row=row, column=0, sticky="ew") row += 1 widgets.append(self[key]) # Align the labels sw.align_labels(widgets, sticky="e") for key in ("set of potentials",): self[key].bind("<<ComboboxSelected>>", self._change_set) self[key].bind("<Return>", self._change_set) self[key].bind("<FocusOut>", self._change_set) # Display the max enmax next to the plane-wave cutoff for key in ("enmax",): w = self[key] = P[key].widget(potentials_frame) w.grid(row=1, column=1, sticky="w") w.config(state="readonly") # Put the possible potential sets into the widget metadata = self.potential_metadata sets = [*metadata.keys()] self.current_potential_set = self["set of potentials"].value self["set of potentials"].config(values=sets) if "GW" in P["subset"]: self.default_potential = default_potentials[ self.current_potential_set + "_GW" ] else: self.default_potential = default_potentials[self.current_potential_set] # This is used for the radiobutton to control what subset is show/used var = self.tk_var["subset"] = tk.StringVar() var.set(P["subset"]) # And make a scrollable periodic table area for the potentials self["scrolled periodic table"] = sw.ScrolledFrame(potentials_frame) self["scrolled periodic table"].grid( row=row, column=0, columnspan=2, sticky=tk.NSEW ) potentials_frame.rowconfigure(row, weight=1) potentials_frame.columnconfigure(1, weight=1) row += 1 frame = self["potentials"] = self["scrolled periodic table"].interior() # Create the widgets in the periodic table layout current = self.node.parameters["potentials"].value self.find_available_potentials() for _row, elements in enumerate(element_layout): for _col, element in enumerate(elements): if element != "": if element in self.available: w = self._widget[element] = ttk.Combobox( frame, values=[f"_{element}_", *self.available[element]], width=6, ) if element in current: w.set(current[element]) else: w.set(self.default_potential[element]) else: w = self._widget[element] = ttk.Combobox( frame, width=5, ) w.set(f"_{element}_") w.config(state="disabled") w.grid(row=_row, column=_col, sticky=tk.EW) w.bind("<<ComboboxSelected>>", self.update_Emax) w.bind("<Return>", self.update_Emax) w.bind("<FocusOut>", self.update_Emax) self.update_Emax() # Radio button to allow selecting standard and GW potentials. for text in ( "Show all potentials", "Show standard potentials", "Show GW potentials", ): w = self._widget[text] = ttk.Radiobutton( potentials_frame, text=text, value=text, variable=self.tk_var["subset"], command=self._handle_show_potentials, ) w.grid(row=row, column=0, sticky="w") row += 1 w = self._widget["default potentials"] = ttk.Button( potentials_frame, text="Reset to default potentials", command=self._set_to_default_potentials, ) w.grid(row=row, column=0, sticky="w") row += 1 w = self._widget["clear all potentials"] = ttk.Button( potentials_frame, text="Clear all potentials", command=self._clear_potentials, ) w.grid(row=row, column=0, sticky="w") row += 1 frame.grid_columnconfigure(2, minsize=30) frame.grid_rowconfigure(7, minsize=30)
def _change_set(self, *args): """Handle changing the set of potentials to use.""" self.current_potential_set = self["set of potentials"].get() self._handle_show_potentials() def _handle_show_potentials(self, current=None): """Show or hide the standard or GW potentials.""" subset = self.tk_var["subset"].get() self.find_available_potentials() if "GW" in subset: self.default_potential = default_potentials[ self.current_potential_set + "_GW" ] else: self.default_potential = default_potentials[self.current_potential_set] if current is None: current = self.get_current_potentials() for elements in element_layout: for element in elements: if element != "": if element in self.available: self._widget[element].config( values=[f"_{element}_", *self.available[element]], state="!disabled", ) if element in current: if current[element] in self.available[element]: self._widget[element].set(current[element]) else: self._widget[element].set( self.default_potential[element] ) else: self._widget[element].set(f"_{element}_") else: self._widget[element].config(state="!disabled") self._widget[element].set(f"_{element}_") self._widget[element].config( values=[f"_{element}_"], state="disabled" ) self.update_Emax() def _set_to_default_potentials(self): """Reset to the default potentials.""" self.find_available_potentials() subset = self.tk_var["subset"].get() if "GW" in subset: self.default_potential = default_potentials[ self.current_potential_set + "_GW" ] else: self.default_potential = default_potentials[self.current_potential_set] for elements in element_layout: for element in elements: if element != "": if element in self.available: self._widget[element].set(self.default_potential[element]) else: self._widget[element].config(state="!disabled") self._widget[element].set(f"_{element}_") self._widget[element].config(state="disabled") self.update_Emax() def _clear_potentials(self): """Reset to the no potentials.""" for elements in element_layout: for element in elements: if element != "": self._widget[element].set(f"_{element}_") self.update_Emax()
[docs] def find_available_potentials(self): potential_data = self.potential_metadata[self.current_potential_set] self.available = {} subset = self.tk_var["subset"].get() for potential, data in potential_data.items(): if "GW" in subset: if "_GW" not in potential: continue elif "all" not in subset: if "_GW" in potential: continue el = potential.split("_")[0] if el in self.available: self.available[el].append(potential) else: self.available[el] = [potential] for el, tmp in self.available.items(): self.available[el] = sorted(tmp)
[docs] def get_current_potentials(self): """Get the currently selected potentials from the widgets.""" result = {} for elements in element_layout: for element in elements: if element != "": if element in self.available: tmp = self._widget[element].get() if tmp != "" and not tmp.startswith("_"): result[element] = tmp return result
[docs] def get_Emax(self): """Get the maximum ENMAX for the currently slsected potentials""" potential_data = self.potential_metadata[self.current_potential_set] Emax = 0 for elements in element_layout: for element in elements: if element != "": if element in self.available: potential = self._widget[element].get() if potential.startswith("_") or potential == "": pass else: Emax = max(Emax, float(potential_data[potential]["Emax"])) return Emax
[docs] def update_Emax(self, event=None): """Update the value of Emax in the display.""" self["enmax"].config(state="!readonly") self["enmax"].set(self.get_Emax(), unit_string="eV") self["enmax"].config(state="readonly")
[docs] def reset_dialog(self, widget=None, row=0): """Layout the widgets in the dialog. The widgets are chosen by default from the information in Energy_parameter. This function simply lays them out row by row with aligned labels. You may wish a more complicated layout that is controlled by values of some of the control parameters. If so, edit or override this method Parameters ---------- widget : Tk Widget = None Returns ------- None See Also -------- TkEnergy.create_dialog """ # Remove any widgets previously packed frame = self["main frame"] for slave in frame.grid_slaves(): slave.grid_forget() # Shortcut for parameters P = self.node.parameters # Whether to just write input widgets = [] for key in ("input only", "use hdf5 files"): self[key].grid(row=row, column=0, sticky=tk.W) widgets.append(self[key]) row += 1 sw.align_labels(widgets, sticky=tk.E) # The calculation and handling of the structure self["calculation frame"].grid( row=row, column=0, columnspan=2, pady=5, sticky="new" ) self["structure frame"].grid( row=row, column=2, columnspan=2, pady=5, sticky="new" ) row += 1 # The model for the calculation self["model frame"].grid(row=row, column=0, columnspan=2, pady=5, sticky="new") self["scf frame"].grid(row=row, column=2, columnspan=2, pady=5, sticky="new") row += 1 self["k-space frame"].grid( row=row, column=0, columnspan=2, pady=5, sticky="new" ) self["performance frame"].grid( row=row, column=2, columnspan=2, pady=5, sticky="new" ) row += 1 # Layout the energy widgets self.reset_calculation_frame() self.reset_model_frame() self.reset_kspace_frame() self.reset_performance_frame() # Setup the results if there are any have_results = ( "results" in self.node.metadata and len(self.node.metadata["results"]) > 0 ) if have_results and "results" in P: self.setup_results() return row
[docs] def reset_calculation_frame(self, widget=None): """Layout the widgets for the calculation control. Note ---- The single point energy has nothing that changes, so do nothing. """ pass
[docs] def reset_model_frame(self, widget=None): """Layout the widgets in the dialog. The widgets are chosen by default from the information in Energy_parameter. This function simply lays them out row by row with aligned labels. You may wish a more complicated layout that is controlled by values of some of the control parameters. If so, edit or override this method Parameters ---------- widget : Tk Widget = None Returns ------- None See Also -------- TkEnergy.create_dialog """ # Remove any widgets previously packed frame = self["model frame"] for slave in frame.grid_slaves(): slave.grid_forget() # Shortcut for parameters P = self.node.parameters # keep track of the row in a variable, so that the layout is flexible # if e.g. rows are skipped to control such as "method" here row = 0 # The model for the calculation keys = ["model", "submodel", "spin polarization", "nonspherical PAW"] model = self["model"].get() # And what models have available sublevels? model_data = self.node.metadata["computational models"][ "Density Functional Theory (DFT)" ]["models"] models = [] for tmp in model_data.keys(): models.append(tmp) w = self["model"] if w.combobox.cget("values") != models: w.config(values=models) if not self.is_expr(model) and model not in models and len(models) > 0: w.set(models[0]) else: w.set(model) # Fill out the possible submodels submodel = self["submodel"].get() choices = model_data[model]["parameterizations"] submodels = [*choices.keys()] w = self["submodel"] if w.combobox.cget("values") != submodels: w.config(values=submodels) if ( not self.is_expr(submodel) and submodel not in submodels and len(submodels) > 0 ): w.set(submodels[0]) else: w.set(submodel) # And the basis 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) frame.columnconfigure(0, weight=1) # Setup the results if there are any have_results = ( "results" in self.node.metadata and len(self.node.metadata["results"]) > 0 ) if have_results and "results" in P: self.setup_results()
[docs] def reset_kspace_frame(self, widget=None): """Layout the widgets in the dialog. The widgets are chosen by default from the information in Energy_parameter. This function simply lays them out row by row with aligned labels. You may wish a more complicated layout that is controlled by values of some of the control parameters. If so, edit or override this method Parameters ---------- widget : Tk Widget = None Returns ------- None See Also -------- TkEnergy.create_dialog """ # Remove any widgets previously packed frame = self["k-space frame"] for slave in frame.grid_slaves(): slave.grid_forget() # keep track of the row in a variable, so that the layout is flexible # if e.g. rows are skipped to control such as "method" here row = 0 widgets = [] widgets1 = [] # The model for the calculation key = "k-grid method" method = self[key].get() self[key].grid(row=row, column=0, columnspan=4, sticky=tk.W) widgets.append(self[key]) row += 1 if "explicit" in method: for col, key in enumerate(("na", "nb", "nc"), start=1): self[key].grid(row=row, column=col, sticky=tk.EW) row += 1 elif "point" in method: pass else: for key in ("k-spacing", "odd grid", "centering"): self[key].grid(row=row, column=1, columnspan=3, sticky=tk.EW) widgets1.append(self[key]) row += 1 key = "occupation type" smearing = self[key].get() self[key].grid(row=row, column=0, columnspan=4, sticky=tk.W) widgets.append(self[key]) row += 1 if "Methfessel-Paxton" in smearing: key = "Methfessel-Paxton order" self[key].grid(row=row, column=1, columnspan=3, sticky=tk.EW) widgets1.append(self[key]) row += 1 if "without smearing" not in smearing: key = "smearing width" self[key].grid(row=row, column=1, columnspan=3, sticky=tk.EW) widgets1.append(self[key]) row += 1 w0 = sw.align_labels(widgets, sticky=tk.E) w1 = sw.align_labels(widgets1, sticky=tk.E) minwidth = w0 - w1 + 30 frame.columnconfigure(0, minsize=minwidth) frame.columnconfigure(1, weight=1) frame.columnconfigure(2, weight=1) frame.columnconfigure(3, weight=1)
[docs] def reset_performance_frame(self, widget=None): """Layout the widgets in the performance frame. Parameters ---------- widget : Tk Widget = None Returns ------- None """ # Remove any widgets previously packed frame = self["performance frame"] for slave in frame.grid_slaves(): slave.grid_forget() electronic_method = self["electronic method"].get() keys = ["np", "ncore", "kpar", "lplane", "lreal", "lscalapack", "lscalu"] if ( self.is_expr(electronic_method) or "fast" in electronic_method or "normal" in electronic_method ): keys.append("nsim") 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)
[docs] def right_click(self, event): """ Handles the right click event on the node. Parameters ---------- event : Tk Event Returns ------- None See Also -------- TkEnergy.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)
[docs] def fit_dialog(self): """Make the dialog fill the window.""" screen_w = self.dialog.winfo_screenwidth() screen_h = self.dialog.winfo_screenheight() w = int(1.0 * screen_w) h = int(1.0 * screen_h) x = 0 y = int(0.0 * screen_h / 2) self.dialog.geometry(f"{w}x{h}+{x}+{y}")
[docs] def handle_dialog(self, result): """Handle closing the dialog. Parameters ---------- result : str The button that was pressed to close the dialog, or None if the x dialog close button was pressed. """ if result is None or result == "Cancel": # Reset the potentials to their original values P = self.node.parameters subset = P["subset"] self.tk_var["subset"].set(subset) for key in ("set of potentials", "plane-wave cutoff"): self[key].set(P[key]) self.current_potential_set = P["set of potentials"].value if "GW" in subset: self.default_potential = default_potentials[ self.current_potential_set + "_GW" ] else: self.default_potential = default_potentials[self.current_potential_set] current = self.node.parameters["potentials"].value self._handle_show_potentials(current) elif result == "OK": self.node.parameters["potentials"].value = self.get_current_potentials() # And let the superclass do the rest super().handle_dialog(result)