Exemple #1
0
    def download(file, to_file):

        if header.ssh_object:

            exist = file_exists_on_server(file, addr)
            # try:
            if exist:
                printlog('Using paramiko: ssh_object.get(): from  to ', file,
                         to_file)
                header.ssh_object.get(file, to_file)
                out = ''
            # except FileNotFoundError:
            else:
                out = 'file not found'

        else:
            # print(addr,file,to_file)
            out = runBash('rsync -uaz  ' + addr + ':' + file + ' ' + to_file)

        if 'error' in out:
            res = out
        else:
            res = 'OK'
            out = ''

        printlog('Download result is ', res)

        return out
Exemple #2
0
def gunzip_file(filename):
    printlog('unzipping file', filename)
    with open(filename.replace('.gz', ''), 'wb') as f_out:
        with gzip.open(filename, 'rb') as f_in:
            shutil.copyfileobj(f_in, f_out)

    return
Exemple #3
0
def find_moving_atom(st1, st2):
    """
    find moving atom

    The cells should have the same rprimd!



    return number of atom which moves between two cell
    """

    for r1, r2 in zip(st1.rprimd, st2.rprimd):
        if np.linalg.norm(r1 - r2) > 0.001:
            printlog(
                'Attention! find_moving_atom(): st1 and st2 have different rprimd'
            )

    st1 = st1.return_atoms_to_cell()
    st2 = st2.return_atoms_to_cell()

    # diffv = np.array(st1.xcart) - np.array(st2.xcart)
    # diffn = np.linalg.norm(diffv, axis = 1)

    diffn = []
    for x1, x2 in zip(st1.xcart, st2.xcart):
        d1, d2 = image_distance(x1, x2, st1.rprimd)
        diffn.append(d1)

    # print('max', max(diffn))

    return np.argmax(diffn)  # number of atom moving along the path
Exemple #4
0
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:
        bash_comm = 'ssh ' + addr + ' "' + command + '"'
        # print(bash_comm)
        out = runBash(bash_comm)

    out = out.split('#')[-1].strip()

    printlog(out)
    # sys.exit()

    return out
Exemple #5
0
def push_to_server(files = None, to = None,  addr = None):
    """
    if header.ssh_object then use paramiko
    to (str)     - path to remote folder ! 
    """
    if not is_list_like(files):
        files = [files]    
    
    to = to.replace('\\', '/') # make sure is POSIX

    files_str = ' '.join(np.array(files ))

    printlog('push_to_server(): uploading files ', files, 'to', addr, to)
    
    command = ' mkdir -p {:}'.format( to )

    run_on_server(command, addr)


    if header.ssh_object:
        for file in files:
            # print(file, to)
            header.ssh_object.put(file,  to+'/'+os.path.basename(file) )
        out = ''
    else:
        out = runBash('rsync -uaz  '+files_str+ ' '+addr+':'+to)
    
    printlog(out)



    return out 
Exemple #6
0
def write_occmatrix(occs, folder):
    #create OCCMATRIX

    makedir(folder)
    printlog('I create OCCMATRIX in ', folder, imp='y')
    filename = folder + '/OCCMATRIX'
    with open(filename, 'w', newline='') as f:
        numat = len(occs)
        f.write(str(numat) + '  #num of atoms to be specified\n')

        at_nums = occs.keys()
        at_spin = []  # # 2 or 1
        at_ltyp = []  # l - orbital type, 1 - s, 2 - d, 3 - f
        for key in occs:
            occ = occs[key]
            if len(occ) == 10:  # spin polarized, d orbital
                at_spin.append(2)
                at_ltyp.append(2)
            else:
                raise RuntimeError  # please write by yourself for other cases

        for i, l, s in zip(at_nums, at_spin, at_ltyp):

            f.write(list2string([i + 1, l, s]) + '    #i, l, s\n')
            # for sp in range(s):
            f.write('spin 1\n')
            for row in occs[i][0:len(occs[i]) // s]:
                f.write(list2string(row) + '\n')
            if s == 2:
                f.write('spin 2\n')
                for row in occs[i][len(occs[i]) // s:]:
                    f.write(list2string(row) + '\n')
            f.write('\n')
    return filename
Exemple #7
0
def determine_symmetry_positions(st, element):
    """
    determine non-equivalent positions for atoms of type *element*

    element (str) - name of element, for example Li

    return list of lists -  atom numbers for each non-equivalent position
    """

    from pymatgen.symmetry.analyzer import SpacegroupAnalyzer


    stp = st.convert2pymatgen()

    spg = SpacegroupAnalyzer(stp)

    info = spg.get_symmetry_dataset()

    positions = {}
    for i, (el, pos) in enumerate(zip(st.get_elements(), info['equivalent_atoms'])):
        
        if el == element and pos not in positions:
            positions[pos] = []

        if el == element:
            positions[pos].append(i)


    printlog('I have found ', len(positions), 'non-equivalent positions for', element, ':',positions.keys(), imp = 'y', end = '\n')
    printlog('Atom numbers: ', positions, imp = 'y')
    
    sorted_keys = sorted(list(positions.keys()))
    pos_lists = [positions[key] for key in sorted_keys ]

    return pos_lists
Exemple #8
0
def insert_atom(
    st,
    el,
    i_void=None,
    r_imp=1.6,
):
    """Simple Wrapper for inserting atoms """

    r_impurity = r_imp
    st_pores, sums, avds = determine_voids(st, r_impurity)

    insert_positions = determine_unique_voids(st_pores, sums, avds)

    printlog('To continue please choose *i_void* from the list above', imp='y')
    if i_void == None:
        sys.exit()

    # st.name = st.name.split('+')[0]

    xc = insert_positions[i_void]

    st_new, i_add = st.add_atoms([xc], el, return_ins=True)

    st_new.name += '+' + el + str(i_void)
    st_new.des += ';Atom ' + el + ' added to ' + str(xc)
    printlog(st.des, imp='y')

    st_new.write_xyz()
    st_new.magmom = [None]

    return st_new, i_add
Exemple #9
0
def gunzip_file(filename):
    printlog('unzipping file', filename)
    with open(filename.replace('.gz', ''), 'wb') as f_out:
        with gzip.open(filename, 'rb') as f_in:
            shutil.copyfileobj(f_in, f_out)

    return
Exemple #10
0
def remove_atoms(st, atoms_to_remove):
    """
    remove atoms either of types provided in *atoms_to_remove* or having numbers provided in *atoms_to_remove*
    st (Structure)
    atoms_to_remove (list) - list of str or int

    """
    st = copy.deepcopy(st)
    numbers = list(range(st.natom))


    atom_exsist = True

    while atom_exsist:

        for i, (n, el) in enumerate(  zip(numbers, st.get_elements()) ):
            # print(i)
            
            if el in atoms_to_remove or n in atoms_to_remove:
                # print(n)
                # atoms_to_remove.remove(i)
                st = st.del_atom(i)
                del numbers[i]

                break
        else:
            atom_exsist = False
    printlog('remove_atoms(): Atoms', atoms_to_remove, 'were removed')

    # print(st.get_elements())
    return st
Exemple #11
0
    def download(file, to_file):

        if header.ssh_object:

            exist = file_exists_on_server(file, addr)
            # try:
            if exist:
                printlog('Using paramiko: ssh_object.get(): from  to ', file, to_file)
                header.ssh_object.get(file,  to_file  )
                out = ''
            # except FileNotFoundError:
            else:
                out = 'file not found'

        else:
            out = runBash('rsync -uaz  '+addr+':'+file+ ' '+to_file)

        if out:
            res = out
        else:
            res = 'OK'

        printlog('Download result is ', res)

        return out
Exemple #12
0
def chgsum(cll, el, site, silent = 1):
    """
    calculate sum of Bader charges for particular atoms
    """


    for cl in cll:
        # print(cl.id, end = '  ')

        try:
            cl.chgsum[(el, site)] = 0
        except:
            pass
        if not hasattr(cl, 'charges') or len(cl.charges) == 0:
            cl.get_bader_ACF()
        # determine_symmetry_positions(cl.end, el, silent = 0)

    # print('')
    try:
        pos = determine_symmetry_positions(cll[0].end, el, silent = 1)
    except:
        printlog('chgsum() Warning!', cll[0].id, 'is broken!')
        return 0

    for p in pos[site]:
        ''
        for cl in cll:
            if not hasattr(cl, 'chgsum'):
                cl.chgsum = {}
                cl.chgsum[(el, site)] = 0

            cl.chgsum[(el, site)] += cl.charges[p]
        
            # print('{:5.3f}'.format(cl.charges[p]), end = '  ')
        # print('')
    if not silent:
        print('Sum of charges for ', el+str(site+1), ':')
    

    el_ind = cl.init.znucl.index(invert(el)) # index of element in znucl and zval and nznucl
    zval = cl.init.zval[el_ind] # number of electrons in chosen potential

    for cl in cll:
        cl.chgsum[(el, site)]/=len(pos[site])
        
        chgsum = zval - cl.chgsum[(el, site)]



        if cl == cll[0]:
            chgsum_ref = chgsum
        if not silent:

            print('{:5.2f}({:4.2f})'.format(chgsum, chgsum_ref-chgsum), end = '  ')
    if not silent:
        print('\n')

    # print(cl.charges)
    return chgsum
Exemple #13
0
    def printme(self):
        for key in self.vasp_params:
            if self.vasp_params[key] == None: continue
            print_and_log( "{:30s} = {:s} ".format("s.vasp_params['"+key+"']", str(self.vasp_params[key]) ), imp = 'Y', end = '\n' )

        printlog('ngkpt:', self.ngkpt, imp = 'Y')

        printlog('POTDIR:', self.potdir, imp = 'Y', end = '\n' )
Exemple #14
0
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
Exemple #15
0
def det_gravity(dos, Erange = (-100, 0)):
    """Determine center of gravity for DOS and return values of energy for d6 orbitals in list
    INPUT:
    dos - ase dos type with added d6 - sum of d orbitals over neighbors to impurity atoms
    Erange - window of energy to determine center of gravity
    """
    sum_dos_E = {}
    sum_dos   = {}
    sum_dos['d6'] = 0
    sum_dos_E['d6'] = 0

    for i, E in enumerate(dos.energy):
        if E < Erange[0]: continue
        if E > Erange[1]: break
        sum_dos['d6']   += dos.d6[i] 
        sum_dos_E['d6'] += dos.d6[i]*E 

    d6_gc = sum_dos_E['d6']/sum_dos['d6']

    if 0: #old
        nn =13
        sum_dos_E = [0 for i in range(nn)]
        sum_dos = [0 for i in range(nn)]

        i=-1
        for E in st.dos[0]:

            i+=1
            if E < -6: continue
            if E >0: break
            l = 1 #s
            sum_dos_E[l] += st.dos[l][i] * E; sum_dos[l] += st.dos[l][i]
            l = 2 #p
            sum_dos_E[l] += st.dos[l][i] * E; sum_dos[l] += st.dos[l][i]
            l = 3 #d
            sum_dos_E[l] += st.dos[l][i] * E; sum_dos[l] += st.dos[l][i]
            l = 0 #p+d
            sum_dos_E[l] += (st.dos[2][i] + st.dos[3][i]) * E; sum_dos[l] += st.dos[2][i] + st.dos[3][i]
            l = 11 #full
            sum_dos_E[l] += st.dos[l][i] * E; sum_dos[l] += st.dos[l][i]
            l = 12 #s+p+d
            sum_dos_E[l] += (st.dos[1][i] + st.dos[2][i] + st.dos[3][i]) * E; sum_dos[l] += st.dos[1][i] + st.dos[2][i] + st.dos[3][i]


        #Determine center of DOS
        st.Ec = [0 for i in range(nn)]
        #    if debug: print "Gravity Centers for s,p,d are (eV):"

        for l in 1,2,3,0,11,12:
            if sum_dos[l] <=0 : 
                printlog('err 123'); 
                sum_dos[l] = 0.00001
            st.Ec[l] = sum_dos_E[l] / sum_dos[l]
            # if debug: print st.Ec[l]


    return d6_gc
Exemple #16
0
def makedir(path):
    """
    *path* - path to some file 
    Make dirname(path) directory if it does not exist
    """
    dirname = os.path.dirname(path)

    if dirname and not os.path.exists(dirname):
        os.makedirs(dirname)
        printlog("Directory", dirname, " was created", imp = 'y')
    return
Exemple #17
0
 def set_ngkpt(self,arg):
     if not is_list_like(arg):
         printlog("Error! set_ngkpt type error")
     old = copy.copy(self.ngkpt)     
     self.ngkpt = copy.copy(arg)
     self.kpoints_file = True
     self.vasp_params['KSPACING'] = None
     if old == arg:
         print_and_log( "Warning! You did not change one of your parameters in new set", imp = 'y')
         return
     self.history += "ngkpt was changed from "+str(old)+" to "+str(arg) + " and KPOINTS file was swithed on\n"
     return
Exemple #18
0
    def update_var(st):
        if st.natom != len(st.xred) != len(st.xcart) != len(st.typat) or len(
                st.znucl) != max(st.typat):
            printlog("Error! write_xyz: check your arrays.\n\n")

        if st.xcart == [] or len(st.xcart) != len(st.xred):
            printlog(
                "Warining! write_xyz: len(xcart) != len(xred) making xcart from xred.\n"
            )
            st.xcart = xred2xcart(st.xred, st.rprimd)
            #print xcart[1]

        return st.rprimd, st.xcart, st.xred, st.typat, st.znucl, len(st.xred)
Exemple #19
0
def create_antisite_defect(st, cation_positions = None):
    """
    exchange cation and transition metal
    st (Structure)

    cation_positions (list of numpy arrays) - reduced coordinates of deintercalated cation positions

    """

    #1. Find first alkali ion
    def find_alkali_ion(st, j_need = 1):
        # return the number of found alk ion of *j_need* occurrence 
        elements = st.get_elements_z()
        # print (elements)
        j = 0
        for i, el in enumerate(elements):
            if el in header.ALKALI_ION_ELEMENTS:
                # print (i,el)
                j+=1
                if j == j_need:
                    return i



    i_alk = find_alkali_ion(st, 3)
    x_alk = st.xcart[i_alk]


    #2. Find closest transition metal
    sur = local_surrounding(x_alk, st, n_neighbours = 1, 
        control = 'atoms', only_elements = header.TRANSITION_ELEMENTS, periodic  = True)

    i_tr = sur[2][0]
    x_tr = st.xcart[i_tr]


    
    #3. Swap atoms
    write_xyz(st, file_name = st.name+'_antisite_start')
    st = st.mov_atoms(i_alk, x_tr)
    st = st.mov_atoms(i_tr,  x_alk)

    write_xyz(st, file_name = st.name+'_antisite_final')

    printlog('Atom ',i_alk+1,'and', i_tr+1,'were swapped')
    printlog('The distance between them is ', sur[3][0])

    st.magmom = [None]

    return st
Exemple #20
0
def create_antisite_defect_old(st, cation_positions=None):
    """
    exchange cation and transition metal
    st (Structure)

    cation_positions (list of numpy arrays) - reduced coordinates of deintercalated cation positions

    """

    #1. Find first alkali ion
    def find_alkali_ion(st, j_need=1):
        # return the number of found alk ion of *j_need* occurrence
        elements = st.get_elements_z()
        # print (elements)
        j = 0
        for i, el in enumerate(elements):
            if el in header.ALKALI_ION_ELEMENTS:
                # print (i,el)
                j += 1
                if j == j_need:
                    return i

    i_alk = find_alkali_ion(st, 3)
    x_alk = st.xcart[i_alk]

    #2. Find closest transition metal
    sur = local_surrounding(x_alk,
                            st,
                            n_neighbours=1,
                            control='atoms',
                            only_elements=header.TRANSITION_ELEMENTS,
                            periodic=True)

    i_tr = sur[2][0]
    x_tr = st.xcart[i_tr]

    #3. Swap atoms
    st.write_xyz(file_name=st.name + '_antisite_start')
    st = st.mov_atoms(i_alk, x_tr)
    st = st.mov_atoms(i_tr, x_alk)

    st.write_xyz(file_name=st.name + '_antisite_final')

    printlog('Atom ', i_alk + 1, 'and', i_tr + 1, 'were swapped')
    printlog('The distance between them is ', sur[3][0])

    st.magmom = [None]

    return st
Exemple #21
0
def wrapper_cp_on_server(file, to):
    """
    tries iterativly scratch and gz
    """
    copy_to = to

    copy_file = file

    for s, gz in product([0, 1], ['', '.gz']):
        printlog('scratch, gz:', s, gz)
        out = server_cp(copy_file + gz, to=to, gz=gz, scratch=s)
        if out == '':
            printlog('Succesfully copied', imp='y')
            break
    return
Exemple #22
0
def determine_symmetry_positions(st, element, silent=0):
    """
    determine non-equivalent positions for atoms of type *element*

    element (str) - name of element, for example Li

    return list of lists -  atom numbers for each non-equivalent position
    """

    from pymatgen.symmetry.analyzer import SpacegroupAnalyzer

    stp = st.convert2pymatgen()

    spg = SpacegroupAnalyzer(stp)

    info = spg.get_symmetry_dataset()

    positions = {}
    for i, (el,
            pos) in enumerate(zip(st.get_elements(),
                                  info['equivalent_atoms'])):

        if el == element and pos not in positions:
            positions[pos] = []

        if el == element:
            positions[pos].append(i)

    if not silent:
        printlog('I have found ',
                 len(positions),
                 'non-equivalent positions for',
                 element,
                 ':',
                 positions.keys(),
                 imp='y',
                 end='\n')
    positions_for_print = {}
    for key in positions:
        positions_for_print[key] = [p + 1 for p in positions[key]]

    if not silent:
        printlog('Atom numbers: ', positions_for_print, imp='y')

    sorted_keys = sorted(list(positions.keys()))
    pos_lists = [positions[key] for key in sorted_keys]

    return pos_lists
Exemple #23
0
def server_cp(copy_file, to, gz=True, scratch=False):

    if scratch:
        copy_file = header.PATH2ARCHIVE + '/' + copy_file
    else:
        copy_file = header.project_path_cluster + '/' + copy_file

    if gz:
        command = 'cp ' + copy_file + ' ' + to + '/CHGCAR.gz' '; gunzip -f ' + to + '/CHGCAR.gz'
    else:
        command = 'cp ' + copy_file + ' ' + to + '/CHGCAR'

    printlog(command, imp='y')
    out = run_on_server(command, addr=header.cluster_address)
    printlog(out, imp='y')
    return out
Exemple #24
0
def file_exists_on_server(file, addr):

    file = file.replace('\\', '/')  # make sure is POSIX

    printlog('Checking existence of file', file, 'on server', addr)
    if header.ssh_object:
        exist = header.ssh_object.fexists(file)
    else:
        exist = runBash('ssh ' + addr + ' ls ' + file)
    if exist:
        res = True
    else:
        res = False

    printlog('File exist? ', res)

    return res
Exemple #25
0
def scale_cell_by_matrix(st,
                         scale_region=(-4, 4),
                         n_scale_images=7,
                         parent_calc_name=None,
                         mul_matrix=None):
    """
    Scale  rprimd and xcart of structure() object *st* from *scale_region[0]* to *scale_region[1]*  (%) using *n_scale_images* images
    and mul_matrix.
    *parent_calc_name* is added to st.des
    Return:
    list of scaled Structure() objects
    
    TODO: Take care of vol, recip and so on - the best is to create some method st.actual() that update all information 
    """
    scales = np.linspace(scale_region[0], scale_region[1], n_scale_images)

    printlog('Scales are', scales, imp='y')
    # print(np.asarray(st.rprimd))

    scaled_sts = []
    for j, s in enumerate(scales):
        st_s = copy.deepcopy(st)
        # print(s)
        mul_matrix_f = s * (np.asarray(mul_matrix) -
                            np.identity(3)) + np.identity(3)
        st_s.rprimd = np.dot(mul_matrix_f, st_s.rprimd)
        # st_s.rprimd = np.dot(s/100*np.asarray(mul_matrix)+np.identity(3), st_s.rprimd)
        print(mul_matrix_f)
        print(np.asarray(st_s.rprimd))
        alpha, beta, gamma = st_s.get_angles()

        print(alpha, beta, gamma)

        st_s.xred2xcart()
        st_s.des = 'obtained from ' + str(
            parent_calc_name) + ' by scaling by ' + str(s) + ' % ' + str(
                mul_matrix)
        st_s.name = str(j + 1)
        scaled_sts.append(st_s)
        # print st_s.rprimd

    # plt.plot([np.linalg.norm(st.rprimd) for st in scaled_sts])
    # plt.show()
    # sys.exit()

    return scaled_sts
Exemple #26
0
def file_exists_on_server(file, addr):

    file = file.replace('\\', '/') # make sure is POSIX

    printlog('Checking existence of file', file, 'on server', addr )
    if header.ssh_object:
        exist = header.ssh_object.fexists(file)
    else:
        exist = runBash('ssh '+addr+' ls '+file)
    if exist:
        res = True
    else:
        res = False

    printlog('File exist? ', res)

    return res
Exemple #27
0
def form_en(sources, products, norm_el = None):
    """
    Calculate formation energy of reaction
    sources, products - list of tuples (x, cl), where x is multiplier and cl is calculation
    norm_el  - which element to use for normalization
        'all' - normalize by total number of atoms

    """

    El = []
    Nzl = []


    for ls in [sources, products]:
        E = 0
        Nz = {}
        for x, cl in ls:
            E += x*cl.e0 
            for i, z in enumerate(cl.end.znucl):
                if z not in Nz:
                    Nz[z] = 0
                Nz[z] += x*cl.end.nznucl[i]
        El.append(E)
        Nzl.append(Nz)

    for z in Nzl[0]:
        if abs(Nzl[0][z] - Nzl[1][z]) > 1e-5:
            printlog('Error! Number of', invert(z), 'atoms in source and product are different!')

    # norm = 1
    if 'all' == norm_el:
        norm = sum(Nzl[0].values())
    elif type(norm_el) == str:
        norm = Nzl[0][invert(norm_el)]
    elif norm_el != None:
        norm = norm_el
    else:
        norm = 1
    # print('Normalizing by ', norm_el, norm, 'atoms')


    print('dE = {:4.2f} eV'.format((El[1]-El[0])/norm))
Exemple #28
0
def create_replaced_structure(st, el1, el2, rep_pos=1, only_one=False):
    """
    allow to replace symmetry non-equivalent positions structures

    rep_pos(int) - number of position starting from 1
    only_one - replace only one first atom
    """
    positions = determine_symmetry_positions(st, el1)
    # position_list = sorted(list(positions.keys()))
    printlog('Choose from the following list using *del_pos*:',
             end='\n',
             imp='y')

    for i, pos in enumerate(positions):
        printlog('     ', i + 1, '--->', pos[0], end='\n', imp='y')

    # pos = position_list[ del_pos - 1 ]
    pos = positions[rep_pos - 1]

    printlog('You have chosen position:', pos[0], imp='y')

    # print(st.get_elements())
    if only_one:
        pos = pos[0:1]

    st1 = st.replace_atoms(atoms_to_replace=pos, el_new=el2)
    st1.name += '.' + el1 + str(pos) + el2 + 'rep'
    # print(st1.get_elements())
    # sys.exit()

    return st1
Exemple #29
0
def create_deintercalated_structure(st, element, del_pos = 1):

    """
    returns deintercalated structures

    del_pos(int) - number of position starting from 1
    """
    positions = determine_symmetry_positions(st, element)
    # position_list = sorted(list(positions.keys()))
    printlog('Choose from the following list using *del_pos*:', end = '\n', imp = 'y')
    
    for i, pos in enumerate(positions):
        printlog('     ', i+1,'--->' , pos[0], end = '\n', imp = 'y')

    # pos = position_list[ del_pos - 1 ]
    pos = positions[ del_pos - 1 ]

    printlog('You have chosen position:', pos[0], imp = 'y')

    # print(st.get_elements())

    st1 = remove_atoms(st, atoms_to_remove = pos)
    st1.name += '.'+element+str(pos)+'del'
    # print(st1.get_elements())
    # sys.exit()

    return st1
Exemple #30
0
def create_deintercalated_structure(st, element, del_pos=1):
    """
    returns deintercalated structures

    del_pos(int) - number of position starting from 1
    """
    positions = determine_symmetry_positions(st, element)
    # position_list = sorted(list(positions.keys()))
    printlog('Choose from the following list using *del_pos*:',
             end='\n',
             imp='y')

    for i, pos in enumerate(positions):
        printlog('     ', i + 1, '--->', pos[0], end='\n', imp='y')

    # pos = position_list[ del_pos - 1 ]
    pos = positions[del_pos - 1]

    printlog('You have chosen position:', pos[0], imp='y')

    # print(st.get_elements())

    st1 = remove_atoms(st, atoms_to_remove=pos)
    st1.name += '.' + element + str(pos) + 'del'
    # print(st1.get_elements())
    # sys.exit()

    return st1
Exemple #31
0
def calc_k_point_mesh(rprimd, kspacing):
    """
    rprimd (list of lists 3x3 of floats) - vectors of cell (Angstroms)
    kspacing (float) - required spacing between k-points in reciprocal space (A-1); paramter KSPACING in VASP

    the provided optimal k-mesh has the smallest sum of squared deviations of kspacings

    returns k-point mesh (list of int)
    """
    N = []
    recip = calc_recip_vectors(rprimd)
    # print(recip)

    for i in 0, 1, 2:
        n = (np.linalg.norm(recip[i])) / kspacing
        N.append(math.ceil(n))

    N_options = [
        ng for ng in itertools.product(*[(n - 1, n, n + 1) for n in N])
    ]

    errors = [
        np.sum(np.square(np.array(calc_kspacings(N, rprimd)) - kspacing))
        for N in N_options
    ]  # sum of squared deviation from kspacing for each option
    i_min = np.argmin(errors)

    N_opt = N_options[i_min]  # k-mesh with smallest error

    printlog('I recommend k-point mesh:',
             N_opt,
             'with k-spacings:',
             np.array(calc_kspacings(N_opt, rprimd)).round(2),
             end='\n',
             imp='y')
    printlog('Other options are:', end='\n', imp='y')
    printlog('{:13s} |    {:20s}'.format('Mesh', 'k-spacings'),
             end='\n',
             imp='y')

    for ngkpt in itertools.product(*[(n - 1, n, n + 1) for n in N_opt]):

        printlog('{:13s} |    {:26s}'.format(
            str(ngkpt), str(np.array(calc_kspacings(ngkpt, rprimd)).round(2))),
                 end='\n',
                 imp='y')

    return N_opt
Exemple #32
0
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
Exemple #33
0
    def set_potential(self,znucl, arg = ''):
        # print arg
        
        if not arg:
            arg = header.PATH2POTENTIALS+'/'+invert(znucl)
            printlog('Attention!, Default potentials is chosen from ',header.PATH2POTENTIALS, 'for',invert(znucl) , imp ='Y')

        if type(arg) not in (str,):
            # sys.exit("\nset_potential error\n")
            raise RuntimeError



        if znucl in self.potdir:
            if arg == self.potdir[znucl]:
                print_and_log( "Warning! You already have the same potential for "+str(znucl)+" element\n" )
        # print type(self.potdir)
        self.potdir[znucl] = arg
        self.history += "Potential for "+str(znucl)+" was changed to "+arg+"\n"
        print_and_log( "Potential for "+str(znucl)+" was changed to "+arg+"\n" )

        # self.update()
        return
Exemple #34
0
def scale_cell_uniformly(
        st,
        scale_region=(-4, 4),
        n_scale_images=7,
        parent_calc_name=None,
):
    """
    Scale uniformly rprimd and xcart of structure() object *st* from *scale_region[0]* to *scale_region[1]*  (%) using *n_scale_images* images.
    *parent_calc_name* is added to st.des
    Return:
    list of scaled Structure() objects
    
    TODO: Take care of vol, recip and so on - the best is to create some method st.actual() that update all information 
    """
    # print scale_region
    scales = np.linspace(scale_region[0], scale_region[1], n_scale_images)
    printlog('Scales are', scales, imp='y')

    # print scales
    scaled_sts = []
    for j, s in enumerate(scales):
        st_s = copy.deepcopy(st)
        for i in (0, 1, 2):
            st_s.rprimd[i] *= (1 + s / 100.)
        # print st_s.rprimd

        st_s.xred2xcart()
        st_s.des = 'obtained from ' + str(
            parent_calc_name) + ' by uniform scaling by ' + str(s) + ' %'
        st_s.name = str(j + 1)
        scaled_sts.append(st_s)
        # print st_s.rprimd

    # plt.plot([np.linalg.norm(st.rprimd) for st in scaled_sts])
    # plt.show()
    return scaled_sts
Exemple #35
0
def remove_one_atom(st, element, del_pos=None, iat=0):
    """
    removes one atom of element type from position del_pos
    iat - number of atom inside subset
    """
    # if not del_pos:
    #     del_pos = 1
    positions = determine_symmetry_positions(st, element)

    if not del_pos and len(positions) > 1:
        printlog(
            'Error! More than one symmetry position is found, please choose del position starting from 1'
        )
    elif len(positions) == 1:
        del_pos = 1
    else:
        printlog('Position', del_pos, 'was chosen', imp='y')

    pos = positions[del_pos - 1]
    i_del = pos[iat]
    st = st.del_atom(i_del)  # remove just iat atom
    st.name += '.' + element + str(i_del) + 'del'
    st.magmom = [None]
    return st, i_del
Exemple #36
0
def ortho_vec(rprim, ortho_sizes=None):
    """
    Function returns mul_mat - 3 vectors of integer numbers (ndarray)
    By calculating np.dot(mul_matrix, rprim) you will get rprim of orthogonal supercell (actually as close as possible to it) 
    """

    printlog(
        'Calculating mul_matrix for ortho:',
        ortho_sizes,
        imp='y',
    )
    printlog('rprim is;', rprim)
    vec_new = np.diag(ortho_sizes)

    # print(rprim)
    # t = rprim[1]
    # rprim[1] = rprim[0]
    # rprim[0] = t

    mul_matrix_float = np.dot(vec_new, np.linalg.inv(rprim))

    # ortho_test = np.dot(mul_matrix_float, rprim )

    # print(ortho_test)
    # print(mul_matrix_float)
    printlog('mul_matrix_float:\n', mul_matrix_float, imp='y', end='\n')

    mul_matrix = np.array(mul_matrix_float)
    mul_matrix = mul_matrix.round(0)
    mul_matrix = mul_matrix.astype(int)

    for i in [0, 1, 2]:
        if mul_matrix[i][i] == 0:
            # mul_matrix[i][i] = 1
            ''

    printlog('mul_matrix:\n', mul_matrix, imp='y', end='\n')

    return mul_matrix
Exemple #37
0
def calc_k_point_mesh(rprimd, kspacing):
    """
    rprimd (list of lists 3x3 of floats) - vectors of cell (Angstroms)
    kspacing (float) - required spacing between k-points in reciprocal space (A-1); paramter KSPACING in VASP

    the provided optimal k-mesh has the smallest sum of squared deviations of kspacings

    returns k-point mesh (list of int)
    """
    N = []
    recip = calc_recip_vectors(rprimd)
    # print(recip)


    for i in 0, 1, 2:
        n = (np.linalg.norm(recip[i])) / kspacing
        N.append( math.ceil(n) )

    N_options = [ng for ng in itertools.product( *[(n-1, n, n+1) for n in N] ) ]

    errors = [  np.sum( np.square( np.array(calc_kspacings(N, rprimd) ) - kspacing ) ) for N in N_options] # sum of squared deviation from kspacing for each option
    i_min = np.argmin(errors)

    N_opt = N_options[i_min] # k-mesh with smallest error



    printlog('I recommend k-point mesh:', N_opt, 'with k-spacings:', np.array( calc_kspacings(N_opt, rprimd) ).round(2), end = '\n', imp = 'y' )
    printlog('Other options are:', end = '\n', imp = 'y' )
    printlog('{:13s} |    {:20s}'.format('Mesh', 'k-spacings'), end = '\n', imp = 'y'  )

    for ngkpt in itertools.product( *[(n-1, n, n+1) for n in N_opt] ):
        
        printlog('{:13s} |    {:26s}'.format(str(ngkpt), str(np.array(calc_kspacings(ngkpt, rprimd) ).round(2))), end = '\n', imp = 'y'  )


    return N_opt
Exemple #38
0
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?)')

    sums = []
    avds = []
    printlog('Searching for voids', important='y')
    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)
        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
    sums = np.array(sums)
    avds = np.array(avds).round(0)

    print_and_log(
        'Sum of distances to 6 neighboring atoms for each void (A):\n',
        sums,
        imp='y')
    print_and_log('Distortion of voids (0 - is symmetrical):\n', avds, imp='y')

    return st_pores, sums, avds
Exemple #39
0
def push_to_server(files=None, to=None, addr=None):
    """
    if header.ssh_object then use paramiko
    to (str)     - path to remote folder ! 
    """
    if not is_list_like(files):
        files = [files]

    to = to.replace('\\', '/')  # make sure is POSIX

    files_str = ' '.join(np.array(files))

    command = ' mkdir -p {:}'.format(to)
    # print('asfsadfdsf', to)
    printlog('push_to_server():', command, run_on_server(command, addr))
    # sys.exit()

    printlog('push_to_server(): uploading files ', files, 'to', addr, to)

    if header.ssh_object:
        for file in files:
            # 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)

    printlog(out)

    return out
Exemple #40
0
def write_lammps(st, filename = '', charges = None):
    """Writes structure in lammps format 

    charges (list of float) - list of charges for each atom type
    """

    rprimd = st.rprimd
    xcart  = st.xcart
    xred   = st.xred
    typat = st.typat
    ntypat = st.ntypat
    znucl = st.znucl
    name = st.name
    natom = st.natom

    if natom != len(xred) != len(xcart) != len(typat) or len(znucl) != max(typat): 
        print_and_log( "Error! write_xyz: check your structure"    )
    
    if name == '': 
        name = 'noname'
    if xcart == [] or len(xcart) != len(xred):
        print_and_log( "Warining! write_xyz: len(xcart) != len(xred) making xcart from xred.\n", imp = 'y')
        xcart = xred2xcart(xred, rprimd)
        #print xcart[1]

    if not filename:
        filename = 'lammps/'+name

    filename+='.inp'

    makedir(filename)



    """Write lammps structure file;  """
    if 1:
        """ My version; valid only for octahedral cells""" 
        printlog( "Warining! write_lammps(): this func supports only orthogonal cells", imp = 'Y')

        with open(filename+'','w') as f:
            f.write("Lammps format "+name+'\n')
            f.write(str(natom)+" atoms\n")
            f.write(str(ntypat)+" atom types\n")
            f.write("{:10.8f}  {:10.8f}  xlo xhi\n".format(0, rprimd[0][0]))
            f.write("{:10.8f}  {:10.8f}  ylo yhi\n".format(0, rprimd[1][1]))
            f.write("{:10.8f}  {:10.8f}  zlo zhi\n".format(0, rprimd[2][2]))
            f.write("0.00000000  0.00000000  0.00000000  xy xz yz\n")
            f.write("\nAtoms\n\n")

            for i, x in enumerate(xcart):
                f.write("{0:8d} {1:2d}".format(i+1, typat[i]))
                if charges:
                    f.write(" {:6.3f}".format(charges[typat[i]-1] ) )
                f.write(" {:12.6f}  {:12.6f}  {:12.6f}\n".format(x[0], x[1], x[2] ))
            


            f.write("\n")
    
        printlog('File', filename, 'was written', imp = 'y')



    else:
        """Write poscar and convert from poscar to lammps using external script; Valid for arbitary cells"""
        cl.write_structure('POSCAR', 'dir', path = 'voronoi_analysis/', state = state)
        runBash("voronoi_analysis/VASP-poscar2lammps.awk voronoi_analysis/POSCAR > "+filepath)
    


    if 0:
        """Write lammps.in file """
        with open('voronoi_analysis/voronoi.in','w') as f:
            f.write("""units           metal
                    atom_style atomic
                    boundary        p p p\n""")
            f.write("read_data   /home/aksenov/programs/Simulation_wrapper/siman1/voronoi_analysis/structure.lammps\n")
    #         f.write('lattice   custom 1 ')
    #         for i, a in enumerate(rprimd):
    #             f.write(' a'+str(i+1))
    #             for x in a:
    #                 f.write(' '+str(x))
            
    #         f.write(' &\n')
    #         for x in xred:
    #             f.write(' basis {0:f} {1:f} {2:f}&\n '.format(x[0], x[1], x[2]) )
    #         f.write("""\n
    # region 1 prism 0 1 0 1 0 1  1 0 0
    # create_box 1 prism
    # create_atoms 1 prism""")

            for i in range(ntypat):
                f.write('\nmass '+str(i+1)+' '+str(int(znucl[i]))+'\n')
            
            f.write('pair_style      lj/cut 2.0\n')
            for i in range(ntypat):
                for j in range(i, ntypat):
                    f.write('pair_coeff      '+str(i+1)+' '+str(j+1)+' 0.0 1.0\n')


            f.write("""compute v1 all voronoi/atom
                    dump    d1 all custom 1 /home/aksenov/programs/Simulation_wrapper/siman1/voronoi_analysis/dump.voro id type x y z c_v1[1] c_v1[2]
                    run 0
                    uncompute v1\n""")

    return
Exemple #41
0
def calc_redox(cl1, cl2, energy_ref = None):
    """
    Calculated average redox potential and change of volume
    cl1 (Calculation) - structure with higher concentration
    cl2 (Calculation) - structure with lower concentration
    energy_ref (float) - energy in eV per one alkali ion in anode; default value is for Li; -1.31 eV for Na, -1.02 eV for K
    """
    if cl1 is None or cl2 is None:
        printlog('cl1 or cl2 is none; return')
        return

    energy_ref_dict = {3:-1.9,  11:-1.31,  19:-1.02}
    z_alk_ions = [3, 11, 19]


    #normalize numbers of atoms by some element except Li, Na, K
    alk1l = [] 
    alk2l = []
    # print cl1.end.znucl
    for i, z in enumerate(cl1.end.znucl):
        # print i, z
        if z in z_alk_ions: 
            alk1l.append(i)
            # print 'i_alk is found'
            continue
        # print i, z

        for j, zb in enumerate(cl2.end.znucl):
            if zb in z_alk_ions: 
                # j_alk = j
                alk2l.append(j)
                continue

            if z == zb:
                # print "I use ", z, " to normalize"
                i_n1 = i
                i_n2 = j

    n1  = cl1.end.nznucl[i_n1]
    n2  = cl2.end.nznucl[i_n2]


    nz1_dict = {}
    nz2_dict = {}
    n_alk1 = 0
    n_alk2 = 0
    for z in z_alk_ions:
        nz1_dict[z] = 0 
        nz2_dict[z] = 0 

    for i in alk1l:
        nz1_dict[ cl1.end.znucl[i] ] = cl1.end.nznucl[i]
    for i in alk2l:
        nz2_dict[ cl2.end.znucl[i] ] = cl2.end.nznucl[i]

    for z in z_alk_ions:
        mul = (nz1_dict[z] / n1 - nz2_dict[z] / n2)
        if abs(mul) > 0: #only change of concentration of one ion type is allowed; the first found is used
            if not energy_ref: #take energy ref from dict
                energy_ref = energy_ref_dict[ z ]
            break

    # print(energy_ref)
    # print(cl1.energy_sigma0, cl2.energy_sigma0, mul)
    if abs(mul) > 0:
        redox = -(  ( cl1.energy_sigma0 / n1 - cl2.energy_sigma0 / n2 ) / mul  -  energy_ref  )
    else:
        redox = 0


    dV = cl1.end.vol / n1 - cl2.end.vol / n2 

    vol_red = dV / (cl1.end.vol/n1) * 100 # %

    # final_outstring = ("{:} | {:.2f} eV \n1".format(cl1.id[0]+'.'+cl1.id[1], redox  ))
    final_outstring = ("{:30} | {:10.2f} eV | {:10.1f} %".format(cl1.name, redox, vol_red  ))
    
    printlog( final_outstring, end = '\n', imp = 'y' )
    try:
        cl1.set.update()

        results_dic = {'is':cl1.id[0], 'redox_pot':redox, 'id_is':cl1.id, 'id_ds':cl2.id, 
        'kspacing':cl1.set.kspacing, 'time':cl1.time/3600.,
        'mdstep':cl1.mdstep, 'ecut':cl1.set.ecut, 'niter':cl1.iterat/cl1.mdstep,
        'set_is':cl1.id[1], 'vol_red':vol_red }
    except:
        results_dic = {}


    return results_dic
Exemple #42
0
def add_neb(starting_calc = None, st = None, 
    it_new = None, ise_new = None, i_atom_to_move = None, 
    up = 'up1',
    search_type = 'vacancy_creation',
    images  = 3, r_impurity = None, corenum = 15, 
    calc_method = ['neb'], 
    inherit_option  = None, mag_config = None, i_void_start = None, i_void_final = None, 
    atom_to_insert = None,
    replicate = None,
    it_new_folder = None,
    inherit_magmom = False,
    x_start = None, xr_start = None,
    x_final = None, xr_final = None,
    upload_vts = False,
    run = False
     ):


    """
    Prepare needed files for NEB
    Provides several regimes controlled by *search_type* flag:
        - existing_voids - search for voids around atom and use them as a final position 
        - vacancy_creation - search for neighbors of the same type and make a vacancy as a start position
        - interstitial_insertion - search for two neighboring voids; use them as start and final positions
                                    by inserting atom *atom_to_insert*
            

    ###INPUT:
        - starting_calc (Calculation) - Calculation object with structure
        - st (Structure) - structure, can be used instead of Calculation
            - it_new (str) - name for calculation


        - i_atom_to_move (int) - number of atom for moving;
        - *mag_config* (int ) - choose magnetic configuration - allows to obtain different localizations of electron
        - *replicate* (tuple 3*int) - replicate cell along rprimd
        - i_void_start,  i_void_final (int) - number of voids from the suggested lists
        - atom_to_insert  (str) - element name of atom to insert
        - it_new_folder  (str) - section folder
        - inherit_option (str) - passed only to add_loop
        - inherit_magmom (bool) - if True than magmom from starting_calc is used, else from set

        - calc_method (list)
            - 'neb'
            - 'only_neb' - run only footer

        - x_start, x_final (array) - explicit coordinates of moving atom for starting and final positions, combined with atom_to_insert
        
        - upload_vts (bool) - if True upload Vasp.pm and nebmake.pl to server
        - run (bool)  - run on server

    ###RETURN:
        None

    ###DEPENDS:

    ###TODO
    please take care of manually provided i_atom_to_move in case of replicate flag using init_numbers 
    """

    calc = header.calc
    struct_des = header.struct_des
    varset = header.varset

    if not hasattr(calc_method, '__iter__'):
        calc_method = [calc_method]


    if starting_calc and st:
        printlog('Warning! both *starting_calc* and *st* are provided. I use *starting_calc*')
        st = copy.deepcopy(starting_calc.end)

    elif starting_calc:
        st = copy.deepcopy(starting_calc.end)
        printlog('I use *starting_calc*')


    elif st:
        ''
        printlog('I use *st*')

    else:
        printlog('Error! no input structure. Use either *starting_calc* or *st*')




    if corenum:
        # header.corenum = corenum
        ''
    else:
        corenum = header.CORENUM

    if corenum % images > 0:
        print_and_log('Error! Number of cores should be dividable by number of IMAGES')


    name_suffix = ''
    st_pores = []

    name_suffix+='n'+str(images)



    """Replicate cell """
    if replicate:
        print_and_log('You have chosen to replicate the structure by', replicate)

        st = replic(st, mul = replicate)
        name_suffix += str(replicate[0])+str(replicate[1])+str(replicate[2])




    """1. Choose  atom (or insert) for moving """

    atoms_to_move = []

    for i, typ, x in zip(range(st.natom), st.typat, st.xcart): #try to find automatically
        if st.znucl[typ-1] == 3: #Li
            atoms_to_move.append([i, 'Li', x])

        if st.znucl[typ-1] == 11: #
            atoms_to_move.append([i, 'Na', x])

        if st.znucl[typ-1] == 19: #
            atoms_to_move.append([i, 'K', x])




    if is_list_like(xr_start):
        x_start = xred2xcart([xr_start], st.rprimd)[0]
        st1 = st.add_atoms([x_start], atom_to_insert)
        x_m = x_start
        name_suffix+='s'
        write_xyz(st1, file_name = st.name+'_manually_start')
        printlog('Start position is created manually by adding xr_start', xr_start, x_start)


    elif not atoms_to_move:
        print_and_log('No atoms to move found, you probably gave me intercalated structure', important = 'y')
        print_and_log('Searching for voids', important = 'y')
        st_pores = find_pores(st, r_matrix = 0.5, r_impurity = r_impurity, fine = 1, calctype = 'all_pores')

        print_and_log('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')



        sums = []
        avds = []
        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,
            sums.append(summ)
            avds.append(avd[0])
        # print
        sums = np.array(sums)
        avds  = np.array(avds).round(0)
        print_and_log('Sum of distances to 6 neighboring atoms for each void (A):\n', sums, imp ='y')
        print_and_log('Distortion of voids (0 - is symmetrical):\n', avds, imp ='y')
        
        crude_prec = 1
        sums_crude = np.unique(sums.round(crude_prec))
        print_and_log('The unique voids based on the sums:', 
            '\nwith 0.01 A prec:',np.unique(sums.round(2)),
            '\nwith 0.1  A prec:',sums_crude,
            imp ='y')
        print_and_log('Based on crude criteria only', len(sums_crude),'types of void are relevant') 

        print_and_log('Please use *i_void_start* to choose the void for atom insertion from this Table:', 
            end = '\n', imp = 'Y')

        insert_positions = []
        start_table = []
        for i, s in enumerate(sums_crude):
            index_of_first =  np.where(sums.round(crude_prec)==s)[0][0]

            start_table.append([i,  st_pores.xcart[index_of_first].round(2), index_of_first,
            avds[index_of_first], sums[index_of_first]     ])

            insert_positions.append( st_pores.xcart[index_of_first] )


        print_and_log( tabulate(start_table, headers = ['Start void #', 'Cart.', 'Index', 'Dev.', 'Sum'], tablefmt='psql'), imp = 'Y' )

        if i_void_start == None:
            sys.exit()

        st = st.add_atoms([insert_positions[i_void_start],], atom_to_insert)

        name_suffix+='i'+str(i_void_start)

        i_m = st.natom-1
        x_m = st.xcart[i_m]


        search_type = 'existing_voids'
        type_atom_to_move = atom_to_insert
        el_num_suffix = ''



    else:

        print_and_log('I have found', len(atoms_to_move), ' anion atoms', important = 'n')
        print_and_log( 'Sums of bond lengths around these atoms:',)
        sums = []
        for a in atoms_to_move:
            summ = local_surrounding(a[2], st, n_neighbours = 6, control = 'sum', periodic  = True)
            sums.append(summ)
            # print( summ, end = '')
        
        print_and_log('\nAmong them only',len(set(sums)), 'unique' , important = 'n')
        
        # if 
        print_and_log('Choosing the first' , important = 'n')

        type_atom_to_move = atoms_to_move[0][1]
        i_atom_to_move = atoms_to_move[0][0]+1
        el_num_suffix =  type_atom_to_move +str(i_atom_to_move)



        i_m = i_atom_to_move-1
        x_m = st.xcart[i_m]

        #highlight the moving atom for user for double-check
        # st_new = st.change_atom_z(i_m, new_z = 100)
        # search_type = 'vacancy_creation'











    """2. Choose final position"""



    if is_list_like(xr_final):
        x_final = xred2xcart([xr_final], st.rprimd)[0]
        st2 = st.add_atoms([x_final], atom_to_insert)
        x_del = x_final 
        search_type = 'manual_insertion'
        name_suffix+='f'+atom_to_insert
        write_xyz(st2, file_name = st.name+'_manually_final')
        printlog('Final position is created manually by adding xr_final', xr_final, x_del)



    elif search_type == 'existing_voids':
        #Search for voids around choosen atoms
        if not st_pores: 
            st_pores = find_pores(st, r_matrix = 0.5, r_impurity = r_impurity, fine = 2, calctype = 'all_pores')

        sur = local_surrounding(x_m, st_pores, n_neighbours = len(st_pores.xcart), control = 'atoms', periodic  = True)
        # print sur


        print_and_log(
        'I can suggest you '+str (len(sur[0])-1 )+' end positions.' )
        # The distances to them are : '+str(np.round(sur[3], 2) )+' A\n ',
        # 'Openning Jmol end positions are highlighted by inserting H ', important = 'y')
        # print x_m
        # print sur[0]
        print_and_log('Please choose *i_void_final* from the following Table:', end = '\n', imp = 'Y')
        
        final_table = []

        for i, (x, d, ind) in enumerate( zip(sur[0], sur[3], sur[2])[1:] ):
            final_table.append([i, np.array(x).round(2), round(d, 2), avds[ind], sums[ind] ]  )

        print_and_log( tabulate(final_table, headers = ['Final void #', 'Cart.', 'Dist', 'Dev.', 'Sum'], tablefmt='psql'), imp = 'Y' )
        
        if i_void_final == None:
            sys.exit()



        x_final = sur[0][i_void_final+1] # +1 because first element is x_m atom itself

        write_xyz(st.add_atoms([ x_final], 'H'), replications = (2,2,2), file_name = st.name+'_possible_positions2_replicated')
        
        # sys.exit()        
        # write_xyz(st.add_atoms(sur[0][2:3], 'H'), analysis = 'imp_surrounding', show_around = 230,nnumber = 10, replications = (2,2,2), file_name = 'local230')
        # # write_xyz(st.add_atoms(sur[0][0:1], 'H'), analysis = 'imp_surrounding', show_around = 226,nnumber = 10, replications = (2,2,2), file_name = 'local')
        # run_jmol
        print_and_log('Choosing the closest position as end', important = 'n')
        # i_void_final = 0

        st1 = st

        # print st1.natom
        # sys.exit()

        st2 = st.mov_atoms(i_m, x_final)
        
        name_suffix += el_num_suffix+'e'+str(i_void_final)+atom_to_insert

        st1 = return_atoms_to_cell(st1)
        st2 = return_atoms_to_cell(st2)

        write_xyz(st1, file_name = st1.name+name_suffix +'_start')

        write_xyz(st2, file_name = st2.name+name_suffix +'_final')


    elif search_type == 'vacancy_creation':
        #Create vacancy by removing some neibouring atom of the same type 
        
        print_and_log('You have chosen vacancy_creation mode of add_neb tool', important = 'Y')

        print_and_log( 'Type of atom to move = ', type_atom_to_move, imp = 'y')
        # print 'List of left atoms = ', np.array(st.leave_only(type_atom_to_move).xcart)
        sur = local_surrounding(x_m, st.leave_only(type_atom_to_move) , n_neighbours = 4, control = 'atoms', 
            periodic  = False)
        # print 'xcart of moving atom', x_m
        # print 'Local surround = ', sur
        # print 'len', len(sur[0])
        if len(sur[0]) < 3:
            
            # print 'rprimd = \n',np.array(st.rprimd)
            # print 'r lengths = \n',( [np.linalg.norm(r) for r in st.rprimd] )
            # print 'xred = \n', np.array(st.xred)
            # print 'xcart = \n', np.array(st.xcart)


            print_and_log('The supercell is too small, I increase it 8 times!')
            st = replic(st, mul = (2,2,2) )
            sur = local_surrounding(x_m, st.leave_only(type_atom_to_move) , n_neighbours = 4, control = 'atoms', 
                periodic  = False)
            # print 'xcart of moving atom', x_m
            write_xyz(st, file_name = st.name+'_replicated')#replications = (2,2,2))

            # print 'Local surround = ', sur
            # sys.exit()


        print_and_log(
        'I can suggest you '+str (len(sur[0]) )+' end positions. The distances to them are : '+str(np.round(sur[3], 2) )+' A\n ',
        'They are all', type_atom_to_move, 'atoms', important = 'y')

        print_and_log('Choosing the closest position as end', important = 'n')
        neb_config = 1 #cause the first item in sur is moving atom itself
        x_del = sur[0][neb_config]
        i_del = st.find_atom_num_by_xcart(x_del)


        print_and_log('Making vacancy at end position for starting configuration', important = 'n')
        print_and_log( 'number of atom to delete = ', i_del)
        # print st.magmom
        st1 = st.del_atom(i_del)
        # print st1.magmom

        print_and_log('Making vacancy at start position for final configuration', important = 'n')


        st2 = st.mov_atoms(i_m, x_del) # i_m and sur[0][neb_config] should coincide
        st2 = st2.del_atom(i_del) # these two steps provide the same order





        name_suffix += el_num_suffix+'v'+str(neb_config)

        write_xyz(st1, file_name = st1.name+'_start')# replications = (2,2,2))
        write_xyz(st2, file_name = st2.name+'_end')# replications = (2,2,2))

        # sys.exit()


    # sys.exit()





    """ Determining magnetic moments  """
    if varset[ise_new].vasp_params['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)

        # sys.exit()
        # print_and_log('The magnetic moments from set:')
        # print cl_test.init.magmom

        #checking for closest atoms now only for Fe, Mn, Ni, Co
        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)
        numb = np.array(sur[2])
        a = zip(numb, dist )
        # a=  np.array(a)
        # print a[1]
        # a = np.apply_along_axis(np.unique, 1, a)
        # print a
        def unique_by_key(elements, key=None):
            if key is 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)
        # a = unique_by_key(a, key=itemgetter(1))
        print_and_log( 'I change spin for the following atoms:\ni atom     dist\n', np.round(mag_atoms_dists, 2) , imp = 'y' )
        # print 'I have found closest Fe atoms'
        muls = [(1.2, 0.6), (0.6, 1.2)]
        mag_moments_variants = []
        for mm in muls:
            mags = copy.deepcopy(cl_test.init.magmom)
            # print mags
            for a, m in zip(mag_atoms_dists, mm):
                # print t[1]
                mags[a[0]] = mags[a[0]]*m
            mag_moments_variants.append(mags)

        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:

            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')

    else:
        print_and_log('Non-magnetic calculation continue ...')















    """3. Add to struct_des, create geo files, check set, add_loop """

    if starting_calc:
        it = starting_calc.id[0]
        it_new = it+'v'+str(starting_calc.id[2])+'.'+name_suffix

        if not it_new_folder:
            it_new_folder = struct_des[it].sfolder+'/neb/'
        obtained_from = str(starting_calc.id) 

        if not ise_new:
            print_and_log('I will run add_loop() using the same set', important = 'Y')
            ise_new = cl.id[1]

    elif st:
        if not it_new:
            printlog('Error! please provide *it_new* - name for your calculation', important = 'Y')


        it = None
        it_new+='.'+name_suffix
        obtained_from = st.name
        
        if not ise_new:
            printlog('Error! please provide *ise_new*', important = 'Y')

        if not it_new_folder:
            printlog('Error! please provide *it_new_folder* - folder for your new calculation', important = 'Y')



    if it_new not in struct_des:
        add_des(struct_des, it_new, it_new_folder, 'Automatically created and added from '+obtained_from  )




    print_and_log('Creating geo files for starting and final configurations (versions 1 and 2) ', important = 'y')

    # if starting_calc:
    #     cl = copy.deepcopy(starting_calc)
    # else:

    cl = CalculationVasp()

    #write start position

    struct_des[it_new].x_m_ion_start = x_m
    struct_des[it_new].xr_m_ion_start = xcart2xred([x_m], st1.rprimd)[0]

    cl.end = st1
    ver_new = 1
    cl.version = ver_new
    cl.path["input_geo"] = header.geo_folder + struct_des[it_new].sfolder + '/' + \
        it_new+"/"+it_new+'.auto_created_starting_position_for_neb_'+search_type+'.'+str(ver_new)+'.'+'geo'
    
    cl.write_siman_geo(geotype = 'end', description = 'Starting conf. for neb from '+obtained_from, override = True)


    #write final position

    struct_des[it_new].x_m_ion_final = x_del
    struct_des[it_new].xr_m_ion_final = xcart2xred([x_del], st2.rprimd)[0]

    cl.end = st2
    ver_new = 2
    cl.version = ver_new
    cl.path["input_geo"] = header.geo_folder + struct_des[it_new].sfolder + '/' + \
        it_new+"/"+it_new+'.auto_created_final_position_for_neb_'+search_type+'.'+str(ver_new)+'.'+'geo'
    
    cl.write_siman_geo(geotype = 'end', description = 'Final conf. for neb from '+obtained_from, override = True)




    #prepare calculations









    #Check if nebmake is avail
    # if int(runBash('ssh '+cluster_address+' test -e '+project_path_cluster+'/tools/vts/nebmake.pl; echo $?') ):

    #     ''
    #     print_and_log('Please upload vtsttools to ',cluster_address, project_path_cluster+'/tools/vts/')
    #     raise RuntimeError

    #     copy_to_server(path_to_wrapper+'/vtstscripts/nebmake.pl', to = project_path_cluster+'/tools/',  addr = cluster_address)
    # if  int(runBash('ssh '+cluster_address+' test -e '+project_path_cluster+'/tools/Vasp.pm; echo $?') ):
    #     copy_to_server(path_to_wrapper+'/vtstscripts/Vasp.pm', to = project_path_cluster+'/tools/',  addr = cluster_address)





    inherit_ngkpt(it_new, it, varset[ise_new])

    add_loop(it_new, ise_new, verlist = [1,2], up = up, calc_method = calc_method, savefile = 'ov', inherit_option = inherit_option, n_neb_images = images, corenum = corenum, run =run  )
    if upload_vts:
        siman_dir = os.path.dirname(__file__)
        # print(upload_vts)
        push_to_server([siman_dir+'/cluster_tools/nebmake.pl', siman_dir+'/cluster_tools/Vasp.pm'], to = header.cluster_home+'/tools/vts',  addr = header.cluster_address)
    
    else:
        print_and_log('Please be sure that vtsttools are at',header.cluster_address, header.cluster_home+'/tools/vts/', imp = 'Y')


    return it_new 
Exemple #43
0
def create_antisite_defect2(st_base, st_from, cation = None, trans = None, trans_pos = 1,  mode = None):
    """
    exchange cation and transition metal
    st_base (Structure) - basic structure in which defects are created
    st_from (Structure) - structure from which the positions of *cation* are chosen;  st_from should be consistent with st_base 
    cation (str) - element, position of which is extracted from st_from and added to st_base

    trans (str) - element name transition metal for exchange
    trans_pos (int) - number of non-equiv position of trans starting from 1

    mode - 
        'add_alk' or 'a1' - add alkali cation
        'mov_trs' or 'a2' - mov trans to alkali pos
        'add_swp' or 'a3' - add alk and swap with trans
    """

    printlog('create_antisite_defect2(): mode = ', mode, imp = 'y')


    st = st_base

    cation_xred = st_from.get_element_xred(cation)
    printlog('For cation ', cation, 'reduced coordinates:',cation_xred, ' were chosen', imp = 'y')


    positions = determine_symmetry_positions(st_from, trans)
    printlog('Transition atom ', trans, 'has ', len(positions), 'non-equiv positions', imp = 'y')
    transition_numbers = positions[trans_pos -1]



    #1. Insert cation
    cation_xcart = xred2xcart([cation_xred], st.rprimd)[0]
    st_i = st.add_atoms([cation_xcart], cation)
    st_i.write_xyz(filename = st.name+'_'+cation+'_added')


    #2. Find transition metal atoms close to cation_xcart and move it here
    sur = local_surrounding(cation_xcart, st, n_neighbours = 1, 
        control = 'atoms', only_numbers = transition_numbers, periodic  = True)

    i_trans = sur[2][0]
    x_trans = sur[0][0]

    st_m = st.mov_atoms(sur[2][0], cation_xcart)
    st_m.write_xyz(filename = st.name+'_trans_moved')


    #3. Put cation to empty trans metal pos
    st_s = st_m.add_atoms([x_trans], cation)
    st_s.write_xyz(filename = st.name+'_swapped')


    if 'add_alk' in mode or 'a1' in mode:
        st = st_i
    elif 'mov_trs' in mode or 'a2' in mode:
        st = st_m
    elif 'add_swp' in mode or 'a3' in mode:
        st = st_s

    st.magmom = [None]

    return st
Exemple #44
0
def plot_dos(cl1, cl2 = None, dostype = None, iatom = 0, orbitals = ('s'), up = None, neighbors = 6, show = 1, path = 'dos', xlim = (None, None), ylim = (None,None) ):
    """
    cl1 (CalculationVasp) - object created by add_loop()
    dostype (str) - control which dos to plot:
        'total'   - plot total dos
        'diff_total' - difference of total dos, use cl2 for second calculation
        'partial' - partial dos

    orbitals (list of str) - any from 's, p, d, py, pz, px, dxy, dyz, dz2, dxz, dx2' where 'p' and 'd' are sums of projections
    up - 'up2' allows to download the file once again


    iatom (int) - number of atom starting from 1 to plot DOS by default it is assumed that the last atom is used
    iatom ([float]*3) - cartesian coordinates of point around which atoms will be found
    show (bool) - whether to show the dos 
    path (str)  - path to folder with images

    neighbors - number of neighbours around iatom to plot dos on them

    xlim, ylim (tuple)- limits for plot

    #0 s     1 py     2 pz     3 px    4 dxy    5 dyz    6 dz2    7 dxz    8 dx2 
    #In all cases, the units of the l- and site projected DOS are states/atom/energy.

    """
    iatom -= 1





    """1. Read dos"""
    printlog("------Start plot_dos()-----", imp = 'Y')
    dos = []
    for cl in cl1, cl2:
        if cl == None: 
            continue

        if not hasattr(cl, "efermi"):
            cl.read_results('o')

        printlog(cl.name, 'e_fermi', cl.efermi, imp = 'Y')
     
        DOSCAR = cl.get_file('DOSCAR', update = up); 
        printlog('DOSCAR file is ', DOSCAR)

        dos.append( VaspDos(DOSCAR, cl.efermi) )
    

    #determine number of zero energy    
    i_efermi = int(len(dos[0].energy)  *  -dos[0].energy[0] / (dos[0].energy[-1] - dos[0].energy[0])) # number of point with zero fermi energy
    if cl2:
        i_efermi_e = int(len(dos[1].energy)  *  -dos[1].energy[0] / (dos[1].energy[-1] - dos[1].energy[0])) # number of point with zero fermi energy

    


    

    """2. Plot dos for different cases"""
    if dostype == 'total':

        fit_and_plot(show = show, image_name = os.path.join(path, cl1.name+'.dosTotal'), xlabel = "Energy (eV)", ylabel = "DOS (states/eV)",
            xlim = xlim, ylim = ylim,
            Total = (dos[0].energy, smoother(dos[0].dos, 10), 'b-'))

    elif dostype == 'diff_total':

        if len(dos) > 1:    
            #calculate dos diff 
            dosd = [(d0 - d1)*e for d0, d1, e in zip(dos[0].dos, dos[1].dos, dos[0].energy)] #calculate difference
            area = trapz(dosd[:i_efermi], dx=1)
            printlog("area under dos difference = ", -area, imp = 'Y')

            fit_and_plot(show = show,image_name = cl1.name+'--'+cl2.name+'.dosTotal_Diff', xlabel = "Energy (eV)", ylabel = "DOS (states/eV)",
                xlim = xlim, ylim = ylim,
                Diff_Total = (dos[0].energy, smoother(dosd, 15), 'b-'))
        else:
            printlog('You provided only one calculation; could not use diff_total')





    elif 'partial' in dostype:
        #Partial dos
        #1  p carbon,  d Ti
        #0 s     1 py     2 pz     3 px    4 dxy    5 dyz    6 dz2    7 dxz    8 dx2 
       
        try:
            dos[0].site_dos(0, 4)
        except:
            printlog('Error! No information about partial dxy dos in DOSCAR; use LORBIT 12 to calculate it')



        """Determine neighbouring atoms """
        printlog("Number of considered neighbors is ", neighbors)

        if type(iatom) == int: #for the cases when we need to build surrounding around specific atom in this calculation - just use number of atom
            t = cl1.end.typat[iatom]
            z = cl1.end.znucl[t-1]
            el = element_name_inv(z)
            printlog('Typat of chosen imp atom in cl1 is ', el)
            surround_center = cl1.end.xcart[iatom]
        else: #for the case when coordinates of arbitary point are provided.
            surround_center = iatom
            el = 'undef'

        local_atoms = local_surrounding(surround_center, cl1.end, neighbors, control = 'atoms', periodic = True)

        numbers = local_atoms[2] # first atom is impurity if exist
        printlog("Numbers of local atoms:", [n+1 for n in numbers] )
        printlog("List of distances", [round(d,2) for d in local_atoms[3]] )


        iX = numbers[0]

        for j in range(len(dos)):
            
            dos[j].p = [] #central and and surrounding
            dos[j].d = [] #central atom and surrounding atoms
            dos[j].d6 = 0 #sum by six atoms

            for i in numbers: #Now for surrounding atoms in numbers list:

                plist = [dos[j].site_dos(i, l)  for l in (1,2,3) ]
                dos[j].p.append( [ sum(x) for x in zip(*plist) ] )


                dlist = [dos[j].site_dos(i, l)  for l in (4,5,6,7,8) ] # For total d T96C
                dsum = [ sum(x) for x in zip(*dlist) ] 
                dos[j].d.append(  dsum   )
            

            dos[j].p6 = [ sum(pi) for pi in zip(*dos[j].p) ] #sum over neighbouring atoms
            dos[j].d6 = [ sum(di) for di in zip(*dos[j].d) ] #sum over neighbouring atoms

            # t2g = [dos[0].site_dos(iTi, l)  for l in 4,5,7] #  Now only for first Ti atom
            # dos[0].t2g =  [ sum(x) for x in zip(*t2g) ]  

            # eg = [dos[0].site_dos(iTi, l)  for l in 8, 6] #  Now only for first Ti atom
            # dos[0].eg =  [ sum(x) for x in zip(*eg) ] 
           


        """Plotting"""
        nsmooth = 15 # smooth of dos
        d1 = dos[0]
        energy1 = dos[0].energy
        args = {}
        i_orb = {'s':0, 'py':1, 'pz':2, 'px':3, 'dxy':4, 'dyz':5, 'dz2':6, 'dxz':7, 'dx2':8}
        color = {'s':'k-', 'p':'g-', 'd':'b-', 'py':'r-', 'pz':'b-', 'px':'c-', 'dxy':'m-', 'dyz':'c-', 'dz2':'m-', 'dxz':'r-', 'dx2':'g-'}

        for orb in orbitals:
            if orb == 'p':
                args[orb] = (d1.energy, smoother(d1.p[0], nsmooth), color[orb])
            elif orb == 'd':
                args[orb] = (d1.energy, smoother(d1.d[0], nsmooth), color[orb])
            else:
                args[orb] = (d1.energy, smoother(d1.site_dos(iX, i_orb[orb]), nsmooth), color[orb])

        image_name = os.path.join(path, cl1.name+'.'+''.join(orbitals)+'.'+el+str(iX))

        fit_and_plot(show = show, image_name = image_name, figsize = (4,6), xlabel = "Energy (eV)", ylabel = "DOS (states/eV)", 
        # title = cl1.name.split('.')[0]+'; V='+str(round(cl1.vol) )+' $\AA^3$; Impurity: '+el,
        xlim = xlim, ylim = ylim, legend = 2,
        **args
        )
        # printlog("Writing file", image_name, imp = 'Y')

        """Additional dos analysis; to be refined"""

        if 0:
            """Calculate d DOS at Fermi level"""
            nn = 50 #number to integrate in both directions 
            x1 = dos[0].energy[i_efermi-nn:i_efermi+nn]
            y1 = smoother(dos[0].d6, nsmooth)[i_efermi-nn:i_efermi+nn]
            x2 = dos[1].energy[i_efermi_e-nn:i_efermi_e+nn]
            y2 = smoother(dos[1].d6, nsmooth)[i_efermi_e-nn:i_efermi_e+nn]
            f1 = interp1d(x1, y1, kind='cubic')
            f2 = interp1d(x2, y2, kind='cubic')
            # if debug: print '\n'
            # if debug: print dos[0].d6[i_efermi] - dos[1].d6[i_efermi_e], " - by points; change of d Ti DOS at the Fermi level due to the carbon"
            # if debug: print f2(0), f1(0)
            e_at_Ef_shift = f1(0) - f2(0)

            printlog("{:5.2f} reduction of d dos at Fermi level; smoothed and interpolated".format( e_at_Ef_shift ), imp = 'Y' )
        
        if 0:
            """Calculate second derivative of d at the Fermi level"""
            # tck1 = interpolate.splrep(x1, y1, s=0)
            # tck2 = interpolate.splrep(x2, y2, s=0)
            # e_at_Ef_shift_spline = interpolate.splev(0, tck1, der=0) - interpolate.splev(0, tck2, der=0)
            # if debug: print "{:5.2f} smoothed and interpolated from spline".format( e_at_Ef_shift_spline )
            # # if debug: print type(interpolate.splev(0, tck1, der=2))
            # if debug: print "{:5.2f} {:5.2f} gb and bulk second derivative at Fermi from spline".format( float(interpolate.splev(0, tck1, der=2)), float(interpolate.splev(0, tck2, der=2)) )




        if 0:
            """Calculate shift of d orbitals after adding impurity"""
            d_shift = det_gravity(dos[0],  Erange = (-2.8, 0)) - det_gravity(dos[1],  Erange = (-2.8, 0) ) #negative means impurity shifts states to negative energies, which is favourable
            printlog( "{:5.2f} Shift of Ti d center of gravity".format( d_shift ), imp = 'Y' )
            # if debug: print det_gravity(dos[0],  Erange = (-2.8, 0)), det_gravity(dos[1],  Erange = (-2.8, 0))
            """Calculate correlation between imp p and matrix d"""
            def rmsdiff(a, b):
                # rms difference of vectors a and b:
                #Root-mean-square deviation
                rmsdiff = 0
                for (x, y) in zip(a, b):
                    rmsdiff += (x - y) ** 2  # NOTE: overflow danger if the vectors are long!
                
                return math.sqrt(rmsdiff / min(len(a), len(b)))

            pd_drms = 1/rmsdiff(dos[0].p, dos[0].d6) # the higher the number the higher hybridization
            printlog("{:5.2f} p-d hybridization estimate".format( pd_drms ) , imp = 'Y')

            # if debug: print "sqeuclidean", sqeuclidean(dos[0].p, dos[0].d6)/len(dos[0].d6)

            # if debug: print "pearsonr", pearsonr(dos[0].p, dos[0].d6) #Pearson correlation coefficient; only shape; the larger number means more similarity in shape

            # def autocorr(x):
            #     result = np.correlate(x, x, mode='full')
            #     return result[result.size/2:]


    printlog("------End plot_dos()-----\n\n")


    return {'name':cl1.name}
Exemple #45
0
def write_xyz(st, path = None, repeat = 1, shift = 1.0,  gbpos2 = None, gbwidth = 1 , 
    imp_positions = [], specialcommand = None, analysis = None, show_around = None, replications = None, nnumber = 6, topview = True,
    filename = None, file_name = None, full_cell = False, orientation = None, boundbox = 2, withgb = False,
    include_boundary = 2, rotate = None, imp_sub_positions = None, jmol = None, show_around_x = None,
    ):
    """Writes st structure in xyz format in the folder xyz/path

    if repeat == 2: produces jmol script
    shift - in rprimd[1][1] - shift of the second view
    gbpos2 - position of grain boundary in A
    gbwidth - atoms aroung gbpos2 will be colored differently

    imp_positions - type and xcart coordinates additionally to be added to structure; to visulaze all impurity positions: for jmol
    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
        nnumber - number of neighbours to show
        show_around - choose atom number around which to show
        show_around_x - show atoms around point, has higher priority

    replications - list of replications, (2,2,2) 

    full_cell - returns atoms to cell and replicate boundary atoms

    jmol - 1,0 - allow to use jmol
    """
    if replications:
        st = replic(st, mul = replications, inv = 1 )
  
    def update_var():
        return st.rprimd, st.xcart, st.xred, st.typat, st.znucl, len(st.xred)

    rprimd, xcart, xred, typat, znucl, natom = update_var()


    if file_name:
        name = file_name
    elif filename:
        name = filename
    else:
        name = st.name



    if natom != len(xred) != len(xcart) != len(typat) or len(znucl) != max(typat): 
        print_and_log( "Error! write_xyz: check your arrays.\n\n"    )
    # print st.natom, len(st.xred), len(st.xcart), len(st.typat), len(st.znucl), max(st.typat)
    
    print_and_log("write_xyz(): Name is", name, important = 'n')
    if name == '': name = 'noname'


    if xcart == [] or len(xcart) != len(xred):
        print_and_log( "Warining! write_xyz: len(xcart) != len(xred) making xcart from xred.\n")
        xcart = xred2xcart(xred, rprimd)
        #print xcart[1]
    
    if path:
        basepath = path
    else:
        basepath = 'xyz/'



    xyzfile = os.path.join(basepath, name+".xyz")
    makedir(xyzfile)


    """Processing section"""


    if analysis == 'imp_surrounding':
        lxcart = []
        ltypat = []
        i=0
        for t, x in zip(typat, xcart):
            
            condition = False
            # print show_around, 'show'
            if show_around:
                # print i, condition
                condition = (i + 1 == show_around)
                # print i, condition

            else:
                condition = (t > 1) # compat with prev behav
            
            # print 'se', condition

            if condition: 
                # lxcart.append(x)
                # ltypat.append(t)
                # print x, ' x'
                x_t = local_surrounding(x, st, nnumber, control = 'atoms', periodic = True)
                # print x_t[1]
                lxcart+=x_t[0]
                ltypat+=x_t[1]
            i+=1
        
        if show_around_x:
            x = show_around_x
            x_t = local_surrounding(x, st, nnumber, control = 'atoms', periodic = True)
            # print x_t[1]
            lxcart+=x_t[0]
            ltypat+=x_t[1]            


        xcart = lxcart
        typat = ltypat
        natom = len(typat)
        # print natom, 'nat'



    """Include atoms on the edge of cell"""
    if full_cell:
        # print xred
        # print natom
        # st = return_atoms_to_cell(st)
        # print xred
        st = replic(st, mul = (1,1,2), inv = 0, cut_one_cell = 1, include_boundary = include_boundary)
        # print natom, st.natom

        # print st.xred

        rprimd, xcart, xred, typat, znucl, natom = update_var()
        
    # asdegf

    """Writing section"""   
    # print_and_log("Writing xyz: "+xyzfile, imp = 'y')

    #analyze imp_positions
    if imp_sub_positions == None:
        imp_sub_positions = []
    nsub = 0
    for pos in imp_positions:
        if 's' not in pos[4]: continue # skip interstitial positions
        xs = np.asarray([pos[0],pos[1],pos[2]])
        nsub+=1
        # print xs
        for i, x in enumerate(xcart):
            # print np.linalg.norm( x-xs)
            if np.linalg.norm( x-xs) < 1:
                imp_sub_positions.append(i)

    if imp_sub_positions : 
        print_and_log( imp_sub_positions, ': numbers of found atoms to be changed ' )


    # for i in sorted(indices, reverse=True):
    #     del somelist[i]




    with open(xyzfile,'w') as f:
        for i in range(repeat):
            f.write(str(natom + len(imp_positions)-nsub + 3)+"\n") #+3 vectors
            f.write(name+"\n")

            if imp_positions: 
                for i, el in enumerate(imp_positions):
                    # if len(el) != 4: continue
                    f.write( "%s %.5f %.5f %.5f \n"%( el[3], el[0], el[1], el[2] ) )
                    # print 'composite -pointsize 60 label:{0:d} -geometry +{1:d}+{2:d} 1.png 2.png'.format(i, el[0], el[1])


            for i in range(natom):
                typ = typat[i] - 1
                
                z = int ( znucl[ typ ] )

                if i in imp_sub_positions: 
                    # f.write( "Be " )
                    continue
                else:
                    el = element_name_inv(z)
                    f.write( el+" " )


                f.write( "%.5f %.5f %.5f \n"%( xcart[i][0], xcart[i][1], xcart[i][2] ) )

            for r in st.rprimd:
                f.write('Tv {:.10f} {:.10f} {:.10f}\n'.format(*r)  )


    # os._exit(1)
    printlog('File', xyzfile, 'was written', imp = 'y')


    if jmol:
        """
        script mode for jmol. Create script file as well for elobarate visualization
        """
        
        """Choose gb atoms to change their color"""
        print_and_log( 'position of boundary 2', gbpos2)
        atomselection = ''

        #create consistent xcart_new list like it will be in Jmol
        xcart_new = []
        for i, x in enumerate(xcart):
            if i in imp_sub_positions: continue
            xcart_new.append(x)    



        if gbpos2:
            
            gbpos1 = gbpos2 - rprimd[0][0]/2.
            gbatoms = []
            
            for i, x in enumerate(xcart_new):
                # print i
                # if x[0] > gbpos1 - gbwidth/2. and x[0] < gbpos1 + gbwidth/2.:
                if abs(x[0] - gbpos1) < gbwidth/2.:
                    gbatoms.append(i)
                    # print i, x[0], abs(x[0] - gbpos1)
                if abs(x[0] - gbpos2) < gbwidth/2.:
                # if x[0] > gbpos2 - gbwidth/2. and x[0] < gbpos2 + gbwidth/2.:
                    # print i, x[0], abs(x[0] - gbpos2)
                    gbatoms.append(i)
            print_and_log( 'Atoms at GB:', gbatoms)
            atomselection = ''
            for i in gbatoms:
                atomselection +='Ti'+str(i+1+len(imp_positions))+','
            atomselection = atomselection[:-1]


        # elif withgb: # color half of cell
        # else: # color half of cell
        #     # pass
            # atomselection = 'atomno>'+str(0+len(imp_positions) )+' and atomno<'+str(( natom + len(imp_positions)  )/2-1)





        xyzfile = os.getcwd()+'/'+xyzfile
        scriptfile = basepath+name+".jmol"
        pngfile = os.getcwd()+'/'+basepath+name+".png"
        
        print_and_log( 'imp_positions = ',imp_positions)
        write_jmol(xyzfile, pngfile, scriptfile, atomselection, topview = topview, rprimd =rprimd, shift = shift, label = [(pos[3], pos[4]) for pos in imp_positions], 
            specialcommand = specialcommand, orientation = orientation, boundbox =boundbox, rotate = rotate)


    return
Exemple #46
0
def write_database(calc = None, conv = None, varset = None, size_on_start = None):
    """
    The function writes main dictionaries to database file calc.s
    Also creates copy of calc.s

    INPUT:
        calc - dict, contains all calculations of the project
        conv - dict, convergence sequences
        varset - dict, parameter sets of the project
        size_on_start - not used now

    RETURN:
        None    

    """
    #size_on_finish = sys.getsizeof(dbase)
    #if size_on_finish != size_on_start:
    # runBash("cp calc.s calc_copy.s") #create copy before writing
    databasefile3 = 'calc.gdbm3'

    # if header.RAMDISK:
    #     databasefile3 = header.RAMDISK+databasefile3

    # shutil.copyfile(databasefile3, 'calc_copy.gdbm3')
    if 0:
        d = shelve.open('calc.s', protocol=1) #Write database of calculations
        d[calc_key]       = calc
        d[conv_key]       = conv
        d[varset_key]     = varset
        d[history_key]    = header.history
        d[struct_des_key] = header.struct_des 
        d.close()

    python2 = False
    if python2:
        import gdbm# use in python2

        d = shelve.Shelf(gdbm.open('calc.gdbm', 'c'), protocol=1) #Write dbm database for python3
        d[unicode(calc_key)]       = calc
        d[unicode(conv_key)]       = conv
        d[unicode(varset_key)]     = varset
        d[unicode(history_key)]    = header.history
        d[unicode(struct_des_key)] = header.struct_des 
        d.close()
    else: #python3 
        import dbm
        # d = shelve.Shelf(dbm.open('calc.gdbm', 'c'), protocol=1) #Write dbm database for python3
        # d[calc_key]       = calc
        # d[conv_key]       = conv
        # d[varset_key]     = varset
        # d[history_key]    = header.history
        # d[struct_des_key] = header.struct_des 
        # d.close()        

        d = shelve.Shelf(dbm.open(databasefile3, 'n'), protocol = 3) #Write dbm database for python3
        # d[calc_key]       = calc
        d[conv_key]       = header.conv
        d[varset_key]     = header.varset
        d[history_key]    = header.history
        d[struct_des_key] = header.struct_des 
        d.close()   

        with shelve.Shelf(dbm.open(header.calc_database, 'w'), protocol = 3) as d:
            for key in header.calc:
                d[str(key)] = header.calc[key]
        
        # with dbm.open(header.calc_database, 'w') as d:
        #     d.reorganize()


    printlog("\nEnd of work at "+str(datetime.datetime.now())+'\n')

    try:
        header.log.close()
    except:
        pass

    #Update history file
    with  open('history','w') as his:
        #print history
        for i in header.history:
            #print i
            his.write(i+"\n")
    
    print("\nDatabase has been successfully updated\n")
    
    return
Exemple #47
0
def read_database(scratch = False):
    """
    Read database of calculations

    INPUT:
        scratch - not used
    
    RETURN:
        calc   - dict, contains all calculations of the project
        conv   - dict, convergence sequences
        varset - dict, parameter sets of the project
        size_on_start, int - not used now
    """

    # databasefile = 'calc.s' #was used with python2
    # databasefile = 'calc.gdbm'
    databasefile3 = 'calc.gdbm3'
    # if header.RAMDISK:
    #     databasefile3 = header.RAMDISK+databasefile3




    # if scratch == True: databasefile =   '/scratch/aksenov/calc.s'
    
    printlog("\nLaunch at "+str( datetime.datetime.today() )+'\n')
    
    # mod = __import__("gdbm")
    # d = shelve.Shelf(mod.open(databasefile, protocol=1))

    # print(databasefile3)
    d = shelve.open(databasefile3, protocol = 3)


    try:
        # calc              = d[calc_key]; 
        # calc              = {}; 
        header.conv       = d[conv_key]; 
        header.varset     = d[varset_key]; 
        header.history    = d[history_key]
        header.struct_des = d[struct_des_key]

    except KeyError: 
        
        # try: calc = d[calc_key] #dictionary of calculations
        # except KeyError:
        #     printlog( "There is no database of calculations. I create new"); calc = {}
        


        try: header.conv = d[conv_key] #dictionary of convergence lists
        except KeyError:
            printlog( "There is no dictionary of convergence lists. I create new"); conv = {}   
        


        try: header.varset = d[varset_key] 
        except KeyError:
            printlog( "There is no dictionary of inputsets. I create new");  varset = {} 
        


        try: header.history = d[history_key] 
        except KeyError:
            header.history = ['Project started on '+ str( datetime.date.today() ) ]

            printlog( "There is still no history in database. The list is in header module ");
        


        try: header.struct_des = d[struct_des_key] 
        except KeyError:
            printlog( "There is no struct_des in database. The dict is in header module "); 

    d.close()
    #print history
    init_default_sets()


    return header.conv, header.varset, sys.getsizeof(d)
Exemple #48
0
def get_from_server(files = None, to = None, to_file = None,  addr = None, trygz = True):
    """
    Download files using either  paramiko (higher priority) or rcync; 
    For paramiko header.ssh_object should be defined

    files (list of str)  - files on cluster to download 
    to (str)      - path to local folder ! 
    to_file (str) - path to local file (if name should be changed); in this case len(files) should be 1 

    The gz file is also checked

    RETURN
        result of download

    TODO:
    now for each file new connection is opened, 
    copy them in one connection
 


    """

    def download(file, to_file):

        if header.ssh_object:

            exist = file_exists_on_server(file, addr)
            # try:
            if exist:
                printlog('Using paramiko: ssh_object.get(): from  to ', file, to_file)
                header.ssh_object.get(file,  to_file  )
                out = ''
            # except FileNotFoundError:
            else:
                out = 'file not found'

        else:
            out = runBash('rsync -uaz  '+addr+':'+file+ ' '+to_file)

        if out:
            res = out
        else:
            res = 'OK'

        printlog('Download result is ', res)

        return out



    if not is_list_like(files):
        files = [files]
    
    files = [file.replace('\\', '/') for file in files] #make sure the path is POSIX




    files_str = ', '.join(np.array(files ))
    printlog('Trying to download', files_str, 'from server', imp = 'n')
    


    for file in files:

        if not to and not to_file: #use temporary file
            with tempfile.NamedTemporaryFile() as f:
                to_file_l = f.name #system independent filename

        elif not to_file: #obtain filename
            to_file_l = os.path.join(to, os.path.basename(file) )
        
        else:
            to_file_l = to_file

        makedir(to_file_l)

        out = download(file, to_file_l)

        if out and trygz:

            printlog('File', file, 'does not exist, trying gz', imp = 'n')
            file+='.gz'
            to_file_l+='.gz'
            out = download(file, to_file_l)

            if out:
                printlog('    No gz either!', imp = 'n')
            else:
                gunzip_file(to_file_l)


    return out
Exemple #49
0
def det_gravity(dos, Erange=(-100, 0)):
    """Determine center of gravity for DOS and return values of energy for d6 orbitals in list
    INPUT:
    dos - ase dos type with added d6 - sum of d orbitals over neighbors to impurity atoms
    Erange - window of energy to determine center of gravity
    """
    sum_dos_E = {}
    sum_dos = {}
    sum_dos['d6'] = 0
    sum_dos_E['d6'] = 0

    for i, E in enumerate(dos.energy):

        if E < Erange[0]:
            continue

        if E > Erange[1]:
            break

        sum_dos['d6'] += dos.d6[i]
        sum_dos_E['d6'] += dos.d6[i] * E

    d6_gc = sum_dos_E['d6'] / sum_dos['d6']

    if 0:  #old
        nn = 13
        sum_dos_E = [0 for i in range(nn)]
        sum_dos = [0 for i in range(nn)]

        i = -1
        for E in st.dos[0]:

            i += 1
            if E < -6: continue
            if E > 0: break
            l = 1  #s
            sum_dos_E[l] += st.dos[l][i] * E
            sum_dos[l] += st.dos[l][i]
            l = 2  #p
            sum_dos_E[l] += st.dos[l][i] * E
            sum_dos[l] += st.dos[l][i]
            l = 3  #d
            sum_dos_E[l] += st.dos[l][i] * E
            sum_dos[l] += st.dos[l][i]
            l = 0  #p+d
            sum_dos_E[l] += (st.dos[2][i] + st.dos[3][i]) * E
            sum_dos[l] += st.dos[2][i] + st.dos[3][i]
            l = 11  #full
            sum_dos_E[l] += st.dos[l][i] * E
            sum_dos[l] += st.dos[l][i]
            l = 12  #s+p+d
            sum_dos_E[l] += (st.dos[1][i] + st.dos[2][i] + st.dos[3][i]) * E
            sum_dos[l] += st.dos[1][i] + st.dos[2][i] + st.dos[3][i]

        #Determine center of DOS
        st.Ec = [0 for i in range(nn)]
        #    if debug: print "Gravity Centers for s,p,d are (eV):"

        for l in 1, 2, 3, 0, 11, 12:
            if sum_dos[l] <= 0:
                printlog('err 123')
                sum_dos[l] = 0.00001
            st.Ec[l] = sum_dos_E[l] / sum_dos[l]
            # if debug: print st.Ec[l]

    return d6_gc
Exemple #50
0
def create_supercell(st, mul_matrix, test_overlap = False, mp = 2, bound = 0.01): 
    """ 
    st (Structure) -  
    mul_matrix (3x3 ndarray of int) - for example created by *ortho_    vec()* 


    bound (float) - shift (A) allows to correctly account atoms on boundaries
    mp    (int)  include additionall atoms before cutting supecell
    test_overlap (bool) - check if atoms are overlapping -  quite slow
    """ 
    sc = copy.deepcopy(st) 

    sc.rprimd = list(np.dot(mul_matrix, st.rprimd  ))
    printlog('New vectors (rprimd) of supercell:\n',np.round(sc.rprimd,1), imp = 'y', end = '\n')
    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
    sc_natom = sc.vol/st.vol*st.natom # test
    printlog('The supercell should contain', sc_natom, 'atoms ... ', imp = 'y', end = ' ')
    sc.xcart = []
    sc.typat = []
    sc.xred  = []
    #find range of multiplication
    mi = np.min(mul_matrix, axis = 0)
    ma = np.max(mul_matrix, axis = 0)
    mi[mi>0] = 0  # 

    # print(mi, ma)


    # find bound values
    lengths = np.linalg.norm(sc.rprimd, axis = 1)
    bounds = bound/lengths # in reduced coordinates


    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):
            
            if all([0-b <= r < 1-b for r, b in zip(xr, bounds)]): #only that in sc.rprimd box are needed
                sc.xcart.append( xc )
                sc.xred.append ( xr )
                sc.typat.append( t  )
    

    sc.natom = len(sc.xcart)
    sc.magmom = [None]


    if abs(sc.natom - sc_natom)>1e-5: #test 1, number of atoms
        printlog('Error! Supercell contains wrong number of atoms:', sc.natom  , 'instead of', sc_natom, 
            'try to increase *mp* of change *bound* ')

    else:
        printlog('OK', imp = 'y')
    
    if test_overlap: #test 2: overlapping of atoms
        enx = list(enumerate(sc.xcart))
        for (i1, x1), (i2, x2) in itertools.product(enx, enx):
            # print image_distance(x1, x2, sc.rprimd)[0]
            if i1 != i2 and image_distance(x1, x2, sc.rprimd)[0] < 0.1: #less than 0.1 Angstrom
                printlog('Error! Atoms in supercell are overlapping. Play with *bound*')



    return sc