From 131c9c2c523b328ef99d5ee853a886151ce7a99e Mon Sep 17 00:00:00 2001 From: BinaryBeaver <38048677+BinaryBeaver@users.noreply.github.com> Date: Mon, 2 Jul 2018 17:30:44 +0300 Subject: [PATCH 1/2] upd --- analysis.py | 39 +- calc_manage.py | 126 +- classes.py | 487 ++- cluster_tools/archivate_dft.py | 104 + database.py | 7 +- default_project_conf.py | 1 + from_server | 4 + functions.py | 34 +- geo.py | 369 ++- header.py | 27 +- impurity.py | 17 +- inout.py | 7 +- neb.py | 155 +- picture_functions.py | 31 +- project_funcs.py | 3757 +++++++++++++++++++++++ project_template/main.py | 171 ++ project_template/project_conf.py | 153 + project_template/project_sets.py | 120 + server_tools/make_database_cvs.py | 98 + server_tools/make_database_hash.py | 78 + server_tools/read_calculation.py | 40 + set_functions.py | 7 +- small_functions.py | 13 +- tutorials/Configure.ipynb | 45 +- tutorials/FAQ.ipynb | 27 +- tutorials/create_vasp_calculation.ipynb | 27 +- workflow_utilities.py | 256 +- 27 files changed, 5937 insertions(+), 263 deletions(-) create mode 100644 cluster_tools/archivate_dft.py create mode 100644 from_server create mode 100644 project_funcs.py create mode 100644 project_template/main.py create mode 100644 project_template/project_conf.py create mode 100644 project_template/project_sets.py create mode 100644 server_tools/make_database_cvs.py create mode 100644 server_tools/make_database_hash.py create mode 100644 server_tools/read_calculation.py diff --git a/analysis.py b/analysis.py index bc7d7e6..fc90dec 100644 --- a/analysis.py +++ b/analysis.py @@ -216,7 +216,7 @@ def calc_redox(cl1, cl2, energy_ref = None, value = 0, temp = None, silent = 0): 'mdstep':cl1.mdstep, 'ecut':cl1.set.ecut, 'niter':cl1.iterat/cl1.mdstep, 'set_is':cl1.id[1], 'vol_red':vol_red } except: - results_dic = {} + results_dic = {'redox_pot':redox, 'vol_red':vol_red} return results_dic @@ -224,7 +224,7 @@ def calc_redox(cl1, cl2, energy_ref = None, value = 0, temp = None, silent = 0): def matrix_diff(cl1, cl2, energy_ref = 0): - + #energy of substitutional impurity e = cl1.energy_sigma0 v = cl1.end.vol n_m = cl1.end.nznucl[0] @@ -468,7 +468,7 @@ def around_alkali(st, nn, alkali_ion_number): n_neighbours = nn alkali_ions = [] - + dist = [] ifmaglist = st.get_maglist() for i, typ, x in zip(range(st.natom), st.typat, st.xcart): @@ -539,7 +539,7 @@ def zscore(s): # sys.exit() - + magmom_tm = None for key in mag_numbers: printlog('Looking at polarons on transition atoms: ',invert(key) ) numbs = np.array(mag_numbers[key]) @@ -561,7 +561,7 @@ def zscore(s): d_to_pols = [] for j in i_pols: x2 = st.xcart[j] - d, _ = st.image_distance(x1, x2) + d, _ = st.image_distance(x1, x2, st.rprimd) d_to_pols.append(d) print('polarons are detected on atoms', [i+1 for i in i_pols], 'with magnetic moments:', magmom[i_pols], 'and distances: '+', '.join('{:2.2f}'.format(d) for d in d_to_pols), 'A' ) print('mag moments on trans. atoms:', magmom_tm.round(out_prec)) @@ -617,6 +617,7 @@ def neb_analysis(cl, show, up = None, push2archive = None, old_behaviour = None, get_from_server(files = cl.project_path_cluster+'/'+cl.dir+'/movie.xyz', to_file = movie_to, addr = cl.cluster_address, ) if os.path.exists(movie_to): + makedir('figs/'+name_without_ext+'.xyz') shutil.copyfile(movie_to, 'figs/'+name_without_ext+'.xyz') @@ -910,4 +911,30 @@ def set_oxidation_states(st): pm.add_oxidation_state_by_guess() st = st.update_from_pymatgen(pm) # print(pm) - return st \ No newline at end of file + return st + + + +def suf_en(cl1, cl2, silent = 0): + """Calculate surface energy + cl1 - supercell with surface + cl2 - comensurate bulk supercell + the area is determined from r[0] and r[1];- i.e they lie in surface + + """ + st1 = cl1.end + st2 = cl2.end + # pm = st1.convert2pymatgen(oxidation = {'Y':'Y3+', 'Ba':'Ba2+', 'Co':'Co2.25+', 'O':'O2-'}) + + A = np.linalg.norm( np.cross(st1.rprimd[0] , st1.rprimd[1]) ) + # print(A) + + if st1.natom%st2.natom > 0: + printlog('Warning! check system sizes: natom1 = ', st1.natom, 'natom2 = ', st2.natom, st1.natom/st2.natom) + + mul = st1.natom/st2.natom + gamma = (cl1.e0 - cl2.e0*mul)/2/A* header.eV_A_to_J_m + if not silent: + print('Surface energy = {:3.2f} J/m2 | {:} | {:} '.format(gamma, cl1.id, cl2.id)) + + return gamma \ No newline at end of file diff --git a/calc_manage.py b/calc_manage.py index 3c6789b..45f59f1 100644 --- a/calc_manage.py +++ b/calc_manage.py @@ -33,7 +33,7 @@ from picture_functions import plot_mep, fit_and_plot, plot_conv from analysis import calc_redox, matrix_diff, fit_a -from geo import image_distance, scale_cell_uniformly, scale_cell_by_matrix, remove_atoms, create_deintercalated_structure, create_antisite_defect, create_antisite_defect2, local_surrounding, find_moving_atom +from geo import replic, image_distance, scale_cell_uniformly, scale_cell_by_matrix, remove_atoms, create_deintercalated_structure, create_antisite_defect, create_antisite_defect2, local_surrounding, find_moving_atom from set_functions import init_default_sets @@ -85,8 +85,14 @@ def write_batch_header(batch_script_filename = None, if schedule_system == 'PBS': f.write("#!/bin/bash \n") f.write("#PBS -N "+job_name+"\n") - if header.WALLTIME_LIMIT: - f.write("#PBS -l walltime=72:00:00 \n") + + if 'walltime' in header.cluster: + f.write("#PBS -l walltime="+str(header.cluster['walltime'])+'\n') + else: + if header.WALLTIME_LIMIT: #deprecated remove + f.write("#PBS -l walltime=72:00:00 \n") + + # f.write("#PBS -l nodes=1:ppn="+str(number_cores)+"\n") if header.PBS_PROCS: f.write("#PBS -l procs="+str(number_cores)+"\n") @@ -96,14 +102,44 @@ def write_batch_header(batch_script_filename = None, f.write("#PBS -r n\n") f.write("#PBS -j eo\n") f.write("#PBS -m bea\n") - f.write("#PBS -M dimonaks@gmail.com\n") + # f.write("#PBS -M dimonaks@gmail.com\n") + f.write("cd $PBS_O_WORKDIR\n") + # f.write("PATH=/share/apps/vasp/bin:/home/aleksenov_d/mpi/openmpi-1.6.3/installed/bin:/usr/bin:$PATH \n") + # f.write("LD_LIBRARY_PATH=/home/aleksenov_d/lib64:$LD_LIBRARY_PATH \n") + if 'modules' in header.cluster: + f.write(header.cluster['modules']+'\n') + + # f.write("module load Compilers/Intel/psxe_2015.6\n") + # f.write("module load MPI/intel/5.1.3.258/intel \n") + # f.write("module load QCh/VASP/5.4.1p1/psxe2015.6\n") + # f.write("module load ScriptLang/python/2.7\n\n") + + + + if schedule_system == 'PBS_bsu': + f.write("#!/bin/bash \n") + f.write("#PBS -N "+job_name+"\n") + if header.WALLTIME_LIMIT: + f.write("#PBS -l walltime=72:00:00 \n") + # f.write("#PBS -l nodes=1:ppn="+str(number_cores)+"\n") + if header.PBS_PROCS: + f.write("#PBS -l nodes=node07:ppn="+str(number_cores)+"\n") + else: # 1 node option + f.write("#PBS -l nodes=node07:ppn="+str(number_cores)+"\n") + # f.write("#PBS -l pmem=16gb\n") #memory per processor, Skoltech + f.write("#PBS -r n\n") + f.write("#PBS -j eo\n") + f.write("#PBS -m bea\n") + f.write("#PBS -M boev.anton.olegovich@gmail.com\n") f.write("cd $PBS_O_WORKDIR\n") - f.write("PATH=/share/apps/vasp/bin:/home/aleksenov_d/mpi/openmpi-1.6.3/installed/bin:/usr/bin:$PATH \n") - f.write("LD_LIBRARY_PATH=/home/aleksenov_d/lib64:$LD_LIBRARY_PATH \n") - f.write("module load Compilers/Intel/psxe_2015.6\n") - f.write("module load MPI/intel/5.1.3.258/intel \n") - f.write("module load QCh/VASP/5.4.1p1/psxe2015.6\n") - f.write("module load ScriptLang/python/2.7\n\n") + f.write("echo $LD_LIBRARY_PATH \n") + + + + + + + if schedule_system == 'SLURM': if '~' in path_to_job: @@ -187,7 +223,7 @@ def prepare_run(): f.write("#!/bin/tcsh\n") f.write("module load sge\n") f.write("module load vasp/parallel/5.2.12\n") - elif schedule_system in ('PBS', 'SLURM'): + elif schedule_system in ('PBS', 'PBS_bsu' 'SLURM'): f.write("#!/bin/bash\n") else: '' @@ -203,7 +239,7 @@ def complete_run(close_run = True): if close_run: with open('run','a', newline = '') as f: - if header.schedule_system == "PBS": + if header.schedule_system in ["PBS", 'PBS_bsu']: f.write("qstat\n") f.write("sleep 2\n") elif header.schedule_system == "SLURM": @@ -329,8 +365,21 @@ def cif2poscar(cif_file, poscar_file): if pymatgen_flag: parser = CifParser(cif_file) - s = parser.get_structures(primitive=0)[0] + s = parser.get_structures(primitive = True)[0] + + si = s._sites[0] + + # print(dir(si)) + # print(si.specie) + + # from pymatgen.symmetry.analyzer import SpacegroupAnalyzer + # sf = SpacegroupAnalyzer(s, ) # + # sc = sf.get_conventional_standard_structure() # magmom are set to None + # print(sc) + + + Poscar(s).write_file(poscar_file) printlog('File',poscar_file, 'created.') @@ -581,6 +630,7 @@ def choose_cluster(cluster_name, cluster_home, corenum): """ *cluster_name* should be in header.project_conf.CLUSTERS dict """ + if cluster_name in header.CLUSTERS: printlog('We use', cluster_name,'cluster') clust = header.CLUSTERS[cluster_name] @@ -588,10 +638,10 @@ def choose_cluster(cluster_name, cluster_home, corenum): else: - printlog('Cluster', cluster_name, 'is not found, using default', header.DEFAULT_CLUSTER) + printlog('Attention!, cluster', cluster_name, 'is not found, using default', header.DEFAULT_CLUSTER) clust = header.CLUSTERS[header.DEFAULT_CLUSTER] - + header.cluster = clust # dict header.cluster_address = clust['address'] header.CLUSTER_ADDRESS = clust['address'] @@ -602,6 +652,16 @@ def choose_cluster(cluster_name, cluster_home, corenum): header.cluster_home = cluster_home + if 'sshpass' in clust and clust['sshpass']: + printlog('setting sshpass to True', imp = '') + # sys.exit() + + header.sshpass = True + else: + header.sshpass = None + + + #Determine cluster home using ssh # run_on_server('touch ~/.hushlogin', header.cluster_address) if header.copy_to_cluster_flag: @@ -631,6 +691,9 @@ def choose_cluster(cluster_name, cluster_home, corenum): except: header.vasp_command = None + # print(clust) + + return @@ -1444,6 +1507,8 @@ def add_calculation(structure_name, inputset, version, first_version, last_versi elif "4" in cl.state: status = "compl" + if up == 'up2': + cl.init.select = None cl.res(check_job = check_job, show = params['show']) # sys.exit() @@ -1681,7 +1746,6 @@ def add_calculation(structure_name, inputset, version, first_version, last_versi - def inherit_icalc(inherit_type, it_new, ver_new, id_base, calc = None, st_base = None, id_from = None, confdic = None, atom_new = None, atom_to_replace = None, @@ -2206,7 +2270,7 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n typconv='', up = "", imp1 = None, imp2 = None, matr = None, voronoi = False, r_id = None, readfiles = True, plot = True, show = 'fo', comment = None, input_geo_format = None, savefile = None, energy_ref = 0, ifolder = None, bulk_mul = 1, inherit_option = None, calc_method = None, u_ramping_region = None, input_geo_file = None, corenum = None, run = None, input_st= None, - ortho = None, mat_proj_cell = None, + ortho = None, mat_proj_cell = None, ngkpt = None, it_folder = None, choose_outcar = None, choose_image = None, cee_args = None, mat_proj_id = None, ise_new = None, push2archive = False, description_for_archive = None, old_behaviour = False, @@ -2363,8 +2427,8 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n else: print_and_log('Warning! Calculation ',b_id, 'was not finished; please check, now skipping ...', important = 'y') else: - printlog('res_loop(): b_id', b_id, 'does not exist. return {} []') - return {}, [] + printlog('Attention! res_loop(): b_id', b_id, 'does not exist. return {} []') + # return {}, [] #define reference values e1_r = 0 @@ -2388,7 +2452,7 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n for inputset in setlist: for v in verlist: id = (it,inputset,v) - + # print(id) if id not in calc: printlog('Key', id, 'not found in calc!', imp = 'Y') continue #pass non existing calculations @@ -2406,6 +2470,14 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n # sys.exit() return + if 'pos' in show: + cl.end.write_poscar() + return + + + + + if not hasattr(cl,'version'): cl.version = v @@ -2431,7 +2503,7 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n b_id = (b_id[0], b_id[1], id[2] + b_ver_shift) except: b_id = (b_id[0], id[1], id[2] + b_ver_shift) - + printlog('b_id', b_id) # print(id) @@ -2466,9 +2538,10 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n # if "4" not in calc[b_id].state: if readfiles: + # print(b_id) calc[b_id].read_results(loadflag, choose_outcar = choose_outcar) - + # print(b_id) if "4" in calc[b_id].state: if calc[id].set.ngkpt != calc[b_id].set.ngkpt: @@ -2610,6 +2683,9 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n e_seg = (e - e_b * bulk_mul) * 1000 v_seg = v - v_b * bulk_mul + + # print(e_seg, e_segmin) + calc[id1].e_seg = e_seg calc[id1].v_seg = v_seg @@ -2625,7 +2701,8 @@ def res_loop(it, setlist, verlist, calc = None, varset = None, analys_type = 'n calc[id1].Xgb = v1 / A # for grain boundary with 1 A width. For other boundaries should be divided by width. #print ("__________________________________________________________________________") - #print (" At zero pressure: segregation energy is %.0f meV; Seg. volume is %.1f A^3; excess seg. vol. is %.2f A" %(e_seg, v_seg, v_seg/A ) ) + # print (" At zero pressure: segregation energy is %.0f meV; Seg. volume is %.1f A^3; excess seg. vol. is %.2f A" %(e_seg, v_seg, v_seg/A ) ) + print ("At min: segregation energy is %.0f meV; Seg. volume is %.1f A^3; excess seg. vol. is %.2f A" %(e_segmin, v_segmin, v_segmin/A ) ) # print ("%s.fit.pe & %.0f & %.1f & %.2f & %.3f & %.1f" %(id[0]+'.'+id[1], e_seg, v_seg, v_seg/A, 1./A, 1./calc[id].natom * 100 ) ) #Calculate distance from impurity to boundary and number of neighbours for version 2! @@ -3208,5 +3285,6 @@ def manually_remove_from_struct_des(struct_des, key): - +add = add_loop +res = res_loop diff --git a/classes.py b/classes.py index 27f2412..3b3406a 100755 --- a/classes.py +++ b/classes.py @@ -126,7 +126,10 @@ def __init__(self): self.xred = [] self.magmom = [] self.select = [] # flags for selective dynamics + # self.pos = write_poscar() + def copy(self): + return copy.deepcopy(self) def new(self): return Structure() @@ -137,6 +140,8 @@ def selective_all(self): st.select = [] for i in range(st.natom): st.select.append([True,True,True]) + # print('9') + # print(st.select) return st def check_selective(self): @@ -268,6 +273,23 @@ def xred2xcart(self,): def update_xcart(self,): self.xcart = xred2xcart(self.xred, self.rprimd) + def exchange_axes(self, i1_r, i2_r): + """ + + """ + st = copy.deepcopy(self) + r = copy.deepcopy(st.rprimd) + + st.rprimd[i1_r] = r[i2_r] + st.rprimd[i2_r] = r[i1_r] + + st.update_xred() + + return st + + + + def get_volume(self): self.vol = np.dot( self.rprimd[0], np.cross(self.rprimd[1], self.rprimd[2]) ); #volume return self.vol @@ -303,6 +325,12 @@ def get_elements_zval(self): zvals.append(zv) return zvals + def determine_symmetry_positions(self, element): + from geo import determine_symmetry_positions + + return determine_symmetry_positions(self, element) + + def get_maglist(self): #return bool list of which elements are magnetic (here all transition metals are searched!) #and dictionary with numbers of each transition metal @@ -321,6 +349,31 @@ def get_maglist(self): return ifmaglist, mag_numbers + + def set_magnetic_config(self, element, moments): + #set magnetic configuration based on symmetry non-equivalent positions + # element (str) - elements for which moments should be set + # moments (list) - list of moments for non-equivalent positions - the same order as in determine + # the length should be the same as number of unique postions + + st = copy.deepcopy(self) + + if not hasattr(st, 'magmom') or None in st.magmom: + magmom = [0.6]*st.natom + else: + magmom = st.magmom + + pos = st.determine_symmetry_positions(element) + + for j, p in enumerate(pos): + for i in p: + magmom[i] = moments[j] + + # print(magmom) + st.magmom = magmom + + return st + def convert2pymatgen(self, oxidation = None, slab = False): """ oxidation (dict) - {'Ti':'Ti3+'} @@ -349,6 +402,10 @@ def convert2pymatgen(self, oxidation = None, slab = False): miller_index = [0,0,1], oriented_unit_cell = None, shift = None, scale_factor = None,reorient_lattice = False, site_properties = site_properties) else: + # print(elements) + # print(len(self.xred)) + # print(site_properties) + pm = pymatgen.Structure(self.rprimd, elements, self.xred, site_properties = site_properties) @@ -366,6 +423,12 @@ def convert2pymatgen(self, oxidation = None, slab = False): return pm + + + + + + def get_pm_composition(self): '' pm = self.convert2pymatgen() @@ -444,23 +507,41 @@ def update_from_pymatgen(self, stpm): only rprimd, xred and xcart are updated now!!!!! TODO: - please update magmom also!!!! + """ st = copy.deepcopy(self) st.rprimd = [np.array(vec) for vec in stpm._lattice._matrix] st.xred = [np.array(site._fcoords) for site in stpm._sites] + + # print(elements) st.update_xcart() s = stpm._sites[0] + + if 'magmom' in s.properties: + st.magmom = [site.properties['magmom'] for site in stpm._sites] + else: + st.magmom = [None] + # print( dir(s._lattice) ) + # print( dir(s) ) + # print( s.properties ) + # print( s._properties ) # print( dir(s.specie) ) - # print( s.specie ) + # print( s.specie.name ) + # sys.exit() elements = [s.specie.name for s in stpm._sites] # print(s.specie.oxi_state) if hasattr(s.specie, 'oxi_state'): charges = [s.specie.oxi_state for s in stpm._sites] st.charges = charges + + # if hasattr(s.specie, 'oxi_state'): + # charges = [s.specie.oxi_state for s in stpm._sites] + # st.charges = charges + + # print(st.charges) # else: # charges = [None] @@ -479,6 +560,122 @@ def update_from_pymatgen(self, stpm): st.name+='_from_pmg' return st + + def rotate(self, axis, angle): + #axis - list of 3 elements, [0,0,1] + #angle in degrees + + from pymatgen.transformations.standard_transformations import RotationTransformation + + st = copy.deepcopy(self) + rot = RotationTransformation(axis, angle) + stpm = st.convert2pymatgen() + stpmr1 = rot.apply_transformation(stpm) + st_r1 = st.update_from_pymatgen(stpmr1) + return st_r1 + + + def invert_axis(self, axis): + st = copy.deepcopy(self) + + st.rprimd[axis] *= -1 + st.update_xred() + st = st.return_atoms_to_cell() + return st + + + + + + + + + + + + def get_conventional_cell(self): + """ + return conventional cell + """ + st_mp = self.convert2pymatgen() + + # st_test = self.update_from_pymatgen(st_mp) + # st_test.printme() + + sf = SpacegroupAnalyzer(st_mp, ) #symprec = 0.1 + + sc = sf.get_conventional_standard_structure() # magmom are set to None + + # print(sc) + st = self.update_from_pymatgen(sc) + + # print(st.rprimd) + # print(len(st.xcart)) + # print(st.ntypat) + + return st + + + + + def get_primitive_cell(self): + """ + return primitive cell + """ + st_mp = self.convert2pymatgen() + + sf = SpacegroupAnalyzer(st_mp, ) #symprec = 0.1 + + sc = sf.get_primitive_standard_structure() # magmom are set to None + + st = self.update_from_pymatgen(sc) + + + return st + + + def get_surface_atoms(self, element, surface = 0, surface_width = 0.5 ): + #return numbers of surface atoms + #elememt - which element is interesting? + #surface_width - which atoms to consider as surface + #surface (int) - 0 or 1 - one of two surfaces; surface 1 has lowest z coordinate + st = self + surface_atoms = [[],[]] + + z1 = 100 + z2 = -100 + z = [] + for x in st.xcart: + if z1 > x[2]: + z1 = x[2] + if z2 < x[2]: + z2 = x[2] + + printlog('Surfaces are ', z1, z2) + + z.append(z1) + z.append(z2) + els = st.get_elements() + + + for i, x in enumerate(st.xcart): + el = els[i] + if el == element: + # print(x[2]) + if z1 <= x[2] < z1+surface_width: + surface_atoms[0].append(i) + + if z2 - surface_width < x[2] <= z2: + surface_atoms[1].append(i) + + + return surface_atoms[surface] + + + + + + def printme(self): print(self.convert2pymatgen()) return @@ -559,8 +756,8 @@ def get_transition_elements(self, fmt = 'names'): tra = ns return tra - def get_specific_elements(self, required_elements = None, fmt = 'names', ): - """Returns list of transition elements (chemical names or z) in the structure + def get_specific_elements(self, required_elements = None, fmt = 'n', ): + """Returns list of specific elements (chemical names or z) in the structure fmt - 'names' 'z' @@ -611,9 +808,12 @@ def add_atoms(self, atoms_xcart, element = 'Pu', return_ins = False, selective = st = copy.deepcopy(self) - if not hasattr(st, 'select') or st.select is None: - st = st.selective_all() - + # print(st.select) + if selective: + if not hasattr(st, 'select') or st.select is None or len(st.select) == 0: + st = st.selective_all() + # print(st.select) + # sys.exit() natom_to_add = len(atoms_xcart) @@ -643,9 +843,12 @@ def add_atoms(self, atoms_xcart, element = 'Pu', return_ins = False, selective = if selective is not None: st.select.extend(selective) - else: - st.select.extend( [[1,1,1] for i in range(natom_to_add)] ) + elif hasattr(st, 'select') and st.select and len(st.select) > 0: + # printlog('adding default selective', imp = 'y') + st.select.extend( [[True,True,True] for i in range(natom_to_add)] ) + else: + '' if magmom_flag: st.magmom.extend( [0.6]*natom_to_add ) @@ -671,11 +874,17 @@ def add_atoms(self, atoms_xcart, element = 'Pu', return_ins = False, selective = st.typat[j_ins:j_ins] = [typ]*natom_to_add + # print(st.select) + # sys.exit() if selective is not None: + printlog('adding selective', imp = '') st.select[j_ins:j_ins] = selective + elif hasattr(st, 'select') and st.select and len(st.select) > 0: + printlog('adding default selective', imp = '') + st.select[j_ins:j_ins] = [[True,True,True] for i in range(natom_to_add)] else: - st.select[j_ins:j_ins] = [[1,1,1] for i in range(natom_to_add)] + '' if magmom_flag: st.magmom[j_ins:j_ins] = [0.6]*natom_to_add @@ -685,6 +894,7 @@ def add_atoms(self, atoms_xcart, element = 'Pu', return_ins = False, selective = + # print(st.select) @@ -771,10 +981,56 @@ def reorder_for_vasp(self, inplace = False): return st + def reorder_element_groups(self, order = None, inplace = False): + """ + + Group and order atoms by atom types; consistent with VASP + order (list) -required order e.g. ['O', 'Li'] + return st + """ + st = copy.deepcopy(self) + # for z in st.znucl: + # print(z) + + typat = [] + xcart = [] + magmom = [] + znucl = [] + # st.write_poscar() + + + els = st.get_elements() + t = 1 + for el in order: + if el not in els: + printlog('Error! Check *order* list') + + znucl.append( invert(el) ) + + for i in range(st.natom): + el_i = els[i] + if el_i not in order: + printlog('Error! Check *order* list') + + if el_i == el: + # print(el) + typat.append(t) + xcart.append(st.xcart[i]) + magmom.append(st.magmom[i]) + t+=1 + + st.xcart = xcart + st.magmom = magmom + st.typat = typat + st.znucl = znucl + st.update_xred() + st.name+='_r' + # st.write_poscar() + return st def del_atom(self, iat): @@ -837,12 +1093,20 @@ def del_atom(self, iat): - def mov_atoms(self, iat = None, to_x = None): + def mov_atoms(self, iat = None, to_x = None, relative = False): """ Move one atom to xcart position *to_x* + relative (bool) - if shift is relative + """ st = copy.deepcopy(self) - st.xcart[iat] = to_x + + if relative: + st.xcart[iat] += to_x + else: + st.xcart[iat] = to_x + + st.xcart2xred() return st @@ -1118,6 +1382,7 @@ def find_atom_num_by_xcart(self, x_tar, prec = 1e-6): for i in [0,1,2]: if xr_tar[i] < 0: xr_tar[i]+= 1 + if xr_tar[i] >= 1: xr_tar[i]-= 1 printlog('find_atom_num_by_xcart(): xr_tar after periodic = ', xr_tar) @@ -1167,7 +1432,7 @@ def replic(self, *args, **kwargs): def image_distance(self, *args, **kwargs): - return image_distance(*args, **kwargs, r = self.rprimd) + return image_distance(*args, **kwargs) @@ -1508,7 +1773,8 @@ def b2s(b): return - def write_cif(self, filename, mcif = False): + + def write_cif(self, filename = None, mcif = False): """ Find primitive cell and write it in cif format @@ -1525,6 +1791,9 @@ def write_cif(self, filename, mcif = False): else: m = '' + if filename == None: + filename = 'cif/'+self.name + makedir(filename) symprec = 0.1 @@ -1948,6 +2217,15 @@ def get_kpoints_density(self): """ print(self.NKPTS*self.end.natom) #KPPRA - k-points per reciprocal atom? + def copy(self): + return copy.deepcopy(self) + + def jmol(self): + self.end.jmol() + def poscar(self): + self.end.write_poscar() + def me(self): + self.end.printme() @property def sfolder(self): @@ -1956,6 +2234,7 @@ def sfolder(self): + class CalculationAbinit(Calculation): """docstring for CalculationAbinit""" pass @@ -2525,7 +2804,7 @@ def actualize_set(self, curset = None): if number_of_ord > 10000: printlog('Attention! Too much orderings (1000), skipping ...') else: - nords = 10 + nords = 71 use_each = number_of_ord // nords # spin() should be improved to find the AFM state based on the number of configuration if use_each == 0: use_each = 1 @@ -3037,7 +3316,7 @@ def name_mod_U_last(): if schedule_system == 'SGE': parrallel_run_command = "mpirun -x PATH vasp" - elif schedule_system == 'PBS': + elif schedule_system in ['PBS', 'PBS_bsu']: # parrallel_run_command = "mpiexec --prefix /home/aleksenov_d/mpi/openmpi-1.6.3/installed vasp" bsu cluster # parrallel_run_command = "mpirun vasp_std" #skoltech cluster parrallel_run_command = header.vasp_command #skoltech cluster @@ -3555,7 +3834,7 @@ def make_run(self, schedule_system, run_name): f.write("qsub -pe 'mpi*' "+str(header.corenum)+" "+header.queue+" "+run_name+"\n") #str(self.set.np) #-l cmmd f.write('sleep 5\n') # runBash('chmod +x run') - elif schedule_system == 'PBS': + elif schedule_system in ['PBS', 'PBS_bsu']: if header.PATH2PROJECT == '': header.PATH2PROJECT = '.' @@ -3718,8 +3997,9 @@ def read_results(self, load = '', out_type = '', voronoi = False, show = '', cho self.cluster_address, join(self.project_path_cluster, path_to_outcar) ) # runBash(command_reduce) - files = [ self.project_path_cluster+'/'+path_to_outcar, self.project_path_cluster+'/'+path_to_outcar+'.gz', self.project_path_cluster+'/'+path_to_contcar, self.project_path_cluster+'/'+path_to_poscar] - + files = [ self.project_path_cluster+'/'+path_to_outcar, self.project_path_cluster+'/'+path_to_contcar ] + # print(load) + # print(files) # get_from_server(files = files, to = os.path.dirname(path_to_outcar), addr = self.cluster_address) for file in files: self.get_file(os.path.basename(file), up = load) @@ -3929,10 +4209,18 @@ def read_results(self, load = '', out_type = '', voronoi = False, show = '', cho lmax = int(line.split()[7]) # print 'lmax', lmax if "W(low)/X(q)" in line: - kk = 1; low = []; high = []; + kk = 1; + low = []; + high = []; + while kk < 100: - if 'Optimization' in outcarlines[i_line + kk] or len(outcarlines[i_line + kk].split() ) != 7: break - # print 'line', outcarlines[i_line + kk] + if 'Optimization' in outcarlines[i_line + kk] or len(outcarlines[i_line + kk].split() ) != 7: + break + if 'PSMAXN' in outcarlines[i_line + kk]: + # print(line) + printlog('Warning! PSMAXN for non-local potential too small') + break + # print( 'line', outcarlines[i_line + kk]) low.append( float(outcarlines[i_line + kk].split()[4]) ) high.append( float(outcarlines[i_line + kk].split()[5]) ) @@ -3993,7 +4281,9 @@ def read_results(self, load = '', out_type = '', voronoi = False, show = '', cho for j in range(self.end.natom): parts = outcarlines[i_line+j+2].split() # print "parts", parts - if self.end.select: + # print(self.end.select) + # sys.exit() + if hasattr(self.end, 'select') and self.end.select: x = float(parts[ff[0]])*self.end.select[j][0] y = float(parts[ff[1]])*self.end.select[j][1] z = float(parts[ff[2]])*self.end.select[j][2] @@ -4785,7 +5075,7 @@ def determine_filenames(self, nametype = 'asoutcar'): if nametype == 'asoutcar': for filetype in 'CHGCAR', 'AECCAR0', 'AECCAR2': self.path[filetype.lower()] = self.path['output'].replace('OUTCAR',filetype) - print('determine_filenames()',self.path[filetype.lower()]) + printlog('determine_filenames()',self.path[filetype.lower()]) @@ -4822,14 +5112,14 @@ def get_chg_file(self, filetype = 'CHGCAR', nametype = '', up = 'up1'): if out: - printlog('File', path2file_cluster, 'was not found, trying scratch', imp = 'Y') + printlog('File', path2file_cluster, 'was not found, trying archive:',header.PATH2ARCHIVE, imp = 'Y') # printlog('Charge file', path_to_chg, 'was not found') try: pp = self.project_path_cluster.replace(self.cluster_home, '') #project path without home except: pp = '' # print(pp) - path_to_chg_scratch = '/scratch/amg/aksenov/'+pp+'/'+path_to_chg + path_to_chg_scratch = header.PATH2ARCHIVE+'/'+pp+'/'+path_to_chg out = get_from_server(path_to_chg_scratch, os.path.dirname(path_to_chg), addr = self.cluster_address) @@ -4875,12 +5165,12 @@ def get_bader_ACF(self, p = 0): #assumes that bader is installed self.res() v = str(self.version) - path = self.project_path_cluster+self.dir - ppc = self.project_path_cluster + path = self.project_path_cluster+'/'+self.dir + ppc = self.project_path_cluster+'/' self.determine_filenames() # print() - CHG_scratch_gz = '/scratch/amg/aksenov/'+self.dir+'/'+v+".CHGCAR.gz" + CHG_scratch_gz = header.PATH2ARCHIVE+'/'+self.dir+'/'+v+".CHGCAR.gz" CHG = ppc + self.path['chgcar'] AECCAR0 = ppc + self.path['aeccar0'] @@ -4893,41 +5183,50 @@ def get_bader_ACF(self, p = 0): command1 = "cd "+path+"; ~/tools/vts/chgsum.pl "+AECCAR0+" "+AECCAR2+"; "+\ - "mv CHGCAR_sum "+CHGCAR_sum+";" + "mv CHGCAR_sum "+CHGCAR_sum+";" # on cluster - command2 = "rsync "+CHG_scratch_gz+' '+path+' ; gunzip '+CHG+'.gz ' + command2 = "rsync "+CHG_scratch_gz+' '+path+' ; gunzip '+CHG+'.gz ' # on cluster mv = v+".bader.log; mv ACF.dat "+v+".ACF.dat; mv AVF.dat "+v+".AVF.dat; mv BCF.dat "+v+".BCF.dat; cat "+v+".bader.log" command3 = "cd "+path+"; ~/tools/bader "+CHG+" -ref "+CHGCAR_sum+" > "+mv command3s = "cd "+path+"; ~/tools/bader "+CHG+" > "+mv #simple - + command_check_CHG_sum = " [ -e "+ CHGCAR_sum +""" ] || echo "NO" ; """ #true if file not exists + command_check_CHG = " [ -e "+ CHG +""" ] || echo "NO" ; """ + command_check_ACF = " [ -e "+ ACF +""" ] || echo "NO" ; """ + command_cat_ACF = " cat "+path+v+".ACF.dat" + # run_on_server() - if runBash("ssh "+self.cluster_address+" '[ -e "+ CHGCAR_sum +""" ] || echo "NO" ;' """): #true if file not exists - print_and_log( CHGCAR_sum, "not exist. trying to calculate it ", imp = 'Y') - printlog( runBash("ssh "+self.cluster_address+" '"+command1+"'")+'\n' ) + if run_on_server(command_check_CHG_sum, self.cluster_address): + print_and_log( CHGCAR_sum, "does not exist. trying to calculate it ", imp = 'Y') + printlog( run_on_server(command1, self.cluster_address)+'\n', imp = 'Y' ) + # sys.exit() - if runBash("ssh "+self.cluster_address+" '[ -e "+ CHG +""" ] || echo "NO" ;' """): #true if file not exists - printlog( runBash("ssh "+self.cluster_address+" '"+command2+"'")+'\n', imp = 'y' ) + + if run_on_server(command_check_CHG, self.cluster_address): #true if file not exists + printlog( 'Warning! File ', CHG, "does not exist. Trying to restore it from archive .. ", imp = 'Y') + + printlog( run_on_server(command2, self.cluster_address)+'\n', imp = 'y' ) def run_bader(command, ): - if runBash("ssh "+self.cluster_address+" '[ -e "+ ACF +""" ] || echo "NO" ;' """): #true if file not exists - print_and_log( ACF, " does not exist. trying to calculate Bader ", imp = 'Y') - printlog( runBash("ssh "+self.cluster_address+" '"+command+"'")+'\n', imp = 'y' ) + if run_on_server(command_check_ACF, self.cluster_address): #true if file not exists + print_and_log( ACF, " does not exist. trying to calculate Bader ... ", imp = 'Y') + printlog( run_on_server(command, self.cluster_address)+'\n', imp = 'y' ) - ACF_text = runBash("ssh "+self.cluster_address+" 'cat "+path+v+".ACF.dat" +"'" ) + ACF_text = run_on_server(command_cat_ACF, self.cluster_address) return ACF_text ACF_text = run_bader(command3) + if 'No such file or directory' in ACF_text: - printlog('Warning!, most probable problemes with',CHGCAR_sum) - printlog('Trying without it ...') + printlog('Warning! Probably you have problems with',CHGCAR_sum) + printlog('Trying to calculate charges from CHGCAR ...', imp = 'Y') ACF_text = run_bader(command3s) print('ACF_text = ', ACF_text) @@ -4936,11 +5235,14 @@ def run_bader(command, ): if ACF_text: ACF_l = ACF_text.splitlines() charges = [] + + for line in ACF_l: try: charges.append(round(float(line.split()[4]), 3)) except: pass + self.charges = charges # print(charges[[1,2]]) @@ -4992,37 +5294,43 @@ def bader_coseg(): def check_job_state(self): #check if job in queue or Running - cl = self - job_in_queue = '' - if hasattr(cl,'schedule_system'): + if header.check_job == 1: + job_in_queue = '' + if hasattr(cl,'schedule_system'): - check_string = cl.id[0]+'.'+cl.id[1] - if 'SLURM' in cl.schedule_system: + check_string = cl.id[0]+'.'+cl.id[1] + if 'SLURM' in cl.schedule_system: - job_in_queue = check_string in run_on_server("squeue -o '%o' ", cl.cluster_address) - printlog(cl.id[0]+'.'+cl.id[1], 'is in queue or running?', job_in_queue) + job_in_queue = check_string in run_on_server("squeue -o '%o' ", cl.cluster_address) + printlog(cl.id[0]+'.'+cl.id[1], 'is in queue or running?', job_in_queue) - elif 'PBS' in cl.schedule_system: - job_in_queue = check_string in run_on_server("qstat -x ", cl.cluster_address) + elif 'PBS' in cl.schedule_system: + job_in_queue = check_string in run_on_server("qstat -x ", cl.cluster_address) - else: - print_and_log('Attention! unknown SCHEDULE_SYSTEM='+'; Please teach me here! ', imp = 'y') - job_in_queue = '' + else: + print_and_log('Attention! unknown SCHEDULE_SYSTEM='+'; Please teach me here! ', imp = 'y') + job_in_queue = '' - if file_exists_on_server(os.path.join(cl.dir, 'RUNNING'), addr = cl.cluster_address) and job_in_queue: - - cl.state = '3. Running' + if file_exists_on_server(os.path.join(cl.dir, 'RUNNING'), addr = cl.cluster_address) and job_in_queue: + + cl.state = '3. Running' + + elif job_in_queue: + + cl.state = '3. In queue' + + else: + '' + if '3' in cl.state: + cl.state = '2. Unknown' - elif job_in_queue: - - cl.state = '3. In queue' - else: - '' - if '3' in cl.state: - cl.state = '2. Unknown' + cl.state = '2. Unknown' + + + return cl.state @@ -5033,7 +5341,7 @@ def res(self, **argv): from calc_manage import res_loop res_loop(*self.id, **argv) - def run(self, ise, iopt = 'full_nomag', up = 'up1', vers = None, *args, **kwargs): + def run(self, ise, iopt = 'full_nomag', up = 'up1', vers = None, i_child = -1, add = 0, *args, **kwargs): """ Wrapper for add_loop (in development) By default inherit self.end @@ -5042,9 +5350,11 @@ def run(self, ise, iopt = 'full_nomag', up = 'up1', vers = None, *args, **kwargs iopt - inherit_option 'full_nomag' 'full' - + 'full_chg' - including chg file vers - list of version for which the inheritance is done + i_child - choose number of child to run res_loop() + add - if 1 than add new calculation irrelevant to children TODO: 1. if ise is not provided continue in the same folder under the same name, however, it is not always what is needed, therefore use inherit_xred = continue @@ -5062,20 +5372,39 @@ def run(self, ise, iopt = 'full_nomag', up = 'up1', vers = None, *args, **kwargs if not hasattr(self, 'children'): self.children = [] - for idd in self.children: + if not add and len(self.children)>0: + print('Children were found:', self.children, 'by defauld reading last, choose with *i_child* ') + + for i in self.children: + # print(i, ise, i[1], i[1] == ise) + if i[1] == ise: + idd = i + # add = True + break + + else: + add = True + # idd = self.children[i_child] + # print(idd) + cl_son = header.calc[idd] - # cl_son.res() - # self.children = list(set(self.children)) + + cl_son.res(up = up, **kwargs) child = idd - # if len(self.children) == 0: - if not vers: - vers = [self.id[2]] - - it_new = add_loop(*self.id[:2], vers, ise_new = ise, up = up, inherit_option = iopt, override = 1, *args, **kwargs) - # it_new = add_loop(*self.id, ise_new = ise, up = up, inherit_option = iopt, override = 1) - child = (it_new, ise, self.id[2]) - if child not in self.children: - self.children.append(child) + + + + if add or len(self.children) == 0: + if not vers: + vers = [self.id[2]] + + idd = self.id + it_new = add_loop(idd[0],idd[1], vers, ise_new = ise, up = up, inherit_option = iopt, override = 1, *args, **kwargs) + # it_new = add_loop(*self.id, ise_new = ise, up = up, inherit_option = iopt, override = 1) + child = (it_new, ise, self.id[2]) + + if child not in self.children: + self.children.append(child) return header.calc[child] diff --git a/cluster_tools/archivate_dft.py b/cluster_tools/archivate_dft.py new file mode 100644 index 0000000..431f5c7 --- /dev/null +++ b/cluster_tools/archivate_dft.py @@ -0,0 +1,104 @@ +""" +archivate_dft.py by Aksyonov Dmitry, Skoltech, Moscow + +1. rsync home directory to backup storage +2. remove all auxilary DFT files from home directory for finished calculations +""" +import sys +import subprocess, datetime, os, glob, copy +from os.path import expanduser + +# print sys.argv +# sys.path.append('/usr/lib64/python2.7/site-packages/numpy') +# import numpy as np + +BACKUP_STORAGE = '/storage/amg/aksenov/' +RETURN_DIRS_COMMAND = """squeue -o '%o' | awk -F / '{$(NF--)} {gsub(/\s+/,FS)}; $0 '""" # queue specific command that return directories of active calculations +AUX_FILES_TEMPL = ['*CHG*', '*DOS*', '*WAV*', '*run.xml*', '*AEC*', '*OSZ*', '*POT*'] # template for auxilary files to remove + +def runBash(cmd, env = None, detached = False): + """Input - string; Executes Bash commands and returns stdout + Need: import subprocess + """ + if detached: + stdout = None + stderr = None + else: + stdout = subprocess.PIPE + stderr = subprocess.STDOUT + + # printlog('running in BASH:', cmd) + my_env = os.environ.copy() + # my_env["PATH"] = "/opt/local/bin:/opt/local/sbin:" + my_env["PATH"] + p = subprocess.Popen(cmd, + # executable='/bin/bash', + shell=True, stdout=stdout, stderr = stderr, stdin = None, env = my_env) + # 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 + + + +with open('archivate_dft.log', 'a') as f: + + """1. Archivate files with rsync""" + f.write("\nStart rsync at "+str(datetime.datetime.now())+'\n') + # out = runBash('rsync -r LiCoO2 '+ BACKUP_STORAGE) + # out = runBash('rsync -r * .'+ BACKUP_STORAGE) + out = runBash('cp -au * '+ BACKUP_STORAGE) + f.write('rsync out: '+out+'\n') + f.write("Finished rsync at "+str(datetime.datetime.now())+'\n') + + + + """2. Remove aux files with find from inactive dirs""" + active_directories = [] + out = runBash(RETURN_DIRS_COMMAND) + # print(out) + active_directories = out.splitlines()[1:] + + curpath = sys.path[0] + + home = expanduser("~") + user = home.split('/')[-1] + print('home is ', home) + print('user is ', user) + active_for_find = ['-path '+p.replace(home, '.')+' -prune -o' for p in active_directories if user in p] + + active_directories = [d.replace(curpath+'/', '').split('/')[0] for d in active_directories] + # print(active_directories) + dirs = filter(os.path.isdir, os.listdir(curpath)) # return list of directories in current folder + + # print(active_full) + + if 0: + # option 1, skipping top directories of active calculations - not effecient + for d in dirs: + if d in active_directories: + continue + + for tem in AUX_FILES_TEMPL: + '' + out = runBash('find '+d+' -name '+tem+' -delete' ) + f.write('find out: '+out+'\n') + + # print(out) + if 1: + #option 2, skipping only active + find_arg = ' '.join(active_for_find) + for tem in AUX_FILES_TEMPL: + '' + find_command = 'find . '+find_arg+' -name '+tem+' -exec rm {} \\;' + out = runBash(find_command) + f.write('find out: '+out+'\n') + + # print(find_command) \ No newline at end of file diff --git a/database.py b/database.py index b765132..8f19792 100644 --- a/database.py +++ b/database.py @@ -10,7 +10,6 @@ import header from header import runBash, print_and_log, printlog -from classes import CalculationVasp from small_functions import makedir from set_functions import init_default_sets from functions import invert @@ -193,9 +192,14 @@ def write_database(calc = None, conv = None, varset = None, size_on_start = None d[struct_des_key] = header.struct_des d.close() + # print(header.db[('Cu.su', '1lo', 100)].inh_id) + printlog('Opening ', header.calc_database, 'for writing') + with shelve.Shelf(dbm.open(header.calc_database, 'w'), protocol = 3) as d: for key in header.calc: + printlog('saving key:', key,imp = 'n') # print(key) + # print(key, header.calc[key].inh_id) d[str(key)] = header.calc[key] if 0: #please run me from time to time to reduce the size of the database file @@ -232,6 +236,7 @@ def get_from_database(x1, x2, mat, inquiry_keys = None, silent = None, ssh_objec ssh_object (SSHTools) - ssh object based on paramiko with access details """ + from classes import CalculationVasp def check(key, inquiry_keys): return all([k in key for k in inquiry_keys]) diff --git a/default_project_conf.py b/default_project_conf.py index 4eac0b1..7cc81e2 100644 --- a/default_project_conf.py +++ b/default_project_conf.py @@ -10,6 +10,7 @@ CLUSTERS = {} DEFAULT_CLUSTER = 'cee' PATH2PROJECT = '' # path to project on cluster relative to home folder +PATH2ARCHIVE = '' # path to archive; if no files are found at home folder, siman will check here; relative paths should be same CLUSTERS['cee'] = { diff --git a/from_server b/from_server new file mode 100644 index 0000000..716edfe --- /dev/null +++ b/from_server @@ -0,0 +1,4 @@ +#!/bin/bash +cd "$(dirname "$0")" + +git pull origin master diff --git a/functions.py b/functions.py index 4a94ba4..fb9da1f 100755 --- a/functions.py +++ b/functions.py @@ -9,7 +9,7 @@ import header from header import print_and_log, printlog, runBash from small_functions import is_list_like, is_string_like, gunzip_file, makedir - +from header import eV_A_to_J_m def unique_elements(seq, idfun=None): @@ -80,10 +80,25 @@ def smoother(x, n, mul = 1, align = 1): def run_on_server(command, addr): printlog('Running', command, 'on server ...') command = command.replace('\\', '/') # make sure is POSIX + # sys.exit() + + if header.ssh_object: + # printlog('Using paramiko ...', imp = 'y') out = header.ssh_object.run(command) + + elif header.sshpass: + com = 'sshpass -f /home/aksenov/.ssh/p ssh '+addr+' "'+command+'"' + # sys.exit() + + out = runBash(com) + + # sys.exit() + else: - out = runBash('ssh '+addr+' "'+command+'"') + bash_comm = 'ssh '+addr+' "'+command+'"' + # print(bash_comm) + out = runBash(bash_comm) out = out.split('#')[-1].strip() @@ -121,6 +136,19 @@ def push_to_server(files = None, to = None, addr = None): # print(file, to) header.ssh_object.put(file, to+'/'+os.path.basename(file) ) out = '' + + elif header.sshpass: + # if '@' not in addr: + # printlog('Error! Please provide address in the form user@address') + # l = addr.split('@') + # print(l) + # user = l[0] + # ad = l[1] + com = 'rsync --rsh='+"'sshpass -f /home/aksenov/.ssh/p ssh' " +' -uaz '+files_str+ ' '+addr+':'+to + # print(com) + # sys.exit() + out = runBash(com) + else: out = runBash('rsync -uaz '+files_str+ ' '+addr+':'+to) @@ -711,7 +739,7 @@ def words(fileobj): def server_cp(copy_file, to, gz = True, scratch = False): if scratch: - copy_file = '/scratch/amg/aksenov/' + copy_file + copy_file = header.PATH2ARCHIVE + '/' + copy_file else: copy_file = header.project_path_cluster + '/' + copy_file diff --git a/geo.py b/geo.py index ddb6604..7fd7dab 100644 --- a/geo.py +++ b/geo.py @@ -401,6 +401,17 @@ def my_round(a, b): else: my_round = round + + def av_dev(): + nonlocal n_neighbours + n_neighbours = float(n_neighbours) + dav = sum(dlistnn)/n_neighbours + av_dev = sum( [abs(d-dav) for d in dlistnn] ) / n_neighbours + max_dev = max([abs(d-dav) for d in dlistnn]) + + + return my_round(av_dev*1000, 0), my_round(max_dev*1000, 0) + st_original = copy.deepcopy(st) st.init_numbers = None if periodic: @@ -469,11 +480,201 @@ def my_round(a, b): elif control == 'av_dev': + output = av_dev() + + elif control == 'sum_av_dev': + output = (my_round(sum(dlistnn), 2), av_dev()) + + + + elif control == 'atoms': + # print dlist_unsort + if hasattr(st, 'init_numbers') and st.init_numbers: + numbers = st.init_numbers + else: + numbers = range(natom) + temp = list(zip(dlist_unsort, xcart, typat, numbers, zlist) ) + + temp.sort(key = itemgetter(0)) + + + if only_elements: + centr_type = temp[0][4] + if centr_type in only_elements: + first = [] + else: + first = temp[0:1] + temp = first+[t for t in temp if t[4] in only_elements] #including central; included ionce even if only elements are and central are the same + + if only_numbers: + temp = temp[0:1]+[t for t in temp if t[3] in only_numbers] + + + + temp2 = list( zip(*temp) ) + dlist = temp2[0][:n_neighbours+1] + xcart_local = temp2[1][:n_neighbours+1] + typat_local = temp2[2][:n_neighbours+1] + numbers = temp2[3][:n_neighbours+1] + # print temp2[0][:n_neighbours] + # print xcart_local[:n_neighbours] + + + + + + + + #check if atoms in output are from neighboring cells + if 0: + xred_local = xcart2xred(xcart_local, st_original.rprimd) + # print 'xred_local', xred_local + for x_l in xred_local: + for i, x in enumerate(x_l): + if x > 1: + x_l[i]-=1 + # print 'returning to prim cell', x,x_l[i] + if x < 0: + x_l[i]+=1 + # print 'returning to prim cell', x,x_l[i] + xcart_local = xred2xcart(xred_local, st_original.rprimd) + + # print 'Warning! local_surrounding() can return several atoms in one position due to incomplete PBC implementation; Improve please\n' + + output = (xcart_local, typat_local, numbers, dlist ) + + return output + + +def local_surrounding2(x_central, st, n_neighbours, control = 'sum', periodic = False, only_elements = None, only_numbers = None, round_flag = 1): + """ + !!! Attempt to improve speed of periodic conditions! + #control = 'atoms' could work wrong!!! check + + Return list of distances to n closest atoms around central atom. (By defauld sum of distances) + + Input: + - x_central - cartesian coordinates of central atom; vector + - st - structure with xcart list of coordinates of all atoms in system + - n_neighbours - number of needed closest neighbours + + - control - type of output; + sum - sum of distances, + av - average distance, + avsq - average squared dist + 'mavm': #min, av, max, av excluding min and max + av_dev - return (average deviation, maximum deviation) from average distance in mA. + list - list of distances; + atoms - coordinates of neighbours + + - periodic - if True, then cell is additionaly replicated; needed for small cells + Only for control = atoms + - *only_elements* - list of z of elements to which only the distances are needed; + - only_numbers (list of int) - calc dist only to this atoms + + round_flag (bool) - if 1 than reduce distance prec to 2 points + + + #TODO: + the periodic boundary conditions realized very stupid by replicating the cell! + + """ + # round_orig = round + if not round_flag: + # overwrite round function with wrapper that do nothing + def my_round(a, b): + return a + else: + my_round = round + + + def av_dev(): + nonlocal n_neighbours n_neighbours = float(n_neighbours) dav = sum(dlistnn)/n_neighbours av_dev = sum( [abs(d-dav) for d in dlistnn] ) / n_neighbours max_dev = max([abs(d-dav) for d in dlistnn]) - output = (my_round(av_dev*1000, 0), my_round(max_dev*1000, 0)) + + + return my_round(av_dev*1000, 0), my_round(max_dev*1000, 0) + + st_original = copy.deepcopy(st) + st.init_numbers = None + if periodic: + '' + # not needed anymore, since image_distance is used, + # however for 'atoms' regime more actions can be needed + # st = replic(st, mul = (2,2,2), inv = 1 ) # to be sure that impurity is surrounded by atoms + # st = replic(st, mul = (2,2,2), inv = -1 ) + + xcart = st.xcart + typat = st.typat + natom = st.natom + # print x_central + + #print len(xcart) + if only_elements: + only_elements = list(set(only_elements)) + # print(only_elements) + # sys.exit() + + + zlist = [int(st.znucl[t-1]) for t in st.typat] + + + dlist_unsort = [image_distance(x_central, x, st.rprimd)[0] for x in xcart ]# if all (x != x_central)] # list of all distances + + if only_elements: + dlist = [image_distance(x_central, x, st.rprimd)[0] for x, z in zip(xcart, zlist) if z in only_elements] + else: + dlist = copy.deepcopy(dlist_unsort) + dlist.sort() + # print('local_surrounding(): dlist', dlist) + + + if len(dlist) > 0 and abs(dlist[0]) < 0.01: + dlistnn = dlist[1:n_neighbours+1] #without first impurity which is x_central + else: + dlistnn = dlist[:n_neighbours] + + # print('dlistnn', dlistnn) + # os._exit(1) + + if control == 'list': + output = dlistnn + + elif control == 'sum': + + output = my_round(sum(dlistnn), 2) + + elif control == 'av': + n_neighbours = float(n_neighbours) + dav = sum(dlistnn)/n_neighbours + output = my_round(dav, 2) + + elif control == 'avsq': + n_neighbours = float(n_neighbours) + # print(dlistnn) + davsq = sum([d*d for d in dlistnn])/n_neighbours + davsq = davsq**(0.5) + output = my_round(davsq, 2) + + + elif control == 'mavm': #min, av, max + dsort = sorted(dlistnn) + if n_neighbours > 2: + output = (my_round(dsort[0], 2), sum(dsort[1:-1])/(n_neighbours-2), my_round(dsort[-1], 2) ) #min, av excluding min and max, max + else: + output = (my_round(dsort[0], 2), 0, my_round(dsort[-1], 2) ) #min, av excluding min and max, max + + + elif control == 'av_dev': + output = av_dev() + + elif control == 'sum_av_dev': + output = (my_round(sum(dlistnn), 2), av_dev()) + + elif control == 'atoms': # print dlist_unsort @@ -534,9 +735,6 @@ def my_round(a, b): return output - - - def ortho_vec_old(rprim, ortho_sizes = None): """ old function @@ -615,6 +813,7 @@ def create_supercell(st, mul_matrix, test_overlap = False, mp = 4, bound = 0.01) test_overlap (bool) - check if atoms are overlapping - quite slow """ sc = st.new() + # st = st.return_atoms_to_cell() sc.name = st.name+'_supercell' sc.rprimd = list(np.dot(mul_matrix, st.rprimd )) printlog('Old vectors (rprimd):\n',np.round(st.rprimd,1), imp = 'y', end = '\n') @@ -624,11 +823,21 @@ def create_supercell(st, mul_matrix, test_overlap = False, mp = 4, bound = 0.01) sc.vol = np.dot( sc.rprimd[0], np.cross(sc.rprimd[1], sc.rprimd[2]) ) st.vol = np.dot( st.rprimd[0], np.cross(st.rprimd[1], st.rprimd[2]) ) # sc_natom_i = int(sc.vol/st.vol*st.natom) # test + # print(st.natom) + + if len(st.typat) != len(st.magmom): + st.magmom = [None]*st.natom + mag_flag = False + else: + mag_flag = True + + sc_natom = sc.vol/st.vol*st.natom # test - printlog('The supercell should contain', sc_natom, 'atoms ... ', imp = 'y', end = ' ') + printlog('The supercell should contain', sc_natom, 'atoms ... \n', imp = 'y', end = ' ') sc.xcart = [] sc.typat = [] sc.xred = [] + sc.magmom = [] #find range of multiplication mi = np.min(mul_matrix, axis = 0) ma = np.max(mul_matrix, axis = 0) @@ -637,27 +846,34 @@ def create_supercell(st, mul_matrix, test_overlap = False, mp = 4, bound = 0.01) # print(mi, ma) + + # find bound values lengths = np.linalg.norm(sc.rprimd, axis = 1) bounds = bound/lengths # in reduced coordinates - - + # print(bounds) + # print(st.xcart) + # print([range(*z) for z in zip(mi-mp, ma+mp)]) + # print(st.rprimd) + # print(sc.rprimd) for uvw in itertools.product(*[range(*z) for z in zip(mi-mp, ma+mp)]): #loop over all ness uvw # print(uvw) xcart_mul = st.xcart + np.dot(uvw, st.rprimd) # coordinates of basis for each uvw # print(xcart_mul) xred_mul = xcart2xred(xcart_mul, sc.rprimd) - - for xr, xc, t in zip(xred_mul, xcart_mul, st.typat): - + + # print(len(xred_mul), len(xcart_mul), len(st.typat), len(st.magmom) ) + for xr, xc, t, m in zip(xred_mul, xcart_mul, st.typat, st.magmom): + # if 01e-5: #test 1, number of atoms @@ -679,6 +895,9 @@ def create_supercell(st, mul_matrix, test_overlap = False, mp = 4, bound = 0.01) sc.ntypat = st.ntypat sc.nznucl = sc.get_nznucl() + if mag_flag is False: + sc.magmom = [None] + return sc @@ -690,6 +909,14 @@ def supercell(st, ortho_sizes): mul_matrix = ortho_vec(st.rprimd, ortho_sizes) return create_supercell(st, mul_matrix) +def cubic_supercell(st, ortho_sizes): + """ + wrapper + """ + mul_matrix = ortho_vec(st.rprimd, ortho_sizes) + return create_supercell(st, mul_matrix) + + def determine_symmetry_positions(st, element, silent = 0): """ determine non-equivalent positions for atoms of type *element* @@ -1023,7 +1250,7 @@ def create_antisite_defect3(st, el1, el2, tol = 0.1, max_sep = 4, iatom = None): i+=1 structures.append(st_as) - st_as.write_xyz() + st_as.write_poscar() st.write_xyz() printlog('List of antisites:', imp = 'y') @@ -1211,3 +1438,121 @@ def remove_half(st, el, sg = None): return st_half + +def primitive(st): + from pymatgen.symmetry.analyzer import SpacegroupAnalyzer + + st.sg() + # st.jmol() + st_mp = st.convert2pymatgen() + # print(st_mp) + + + sf = SpacegroupAnalyzer(st_mp) + + st_mp_prim = sf.find_primitive() + + # print(st_mp_prim) + + st =st.update_from_pymatgen(st_mp_prim) + # st.sg() + return st + + + + + +def create_surface(st, miller_index, min_slab_size = 10, min_vacuum_size = 10, surface_i = 0, oxidation = None, ): + """ + INPUT: + st (Structure) - Initial input structure. Note that to + ensure that the miller indices correspond to usual + crystallographic definitions, you should supply a conventional + unit cell structure. + + miller_index ([h, k, l]): Miller index of plane parallel to + surface. Note that this is referenced to the input structure. If + you need this to be based on the conventional cell, + you should supply the conventional structure. + + + oxidation (dic) - dictionary of effective oxidation states, e. g. {'Y':'Y3+', 'Ba':'Ba2+', 'Co':'Co2.25+', 'O':'O2-'} + allows to calculate dipole moment + + surface_i (int) - choose particular surface + + min_slab_size (float) - minimum slab size + + min_vacuum_size (float) - vacuum thicknes in A + + """ + + from pymatgen.core.surface import SlabGenerator + from pymatgen.io.vasp.inputs import Poscar + from geo import replic + + + pm = st.convert2pymatgen(oxidation = oxidation) + # pm = st.convert2pymatgen() + + + slabgen = SlabGenerator(pm, miller_index, min_slab_size, min_vacuum_size) + # print(slabgen.oriented_unit_cell) + slabs = slabgen.get_slabs() + + printlog(len(slabs), 'surfaces were generated, choose required surface using *surface_i* argument\nWriting POSCARs to xyz', imp = 'y') + + for i, slab in enumerate(slabs): + pos = Poscar(slab) + pos.write_file('xyz/POSCAR_suf'+str(i)) + + return slabs[surface_i] + + + +def create_surface2(st, miller_index, min_slab_size = 10, min_vacuum_size = 10, surface_i = 0, oxidation = None, suf = '', + primitive = None, symmetrize = False): + """ + INPUT: + st (Structure) - Initial input structure. Note that to + ensure that the miller indices correspond to usual + crystallographic definitions, you should supply a conventional + unit cell structure. + + miller_index ([h, k, l]): Miller index of plane parallel to + surface. Note that this is referenced to the input structure. If + you need this to be based on the conventional cell, + you should supply the conventional structure. + + + oxidation (dic) - dictionary of effective oxidation states, e. g. {'Y':'Y3+', 'Ba':'Ba2+', 'Co':'Co2.25+', 'O':'O2-'} + allows to calculate dipole moment + + surface_i (int) - choose particular surface + + min_slab_size (float) - minimum slab size + + min_vacuum_size (float) - vacuum thicknes in A + + """ + + from pymatgen.core.surface import SlabGenerator + from pymatgen.io.vasp.inputs import Poscar + from geo import replic + + + pm = st.convert2pymatgen(oxidation = oxidation) + # pm = st.convert2pymatgen() + + + slabgen = SlabGenerator(pm, miller_index, min_slab_size, min_vacuum_size, primitive = primitive) + # print(slabgen.oriented_unit_cell) + slabs = slabgen.get_slabs(symmetrize = symmetrize) + + printlog(len(slabs), 'surfaces were generated, choose required surface using *surface_i* argument\nWriting POSCARs to xyz', imp = 'y') + + for i, slab in enumerate(slabs): + pos = Poscar(slab) + pos.write_file('xyz/POSCAR_suf'+str(i)+str(suf)) + + return slabs diff --git a/header.py b/header.py index 3cf2a4d..9e44422 100755 --- a/header.py +++ b/header.py @@ -78,6 +78,13 @@ 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: + key = ('.'.join(l[0:-2]), l[-2], int(l[-1])) + # else: if dict.__contains__(self, key): # print('key', key, 'is in self') @@ -86,21 +93,9 @@ def __getitem__(self, key): else: with shelve.open(calc_database, protocol = 3) as d: try: - # print(type(key)==str) - if type(key) == str: - # print('String key detected', key) - l = key.split('.') - if len(l) > 2: - key = ('.'.join(l[0:-2]), l[-2], int(l[-1])) - # print(key) val = d[str(key)] - # print(len(d)) dict.__setitem__(self, key, val) # print('reading ',str(key), 'from db') - # print(val) - # else: - - except: val = None @@ -140,8 +135,11 @@ def items(self): 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 + @@ -266,7 +264,10 @@ def runBash(cmd, env = None, detached = False): stdout = subprocess.PIPE stderr = subprocess.STDOUT - printlog('running in BASH:', cmd) + 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"] p = subprocess.Popen(cmd, diff --git a/impurity.py b/impurity.py index f548574..71da78f 100755 --- a/impurity.py +++ b/impurity.py @@ -18,7 +18,7 @@ from functions import return_atoms_to_cell, element_name_inv from inout import write_xyz -from geo import local_surrounding +from geo import local_surrounding, local_surrounding2 lib = cdll.LoadLibrary(os.path.dirname(__file__)+'/libfindpores.so') @@ -246,6 +246,7 @@ def find_pores(st_in, r_matrix=1.4, r_impurity = 0.6, step_dec = 0.05, fine = 0. st_result.rprimd = rprimd st_result.xred2xcart() st_result.typat = [1 for x in st_result.xred] + st_result.ntypat = 1 st_result.natom = len(st_result.typat) st_result.znucl = [200] st_ntypat = 1 @@ -784,7 +785,7 @@ def insert(it_ins, ise_ins, mat_path, it_new, calc, type_of_insertion = "xcart" -def determine_voids(st, r_impurity): +def determine_voids(st, r_impurity, fine = 1, step_dec = 0.05): if not r_impurity: printlog('add_neb(): Error!, Please provide *r_impurity* (1.6 A?)') @@ -793,16 +794,18 @@ def determine_voids(st, r_impurity): sums = [] avds = [] printlog('Searching for voids', important = 'y') - st_pores = find_pores(st, r_matrix = 0.5, r_impurity = r_impurity, fine = 1, calctype = 'all_pores') + st_pores = find_pores(st, r_matrix = 0.5, r_impurity = r_impurity, step_dec = step_dec, fine = fine, calctype = 'all_pores') printlog('List of found voids:\n', np.array(st_pores.xcart) ) write_xyz(st.add_atoms(st_pores.xcart, 'H'), file_name = st.name+'_possible_positions') write_xyz(st.add_atoms(st_pores.xcart, 'H'), replications = (2,2,2), file_name = st.name+'_possible_positions_replicated') for x in st_pores.xcart: - summ = local_surrounding(x, st, n_neighbours = 6, control = 'sum', periodic = True) - avd = local_surrounding(x, st, n_neighbours = 6, control = 'av_dev', periodic = True) - # print sur, + # summ = local_surrounding(x, st, n_neighbours = 6, control = 'sum', periodic = True) + # avd = local_surrounding(x, st, n_neighbours = 6, control = 'av_dev', periodic = True) + summ, avd = local_surrounding2(x, st, n_neighbours = 6, control = 'sum_av_dev', periodic = True) + # print (summ, avd) + sums.append(summ) avds.append(avd[0]) # print @@ -838,7 +841,7 @@ def determine_unique_voids(st_pores, sums, avds): return insert_positions -def insert_atom(st, el, i_void = None, r_imp = 1.6): +def insert_atom(st, el, i_void = None, r_imp = 1.6, ): """Simple Wrapper for inserting atoms """ diff --git a/inout.py b/inout.py index 4075bed..f82da36 100644 --- a/inout.py +++ b/inout.py @@ -140,7 +140,8 @@ def write_jmol(xyzfile, pngfile, scriptfile = None, atomselection = None, topvie if 0: f.write('cpk 250 \nwireframe 0.3\n') - f.write('background white \nselect Ti* \ncolor [20,120,250] \nselect C* \ncolor [80,80,80]\n cpk 100\n') + f.write('background white \n') + # f.write('select Ti* \ncolor [20,120,250] \nselect C* \ncolor [80,80,80]\n cpk 100\n') f.write('set perspectivedepth off\n') @@ -236,7 +237,6 @@ def write_xyz(st = None, path = None, filename = None, file_name = None, imp_positions - (x1,x2,x3, element, label)- xcart and element name coordinates additionally to be added to structure; to visulaze all impurity positions: for jmol, additional key 's', 'i' can be added after element imp_sub_positions - list of atom numbers; the typat of these atoms is changed: not used now - specialcommand - any command at the end of script analysis - additional processing, allows to show only specifice atoms, 'imp_surrounding' - shows Ti atoms only around impurity @@ -254,6 +254,9 @@ def write_xyz(st = None, path = None, filename = None, file_name = None, jmol - 1,0 - use jmol to produce png picture jmol_args - see write_jmol() + specialcommand - any command at the end of jmol script + + sts - list of Structure - write several structures to xyz file - other options are not working in this regime """ diff --git a/neb.py b/neb.py index 814029b..cb10472 100644 --- a/neb.py +++ b/neb.py @@ -13,10 +13,10 @@ from small_functions import is_list_like, makedir from classes import CalculationVasp, cd -from impurity import find_pores +# from impurity import find_pores from tabulate import tabulate from geo import xcart2xred, xred2xcart, local_surrounding, replic, determine_symmetry_positions -from impurity import determine_voids, determine_unique_voids +# from impurity import determine_voids, determine_unique_voids @@ -61,7 +61,7 @@ def determine_unique_final(st_pores, sums, avds, x_m): sur = local_surrounding(x_m, st_pores, n_neighbours = len(st_pores.xcart), control = 'atoms', periodic = True) - print('neb.determine_unique_final(): sur', sur) + # print('neb.determine_unique_final(): sur', sur) print_and_log( 'I can suggest you '+str (len(sur[0]) )+' end positions.', imp = 'y' ) @@ -98,7 +98,8 @@ def add_neb(starting_calc = None, st = None, st_end = None, x_start = None, xr_start = None, x_final = None, xr_final = None, upload_vts = False, - run = False, add_loop_dic = None, old_behaviour = None, + center_on_moving = True, + run = False, add_loop_dic = None, old_behaviour = None, params = None ): @@ -157,6 +158,8 @@ def add_neb(starting_calc = None, st = None, st_end = None, else: naming_conventions209 = True # set False to reproduce old behavior before 2.09.2017 + # print(atom_to_insert) + # sys.exit() calc = header.calc struct_des = header.struct_des @@ -270,6 +273,7 @@ def add_neb(starting_calc = None, st = None, st_end = None, else: nn = str(i_void_start) + name_suffix+=atom_to_insert+nn write_xyz(st1, file_name = st.name+'_manually_start') printlog('Start position is created manually by adding xr_start', xr_start, x_start) @@ -282,7 +286,7 @@ def add_neb(starting_calc = None, st = None, st_end = None, atoms_to_move = [] atoms_to_move_types = [] - # print(i_atom_to_move) + # print('d', i_atom_to_move) # sys.exit() if i_atom_to_move: @@ -299,7 +303,7 @@ def add_neb(starting_calc = None, st = None, st_end = None, else: #try to find automatically among alkali - special case for batteries for i, typ, x in zip(range(st.natom), st.get_elements(), st.xcart): - if typ in ['Li', 'Na', 'K', 'Rb']: + if typ in ['Li', 'Na', 'K', 'Rb', 'Mg']: atoms_to_move.append([i, typ, x]) if typ not in atoms_to_move_types: atoms_to_move_types.append(typ) @@ -344,20 +348,34 @@ def add_neb(starting_calc = None, st = None, st_end = None, atom_to_insert = atom_to_move st1 = st + # elif atom_to_replace: + # num = st.get_specific_elements(atom_to_replace) + + # if len(n)>0: + # printlog('Please choose position using *i_void_start* :', [i+1 for i in range(len(num))],imp = 'y' ) + # printlog('*i_void_start* = ', i_void_start) + # i_m = num[i_void_start-1] + # printlog('Position',i_void_start,'chosen, atom to replace:', i_m+1, atom_to_replace, imp = 'y' ) + # sys.exit() + else: print_and_log('No atoms to move found, you probably gave me deintercalated structure', important = 'y') - st_pores, sums, avds = determine_voids(st, r_impurity) - + st_pores, sums, avds = determine_voids(st, r_impurity, step_dec = 0.1, fine = 2) + + insert_positions = determine_unique_voids(st_pores, sums, avds) print_and_log('Please use *i_void_start* to choose the void for atom insertion from the Table above:', end = '\n', imp = 'Y') + if i_void_start == None: sys.exit() + if atom_to_insert == None: + printlog('Error! atom_to_insert = None') st = st.add_atoms([insert_positions[i_void_start],], atom_to_insert) @@ -454,6 +472,7 @@ def add_neb(starting_calc = None, st = None, st_end = None, only_elements = [invert(type_atom_to_move)]+end_pos_types_z, periodic = True) #exclude the atom itself + # print(x_m) # print(sur) # st.nn() @@ -472,7 +491,13 @@ def add_neb(starting_calc = None, st = None, st_end = None, x_del = sur[0][i_void_final] printlog('xcart of atom to delete', x_del) i_del = st.find_atom_num_by_xcart(x_del) + # print(x_del) # print(st.xcart) + # for x in st.xcart: + # if x[0] > 10: + # print(x) + + print_and_log( 'number of atom to delete = ', i_del, imp = 'y') if i_del == None: printlog('add_neb(): Error! I could find atom to delete!') @@ -535,33 +560,33 @@ def add_neb(starting_calc = None, st = None, st_end = None, """ Determining magnetic moments """ vp = varset[ise_new].vasp_params - if search_type != None: #for None not implemented; x_m should be determined first for this - if 'ISPIN' in vp and vp['ISPIN'] == 2: - print_and_log('Magnetic calculation detected. Preparing spin modifications ...', imp = 'y') - cl_test = CalculationVasp(varset[ise_new]) - cl_test.init = st1 - # print 'asdfsdfasdfsadfsadf', st1.magmom - if inherit_magmom and hasattr(st, 'magmom') and st.magmom and any(st.magmom): - print_and_log('inherit_magmom=True: You have chosen MAGMOM from provided structure', imp = 'y') - name_suffix+='mp' #Magmom from Previous - else: - cl_test.init.magmom = None - print_and_log('inherit_magmom=False or no magmom in input structure : MAGMOM will be determined from set', imp = 'y') - name_suffix+='ms' #Magmom from Set + if 'ISPIN' in vp and vp['ISPIN'] == 2: + print_and_log('Magnetic calculation detected. Preparing spin modifications ...', imp = 'y') + cl_test = CalculationVasp(varset[ise_new]) + cl_test.init = st1 + # print 'asdfsdfasdfsadfsadf', st1.magmom + if inherit_magmom and hasattr(st, 'magmom') and st.magmom and any(st.magmom): + print_and_log('inherit_magmom=True: You have chosen MAGMOM from provided structure', imp = 'y') + name_suffix+='mp' #Magmom from Previous + else: + cl_test.init.magmom = None + print_and_log('inherit_magmom=False or no magmom in input structure : MAGMOM will be determined from set', imp = 'y') + name_suffix+='ms' #Magmom from Set - cl_test.actualize_set() #find magmom for current structure - st1.magmom = copy.deepcopy(cl_test.init.magmom) - st2.magmom = copy.deepcopy(cl_test.init.magmom) + cl_test.actualize_set() #find magmom for current structure - # sys.exit() - # print_and_log('The magnetic moments from set:') - # print cl_test.init.magmom + st1.magmom = copy.deepcopy(cl_test.init.magmom) + st2.magmom = copy.deepcopy(cl_test.init.magmom) + # sys.exit() + # print_and_log('The magnetic moments from set:') + # print cl_test.init.magmom + if search_type != None: # for None not implemented; x_m should be determined first for this #checking for closest atoms now only for Fe, Mn, Ni, Co - sur = local_surrounding(x_m, st1, n_neighbours = 3, control = 'atoms', + sur = local_surrounding(x_m, st1, n_neighbours = 3, control = 'atoms', periodic = True, only_elements = header.TRANSITION_ELEMENTS) dist = np.array(sur[3]).round(2) @@ -576,7 +601,7 @@ def unique_by_key(elements, key=None): # no key: the whole element must be unique key = lambda e: e return list ( {key(el): el for el in elements}.values() ) - + # print a mag_atoms_dists = unique_by_key(a, key=itemgetter(1)) # print (mag_atoms_dists) @@ -596,21 +621,21 @@ def unique_by_key(elements, key=None): print_and_log( 'The list of possible mag_moments:', imp = 'y' ) for i, mag in enumerate(mag_moments_variants): print_and_log( i, mag) - + print_and_log( 'Please use *mag_config* arg to choose desired config' , imp = 'y' ) - if mag_config != None: + if mag_config != None: - st1.magmom = copy.deepcopy(mag_moments_variants[mag_config]) - st2.magmom = copy.deepcopy(mag_moments_variants[mag_config]) - - name_suffix+='m'+str(mag_config) - - print_and_log('You have chosen mag configuration #',mag_config,imp = 'y') + st1.magmom = copy.deepcopy(mag_moments_variants[mag_config]) + st2.magmom = copy.deepcopy(mag_moments_variants[mag_config]) - else: - print_and_log('Non-magnetic calculation continue ...') + name_suffix+='m'+str(mag_config) + + print_and_log('You have chosen mag configuration #',mag_config,imp = 'y') + + else: + print_and_log('Non-magnetic calculation continue ...') @@ -673,25 +698,25 @@ def unique_by_key(elements, key=None): cl = CalculationVasp() #write start position + if search_type is not None: + struct_des[it_new].x_m_ion_start = x_m + struct_des[it_new].xr_m_ion_start = xcart2xred([x_m], st1.rprimd)[0] + + # st1, _, _ = st1.remove_close_lying() + # st2, _, _ = st2.remove_close_lying() + i1 = st1.find_atom_num_by_xcart(x_m, prec = 0.3) + i2 = st2.find_atom_num_by_xcart(x_del, prec = 0.3) + + if rep_moving_atom: #replace the moving atom by required + st1 = st1.replace_atoms([i1], rep_moving_atom) + st2 = st2.replace_atoms([i2], rep_moving_atom) + else: + #allows to make correct order for nebmake.pl + st1 = st1.replace_atoms([i1], type_atom_to_move) + st2 = st2.replace_atoms([i2], type_atom_to_move) - struct_des[it_new].x_m_ion_start = x_m - struct_des[it_new].xr_m_ion_start = xcart2xred([x_m], st1.rprimd)[0] - - # st1, _, _ = st1.remove_close_lying() - # st2, _, _ = st2.remove_close_lying() - i1 = st1.find_atom_num_by_xcart(x_m, prec = 0.3) - i2 = st2.find_atom_num_by_xcart(x_del, prec = 0.3) - - if rep_moving_atom: #replace the moving atom by required - st1 = st1.replace_atoms([i1], rep_moving_atom) - st2 = st2.replace_atoms([i2], rep_moving_atom) - else: - #allows to make correct order for nebmake.pl - st1 = st1.replace_atoms([i1], type_atom_to_move) - st2 = st2.replace_atoms([i2], type_atom_to_move) - - i1 = st1.find_atom_num_by_xcart(x_m, prec = 0.3) # the positions were changed - i2 = st2.find_atom_num_by_xcart(x_del, prec = 0.3) + i1 = st1.find_atom_num_by_xcart(x_m, prec = 0.3) # the positions were changed + i2 = st2.find_atom_num_by_xcart(x_del, prec = 0.3) cl.end = st1 @@ -718,19 +743,19 @@ def unique_by_key(elements, key=None): cl.write_siman_geo(geotype = 'end', description = 'Final conf. for neb from '+obtained_from, override = True) - if not rep_moving_atom: + if not rep_moving_atom and search_type is not None: st1s = st1.replace_atoms([i1], 'Pu') st2s = st2.replace_atoms([i2], 'Pu') else: st1s = copy.deepcopy(st1) st2s = copy.deepcopy(st2) - - vec = st1.center_on(i1) - st1s = st1s.shift_atoms(vec) - st2s = st2s.shift_atoms(vec) - write_xyz(st1s, file_name = it_new+'_start') - write_xyz(st2s, file_name = it_new+'_end') + if center_on_moving and search_type is not None: + vec = st1.center_on(i1) + st1s = st1s.shift_atoms(vec) + st2s = st2s.shift_atoms(vec) + write_xyz(st1s, file_name = it_new+'_start') + write_xyz(st2s, file_name = it_new+'_end') st1s.write_poscar('xyz/POSCAR1') @@ -778,7 +803,7 @@ def unique_by_key(elements, key=None): inherit_ngkpt(it_new, it, varset[ise_new]) - add_loop(it_new, ise_new, verlist = [1,2], up = up, calc_method = calc_method, savefile = 'oc', inherit_option = inherit_option, n_neb_images = images, corenum = corenum, run =run, **add_loop_dic ) + add_loop(it_new, ise_new, verlist = [1,2], up = up, calc_method = calc_method, savefile = 'oc', inherit_option = inherit_option, n_neb_images = images, corenum = corenum, run =run, params=params, **add_loop_dic ) if upload_vts: diff --git a/picture_functions.py b/picture_functions.py index b9d2402..33b8e22 100755 --- a/picture_functions.py +++ b/picture_functions.py @@ -125,7 +125,7 @@ def plot_mep(atom_pos, mep_energies, image_name = None, filename = None, show = print_and_log('plot_mep(): Diffusion barrier =',round(diff_barrier, 2),' eV', imp = 'y') # sys.exit() - + # print() path2saved = None if plot: @@ -137,13 +137,14 @@ def plot_mep(atom_pos, mep_energies, image_name = None, filename = None, show = fig_format = 'eps', **fitplot_args) # print(image_name, filename) - with open(filename+'.txt', 'w') as f: - f.write('DFT points:\n') - for m, e in zip(mep_pos, eners): - f.write('{:10.5f}, {:10.5f} \n'.format(m, e)) - f.write('Spline:\n') - for m, e in zip(xnew, ynew): - f.write('{:10.5f}, {:10.5f} \n'.format(m, e)) + if 0: + with open(filename+'.txt', 'w') as f: + f.write('DFT points:\n') + for m, e in zip(mep_pos, eners): + f.write('{:10.5f}, {:10.5f} \n'.format(m, e)) + f.write('Spline:\n') + for m, e in zip(xnew, ynew): + f.write('{:10.5f}, {:10.5f} \n'.format(m, e)) @@ -177,10 +178,11 @@ def process_fig_filename(image_name, fig_format): def fit_and_plot(ax = None, power = None, xlabel = None, ylabel = None, image_name = None, filename = None, - show = None, fontsize = None, pad = None, + show = None, pad = None, xlim = None, ylim = None, title = None, figsize = None, xlog = False,ylog = False, scatter = False, - legend = False, ncol = 1, legend_fontsize=None, markersize = None, + legend = False, ncol = 1, + fontsize = None, legend_fontsize=None, markersize = None, linewidth = None, hor = False, fig_format = 'eps', dpi = 300, ver_lines = None, xy_line = None, x_nbins = None, alpha = 0.8, fill = False, @@ -527,7 +529,8 @@ def fit_and_plot(ax = None, power = None, xlabel = None, ylabel = None, plt.show() plt.clf() plt.close('all') - + else: + printlog('Attention! last = False, no figure is saved') return path2saved @@ -968,8 +971,10 @@ def fit_and_plot(x1, y1, x2, y2, power, name = "", xlabel = "", ylabel = "", ima plt.tight_layout() #plt.savefig('images/'+image_name) - print_and_log( 'Saving file ...',path_to_images+str(image_name)+'.png', imp = 'y' ) - plt.savefig(path_to_images+str(image_name)+'.png',format='png', dpi = 300) + file = header.path_to_images+'/'+str(image_name)+'.png' + makedir(file) + print_and_log( 'Saving file ...',file, imp = 'y' ) + plt.savefig(file,format='png', dpi = 300) return fit_func2 diff --git a/project_funcs.py b/project_funcs.py new file mode 100644 index 0000000..daf8df3 --- /dev/null +++ b/project_funcs.py @@ -0,0 +1,3757 @@ +from __future__ import division, unicode_literals, absolute_import +import sys, copy, re, os +#external +import numpy as np +import pandas as pd +import matplotlib as mpl +import matplotlib.pyplot as plt + +import header +from header import print_and_log as printlog +from header import calc +from header import db +from picture_functions import fit_and_plot +from small_functions import merge_dics as md +from calc_manage import add_loop, name_mod_supercell, res_loop, inherit_icalc, push_figure_to_archive +from neb import add_neb +from classes import Calculation +from analysis import calc_redox, matrix_diff +from geo import create_deintercalated_structure +from geo import remove_one_atom +from geo import create_replaced_structure, create_antisite_defect3, determine_symmetry_positions +from inout import write_occmatrix +from database import add_to_archive_database + +mpl.rcParams.update({'font.size': 22}) + + + +def workflow(): + + # manually_remove_from_struct_des(struct_des, 'Na111.su') + + + #Na + # add_loop('Na111', '8u', 1, up = 'up1', input_geo_format = 'vasp', it_folder = 'Na/bcc') + + # Li + # res_loop('Li111', '8Utmb4', 1, up = 'up1',) + # res_loop('Li111', '2b4', 1, up = 'up1', input_geo_format = 'mat_proj', it_folder = 'Li/bcc') + # res_loop('Li111', '2b4', 1, up = 'up1') + # add_loop('K111', '8Utmb4', 1, up = 'up1', input_geo_format = 'mat_proj', it_folder = 'K/bcc') + + # add_loop('Li111', '', 1, ise_new = '1ub4', savefile = 'o', + # calc_method = 'uniform_scale', scale_region = [-4,4], it_folder = 'Li/bcc/scaled/', cluster = 'skol') + + # add_loop('Na111', '', 1, ise_new = '1ub4', savefile = 'o', + # calc_method = 'uniform_scale', scale_region = [-4,4], it_folder = 'Na/bcc/scaled/', cluster = 'skol') + + # add_loop('K111', '', 1, ise_new = '1ub4', savefile = 'o', + # calc_method = 'uniform_scale', scale_region = [-4,4], it_folder = 'K/bcc/scaled/', cluster = 'skol') + + # res_loop('Li111.su', ['1ub4'], [1, 2, 3, 4, 5, 6, 7, 100], up = 'up2', show = 'fofit', analys_type = 'fit_a' ) # , on 2016-10-19 + # res_loop('Na111.su', ['1ub4'], [1, 2, 3, 4, 5, 6, 7, 100], up = 'up2', show = 'fofit', analys_type = 'fit_a' ) # , on 2016-10-19 + # res_loop('K111.su', ['1ub4'], [1, 2, 3, 4, 5, 6, 7, 100], up = 'up2', show = 'fofit' , analys_type = 'fit_a' ) + + + # print (calc) + + + + + """OCC""" + # add_loop('LiFePO4', '1uOCC', 1, input_geo_format = 'vasp', show = 'fo') + + + + """Convergence""" + # add_loop('LiFePO4', '1u', 1, show = 'force') + # res_loop('LiCoO2', '9uk1', 1, show = 'force') + # res_loop('LiCoO2', '8ue4', 1, show = 'force') + # res_loop('LiCoO2', '8ue5', 1, show = 'force') + + + + """Uniform scale""" + #pmna from LiFePO4 + # inherit_icalc('replace_atoms', 'NaFePO4.pnma', 1, ('LiFePO4','9u',1), calc, atom_new = 'Na', atom_to_replace = 'Li', it_folder = 'NaFePO4') #on 2014-02-26 + # inherit_icalc('replace_atoms', 'KFePO4.pnma', 1, ('LiFePO4','9u',1), calc, atom_new = 'K', atom_to_replace = 'Li', it_folder = 'KFePO4') #on 2014-02-26 + + # res_loop('NaFePO4.pnma','1u', 1) + # res_loop('KFePO4.pnma','1u', 1, show = 'fo') + + + + # for ise in ['1u', 1ui', '4ui']: + # for ise in ['4uiWF', '4uiCF', '4uiCWF',]: + for ise in ['4ui', '4uiWF', ]: + '' + # add_loop('KFePO4.pnma','1u', 1, ise_new = '4uiCWF', savefile = 'o', calc_method = 'uniform_scale', scale_region = (4,12), inherit_option = 'inherit_xred' ) + # add_loop('FePO4.pnma2','1u', 1, ise_new = '4ui', savefile = 'o', calc_method = 'uniform_scale', scale_region = (-4,4), inherit_option = 'inherit_xred' ) + + # res_loop('KFePO4.pnma.su',ise, [1,2,3,4,5,6,100], up = '1', show = 'fo', analys_type = 'fit_a') + + #NaFePo + # add_loop('NaFePO4.pnma','1u', 1, ise_new = '4ui', savefile = 'o', calc_method = 'uniform_scale', scale_region = (-2,6), inherit_option = 'inherit_xred' ) + # res_loop('NaFePO4.pnma.su','4ui', list(range(1,8) )+[100], analys_type = 'fit_a' ) + + + # sys.exit() + + + + inherit_option = None + calc_method = 'neb' + + + """LiFePO4 """ + + """IS """ + #111 + # add_neb(calc['LiFePO4', '9u', 1], ise_new = '1uD', images = 3, corenum = 15, inherit_option = None, mag_config = None, replicate = None) + # res_loop('LiFePO4v1.n3Li1v1', '1', [1], show = 'mep', old_behaviour = 0 ) + + + # for ise in ['1ue6', '1uk1', '1ut' ]: + for ise in ['1ue5k15']: + # for ise in ['1uMM40','1up', '1upA' , '1upAMMD', ]: + # for ise in ['1up', '1upA']: + # for ise in ['1uMM40', '1up']: + # for ise in ['1uMM40', '1uA']: + # for ise in ['1uMM40','1uB03' , '1uB01' , '1uB005' ,]: + # for ise in ['1m', '1uA', '1uLF', '1ulm', '1uB05', '1uWC1000', '1ulmA04', '1uMM40']: + # for ise in [ '1m' ]: #inherit_magmom = False + # for ise in [ '1uD', '1uMM40' ]: + '' + # add_neb(calc['LiFePO4', '9u', 1], ise_new = ise, images = 3, corenum = 15, inherit_option = None, mag_config = None, inherit_magmom = True) + # res_loop('LiFePO4v1.n3Li1v1mp', ise, [5], show = 'fo', old_behaviour = 0 ) + # res_loop('LiFePO4v1.n3Li1v1ms', ise, [1,2,3,4,5], show = 'me', old_behaviour = 0 ) + + + # res_loop('LiFePO4.nebLi1v1','1u', [5,], show = 'en', old_behaviour = 0 ) + # res_loop('LiFePO4v1.n3Li1v1mp','1uMMD', [5,], show = 'en', old_behaviour = 0 ) + # res_loop('LiFePO4.nebLi1v1','1ulong', [1], show = 'occ', old_behaviour = 0 ) + + + if 0: #checking initial magmom - in this case ms and mp are equivalent, + '' + #but still some differences in final for 1uA. the situat. is much better for 1upAMMD, where smaller EDIFF is used + #for 1m no such problem + #intersting moment - the elapsed time could different for the same run + #since the base calc['LiFePO4', '9u', 1] did not have magmom + # print calc['LiFePO4v1.n3Li1v1mp', '1uA', 1].init.magmom + # print calc['LiFePO4v1.n3Li1v1ms', '1uA', 1].init.magmom + # print calc['LiFePO4', '9u', 1].end.magmom + # res_loop('LiFePO4v1.n3Li1v1mp', '1uA', [1], show = '', old_behaviour = 0 ) + # res_loop('LiFePO4v1.n3Li1v1ms', '1uA', [1], show = '', old_behaviour = 0 ) + + # res_loop('LiFePO4v1.n3Li1v1mp', '1upAMMD', [4], show = '', old_behaviour = 0 ) + # res_loop('LiFePO4v1.n3Li1v1ms', '1upAMMD', [4], show = '', old_behaviour = 0 ) + + # res_loop('LiFePO4v1.n3Li1v1mp', '1m', [4], show = '', old_behaviour = 0 ) + # res_loop('LiFePO4v1.n3Li1v1ms', '1m', [4], show = '', old_behaviour = 0 ) + + + if 0: #checking influence of MAXMIX + '' + # res_loop('LiFePO4.nebLi1v1','1u', [5,], show = 'en', old_behaviour = 0 ) + # res_loop('LiFePO4v1.n3Li1v1mp','1uMMD', [5,], show = 'en', old_behaviour = 0 ) + + + if 0: # cheking influence of restart + '' + + #result - doesnot help a lot + #TODO - make possible restart with magnetic moments initial for parent calc + + # res_loop('LiFePO4.nebLi1v1', '1ulong', [1], up = '1', show = 'fo', ) + # res_loop('LiFePO4.nebLi1v1', '1ulong', [1], up = '1', show = 'fo', ) + # res_loop('LiFePO4.nebLi1v1', '1ulong', [4], up = '1', show = 'fo', ) + # res_loop('LiFePO4.nebLi1v1', '1u', [1,2], up = '1', show = 'mep', ) + # res_loop('LiFePO4.nebLi1v1m0', '1u', [1,2], up = '1', show = 'mep', ) + # res_loop('LiFePO4.nebLi1v1m1', '1u', [1,2], up = '1', show = 'mag', ) + + + # res_loop('LiFePO4.nebLi1v1.ifn', '1u', [1,2], up = 'up1', show = 'mep', inherit_option = 'full_nomag' ) + # res_loop('LiFePO4.nebLi1v1m0.ifn', '1u', [1,2], up = 'up1', show = 'mep', inherit_option = 'full_nomag' ) + # res_loop('LiFePO4.nebLi1v1m1.ifn', '1u', [1,2], up = 'up1', show = 'mag', inherit_option = 'full_nomag' ) + + + if 0: #compare 1urNM and 1urm + '' + # res_loop('LiFePO4.nebLi1v1m0','1urNM', verlist = [2], up = 'up1', show = 'fo', old_behaviour = 0) + # res_loop('LiFePO4.nebLi1v1m0','1urm', verlist = [2], up = 'up1', show = 'en', old_behaviour = 1) + # res_loop('LiFePO4.nebLi1v1m1','1urm', verlist = [2], up = 'up1', show = 'fo', old_behaviour = 0) + + + + # res_loop('LiFePO4','9uk1', 1, up = 'up1',) #on 2016-09-03 + + + + + + #122 + # for ise in [ '1u', '1uA' ]: + for ise in [ '1m' ]: + ' ' + # add_neb(calc['LiFePO4', '9u', 1], ise_new = ise, images = 3, corenum = 15, replicate = (1,2,2), it_new_folder = 'LiFePO4/122/neb/') + # res_loop('LiFePO4.neb122Li1v1', '1urWF', [1,], up = '1', show = 'me', ) + # res_loop('LiFePO4.neb122Li1v1m1', '1urm', [1,2], up = '1', show = 'mep', ) + # res_loop('LiFePO4.neb122Li1v1m0', '1urm', verlist = [1, 2,], up = 'up1', show = 'fo', choose_image = 2, choose_outcar = 3 ) #on 2016-09-09 + + # res_loop('LiFePO4v1.n3122Li1v1ms',[u'1u'], verlist = [1], show ='mep' ) + # res_loop('LiFePO4v1.n3122Li1v1ms',[u'1uA'], verlist = [1], show ='occ' ) + + + # res_loop('LiFePO4v1.n3122Li1v1ms',[u'1m'], verlist = [1,], up = 'up1', show = 'mep') #on 2016-09-26 + + + + + #NaFePO4, + + # add_neb(calc['NaFePO4.pnma.su', '4ui', 100], ise_new = '1m', images = 3, corenum = 15, + # inherit_option = None, mag_config = None, replicate = None, inherit_magmom = False) + + + # res_loop('NaFePO4.pnma.n3Na1v1mp',[u'1ulong'], verlist = [1,2,4], up = 'up1', show = 'mepfo' ) #on 2016-09-15 + + # res_loop('NaFePO4.pnma.suv100.n3Na1v1mp',[u'1u'], verlist = [4,], show = 'me' ) # + # res_loop('NaFePO4.pnma.suv100.n3Na1v1ms',[u'1ulong'], verlist = [1,2,3,4,5], show = 'mep' ) #on 2016-09-28 + # res_loop('NaFePO4.pnma.suv100.n3Na1v1ms',[u'1uA'], verlist = [1,2,3,4,5], show = 'mep' ) #on 2016-09-28 + # res_loop('NaFePO4.pnma.suv100.n3Na1v1ms',[u'1ur30'], verlist = [1,2,3,4,5], show = 'mep' ) #on 2016-09-28 + # res_loop('NaFePO4.pnma.suv100.n3Na1v1ms', [u'1m'], [1, 2,3,4,5], show = 'fomep' ) # comment = None, on 2016-09-30 + + + # sys.exit() + + + + + + #KFePO4 + # add_neb(calc['KFePO4.pnma.su', '4uiWF', 100], ise_new = '1u', + # images = 3, corenum = 15, i_void_start = 1, i_void_final = 2, + # inherit_magmom = False) + + # res_loop('KFePO4.pnma.suv100.n3K1v1ms',[u'1u'], verlist = [1],show = 'mep' ) #on 2016-09-23 + + + # sys.exit() + + + + """DS """ + # + # res_loop('FePO4.pnma','1u', 1, up = 'up1', input_geo_format = 'vasp', it_folder = 'LiFePO4', mat_proj_id = 'mp-777026') #on 2016-09-03 + # res_loop('FePO4.pnma2','1u', 1, up = 'up1', input_geo_format = 'mat_proj', it_folder = 'LiFePO4', mat_proj_id = 'mp-25001') #on 2016-09-03 + if 1: + for i_s in [0,1]: + for i_f in [0,2]: + if i_s == 0 and i_f == 2: #stupid path + continue + atom_to_insert = 'Li' + # add_neb(calc['FePO4.pnma2', '1u', 1], ise_new = '1m', + # images = 3, corenum = 15, atom_to_insert = atom_to_insert, i_void_start = i_s, i_void_final = i_f, + # r_impurity = 1.6 , it_new_folder = atom_to_insert+'FePO4/neb/', + # inherit_magmom = False) + + # res_loop('FePO4.pnma2.n3i'+str(i_s)+'e'+str(i_f)+atom_to_insert, [u'1'], verlist = [1,2], up = 'up1', show = 'm', old_behaviour = 0 ) #on 2016-09-15 + # res_loop('FePO4.pnma21.n3i'+str(i_s)+'e'+str(i_f)+atom_to_insert, [u'1'], verlist = [1], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + # res_loop('FePO4.pnma21.n3i'+str(i_s)+'e'+str(i_f)+atom_to_insert+'ms', [u'1m'], verlist = [1], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + # res_loop('FePO4.pnma2.n7i'+str(i_s)+'e'+str(i_f)+atom_to_insert+'ms', [u'1usv'], verlist = [1,2], up = 'up1', show = 'mep' ) #on 2016-09-15 + # res_loop('FePO4.pnma2.n7i'+str(i_s)+'e'+str(i_f)+atom_to_insert+'ms', [u'1ulong'], verlist = [2], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + + # for ise in ['1ur', '1urWF', '1uA', '1uLF' ]: + # res_loop('FePO4.pnma2v1.n3i1e2Lims', ise, verlist = [1], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + atom_to_insert = 'Li' + + # add_neb(calc['FePO4.pnma2', '1u', 1], ise_new = '1ur30', + # images = 3, corenum = 15, atom_to_insert = atom_to_insert, i_void_start = 1, i_void_final = 2, + # r_impurity = 1.6 , it_new_folder = atom_to_insert+'FePO4/neb/', + # inherit_magmom = False) + + # sys.exit() + #Li + + # res_loop('FePO4.pnma2.n3i1e2Lims', '1u', verlist = [1], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + # res_loop('FePO4.pnma2v1.n3i1e2Lims', '1ur', verlist = [1], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + # res_loop('FePO4.pnma2v1.n7i1e2Lims',[u'1ur30'], verlist = [1], show = 'mep' ) #on 2016-09-22 + # add_neb(calc['FePO4.pnma2', '1u', 1], ise_new = '1u', images = 3, corenum = 15, + # i_void_start = 1, i_void_final = 2, atom_to_insert = 'Li', + # r_impurity = 1.6 , + # inherit_magmom = False, it_new_folder = 'LiFePO4/neb/') + + # res_loop('FePO4.pnma2v1.n3i1e2Lims',[u'1u'], verlist = [1], show ='mep' ) #on 2016-09-26 + + # res_loop('FePO4.pnma2.n3i1e2Li',[u'1u'], verlist = [1], up = 'up1', show = 'mep') + # res_loop('FePO4.pnma2.n7i1e2Lims',[u'1ulong'], verlist = [1,2,3,4,5,6,7,8,9], analys_type = 'neb', show = 'mep') + # res_loop('FePO4.pnma2v1.n7i1e2Lims',[u'1ur30'], verlist = [1,2,3,4,5,6,7,8,9], analys_type = 'neb', show = 'mep') + + # res_loop('FePO4.pnma2v1.n7i1e2Lims.if',[u'0m'], 6, show = 'fo' ) #??? + + # res_loop('FePO4.pnma2v1.n3i1e2Lims', [u'1ur30'], [1, 2,3,4,5], choose_outcar = None, show = 'mag', analys_type = 'neb' ) # for OMC tutorial!!! + + + + + + + + + + #122 + # add_neb(calc['FePO4.pnma2', '1u', 1], ise_new = '1ur30s', images = 3, corenum = 15, + # replicate = (1,2,2), i_void_start = 2, i_void_final = 2, atom_to_insert = 'Li', + # r_impurity = 1.6 , + # inherit_magmom = False, it_new_folder = 'LiFePO4/122/neb/') + + # res_loop('FePO4.pnma2v1.n3122i2e2Lims',[u'1u'], verlist = [4,], show = 'mep' ) #on 2016-09-26 + # res_loop(u'FePO4.pnma2v1.n7i1e2Lims', u'1ur30', 6, show = 'occ' ) #on 2016-09-26 + # add_loop('FePO4.pnma2v1.n3122i2e2Lims',[u'1u'], verlist = [4,], inherit_option = 'occ', ise_new = '1uos', + # id_from = ('FePO4.pnma2v1.n7i1e2Lims', '1ur30', 6), it_folder = 'LiFePO4/inherited',) + + # add_loop('FePO4.pnma2v1.n3122i2e2Lims.ifo', [u'1uos'], [4],up = 'up1', show = 'fo' ) # comment = None, on 2016-09-28 + # sys.exit() + # res_loop('FePO4.pnma2v1.n3122i2e2Lims.ifo', [u'1uos'], [4], up = 'up2', show = 'occ' ) # comment = None, on 2016-09-29 + + + + """hybrid functional!""" + + # add_loop('LiFePO4','1hss', 1,) + + # res_loop('LiFePO4','1hss', 1,) + # res_loop('LiFePO4','1u', 1,) + + + # add_loop('FePO4.pnma2','1hss', 1) + + # add_neb(calc['FePO4.pnma2', '1u', 1], ise_new = '1hse', images = 3, corenum = 15, + # i_void_start = 1, i_void_final = 2, atom_to_insert = 'Li', + # r_impurity = 1.6 , + # inherit_magmom = False, it_new_folder = 'LiFePO4/neb/') + + + + + + #Na + # res_loop('FePO4.pnma2v1.n3i1e2Nams', '1u', verlist = [1], up = 'up1', show = 'mep', old_behaviour = 0 ) #on 2016-09-15 + + #K + # atom_to_insert = 'K' + # add_neb(calc['FePO4.pnma2', '1u', 1], ise_new = '1u', + # images = 3, corenum = 15, atom_to_insert = atom_to_insert, i_void_start = 1, i_void_final = 2, + # r_impurity = 1.6 , it_new_folder = atom_to_insert+'FePO4/neb/', + # inherit_magmom = False) + + # res_loop('FePO4.pnma2v1.n3i1e2Kms',[u'1u'], verlist = [1,2,3,4,5], up = 'up1', show ='fo') + + + + # sys.exit() + + + + if 0: #checking influence of compression on neb + '' + atom_to_insert = 'Li' + + # add_neb(calc['FePO4.pnma2.su', '1u', 1], ise_new = '1u', + # images = 3, corenum = 15, atom_to_insert = atom_to_insert, i_void_start = 1, i_void_final = 2, + # r_impurity = 1.3 , it_new_folder = atom_to_insert+'FePO4/neb/', + # inherit_magmom = False) + + # add_neb(calc['FePO4.pnma2.su', '1u', 2], ise_new = '1u', + # images = 3, corenum = 15, atom_to_insert = atom_to_insert, i_void_start = 2, i_void_final = 3, + # r_impurity = 1.4 , it_new_folder = atom_to_insert+'FePO4/neb/', + # inherit_magmom = False) + + # res_loop('FePO4.pnma2.suv1.n3i1e2Lims', [u'1u'], verlist = [4], up = 'up1', show = 'me') + # res_loop('FePO4.pnma2.n3i1e2Li', [u'1u'], verlist = [4], up = 'up1', show = 'me') + # res_loop('FePO4.pnma2.suv2.n3i2e3Lims',[u'1u'], verlist = [1,2,3,4,5], up = 'up1', show = 'mep' ) #on 2016-09-23 + + # sys.exit() + + + + #LiVPO4F + # res_loop('LiVPO4F.nebLi1v1','1ur', verlist = [1,2,3,4,5], up = 'up1', show = 'fo', old_behaviour =0) #on 2016-09-08 + + + + + #LiMnPO4 + for it in ['LiMnPO4', 'LiNiO2', ]: + '' + # add_neb(calc[it, '9u', 1], ise_new = '1u', images = 3, corenum = 15, inherit_option = None, mag_config = None, inherit_magmom = False) + # res_loop(it+'v1.n3Li1v1ms',[u'1u'], verlist = [1,2,3,4,5], up = 'up1', show = 'm') #on 2016-09-23 + + + # add_neb(calc['LiCoPO4', '8Utmr2-8', 1], ise_new = '1u', images = 3, corenum = 15, inherit_option = None, mag_config = None, inherit_magmom = False) + + #LiMnPO4 + # res_loop('LiCoPO4v1.n3Li1v1ms',[u'1u'], verlist = [1,2,3,4,5], up = 'up1', ) #on 2016-09-23 + # res_loop('CoPO4v1.n3i3e2Nams', [u'1u'], [1, 2,3,4,5], show = 'mep' ) # comment = None, on 2016-09-29 + + + + #DS + # add_neb(calc['CoPO4', '8Utmr4-2', 1], ise_new = '1u', + # images = 3, corenum = 15, + # atom_to_insert = 'Na', i_void_start = 3, i_void_final = 2, + # r_impurity = 1.8 , it_new_folder = 'LiCoPO4/neb/' + # ) + + # sys.exit() + #NaMnAsO4 + #IS + # add_neb(calc['NaMnAsO4', '8u', 1], ise_new = '1u', images = 3, corenum = 15, inherit_option = None, mag_config = None, inherit_magmom = False) + # res_loop('NaMnAsO4v1.n3Na17v1ms', [u'1u'], [1, 2,3,4,5], show = 'mep' ) # comment = None, on 2016-09-29 + + + #DS + # add_neb(calc['MnAsO4', '8u', 1], ise_new = '1u', + # images = 3, corenum = 15, inherit_option = None, mag_config = None, inherit_magmom = False, + # atom_to_insert = 'Na', i_void_start = 0, i_void_final = 0, + # r_impurity = 1.6 , it_new_folder = 'NaMnAsO4/neb/' + # ) + + # res_loop('MnAsO4v1.n3i0e1Nams', [u'1u'], [1, 2,3,4,5], show = 'mep' ) # comment = None, on 2016-09-29 + # res_loop('MnAsO4v1.n3i0e0Nams', [u'1u'], [1, 2,3,4,5], show = 'fomep' ) # comment = None, on 2016-09-29 + + + # sys.exit() + + + #some additional + # add_loop('Na2FePO4F', '1u', 1, input_geo_format = 'cee_database', it_folder = 'Na2FePO4F') + # add_loop('KFeSO4F', '1u', 1, input_geo_format = 'cee_database', it_folder = 'KFeSO4F') + # add_loop('Na2FeVF7', '1u', 1, input_geo_format = 'cee_database', it_folder = 'Na2FeVF7') + + + + + + + + + + + + """Charge den analysis""" + calc = header.calc + # print calc['LiFePO4.nebLi1v1', '1u', 1].get_chg_file('CHG') + # print calc['LiFePO4v1.n3Li1v1ms', '1m', 1].get_chg_file('CHG') + # print calc['LiFePO4.nebLi1v1.if', '0m', 1].get_chg_file('CHG') + # print calc['FePO4.pnma2v1.n7i1e2Lims', '1ur30', 1].get_chg_file('CHG') + + # print (calc['LiFePO4.nebLi1v1', '1u', 4].get_chg_file('CHG')) + # print (calc['LiFePO4.nebLi1v1.if','0m', 4].get_chg_file('CHG', 'asoutcar')) + + # print (calc['LiFePO4.nebLi1v1.ifi', '0u', 1].get_chg_file('CHG', 'asoutcar')) + # print (calc['LiFePO4', '1u', 1].get_chg_file('CHG', 'asoutcar')) + + + # add_loop('LiFePO4.nebLi1v1','1u', 1, up = 'up1', ise_new = '0m', inherit_option = 'full' ) + # add_loop('LiFePO4.nebLi1v1','1u', 4, up = 'up1', ise_new = '0m', inherit_option = 'full', savefile = 'ocv', override = 1 ) + # res_loop('LiFePO4.nebLi1v1', '1u', 1, show = 'mag', ) + # res_loop('LiFePO4.nebLi1v1', '1u', 1, show = 'mag', ) + # res_loop('LiFePO4','1u', 1, show = 'occ', ) + + + # add_loop('FePO4.pnma2v1.n7i1e2Lims','1ur30', 6, up = 'up1', ise_new = '0m', inherit_option = 'full' ) + + + # inherit_icalc('full', 'LiFePO4.nebLi1v1.ifi', 1, ('LiFePO4.nebLi1v1','1u',1), header.calc, id_base_st_type = 'init', it_folder = 'LiFePO4' ) #on 2014-02-26 + # add_loop('LiFePO4.nebLi1v1.ifi', '0u', 1, savefile = 'cov') + # res_loop('LiFePO4.nebLi1v1.ifi', '0u', 1, show = 'mag') + + + + + + # + + # add_loop('LiFePO4.nebLi1v1','1u', 1, up = 'up1', ise_new = '1urseq', calc_method = 'uniform_scale', it_folder = 'LiFePO4/uscale/', scale_region = [-2,6], inherit_option = 'inherit_xred' ) + # sys.exit() + + # add_loop('LiFePO4.nebLi1v1','1useq', [1,2], up = 'up1', ise_new = '1urseq', calc_method = 'neb', n_neb_images = 3 ) + # sys.exit() + + """OMC analysis""" + # res_loop('LiFePO4.nebLi1v1','1u', 4, show = 'occ') + + # res_loop('FePO4.pnma2v1.n3i1e2Lims',[u'1u'], verlist = [4], show ='occ21' ) + + + # res_loop('FePO4.pnma2.n7i1e2Lims', [u'1ulong'], verlist = [1], show = 'oc') + # res_loop('FePO4.pnma2v1.n7i1e2Lims',[u'1ur30'], verlist = [6], show = 'occ' ) + + + + # add_loop('FePO4.pnma2.n7i1e2Lims','1ulong', 1, up = 'up1', inherit_option = 'occ', ise_new = '1uos', + # id_from = ('FePO4.pnma2v1.n7i1e2Lims', '1ur30', 1), it_folder = 'LiFePO4/inherited' ) + # res_loop('FePO4.pnma2.n7i1e2Lims.ifo','1uomc', 1, up = 'up2', show = 'occ' ) + # res_loop('FePO4.pnma2.n7i1e2Lims.ifo','1uos', 1, show = 'occ' ) + + + + # res_loop('LiCoO2.s10','1urs',1, choose_outcar = 0, show = 'maga') + # res_loop('LiCoO2.s10.su','4uis',100, choose_outcar = 0, show = 'maga') + + + + + # res_loop('NiO2.id.su.s10.su','4uris',100, choose_outcar = 3, show = 'oc') + # res_loop('NiO2.id.su.s10.su','4uris',100, choose_outcar = 4, show = 'oc') + + # res_loop('NiO2.id.su','4uis', 4, choose_outcar = 2, show = 'smag') + # res_loop('NiO2.id.su','4uisWF',4, choose_outcar = 2, show = 'smag') + # res_loop('NiO2.id.su','4uis',4, choose_outcar = 2, show = 'smag') + + # res_loop('NiO2.id.su','4uisC0W1',4, choose_outcar = 1, show = 'smag') + # res_loop('NiO2.id.su','4uisWF', list(range(1,7))+[100], choose_outcar = 2, show = 'fi', analys_type = 'fit_a') + # res_loop('NiO2.id.su','4uisC0W1', list(range(1,7))+[100], choose_outcar = 1, show = 'fo', analys_type = 'fit_a') + # ('NiO2.id.su', '4uisC0W1', 7) + # ('NiO2.id.su', '4uisC0W2', 7) + + # print(calc['NiO2.id.su','4uis',4].dir) + + + + # res_loop('LiFePO4.s10.suv100.n3Li1v1ms','1urs',4, choose_outcar = 3, show = 'occ102') + # res_loop('LiFePO4.s10.suv100.n3Li1v1ms','1urs',4, choose_outcar = 4, show = 'occ102') + + + # add_loop('Na111', '8u', 1, up = 'up1', input_geo_format = 'vasp', it_folder = 'Na/bcc') + + + + + """Space groups""" + + # res_loop('LiNiO2.r3m','1u', 1, input_geo_format = 'mat_proj', it_folder = 'LiNiO2/r3m', mat_proj_id = 'mp-25592') #on 2016-09-03 + # add_loop('NiO2.r3m','1u', 1, input_geo_format = 'mat_proj', it_folder = 'LiNiO2/r3m', mat_proj_id = 'mp-35925') + # res_loop('NiO2.r3m','1u', 1, input_geo_format = 'mat_proj', it_folder = 'LiNiO2/r3m', mat_proj_id = 'mp-35925', show = 'occ1') + # res_loop('NiO2.r3m.id.su','4urisC0W1',100, show = 'occ1') + # res_loop('NiO2.r3m.id.su','4uiAl',100, show = 'occ1') + # rprimd = calc['KVPO4F.Pna21','1u', 1].init.rprimd + # print(rprimd) + # print(calc['NiO2.r3m.id.su','4urisC0W1', 1].end.rprimd) + # res_loop('LiTiS2.s10.su','4uis',100, show = 'occ1' ) + # from geo import ortho_vec2, ortho_vec + # print(ortho_vec(rprimd, [10,10,10]) ) + # print(ortho_vec2(rprimd, [10,10,10]) ) + + # add_loop('LiMn2O4.Fd3m.111','1u', 1, input_geo_format = 'mat_proj', it_folder = 'LiMn2O4/Fd3m', mat_proj_id = 'mp-25015', mat_proj_cell = 'conv') #on 2016-09-03 + # res_loop('LiMn2O4.Fd3m.111','1u', 1, show = 'fomag') #on 2016-09-03 + # res_loop('LiMn2O4.Fd3m','1urs', 1, choose_outcar = 3, show = 'mag') #on 2016-09-03 + # res_loop('LiMn2O4.Fd3m','1u', 1, show = 'fomag') #on 2016-09-03 + # res_loop('LiMn2O4.Fd3m.s10','1urs', 1, show = 'fomag', choose_outcar = 3) #on 2016-09-03 + # res_loop('LiMn2O4.Fd3m.s10','1ur10', 1, show = 'fomag', choose_outcar = 10) #on 2016-09-03 + # print (calc['LiMn2O4.Fd3m','1u',1].end.get_space_group_info() ) + # print (calc['LiMn2O4.Fd3m.s10','1ur10',1].end.get_space_group_info() ) + # print (calc['LiMn2O4.Fd3m.111','1u', 1,].end.get_space_group_info() ) + # res_loop('LiMn2O4.Fd3m.111','1u', 1,) + + + # print (calc['Na2FePO4F.s10','1urs', 1,].end.get_space_group_info() ) + + # add_loop('KVPO4F.Pna21','1u', 1, input_geo_format = 'cee_database', it_folder = 'KVPO4F/Pna21', cee_file = 'x1aa_exp.cif') #on 2016-09-03 + # res_loop('KVPO4F.Pna21','1u', 1, input_geo_format = 'cee_database', it_folder = 'KVPO4F/Pna21') #on 2016-09-03 + # add_loop('Na2FePO4F', '1u', 1, input_geo_format = 'cee_database', it_folder = 'Na2FePO4F') + # print (calc['KVPO4F.Pna21','1u', 1].init.get_space_group_info() ) + + + # print (calc['LiVPO4F.s10.su','4uis',100].end.get_space_group_info() ) + # print (calc['LiVP2O7.s10.su','4uis',100].end.get_space_group_info() ) + # print (calc['LiNiO2.s10.su','4uisns',100].end.get_space_group_info() ) + + # print (calc['NiO2.id.su','4uisC0W1',1].init.get_space_group_info() ) + # print (calc['NiO2.id.su','4uisC0W1',1].init.get_space_group_info() ) + + # print (calc['LiTiO2.s10.su','4uisns',100].end.get_space_group_info() ) + # print (calc['TiS2.id.su','4uis',100].end.rprimd ) + # print (calc['TiS2','8Utm3-5',1].end.rprimd ) + # sys.exit() + # print (calc['LiTiS2.s10.su','4uis',100].end.get_space_group_info() ) + # print (calc['LiMn2O4.s10.su','4uis',100].end.get_space_group_info() ) + # print (calc['LiTiS2.s10.su','4uis',100].end.get_space_group_info() ) + # print (calc['KVPO4F.ir.su','4uisC0W1',100].end.get_space_group_info() ) + + # print (calc['Li2FePO4F.ir.su.s10.su','4uis',100].end.get_space_group_info() ) + + + # res_loop('LiFePO4.s10.suv100.n3Li1v1ms','1urs',4, choose_outcar = 3 , show = 'occ97') + # res_loop('LiFePO4.s10.suv100.n3Li1v1ms','1urs',4, choose_outcar = None, show = 'occ97') + + + + + + + + + + + + """For notebooks""" + + # sys.path.extend(['/home/aksenov/Simulation_wrapper/siman', '/home/aksenov/Simulation_wrapper/SSHTools']) + # from SSHTools import SSHTools + # header.ssh_object = SSHTools() + # header.ssh_object.setup(user="aksenov",host="10.30.16.62",pkey="/home/aksenov/.ssh/id_rsa") + # header.PATH2PROJECT = 'topologic' + # header.varset['static'].potdir = {83:'Bi_pv', 34:'Se'} + # header.siman_run = 0 + # add_loop('Bi2Se3', 'static', 1, input_geo_file = 'Bi2Se3_mp-541837_computed.cif', it_folder = 'Bi2Se3', run = 0) + + # res_loop('Bi2Se3', 'static', 1, up = 'up') + # header.warnings = 'yY' + # add_loop('Bi2Se3', 'static', 1, calc_method = 'uniform_scale', scale_region = (-5, 5), run = 0) + + + + from dos_functions import plot_dos + # add_loop('Li2', 'dosb4', 1, run = 1) + # res_loop('Li2', 'dosb4', 1, ) + # add_loop('Li2', 'fullb4sdos', 1, run = 1) + # plot_dos(calc['Li2', 'dosb4', 1], dostype = 'partial', orbitals = 'd') + # plot_dos(calc['Li2', 'fullb4sdos', 1], dostype = 'partial', orbitals = 's', up = 1, show =0 ) + + # header.PATH2PROJECT = 'topologic' + + # add_loop('Bi2Se3', 'dos', 1, input_geo_file = 'Bi2Se3_mp-541837_computed.POSCAR', run = 0) + + + # res_loop('Bi2Se3', 'dos', 1) + # plot_dos(header.calc['Bi2Se3', 'dos', 1], dostype = 'total') + + + + + # add_loop('Li2', 'fullb4', 1, run =0) + # res_loop('Li2', 'fullb4', 1, show = 'fo', up = 'up') + # add_loop('Li2', 'fullb4', 1, ise_new = 'ion', inherit_option = 'supercell', mul_matrix = [[3,0,0],[0,3,0],[0,0,3]], run = 1) + # res_loop('Li2.s333', ['ion'], [1], up = 'up2', show = 'fo' ) + # add_loop('Li2.s333', ['ion'], [1], inherit_option = 'make_vacancy', i_atom_to_remove = 0, run = 1, override = 1) + + # res_loop('Li2.s333.vac', ['ion'], [1], up = 'up2', show = 'fo', analys_type = 'matrix_diff', b_id = ('Li2.s333', 'ion', 1)) + from impurity import add_impurity + # add_impurity('Li2.s333.oct', 'Li', calc = calc, it_to = 'Li2.s333', put_exactly_to = (0, 1/6, 1/6)) + + # add_loop('Li2.s333.tet', ['ion'], [1], run = 1, override = 1) + # res_loop('Li2.s333.tet', ['ion'], [1], show = 'fo', analys_type = 'matrix_diff', b_id = ('Li2.s333', 'ion', 1)) + # add_loop('Li2.s333.oct', ['ion'], [1], run = 1, override = 1) + # res_loop('Li2.s333.oct', ['ion'], [1], show = 'fo', analys_type = 'matrix_diff', b_id = ('Li2.s333', 'ion', 1)) + + from impurity import find_pores + # st = calc['Li2.s333', 'ion', 1].end + # st_pores = find_pores(calc['Li2.s333', 'ion', 1].end, r_matrix = 1.0, r_impurity = 0.5, fine = 1, calctype = 'all_pores') + # write_xyz(st.add_atoms(st_pores.xcart, 'H'), file_name = st.name+'_possible_positions') + + + + + def test_energy_convergence(): + """Comparison of two Li2FePO4 structures obtained with U-ramping and without it""" + + + # res_loop('Li2FePO4F.ir.su.s10.su.ifn','1ur30', 100, show = 'occ35') + # res_loop('Li2FePO4F.ir.su.s10.su', '4uis', 100, show = 'occ35') + + # add_loop('Li2FePO4F.ir.su.s10.su.ifn','1ur30', 100, ise_new = '0ur', inherit_option = 'full', savefile = 'ocv', override = True) + # add_loop('Li2FePO4F.ir.su.s10.su', '4uis', 100, ise_new = '0ur', inherit_option = 'full', savefile = 'ocv', override = True) + res_loop('Li2FePO4F.ir.su.s10.su.if', ['0ur'], [100], show = 'occ', choose_outcar = 3 ) + res_loop('Li2FePO4F.ir.su.s10.su.ifn.if', ['0ur'], [100], show = 'occ', choose_outcar = 3 ) # relaxed in some high energy state + # print(calc['Li2FePO4F.ir.su.s10.su.if', '0ur', 100].get_chg_file('100.U00.CHGCAR')) + # print(calc['Li2FePO4F.ir.su.s10.su.ifn.if', '0ur', 100].get_chg_file('100.U00.CHGCAR')) + + # res_loop('Li2FePO4F.ir.su', '4uis', 100) + # add_loop('Li2FePO4F.ir.su', '4uis', 100, ise_new = '1urs', inherit_option = 'full', savefile = 'ocv', override = True) + + # add_loop('Li2FePO4F.ir.su.if', '1urst5', 100) + # res_loop('Li2FePO4F.ir.su.if', '1urs', 100, show = 'fo') + # res_loop('Li2FePO4F.ir.su.if', '1urst5', 100, show = 'fo', choose_outcar = 3) + # res_loop('Li2FePO4F.ir.su.if', '1urst5', 100, show = 'fo', choose_outcar = 4) + + # add_loop('Li2FePO4F.ir.su.if', '1ursns', 100) + + + # test_energy_convergence() + + + + + + + + + + + + """Adding to database""" + # from calc_manage import add_to_database + # cl = calc['Li2FePO4F.ir.su.s10.su','4uis',100] + # print(cl.end.natom) + # print (st.get_space_group_info()) + # add_to_database(cl) + + # calc2['asdf'] = 'test' + # print(calc2['asdf']) + + + + + + + + + """Additional task""" + if 0: + from set_functions import InputSet + folder = '/home/aksenov/scientific_projects/cathode/azh_task/' + ise = 'azh30' + s = InputSet('azh30', folder+'POTCAR') + # varset[ise] = + s.read_incar(folder+'/INCAR') + s.kpoints_file = folder+'/KPOINTS' + s.vasp_params['LDAUL'] = {'Co':2} + s.vasp_params['LDAUU'] = {'Co':5.7} + s.vasp_params['LDAUJ'] = {'Co':0} + s.u_ramping_nstep = 30 + s.save_last_wave = True + # manually_remove_from_struct_des(struct_des, 'CoPO4F') + + # add_loop('CoPO4F', 'azh', 1, input_geo_file = 'azh_task/POSCAR', it_folder = 'azh_task') + # res_loop('CoPO4F', '0ur', 1, input_geo_file = 'azh_task/POSCAR', it_folder = 'azh_task') + + # res_loop('CoPO4F', 'azh30', 1, input_geo_file = 'azh_task/POSCAR', it_folder = 'azh_task', show = 'mag') + # res_loop('CoPO4F', '0u57r', 1, input_geo_file = 'azh_task/POSCAR', it_folder = 'azh_task', show = 'mag') + + + + + + + + + + Li2Co_pbcn = calc['Li2CoPO4F.pbcn.su','4uis',100] #'Li2CoPO4F.pbcn.su.s10' + # v_LiCo = calc['LiCoPO4F.pbcn.id1.su.s10','1u',100] + + cl = Li2Co_pbcn + it_folder = header.struct_des[cl.id[0]].sfolder+'/chg' + for del_pos in 1, 2: + it_new = cl.id[0]+'.id'+str(del_pos) + # st = create_deintercalated_structure(cl.end, 'Li', del_pos = del_pos) + # add_loop(it_new,'0u',1, input_st = st, it_folder = it_folder, override = True) #charge density without relaxation + res_loop(it_new,'0u',1) + + + v_LiCo_pbcn = calc['Li2CoPO4F.pbcn.su.id1','0u',1] + cal_chg_diff(Li2Co_pbcn, v_LiCo_pbcn, wcell = 0) + + + + + + + + + + + from analysis import calc_redox + + + # calc_redox(calc['KVPO4F.Pna21.s10.su','4uis',100], calc['VPO4F.Pna21.id.su.s10.su','4uis',100]) + + + + + from geo import determine_symmetry_positions + + # st = calc['NaFePO4F.id1.su.s10.su','4uis',100].end + # st = calc[('KVPO4F.Pna21', '1u', 1)].end + # st = calc['LiFePO4F.pnma.id2.su.s10','1u',100].end + # determine_symmetry_positions(st, 'Fe') + + + + from geo import create_antisite_defect2 + + st1 = calc['NaFePO4F.id1.su.s10.su','4uis',100].init + st2 = calc['NaFePO4F.id2.su.s10.su','4uis',100].end + # print(st1.convert2pymatgen()) + # print() + + + # st = create_antisite_defect2(st_base = st2, st_from = st1, cation = 'Na', trans = 'Fe', mode = 'add_swp') + + + + + + + + from calc_manage import smart_structure_read + + + + # st = calc['Li2CoPO4F.pnma','1u', 1].end + # print(calc['Li2CoPO4F.pnma','1u', 1].end.get_elements()) + # from geo import create_deintercalated_structure + # create_deintercalated_structure(st, 'Li', del_pos = 1) + + + + # add_loop('Li2CoPO4F.pnma','1u', 1, input_geo_format = 'mat_proj', it_folder = 'Li2CoPO4F/pnma', mat_proj_id = 'mp-770853') + + # add_loop('Li2CoPO4F.pbcn','1u', 1, input_geo_format = 'mat_proj', it_folder = 'Li2CoPO4F/pbcn', mat_proj_id = 'mp-770624') + + # add_loop('Li2CoPO4F.pnma','1ur', 1, input_geo_format = 'mat_proj', it_folder = 'Li2CoPO4F/pnma', mat_proj_id = 'mp-770853', run = 1) + + + # res_loop('Li2CoPO4F.pbcn','1u', 1) + # res_loop('Li2CoPO4F.pnma','1u', 1) + # res_loop('Li2CoPO4F.pnma','1ur', 1, show = 'occ') + + # st = smart_structure_read(input_geo_file = 'Li2FePO4F/Li2FePO4F_abakumov.cif') + + # add_loop('Li2FePO4F.abak','1u', 1, input_geo_file = 'Li2FePO4F/Li2FePO4F_abakumov.cif', it_folder = 'Li2FePO4F/pnma' ) + # res_loop('Li2FePO4F.abak','1u',1, show = 'fo') + # st = calc['Li2FePO4F.abak','1u',1].end + # st = calc['Li2FePO4F.pnma','1u', 1].end + # print(st.convert2pymatgen()) + # print(st.get_space_group_info(0.3)) + + + # add_loop('Li2FePO4F.pnma','1u', 1, input_geo_format = 'mat_proj', it_folder = 'Li2FePO4F/pnma', mat_proj_id = 'mp-776062') + + # res_loop('Li2FePO4F.pnma','1u', 1) + # res_loop('Li2FePO4F.ir.su','4uis',100) + + + # calc['Li2FePO4F.abak','1u',1].end.jmol() + # calc['Li2FePO4F.pnma','1u', 1].end.jmol() + + + + + + + # add_loop('LiCrPO4.pnma','1u', 1, input_geo_format = 'mat_proj', it_folder = 'LiCrPO4/pnma', mat_proj_id = 'mp-25507') + # add_loop('LiCrPO4.pnma','1u', 1, input_geo_format = 'mat_proj', it_folder = 'LiCrPO4/pnma', mat_proj_id = 'mp-25507') + if 0: + param_dic = {'id':('LiCrPO4.pnma','', 1), 'ds':'CrPO4.pnma', 'itfolder':'LiCrPO4/pnma', 'main_set':'1u' } + # calc_barriers('normal', up = 0, param_dic = param_dic) + # calc_barriers('replace', 'Li', 'Na', show_fit = 0, up = 0, upA = 0, param_dic = param_dic) + calc_barriers('make_ds', 'Li', 'Na', show_fit = 0, up = 0, upA = 0, param_dic = param_dic) + + + + # from SSHTools import SSHTools + # header.ssh_object = SSHTools() + # header.ssh_object.setup(user="aksenov",host="10.30.16.62",pkey="/home/aksenov/.ssh/id_rsa") + + + + + + + + + + + # add_loop('Bi2Se3.hex', '1', 1, input_geo_file = 'Bi2Se3/Bi2Se3_hex.POSCAR', it_folder = 'Bi2Se3', run = 1) + # add_loop('Bi2Se3.rho', '1', 1, input_geo_file = 'Bi2Se3_mp-541837_computed.POSCAR', it_folder = 'Bi2Se3', run = 0) + + + # res_loop('Bi2Se3.hex.su', '1', 100) + # res_loop('Bi2Se3.rho', '1', 1) + + # add_loop('Bi2Se3.hex', '1', 1, calc_method = 'uniform_scale', inherit_option = 'inherit_xred', scale_region = (-4, 4), run = 1) + + + # print(calc['Bi2Se3.hex.su', '1', 100].energy_sigma0/15 - calc['Bi2Se3.rho', '1', 1].energy_sigma0/5) + + # res_loop('Bi2Se3.hex.su', ['1'], [1, 2, 3, 4, 5, 6, 7, 100], show = 'fitfo', analys_type = 'fit_a' ) + + # add_loop('Bi2Se3.rho', '1', 1, ise_new = '0bsr', inherit_option = 'full', savefile = 'ocx', override = 1, run = 1) + + # add_loop('Bi2Se3.rho', 'dos', 1, savefile = 'ocx', input_geo_file = 'Bi2Se3_mp-541837_computed.POSCAR', it_folder = 'Bi2Se3', run = 0) + + # res_loop('Bi2Se3.rho.if', '0bsr', 1 ,up = 'x') + # res_loop('Bi2Se3.rho', 'dos', 1 ,up = 'x') + + # add_loop('Bi2Se3.rho', '1', 1, ise_new = '0bsrsoc', inherit_option = 'full', savefile = 'ocx', override = 1, run = 1) + # add_loop('Bi2Se3.rho', '1', 1, ise_new = '0bsrsoc100', inherit_option = 'full', savefile = 'ocx', override = 1, run = 1) + # add_loop('Bi2Se3.rho', '1', 1, ise_new = '0bsrsoc010', inherit_option = 'full', savefile = 'ocx', override = 1, run = 1) + # add_loop('Bi2Se3.rho', '1', 1, ise_new = '0bsrsoc000', inherit_option = 'full', savefile = 'ocx', override = 1, run = 1) + # add_loop('Bi2Se3.rho', '1', 1, ise_new = '0bsrsoc0', inherit_option = 'full', savefile = 'ocx', override = 1, run = 1) + + # res_loop('Bi2Se3.rho.if', '0bsrsoc', 1, up = 'x') + # res_loop('Bi2Se3.rho.if', '0bsrsoc100', 1, up = 'x') + # res_loop('Bi2Se3.rho.if', '0bsrsoc010', 1, show = 'mag') + # res_loop('Bi2Se3.rho.if', '0bsrsoc000', 1, up = 'x') + # res_loop('Bi2Se3.rho.if', '0bsrsoc0', 1, up = 'x') + + + # from bands import plot_bands + # ban = '/home/aksenov/scientific_projects/cathode/Bi2Se3/Bi2Se3.rho.if.0bsrsoc0/' + # plot_bands('/home/aksenov/scientific_projects/cathode/Bi2Se3/Bi2Se3.rho.dos/1.vasprun.xml', + # vasprun_bands = ban+'1.vasprun.xml', kpoints = ban+'KPOINTS', element = 'Bi', ylim = (-1.5, 2.5)) + + + + + # file = 'VO/CONTCAR_mopac' + # # file = 'VO/Kayunkid10.cif' + # st = smart_structure_read(input_geo_file = file) + + # st = st.return_atoms_to_cell() + # st = st.shift_atoms(vector_red = (0.5,0.5,0.5)) + # st = st.return_atoms_to_cell() + + # st.write_poscar(file+'_conv', vasp5 = True) + + + + # add_loop('Ti2', '0', 1, input_geo_file = 'Ti/hex111.geo', it_folder = 'Ti/hex/', run = 1, corenum = 1) + # add_loop('Ti2', '1hssb', 1, input_geo_file = 'Ti/hex111.geo', it_folder = 'Ti/hex/', run = 1, corenum = 4) + # add_loop('TiFe', '1hssb', 1, input_geo_file = 'TiFe/1.CONTCAR', it_folder = 'TiFe/B1/', run = 1, corenum = 4) + # add_loop('Fe2', '1hssbm', 1, input_geo_file = 'Fe/1.CONTCAR', it_folder = 'Fe/bcc/', run = 1, corenum = 8) + + # res_loop('Ti2', '0', 1) + + + # res_loop('Ti2', '1hssb', 1) + # res_loop('TiFe', '1hssb', 1) + # res_loop('Fe2', '1hssbm', 1) + + + # print(-20.8478--9.1541--9.2957 ) + + + + + + + + + def k10(): + V250 = -2235.4046 + V249v = -2224.0141 + V248Tiv = -2223.2459 + V249Ti = -2233.7968 + + + print(V249Ti+V249v - (V248Tiv + V250 ) ) + + def k15(): + V250 = -2235.5223 + V249v = -2224.1072 + V248Tiv = -2223.2724 + V249Ti = -2234.0743 + print(V249Ti+V249v - (V248Tiv + V250 ) ) + + # k15() + + + + + + + + + + + + + + + return #end of workflow + + + + + + + + + + + + + + + + + + + + + +def redox(run = 0, ramp = 0, readfiles = 0, input_geo_format = 'vasp', + image_name = None, image_format = 'pdf', dpi = 300): + """ + Run, analyze, plot redox potentials + + """ + calc = header.calc + + + + cl_list7 = [ + ['LiVPO4F', '8Utmr3-1', 'VPO4F', '8Utmr3-1', 'LiVPO4F'] , + ['LiVP2O7', '8Utmr3-1', 'VP2O7', '8Utmr3-1', 'LiVP2O7'] , + ['LiTiO2', '8Utmr4-2', 'TiO2', '8Utmr4-2', 'LiTiO2'] , + # ['LiMn2O4', '8Utmr4-9', 'Mn2O4', '8Utmr4-9', 'LiMn2O4'] , + ['NaMnAsO4', '8Utmr3-9', 'MnAsO4', '8Utmr3-9', 'NaMnAsO4'] , + # ['Na2FePO4F', '8Utmr4', 'FePO4F', '8Utmr4', 'Na2FePO4F'] , + # ['KFeSO4F', '8Utmr4', 'FeSO4F', '8Utmr4', 'KFeSO4F'] , + # ['KVPO4F', '8Utmr3-1', 'VPO4F', '8Utmr3-1', 'KVPO4F'] , + ] + + + + + cl_list8 = [] + for ise in '8u', '8ue4', '8ue5', '8uL': + # for ise in '9u', '9uk15', '9uk1': + cl_list8.extend([ + # ['KFeSO4F', ise, 'FeSO4F', ise, 'KFeSO4F'] , + # ['KVPO4F', ise, 'VPO4F', ise, 'KVPO4F'] , + ['LiCoO2', ise, 'CoO2', ise, 'LiCoO2'] , + # ['LiCoPO4', ise, 'CoPO4', ise, 'LiCoPO4'] , + ['LiFePO4', ise, 'FePO4', ise, 'LiFePO4'] , + # ['LiMn2O4', ise, 'Mn2O4', ise, 'LiMn2O4'] , + ['LiMnPO4', ise, 'MnPO4', ise, 'LiMnPO4'] , + ['LiNiO2', ise, 'NiO2', ise, 'LiNiO2'] , + ['LiTiO2', ise, 'TiO2', ise, 'LiTiO2'] , + ['LiTiS2', ise, 'TiS2', ise, 'LiTiS2'] , + ['LiVP2O7', ise, 'VP2O7', ise, 'LiVP2O7'] , + ['LiVPO4F', ise, 'VPO4F', ise, 'LiVPO4F'] , + # ['Na2FePO4F', ise, 'FePO4F', ise, 'Na2FePO4F'] , + ['NaFePO4', ise, 'FePO4', ise, 'NaFePO4'] , + ['NaMnAsO4', ise, 'MnAsO4', ise, 'NaMnAsO4'] , + ] + ) + + # for li in cl_list8: + # print li + # sys.exit() + + + + cl_list0 = [ #Shishkin2016 + ['LiCoPO4', '8Utmr2-8', 'LiCoPO4'] , + ['LiFePO4', '8Utmr2-1', 'LiFePO4'] , + ['FePO4', '8Utmr3-7', 'LiFePO4'] , + ['LiTiS2', '8Utmr3-3', 'LiTiS2'] , + ['TiS2', '8Utmr3-5', 'LiTiS2'] , + ['NiO2', '8Utmr4', 'LiNiO2'] , + ['MnPO4', '8Utmr4', 'LiMnPO4'] , + ['CoO2', '8Utmr3-9', 'LiCoO2'] , + ['LiNiO2', '8Utmr4-6', 'LiNiO2'] , + ['LiMnPO4', '8Utmr2-2', 'LiMnPO4'] , + ['NaFePO4', '8Utmr2-2', 'NaFePO4'] , + ['CoPO4', '8Utmr4-2', 'LiCoPO4'] , + ['LiCoO2', '8Utmr3-6', 'LiCoO2'] , + ['LiTiO2.s10.su','4uisns', 'LiTiO2'], + ['TiO2.id.su','4uis', 'LiTiO2'], + + ['LiMn2O4.s10.su','4uis', 'LiMn2O4'], + ['Mn2O4.id.su.s10','1urs', 'LiMn2O4'], + + ] + + + cl_list1 = [ + # ['LiCoO2', '8Ur3-6', 'LiCoO2'] , + # ['CoO2', '8Ur3-9', 'LiCoO2'] , + # ['LiTiS2', '8Ur3-3', 'LiTiS2'] , + # ['TiS2', '8Ur3-5', 'LiTiS2'] , + ['LiFePO4', '8Ur2-1', 'LiFePO4'] , + ['FePO4', '8Ur3-7', 'LiFePO4'] , + # ['NiO2', '8Ur4', 'LiNiO2'] , + # ['MnPO4', '8Ur4', 'LiMnPO4'] , + # ['LiCoPO4', '8Ur2-8', 'LiCoPO4'] , + # ['LiNiO2', '8Ur4-6', 'LiNiO2'] , + # ['LiMnPO4', '8Ur2-2', 'LiMnPO4'] , + # ['NaFePO4', '8Ur2-2', 'NaFePO4'] , + # ['CoPO4', '8Ur4-2', 'LiCoPO4'] , + ] + + # print cl_list8 + # sys.exit() + + DSs = [] + results = [] + final_list = [] + # for ls in cl_list7+cl_list0, : + # for ls in cl_list8+cl_list0+cl_list7, : + + + # for ls in cl_list8,: + for ls in cl_list0,: + # for ls in cl_list7, : + # print ls + for cl in ls: + # print ('hello',cl) + energy_ref = 0 + if 'Li' in cl[0]: energy_ref = calc['Li111', '8Utmb4', 1].energy_sigma0/2 + if 'Na' in cl[0]: energy_ref = calc['Na111', '8Utmb4', 1].energy_sigma0/2 + + if len(cl) == 3: + if not ramp: + cl[1] = cl[1].replace('r', '') + + if run: + add_loop(cl[0], cl[1], 1, up = 'up1', input_geo_format = 'vasp', it_folder = cl[2]) + + else: + if 'Li' not in cl[0] and 'Na' not in cl[0]: + continue + # print 'hello' + + + for clb in ls: #find deintercalated + # print clb == cl + if clb == cl: + continue + if clb[0].split('.')[0] in cl[0]: + bcl = copy.deepcopy(clb) + # print (clb[0], cl[0]) + + # print energy_ref + + if not ramp: + bcl[1] = bcl[1].replace('r', '') + + v = 1 + if 'TiO2' in cl[0] or 'Mn2O4' in cl[0]: + v = 100 + # print (v, cl[0], bcl[0]) + # else: + # v = 1 + + + res_loop(bcl[0], bcl[1], v, choose_outcar = -1,readfiles = readfiles) + final_list, _ = res_loop(cl[0], cl[1], v, choose_outcar = -1,readfiles = readfiles, analys_type = 'redox_pot', b_id = (bcl[0], bcl[1], v), energy_ref = energy_ref) + # print final_list + + + elif len(cl) == 5: + if not ramp: cl[1] = cl[1].replace('r', ''); cl[3] = cl[3].replace('r', '') + + if run: + add_loop(cl[0], cl[1], 1, up = 'up1', input_geo_format = input_geo_format, it_folder = cl[4]) + id2 = cl[2]+cl[3] + if id2 not in DSs: + add_loop(cl[2], cl[3], 1, up = 'up1', input_geo_format = input_geo_format, it_folder = cl[4]) + DSs.append(id2) + + else: + final_list, _ = res_loop(cl[0], cl[1], 1, readfiles = readfiles, analys_type = 'redox_pot', b_id = (cl[2], cl[3], 1), energy_ref = energy_ref) + + # print 'hello' + # print (final_list) + if not run and final_list: + results.append(final_list) + + if not run: + '' + # print (results) + df = pd.DataFrame(data = results, columns=['is', 'redox_pot', 'kspacing', 'time', 'mdstep', 'ecut', 'niter', 'set_is']) + # print df.set_index(['is', 'mdstep', 'set_is']).sortlevel(0).round(3) + + + + if 1: # compare souces + df = pd.DataFrame(data = results, columns=['is', 'redox_pot', 'id_is', 'id_ds'])[['is', 'redox_pot']] + df['source'] = 'GGA+U_ramp' + df['type'] = 'GGA+U' + df['is'] = [ d.split('.')[0] for d in df['is']] + # print df + dfs = pd.read_csv(r'database/literature.csv')[['is', 'redox_pot', 'source', 'type']] + dfs.drop(0, inplace=True) + dfs.drop(1, inplace=True) + # print (dfs) + # sys.exit() + + df = pd.concat([df, dfs]) + # df = df.set_index(['is', 'redox_pot']).sortlevel(0) + df = df.reset_index(drop=True) + # print (df) + + df['is'] = pd.Series([re.sub("([0-9])", "$_\\1$", s) for s in df['is'] ] ) # #Make low indexes + + + wc2= 'redox_pot' + df = df.apply(lambda x: pd.to_numeric(x, errors='ignore')) + df[[wc2]] = df[[wc2]].apply(lambda x: pd.Series.round(x, 1)) + + + if 1: #compare with other dft + df_piv = df.pivot(index='is', columns='source', values='redox_pot') + # print(df_piv) + df_piv = df_piv.sort_values(['azh']) + df_piv[['GGA+U_ramp', 'azh', 'Shishkin2016' ]].plot(kind = 'bar',rot = 70, ylim = (0,6), + colormap = 'RdYlBu') + else: #compare with experiment + df = df.dropna() + # print (df) + df_piv = df.pivot(index='is', columns='type', values='redox_pot')[['GGA+U', 'exp']] + df_piv = df_piv.sort_values(['exp']) + df_piv.plot(kind = 'bar',rot = 70, ylim = (0,6), + colormap = 'RdYlBu') + + + + + + plt.xlabel('') + plt.ylabel('Intercalation voltage (V)') + + + # plt.legend(loc='best') + plt.legend(loc='best', ncol =3, handlelength = 0.25, + handleheight = 2, frameon=False, fontsize=20) + + if 1: + # mpl.rcParams.update({'font.size': 14}) + # mpl.rcParams.update({'font.size': 18}) + # mpl.rc('legend', fontsize= 10) + + + plt.tight_layout() + + + + + if image_name: + if not os.path.exists(header.path_to_images): + os.makedirs(header.path_to_images) + path2im = header.path_to_images+str(image_name)+'.'+image_format + printlog( "Saving image ...", path2im) + # plt.savefig(path2im, dpi = dpi, format=image_format) + plt.savefig('figs/'+image_name+'.png', dpi = 300) + plt.savefig('figs/'+image_name+'.eps', dpi = 300) + else: + plt.show() + + + + + + +def potential_barriers(): + """ + Creates figures and tables for report + """ + calc = header.calc + readfiles = False + + res_loop('LiFePO4.nebLi1v1',[u'1ulong'], verlist = [1], up = '', show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li ') #mep + + res_loop('LiFePO4.nebLi1v1', '1u', [1], up = '', show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li ' + ) #unexpectedly slightly lower energy for saddle point + + res_loop('LiFePO4.n7Li1v1',[u'1ulong'], verlist = [1], up = 'up1', show ='m', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li ' + ) + + + res_loop('FePO4.pnma2.n3i1e2Lims', '1u', verlist = [1], up = 'up1', show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li without u-ramping ' + ) + res_loop('FePO4.pnma2v1.n3i1e2Lims', '1ur', verlist = [1], up = 'up1', show = 'm',push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li, u-ramping du = 1.3 V' + ) + res_loop('FePO4.pnma2v1.n7i1e2Lims',[u'1ur30'], verlist = [1], show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li, u-ramping du = 0.13 V ' + ) + + + + res_loop('NaFePO4.pnma.n3Na1v1mp',[u'1ulong'], verlist = [1], up = 'up1', show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Na ' + ) + + res_loop('FePO4.pnma2.n3i1e2Na',[u'1u'], verlist = [1], up = 'up1', show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Na ' + ) + + res_loop('KFePO4.pnma.suv100.n3K1v1ms',[u'1u'], verlist = [1],show = '', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for K ') #mep + + + res_loop('LiVPO4F.nebLi1v1','1ur', verlist = [1], up = '', show = '', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li ') #mep + + res_loop('LiMnPO4v1.n3Li1v1ms',[u'1u'], verlist = [1], up = 'up1', show = 'm', push2archive = True, + readfiles = readfiles, + description_for_archive = 'Diffusion path for Li ') + + + mpl.rc('axes', titlesize= 12) + + mpl.rcParams.update({'font.size': 14}) + + res_loop('KFePO4.pnma.su','4uiWF', range(1,8)+[100], up = '1', show = 'fo', analys_type = 'fit_a', + push2archive = True, + readfiles = readfiles, + description_for_archive = 'Cell shape relaxation and search of minimum') #mep + + + +def find_matched_calculations(it): + """ + Look for it in struct_des and find similar calcs. + Useful to find corresponding intercalated structure + """ + for key in header.struct_des: + if it in key: + print (key) + sys.exit() + + + + +def calc_barriers(mode = '', del_ion = '', new_ion = '', func = 'gga+u', show_fit = False, up = None, upA = None, upB = None, upC = None, + param_dic = None, run_sc = 1, run_neb = 1, up_add_loop = 'up2', + up_res = 'up1', add_loop_dic = None, fitplot_args = None, + nise = 1, + choose_outcar_global = None, + cathodes = None, style_dic = None, readfiles = 1 ): + """ + Simplifies calculation of intercalation voltages + and barriers by performing step by step calculations - + remove cations or replace cations, + create supercell, optimize supercell, calculate migration barriers + + mode (str) - + - 'normal' + param_dic['start_pos'] (int) - number of starting non-eqiv position + param_dic['end_pos'] (int) - number of final non-eqiv position + + - 'replace' - creates additional structures by replacing cations + + - *new_ion* (str) - choose new ion + + - 'make_ds' - creates deintercalated structures by removing all cations and then inserting in analogy to + + - *del_ion* - ions to be deleted either by replacement or removing, use 'Li Na' if both should be removed + + param_dic['neb_search_voids'] - if exists then in 'make_ds' mode new voids are searched as final positions + + - func - functional either gga or gga+u, if gga is used the energies are taken for u=0, however + take in mind that optimization was made for 'gga+u' + + nise - if 1 than neb_ise is use, if 0 than main_ise is used. Variable is useful for two-step barrier determination with the second step with fixed occ + + param_dic - dictionary with parameters + 'id' - starting id + 'ds' - name of ds structure + 'itfolder' - folder for calculation + 'main_set' - set used for supercells and neb + 'neb_set' - set for neb used instead of main_set + 'readfiles' - to res_loop + -del_pos - specific non-eqv position of del_ion to be removed starting from 0 + + - meps - list of tuples (start_pos, end_pos) + - meps2 - list of tuples (i_atom_to_move, end_pos) + - ortho - global target sizes of supercell + - ortho.mode_id - specific target sizes of supercell + - old_behaviour (bool) - if True then first optimization of cell is not done for 'normal', second optimization for all modes; + if False - only first optimization for all cells + 'old.'+mode_id + ! war + + run_sc - run supercell construction part + run_neb - run neb construction part + + style_dic - passed to plot_mep() + + choose_outcar_global - allows to override param_dic values, choose outcar to read from sequence set or u-ramp loop + + cathodes - list of lists - another way to configure the calculation - was initially used + + update + + + + + TODO + curver - is 1!!! check if it works correctly for other cases + + + return + + + """ + if not param_dic: + param_dic = {} + + if not add_loop_dic: + add_loop_dic = {} + + + calc = header.calc + struct_des = header.struct_des + varset = header.varset + + + def calc_added(cl, attr, state): + """ + Check whether *cl* has attribute *attr* (tuple) and attr[3] is equal to *state* + """ + added = False + hasat = False + if hasattr(cl, attr): + hasat = True + + if getattr(cl, attr)[3] == state: + added = True + + return added and hasat + + def calc_added2(cl, attr, state): + """ + Check whether *cl* has attribute *attr* (tuple) and attr[3] is equal to *state* + """ + # print(attr, state) + # print(cl.neb_id) + # sys.exit() + added = False + hasat = False + if hasattr(cl, attr): + hasat = True + + if state in getattr(cl, attr): + added = True + else: + setattr(cl, attr, {}) + return added and hasat + + + + def make_dummy_calc_obj(calc_id): + """ + if id not in calc saves dummy Calculation() to calc database + """ + if calc_id: + if calc_id in calc: + cl = calc[calc_id] + else: + cl = Calculation() #just empty calc to store state iformation + calc[calc_id] = cl + return cl + + + def cat_name_mod(init_name): + #'cathode_name' + if 'replace' in mode: + name = init_name.replace(del_ion, new_ion) + elif 'make_ds' in mode: + name = init_name.replace(del_ion, '') + elif 'normal' in mode: + name = init_name + return name + + + def replace_cations(ion_to_replace = None, replace_by =None, datalist = None, ver = None): + """Step P: Create cells with Na and K from Li cells and optimize them first for small cells""" + cat = datalist + LiX = cat[0] + curise = cat[1] + curver = ver + + curit = LiX.replace(ion_to_replace, replace_by) + curfol = cat[4].replace(ion_to_replace, replace_by) + + itP = curit+'.ir' #inherit by replacement + + if ion_to_replace in LiX and ion_to_replace != replace_by: + + if itP not in struct_des: + inherit_icalc('replace_atoms', itP, curver, + (LiX, curise, curver), calc, atom_new = replace_by, atom_to_replace = ion_to_replace, it_folder = curfol, use_init = 1) + else: + printlog('Error!', ion_to_replace, 'was not found in name', LiX, '; Use correct names') + itP = None + return itP + + + def remove_cations(ions = None, cat = None, ver = None, update = None): + """Step S: remove cations and create DS structures from IS + ions (list) + """ + idA0 = (cat[0], cat[1], ver) + dic = cat[7] + + + if 'del_pos' in dic: + itS = cat[2]+'.id'+str(dic['del_pos']) #inherit delete + del_pos = dic['del_pos'] + else: + itS = cat[2]+'.id' + del_pos = None + + ions_present = False + for ion in ions: # all ions should be in name + if ion in cat[0]: + ions_present = True + else: + ions_present = False + # print(ions_present) + + if ions_present: + # print(update) + + if update or itS not in struct_des: + # print(update) + inherit_icalc('remove_atoms', itS, ver, idA0, calc, + atoms_to_remove = ions, del_pos = del_pos, it_folder = cat[4], use_init = 1) + + return itS + + + + def optimize_cell(id_base = None, datalist = None, scale_region = None, update = None, irun = ''): + """ + Create and read results + irun (str) - number of run + """ + dic = cat[7] + # print(id_base) + # sys.exit() + + if id_base and id_base[0]: + + if 'scaling_set' in dic: + ise_new = dic['scaling_set'] + else: + try: + ise_new = dic['scaling_set'+irun+'.'+mode_id] # + except: + ise_new = dic['scaling_set.'+mode_id] # + + if 'save' in dic: + savefile = dic['save'] + else: + savefile = 'o' + + if dic['scale_region.'+mode_id]: + printlog('optimize_cell(): scale_region changed from', scale_region, 'to', dic['scale_region.'+mode_id], imp ='y') + + scale_region = dic['scale_region.'+mode_id] + + + curfol = struct_des[id_base[0]].sfolder + + id_res = (id_base[0]+'.su', ise_new, 100) + + + if update or id_res not in calc: + printlog('Scale region is ', scale_region, imp = 'y') + add_loop(*id_base, up = up_add_loop, ise_new = ise_new, savefile = savefile, calc_method = 'uniform_scale', scale_region = scale_region, + inherit_option = 'inherit_xred', it_folder = curfol+'/scaled/', **add_loop_dic) + + else: + # print(dic['scale_outcar.'+mode_id], up_res) + # print(up_res) + # sys.exit() + res_loop(*id_res, up = up_res, readfiles= readfiles, choose_outcar = dic['scale_outcar.'+mode_id], show = 'e', check_job = 0) + if show_fit: + res_loop(*id_res[0:2],list(range(0+1,0+8))+[100], up = up_res, readfiles= readfiles, choose_outcar = dic['scale_outcar.'+mode_id], analys_type = 'fit_a', show = 'fitfo', check_job = 0) + # sys.exit() + if '2' in calc[id_res].state or '5' in calc[id_res].state: + '' + # del calc[id_res] + + elif '4' in calc[id_res].state: + # print(np.real(calc[id_res].B)) + try: + curres.update({'B':float(calc[id_res].B)}) + except: + printlog('No Bulk modulus') + + + curres['vol'] = calc[id_res].end.vol + + curres['id'] = id_res + + if '2' in irun: + '' + if add_to_database: + add_to_database(calc[id_res]) + + + + return id_res + + + + + def make_supercell(base_id, cat, update): + """Step A: Create supercells and calculate their total energy""" + dic = cat[7] + pd = dic + ise_new = cat[6] + + if 'ortho' in pd: + ortho = pd['ortho'] + printlog('ortho found in pd:', ortho) + + elif 'ortho.'+mode_id in pd: + ortho = pd['ortho.'+mode_id] + printlog('ortho mode_id found in pd:', ortho) + else: + ortho = [10,10,10] + printlog('Default ortho is used:', ortho) + nonlocal support_dict_key + + support_dict_key = 'support_'+name_mod_supercell(ortho) + + + sc_unique_id = (name_mod_supercell(ortho), ise_new) + + + if support_dict_key not in calc: + calc[support_dict_key] = {} #create supportive dictionary, which depends on ortho parameter + + + + + if base_id: + # print(base_id) + clA0 = db[base_id] + + mul_matrix = None + ngkpt = None + + + + + # print(clA0.inh_id, sc_unique_id) + # sys.exit() + # if update or not calc_added(clA0, 'inh_id', 1): + if update or not calc_added2(clA0, 'inh_id', sc_unique_id): + + + if 'make_ds' in mode: #for DS structures use the same parameters as for IS structures + if 1: + printlog ('Cell obtained by removing atoms', imp = 'y') + printlog ('I use mul_matrix and ngkpt from intercalated structure', imp = 'y') + try: + mul_matrix = calc[support_dict_key][cat[0], 'mul_matrix'] + ngkpt_dict = calc[support_dict_key][cat[0], 'ngkpt_dict'] + + except KeyError: + printlog('Error! You are in IS->DS inheritance mode, please first make IS calculation to fill in supportive dictionary with mul_matrix and ngkpt') + ks = varset[ise_new].kspacing + ngkpt = ngkpt_dict[ks] + # printlog ('I use mul_matrix and ngkpt from intercalated structure', imp = 'y') + + + sfolder = struct_des[base_id[0]].sfolder + # print (sfolder) + # sys.exit() + itA = add_loop(*base_id, ise_new = ise_new, up = up_add_loop, + it_folder = sfolder+'/super/', inherit_option = 'supercell', ortho = ortho, + mul_matrix = mul_matrix, ngkpt = ngkpt , **add_loop_dic) + + # print([itA, ise_new, base_id[2], support_dict_key, 'exist']) + # clA0.inh_id = [itA, ise_new, base_id[2], support_dict_key, 'exist'] + if not hasattr(clA0, 'inh_id') or type(clA0.inh_id) == list:# temporary for compat + clA0.inh_id = {} + + clA0.inh_id[sc_unique_id] = (itA, ise_new, base_id[2]) # additional unique id and state, TODO: maybe move to add_neb + + # print(clA0.inh_id) + # print(db[('Cu.su', '1lo', 100)].inh_id) + # header.db = db + if 'normal' in mode: + calc[support_dict_key][cat[0], 'mul_matrix'] = struct_des[itA].mul_matrix #save for intercalated structure + calc[support_dict_key][cat[0], 'ngkpt_dict'] = struct_des[itA].ngkpt_dict_for_kspacings #save for intercalated structure + + + + else: + idA = clA0.inh_id[sc_unique_id] + + if func == 'gga': + choose_outcar = 1 + else: #gga+u with additional control + choose_outcar = dic['neb_outcar.'+mode_id] + # print(dic['neb_outcar.'+mode_id]) + # print('suprecell: chosen outcar:', choose_outcar) + # print(up_res) + res_loop(*idA, up = up_res, readfiles = readfiles, choose_outcar = choose_outcar, show = 'm', check_job = 0) + # res_loop(*idA, choose_outcar = 3, show = 'fo') + # res_loop(*idA, choose_outcar = 4, show = 'fo') + if '4' in calc[idA].state: + + + + return idA + + + def make_neb(base_id, atom_to_insert, cat, update): + """Step C: make neb + base_id - calc id - where to study migration + cat - special list of parameters, at cat[7] contains dict with paramerters + dict + 'start_pos' - i_void_start + 'end_pos' - i_void_final + 'meps' - list of tuples ('start_pos', 'end_pos') + + TODO: + 1. Transform cat to pure dicts? + 2. Make names consistent, like 'start_pos' and i_void_start is the same! + + """ + pd = cat[7]#param_dic + + # print(atom_to_insert) + # sys.exit() + + + if 'neb_set' in pd and pd['neb_set']: + ise_new = pd['neb_set'] + else: + ise_new = cat[6] + + if base_id: + idB = base_id + clB = calc[idB] + # print(pd) + default = {'i_atom_to_move':'', 'start_pos':1, 'end_pos':1} + for key in default: + if key not in pd: + pd[key] = default[key] + + + printlog('Start:', pd['start_pos'], '; End:', pd['end_pos']) + + sup_key = (cat[0], pd['start_pos'], pd['end_pos'], pd['i_atom_to_move']) # support key - should be unique for current path, used to transfer xr from IS to DS + + # if 'replace' in mode: + # sup_key = (cat[0], pd['start_pos'], pd['end_pos'], pd['i_atom_to_move']) + + + neb_unique_id = (pd['start_pos'], pd['end_pos'], pd['i_atom_to_move'], atom_to_insert, ise_new) + if 'rep_moving_atom' in pd: + # sys.exit() + neb_unique_id = (pd['start_pos'], pd['end_pos'], pd['i_atom_to_move'], atom_to_insert, ise_new, pd['rep_moving_atom']) + + + + printlog('neb_unique_id = ', neb_unique_id) + + if 'images' in pd: + images = pd['images'] + else: + images = 3 + printlog('Number of images set to', images) + + ok = 'occmatrix_id' # general + + if ok not in pd: + ok = 'occmatrix_id.'+mode_id + + + + + + if ok in pd: + cl = db[pd[ok]] + occfile = write_occmatrix(cl.occ_matrices, cl.dir) + + add_loop_dic['params'] = {'occmatrix':occfile} + + + # up_res = 'up1' + + # sys.exit() + if update or not calc_added2(clB, 'neb_id', neb_unique_id): + + other_param = {} + if 'r_impurity' in pd: + other_param['r_impurity'] = pd['r_impurity'] + + if 'i_atom_to_move' in pd: + other_param['i_atom_to_move'] = pd['i_atom_to_move'] + + if 'atom_to_move' in pd: + other_param['atom_to_move'] = pd['atom_to_move'] + # print(other_param['atom_to_move']) + if 'end_pos_types_z' in pd: + other_param['end_pos_types_z'] = pd['end_pos_types_z'] + + if 'rep_moving_atom' in pd: + other_param['rep_moving_atom'] = pd['rep_moving_atom'] + + + + # print('sdfsaf') + + if 'normal' in mode or 'replace' in mode: + + if 'neb_search_voids' in pd and pd['neb_search_voids'] == 1: + search_type = 'existing_voids' + else: + search_type = 'vacancy_creation' + + # print('make_neb:', add_loop_dic) + it = add_neb(clB, up = up_add_loop, ise_new = ise_new, images = images, + i_void_start = pd['start_pos'], i_void_final = pd['end_pos'], + atom_to_insert = atom_to_insert, + search_type = search_type, add_loop_dic = add_loop_dic, old_behaviour = old_behaviour, **other_param) + + elif 'make_ds' in mode: + + # printlog('made_ds mode') + if 'neb_search_voids' in pd and pd['neb_search_voids'] == 1: + it = add_neb(clB, up = up_add_loop, ise_new = ise_new, images = images, + i_void_start = pd['start_pos'], i_void_final = pd['end_pos'], + atom_to_insert = atom_to_insert, search_type = 'existing_voids', + add_loop_dic = add_loop_dic, old_behaviour = old_behaviour, **other_param) + else: + # use the same positions as was used in normal + xr_start = calc[support_dict_key][sup_key, 'xr_m_ion_start'] + xr_final = calc[support_dict_key][sup_key, 'xr_m_ion_final'] + printlog('Using start and final positions from', support_dict_key, sup_key, xr_start, xr_final, imp = 'Y') + # sys.exit() + it = add_neb(clB, up = up_add_loop, ise_new = ise_new, images = images, + xr_start = xr_start, + xr_final = xr_final, + i_void_start = pd['start_pos'], i_void_final = pd['end_pos'], #just for name + atom_to_insert = atom_to_insert, add_loop_dic = add_loop_dic, + old_behaviour = old_behaviour) + + id_n = (it, ise_new, 1) + + if 'map' not in calc: # attempt to create map of calculations of graph of calculations, not working yet + calc['map'] = {} + mp = calc['map'] + else: + mp = calc['map'] + # print(mp) + # sys.exit() + if idB not in mp: + mp[idB] = [] + + try: + id_nold = clB.neb_id[0:3] + + if id_nold not in mp[idB]: + mp[idB].append(id_nold) + except: + pass + + + if id_n not in mp[idB]: + mp[idB].append(id_n) + + + if not hasattr(clB, 'neb_id') or type(clB.neb_id) == list:# temporary for compat + clB.neb_id = {} + # print(neb_unique_id) + clB.neb_id[neb_unique_id] = (it, ise_new, 1) # additional unique id and state, TODO: maybe move to add_neb + # print(clB.id, clB.neb_id) + + if 'normal' in mode: + calc[support_dict_key][sup_key, 'xr_m_ion_start'] = struct_des[it].xr_m_ion_start # xred coordinate of migrating ion in starting position + calc[support_dict_key][sup_key, 'xr_m_ion_final'] = struct_des[it].xr_m_ion_final # xred coordinate of migrating ion in final position + # print (struct_des[it].x_m_ion_start, struct_des[it].x_m_ion_final) + # sys.exit() + + + + + else: + idC = clB.neb_id[neb_unique_id] + + + + # res_loop(*idC[0:2],[1,2], show = 'me', readfiles = 1, choose_outcar = 3) + # res_loop(*idC[0:2],[4], up = 'up1',show = 'mag', readfiles = 1, choose_outcar = 3, analys_type = 'ne') + # res_loop(*idC[0:2],[4], up = 'up1',show = 'mag', readfiles = 1, choose_outcar = None, analys_type = 'ne') + # print (dic) + # print (dic['neb_outcar.'+mode_id]) + if choose_outcar_global: + choose_outcar = choose_outcar_global + + elif func == 'gga': + choose_outcar = 1 + else: #gga+u with additional control + okey = 'neb_outcar.'+mode_id + printlog('choosing outcar from dic ', okey) + choose_outcar = dic[okey] + printlog('chosen outcar = ', choose_outcar) + + + if neb_fit: + '' + printlog('up key of res_loop = ', up_res) + # printlog('choose_outcar = ', choose_outcar) + + # sys.exit() + + res, _ = res_loop(idC[0],ise_new,range(1, images+3), up = up_res, show = 'fomep', readfiles = readfiles, + choose_outcar = choose_outcar, + analys_type = 'neb', fitplot_args = fitplot_args, + check_job = add_loop_dic['check_job'], style_dic = style_dic, params = pd) + else: + res_loop(*idC[0],ise_new, [1,2], show = 'me', up = up_res, readfiles = readfiles, choose_outcar = choose_outcar, check_job = add_loop_dic['check_job']) + + + + # print (res) + + # if '5' in calc[idC].state: #some error + # clB.neb_id[3] = None + + if '4' in calc[idC].state: + # try: + # curres['dAO_change'] = res['dAO_change'] + curres['sts'] = res['sts'] + # except: + # pass + + + try: + curres.update({'barrier':calc[idC].barrier}) + + except: + curres.update({'barrier':0}) + + curres['dEm1'] = res['dEm1'] #difference of energies between middle and first image of NEB + + # print(curres['barrier'], curres['dEm1']) + + + + curres['id_start'] = (idC[0], idC[1],1) + curres['id_end'] = (idC[0], idC[1],2) + + # dn = calc[idC].end.natom - calc[idB].end.natom + # v_int1 = calc[idC[0], idC[1],1].energy_sigma0 - calc[idB].energy_sigma0 - dn * curres['Eref'] + # v_int2 = calc[idC[0], idC[1],2].energy_sigma0 - calc[idB].energy_sigma0 - dn * curres['Eref'] + printlog('Calculating atom-wise intercalation potentials', imp = 'Y', end = '\n') + v_int1 = calc_redox(calc[idC[0], idC[1],1], calc[idB])['redox_pot'] + v_int2 = calc_redox(calc[idC[0], idC[1],2], calc[idB])['redox_pot'] + + + # print('Redox pot:', dn, v_int1, v_int2, curres['Eref']) + + + curres.update({'V2':v_int1}) # the batterry is fully discharged + return + + + + + if 1: # prepare parameters + main_set = '1urs' + results = [] # result list, for each structure we have dict + scale_regions = {} + + neb_fit = 1 # if to make neb fitting; the barries is saved to cl1.barrier + run_scale = 1 + add_to_database = 0 + + curver = 1 + local_state = None + + support_dict_key = '' + + pd = param_dic + + + + + + if 'check_job' not in add_loop_dic: + add_loop_dic['check_job'] = 1 + + + # print(pd) + if 'scaling_set' in pd: + scaling_set = pd['scaling_set'] + # print(scaling_set) + else: + scaling_set = '4uis' + # print(scaling_set) + # sys.exit() + + mode_id = mode+'.'+del_ion+'.'+new_ion + dic = { + 'neb_outcar.' + mode_id:None, #by default the last one is used + 'scale_outcar.' + mode_id:None, #by default the last one is used + 'scaling_set.'+ mode_id:scaling_set, # + 'skip.'+mode_id:False, + 'scale_region.'+mode_id:None, + }# additional specific control + # 'neb_outcar' - (int) - choose_outcar in res_loop of make_neb + + if 'scale_region' in pd: + dic['scale_region.'+mode_id] = pd['scale_region'] + + scale_regions['optimal'] = (-4,4) + scale_regions['Li'] = (-5,3) + scale_regions['Na'] = (-1,7) + scale_regions['K'] = (4,16) + scale_regions['Rb'] = (-4,4) + scale_regions['Li_removal'] = (-5,3) + scale_regions['Na_removal'] = (-5,3) + scale_regions['K_removal'] = (-8,0) + scale_regions['Rb_removal'] = (-6,2) + + scale_regions[new_ion] = (-4,4) + + # print(new_ion) + # sys.exit() + + + if up: + update = up # initial update for removing and replacing atoms + else: + update = 0 + + if upA: + updateA = upA + else: + updateA = 0 # make supecell + + if upB: + updateB = upB + else: + updateB = 0 # volume optimization, su + + if upC: + updateC = upC + else: + updateC = 0 # NEB + + if not up_res: + up_res = 'up1' # update files + + if 'readfiles' in pd: + readfiles = pd['readfiles'] + else: + readfiles = readfiles + + if not show_fit: + show_fit = 0 #control if to show fitting of supercell sizes + + + ise = '8u' # old + if pd: + if 'ds' not in pd: + pd['ds'] = 'None' + cathodes = [ [pd['id'][0], pd['id'][1], pd['ds'], '', pd['itfolder'], '', pd['main_set'], md(dic, pd) ], ] + curver = pd['id'][2] + + else: + if nise: + neb_set = nise #'1uos' + else: + neb_set = None + + if cathodes: + for c in cathodes: + c[-1] = md(dic, c[-1]) + else: + # cathodes == None: + + cathodes = [ #cat[3] and cat[5] eventually was not used + # ['LiCoO2', ise, 'CoO2', ise, 'LiCoO2' ,'', main_set, merge_dics(dic,{'scaling_set.make_ds.Li.Li':'4uris', } ) ], old + # ['LiCoO2', ise, 'CoO2', ise, 'LiCoO2' ,'', '1u', merge_dics(dic,{'scaling_set.normal.Li.Li':'1u', } ) ], + # ['LiCoO2', ise, 'CoO2', ise, 'LiCoO2' ,'', '1uafm', merge_dics(dic,{ }) ], + # ['LiTiO2', ise, 'TiO2', ise, 'LiTiO2', '', main_set, merge_dics(dic,{'scaling_set.normal.Li.Li':'4uisns', 'scaling_set.replace.Li.Na':'4uisns', 'scaling_set2.make_ds.Li.Li':'4uisns'}) ], # only for IS Li Na + # ['LiNiO2', ise, 'NiO2', ise, 'LiNiO2' ,'', main_set, merge_dics(dic,{'scale_outcar.make_ds.Li.Li':None, 'neb_outcar.replace.Li.Na':3,'neb_outcar.replace.Li.K':3, 'scaling_set.normal.Li.Li':'4uisns', 'scaling_set2.make_ds.Li.Li':'4uris', 'scaling_set1.make_ds.Li.Li':'4uisC0W1', 'save':'oc'}) ] , # for Li use larger symprec, or isym = 0 + # ['LiTiS2', ise, 'TiS2', ise, 'LiTiS2' ,'', main_set, md(dic, {'neb_outcar.make_ds.Li.Li':None}) ] , + # ['LiMn2O4', '', 'Mn2O4', '', 'LiMn2O4' , '', main_set, md(dic, {'neb_outcar.normal.Li.Li':3} ) ] , + # ['LiVP2O7', ise, 'VP2O7', ise, 'LiVP2O7' ,'', main_set, md(dic, {'neb_outcar.normal.Li.Li':None, 'scale_region.replace.Li.K':(0,8) } ) ] , + + # ['Li2CoPO4F.pnma', '1u', 'CoPO4F', '', 'Li2CoPO4F/pnma' , '', main_set, md(dic, {} ) ], + # ['NaMnAsO4', ise, 'MnAsO4', ise, 'NaMnAsO4' ,'', main_set, md(dic, {'neb_outcar.normal.Li.Li':None} ) ] , + # ['Na2FeVF7', '', 'FeVF7', '', 'Na2FeVF7' , '', main_set, dic ] , + # ['KFeSO4F', '', 'FeSO4F', '', 'KFeSO4F' , '', '1urS', md(dic,{'scaling_set.normal.Li.Li':'4uSi', 'scale_outcar.normal.Li.Li':1, 'scaling_set.make_ds.K.K':'4uSi' }) ] , + # ['NaLiCoPO4F' ,'', 'CoPO4F','','NaLiCoPO4F' , '', main_set, md(dic,{'scaling_set.make_ds.Li Na.Li':'4uris', }) ] , + + # ['LiNiO2.r3m', '1u', 'NiO2.r3m', '', 'LiNiO2/r3m' , '', '1urAl', md(dic,{'neb_outcar.normal.Li.Li':1, 'scaling_set.normal.Li.Li':'4uisC0W1', 'scaling_set.make_ds.Li.Li':'4uiAl', }) ] , # for IS main_set is '1urns' + + + # for paper exchange, from 06.09.2017 moved to file paper7 + # ['LiMn2O4.Fd3m.111', '1u', 'Mn2O4.Fd3m.111', '', 'LiMn2O4/Fd3m' , '', main_set, md(dic,{'neb_set':neb_set, 'old.normal.Li.Li':1, 'neb_outcar.normal.Li.Li':None,'neb_outcar.replace.Li.Na':3, 'occmatrix_id.replace.Li.Na':'NaMn2O4.Fd3m.111.ir.su.s10v100.n3Na1v1ms.1urs.4'}) ] , + # ['LiFePO4', ise, 'FePO4', ise, 'LiFePO4' ,'', main_set, md(dic,{'neb_set':neb_set, 'neb_outcar.normal.Li.Li':3, 'neb_outcar.replace.Li.K':3, 'old.normal.Li.Li':1,'old.make_ds.Li.Li':0, 'occmatrix_id.normal.Li.Li':'LiFePO4.s10.suv100.n3Li1v1ms.1urs.3', 'occmatrix_id.make_ds.Li.Li':'FePO4.id.su.s10v100.n3Li1v1ms.1urs.4' }) ] , + # ['LiMnPO4', ise, 'MnPO4', ise, 'LiMnPO4' ,'', main_set, md(dic, {'neb_outcar.make_ds.Li.Li':None, 'old.normal.Li.Li':1, 'old.make_ds.Li.Li':1}) ] , + # ['LiVPO4F', ise, 'VPO4F', ise, 'LiVPO4F' ,'', main_set, md(dic,{'ortho.replace.Li.Na':[10,10,13],'ortho.replace.Li.K':[10,10,13], 'old.normal.Li.Li':1, 'scale_outcar.replace.Li.Na':None, 'neb_outcar.normal.Li.Li':None, 'neb_outcar.make_ds.Li.Li':None,'scaling_set.normal.Li.Li':'4uris', 'scaling_set.replace.Li.K':'4uisC0W1', 'scaling_set.replace.Li.Na':'4uris', 'scale_region.replace.Li.K':(-1,7), 'skip.replace.Li.K':0, 'skip.replace.Li.Na':0}) ] ,# only for IS + # ['KVPO4F.Pna21', '1u', 'VPO4F.Pna21', '', 'KVPO4F/Pna21', '', '1urs', md(dic,{'neb_outcar.normal.Li.Li':None, 'old.normal.K.K':1, 'old.normal..':1, 'images':3}) ], + # ['Li2FePO4F.pnma', '1u', 'LiFePO4F.pnma', '', 'Li2FePO4F/pnma' , '', '1u', md(dic, {'ortho.replace.Li.Na':[13,13,13],'ortho.replace.Li.K':[13,13,13],'meps':[(1,1), (2,1), (1,3), (2,3), (3,2), (3,3)], 'del_pos':1} ) ], #(1,1), + # ['Li2FePO4F.pnma', '1u', 'LiFePO4F.pnma', '', 'Li2FePO4F/pnma' , '', '1u', md(dic, {'neb_set':'1urs', 'ortho.replace.Li.Na':[13,13,13],'ortho.replace.Li.K':[13,13,13],'meps':[(3,2), (3,5)], 'del_pos':1} ) ], #(1,1), + # ['Na2FePO4F', '', 'NaFePO4F', '', 'Na2FePO4F' , '', '1u', md(dic, {'neb_set':nise, 'meps':[(1,1), (1,2), (1,3), (2,1), (2,2), (2,3)], 'scaling_set':'4uis', 'del_pos':2}) ] , #neb_set: 1urs, 1u + # ['Na2FePO4F', '', 'NaFePO4F', '', 'Na2FePO4F' , '', '1u', md(dic, {'neb_set':nise, 'meps':[(2,2), ], 'scaling_set':'4uis', 'del_pos':2}) ] , #neb_set: 1urs, 1u, DS + + # for checks + # ['Li2FePO4F.pnma', '1u', 'LiFePO4F.pnma', '', 'Li2FePO4F/pnma' , '', '1u', md(dic, {'ortho.replace.Li.Na':[13,13,13],'ortho.replace.Li.K':[13,13,13],'meps':[(1,3)], 'del_pos':1} ) ], #(1,1), + + + + + # other try + # ['LiFePO4', ise, 'FePO4', ise, 'LiFePO4' ,'', '1urs10', merge_dics(dic,{'neb_outcar.normal.Li.Li':None, 'neb_outcar.replace.Li.K':4}) ] , + # ['LiFePO4', ise, 'FePO4', ise, 'LiFePO4' ,'', '1m', merge_dics(dic,{'scaling_set.normal.Li.Li':'4mi'}) ] , + # ['NaFePO4', ise, 'FePO4', ise, 'NaFePO4' ,scaling_set, main_set ] , # maricite structure, barrier is high + + # ['LiNiO2.r3m', '1u', 'NiO2.r3m', '', 'LiNiO2/r3m' , '', '1urns', md(dic,{'neb_outcar.normal.Li.Li':3, 'scaling_set.normal.Li.Li':'4uisC0W1', 'scaling_set.make_ds.Li.Li':'4uiAl', }) ] , # for IS main_set is '1urns' + # ['LiMn2O4.Fd3m', '1u', 'Mn2O4.Fd3m', '', 'LiMn2O4/Fd3m' , '', '1ur10', md(dic,{'neb_outcar.normal.Li.Li':None, 'scaling_set.'+mode_id:'1ur10',}) ] , + # ['LiMn2O4.Fd3m', '1u', 'Mn2O4.Fd3m', '', 'LiMn2O4/Fd3m' , '', '1ur10', md(dic,{'neb_outcar.normal.Li.Li':None, 'scaling_set.'+mode_id:'4uis',}) ] , + # ['LiVPO4F', ise, 'VPO4F', ise, 'LiVPO4F' ,'', main_set, md(dic,{'neb_outcar.normal.Li.Li':None, 'scaling_set.normal.Li.Li':'4uris', 'scaling_set.replace.Li.K':'4uris', 'scale_region.replace.Li.K':(-5,3), 'skip.replace.Li.K':0, 'skip.replace.Li.Na':1}) ] ,# old + + ] + + + for cat in cathodes: + curres = {} #current result dict + dic = cat[7] # dictionary with parameters + + + + name = cat_name_mod(cat[0]) + curres['name'] = name + curres['DS'] = cat[2] + curres['proto']= 'X'+cat[2] + curres['ion'] = name.replace(cat[2], '') + if not curres['ion']: + # print('no') + curres['ion'] = new_ion + + if 'make_ds' in mode: + curres['x'] = '0%' + else: + curres['x'] = '100%' + + + curres['vol'] = 0.001 + curres['id'] = ('','',1) + + + if 'old.'+mode_id in dic: + old_behaviour = dic['old.'+mode_id] + elif 'old_behaviour' in dic: + old_behaviour = dic['old_behaviour'] + else: + old_behaviour = 0 + # print ('old_behaviour', old_behaviour) + + if not dic['skip.'+ mode_id]: + # continue + + if 'replace' in mode: + + itP0 = replace_cations(del_ion, new_ion, cat, curver) + + idA0 = optimize_cell( (itP0, dic['scaling_set.'+mode_id], curver), cat, scale_regions[new_ion], update, irun = '1') + + elif 'make_ds' in mode: + + itP0 = remove_cations(del_ion.split(), cat, curver, update) + + idA0 = optimize_cell( (itP0, dic['scaling_set.'+mode_id], curver), cat, scale_regions[del_ion.split()[-1]+'_removal'], update, irun = '1') + + elif 'normal' in mode: #nothing done, use structures from provided list + + if old_behaviour: + idA0 = (cat[0], cat[1], curver) + else: + #9.04.2017# idA0 = optimize_cell( (cat[0], cat[7]['scaling_set.'+mode_id], curver), cat, scale_regions['optimal'], update, irun = '1') + idA0 = optimize_cell( (cat[0], cat[1], curver), cat, scale_regions['optimal'], update, irun = '1') + + + + if run_sc and idA0:# and name != 'NiO2': + + make_dummy_calc_obj(idA0) + + + idA = make_supercell(idA0, cat, updateA) + + # continue + if run_scale: + if old_behaviour: + idB = optimize_cell(idA, cat, scale_regions['optimal'], updateB, irun = '2') + else: + idB = idA + + + if run_neb and idB: + + + if 'meps' in dic: # start_pos, end_pos + for mep in dic['meps']: + printlog('MEP ', mep, ':') + dic['start_pos'] = mep[0] + dic['end_pos'] = mep[1] + make_neb(idB, new_ion, cat, updateC) + elif 'meps2' in dic: # (i_atom_to_move, end_pos) + for mep in dic['meps2']: + + dic['i_atom_to_move'] = mep[0] + dic['end_pos'] = mep[1] + make_neb(idB, new_ion, cat, updateC) + + else: + make_neb(idB, new_ion, cat, updateC) + + + results.append(curres) + + + return results + + + + + + + +def calc_antisite_defects(dpi = 300, image_format = 'eps', update = 0): + struct_des = header.struct_des + calc = header.calc + readfiles = 1 + # update = 0 + main_set = '1urs' + # ise_new = '1ur30' + gga = 'gga' + + if gga == 'gga+u': + choose_outcar = 0 + elif gga == 'gga': + choose_outcar = 1 + + + cathodes = [ + + + # {'id':('LiFePO4.s10.su','4uis',100), 'cluster':'cee', 'main_set':'1ur30'}, + # {'id':('NaFePO4.ir.su.s10.su','4uis',100), 'cluster':'skol'}, + # {'id':('LiMnPO4.s10.su','4uis',100), 'cluster':'skol'}, + # {'id':('LiVPO4F.s10.su','4uis',100), 'cluster':'skol','main_set':'1ur30'}, + # {'id':('LiVP2O7.s10.su','4uis',100), 'cluster':'skol'}, + # {'id':('NaMnAsO4.s10.su','4uis', 100) , 'cluster':'cee' }, + # {'id':('LiTiS2.s10.su','4uis', 100) , 'cluster':'cee' }, + + + + # {'id':('Li2FePO4F.ir.su.s10.su','4uis',100), 'main_set':'1u', 'cluster':'cee'}, #14 meV!!! + # {'id':('Li2FePO4F.ir.su.s10.su','4uis',100), 'main_set':'1uAlf', 'cluster':'cee'}, #50 meV!! + + # {'id':('LiFePO4.s10.su','4uis',100), 'cluster':'cee', 'main_set':'1urZhang'}, + + # {'id':('LiFePO4.s10.su','4mi',100), 'cluster':'cee', 'main_set':'1m'}, + # {'id':('LiFePO4.s10.su','4mi',100), 'cluster':'cee', 'main_set':'1msv'}, + # {'id':('LiFePO4.s10.su','4mi',100), 'cluster':'cee', 'main_set':'1mk15'}, + # {'id':('LiFePO4.s10.su','4mi',100), 'cluster':'cee', 'main_set':'1uAlf'}, + # {'id':('LiFePO4.s10.su','4mi',100), 'cluster':'cee', 'main_set':'1mAlf'}, + + + # {'id':('KVPO4F.Pna21.s10.su', '4uis', 100) , 'cluster':'cee'}, # energy is too high + + # {'id':('Na2FePO4F.s10.su','4uis', 100) , 'cluster':'cee' }, #also incorrect groundstate + # {'id':('Li2FePO4F.ir.su.s10.su','4uis',100), 'main_set':'1ur30', 'cluster':'skol'}, #incorrect groundstate + # {'id':('KFeSO4F.s10.su','4uSi', 100), 'main_set':'1urS', 'cluster':'cee'}, #too much forces + # {'id':('LiMn2O4.s10.su','4uis',100), 'cluster':'cee'}, + # {'id':('LiCoO2.s10.su','4uis',100), 'cluster':'cee'}, + # {'id':('Li2FePO4F.ir.su','4uis',100), 'cluster':'cee'}, + + #pbcn + # {'id':('Na2FePO4F.s10.su','4uis', 100) , 'main_set':'1uAlf', 'cluster':'cee' }, + # {'id':('Na2FePO4F.s10.su','4uis', 100) , 'main_set':'1mAlf', 'cluster':'cee' }, + # {'id':('NaFePO4F.id2.su.s10.su','4uis',100) , 'main_set':'1mAlf', 'cluster':'cee' }, + # {'id':('NaFePO4F.id2.su.s10.su','4uis',100) , 'main_set':'1uAlf', 'cluster':'cee' }, + + #pbcn + # {'id':('NaFePO4F.id2.su.s10.su','4uis',100),'st_from':calc['NaFePO4F.id1.su.s10.su','4uis',100].init, 'cation':'Na', 'trans':'Fe', 'main_set':'1mAlf', 'cluster':'cee' }, + # {'id':('NaFePO4F.id2.su.s10.su','4uis',100),'st_from':calc['NaFePO4F.id1.su.s10.su','4uis',100].init, 'cation':'Na', 'trans':'Fe', 'main_set':'1uAlf', 'cluster':'cee' }, + # {'id':('NaFePO4F.id2.su.s10.su','4uis',100),'st_from':calc['NaFePO4F.id1.su.s10.su','4uis',100].init, 'cation':'Na', 'trans':'Fe', 'main_set':'1urs', 'cluster':'cee' }, + + # {'id':('LiCoPO4F.pbcn.id2.su.s10','1u',100),'st_from':calc['LiCoPO4F.pbcn.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Co', 'main_set':'1urs', 'cluster':'cee' }, + # {'id':('LiFePO4F.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1urs', 'cluster':'cee' }, + # {'id':('LiFePO4F.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1m', 'cluster':'cee' }, + # {'id':('LiFePO4F.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1mAlf', 'cluster':'cee' }, + # {'id':('LiFePO4F.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1uAlf', 'cluster':'cee' }, + # {'id':('LiFePO4F.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1urs', 'cluster':'cee' }, + + + + + #pnma Co! + + # {'id':('LiCoPO4F.pnma.id2.su.s10','1urs',100),'st_from':calc['LiCoPO4F.pnma.id1.su.s10','1urs',100].init, 'cation':'Li', 'trans':'Co', 'main_set':'1urs', 'cluster':'cee' }, + + # {'id':('LiFePO4F.pnma.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.pnma.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1urs', 'cluster':'cee' }, + + # {'id':('LiFePO4F.pnma.id2.su.s10','1u',100),'st_from':calc['LiFePO4F.pnma.id1.su.s10','1u',100].init, 'cation':'Li', 'trans':'Fe', 'main_set':'1m', 'cluster':'cee' }, + + + + + + ] + + results = {} # result dictionary, for each structure we have dict + for cat in cathodes: + # name = cat_name_mod(l[0]) + name = cat['id'][0].split('.')[0] + results[name] = {} + + for cat in cathodes: + # print(cat['id']) + name = cat['id'][0].split('.')[0] + + if 'main_set' in cat: + ise_new = cat['main_set'] + else: + ise_new = main_set + + + itA = cat['id'][0]+'.as' + itB = cat['id'][0]+'.ifn' + idA = (itA, ise_new, cat['id'][2]) + idB = (itB, ise_new, cat['id'][2]) + + if 'st_from' in cat: + #for creating in partly deintercalated structures + ids = [] + # sufs = ['.a1', '.a2', '.a3'] + sufs = ['.a1', '.a3'] + for suf in sufs: + it = cat['id'][0]+suf + idd = (it, ise_new, cat['id'][2]) + ids.append( idd ) + if 'a1' in suf: + ida1 = idd + elif 'a3' in suf: + ida3 = idd + + + idsuf = ids[0] + + else: + sufs = ['.as'] + idsuf = idA + + # print(idA not in calc, idsuf not in calc ) + # sys.exit() + + # if update or idA not in calc or idsuf not in calc: + if update or idsuf not in calc: + '' + add_loop(*cat['id'], ise_new = ise_new, inherit_option = 'full_nomag', + it_folder = struct_des[cat['id'][0]].sfolder, + cluster = cat['cluster'], override = 1) + + # cat['st_from'] = calc[cat['id_frm']].init + for suf in sufs: + cat['mode'] = suf + # print(suf) + # sys.exit() + add_loop(*cat['id'], ise_new = ise_new, + inherit_option = 'antisite'+suf, confdic = cat, + it_folder = struct_des[cat['id'][0]].sfolder+'/anti/', + cluster = cat['cluster'], override = 1) + + + + + else: + res = None + try: + for idx in ids: + res_loop(*idx, up = 'up1',choose_outcar = choose_outcar, show = 'fo', readfiles = readfiles) + + _, res = res_loop(*ida3, up = 'up1', analys_type = 'diff', show = 'fo', b_id = ida1, choose_outcar = choose_outcar, readfiles = readfiles) #a1 - a3 - antisite energy + + # _, res = res_loop(*ids[1], up = 'up1', analys_type = 'diff', show = 'fo', b_id = idB, choose_outcar = choose_outcar, readfiles = readfiles) #A - a2 move iron - energy of moving iron + + calc_redox(calc[ida1], calc[idB] ) #voltage for alk ion intercalation + + except: + _, res = res_loop(*idA, up = 'up1', analys_type = 'diff', show = 'fo', b_id = idB, choose_outcar = choose_outcar, readfiles = readfiles) + + if res: + results[name]['e_as'] = res[0] + + + + + + + + + + + df = pd.DataFrame(results) + df = df.transpose() + df['source'] = gga + print(df) + if 1: + dfs = pd.read_csv(r'database/literature.csv')[['is', 'e_as', 'source', 'functional']] + dfs.drop(0, inplace=True) + dfs.drop(1, inplace=True) + dfs.dropna(inplace=True) + dfs.set_index('is', inplace = True) + dfs = dfs.apply(lambda x: pd.to_numeric(x, errors='ignore')) + + dfs['source'] = dfs['source']+' '+dfs['functional'] + del dfs['functional'] + # print(dfs) + df = df.append(dfs) + # print(df) + + + df_piv = df.pivot(columns='source', values='e_as') + print(df_piv) + + df_piv = df_piv.reindex(index = ['Li2FePO4F', 'LiFePO4', 'LiMnPO4', 'NaFePO4', 'NaMnAsO4', 'LiTiS2', 'LiVPO4F', 'LiVP2O7' ]) + + df_piv.index = pd.Series([re.sub("([0-9])", "$_\\1$", s) for s in df_piv.index ] ) # #Make low indexes + + + df_piv.plot(kind = 'bar', rot = 50, colormap = 'RdYlBu_r') + + plt.ylabel('Antisite formation energy (eV)') + + + # plt.legend(loc='best') + plt.legend(loc=2, ncol =2, handlelength = 0.25, + handleheight = 2, frameon=False, fontsize=14) + + + plt.tight_layout() + + # plt.show() + figname = 'figs/antisite_'+gga#+'.'+image_format + plt.savefig(figname+'.'+image_format, dpi = dpi, format=image_format) + plt.savefig(figname+'.png', dpi = 300) + + # push_figure_to_archive(figname, + # caption = gga+r""" Formation energies of antisite defects Li$_M^`M_{ \rm Li}^\bullet$ ($M$ = Fe, Mn, V) for several cathode materials""", + # figlabel = 'as_'+gga, autocompl = False ) + + return + + + + + + + + +def calc_antisite_defects3(update = 0, cathodes = None, param_dic = None, add_loop_dic = None, only = None): + """ + + 'add' - element to be inserted in void! + if provided + only - only these configurations are considered + """ + from impurity import insert_atom + from analysis import find_polaron + from geo import image_distance + + from current_structures import Na2X + + struct_des = header.struct_des + calc = header.calc + + if not cathodes: + cathodes = [ + # {'cl':calc[('Li2FePO4F.pnma','1u', 1)], 'el1':'Li', 'el2':'Fe', 'max_sep':4, 'set':'1uAlf', 'cluster':'cee' }, + # {'cl':calc['Li2FePO4F.pnma.su.s10','1u', 100], 'el1':'Li', 'el2':'Fe', 'max_sep':4, 'set':'1uAlf', 'cluster':'cee' }, + + {'cl':Na2X, 'el1':'Na', 'el2':'Fe', 'max_sep':4, 'set':'1uAlf', 'cluster':'cee' }, + # {'cl':calc['Na2FePO4F.s10.su','4uis', 100], 'el1':'Na', 'el2':'Fe', 'max_sep':4, 'set':'1uAlf', 'cluster':'cee' }, + # {'cl':Na_X, 'el1':'Na', 'el2':'Fe', 'max_sep':4, 'set':'1uAlf', 'cluster':'cee' }, + # {'cl':Na_X, 'el1':'Na', 'el2':'Fe', 'max_sep':4, 'set':'1uAlf', 'cluster':'cee', 'add':'Na' ,'i_void':3 }, #i_void: 0, 1 + ] + + if update: + up = 'up2' + else: + up = 'up1' + + + if not add_loop_dic: + add_loop_dic = {} + + if param_dic: + cathodes = [param_dic] + + # print(cathodes) + for c in cathodes: + + st = c['cl'].end + it = c['cl'].id[0] + it_base = it + + if 'add' in c: + el_add = c['add'] + st, i_add = insert_atom(st, el_add, i_void = c['i_void'], r_imp = 1.7) + it+=el_add+str(c['i_void']) + add_loop(it, c['set'], 1, input_st = st, it_folder = struct_des[it_base].sfolder+'/as', up = up, **add_loop_dic) + else: + if 'iatom' in c: + i_add = c['iatom'] + else: + i_add = None + + sts = create_antisite_defect3(st, c['el1'], c['el2'], max_sep = c['max_sep'], iatom = i_add ) + + + + cl_base = c['cl'].run(c['set'], iopt = 'full_nomag', up = up, add = update, **add_loop_dic) + + header.show = 'fo' + + for i, st_as in enumerate(sts): + if only is not None: + if i not in only: + continue + suf = 'as'+str(i) + st_as.name+=suf + st_as.write_poscar() + add_loop(it+'.'+suf, c['set'], 1, input_st = st_as, it_folder = struct_des[it_base].sfolder+'/as', up = up, **add_loop_dic) + cl_as = calc[it+'.'+suf, c['set'], 1] + # print(cl_as.path['output']) + try: + print('dE(as) = {:.0f} meV'.format( (cl_as.energy_sigma0-cl_base.energy_sigma0)*1000)) + st = cl_as.end + find_polaron(st, st_as.i_el1, out_prec = 2) + print('Separation after relax = {:.2f} A'.format( image_distance(st.xcart[st_as.i_el1], st.xcart[st_as.i_el2], st.rprimd )[0] ) ) + + except: + pass + + # if 'as0' in suf: + # break + + # sys.exit() + return + + +def alkali_bar(m, param, option = ''): + # bulk mod, volume change, average voltage + + if option in [ '1', '3']: + m.set_index('name', inplace = True) + try: + m.drop('KNiO2', inplace =1) + except: + pass + + # print (m) + + if option != '3': + m.set_index('proto', inplace = True) + + if option == '2': + + m_piv = m.pivot(columns='x', values=param['val']) + elif option == '3': + # m_piv = m.pivot(columns='ion', values=param['val']) + m_piv = m[['barrier']] + # m_piv = m.pivot(columns='ion', values=param['val'])[['Li', 'Na', 'Na2', 'NaLi']] + + else: + m_piv = m.pivot(columns='ion', values=param['val'])[['Li', 'Na', 'K',]] + + # if option == '2': + # m.set_index('name', inplace = True) + if option == '1': + m_piv = m_piv.reindex(index = ['XFePO4', 'XMnPO4', 'XTiS2', 'XNiO2', 'XVP2O7', 'XTiO2' ]) + elif option == '2': + m_piv = m_piv.reindex(index = ['XFePO4', 'XMnPO4', 'XVPO4F', 'XTiS2', 'XVP2O7', 'XTiO2', 'XMn2O4', ]) + + elif option == '3': + m_piv = m_piv.sort('barrier') + pass + + else: + print(m_piv) + m_piv = m_piv.reindex(index = ['XFeSO4F', 'XVPO4F.Pna21','XVPO4F', 'XVP2O7', 'XTiS2', 'XMnPO4', 'XFePO4', 'XNiO2', 'XMn2O4', 'XTiO2' ]) + + # m_piv.index['XFeSO4F'] = + m_piv.rename(index = {'XFeSO4F':'KFeSO4F', 'XVPO4F.Pna21':'KVPO4F.Pna21', 'XVPO4F':'LiVPO4F'}, inplace = 1) + m_piv.index = pd.Series([re.sub("([0-9])", "$_\\1$", s.split('.')[0]) for s in m_piv.index ] ) # #Make low indexes + if option == '2': + m_piv.index = pd.Series([s.replace('X', 'Li') for s in m_piv.index ] ) # #Make low indexes + + + + m_piv.plot(kind = 'bar', rot = 60, colormap = 'RdYlBu') + + plt.legend(loc='best', ncol =3, handlelength = 0.25, + handleheight = 2, frameon=1, fontsize=20) + + # mpl.rcParams.update({'font.size': 22}) + plt.axhline(color='black') + plt.axvline(x=1.5, color='black') + + if 0: + plt.axvline(x=3.5, color='black') + plt.axvline(x=5.5, color='black') + s = 0.1; h = param['h'] + plt.text(0+s, h,'Anatase\n P1', ha='left', va='top', fontsize = 14) + plt.text(1.5+s,h,'Olivine', ha='left', va='top', fontsize = 14) + plt.text(3.5+s,h,r'P$\bar{1}$ Layered', ha='left', va='top', fontsize = 14) + plt.text(5.5+s,h,'Pyrophospate\n Pristine', ha='left', va='top', fontsize = 14) + + plt.xlabel('') + plt.ylabel(param['yl']) + plt.tight_layout() + + # plt.show() + plt.savefig('figs/'+param['fig']+'.png', dpi = 300) + plt.savefig('figs/'+param['fig']+'.eps', dpi = 300) + # plt.close('all') + # plt.clf() + plt.show() + +def cathode_screening(): + """ + Analyze results + + Notes: + Eref is removed + replace res_loop with calc_redox !!! + + """ + calc = header.calc + + def sort_func(s): + s = s.replace('Li', 'A') + s = s.replace('Na', 'B') + s = s.replace('K', 'C') + s = s[::-1] + # print (s) + return s + + + if 'main' not in calc: + calc['main'] = {} + df = calc['main'] + + if 1: + if 1: + '' + # df['Li_IS'] = calc_barriers('normal') #Basic intercalated structures + # df['IS'] = calc_barriers('normal') # all, except LiCoO2, KFeSO4F + + # df['Li_IS_gga'] = calc_barriers('normal', func = 'gga') # U = 0, LiFePO4 LiMnPO4 LiNiO2 LiVPO4F NaMnAsO4 Na2FePO4F + # df['Li_IS2'] =calc_barriers('normal') #NaMnAsO4, Na2FePO4F, Na2FeVF7, NaLiCoPO4F, LiNiO2, LiMn2O4 + + # df['K_IS2'] = calc_barriers('normal') #KVPO4, KFeSO4 + + calc_barriers('normal') + + # df['Na_IS'] = calc_barriers('replace', 'Li', 'Na') #Na IS obtained from Li=base + # df['K_IS'] = calc_barriers('replace', 'Li', 'K') #K IS obtained from Li=base + # calc_barriers('replace', 'Li', 'Na') #K IS obtained from Li=base + # calc_barriers('replace', 'Na', 'K') #K IS obtained from Li=base + # calc_barriers('replace', 'Na', 'Li') #K IS obtained from Li=base + + if 1: + '' + # df['Li_DS'] = calc_barriers('make_ds', 'Li', 'Li') #Basic deintercalated structures + # calc_barriers('make_ds', 'Li', 'Li') #Basic deintercalated structures + # df['DS_gga'] = calc_barriers('make_ds', 'Li', 'Li', func = 'gga') #Basic deintercalated structures + # sys.exit() + # calc_barriers('make_ds', 'Na', 'Na') #Basic deintercalated structures + # df['K_DS'] = calc_barriers('make_ds', 'K', 'K') #Basic deintercalated structures + # calc_barriers('make_ds', 'Li Na', 'Li') #Basic deintercalated structures + # save = 1 + # print(df['Li_DS'][0]['vol']) + else: + #calculate change of volume due to deintercalation + # print(df) + al = df['IS'] + a = df['Li_IS'] + a2= df['Li_IS2'] + b = df['Na_IS'] + c = df['K_IS']+df['K_IS2'] + + d = df['Li_DS']+df['K_DS'] + e = df['Li_IS_gga'] + f = df['DS_gga'] + + + + for x in a,b,c: + for ix, jd in zip(x,d): + + if jd['name'] in ix['name']: + # ix['vol'] + # ix['vol_red'] = (ix['vol']/jd['vol']-1)*100 #reduction of volume in % due to deintercalation + dic, _ = res_loop(*ix['id'], b_id = jd['id'], energy_ref = ix['Eref'], analys_type = 'redox_pot', readfiles = 0) + if 'vol_red' in dic: + ix['vol_red'] = dic['vol_red'] + ix['Vav'] = dic['redox_pot'] + print('Volumes are', calc[ix['id']].end.vol, calc[jd['id']].end.vol,'; ids are',ix['id'], jd['id'] ) + + else: + ix['vol_red'] = None + ix['vol_ds'] = jd['vol'] + + # print (ix['name']) + if ix['name'] == 'KVP2O7': + ix['vol_red'] = None + ix['Vav'] = None + + + else: + printlog('DS structure ', jd['name'], 'is not in intercalated structure', ix['name']) + ix['vol_red'] = None + '' + + + + + al = pd.DataFrame(al) + a = pd.DataFrame(a) + a2 = pd.DataFrame(a2) + # a.dropna('LiMn2O4') + b = pd.DataFrame(b) + c = pd.DataFrame(c) + d = pd.DataFrame(d) + e = pd.DataFrame(e) + f = pd.DataFrame(f) + + + # print(b) + # sys.exit() + + + # print(a.round(1)) + m = pd.concat([a, b, c]) + md = pd.concat([a, b, c, d]) + # print(m) + # m = pd.DataFrame(m, index = sorted(m.index, key = sort_func ) ) #sort + # print(m) + + # print(m) + # sys.exit() + + + + # alkali_bar(m, {'val':'B', 'h':135, 'yl':'Bulk modulus (GPa)', 'fig':'bulk' } ) #plot Bulk modulus + # alkali_bar(m, {'val':'vol_red', 'h':440, 'yl':'Volume change (%)' , 'fig':'volume' } ) + # alkali_bar(m, {'val':'Vav', 'h':40, 'yl':'Intercalation voltage (V)' , 'fig':'av_pot' }) + # alkali_bar(m, {'val':'barrier', 'h':135, 'yl':'Migration barrier (eV)', 'fig':'barrier_Li_Na_K' }, option = '1' ) + # alkali_bar(pd.concat([a, d]), {'val':'barrier', 'h':135, 'yl':'Migration barrier (eV)', 'fig':'barrier_Li_IS_DS' }, option = '2' ) + # alkali_bar(a2, {'val':'barrier', 'h':135, 'yl':'Migration barrier (eV)', 'fig':'barrier_Li_IS2' }, option = '3' ) + + #comparison of gga and gga+ + if 1: + if 1: #IS + al['func'] = 'GGA+U' + e['func'] = 'GGA' + mc = pd.concat([al, e]) + filename = 'barriers_gga_ggau' + # print(mc) + else: #DS + d['func'] = 'GGA+U' + f['func'] = 'GGA' + mc = pd.concat([d, f]) + filename = 'barriers_gga_ggau_DS' + + mc.set_index('name', inplace = True) + m_piv = mc.pivot(columns='func', values='barrier') + m_piv.dropna(inplace =1) + + # print(m_piv) + # sys.exit() + m_piv = m_piv.reindex(index = ['Na2FePO4F', 'NaMnAsO4', 'LiVPO4F', 'LiFePO4', 'LiMnPO4', 'LiNiO2', 'LiVP2O7' ]) + + + m_piv.index = pd.Series([re.sub("([0-9])", "$_\\1$", s) for s in m_piv.index ] ) # #Make low indexes + + m_piv.plot(kind = 'bar', rot = 60, colormap = 'RdYlBu_r') + + plt.legend(loc='best', ncol =3, handlelength = 0.25, + handleheight = 2, frameon=1, fontsize=20) + plt.xlabel('') + plt.ylabel('Migration barrier (eV)') + plt.ylim(0, 1.2) + + plt.tight_layout() + + plt.savefig('figs/'+filename+'.png', dpi = 300) + plt.savefig('figs/'+filename+'.eps', dpi = 300) + plt.show() + + + if 0: + dfs = pd.read_csv(r'database/literature.csv')[['is', 'barrier', 'source', 'type']] + dfs.drop(0, inplace=True) + dfs.dropna(inplace=True) + dfs.set_index('is', inplace = True) + dfs = dfs.apply(lambda x: pd.to_numeric(x, errors='ignore')) + # dfs['owner'] = 'world' + # print(dfs.sort_index()) + # print(dfs) + # sys.exit() + + # m = + + m['source'] = 'our' + # m['owner'] = 'Skoltech' + m['type'] = 'our' + # print(m) + + # m.dropna(inplace =1) + m = m[['name', 'barrier', 'source', 'type']] + m.set_index('name', inplace = 1) + if 1: + m = m.append(dfs) + + m.dropna(inplace =1) + + + # m.sort_index(inplace = 1) + + # print (m) + m_piv = m.pivot(columns='type', values='barrier')[['our', 'theory']] + # print( m_piv) + m_piv.dropna(inplace =1) + + + # df_piv = pd.DataFrame(df_piv, index = sorted(df_piv.index, key = sort_func ) ) + + if 1: + m_piv.drop('LiMn2O4', inplace =1) + m_piv = m_piv.reindex(index = ['LiFePO4', 'NaFePO4', 'LiMnPO4', 'LiVPO4F', 'LiTiS2', 'LiTiO2' ]) + + m_piv.rename(columns = {'theory':'Literature DFT'}, inplace =1) + + m_piv.index = pd.Series([re.sub("([0-9])", "$_\\1$", s) for s in m_piv.index ] ) # #Make low indexes + + m_piv.plot(kind = 'bar', rot = 60, colormap = 'RdYlBu') + + plt.legend(loc='best', ncol =3, handlelength = 0.25, + handleheight = 2, frameon=1, fontsize=20) + + plt.ylim(0, 1.6) + + plt.xlabel('') + plt.ylabel('Migration barrier (eV)') + plt.tight_layout() + + plt.savefig('figs/barriers_theory.png', dpi = 300) + plt.savefig('figs/barriers_theory.eps', dpi = 300) + plt.show() + + +def alkali_bar2(m, param = None, option = '', plot_type = 'bar', suf = '', reindex = None): + """ + bulk mod, volume change, average voltage + plot bar figures for paper7 + + m - dataframe object with data build from output of calc_barriers() + param + - val - y value to plot + - barrier + - yl - y legend + - h - high of figure + - fig - figure name + + option - + 1 - compare Li Na K + 2 - compare IS and DS on one plot + + reindex - change the order of index - for each project is added additionaly + + + plot_type + bar + dAO_barrier - specific plot + + suf (str) - arbirtary suffix + + param['val'] - ['redox', 'vol_red'] + + """ + m = copy.deepcopy(m) + if param == None: + param = {'val':None} + + # if plot_type == 'dAO_barrier': + # param = None + + if option in [ '1', '3']: + # print(m['name']) + # sys.exit() + m.set_index('name', inplace = True) + # sys.exit() + try: + m.drop('KNiO2', inplace =1) + except: + pass + + + + # print(m) + + if 'barrier' in param['val']: + printlog('Attention! Barriers were converted to absolute values', imp = 'y') + # convert negative barriers to positive! + m.loc[:, param['val']] = m[param['val']].abs() + # print(m[param['val']]) + + # sys.exit() + + + m_x = m.set_index('x') + mIS = m_x.ix['100%'] + mDS = m_x.ix['0%'] + + + # print(mIS) + # print(mDS) + + + + ms = [] + if option in ['1', '2']: + m.set_index('proto', inplace = True) + mIS.set_index('proto', inplace = True) + mDS.set_index('proto', inplace = True) + + + + + #determine redox pot and volume change + if plot_type == 'bar': + + redox, volred = [], [] + if param['val'] in ['redox', 'vol_red']: + + # mIS.ix[0]['new'] = 'go' + # print(mIS) + for rowIS, rowDS in zip(mIS.iterrows(), mDS.iterrows()): + idIS = rowIS[1]['id'] + idDS = rowDS[1]['id'] + # print(idIS, idDS) + out = calc_redox(db[idIS], db[idDS], silent = 1) + redox.append(out['redox_pot']) + volred.append(out['vol_red']) + + + mIS = mIS.assign(redox=pd.Series(redox, index=mIS.index)) # add column + mIS = mIS.assign(vol_red=pd.Series(volred, index=mIS.index)) # add column + # print(mIS) + # sys.exit() + + + + if option == '1': + m_pivIS = mIS.pivot(columns='ion', values=param['val'])[['Li', 'Na', 'K',]] + ms.append(m_pivIS) + + if param['val'] in ['barrier', ]: #use negative axis for DS state + + + mDS.loc[:, param['val']] = mDS[param['val']]*-1 + + m_pivDS = mDS.pivot(columns='ion', values=param['val'])[['Li', 'Na', 'K',]] + + ms.append(m_pivDS) + + + + + + if option == '2': + m_piv = m.pivot(columns='x', values=param['val']) + ms.append(m_piv) + + + elif option == '3': + # m_piv = m.pivot(columns='ion', values=param['val']) + m_piv = m[['barrier']] + # m_piv = m.pivot(columns='ion', values=param['val'])[['Li', 'Na', 'Na2', 'NaLi']] + ms.append(m_piv) + + else: + '' + # m_piv = m.pivot(columns='ion', values=param['val'])[['Li', 'Na', 'K',]] + + # ms.append(m_piv) + # if option == '2': + # m.set_index('name', inplace = True) + + # print(m_pivDS) + + + if option == '1': + '' + # m_piv = m_piv.reindex(index = ['XFePO4', 'XMnPO4', 'XTiS2', 'XNiO2', 'XVP2O7', 'XTiO2' ]) + elif option == '2': + m_piv = m_piv.reindex(index = ['XFePO4', 'XMnPO4', 'XVPO4F', 'XTiS2', 'XVP2O7', 'XTiO2', 'XMn2O4', ]) + + elif option == '3': + m_piv = m_piv.sort('barrier') + pass + + else: + # print(m_piv) + m_piv = m_piv.reindex(index = ['XFeSO4F', 'XVPO4F.Pna21','XVPO4F', 'XVP2O7', 'XTiS2', 'XMnPO4', 'XFePO4', 'XNiO2', 'XMn2O4', 'XTiO2' ]) + + + for i in range(len(ms)): + mp = ms[i] + mp.rename(index = {'XMn2O4.Fd3m.111':'XMn2O4','XFeSO4F':'KFeSO4F', 'XVPO4F.Pna21':'KVPO4F.Pna21', }, inplace = 1) + mp.rename(index = {'XMO':'XMn2O4','XFPO':'XFePO4', 'XMPO':'XMnPO4', 'XVPOF':'XVPO4F', }, inplace = 1) + + ms[i] = mp.reindex(index = ['XMn2O4', 'XFePO4', 'XMnPO4', 'XVPO4F']) + mp = ms[i] + + mp.index = pd.Series([re.sub("([0-9])", "$_\\1$", s.split('.')[0]) for s in mp.index ] ) # #Make low indexes + + # print(mp.index) + + mp.index = pd.Series([s.replace('X', 'A') for s in mp.index ] ) # + # print(mp.index) + + + if option == '2': + m_piv.index = pd.Series([s.replace('X', 'Li') for s in m_piv.index ] ) # + + + # print(m_piv) + # mpl.style.use('ggplot') + + # fig, ax = plt.subplots() + + + if 'ylim' in param: + ylim = param['ylim'] + else: + ylim = None + + if plot_type == 'bar': + ax = None + + + for mp in ms: + if ax != None: + ax.legend('') + # print(mp) + ax = mp.plot(kind = 'bar', rot = 60, colormap = 'RdYlBu', ax = ax, ylim = ylim) + + # plt.legend(['Li', 'Na', 'K']) + + ax.legend(['Li', 'Na', 'K'],loc='best', ncol =3, handlelength = 0.25, + handleheight = 2, frameon=1, fontsize=20) + + # mpl.rcParams.update({'font.size': 22}) + plt.axhline(color='black') + plt.axvline(x=1.5, color='black') + + if 0: + plt.axvline(x=3.5, color='black') + plt.axvline(x=5.5, color='black') + s = 0.1; h = param['h'] + plt.text(0+s, h,'Anatase\n P1', ha='left', va='top', fontsize = 14) + plt.text(1.5+s,h,'Olivine', ha='left', va='top', fontsize = 14) + plt.text(3.5+s,h,r'P$\bar{1}$ Layered', ha='left', va='top', fontsize = 14) + plt.text(5.5+s,h,'Pyrophospate\n Pristine', ha='left', va='top', fontsize = 14) + + plt.xlabel('') + plt.ylabel(param['yl']) + + filename = param['fig'] + + elif plot_type == 'dAO_barrier': + # print(m_x) + m_dAO_IS = m_x.set_index('dAO_change') + # dAO_bar = mIS[['dAO_change', 'barrier']] + # print(dAO_bar) + + # dAO_bar.plot(x= 'dAO_change',y = 'barrier', xlim = (0, 0.3), style = ['o']) + m_dAO_IS_piv = m_dAO_IS.pivot(columns='ion', values='barrier')[['Li', 'Na', 'K',]] + + + # m_dAO_IS_piv.columns.name = 'A-(O,F) distance, $\AA$' + m_dAO_IS_piv.index.name = 'Change of A-(O,F) distance, $\AA$' + # print(m_dAO_IS_piv) + + + + header.mpl.rc('legend', fontsize= 16) + + m_dAO_IS_piv.plot(xlim = (0, 0.3), style = ['ro', 'gs', 'bv'], ms = 10, ) + + plt.ylabel('Migration barrier, eV') + # plt.show() + filename = param['fig'] + + # filename = plot_type+suf + + plt.tight_layout() + + + # plt.show() + plt.savefig('figs/'+filename+'.png', dpi = 300) + plt.savefig('figs/'+filename+'.pdf', dpi = 300) + # plt.close('all') + # plt.clf() + # plt.show() + return + +def e_bind(cl_bulk, cl_vac, cl_sol, cl_compl): + #binding energy of vacancy - solute complex + #cl_compl - complex + dE = cl_sol.e0 + cl_vac.e0 - (cl_bulk.e0 + cl_compl.e0) + + if cl_compl.end.nznucl[1] > 1: + n_sol = cl_compl.end.nznucl[1] + print('Number of solute atoms = ', n_sol) + dE = n_sol*cl_sol.e0 + cl_vac.e0 - (n_sol*cl_bulk.e0 + cl_compl.e0) + + + + return dE + + + + +def plot_UvsD(it1, it2, it_b, ise, sc_reg, n_imag, ise_b = None, v_b = None, suf = '', + up = 0, legend = None, invert_x = False, linetypes = None, + st_start = None, ver_lines = None, ylim = None): + """ + Intercalation potential vs deformation + sc_reg - scale region + n_imag - n_scale_images + suf - suffix + v_b (int) - if provided than version of base fixed to this number + """ + plot_dist = False + + if plot_dist: + show = 'sur' + else: + show = 'fo' + + + scales = np.linspace(*sc_reg, n_imag) + U1, U2 = [], [] + + if not ise_b: + ise_b = ise + + for it in [it1, it2, it_b]: + # print(calc[it, ise, 2].state) + if it == it_b: + iset = ise_b + else: + iset = ise + if '4' not in calc[it, iset, 1].state or up : + res_loop(it, iset, range(1, n_imag+1), show = show) + # print(calc[it, ise, 2].state) + # sums = {'Li-O':[], 'Na-O':[], 'Li-O(b)':[], 'Na-O(b)':[]} + sums = {} + for v in range(1,n_imag+1): + cl1 = calc[it1, ise, v] + cl2 = calc[it2, ise, v] + if v_b: + cl_b = calc[it_b, ise_b, v_b] + else: + cl_b = calc[it_b, ise_b, v] + U1.append(calc_redox(cl1, cl_b, value = -scales[v-1])['redox_pot'] ) + U2.append(calc_redox(cl2, cl_b, value = -scales[v-1])['redox_pot'] ) + + if plot_dist: + for k, cl in ('1', cl1), ('2', cl2), ('b', cl_b): + for bond in ('Li-O', 'Na-O', 'Fe-O', 'O-O', 'Li-Fe', 'Na-Fe'): + if bond in cl.sumAO: + key = bond+'('+str(k)+')' + if key not in sums: + sums[key]= [] + sums[key].append(cl.sumAO[bond]) + + # cl1.end.write_xyz() + # cl2.end.write_xyz() + # cl_b.end.write_xyz() + + if not legend: + legend = ('pos1', 'pos2', 'lower left') + elif len(legend) == 2: + legend.append('lower left') + + if invert_x: + scales = [-s for s in scales ] + # U1 = U1[::-1] + # U2 = U2[::-1] + + + if not linetypes: + linetypes = ['b-o', 'g-o'] + + if 1: + fit_and_plot(U1 = (scales, U1, linetypes[0], legend[0]), U2 = (scales, U2, linetypes[1], legend[1]), + image_name = 'figs/strain_'+suf, legend = legend[2], ylabel = 'Redox potential, V', xlabel = 'Compression, $\delta$, %', + ylim = ylim, + ver_lines = ver_lines) + + + + + + + + + + if plot_dist: + header.mpl.rc('legend', fontsize= 10) + + fit_and_plot( + # l1 = (scales, sums['Li-O(1)'], 'g--', 'Li-O'), + # l2 = (scales, sums['Li-O(b)'], 'g-', 'Li-O(b)'), + # l3 = (scales, sums['Na-O(2)'], 'r--', 'Na-O'), + # l4 = (scales, sums['Na-O(b)'], 'r-', 'Na-O(b)'), + l5 = (scales, sums['Fe-O(1)'], 'g--', 'Fe-O(1)'), + l6 = (scales, sums['Fe-O(2)'], 'r--', 'Fe-O(2)'), + l7 = (scales, sums['Fe-O(b)'], 'r-', 'Fe-O(b)'), + # l5 = (scales, sums['O-O(1)'], 'g--', 'O-O(1)'), + # l6 = (scales, sums['O-O(2)'], 'r--', 'O-O(2)'), + # l7 = (scales, sums['O-O(b)'], 'k-', 'O-O(b)'), + + # l5 = (scales, sums['Li-Fe(1)'], 'g--', 'Li-Fe(1)'), + # l6 = (scales, sums['Na-Fe(2)'], 'r--', 'Na-Fe(2)'), + # l7 = (scales, sums['Li-Fe(b)'], 'g-', 'Li-Fe(b)'), + # l8 = (scales, sums['Na-Fe(b)'], 'r-', 'Na-Fe(b)'), + + + # ld = (scales, np.array(sums['Na-O']) - np.array(sums['Na-O(b)']), 'r--', 'd Na-O'), + # ld2 = (scales, np.array(sums['Li-O']) - np.array(sums['Li-O(b)']), 'g-', 'd Li-O'), + + + image_name = 'figs/AO_dist_'+suf, legend = 'best', ncol = 1, ylabel = 'average A-O, A', xlabel = 'Compression, $\delta$, %', ylim = None) + + + + return scales, U1, U2, legend + + +def calc_strain_influence(cl_b, replace = False, rep_pos = None, + half = False, del_el_list = None, del_pos_list = None, + invert_x = None, vac = False, it_folder = 'Na2FePO4F/scaled', + plot = 0, ise = '', mul_matrix = None, sreg = None, + suf = None, up = 0, n_scale_images = None, + ver_lines = None, ylim = None): + """ + Helper function + Creates 3 calculations + replace - if replacement of one Na by Li is needed + rep_pos - replacement pos of Na with Li + del_pos_list - del pos + vac - if False all atoms are removed, if True only one atom is removed + half - (bool) remove half of atoms (half charged) + sreg - scale_region + """ + scale_region = sreg + if not mul_matrix: + mul_matrix = [[0.99, 0, 0], [0, 1.0025, 0], [0, 0, 0.98]] + if not scale_region: + scale_region = (-3, 8) + + if not ylim: + ylim = (2.6, 3.5) + + + if not n_scale_images: + n_scale_images = 12 + + cl_list = [] + if not ise: + ise = '1uis' + + if not del_el_list: + del_el_list = ['Na', 'Li'] + + if not del_pos_list: + del_pos_list = [1,] + + + if replace: + st_b = create_replaced_structure(cl_b.end, el1 = 'Na', el2 = 'Li', rep_pos = rep_pos) + it_b = cl_b.id[0]+'.ir'+str(rep_pos)+'Li' + + + else: + st_b = copy.deepcopy(cl_b.end) + it_b = cl_b.id[0] + + + st_b.magmom = [None] + cl_list.append([it_b, st_b]) + # names = [] + for el in del_el_list: + for del_pos in del_pos_list: + lsuf = '' + if vac: + # del_pos = 1 + st_del = remove_one_atom(st_b, el, del_pos = del_pos) + it_del = it_b+'.vac'+el+str(del_pos) + + elif half: + lsuf = 'half' + if len(del_el_list) == 2: + if el == 'Na': + at_to_remove = [61, 60, 57,64] + conf = 'c6' + st_del = st_b.remove_atoms(at_to_remove, from_one = 1) + elif el == 'Li': + at_to_remove = [65, 72, 69, 68] + conf = 'c5' + st_del = st_b.remove_atoms(at_to_remove, from_one = 1) + it_del = it_b+'.id'+el+lsuf+'.'+conf # + + + elif len(del_el_list) == 1: + if del_pos == 1: + at_to_remove = [61,62,57,59] + conf = 'c13' + st_del = st_b.remove_atoms(at_to_remove, from_one = 1) + elif del_pos == 2: + at_to_remove = [65,72, 69,68] + conf = 'c5' + st_del = st_b.remove_atoms(at_to_remove, from_one = 1) + + it_del = it_b+'.id'+el+str(del_pos)+lsuf+'.'+conf # + + + + else: + st_del = create_deintercalated_structure(st_b, el, del_pos = del_pos) + + if len(del_pos_list) ==1: + it_del = it_b+'.id'+el # for compatibility + else: + it_del = it_b+'.id'+el+str(del_pos) + + + + + cl_list.append([it_del, st_del]) + + + + + + + if not suf: + suf = '.sm' + scales, U1, U2, legend = None, None, None, None + + if not plot: + for clt in cl_list: + idd = (clt[0], ise, 1) + iddsm = (clt[0]+suf, ise, 1) + if iddsm not in calc or up: + add_loop(*idd, input_st = clt[1], it_suffix = suf.replace('.', ''), calc_method = 'scale', mul_matrix = mul_matrix, + scale_region = scale_region, n_scale_images = n_scale_images, inherit_option = 'inherit_xred', it_folder = it_folder) + else: + + + + + + if rep_pos == 1: + pos2 = 2 + # lin1 = '-b' + # lin2 = '-g' + elif rep_pos == 2: + pos2 = 1 + # l1 = lin1 + # lin1 = lin2 + # lin2 = l1 + + + + + if len(del_el_list) == 2: + leg2 = 'Li'+str(rep_pos) +' removal' + leg1 = 'Na'+str(pos2) +' removal' + + elif len(del_el_list) == 1: + el = del_el_list[0] + leg1 = el+str(del_pos_list[0]) +' removal' + leg2 = el+str(del_pos_list[1]) +' removal' + + lin1 = '-ob' + lin2 = '-og' + + # if 'Li' in leg2: + # lin2 = '-og' + # elif 'Na' in leg2: + # lin2 = '-ok' + + + scales, U1, U2, legend = plot_UvsD(it1 = cl_list[1][0]+suf , it2 = cl_list[2][0]+suf, it_b = cl_list[0][0]+suf, ise = ise, sc_reg = scale_region, + n_imag = n_scale_images, + suf = cl_list[2][0]+suf+ise, legend = (leg1, leg2, 'lower left'), linetypes = (lin1, lin2), up = 1 , + invert_x = invert_x, st_start = cl_b.end, ver_lines = ver_lines, ylim = ylim) + + +# ise, sc_reg, n_imag + return scales, U1, U2, legend + + + +def replace(update, cl, el1, el2, reptype = None, show_fit = 0): + """ + cl - calculation to work with + el1 - element to be replaced + el2 - replace by this + reptype - type of replacement + 'full' - all atoms of specific symmetry type + 'one' - only one atom of specific symmetry type + + update - update + """ + + st = cl.end + # print(determine_symmetry_positions(st, el1)) + n_noneq_pos = len(determine_symmetry_positions(st, el1)) + printlog('Number of non-equiv pos', n_noneq_pos) + + + # sys.exit() + if not reptype: + printlog('Error! replace(): Please provide reptype = "full" or "one"') + + for pos in range(n_noneq_pos): + '' + pos+=1 + if 'one' in reptype: + suf = 'one' + ise = '1uis' + scale_region = (-4, 4) + one = 1 + else: + suf = '' + ise = '4uis' + scale_region = (-6, 2) + one = 0 + + it_new = cl.id[0]+'.ir'+str(pos)+suf+el2 + id_new = (it_new, ise, 1) + it_folder = header.struct_des[cl.id[0]].sfolder + '/' + 'replaced' + + # print((it_new+'.su', ise, 1)) + # print((it_new+'.su', ise, 1) not in header.calc) + # sys.exit() + if one: + id_new2 = id_new + else: + id_new2 = (it_new+'.su', ise, 1) + + if update or id_new2 not in header.calc: + st_rep = create_replaced_structure(st, el1 = el1, el2 = el2, rep_pos = pos, only_one = one) + st_rep.write_xyz() + + if one: + add_loop(*id_new, input_st = st_rep, it_folder = it_folder, override = True) #charge density without relaxation + + else: + add_loop(*id_new, calc_method = 'uniform_scale', inherit_option = 'inherit_xred', scale_region = scale_region, input_st = st_rep, it_folder = it_folder) + + + + + else: + '' + if 'full' in reptype: + if show_fit: + res_loop(it_new+'.su', ise, list(range(1,8))+[100], analys_type = 'fit_a', show = 'fitfo') + else: + res_loop(it_new+'.su', ise, 100, show = 'fo') + + else: + res_loop( *id_new, show = 'fo') + + + return + + +calc_material = calc_barriers + + + +def neb_wrapper( param_dic = None, paths = None, run_neb = 0, read = 0, plot = 0, mode = 'IS', DS = None, ylim = None, + special_case = None, add_loop_args = None, first =1, last = 1, style_dic = None, substitute = None, up_res = 'up2'): + """ + Allows to run, read, and plot composition diffusion path; + was used for RbVPO4F and KVPO4F + + + paths - list of tuples; each tuple contains (A, B, C, D, E), + where A - #atom number from 0 - start position for migration + B - end position number according add_neb + C - name of created it + D - (not nessesary) either path to occupation matrix or + id, from which the occupation matrix should be taken for IS + E - (not nessesary) either path to occupation matrix or + id, from which the occupation matrix should be taken for DS + + special_case: # for KVP additional static run + mode - + 'IS', 'DS' + + DS - calc used as initial ds + + + + + + substitute - manually substitute specific points of MEP + + """ + from picture_functions import plot_mep + + + + struct_des = header.struct_des + calc = header.calc + + if not add_loop_args: + add_loop_args = {} + + if 'upC' not in param_dic: + param_dic['upC'] = None + + n_set = param_dic['neb_set'] + imag = param_dic['images'] + + nameadd = '_'+param_dic['id'][0]+'_'+param_dic['main_set']+'_'+n_set + tkeys = {'1':'t_mep'+nameadd, '2':'t_it'+nameadd,'3':'t_mepDS'+nameadd} + for key in tkeys: + if tkeys[key] not in calc: + # print(key) + calc[tkeys[key]] = {} + + + pos = [] + mep = [] + + el = param_dic['el'] + # if 'old_behaviour' in param_dic: + # old_behaviour = param_dic['old_behaviour'] + # else: + # old_behaviour = 0 + + if run_neb or read: + plot = 0 + + for p in paths: + + if len(p)>3: + if 'OCCMATRIX' in p[3]: # the file is provided + add_loop_args['params'] = {'occmatrix':p[3]} + else: # assuming that id of calculation is provided + param_dic['occmatrix_id'] = p[3] + pk = p[0:3] + + if mode == 'IS': + """intercalated""" + + if len(p)>3: + if 'OCCMATRIX' in p[3]: # the file is provided + add_loop_args['params'] = {'occmatrix':p[3]} + else: # assuming that id of calculation is provided + param_dic['occmatrix_id'] = p[3] + pk = p[0:3] + + t_key = tkeys['1'] + # print(t_key) + param_dic['i_atom_to_move'] = p[0] + param_dic['start_pos'] = None + param_dic['end_pos'] = p[1] + if run_neb or read: + calc_barriers('normal', el, el, up_res = up_res, run_neb = 1, show_fit = 0, up = 0, upA = 0, upC = param_dic['upC'], param_dic = param_dic, add_loop_dic = add_loop_args) # here 1 is 4.47 A; 3 is 6.64 A + # print(t_key) + calc[t_key][pk] = calc['_mep'] + # print(calc[t_key][p]) + + # print (t_key) + # print (calc[t_key]) + # print(calc[t_key][p][1]) + print('t_key', t_key) + pos.extend(list((calc[t_key][pk][0]))) + + if special_case: # for KVP additional static run + e_stat = [calc[pk[2]+'.ifn', '0m', i].e0 for i in [1, 3,4,5,6,7, 2]] + mep.extend(list(reversed(e_stat))) + suf2= '_spec' + + else: + mep.extend(list(reversed(calc[t_key][pk][1]))) + suf2 = '' + + + + elif mode == 'DS': + + + if len(p)>4: + if 'OCCMATRIX' in p[4]: # the file is provided + add_loop_args['params'] = {'occmatrix':p[4]} + else: # assuming that id of calculation is provided + param_dic['occmatrix_id'] = p[4] + + cl = db[p[4]] + # print(p[4]) + + occfile = write_occmatrix(cl.occ_matrices, cl.dir) + # continue + add_loop_args['params'] = {'occmatrix':occfile} + + + pk = p[0:3] + + + suf2 = '' + """deintercalated""" + for cl in ( + DS, + # Rb05V12, + # Rb05V22 + ): + '' + t_key_it = tkeys['2'] + t_key = tkeys['3'] + + if run_neb: + it = add_neb(cl, up = 'up2', ise_new = n_set, images = imag, + xr_start = struct_des[p[2]].xr_m_ion_start, + xr_final = struct_des[p[2]].xr_m_ion_final, + i_atom_to_move = p[0], i_void_final = p[1], #just needed for name + atom_to_insert = el, add_loop_dic = add_loop_args) + calc[t_key_it][pk] = it + + + + + if read: + res, _ = res_loop(calc[t_key_it][pk],n_set,range(1, imag+3), up = 'up1', check_job = 0, show = 'fomep', readfiles = 1, analys_type = 'neb', fitplot_args = None) + calc[t_key][pk] = calc['_mep'] + elif not run_neb: + pos.extend(list((calc[t_key][pk][0]))) + # mep.extend(list(reversed(calc[t_key][p][1]))) + mep.extend(list(calc[t_key][pk][1])) + + + + + if substitute: + for k in substitute: + mep[k] = substitute[k] + + # print(pos) + # print(mep) + + if plot: + name = t_key.replace("'","").replace('(','').replace(')','').replace(' ', '').replace(',','_') + # print(pos, mep) + plot_mep(pos, mep, filename = 'figs/path_'+name+suf2, fitplot_args = {'figsize':(8,6), 'hor':1, 'ylim':ylim, 'legend':1, 'first':first, 'last':last}, style_dic = style_dic) + + return + + + + +def calc_charged(cl, del_dic, name = None, run = 0, ise = '4uis', it_folder = None ): + + """ + create charged by removing specific sets of atoms provided in del_dic manually starting from 1 + + """ + + # if not del_dic: + + if not it_folder: + it_folder = name+'/' + + for key in del_dic: + del_pos = del_dic[key] + it_new = name+'.c'+str(key) + + if run: + st = cl.end.remove_atoms(del_pos, from_one = 1) + st.name+='c'+str(key) + # st_halfLi.write_xyz() + add_loop(it_new, ise, 1, calc_method = 'uniform_scale', inherit_option = 'inherit_xred', scale_region = (-5, 3), input_st = st, it_folder = it_folder) + # print(st_halfLi.get_space_group_info()) + # add_loop(it_new,'0u',1, input_st = st_halfLi, it_folder = 'Na2FePO4F/chg', override = True) #charge density without relaxation + + else: + idd = (it_new+'.su', ise, 100) + res_loop(*idd, show = 'maga', up = 'up1')#list(range(1,8))+[100], analys_type = 'fit_a', show = 'fitfo', up = '1') + # st = calc[idd].end + # print(st.get_space_group_info()) + # alpha, beta, gamma = st.get_angles() + + # print(alpha, beta, gamma) + return + + +def optimize(st, name = None, run = 0, ise = '4uis', it_folder = None, fit = 0 ): + + """ + + """ + + # if not del_dic: + + if not it_folder: + it_folder = 'optimization/'+name.split('.')[0]+'/' + + it_new = name + if run: + add_loop(it_new, ise, 1, calc_method = 'uniform_scale', inherit_option = 'inherit_xred', scale_region = (-5, 3), input_st = st, it_folder = it_folder) + + else: + idd = (it_new+'.su', ise, 100) + if fit: + res_loop(*idd[0:2], list(range(1,8))+[100], analys_type = 'fit_a', show = 'fitfo', up = '1') + + else: + res_loop(*idd, show = 'maga', up = 'up1')#list(range(1,8))+[100], analys_type = 'fit_a', show = 'fitfo', up = '1') + # st = calc[idd].end + # print(st.get_space_group_info()) + # alpha, beta, gamma = st.get_angles() + + # print(alpha, beta, gamma) + return diff --git a/project_template/main.py b/project_template/main.py new file mode 100644 index 0000000..50656d0 --- /dev/null +++ b/project_template/main.py @@ -0,0 +1,171 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- +""" +siman is needed; Author: Aksyonov D.A. +""" +from __future__ import division, unicode_literals, absolute_import, print_function + +if 1: + import sys, re, copy + import numpy as np + import pandas as pd + import matplotlib.pyplot as plt + import matplotlib as mpl + + + sys.path.append('/home/aksenov/Simulation_wrapper/siman') #path to siman package + # from header import *; + + + import header + + # sys.exit() + + from header import print_and_log as printlog + + from calc_manage import (clean_history_file, prepare_run, manually_remove_from_struct_des, update_des, inherit_icalc, add_loop, res_loop, complete_run, add_des ) + + from functions import calc_ac, plot_charge_den + from inout import write_xyz + + from database import read_database, write_database + from set_functions import read_vasp_sets + from project_funcs import redox, potential_barriers, calc_antisite_defects + from project_funcs import workflow + from project_funcs import calc_barriers, cathode_screening + from analysis import calc_redox + + + + header.conv, header.varset, size_on_start = read_database() + + + calc = header.calc; conv = header.conv; varset = header.varset + # header.db = calc; + db = header.db + header.struct_des = update_des(header.struct_des, header.MANUALLY_ADDED); #read manually added calculations from project_conf.py file + struct_des = header.struct_des + import project_sets # should be after read_database + + varset = read_vasp_sets(project_sets.user_vasp_sets, override_global = 0) #3. read user sets + + # header.history = clean_history_file(header.history) + + + +"""Control""" +save = 1 +header.warnings = 'neyY' +header.warnings = 'yY' +header.EXCLUDE_NODES = 0 +# header.siman_run = 0 +# header.copy_to_cluster_flag = 0 +# header.corenum = 5 +# header.schedule_system = 'SLURM' + + + +"""Start working""" +from SSHTools import SSHTools +# header.ssh_object = SSHTools() +# header.ssh_object.setup(user='Dmitry.Aksenov', host = '10.30.17.12', pkey = '/home/aksenov/.ssh/id_rsa') + + + + + + + + + + + + + +"""End working""" + + + + + + + + + +complete_run(header.close_run) + + + +if save: + write_database(calc, conv, varset, size_on_start) + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" +TODO: +исправить calc[id].path["output"] для U_ramping - вроде сделано + + +0) read_geometry(), Если переменная не найдена, то подставляется [None] - это не очень удобно и лучше сделать просто None. +1) read project_conf explicitly from here and not from header - maybe not needed. The values from project_conf can be needed everywhere in siman and header is universal file for siman +2) перенести настройки matplotlib из header в конкретные функции, которые строят графики +3) project_sets.update_sets(varset) нужно удалить, она остается пока для этого проекта + +4) inherit_option = continue и sequence_set совместно не тестировались! + +5) sequence_set and self.associated_outcars ???? + +!How to make tables and pictures more straightforward? +!How to make inheritance of last relaxed configuration more straightforward? - добавить возможность продолжения расчёта + +!Для нового проекта нужно подумать об объединении папки geo с исходными структурами и выходной папки; Лучше все что касается отдельного расчета хранить в одной папке, просто использовать разные имена для файлов или подпапки. + + +!Добавление нового атома подразумевает набор стандартных действий. Написать маленькую функцию для этого. Сейчас код подобной функции используется +в двух местах: внутри create_segregation_cases() и add_impurity().add() + + +!gbpos в самом старте определяется вручную для первой версии и просто копируется для других версий. + + +!make_incar_and_copy_all проверить magmom + + + +! В классе Structure() добавить методы: +удалить атом, добавить атом, заменить атом; +наследовать rprimd; растянуть; +потом с помощью этих методов упростить функции inherit_icalc и add_impurity + + +Changes to siman2; please move this section to siman2 folder. +1. latex_table() moved to functions.py + + +""" + diff --git a/project_template/project_conf.py b/project_template/project_conf.py new file mode 100644 index 0000000..869fcdc --- /dev/null +++ b/project_template/project_conf.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +""" +Control of project + +TODO: +cif2cell installation check or add to siman +""" +from __future__ import division, unicode_literals, absolute_import + +NEW_BATCH = True # for testing new batch system based on set sequences + +PBS_PROCS = True # if true than #PBS -l procs="+str(number_cores) is used +WALLTIME_LIMIT = True + +"""Cluster constants""" +# cluster_address = 'aksenov@10.30.16.62' # +# CLUSTER_ADDRESS = cluster_address +# cluster_home = '/home/aksenov/' # needed only for SLURM std out and std err +# CLUSTER_PYTHONPATH = '/usr/lib64/python2.7/site-packages/numpy' + +# SCHEDULE_SYSTEM = 'SLURM' #see write_batch_header() +# corenum = 16; #queue = ' -l cmmd ' +# CORENUM = corenum + +CLUSTERS = {} +DEFAULT_CLUSTER = 'cee' +PATH2PROJECT = '' # path to project on cluster relative to home folder +# project_path_cluster = '' +# PATH_TO_PROJECT_ON_CLUSTER = project_path_cluster + + +CLUSTERS['cee'] = {'address':'aksenov@10.30.16.62', +'vasp_com':'prun /opt/vasp/bin/vasp5.4.1MPI_aksenov', +# 'vasp_com':'prun /opt/vasp/bin/vasp5.4.1MPI_ncl', + +'homepath':'/home/aksenov/', +'schedule':'SLURM', +'corenum':16, +'pythonpath':'/usr/lib64/python2.7/site-packages/numpy' +} + +CLUSTERS['skol'] = {'address':'Dmitry.Aksenov@10.30.17.12', +'vasp_com':'mpirun vasp_std', +'homepath':'/home/Dmitry.Aksenov/', +'schedule':'PBS', +'corenum':16, +'pythonpath':'/usr/lib64/python2.7/site-packages/numpy' +} + +CLUSTERS['bsu'] = {'address':'aleksenov_d@95.167.109.79', +'vasp_com':'mpiexec --prefix /home/aleksenov_d/mpi/openmpi-1.6.3/installed vasp', +'homepath':'/home/aleksenov_d', +'schedule':'PBS', +'corenum':16, +'pythonpath':'/usr/lib64/python2.7/site-packages/numpy' +} + + + + + + +"""Local constants""" +PATH2POTENTIALS = '/home/aksenov/scientific_projects/PAW_PBE_VASP' +pmgkey = "AWqKPyV8EmTRlf1t" + +path_to_paper = '/home/aksenov/Research/CEStorage/aksenov_report/' +# PATH2DATABASE = '/home/aksenov/Data/CEStorage/_aksenov' +PATH2DATABASE = '/home/aksenov/Data/CEStorage/' +# gb4_geo_folder = '/home/dim/Simulation_wrapper/gb4/out/' +#we have gb5! +PATH2JMOL = 'jmol' +PATH2NEBMAKE = '~/Simulation_wrapper/vts/nebmake.pl' + +geo_folder = './' +# path_to_images = '/home/aksenov/ydisk/cathode_report/images/' +path_to_images = path_to_paper+'/fig/' +# path_to_jmol = '/home/dim/installed/jmol-14.2.12_2015.02.11/jmol.sh ' +path_to_wrapper = '/home/aksenov/Simulation_wrapper/' + +# RAMDISK = '/mnt/ramdisk/' +RAMDISK = None +EXCLUDE_NODES = 1 + + +"""List of constants determined during installation""" +CIF2CELL = True + + + + + + +"""List of manually added calculations:""" +MANUALLY_ADDED = [# calc name, calc folder, calc des + ( 'Li111' ,"Li", "2 Li" ), + ( 'Rb111' ,"Rb/bcc", "2 Rb" ), + ] + + + + + + + + + + + + + + + + + + + + +""" +Naming conventions: + +endings: +'_ml' - was used to show that this calculation uses manual equilibrium lattice determination and +contains several versions of identical structures with different +lattice constants. Now not in use, because I always use this method. Usually 16 versions for hcp; + +'_r' - calculation with structure constructed for fitted lattice constants; +Now was replaced with '.f'; Usually one version. +'.ur' - unrelaxed +.r - relaxed atomic positions +.o - optimised cell and volume and atomic positions automatically +'.f' - fitted +'.fr' - means that current calculation based on the structure for which lattice constants were fitted and +positions of atoms were relaxed. However see description to know for wich set they were fitted and relaxed. +Calculations with '.f' and '.fr' can have different versions which are correspondig to different sets. + +.m - only matrix, all impurities were removed and matrix was freezed + + +letters in name, wich are usually between didgits and element's names: +b - stands for bulk, which denote ideal cells without boundaries. +g - cells with grain boundary; +v - means that impurity is in the volume of grain; far away from boundaries; +i - means that impurity is close to interface plane (grain boundary) + +Versions: +20 - usually means that lattice constatns was used from other calculation and this is very good assumtion. + + +""" + + + diff --git a/project_template/project_sets.py b/project_template/project_sets.py new file mode 100644 index 0000000..14d43e5 --- /dev/null +++ b/project_template/project_sets.py @@ -0,0 +1,120 @@ + +import copy +# from header import * +import header +from set_functions import InputSet, inherit_iset, make_sets_for_conv, init_default_sets +""" +remove update_set() completly +""" + + +#1 - only volume; v isif = 5 +#2 - full relax; vsa +#8 - no relaxation; 0 +#9 - only atoms; a + + +#set_potential uses relative paths + +"""List of user VASP sets obtained on inheritance principle """ +"""Syntax: ("set_new", "set_old", {"param1":value1, "param2":value2, ...}) + - set_new - name of new set + - set_old - name of base set used for creating new set + - {} - dictionary of parameters to be updated in set_new + +""" + # Ueff::list(string=numeric):=["V"=3.1,"Cr"=3.5,"Mn"=3.9,"Fe"=4.0,"Co"=3.4,"Ni"=6.0,"Cu"=4.0,"Mo"=3.5,"Ag"=1.5] +dftu_packet = {'ISTART' :1, 'ICHARG':1, 'LDAUTYPE':2, 'LASPH':'.TRUE.', + 'LDAUPRINT':2, 'LMAXMIX' :4, 'LDAU' :'.TRUE.', + 'LDAUL':{'Ti':2, 'Co':2 , 'Fe':2 , 'Ni':2 , 'Mn':2 , 'V':2 , 'Cr':2 }, + 'LDAUU':{'Ti':0, 'Co':3.4, 'Fe':4.0, 'Ni':6.2, 'Mn':3.9, 'V':3.1 , 'Cr':3.5, 'Fe/S':1.9 }, + 'LDAUJ':{'Ti':0.0, 'Co':0.0, 'Fe':0.0, 'Ni':0.0, 'Mn':0.0, 'V':0.0 , 'Cr':0.0, 'Fe/S':0 } } # universal set, Jain2011 azh values, Ni from genome + +dftu_packet_off = {'LDAU' :None, 'LASPH':None, 'LDAUPRINT':None, 'LDAUTYPE':None, 'LDAUL':None, 'LDAUU':None, 'LDAUJ':None, } + +YBaCoO_dftu = {'LDAUU':{'Co':5}, 'LDAUJ':{'Co':0.8} } + +mag_packet = { + 'GGA_COMPAT': '.FALSE.', + 'ISPIN':2, + 'LORBIT':11, #more info + 'magnetic_moments':{'Ti':0.6, 'V':5, 'Fe':5, 'Co':5, 'Mn':5, 'Ni':5, 'Cr':5 } + +} + + +#hybrid packet +hse6_pack = {'ISTART':1, 'LHFCALC':'.TRUE.', 'HFSCREEN':0.2, 'add_nbands':1.1, 'ALGO':'All', 'TIME':0.4} +hse6_pack_low = hse6_pack.copy() +hse6_pack_low.update({'PRECFOCK':'Fast', 'NKRED':2}) + + +mix_mag_packet = {'AMIX':0.2, 'BMIX':0.00001, 'AMIX_MAG':0.8, 'BMIX_MAG':0.00001} #linear mixing fine +mix_mag_packet_fine = {'AMIX':0.1, 'BMIX':0.00001, 'AMIX_MAG':0.4, 'BMIX_MAG':0.00001} #even finer linear mixing + +ion_relax_packet = {'NSW':25, 'EDIFFG':-0.025, 'EDIFF':0.0001, 'ISIF':2} +static_run_packet = {'NSW':0, 'EDIFF' : 6e-06, 'NELM':50} +my_low_pack = {'KSPACING':0.3, 'ENCUT':400, 'ENAUG':400*1.75, 'POTIM':0.2, 'NELM':20, 'EDIFFG':-0.05 } +acc_pack = {'PREC':'Accurate', 'ADDGRID':'.TRUE.', 'EDIFF':6e-6, 'EDIFFG':-0.010, 'NSW':50, 'ISTART':1, 'ICHARG':0 } +acc_pack_relax = {'PREC':'Accurate', 'ADDGRID':'.TRUE.', 'EDIFF':6e-6, 'EDIFFG':-0.010, 'NSW':50, 'ISTART':1, 'ICHARG':0 } +acc_pack2_stat = {'PREC':'Accurate', 'ADDGRID':'.TRUE.', 'EDIFF':1e-8, 'LREAL':False, 'NSW':0, 'ISTART':1, 'ICHARG':0 } +acc_pack2_relax = {'PREC':'Accurate', 'ADDGRID':'.TRUE.', 'EDIFF':1e-8, 'LREAL':False, 'EDIFFG':-0.025, 'NSW':50, 'ISTART':1, 'ICHARG':0 } + + +dos_pack = {'NSW':0, 'LORBIT':12, 'ISMEAR':-5, 'SIGMA':None, 'LAECHG':'.TRUE.', 'EMIN':-10, 'EMAX':14, 'NEDOS':2000, 'KSPACING':0.15, 'savefile':'dox'} +bader_pack = {'PREC':'Accurate', 'ADDGRID':'.TRUE.', 'EDIFF':1e-08, 'LAECHG':'.TRUE.', 'NELM':100, 'savefile' : 'acox'} +surface_pack = {'AMIN':0.01, 'AMIX':0.2, 'BMIX':0.001, 'NELMIN':8, 'IDIPOL':3, 'LDIPOL':'.TRUE.'} # from pymatgen +# slab_incar["DIPOL"] = structure.center_of_mass # please consider + + + + +dos_pack2 = dos_pack.copy() +dos_pack3 = dos_pack.copy() +dos_pack3.update({'PREC':'Accurate', 'ADDGRID':'.TRUE.', 'EDIFF':6e-6, 'NELM':50, }) +# dos_pack2.update({83:'Bi_pv', 34:'Se'}) +mag_relax = mag_packet.copy() +mag_relax.update(ion_relax_packet) +# print mag_relax +sv_pot_pack = {'set_potential':{3:"Li_sv2", 8:"O", 9:"F", 11:'Na_sv', 37:'Rb_sv', 15:"P", 16:'S', 19:'K_sv', 22:"Ti_sv_new", 23:"V_sv_new", 25:"Mn_sv", 26:"Fe_sv", 27:"Co_sv" , 28:"Ni_pv", 33:'As_d' }} #except O_sv, which requires 1000 eV ecut at least +pot_pack = {'set_potential':{1:'H', 3:"Li", 5:'B', 6:'C', 8:"O", 9:"F", 11:'Na', 15:"P", 16:'S', 19:'K_pv', 22:"Ti", 23:"V", 24:'Cr', 25:"Mn", 26:"Fe", 27:"Co_new", 28:"Ni_new", 33:'As', 37:'Rb_pv', 39:'Y_sv', 56:'Ba_sv', 83:'Bi_pv', 34:'Se', } } +over = '' + +user_vasp_sets = [ +('8', 'static', {}), +('8','8',pot_pack,), +('9', '8', ion_relax_packet), +('8U', '8', dftu_packet ), +('8Um', '8U', mag_packet ), + + +] + + + + + + + + + + + + + + +# for phonons you should use: +# PREC = Accurate avoid wrap around errors +# LREAL = .FALSE. reciprocal space projection technique +# EDIFF = 1E-6 high accuracy required + + #May be useful +#For very accurate energy calculations: +#s.set_vaspp['ISMEAR'] = [-5, " Tetrahedron with Blochl corrections"] +#However this approach needs at least 3 kpoints and produce errors in stress tensor and forces + + # + + + + diff --git a/server_tools/make_database_cvs.py b/server_tools/make_database_cvs.py new file mode 100644 index 0000000..a4b7f30 --- /dev/null +++ b/server_tools/make_database_cvs.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 +from __future__ import division, unicode_literals, absolute_import, print_function +import sys, glob, os, json, pickle, re +from pathlib import Path +import numpy as np +sys.path.append('/home/aksenov/Simulation_wrapper/siman') #path to siman library +sys.path.append('siman') #path to siman library on sd cluster +from classes import CalculationVasp + +""" +NAME + create .cvs files from .pickle for web visualization + +SYNOPSIS + make_database_cvs.py path_to_database + +DESCRIPTION + + Walk through path_to_database, read pickle in Calculation objects and create + required cvs files. + +REQUIRE + numpy, siman + +AUTHOR + Aksyonov Dmitry, Skoltech, Moscow + +""" + +__author__ = "Aksyonov Dmitry" +__copyright__ = "Copyright 2017, Skoltech" +__version__ = "0.1" +__maintainer__ = "Aksyonov Dmitry" +__email__ = "dimonaks@gmail.com" +__status__ = "alpha" +__date__ = "" + + +path2database = sys.argv[1] + + +os.chdir(path2database) + + +csv = [] + +if 1: + + with open('hash_dict.json') as fp: + hash_dict = json.load(fp) + # print(hash_dict) + + for pickle_file in hash_dict: + # pickle_fileP = Path(pickle_file+'.pickle') + pickle_fileP = Path(pickle_file) + row = {'path':pickle_file} + if pickle_fileP.is_file(): + with pickle_fileP.open('rb') as f: + cl = pickle.load(f) + # a = cl.read_results() + # print(a ) + try: + row['name'] = cl.name + row['energy'] = '{:.3f}'.format(cl.energy_sigma0) + row['energy_at'] = '{:.3f}'.format(cl.energy_sigma0/cl.end.natom) + row['status'] = 'OK' + row['spg'] = cl.end.get_space_group_info()[0] + row['nat'] = cl.end.natom + row['vol'] = cl.end.vol + except: + row['status'] = 'broken pickle file' + + # print (pickle_fileP.name.split('_')[0]) + c = pickle_fileP.name.split('_')[0] + print(c) + c = re.sub('\D', '', c) # replace any non-digit character with '' + if c: + c = int(c) + if c == 1: + c *= 100 + else: + c = None + row['conc'] = c + + + else: + row['status'] = 'no pickle file' + + csv.append(row) + import pandas as pd + df = pd.DataFrame(csv, columns = ['name', 'spg', 'conc', 'energy_at', 'nat', 'vol', 'path', 'status']) + + # df['nat'] = df['nat'].apply(np.int64) + + + df = df.rename(columns = {'name':'Name', 'spg':'Group', 'conc':'X, %', 'energy_at':'E, eV/at', 'nat':'Nsites', 'vol':'Vol (A3)', 'path':'path', 'status':'status'}) + # print(df) + df.to_csv('database1.csv') diff --git a/server_tools/make_database_hash.py b/server_tools/make_database_hash.py new file mode 100644 index 0000000..50c7fb9 --- /dev/null +++ b/server_tools/make_database_hash.py @@ -0,0 +1,78 @@ +#!/usr/bin/python3 +from __future__ import division, unicode_literals, absolute_import, print_function +import sys, glob, os, json +sys.path.append('/home/aksenov/Simulation_wrapper/siman') #path to siman library +sys.path.append('siman') #path to siman library +from classes import CalculationVasp + +""" +NAME + make_database_hash.py - serialize all found .out vasp files into .pickle + +SYNOPSIS + make_database_hash.py path_to_database + +DESCRIPTION + + Walk through path_to_database, read VASP outcars in Calculation objects and serialize them + for futher fast access in pickle files. + Save dictionary hash_dict.json with paths for accessing them later + +REQUIRE + numpy, siman + +AUTHOR + Aksyonov Dmitry, Skoltech, Moscow + +""" + +__author__ = "Aksyonov Dmitry" +__copyright__ = "Copyright 2016, Skoltech" +__version__ = "0.1" +__maintainer__ = "Aksyonov Dmitry" +__email__ = "dimonaks@gmail.com" +__status__ = "alpha" +__date__ = "" + + +path2database = sys.argv[1] + + +os.chdir(path2database) + +if 1: + walk = os.walk(path2database) + materials = next(walk)[1] + # print(materials) + hash_dict = {} + for mat in walk: + for outcar in mat[2]: + if '.out' in outcar: + mat_folder = os.path.relpath(mat[0], path2database) + # print(mat_folder) + + iid = outcar.replace('.out', '') + + pickle_file = os.path.join(mat_folder, 'bin', iid) + if not os.path.isfile(pickle_file+'.pickle'): + cl = CalculationVasp(output = os.path.join(mat_folder, outcar ) ) + # print(cl.path['output']) + cl.read_results() + # material = os.path.basename(mat_folder) + # print(mat_folder, material) + material = mat_folder.split('/')[0] + # print(mat_folder.split('/')[0]) + cl.name = material + + print(pickle_file) + pickle_file = cl.serialize(os.path.join(mat_folder, 'bin', iid) ) + else: + print('pickle file', pickle_file, 'exist') + # concentr = outcar.split('_')[0] + # hash_dict[material+'_'+iid] = pickle_file + hash_dict[pickle_file] = pickle_file + # print(hash_dict) + + with open('hash_dict.json', 'w') as fp: + json.dump(hash_dict, fp, indent=4) + diff --git a/server_tools/read_calculation.py b/server_tools/read_calculation.py new file mode 100644 index 0000000..f5ee47b --- /dev/null +++ b/server_tools/read_calculation.py @@ -0,0 +1,40 @@ +#!/usr/bin/python3 +""" +read_calculation.py by Aksyonov Dmitry, Skoltech, Moscow + + +""" +import cgitb, cgi +cgitb.enable() +print('Content-type: text/html\n\n') + +import sys +sys.path.extend(['/home/aksenov/www/siman']) +from classes import CalculationVasp +from analysis import calc_redox + +db_path = '/home/aksenov/www/CES/' + +form = cgi.FieldStorage() + +# Get data from fields +string = form.getvalue('param') +string = string.replace('"', '') +files = string.split() + + +cl1 = CalculationVasp().deserialize(db_path+files[0]) +cl2 = CalculationVasp().deserialize(db_path+files[1]) + +# output = cl1.energy_sigma0 +output = calc_redox(cl1, cl2)['redox_pot'] + +# print(output, 'V') + + +# sys.stdout.write(str(output) ) +# sys.stdout.flush() +sys.exit(0) + + + diff --git a/set_functions.py b/set_functions.py index aa7a733..596f42e 100755 --- a/set_functions.py +++ b/set_functions.py @@ -116,7 +116,12 @@ 'IDIPOL', 'LDIPOL', 'DIPOL', -'LVTOT' +'LVTOT', +'TEBEG', +'LSOL', +'EB_K', +'LAMBDA_D_K', +'CORE_C' ] vasp_keys = vasp_electronic_keys+vasp_ionic_keys+vasp_other_keys diff --git a/small_functions.py b/small_functions.py index ad603c6..9f23ccd 100644 --- a/small_functions.py +++ b/small_functions.py @@ -1,14 +1,25 @@ #Copyright Aksyonov D.A from __future__ import division, unicode_literals, absolute_import -import os, math, re +import os, math, re, sys import numpy as np from six import string_types from collections import Iterable import shutil, gzip +import traceback from header import printlog + + +class TracePrints(object): + def __init__(self): + self.stdout = sys.stdout + def write(self, s): + self.stdout.write("Writing %r\n" % s) + traceback.print_stack(file=self.stdout) + + def angle(v1, v2): return math.acos(np.dot(v1, v2) / (np.linalg.norm(v1) * np.linalg.norm(v2))) / math.pi * 180 diff --git a/tutorials/Configure.ipynb b/tutorials/Configure.ipynb index 79caf58..a12dbe0 100644 --- a/tutorials/Configure.ipynb +++ b/tutorials/Configure.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:c2b8f74c3fcf2d06349ca03e41fba8a4af62d3dc9bc251a21b97c9b0eeb48429" + "signature": "sha256:443892cd776f9de1ef7d55829a60f6c3a1ae1169187dd95cdb26451b04b9efcd" }, "nbformat": 3, "nbformat_minor": 0, @@ -20,7 +20,13 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Configuration is provided in \"siman/default_project_conf.py\" file. Open it." + "You can use siman in IPython as shown in futher tutorials. \n", + "However, in our opinion it is more convinient to use Advanced code editor. We use Sublime Text 3. It has many cool features, including building the project right from your window with code.\n", + "\n", + "If you choose the latter case we suggest to download this [project template](https://github.com/dimonaks/siman/tree/master/project_template). It contains three python files. In main.py you make all your calculations. In project_conf.py you put all your control parameters. In project_sets.py you create new calculation sets. \n", + "\n", + "\n", + "Global configuration can be provided in \"siman/default_project_conf.py\" file, which is similar to project_conf.py. However, be careful not to overwrite it during update. The issue will be resolved." ] }, { @@ -28,13 +34,14 @@ "level": 2, "metadata": {}, "source": [ - "1. Configuration of cluster" + "1. Description of project_conf.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ + "###Cluster description\n", "Find the code below and provide your address, your homepath, your schedule system (from 'PBS', 'SLURM', SGE),\n", "number of cores, path to python (optional), and vasp_command - path to vasp binary on cluster" ] @@ -50,7 +57,10 @@ "'corenum':16,\n", "'pythonpath':'/usr/lib64/python2.7/site-packages/numpy',\n", "'vasp_com':'prun /opt/vasp/bin/vasp5.4.1MPI', # path to vasp binary\n", - "}" + "#optional parameters:\n", + "'sshpath':True # use sshpath in rsync commands \n", + "}\n", + "\n" ], "language": "python", "metadata": {}, @@ -66,29 +76,26 @@ ] }, { - "cell_type": "heading", - "level": 2, + "cell_type": "markdown", "metadata": {}, "source": [ - "2. Path to potentials" + "###Required parameters:\n", + "DEFAULT_CLUSTER = 'cee' # key from CLUSTERS dictionary described above\n", + "\n", + "PATH2PROJECT = '' # path to project on cluster relative to home folder\n", + "\n", + "PATH2POTENTIALS = '/path/to/potentials' # path to folder with VASP potentials on local machine\n", + "###Optional parameters:\n", + "PATH2ARCHIVE = '/storage/amg/aksenov/' # additional folder on cluster used as a copy of calculations (e.g. storage of charge density, wavefunctions)\n" ] }, { - "cell_type": "markdown", + "cell_type": "heading", + "level": 2, "metadata": {}, "source": [ - "Change the following string, which is the path to folder with VASP potentials" + "2. Description of project_sets.py" ] - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "PATH2POTENTIALS = '/home/aksenov/scientific_projects/PAW_PBE_VASP'" - ], - "language": "python", - "metadata": {}, - "outputs": [] } ], "metadata": {} diff --git a/tutorials/FAQ.ipynb b/tutorials/FAQ.ipynb index 17fb632..a72eddd 100644 --- a/tutorials/FAQ.ipynb +++ b/tutorials/FAQ.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:d918259dbef5885906fcdb73d5e3f76360755c38c423deda0e4a64268826c9ad" + "signature": "sha256:e26062e09247697ac885e671317358ae2b73456a12099101c63b3f0471a68860" }, "nbformat": 3, "nbformat_minor": 0, @@ -67,7 +67,11 @@ "collapsed": false, "input": [ "res_loop(show = 'smag') # show sum of all magnetic moments (and augmentation part) at each relaxation step\n", - "res_loop(show = 'conv') # show convergence at each MD step" + "res_loop(show = 'conv') # show convergence at each MD step\n", + "res_loop(show = 'en') # show energy vs max. force plot\n", + "res_loop(show = 'path') # show path to calculation folder\n", + "res_loop(show = 'pos') # write poscar for last structure\n", + "cl.end.jmol() or cl.jmol() # run jmol and show the structure" ], "language": "python", "metadata": {}, @@ -91,6 +95,25 @@ "language": "python", "metadata": {}, "outputs": [] + }, + { + "cell_type": "heading", + "level": 2, + "metadata": {}, + "source": [ + "5. Main control parameters in project_conf.py" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "check_job = 0 or 1 # whether to check job status, set to 0 for slow connections" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 1 } ], "metadata": {} diff --git a/tutorials/create_vasp_calculation.ipynb b/tutorials/create_vasp_calculation.ipynb index 25c1110..11dc911 100644 --- a/tutorials/create_vasp_calculation.ipynb +++ b/tutorials/create_vasp_calculation.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:97126c9dbbd1e1781dbc3be5fb4ce7ed564aa7a67aa226273dbcc1fab1d87481" + "signature": "sha256:5040e4910d3d00c1ad2b52c49e6e6f373c2571a276074f16f0cf7ea7a57d4d2f" }, "nbformat": 3, "nbformat_minor": 0, @@ -38,6 +38,7 @@ "from calc_manage import add_loop, res_loop\n", "from database import write_database, read_database\n", "from set_functions import read_vasp_sets\n", + "from calc_manage import smart_structure_read\n", "%matplotlib inline" ], "language": "python", @@ -99,6 +100,25 @@ "outputs": [], "prompt_number": 2 }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "or using structure explicitly" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "st = smart_structure_read(input_geo_file = 'Bi2Se3_mp-541837_computed.POSCAR')\n", + "\n", + "add_loop('Bi2Se3', 'static', 1, input_st = st, it_folder = 'Bi2Se3', run = 0)" + ], + "language": "python", + "metadata": {}, + "outputs": [] + }, { "cell_type": "markdown", "metadata": {}, @@ -302,7 +322,10 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "###Optimize cell volume" + "###Optimize cell volume\n", + "Make sure that ~/tools/fit_tool.py is on cluster;\n", + "\n", + "siman/cluster_tools/fit_tool.py " ] }, { diff --git a/workflow_utilities.py b/workflow_utilities.py index 896e275..a8bb80e 100644 --- a/workflow_utilities.py +++ b/workflow_utilities.py @@ -9,7 +9,7 @@ import header from header import print_and_log as printlog -from header import calc, db +from header import calc, db, struct_des from picture_functions import fit_and_plot from small_functions import merge_dics from calc_manage import add_loop, name_mod_supercell, res_loop, inherit_icalc, push_figure_to_archive @@ -17,9 +17,10 @@ from classes import Calculation from analysis import calc_redox, matrix_diff from geo import create_deintercalated_structure -from geo import remove_one_atom +from geo import remove_one_atom, replic, local_surrounding from geo import create_replaced_structure, create_antisite_defect3, determine_symmetry_positions, image_distance -from inout import write_occmatrix +from inout import write_occmatrix, write_xyz +from functions import invert @@ -57,7 +58,7 @@ def prepare(it_new, opt_vol, it_folder, ise, cl, st_type, option): def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, opt_vol = 0, suf = '', it_folder = None, el_rep = '', pos_rep = 1, pos_rep2 = None, polaron_pos = None, occ_matrix = None, - up = 0, fit = 0, outcar = None, only_read = 0, + up = 0, fit = 0, outcar = None, only_read = 0, Eref = 0, compat1 = False, add_loop_arg = {}): """ Function allow to create point defects and run them @@ -70,10 +71,12 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, option - 'vac' - make vacancy - 'rep' - replace one atom with Ti, was used for V-Ti project + 'rep' - replace one atom with 'el_rep', 'pair' - make vacancy -Ti complex for V-Ti project pos - unique position of el if non-eqivalent atoms exist - for vac + pos_rep - number of position to replace from 0 + ise - new set opt_vol (bool) - optimize volume @@ -90,6 +93,8 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, compat1 - compatability with previous calculations, which were used for Na2FePO4F project + Eref - reference energy for solution energy + TODO: rename to ?_point_defects() """ @@ -117,7 +122,7 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, it_new = cl.id[0].replace('su', 'vac')+str(pos) id_new, st, it_folder = prepare(it_new, opt_vol, it_folder, ise, cl, st_type, option) - + occfile = None if not only_read and (up or id_new not in calc): # it_new @@ -132,6 +137,7 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, i_tr = st.get_transition_elements(fmt = 'n') # dist = [] max_d = 0 + i_max_d = None for i in i_tr: d1, d2 = image_distance(st.xcart[i], st.xcart[i_del], st.rprimd) # print(i+1, d1, d2) @@ -139,8 +145,8 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, if d1 > max_d: max_d = d1 i_max_d = i - - print('The longest distance to transition metal in current supercell is ', max_d, 'A for atom', i_max_d+1, st.get_elements()[i_max_d]) + if i_max_d is not None: + print('The longest distance to transition metal in current supercell is ', max_d, 'A for atom', i_max_d+1, st.get_elements()[i_max_d]) numb = st.nn(i_del, from_one = 0, n = len(tr)+5, only = list(set(tr)))['numbers'][1:] @@ -165,10 +171,10 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, elif 'rep' in option: - st_del1 = st.replace_atoms([pos_rep], el) - print('Atom', str(pos_rep),st.get_elements()[pos_rep],' replaced with', el, ) + st_del1 = st.replace_atoms([pos_rep], el_rep) + print('Atom', str(pos_rep),st.get_elements()[pos_rep],' replaced with', el_rep, ) print(st_del1.get_elements()[pos_rep]) - st_del1.name+=it_new + st_del1.name=it_new elif 'pair' in option: st_del1 = st.replace_atoms([1], el_rep) @@ -177,7 +183,7 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, st_del1 = remove_one_atom(st_del1, el, pos) print('Atom 1 replaced with', el,'and atom removed' ) - st_del1.name+=it_new + st_del1.name=it_new st_del1.write_xyz() @@ -216,12 +222,14 @@ def make_defect(cl, el, st_type = 'end', option = 'vac', pos = None, ise = None, if option == 'vac': + cl_v.res() + cl.res() print('Evac = {:3.2f} eV'.format(cl_v.e0 - cl.e0/cl.end.natom*cl_v.end.natom)) elif option == 'rep': diffE, diffV = matrix_diff(cl_v, cl) - print('Esol = {:3.2f} eV'.format(diffE)) + print('Esol = {:3.2f} eV'.format(diffE - Eref)) elif 'pair' in option: '' @@ -320,3 +328,225 @@ def process_modified(cl, mod_dic = None, scale_region = (-4,4), opt_vol = 1, fit res_loop(*id_new, up = '1', choose_outcar = None, show = 'fo') return + + + + + +def create_segregation_cases(it, ise, verlist, dist_gb, gbpos = None, ise_new = None, option = None, + precip_folder = None, use_init = False, precision = None): + """ + Written for Ti-Fe project. + Allows to create segregation by substituting atoms; + dist_gb - distance from gb inside which the atoms are included + + + option = 'precip'- adding additional impurities to the already existing at gb. Please use 'precip_folder' + use_init - allows to use initial structure. + + + !Warning PBC are not used in determination of seg positions + + """ + + + # hstring = ("%s #on %s"% (traceback.extract_stack(None, 2)[0][3], datetime.date.today() ) ) + # try: + # if hstring != header.history[-1]: header.history.append( hstring ) + # except: + # header.history.append( hstring ) + def write_local(cl, it_new, it_new_path, el_sub, main_path ): + cl.version = v + # it_new_path + + cl.name = it_new + cl.des = 'Obtained from end state of '+str((it, ise, v))+' by substitution of one atom near gb with '+el_sub+' impurity ' + path_new_geo = it_new_path+"/"+it_new+"/"+it_new+'.imp.'+el_sub+'.'+str(cl.version)+'.'+'geo' + cl.init.name = it_new+".init."+str(cl.version) + xyzpath = it_new_path+"/"+it_new + cl.path["input_geo"] = path_new_geo + print(path_new_geo) + cl.write_geometry("init", cl.des, override = 1) + write_xyz(cl.init, xyzpath) + return it_new_path + + if 0: + res_loop(it, ise, verlist, up = 0) + + cl = header.calc[(it, ise, verlist[0])] + + znucl_sub = 3 #atom to be added + + + """1. Create list of atoms near gb to substitue""" + cl.gbpos = gbpos + # print cl.gbpos + seg_pos_list = [] # numbers of segregation positions + + if use_init: + st = cl.init + else: + st = cl.end + + + + for i, x in enumerate(st.xcart): + z_cur = st.znucl[st.typat[i]-1] + print ('z_cur', z_cur) + if z_cur == znucl_sub: + print_and_log('Skipping znucl_sub atom\n') + continue + if abs(x[0] - gbpos)< dist_gb: + print('adding possible seg position') + seg_pos_list.append(i) + + + """2. Substitue""" + el_sub = invert(znucl_sub) + base_name = it + main_path = struct_des[it].sfolder + based_on = it+'.'+ise + des_list = [] + add_list = [] + + cl_list = [] + sumr_list = [] + + i = 0 + for j, replace_atom in enumerate(seg_pos_list): # + + v = verlist[0] # the first version from list is used + cl = calc[(it, ise, v)] + cl.gbpos = gbpos + + new = copy.deepcopy(cl) + if use_init: + new.end = new.init + else: + new.init = new.end #replace init structure by the end structure + + if 1: #atom substitution !make function; see TODO + + if znucl_sub not in new.init.znucl: + new.init.znucl.append(znucl_sub) + new.init.ntypat+=1 + new.init.typat[replace_atom] = new.init.ntypat + else: + ind = new.init.znucl.index(znucl_sub) + new.init.typat[replace_atom] = ind + 1 + new.init.nznucl = [] + for typ in range(1, new.init.ntypat+1): + new.init.nznucl.append(new.init.typat.count(typ) ) + printlog("Impurity with Z="+str(znucl_sub)+" has been substituted in "+new.name+"\n\n") + + it_new = base_name+el_sub+'is'+str(i+1) #interface substitution + + if option == 'precip': + it_new_path = precip_folder + + else: + it_new_path = main_path+'/'+base_name+'_segreg' + + + #Check if configuration is unique + add = 1 + # for cl in cl_list: + st = new.end + st_replic = replic(st, (2,2,2)) + st_replic = replic(st_replic, (2,2,2), -1) #replic in negative direction also + sumr = local_surrounding(st.xcart[replace_atom], st_replic, n_neighbours = 6) # sum of distances to surrounding atoms + print ("sumr", sumr) + for ad_sumr in sumr_list: + if abs(ad_sumr-sumr) < precision : + add = 0 + printlog("The void is non-equivalent; skipping\n") + + + if add: + i+=1 + sumr_list.append(sumr) + # cl_list.append(new) + write_local(new, it_new, it_new_path, el_sub, main_path) + for v in verlist[1:]: #write files; versions are scaled + cl = calc[(it, ise, v)] + rprimd_scaled = cl.end.rprimd + new_scaled = copy.deepcopy(new) + new_scaled.init.rprimd = copy.deepcopy(rprimd_scaled) + new_scaled.init.xred2xcart() + write_local(new_scaled, it_new, it_new_path, el_sub, main_path) + #create names + des_list.append( "struct_des['{0:s}'] = des('{1:s}', 'segregation configurations; made from {2:s}' )".format(it_new, it_new_path, based_on) ) + add_list.append( "add_loop('"+it_new+"','"+ise_new+"',"+"range(1,6)"+", up = 'up1', it_folder = '"+it_new_path+"')" ) + + + + + for d in des_list: + print (d) + + + for d in add_list: + print (d) + + + + return + + + + +def optimize_wrapper(cl, ise, add = 0, show_fit = 1): + #wrapper for optimization function + + + up_res = 'up1' + readfiles = 1 + check_job = 1 + id_res = (cl.id[0]+'.su', ise, 100) + + if add: + add_loop(*cl.id, ise_new = ise, up = 'up1', calc_method = 'uniform_scale', + scale_region = (-4, 4), input_st = cl.end, show = '', run = 0, inherit_option = 'inherit_xred', + it_folder = cl.sfolder+'/scaled/') + else: + + if show_fit: + res_loop(*id_res[0:2],list(range(0+1,0+8))+[100], up = up_res, readfiles= readfiles, analys_type = 'fit_a', show = 'fitfo') + else: + res_loop(*id_res, up = up_res, show = 'fo', check_job = check_job) + + + + +def run_wrapper(sts, ise = None, add = 0, cl = None, suf = 'w', it_folder = None, ngkpt = None, acc = None, ise1= None, acc2 = None, ise2 = None): + """ + Add Several structures + """ + folder = suf.replace('.', '') + # print(folder) + # sys.exit() + if ise1 is None: + ise1 = ise + + for i, st in enumerate(sts): + + itn = cl.id[0]+suf+ str(i) + # del header.struct_des[itn] + # continue + if add: + add_loop(itn, ise, 1, show = 'fo', up = 'up2', input_st = st, ngkpt = ngkpt, it_folder = cl.sfolder+'/'+folder+'/', ) # + else: + '' + + if acc: + if acc2: + db[itn+'.ifc', ise, 1].run(ise2, show = 'fo', iopt = 'full_chg', add = 0) + + else: + db[itn, ise, 1].run(ise1, show = 'fo', iopt = 'full_chg', add = 0, ngkpt = ngkpt) + else: + res_loop(itn, ise, 1, up = 'up2') + + + + return \ No newline at end of file From 1256da1f6d44c589c7a06b2f4cc2daf9350c0ccd Mon Sep 17 00:00:00 2001 From: BinaryBeaver <38048677+BinaryBeaver@users.noreply.github.com> Date: Mon, 2 Jul 2018 22:08:10 +0300 Subject: [PATCH 2/2] neb # --- neb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neb.py b/neb.py index cb10472..2c2440c 100644 --- a/neb.py +++ b/neb.py @@ -13,10 +13,10 @@ from small_functions import is_list_like, makedir from classes import CalculationVasp, cd -# from impurity import find_pores +from impurity import find_pores from tabulate import tabulate from geo import xcart2xred, xred2xcart, local_surrounding, replic, determine_symmetry_positions -# from impurity import determine_voids, determine_unique_voids +from impurity import determine_voids, determine_unique_voids