Source code for siman.header

# -*- coding: utf-8 -*-
#Copyright Aksyonov D.A
#hello_man
from __future__ import division, unicode_literals, absolute_import, print_function

"""
Siman - management of VASP calculations
Author: Aksyonov D.A.


!Internal units are Angstroms!
Bohrs should be converted during reading!

TODO:


"""

import os, subprocess, sys, shelve
try:
    import matplotlib as mpl
    """Global matplotlib control"""
    # size = 22 #for one coloumn figures
    size = 16 #for DOS
    # size = 16 #for two coloumn figures
    mpl.rc('font',family='Serif')
    # mpl.rc('xtick', labelsize= size) 
    # mpl.rc('ytick', labelsize= size) 
    # mpl.rc('axes', labelsize = size) 
    # mpl.rc('legend', fontsize= size) 
    # mpl.rc('Axes.annotate', fontsize= size) #does not work
    mpl.rcParams.update({'font.size': size})
    mpl.rcParams.update({'mathtext.fontset': "stix"})
    # plt.rcParams['mathtext.fontset'] = "stix"

    #paths to libraries needed by siman
    # sys.path.append('/home/dim/Simulation_wrapper/ase') #
    # plt = None
except:
    mpl = None
    plt = None
    print('Warning! matplotlib is not installed! Some functions will not work!')

history = []

#Defaults to some project_conf values
PBS_PROCS = False # if true than #PBS -l procs="+str(number_cores) is used
WALLTIME_LIMIT = False # now only for PBS if True 72 hours limit is used


# warnings = 'neyY'
warnings = 'yY' # level of warnings to show: n - all, e - normal, y - important, Y - very important

#1. Read default global settings for siman package
from siman.default_project_conf import *

#2. Read user-related settings for siman
simanrc = os.path.expanduser("~/simanrc.py")
if os.path.exists(simanrc):
    # if 'n' in war
    print(simanrc, 'was read')
    sys.path.insert(0, os.path.dirname(simanrc))
    from simanrc import *

#3. Read project specific
if os.path.exists('./project_conf.py'):
    print('Reading ./project_conf.py')

    from project_conf import *
    siman_run = True
    log = open('log','a')
else:
    # print('Some module is used separately; default_project_conf.py is used')
    if mpl and not os.path.exists(simanrc):
        mpl.use('agg') #switch matplotlib on or off; for running script using ssh
    siman_run = False
    history.append('separate run')













try:
    import matplotlib.pyplot as plt
except:
    plt = None

calc_database = 'only_calc.gdbm3'

[docs]class CalcDict(dict): def __getitem__(self, key): # print(self) if type(key) == str: # print('String key detected', key) key_str = key l = key.split('.') if len(l) > 2 and l[-1].isdecimal(): key = ('.'.join(l[0:-2]), l[-2], int(l[-1])) # else: if dict.__contains__(self, key): # print('key', key, 'is in self') val = dict.__getitem__(self, key) else: with shelve.open(calc_database, protocol = 3) as d: try: val = d[str(key)] dict.__setitem__(self, key, val) # print('reading ',str(key), 'from db') except: print('Problem with key',key,', return None') val = None val = d[str(key)] # for k in d: # # print(k[0]) # if str(key) in k: # print(k) return val def __contains__(self, key): if dict.__contains__(self, key): return True else: with shelve.open(calc_database, protocol = 3) as d: # print('checking if key',key, 'is in db:', str(key) in d) # print(self) return str(key) in d
[docs] def items(self): keys = [] with shelve.open(calc_database, protocol = 3) as d: for key in d: key = key.replace("'", "").replace('(', '').replace(')', '') #remove unnessary symbols from string l = key.split(',') # go back to tuple if len(l) == 3 and l[2].strip().isdigit(): keyt = (l[0].strip(), l[1].strip(), int(l[2])) keys.append(keyt) return keys
#Global variables final_vasp_clean = True copy_to_cluster_flag = True close_run = False # alows to control close run file automatically after each add_loop first_run = True # needed to write header of run script ssh_object = None # paramiko ssh_object sshpass = None # using sshpass wrapper for rsync; see functions.py/push_to_server() show = None corenum = 1 check_job = 1 # check job by additional ssh requests reorganize = 0 # use this from time to time to optimize database file size verbose_log = 0 # in addition to normal log write verbose log in any case by openning the log_verbose each time cluster_address = '' override_cluster_address = 0 # 1 or 0, override read calculations to header.CLUSTERS[cluster]['address'], usefull when switching between proxy and back of the same cluster pymatgen_flag = None db = CalcDict() # global db calc = db conv = {}; varset = {}; struct_des = {}; sets = varset #Constants to_ang = 0.52917721092 to_eV = 27.21138386 Ha_Bohr_to_eV_A = 51.4220641868956 kB_to_GPa = 0.1 eV_A_to_J_m = 16.021765 eV_nm_to_J_m = 1.6021765 THz2eV = 0.00413566553853599 kJ_mol2eV = 1.0364e-2 J_mol_T2eV_T = 1.0364e-5 J2eV = 6.242e+18 h = 4.135668e-15 # eV/Hz F = 96485.3329 # sA/mol kB = 8.617e-5 # eV/K kB_SI = 1.380649e-23 # J/K R = 8.3145 # J/mol/K TRANSITION_ELEMENTS = [22, 23, 24, 25, 26, 27, 28, 29, 40, 44, 74] ALKALI_ION_ELEMENTS = [3, 11, 19, 37] MAGNETIC_ELEMENTS = [26, 27, 28] TM_MAG = {'NM':0.6, 'Co2+hs':3, 'Co2+ls':1, 'Co3+hs':4, 'Co3+ls':0, 'Co4+hs':5, 'Co4+ls':1, 'Ni2+':2, 'Ni3+hs':3, 'Ni3+ls':1, 'Ni4+hs':4, 'Ni4+ls':0, 'Mn3+ls':0, 'Mn3+hs':4, 'Mn2+hs':5,'Mn2+ls':1, 'Mn4+':3, 'Fe3+hs': 5, 'Fe3+ls': 1, 'Fe2+ls': 0,'Fe2+hs': 4, 'Fe4+': 4, 'Cr3+':3, 'Cr4+':2, 'Cr2+hs':4, 'Cr2+ls':2, 'V4+': 1, 'V2+': 3, 'V3+': 2, 'Ti3+':1, 'Ti4+':0, 'Ti2+':2 , 'Al3+':0, 'W4+':0, 'Mg2+':0, } # canonical magnetic moments of TM depending on oxidation state and spin state ION_RADII_coord_6 = { 'Co2+hs':0.745, 'Co2+ls':0.65, 'Co3+hs':0.61, 'Co3+ls':0.545, 'Co4+hs':0.53, 'Co4+ls': 0.53, 'Ni2+':0.69, 'Ni3+hs':0.6, 'Ni3+ls':0.56, 'Ni4+ls':0.48, 'Ni4+hs':0.48, 'Mn2+ls':0.67, 'Mn2+hs':0.83, 'Mn3+ls':0.58, 'Mn3+hs':0.645, 'Mn4+':0.53, 'Fe2+hs':0.78, 'Fe2+ls':0.61, 'Fe3+ls':0.55, 'Fe3+hs':0.645, 'Fe4+':0.585, 'Cr2+ls':0.73, 'Cr2+hs':0.8, 'Cr3+':0.615, 'Cr4+':0.55, 'V2+':0.79, 'V3+':0.64, 'V4+':0.58, 'Ti2+':0.86, 'Ti3+':0.67, 'Ti4+':0.605, 'Mg2+':0.72, 'Al3+':0.535, } el_dict = {'void':300, 'octa':200, 'n':0, 'H':1, 'He':2, 'Li':3, 'Be':4, 'B':5, 'C':6, 'N':7, 'O':8, 'F':9, 'Ne':10, 'Na':11, 'Mg':12, 'Al':13, 'Si':14, 'P':15, 'S':16, 'Cl':17, 'Ar':18, 'K':19, 'Ca':20, 'Sc':21, 'Ti':22, 'V':23, 'Cr':24, 'Mn':25, 'Fe':26, 'Co':27, 'Ni':28, 'Cu':29, 'Zn':30, 'Ga':31, 'Ge':32, 'As':33, 'Se':34, 'Br':35, 'Kr':36, 'Rb':37, 'Sr':38, 'Y':39, 'Zr':40, 'Nb':41, 'Mo':42, 'Tc':43, 'Ru':44, 'Rh':45, 'Pd':46, 'Ag':47, 'Cd':48, 'In':49, 'Sn':50, 'Sb':51, 'Te':52, 'I':53, 'Xe':54, 'Cs':55, 'Ba':56, 'La':57, 'Ce':58, 'Pr':59, 'Nd':60, 'Pm':61, 'Sm':62, 'Eu':63, 'Gd':64, 'Tb':65, 'Dy':66, 'Ho':67, 'Er':68, 'Tm':69, 'Yb':70, 'Lu':71, 'Hf':72, 'Ta':73, 'W':74, 'Re':75, 'Os':76, 'Ir':77, 'Pt':78, 'Au':79, 'Hg':80, 'Tl':81, 'Pb':82, 'Bi':83, 'Po':84, 'At':85, 'Rn':86, 'Fr':87, 'Ra':88, 'Ac':89, 'Th':90, 'Pa':91, 'U':92, 'Np':93, 'Pu':94, 'Am':95, 'Cm':96, 'Bk':97, 'Cf':98, 'Es':99, 'Fm':100, 'Md':101, 'No':102, 'Lr':103, 'Rf':104, 'Db':105, 'Sg':106, 'Bh':107, 'Hs':108, 'Mt':109, 'Ds':110, 'Rg':111, 'Cn':112, 'Uuq':114, 'Uuh':116, } nu_dict = {300:'void', 200:'octa', 0:'n', 1:'H', 2:'He', 3:'Li', 4:'Be', 5:'B', 6:'C', 7:'N', 8:'O', 9:'F', 10:'Ne', 11:'Na', 12:'Mg', 13:'Al', 14:'Si', 15:'P', 16:'S', 17:'Cl', 18:'Ar', 19:'K', 20:'Ca', 21:'Sc', 22:'Ti', 23:'V', 24:'Cr', 25:'Mn', 26:'Fe', 27:'Co', 28:'Ni', 29:'Cu', 30:'Zn', 31:'Ga', 32:'Ge', 33:'As', 34:'Se', 35:'Br', 36:'Kr', 37:'Rb', 38:'Sr', 39:'Y', 40:'Zr', 41:'Nb', 42:'Mo', 43:'Tc', 44:'Ru', 45:'Rh', 46:'Pd', 47:'Ag', 48:'Cd', 49:'In', 50:'Sn', 51:'Sb', 52:'Te', 53:'I', 54:'Xe', 55:'Cs', 56:'Ba', 57:'La', 58:'Ce', 59:'Pr', 60:'Nd', 61:'Pm', 62:'Sm', 63:'Eu', 64:'Gd', 65:'Tb', 66:'Dy', 67:'Ho', 68:'Er', 69:'Tm', 70:'Yb', 71:'Lu', 72:'Hf', 73:'Ta', 74:'W', 75:'Re', 76:'Os', 77:'Ir', 78:'Pt', 79:'Au', 80:'Hg', 81:'Tl', 82:'Pb', 83:'Bi', 84:'Po', 85:'At', 86:'Rn', 87:'Fr', 88:'Ra', 89:'Ac', 90:'Th', 91:'Pa', 92:'U', 93:'Np', 94:'Pu', 95:'Am', 96:'Cm', 97:'Bk', 98:'Cf', 99:'Es', 100:'Fm', 101:'Md', 102:'No', 103:'Lr', 104:'Rf', 105:'Db', 106:'Sg', 107:'Bh', 108:'Hs', 109:'Mt', 110:'Ds', 111:'Rg', 112:'Cn', 114:'Uuq', 116:'Uuh', } #void 300 is not written to poscar nme_list = ['H', 'He', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Si', 'P', 'S', 'Cl', 'Ar', 'As', 'Se', 'Br', 'Kr', 'Te', 'I', 'Xe', 'At', 'Rn', 'Ts', 'Og'] EXCLUDE_NODES = False MEM_CPU = None
[docs]def printlog(*logstrings, **argdic): """ '' - silent e - errors and warnings a - attentions m - minimalistic output of scientific procedures - only obligatory mess are shown M - maximalistic output of scientific procedures debug_level importance: 'n' - not important at all - for debugging '' - almost all actions, no flag is needed 'y' - important - major actions 'Y' - super important, or output asked by user """ end = '\n\n'# no argument for end, make one separate line debug_level = 'e' #empty for key in argdic: if 'imp' in key: debug_level = argdic[key] if 'end' in key: end = argdic[key] mystring = '' for m in logstrings: mystring+=str(m)+' ' if len(mystring.splitlines()) == 1: mystring = '-- '+mystring else: '' # mystring = ' '+mystring.replace('\n', '\n ') mystring+=end if 'Error' in mystring:# or 'Warning' in mystring: mystring+='\n\n\n' if 'Warning' in mystring or 'Attention' in mystring: debug_level = 'Y' for level in 'neyY': # print(level, debug_level) if (level in warnings and level in debug_level): print (mystring, end = "") # if warnings: # '' # # print(debug_level) # if 'n' in debug_level and 'n' not in warnings: # pass # else: # print (mystring, end = "") if siman_run: log.write(mystring) if verbose_log: with open('verbose_log','a') as f: f.write(mystring) if 'Error!' in mystring: print (mystring) print ('Error! keyword was detected in message; invoking RuntimeError ') # sys.exit() raise RuntimeError return
print_and_log = printlog open_terminal = False
[docs]def runBash(cmd, env = None, detached = False, cwd = None): """Input - string; Executes Bash commands and returns stdout Need: import subprocess """ global open_terminal if detached: stdout = None stderr = None else: stdout = subprocess.PIPE stderr = subprocess.STDOUT printlog('running in BASH:', cmd, '\n') # if 'sshpass' in cmd: # sys.exit() my_env = os.environ.copy() # my_env["PATH"] = "/opt/local/bin:/opt/local/sbin:" + my_env["PATH"] if open_terminal: cmd = cmd[:-1]+'; exec bash;'+cmd[-1:] # cmd = cmd.replace('"', '\\"') cmd = cmd.replace('ssh ','ssh -t ' ) cmd2 = "gnome-terminal -- bash -c ' "+cmd+" ; exec bash' " # print(cmd2) os.system(cmd2) open_terminal = False else: p = subprocess.Popen(cmd, # executable='/bin/bash', shell=True, stdout=stdout, stderr = stderr, stdin = None, env = my_env, cwd = cwd) # print (cmd) # print 'Bash output is\n'+out # print ( str(out, 'utf-8') ) out = '' try: out = p.stdout.read().strip() out = str(out, 'utf-8') except: pass return out #This is the stdout from the shell command
[docs]def run_win_cmd(cmd): #example for windows result = [] process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) for line in process.stdout: result.append(line) errcode = process.returncode for line in result: print(line) if errcode is not None: raise Exception('cmd %s failed, see above for details', cmd)
[docs]def pickle_module_migration_script(): """ This script allows to update modules in database after moving them to siman package """ import sys import siman from siman import header sys.modules['set_functions'] = siman.set_functions sys.modules['classes'] = siman.classes for key in header.db.items(): print(header.db[key])