Beispiel #1
0
    def set_vaspp(self, token, arg, des = "see manual"):
        """
        Used for setting vasp parameters.

        """


        if token in ("ISMEAR",):
            if type(arg) not in [int, None, ]:
                raise TypeError
        if token in ("KSPACING",):
            if type(arg) not in [float, None, ]:
                raise TypeError


        old = self.vasp_params[token]
        self.vasp_params[token] = arg
        
        if old == arg:
            print_and_log("Warning! You did not change  "+token+"  in "+self.ise+" set\n")
        else:
            self.history += " "+token+"  was changed from "+str(old)+" to "+str(arg) + "\n"
            print_and_log(token+"  was changed from "+str(old)+" to "+str(arg) +" - "+ des+" in set "+self.ise+" \n")
        
        self.update()                

        return
Beispiel #2
0
def read_vectors(token, number_of_vectors, list_of_words):
    """Returns the list of numpy vectors for the last match"""

    number_of_matches = list_of_words.count(token)
    if number_of_matches == 0:
        #print_and_log("Warning token '"+token+"' was not found! return empty\n")
        return [None]

    if number_of_matches > 1:
        print_and_log("Warning token '" + token +
                      "' was found more than one times\n")
        raise RuntimeError

    index = list_of_words.index(token, number_of_matches -
                                1)  #Return the index of the last match
    #print list_of_words[index]
    list_of_vectors = []
    vector = np.zeros((3))
    for i in range(number_of_vectors):
        vector[0] = float(list_of_words[index + 1])
        vector[1] = float(list_of_words[index + 2])
        vector[2] = float(list_of_words[index + 3])
        index += 3
        list_of_vectors.append(vector.copy())
    return list_of_vectors
Beispiel #3
0
 def set_relaxation_type(self,type_of_relaxation):
     name = "Type of relaxation ISIF"
     if type(type_of_relaxation) not in [str, ]:
         raise TypeError
     old = self.vasp_params["ISIF"]
     if "ions" == type_of_relaxation:
         if int(self.ise[0]) != 9:
             print_and_log("Warning! The name of set is uncostintent with relaxation type\n")
             raise TypeError     
         self.vasp_params["ISIF"] = 2
         # self.set_nmdsteps(200)
     elif type_of_relaxation == "full":
         if int(self.ise[0]) != 2:
             print_and_log("Warning! The name of set is uncostintent with relaxation type\n")
             raise TypeError              
         self.vasp_params["ISIF"] = 3
     else:
         print_and_log("Error! Uncorrect type of relaxation\n")
         raise TypeError
     arg = self.vasp_params["ISIF"]
     if old == arg:
         print_and_log("Warning! You did not change  "+name+"  in "+self.ise+" set\n")
         return
     self.history += " "+name+"  was changed from "+str(old)+" to "+str(arg) + "\n"
     print_and_log(name+"  was changed from "+str(old)+" to "+str(arg) + " in set "+self.ise+" \n")
     self.update()                
     #print self.history
     return
Beispiel #4
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
Beispiel #5
0
    def load(self, param, inplace=False):
        """
        Update parameters of set from dict param
        """
        # print(param)

        if inplace:
            s = self
        else:
            s = copy.deepcopy(self)

        for key in param:

            if key in vasp_keys:
                s.set_vaspp(key, param[key])

            elif key == 'set_potential':
                for key2 in param[key]:
                    # print key2, 'key2'
                    s.set_potential(key2, param[key][key2])

            elif key == 'add_nbands':
                # print param[key]

                s.set_add_nbands(param[key])

            elif key == 'ngkpt':
                s.set_ngkpt(param[key])

            elif key == 'bfolder':
                print_and_log('New blockfolder', param[key])

            elif key in siman_keys:
                s.set_attrp(key, param[key])

            elif key in aims_keys:
                s.set_vaspp(key, param[key])

            else:
                print_and_log('Error! Uknown key: ' + key)
                raise RuntimeError

            if key == 'set_sequence':
                sets = []
                for se in s.set_sequence:
                    sets.append(copy.deepcopy(header.varset[se]))

                s.set_sequence = sets  #put objects instead of names

            # if hasattr(s, 'set_sequence') and s.set_sequence:
            #     sets = []
            #     for se in s.set_sequence:
            #         if type(se) == str:
            #             sets.append(copy.deepcopy(varset[se]))
            #         else:
            #             sets.append(copy.deepcopy(se))

            #     s.set_sequence = sets  #put objects instead of names
        return s
Beispiel #6
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' )
Beispiel #7
0
 def add_conv_kpoint(self, arg):
     if type(arg) is not str:
         sys.exit("\nadd_conv_kpoint error\n")
     if arg in self.conv_kpoint:
         print_and_log("Warning! You already have this name in list")
         return
     self.conv_kpoint.append(arg)
     self.history += "Name " + arg + " was added to self.conv_kpoint\n"
     self.update()
Beispiel #8
0
def determine_unique_final(st_pores, sums, avds, x_m):

    final_table = []
    insert_positions = []
    """Please determine unique positions with similar distances taking into acc PBC!!!
    below is incorrect
    """
    # 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', imp = 'y')

    # xcart_unique = []
    # avds_unique  = []
    # sums_unique  = []

    # for i, s in enumerate(sums_crude):
    #     index_of_first =  np.where(sums.round(crude_prec)==s)[0][0]
    #     xcart_unique.append(st_pores.xcart[index_of_first])
    #     avds_unique.append(avds[index_of_first] )
    #     sums_unique.append(sums[index_of_first] )

    # st_pores_unique = copy.deepcopy(st_pores)

    # st_pores_unique.xcart = xcart_unique
    # st_pores_unique.xcart2xred()

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

    # print('neb.determine_unique_final(): sur',  sur)

    print_and_log('I can suggest you ' + str(len(sur[0])) + ' end positions.',
                  imp='y')

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

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

    return sur
Beispiel #9
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
Beispiel #10
0
 def add_conv_tsmear(self,arg):
     if type(arg) is not str:
         sys.exit("\nadd_conv_tsmear type error\n")
     try:
         self.conv_tsmear[0]
     except AttributeError:
         print_and_log( "Error! Set "+self.ise+" does not have conv_tsmear, I create new\n")
         self.conv_tsmear = []
     if arg in self.conv_tsmear:
         print_and_log( "Warning! You already have this name in list", imp = 'y')
         return    
     self.conv_tsmear.append(arg)
     self.history += "Name "+arg+" was added to self.conv_tsmear\n"
     self.update()
Beispiel #11
0
 def add_conv(self, arg, type_of_conv):
     if type(arg) is not str:
         raise TypeError
     if type_of_conv not in [
             "kpoint_conv", "tsmear_conv", "ecut_conv", "nband_conv",
             "npar_conv"
     ]:
         raise TypeError
     try:
         self.conv[type_of_conv][0]
     except AttributeError:
         print_and_log("Warning! Set " + self.ise +
                       " does not have conv, I create new\n")
         self.conv = {}
     except KeyError:
         print_and_log(
             "Warning! Set " + self.ise +
             " does not have list for this key in conv, I add new\n")
         self.conv[type_of_conv] = []
     except IndexError:
         pass
     if arg in self.conv[type_of_conv]:
         print_and_log( "Warning! You already have name %s in list of conv %s. Nothing done.\n" % \
         (str(arg), str(self.conv[type_of_conv])    ) )
         return
     self.conv[type_of_conv].append(arg)
     self.history += "Name " + arg + " was added to self.conv[" + type_of_conv + "]\n"
     print_and_log("Name " + arg + " was added to self.conv[" +
                   type_of_conv + "] of set " + self.ise + " \n")
     self.update()
Beispiel #12
0
def gb_energy_volume(gb,bulk):
    if (gb.end.rprimd[1] != bulk.end.rprimd[1]).any() or (gb.end.rprimd[2] != bulk.end.rprimd[2]).any():
        print_and_log("Warning! You are trying to calculate gb_energy from cells with different lateral sizes:"+str(gb.end.rprimd)+" "+str(bulk.end.rprimd)+"\n")
    #print bulk.vol
    V_1at = bulk.vol / bulk.natom #* to_ang**3

    E_1at = bulk.energy_sigma0 / bulk.natom 
    A = np.linalg.norm( np.cross(gb.end.rprimd[1], gb.end.rprimd[2])  ) #surface area of gb
    #print A
    gb.v_gb =      ( gb.vol              - V_1at * gb.natom) / A / 2. * 1000
    gb.e_gb =      ( gb.energy_sigma0    - E_1at * gb.natom) / A / 2. * eV_A_to_J_m * 1000
    gb.e_gb_init = ( gb.list_e_sigma0[0] - E_1at * gb.natom) / A / 2. * eV_A_to_J_m * 1000
    gb.bulk_extpress = bulk.extpress     
    #print "Calc %s; e_gb_init = %.3f J/m^2; e_gb = %.3f J/m; v_gb = %.3f angstrom "%(gb.name, gb.e_gb_init, gb.e_gb, gb.v_gb )
    outst = "%15s&%7.0f&%7.0f"%(gb.name, gb.e_gb, gb.v_gb)
    return outst
Beispiel #13
0
def calc_ac(a1, c1, a2, c2, a_b = 0.1, c_b = 0.1, type = "two_atoms"):
    """
    Calculate values of hexagonal lattice parameters for cell with two different atoms.
    The used assumption is:
    1. Provided lattice constants are for large enougth cells, in which excess volume (dV) of impurity does not depend on the size of cell.
    2. Two atoms do not interact with each other, which allows to use dV(CO) = dV(C) + dV(O)
    
    Two regimes:
    two_atoms - calculate cell sizes if additional atom was added
    double_cell - if cell was doubled; only first cell and second_cell are needed


    Input:
    a1, c1 - lattice constants of cell with first impurity atom (first cell)
    a2, c2 - lattice constants of cell with second impurity atom (second cell)
    a_b, c_b - lattice constants of cell with pure hexagonal metall
    
    Output:
    a, c - lattice constants of cell with two atoms
    """
    hstring = ("%s    #on %s"% (traceback.extract_stack(None, 2)[0][3],   datetime.date.today() ) )
    if hstring != header.history[-1]: header.history.append( hstring  )
    
    A = (a1**2 * c1) + (a2**2 * c2) - (a_b**2 * c_b)
    B = 0.5 * (c1/a1 + c2/a2)
    C = ( (a1**2 * c1) + (a2**2 * c2) ) * 0.5 #sum of cell volumes divided by 2 since during the construction of new cell we will use multiplication by 2
    # print "A,B=",A,B
    a = (A/B)**(1./3)
    c = a * B
    a = round(a,5)
    c = round(c,5)
    print_and_log( "a, c, c/a for cell with pure    hcp ", a_b, c_b, round(c_b/a_b,4), imp ='y' )
    print_and_log( "a, c, c/a for cell with first  atom ", a1, c1, round(c1/a1,4), imp ='y' )
    print_and_log( "a, c, c/a for cell with second atom ", a2, c2, round(c2/a2,4), imp ='y' )

    #for double cell
    a3 = (C/B)**(1./3)
    c3 = a3 * B
    a3 = round(a3,5)
    c3 = round(c3,5)    

    if type == "two_atoms":
        print_and_log( "a, c, c/a for cell with two   atoms ", a,  c, round(c/a,4), "# the same cell but with two atoms\n", imp ='y')
    elif type == "double_cell":
        print_and_log( "a, c, c/a for new cell              ", a3,  c3, round(c3/a3,4), "# for cell with V = V(first_cell) + V(second cell), but only for the case if V(second cell) == V(first_cell)", imp ='y')

    return a, c
Beispiel #14
0
def calculate_voronoi(self, state = 'end'):
    # By default two quantities per atom are calculated by this compute. 
    # The first is the volume of the Voronoi cell around each atom. 
    # Any point in an atom's Voronoi cell is closer to that atom than any other. 
    # The second is the number of faces of the Voronoi cell, which 
    # is also the number of nearest neighbors of the atom in the middle of the cell. 
    # state - init or end; if init then saved in self.init.vorovol; if end than saved in self.vorovol

    write_lammps(self, state, filepath = 'voronoi_analysis/structure.lammps') #write structure for lammps
    runBash("rm voronoi_analysis/dump.voro; /home/aksenov/installed/lammps-1Feb14/src/lmp_serial < voronoi_analysis/voronoi.in > voronoi_analysis/log")

    if state == 'end':
        self.vorovol = []
        self.vorofaces = []
        vorovol = self.vorovol
        vorofaces = self.vorofaces
    elif state == 'init':
        self.init.vorovol = []
        self.init.vorofaces = []
        vorovol = self.init.vorovol
        vorofaces = self.init.vorofaces        

    vsum=0
    wlist = []    
    with open('voronoi_analysis/dump.voro','r') as volfile:  #analyze dump.voro
        for line in volfile:
            if 'ITEM: ATOMS ' in line:
                break
        for line in volfile:
            ll = line.split()
            if int(ll[1]) > 1:
                wlist.append( [ll[0], ll[5], ll[6], ll[2]] )
            # print 'Volume of atom ',ll[0],'is', ll[5]
            vsum= vsum+float(ll[5])
        print_and_log( 'Check total volume ', vsum, self.end.vol)

        wlist.sort(key = itemgetter(0)) #sort according to the position of atoms
        print_and_log( "atom #, voronoi vol, voronoi faces, x coordinate: ", )
        print_and_log( wlist)
        for w in wlist:
            vorovol.append(float(w[1]))
            vorofaces.append(int(w[2]))
        # print 'Voro vol  ',self.end.vorovol
        # print 'Voro faces',self.end.vorofaces
        # print len(wlist)
    if hasattr(self, 'vorovol'): 
        voro = ''
        if len(vorovol) == 2: #C and O
            voro = " {0:5.2f} & {1:2d} & {2:5.2f} & {3:2d} ".format(vorovol[0], vorofaces[0], vorovol[1], vorofaces[1]  ).center(25)
        else: 
            voro = " {0:5.2f} & {1:2d} ".format(vorovol[0], vorofaces[0] ).center(25)
        voro+='&'
    else:
        voro = ""
    print_and_log( "Voronoi volume = ", voro, imp = 'y')
    return voro
Beispiel #15
0
def read_vectors(token,
                 number_of_vectors,
                 list_of_words,
                 type_func=None,
                 lists=False):
    """Returns the list of numpy vectors for the last match"""
    # lists - return list of lists instead list of vectors

    if type_func is None:
        type_func = lambda a: float(a)

    number_of_matches = list_of_words.count(token)
    if number_of_matches == 0:
        #print_and_log("Warning token '"+token+"' was not found! return empty\n")
        return [None]

    if number_of_matches > 1:
        print_and_log("Warning token '" + token +
                      "' was found more than one times\n")
        raise RuntimeError

    index = list_of_words.index(token, number_of_matches -
                                1)  #Return the index of the last match
    #print list_of_words[index]
    list_of_vectors = []
    list_of_lists = []
    vector = np.zeros((3))
    for i in range(number_of_vectors):
        vector[0] = type_func(list_of_words[index + 1])
        vector[1] = type_func(list_of_words[index + 2])
        vector[2] = type_func(list_of_words[index + 3])
        list3 = []
        for j in 1, 2, 3:
            list3.append(type_func(list_of_words[index + j]))

        index += 3
        list_of_vectors.append(vector.copy())
        list_of_lists.append(list3)

    if lists:
        out = list_of_lists
    else:
        out = list_of_vectors

    return out
Beispiel #16
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
Beispiel #17
0
def element_name_inv(el):
    el_dict = header.el_dict
    nu_dict = header.nu_dict
    # print type(el), el, type(str('sdf') )
    if is_string_like(el):
        try:
            elinv = el_dict[el]
        except:
            print_and_log("Error! Unknown element: " + str(el))
            raise RuntimeError
    else:
        el = int(el)
        try:
            elinv = nu_dict[el]
        except:
            print_and_log("Error! Unknown element: " + str(el))
            raise RuntimeError

    return elinv  # inversed notion of element
Beispiel #18
0
 def set_add_nbands(self,arg):
     name = "add_nbands"  
     # print(type(arg))
     if type(arg) not in [float, int, type(None) ]:
         raise TypeError
     try: 
         self.add_nbands
     except AttributeError: 
         self.add_nbands = None
     
     old = self.add_nbands    
     
     self.add_nbands = arg
     
     if old == arg:
         print_and_log("Warning! You did not change  "+name+"  in "+self.ise+" set\n")
         return
     self.history += " "+name+"  was changed from "+str(old)+" to "+str(arg) + "\n"
     print_and_log(" "+name+"  was changed from "+str(old)+" to "+str(arg) + " in set "+self.ise+" \n")
     return
Beispiel #19
0
def determine_unique_voids(st_pores, sums, avds):
    crude_prec = 1  # number of signs after 0

    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',
                  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=['void #', 'Cart.', 'Index', 'Dev.', 'Sum'],
                           tablefmt='psql'),
                  imp='Y')

    return insert_positions
Beispiel #20
0
    def set_attrp(self, token, arg, des="see manual"):
        """
        set any attribute.

        """
        # print (token)
        if hasattr(self, token):
            old = getattr(self, token)
            if old == arg:
                print_and_log("Warning! You did not change  " + token +
                              "  in " + self.ise + " set\n")
            else:
                setattr(self, token, arg)

                self.history += " " + token + "  was changed from " + str(
                    old) + " to " + str(arg) + "\n"
                print_and_log(token + "  was changed from " + str(old) +
                              " to " + str(arg) + " - " + des + " in set " +
                              self.ise + " \n")

        else:
            setattr(self, token, arg)
            print_and_log("New attribute  " + token + "  added to " +
                          self.ise + " set\n")
            self.history += " " + token + "  was added as a new attr with " + str(
                arg) + " value \n"

        return
Beispiel #21
0
def inherit_iset(ise_new,
                 ise_from,
                 varset,
                 override=False,
                 newblockfolder=None):
    """ Create new set copying from existing and update some fields. If ise_from does not exist create new"""

    ise_new = ise_new.strip()
    ise_from = ise_from.strip()

    if ise_from not in varset:
        print_and_log("\nError! Set " + ise_from +
                      " does not exist. I return new empty set\n")
        return InputSet(ise_new)

    old = varset[ise_from]

    for key in vasp_electronic_keys + vasp_ionic_keys + vasp_other_keys:  #check if new keys was added
        if key not in old.vasp_params:
            old.vasp_params[key] = None

    if override:
        print_and_log("\nAttention! You have chosen to override set " +
                      ise_new + "\n")
    elif ise_new in varset:
        print_and_log(
            "\nSet " + ise_new +
            " already exists. I return it without changes. Be carefull not to spoil it\n"
        )
        return varset[ise_new]

    new = copy.deepcopy(old)
    new.ise = ise_new
    new.compare_with = ise_from + " "
    new.des = "no description for these set, see history"
    new.conv = {}

    print_and_log("New set " + ise_new + " was inherited from set " +
                  ise_from + "\n")
    new.history = old.history + "\nSet " + ise_new + " was inherited from: " + ise_from + "\n"

    if newblockfolder:
        new.history += 'blockfolder changed from ' + new.blockfolder + ' to ' + newblockfolder + '\n'
        new.blockfolder = newblockfolder

    varset[ise_new] = new

    return new
Beispiel #22
0
    def test_adding_of_impurities(added, init, v):
        """
        Can be used only inside add_impurity()
        Replicates the structure and find again pores
        """
        global natoms_v1
        if added == None: return
        if v == 1:  #TEST

            natoms_v1 = len(added.init.xcart)  # for test
            st_rep_after = added.init.replic((1, 2, 1))

            rep = copy.deepcopy(init)

            rep.init = rep.init.replic((1, 2, 1))
            #print rep
            rep = add(znucl, "", rep, write_geo=False)
            #print rep
            #print "xcart of replic after adding ", st_rep_after.xcart
            #print "xcart of adding to    replic ", rep.init.xcart
            if len(st_rep_after.xcart) != len(rep.init.xcart):
                raise RuntimeError
            p = 0
            #for x2 in st_rep_after.xcart:
            #    print x2
            for x in rep.init.xcart:
                a = any((np.around(x2, p) == np.around(x, p)).all()
                        for x2 in st_rep_after.xcart)
                #b = any(  ( np.ceil(x2, p)   == np.ceil(x, p)  ).all()  for x2 in st_rep_after.xcart   )
                #c = any(  ( np.floor(x2, p)  == np.floor(x, p) ).all()  for x2 in st_rep_after.xcart   )
                #print a, b, c
                #np.concatenate(a, b, c):
                if not a:
                    print_and_log("Error! Can't find ", np.around(x, 3),
                                  "in replic  ")
                    raise RuntimeError

            #assert all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(st_rep_after.xcart, rep.init.xcart) ])
            print_and_log("add_impurity: test succesfully done")

        if natoms_v1 != len(added.init.xcart):
            print_and_log(
                "You have different number of pores in different versions\n")
            raise RuntimeError
        return
Beispiel #23
0
def insert(it_ins, ise_ins, mat_path, it_new, calc, type_of_insertion="xcart"):
    """For insertion of atoms to cells with changed lateral sizes
    Input:
    'type_of_insertion = xred' used to add xred coordinates  
    mat_path - path to geo files which are supposed to be changed
    it_ins - already existed calculation; xred will be used from this calculation.
    it_new - new folder in geo folder for obtained structure
    
    This function finds version of calculation in folder mat_path and tries to use the same version of it_ins

    """
    if not os.path.exists(mat_path):
        print_and_log("Error! Path " + mat_path + " does not exist\n\n")
        raise RuntimeError

    if it_ins not in mat_path and it_ins not in it_new:
        print_and_log('Cells are', it_ins, mat_path, it_new)
        print_and_log(
            "Error! you are trying to insert coordinates from cell with different name\n\n"
        )
        #raise RuntimeError

    hstring = ("%s    #on %s" %
               (traceback.extract_stack(None, 2)[0][3], datetime.date.today()))
    if hstring != header.history[-1]: header.history.append(hstring)

    geofilelist = runBash('find ' + mat_path +
                          '/target -name "*.geo*" ').splitlines()

    if geofilelist == []:
        print_and_log(
            "Warning! Target folder is empty. Trying to find in root folder ..."
        )
        geofilelist = runBash('find ' + mat_path +
                              '/ -name "*.geo*" ').splitlines()

    ins = None
    for mat_geofile in geofilelist:
        mat = CalculationVasp()
        mat.name = mat_geofile
        mat.read_geometry(mat_geofile)
        #step = 0.27
        #r_pore = 0.56
        #r_mat = mat.hex_a / 2 - step
        #pores = find_pores(mat.init, r_mat, r_pore, step, 0.3, 'central') #octahedral
        #mat.xcart.append ( pores.xcart[0] )
        #mat.typat.append(1)
        try:
            ins_working = ins
            ins = calc[(it_ins, ise_ins, mat.version)]
        except KeyError:
            print_and_log("No key", (it_ins, ise_ins, mat.version),
                          "I use previous working version !!!",
                          imp='y')
            ins = ins_working
            #return
        #ins.end.znucl = ins.znucl
        #ins.end.nznucl = ins.nznucl
        #ins.end.ntypat = ins.ntypat
        #ins.end.typat = ins.typat
        #print ins.xcart[-1]
        mat_geopath = geo_folder + struct_des[it_new].sfolder + '/'

        if type_of_insertion == "xcart":
            #Please update here!
            mat_filename = '/' + it_new + "." + "inserted." + str(
                mat.version) + '.' + 'geo'

            v = np.zeros(3)
            result = insert_cluster(ins.end, v, mat.init, v)
            mat.end = result
            mat.init = result
            # mat.znucl  =   mat.end.znucl
            # mat.nznucl =   mat.end.nznucl
            # mat.ntypat =   mat.end.ntypat
            # mat.typat  =   mat.end.typat
            # mat.natom = len(mat.end.xred)
            #mat.version = ins.version
            des = ins.name + " was inserted to " + mat_geofile

        elif type_of_insertion == "xred":

            mat_filename = '/from/' + it_new + ".xred." + str(
                mat.version) + '.' + 'geo'

            #mat.end.rprimd = mat.rprimd
            #mat.init.xred  = copy.deepcopy(ins.end.xred)
            #mat.init.typat = copy.deepcopy(ins.end.)
            #print ins.end.xcart
            rprimd = copy.deepcopy(mat.init.rprimd)
            #build    = mat.build
            mat.init = copy.deepcopy(ins.end)
            #mat.build = build
            mat.init.rprimd = rprimd  #return initial rprimd
            mat.init.xred2xcart()  #calculate xcart with new rprimd

            des = "atoms with reduced coord. from " + ins.name + " was fully copied to " + mat_geofile
            mat.init.name = 'test_insert_xred' + str(mat.version)
            write_xyz(mat.init)

        mat.path["input_geo"] = mat_geopath + it_new + mat_filename
        if not mat.write_geometry("init", des): continue
        print_and_log("Xred from " + it_ins + " was inserted in " +
                      mat_geofile + " and saved as " + mat_filename + " \n\n")

    return
Beispiel #24
0
def insert_cluster(insertion, i_center, matrix, m_center):
    """
    Take care of orientation; typat should be consistent
    Input:
    insertion -  object of class Structure(), which is supposed to be inserted in matrix
    in such a way that i_center will be combined with m_center.
    matrix - object of class Structure().
    i_center, m_center - numpy arrays (3) cartesian coordinates
    """
    ins = copy.deepcopy(insertion)
    mat = copy.deepcopy(matrix)
    r = mat.rprimd

    hproj = [(r[0][i] + r[1][i] + r[2][i]) * 0.5
             for i in (0, 1, 2)]  #projection of vectors on three axis
    if 1:
        for i, x in enumerate(ins.xcart):
            ins.xcart[i] = x - i_center

        for i, x in enumerate(mat.xcart):
            mat.xcart[i] = x - m_center

    max_dis = 1
    for i_x, ix in enumerate(ins.xcart):
        dv_min = max_dis
        print_and_log(
            "Insertion atom ",
            ix,
        )
        if 1:
            for j, mx in enumerate(mat.xcart):
                dv = mx - ix
                for i in 0, 1, 2:
                    if dv[i] > hproj[i]:
                        dv = dv - mat.rprimd[
                            i]  #periodic boundary conditions - can be not correct (in the sense that closest image can lie not 100 % in the neighbourhood image cell ) for oblique cells and large absolute values of dv
                    if dv[i] < -hproj[i]: dv = dv + mat.rprimd[i]

                len1 = np.linalg.norm(dv)
                len2, second_len2 = mat.image_distance(mx, ix, r,
                                                       1)  #check len1

                #print "Lengths calculated with two methods ", len1, len2
                len1 = len2  #just use second method
                #assert np.around(len1,1) == np.around(len2,1)

                if len1 < dv_min:
                    dv_min = len1
                    j_r = j  # number of matrix atom to replace

        if 1:
            #Modify to replace overlapping atoms
            if dv_min == max_dis:
                print_and_log(" is more far away from any matrix atom than ",
                              dv_min, " A; I insert it")
                # mat.xcart.append( ix )
                # print_and_log( 'type of added atom is ', ins.typat[i_x])
                # mat.typat.append( ins.typat[i_x]   )
                mat = mat.add_atom(xc=ix, element=ins.get_elements()[i_x])

            else:
                print_and_log("will replace martix atom", mat.xcart[j_r])
                mat.xcart[j_r] = ix.copy()

    mat.rprimd = r
    mat.xcart2xred()
    mat.natom = len(mat.xcart)
    mat.name = 'test_of_insert'
    st = mat
    # print(st.natom, len(st.xcart), len(st.typat), len(st.znucl), max(st.typat) )
    # write_xyz(mat)
    mat = mat.return_atoms_to_cell()
    mat.write_poscar()
    return mat
Beispiel #25
0
    def add(znucl, xyzpath="", new=None, write_geo=True, put_exactly_to=None):
        "if put_exactly_to is True, then atom just added and nothing are searched"

        if write_geo and os.path.exists(
                new.path["input_geo"]) and not override:
            print_and_log("add: File '" + new.path["input_geo"] +
                          "' already exists; continue\n",
                          imp='Y')
            return new

        #new.init = return_atoms_to_cell(new.init)
        if replace_atom:
            #atom substitution
            if znucl not in new.init.znucl:
                new.init.znucl.append(znucl)
                new.init.ntypat += 1
                new.init.typat[replace_atom] = new.init.ntypat
            else:
                ind = new.init.znucl.index(znucl)
                new.init.typat[replace_atom] = ind + 1
            new.init.nznucl = []
            for typ in range(1, new.init.ntypat + 1):
                new.init.nznucl.append(new.init.typat.count(typ))

        else:
            new_before = copy.deepcopy(new)

            # new.init.xcart[-2][0]-=0.9 #was made once manually for c1gCOi10.1
            # new.init.xcart[-2][2]+=0.2
            # new.init.xred = xcart2xred(new.init.xcart, new.init.rprimd)
            write_xyz(new.init)
            #step = 0.042
            step = 0.06
            #r_pore = 0.56
            #fine = 0.3 # for visualisation of pores
            #fine = 4   #controls small steps; the steps are smaller for larger numbers
            #r_pore = 0.54
            prec = 0.004  # precision of center Angs
            if new.hex_a == None:
                r_mat = 1.48 - step
            else:
                r_mat = new.hex_a / 2 - step

            if put_exactly_to:
                pores_xred = [
                    np.array(put_exactly_to),
                ]
                print_and_log('Inmpurity just put in ', pores_xred, imp='Y')
            else:
                pores = find_pores(new.init, r_mat, r_pore, step, fine, prec,
                                   addtype, new.gbpos, find_close_to,
                                   check_pore_vol)  #octahedral
                pores_xred = pores.xred

            npores = len(pores_xred)

            st = new.init

            #delete last oxygen; was made once manually for c1gCOi10.1
            # st.natom-=1
            # del st.xred[-1]
            # del st.typat[-1]

            st.natom += npores
            st.xred.extend(pores_xred)

            if znucl in st.znucl:
                print_and_log("znucl of added impurity is already in cell")
                ind = st.znucl.index(znucl)
                typat = ind + 1
                st.nznucl[ind] += npores
            else:
                st.ntypat += 1
                typat = st.ntypat
                st.znucl.append(znucl)
                st.nznucl.append(npores)

            for i in range(npores):
                st.typat.append(typat)

            st.xred2xcart()

            new.init = st

            #print "Add impurity: len(xred ", len(new.init.xred)
            #print "natom", new.init.natom

            #For automatisation of fit
            try:
                #new.build
                if new.build.nadded == None: new.build.nadded = npores
                else: new.build.nadded += npores
                if new.build.listadded == [None]:
                    new.build.listadded = range(
                        new.natom - npores,
                        new.natom)  #list of atoms which were added
                else:
                    new.build.listadded.extend(
                        range(new.natom - npores, new.natom))
                #print "Warning!!! Information about added impurities rewritten"
            except AttributeError:
                pass

            #new.init.znucl = new.znucl
            #new.init.typat = new.typat

            #write_xyz(replic(new.init, (2,1,2))  , xyzpath)

            #test_adding_of_impurities(new, new_before, v)

            print_and_log("Impurity with Z=" + str(znucl) +
                          " has been added to the found pore in " + new.name +
                          "\n\n")

        if write_geo:
            write_xyz(new.init, xyzpath)
            new.write_geometry("init", new.des, override=override)

        print_and_log("\n")

        return new
Beispiel #26
0
def find_pores(st_in,
               r_matrix=1.4,
               r_impurity=0.6,
               step_dec=0.05,
               fine=0.3,
               prec=0.1,
               calctype='central',
               gbpos=0,
               find_close_to=(),
               check_pore_vol=0):
    """
    st_in - input Structure() object
    r_impurity (A)- all pores smaller than this radius will be found
    r_matrix (A) - radius of matrix atoms disregarding to their type
    step_dec - scanning step of the cell in Angstroms
    fine - allows to change density of local points; local_step = step_dec/fine
    prec - precicion of pore center determination
    check_pore_vol - allows to estimate volume of pores; has problems for big cells


    'find_close_to' - works in the cases of gb and grain_vol; allows to ignore all and find pore close to provided three reduced coordinates
    return - instance of Structure() class with coordinates of pores. Number and type of included pores depend on the argument of 'calctype'.
    """

    xred = st_in.xred
    natom = len(xred)
    rprimd = st_in.rprimd
    name = st_in.name
    #print xred
    """Additional values"""
    # check_pore_vol = 1
    #if calctype in ("pore_vol","gb","grain_vol","all_local" ): check_pore_vol = 1 #something wrong with this function, especially for big cells
    """----Conversions of types for C++"""
    r1 = create_c_array(rprimd[0], float)
    r2 = create_c_array(rprimd[1], float)
    r3 = create_c_array(rprimd[2], float)

    xred1 = (c_float * len(xred))(*[x[0] for x in xred])
    xred2 = (c_float * len(xred))(*[x[1] for x in xred])
    xred3 = (c_float * len(xred))(*[x[2] for x in xred])

    max_npores = 10000
    ntot = ctypes.c_int32()
    npores = ctypes.c_int32()
    l_pxred1 = (c_float * max_npores)(0)  #make static arrays fol local points
    l_pxred2 = (c_float * max_npores)(0)
    l_pxred3 = (c_float * max_npores)(0)
    l_npores = (ctypes.c_int32 * max_npores)(0)

    pxred1 = (c_float * max_npores)(0)  #make static arrays natoms + npore
    pxred2 = (c_float * max_npores)(0)
    pxred3 = (c_float * max_npores)(0)
    """----Run C++ function"""
    print_and_log("Starting C++ function lib.findpores()...\n")
    # print(r_matrix, r_impurity, step_dec, fine, prec)
    lib.findpores ( check_pore_vol, \
                    max_npores, \
                    byref(ntot),   l_pxred1, l_pxred2, l_pxred3, l_npores, \
                    byref(npores), pxred1,   pxred2,   pxred3,  \
                    natom,         xred1,    xred2,    xred3, \
                    c_float(r_matrix), c_float(r_impurity), c_float(step_dec), c_float(fine), c_float(prec), \
                    r1, r2, r3 )

    print_and_log("ntot is ", ntot.value)
    print_and_log("l_npores[0] is ", l_npores[0])

    v = np.zeros((3))
    l_pxred = []
    shift1 = 0
    shift2 = 0
    for i_por in range(npores.value):
        l_pxred.append([])
        shift2 += l_npores[i_por]

        for i in range(shift1, shift2):
            v[0] = l_pxred1[i]
            v[1] = l_pxred2[i]
            v[2] = l_pxred3[i]

            l_pxred[i_por].append(v.copy())

        shift1 = shift2

    if shift2 != ntot.value:
        print_and_log("Error! final shift2 not equal to ntot")

    #print l_pxred[0]

    pxred = []  # only coordinates of pores
    #print pxred1[natom]
    for i in range(npores.value):
        v[0] = pxred1[i + natom]
        v[1] = pxred2[i + natom]
        v[2] = pxred3[
            i +
            natom]  #with shift, because first natom elements are coordinates of atoms
        pxred.append(v.copy())

    #print pxred
    """----End of C++; result is two lists: lpxred - local geometry of all pores, pxred - coordinates of all pores"""
    """ Analyse of pores """
    # st_result = Structure()
    st_result = st_in.new()

    st_result.rprimd = rprimd

    targetp = np.array((0., 0., 0.))
    if find_close_to:
        targetp = np.asarray(find_close_to)  #targer point
        print_and_log("Target point is                        ", targetp)

    a = step_dec / fine  #the side of little cube formed by the mesh which is used to find spheres inside the pore.
    aaa = a * a * a

    #find most central pore
    if calctype == 'central':  #return coordinates of the most central pore
        st_result.name = "central_pore_from " + name
        center = np.array((0.5, 0.5, 0.5))  #center of cell
        d_min = 100
        for x in pxred:
            d = np.linalg.norm(x - center)
            #print x, x-center, d
            if d < d_min and x[0] <= 0.5 and x[1] <= 0.5 and x[2] <= 0.5:
                d_min = d
                x_min = x
        print_and_log("The closest pore to the center has coordinates", x_min)
        st_result.xred.append(x_min)

    elif calctype == 'gb':  #add impurity at gb
        st_result.name = "gb_pore_from " + name
        d_min = 100
        #d2_min = 100
        dt_min = 100
        i_min = 0
        x_min = np.zeros((3))
        for i, x in enumerate(pxred):
            #print "l_npores ",l_npores[i]
            d = abs(x[0] - gbpos / rprimd[0][0])  #
            #print x[0], d
            if find_close_to: closer = (np.linalg.norm(targetp - x) < dt_min)
            else: closer = (d < d_min)  # and x[1]>0.3 and x[2]>0.3:

            if closer:
                x_pre = x_min
                i_pre = i_min
                d_min = d
                dt_min = np.linalg.norm(targetp - x)
                x_min = x
                i_min = i

            #find and add impurity in bulk
            #d2 = abs( x[0] - (gbpos/rprimd[0][0] - 0.25) )
            #if d2 < d2_min:
            #    d2_min = d2
            #    x2_min = x
            #    i2_min = i

        #print "rprimd[0][0]", rprimd[0][0]
        print_and_log("Position of boundary is ", gbpos / rprimd[0][0])

        #x_min[0] = gbpos/rprimd[0][0]
        if find_close_to:
            print_and_log(
                "The closest pore to the target point is [ %.2f  %.2f  %.2f ]"
                % (x_min[0], x_min[1], x_min[2]))
        else:
            print_and_log("The closest pore to the gb has coordinates", x_min)
        st_result.xred.append(x_min)
        #st_result.xred.append( x_pre )
        #Calculate volume of the pore using local balls:
        print_and_log("The number of pore is ", i_min, " ; It has ",
                      l_npores[i_min], "local balls")
        print_and_log("Volume of pore is ", l_npores[i_min] * a * a * a,
                      " A^3")
        #st_result.xred.extend( l_pxred[i_min] )
        #st_result.xred.extend( l_pxred[i_pre] )

        #print "The closest pore to the center of bulk has coordinates",x2_min
        #st_result.xred.append( x2_min )
        #Calculate volume of the pore using local balls:
        #print "The number of bulk pore is ",i2_min," ; It has ",l_npores[i2_min], "local balls"
        #print "Volume of pore is ", l_npores[i2_min] * a*a*a, " A^3";
        #st_result.xred.extend( l_pxred[i2_min] )

    elif calctype == 'grain_vol':  #add impurity to volume of grain
        st_result.name = "grain_volume_pore_from " + name
        d2_min = 100
        dt_min = 100
        i_min = 0
        x_min = np.zeros((3))
        for i, x in enumerate(pxred):
            #find and add impurity to the  bulk
            d2 = abs(x[0] - (gbpos / rprimd[0][0] - 0.25))

            if find_close_to: closer = (np.linalg.norm(targetp - x) < dt_min)
            else: closer = (d2 < d2_min)  # and x[1]>0.3 and x[2]>0.3:

            if closer:
                dt_min = np.linalg.norm(targetp - x)
                d2_min = d2
                x2_min = x
                i2_min = i

        if find_close_to:
            print_and_log(
                "The closest pore to the target point is [ %.2f  %.2f  %.2f ]"
                % (x2_min[0], x2_min[1], x2_min[2]))
        else:
            print_and_log(
                "The closest pore to the center of bulk has coordinates",
                x2_min)
        st_result.xred.append(x2_min)
        #Calculate volume of the pore using local balls:
        print_and_log("The number of bulk pore is ", i2_min, " ; It has ",
                      l_npores[i2_min], "local balls")
        print_and_log("Volume of pore is ", l_npores[i2_min] * a * a * a,
                      " A^3")
        st_result.xred.extend(l_pxred[i2_min])

    elif calctype == 'all_local':
        st_result.name = "all_local_points_from " + name
        v_max = 0
        i_max = 0
        for i in range(npores.value):
            v_pore = l_npores[i] * aaa
            print_and_log("Volume of pore is ", l_npores[i] * aaa, " A^3")
            if v_pore > v_max:
                v_max = v_pore
                i_max = i
        print_and_log("Pore number ", i_max, "has the largest volume ", v_max,
                      " A^3")
        # st_result.xred = l_pxred[i_max] # here coordinates of all local points to show geometry of pore with largerst volume
        st_result.xred = [x for group in l_pxred for x in group]  # all pores

    elif calctype == 'all_pores':
        st_result.name = "all_local_pores_from " + name
        st_result.xred = pxred

    st_result.rprimd = rprimd
    st_result.xred2xcart()
    st_result.typat = [1 for x in st_result.xred]
    st_result.ntypat = 1
    st_result.natom = len(st_result.typat)
    st_result.znucl = [200]
    st_ntypat = 1

    return st_result
Beispiel #27
0
def add_impurity(it_new,
                 impurity_type=None,
                 addtype='central',
                 calc=[],
                 r_pore=0.5,
                 it_to='',
                 ise_to='',
                 verlist_to=[],
                 copy_geo_from="",
                 find_close_to=(),
                 add_to_version=0,
                 write_geo=True,
                 only_version=None,
                 fine=4,
                 put_exactly_to=None,
                 check_pore_vol=0,
                 replace_atom=None,
                 override=False):
    """
    Add impurities in pores.

    Input:
    it_new - name of new structure with impurity
    
    impurity_type - name of impurity from Mendeley table, for example 'C'
    
    addtype - type of adding: ['central',]; 'central' means that impurity 
    will be placed as close to the geometrical center of cell as possible.
    
    it_to , ise_to , verlist_to - completed calculations in which impurity 
    will be added
    
    if 'verlist_to' is empty, function will try to find geometry files in 'geo_folder + struct_des[it_to].sfolder' folder;
    even if 'it_to' is empty it will try to find files in 'geo_folder + struct_des[it_new].sfolder+'/from' ' folder.
    'ise_to' also can be empty

    if 'copy_geo_from' is not empty, then programm copy all files from folder 'copy_geo_from' to 
    folder 'geo_folder + struct_des[it_to].sfolder+"/"+it_to' or  'geo_folder + struct_des[it_new].sfolder+"/from" '  

    'find_close_to' is tuple of three reduced coordinates of point close to which you want to find impurity. If empty - ignored; 

    'add_to_version' is integer number added to each 'verlist_to' number to produce ver_new.
    
    'only_version' - if == [v,], then instertion will be provided only for v. If None insertion will be made in all found versions

    If you want to add impurity to relaxed structure ...

    'fine' - integer number; allows to reduce number of small steps for defining center


    Possible addtype's:
    'central' - add one atom to the pore which is most close to  the center of the cell but with reduced coordinates less than 0.5 0.5 0.5
    'all_pore'  - add atoms in every found pore
    'all_local' - add atoms to every local point which allows to visualise topology of pores.
    'gb' - uses self.gbpos and places atom close to this value assuming that it will be at gb
    'grain_vol' - uses self.gbpos and assuming that cell contains two gb and two equal grains, places atom close to the centre of grain; y and z can be arbiratry


    put_exactly_to - will add impurity to this point 
    find_close_to - will try to find closest void and insert pore here.

    check_pore_vol - allows to estimate volume of pores; has problems for big cells

    replace_atom - if not None, than the specified atom is substituted


    Side effects: creates new geometry folder with input structures; 

    """

    struct_des = header.struct_des

    def test_adding_of_impurities(added, init, v):
        """
        Can be used only inside add_impurity()
        Replicates the structure and find again pores
        """
        global natoms_v1
        if added == None: return
        if v == 1:  #TEST

            natoms_v1 = len(added.init.xcart)  # for test
            st_rep_after = added.init.replic((1, 2, 1))

            rep = copy.deepcopy(init)

            rep.init = rep.init.replic((1, 2, 1))
            #print rep
            rep = add(znucl, "", rep, write_geo=False)
            #print rep
            #print "xcart of replic after adding ", st_rep_after.xcart
            #print "xcart of adding to    replic ", rep.init.xcart
            if len(st_rep_after.xcart) != len(rep.init.xcart):
                raise RuntimeError
            p = 0
            #for x2 in st_rep_after.xcart:
            #    print x2
            for x in rep.init.xcart:
                a = any((np.around(x2, p) == np.around(x, p)).all()
                        for x2 in st_rep_after.xcart)
                #b = any(  ( np.ceil(x2, p)   == np.ceil(x, p)  ).all()  for x2 in st_rep_after.xcart   )
                #c = any(  ( np.floor(x2, p)  == np.floor(x, p) ).all()  for x2 in st_rep_after.xcart   )
                #print a, b, c
                #np.concatenate(a, b, c):
                if not a:
                    print_and_log("Error! Can't find ", np.around(x, 3),
                                  "in replic  ")
                    raise RuntimeError

            #assert all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(st_rep_after.xcart, rep.init.xcart) ])
            print_and_log("add_impurity: test succesfully done")

        if natoms_v1 != len(added.init.xcart):
            print_and_log(
                "You have different number of pores in different versions\n")
            raise RuntimeError
        return

    def add(znucl, xyzpath="", new=None, write_geo=True, put_exactly_to=None):
        "if put_exactly_to is True, then atom just added and nothing are searched"

        if write_geo and os.path.exists(
                new.path["input_geo"]) and not override:
            print_and_log("add: File '" + new.path["input_geo"] +
                          "' already exists; continue\n",
                          imp='Y')
            return new

        #new.init = return_atoms_to_cell(new.init)
        if replace_atom:
            #atom substitution
            if znucl not in new.init.znucl:
                new.init.znucl.append(znucl)
                new.init.ntypat += 1
                new.init.typat[replace_atom] = new.init.ntypat
            else:
                ind = new.init.znucl.index(znucl)
                new.init.typat[replace_atom] = ind + 1
            new.init.nznucl = []
            for typ in range(1, new.init.ntypat + 1):
                new.init.nznucl.append(new.init.typat.count(typ))

        else:
            new_before = copy.deepcopy(new)

            # new.init.xcart[-2][0]-=0.9 #was made once manually for c1gCOi10.1
            # new.init.xcart[-2][2]+=0.2
            # new.init.xred = xcart2xred(new.init.xcart, new.init.rprimd)
            write_xyz(new.init)
            #step = 0.042
            step = 0.06
            #r_pore = 0.56
            #fine = 0.3 # for visualisation of pores
            #fine = 4   #controls small steps; the steps are smaller for larger numbers
            #r_pore = 0.54
            prec = 0.004  # precision of center Angs
            if new.hex_a == None:
                r_mat = 1.48 - step
            else:
                r_mat = new.hex_a / 2 - step

            if put_exactly_to:
                pores_xred = [
                    np.array(put_exactly_to),
                ]
                print_and_log('Inmpurity just put in ', pores_xred, imp='Y')
            else:
                pores = find_pores(new.init, r_mat, r_pore, step, fine, prec,
                                   addtype, new.gbpos, find_close_to,
                                   check_pore_vol)  #octahedral
                pores_xred = pores.xred

            npores = len(pores_xred)

            st = new.init

            #delete last oxygen; was made once manually for c1gCOi10.1
            # st.natom-=1
            # del st.xred[-1]
            # del st.typat[-1]

            st.natom += npores
            st.xred.extend(pores_xred)

            if znucl in st.znucl:
                print_and_log("znucl of added impurity is already in cell")
                ind = st.znucl.index(znucl)
                typat = ind + 1
                st.nznucl[ind] += npores
            else:
                st.ntypat += 1
                typat = st.ntypat
                st.znucl.append(znucl)
                st.nznucl.append(npores)

            for i in range(npores):
                st.typat.append(typat)

            st.xred2xcart()

            new.init = st

            #print "Add impurity: len(xred ", len(new.init.xred)
            #print "natom", new.init.natom

            #For automatisation of fit
            try:
                #new.build
                if new.build.nadded == None: new.build.nadded = npores
                else: new.build.nadded += npores
                if new.build.listadded == [None]:
                    new.build.listadded = range(
                        new.natom - npores,
                        new.natom)  #list of atoms which were added
                else:
                    new.build.listadded.extend(
                        range(new.natom - npores, new.natom))
                #print "Warning!!! Information about added impurities rewritten"
            except AttributeError:
                pass

            #new.init.znucl = new.znucl
            #new.init.typat = new.typat

            #write_xyz(replic(new.init, (2,1,2))  , xyzpath)

            #test_adding_of_impurities(new, new_before, v)

            print_and_log("Impurity with Z=" + str(znucl) +
                          " has been added to the found pore in " + new.name +
                          "\n\n")

        if write_geo:
            write_xyz(new.init, xyzpath)
            new.write_geometry("init", new.des, override=override)

        print_and_log("\n")

        return new

    """0.Begin----------------------------------------------------------------------------"""

    znucl = element_name_inv(impurity_type)

    if impurity_type != 'octa' and impurity_type not in it_new:
        print_and_log("add_impurity: Your name 'it_new' is incorrect!\n\n")
        raise RuntimeError
    #del header.history[-2]
    #

    #hstring = ("add_impurity('%s', '%s', '%s', calc, %.3f, '%s', '%s', %s, '%s')  #at %s" %
    #    (it_new, impurity_type, addtype, r_pore,
    #        it_to, ise_to, verlist_to, copy_geo_from,
    #     datetime.date.today() ) )

    hstring = ("%s    #on %s" %
               (traceback.extract_stack(None, 2)[0][3], datetime.date.today()))
    if hstring != header.history[-1]: header.history.append(hstring)

    #geo_exists =
    """1. The case of insertion to existing calculations--------------------------------------------------"""

    if verlist_to:

        for v in verlist_to:
            if only_version and v not in only_version:
                continue  # only_version = None works for all versions
            id = (it_to, ise_to, v)
            new = copy.deepcopy(calc[id])

            new.init = new.end  #replace init structure by the end structure

            new.version = v + add_to_version
            new.name = it_new  #+'.'+id[1]+'.'+str(id[2])
            new.des = 'Obtained from ' + str(
                id) + ' by adding ' + impurity_type + ' impurity '
            path_new_geo = struct_des[
                it_new].sfolder + "/" + it_new + "/" + it_new + '.imp.' + addtype + '.' + str(
                    new.version) + '.' + 'geo'
            new.init.name = it_new + ".init." + str(new.version)
            xyzpath = struct_des[it_new].sfolder + "/" + it_new

            new.path["input_geo"] = geo_folder + path_new_geo

            print_and_log("File '" + new.path["input_geo"] +
                          "' with impurity will be created\n")
            #new.init.name = 'test_before_add_impurity'

            new = add(znucl,
                      xyzpath,
                      new,
                      write_geo,
                      put_exactly_to=put_exactly_to)
        """2. The case of insertion to geo files------------------------------------------------------------"""
    else:
        """ Please rewrite using new functions """

        print_and_log(
            "You does not set 'id' of relaxed calculation. I try to find geometry files in "
            + it_new + " folder\n")

        if it_to:
            geo_path = geo_folder + struct_des[it_to].sfolder + "/" + it_to
        else:
            geo_path = geo_folder + struct_des[
                it_new].sfolder + "/" + it_new + '/from'
        if copy_geo_from:
            print_and_log("You asked to copy geo files from " + copy_geo_from +
                          " to " + geo_path + " folder\n")
            #if not os.path.exists(os.path.dirname(geo_path)):
            runBash("mkdir -p " + geo_path)
            runBash("cp " + copy_geo_from + "/* " + geo_path)

        if os.path.exists(geo_path):
            print_and_log("Folder '" + geo_path +
                          "' was found. Trying to add impurity\n")
        else:
            print_and_log("Error! Folder " + geo_path + " does not exist\n")
            raise RuntimeError

        #geofilelist = glob.glob(geo_path+'/*.geo*') #Find input_geofile
        #geofilelist = runBash('find '+geo_path+' -name "*grainA*.geo*" ').splitlines()
        #geofilelist = runBash('find '+geo_path+' -name "*.geo*" ').splitlines()
        geofilelist = glob.glob(geo_path + '/*.geo*')
        print_and_log("There are several files here already: ",
                      geofilelist,
                      imp='y')
        #print 'find '+geo_path+' -name "*.geo*" ',geofilelist
        #return

        for input_geofile in geofilelist:

            v = int(runBash("grep version " + str(input_geofile)).split()[1])

            if only_version and v not in only_version:
                continue  # only_version = None works for all versions

            new = CalculationVasp()
            new.version = v
            new.name = input_geofile

            new.read_geometry(input_geofile)
            init = copy.deepcopy(new)

            igl = input_geofile.split("/")
            #new.name = igl[-3]+'/'+igl[-3] #+input_geofile
            new.name = struct_des[it_new].sfolder + "/" + it_new + "/" + it_new
            print_and_log("New path and part of name of file is ",
                          new.name,
                          imp='Y')
            #return
            new.des = 'Obtained from ' + input_geofile + ' by adding ' + impurity_type + ' impurity '
            #new.init.xred   = new.xred
            #new.init.rprimd = new.rprimd

            #print new.rprimd
            new.init.name = new.name + '.imp.' + addtype + '.' + str(
                new.version)
            #new.path["input_geo"] = geo_folder+it_new+"/"+new.end.name+'.'+'geo'
            new.path[
                "input_geo"] = geo_folder + "/" + new.init.name + '.' + 'geo'
            #new.init.name = 'test_before_add_impurity'

            new = add(znucl, "", new, write_geo, put_exactly_to=put_exactly_to)

    return new.path["input_geo"]  #return for last version
Beispiel #28
0
def determine_barrier(positions=None, energies=None):
    """
    The sign of barrier determined by the curvuture at saddle point. Minimum at saddle point corresponds to negative barrier
    The saddle point is determined as maximum deviation from energy in initial position

    """

    import scipy

    if positions is None:
        positions = range(len(energies))

    if energies is None:
        printlog('Error! Please provide at least energies')

    spl = scipy.interpolate.PchipInterpolator(positions, energies)

    spl_der = spl.derivative()
    spl_der2 = spl_der.derivative()
    mi = min(positions)
    ma = max(positions)
    r = spl_der.roots()

    # print(r)
    r = r[np.logical_and(
        mi < r, r < ma)]  # only roots inside the interval are interesting

    e_at_roots = spl(r)
    if len(e_at_roots) > 0:
        # diff_barrier = max( e_at_roots ) # the maximum value
        printlog('roots are at ', r, e_at_roots)

        #find r for saddle point. the energy at saddle point is most far away from the energy at initial position by definition
        de_s = np.abs(e_at_roots - energies[0])
        i_r_de_max = np.argmax(de_s)
        # print(de_s)
        # print(i_r_de_max)

        r_de_max = r[i_r_de_max]
        e = spl(r_de_max)
        curvuture_at_saddle = spl_der2(r_de_max)

        sign = -np.sign(curvuture_at_saddle)
        if curvuture_at_saddle < 0:
            critical_point_type = 'maximum'
        elif curvuture_at_saddle > 0:
            critical_point_type = 'minimum'
        else:
            critical_point_type = 'undefined'

        # print(type(r_de_max), type(e), critical_point_type)
        print('Saddle point at {:.2f} {:.2f} is a local {:}'.format(
            r_de_max, float(e), critical_point_type))

    else:
        print_and_log('Warning! no roots')
        # diff_barrier = 0
        sign = 1

    mine = min(energies)
    maxe = max(energies)
    de = abs(mine - maxe)
    # if de > diff_barrier:
    diff_barrier = de * sign

    print('Migration barrier is {:.2f}'.format(diff_barrier))
    # plt.plot(spl(np.linspace(0, ma, 1000)))
    # plt.show()

    return diff_barrier
Beispiel #29
0
def neb_analysis(cl,
                 show,
                 up=None,
                 push2archive=None,
                 old_behaviour=None,
                 results_dic=None,
                 fitplot_args=None,
                 style_dic=None,
                 params=None):
    """
    Analyse traectories and polarons

    params
        mep_shift_vector
    """
    def determing_rms_for_surrounding_atoms(sts):
        # change of rms on each step compared to first structure
        #here first and last structures should correspond to first and last images

        st1 = sts[0]

        st_interp = interpolate(sts[0], sts[-1], 1)[0]
        rms_list = []

        for st in sts:
            rms = rms_pos_diff(st_interp, st)
            rms_list.append(rms)
            print('rms is {:.3f}'.format(rms))

        print('d rms is {:.3f}'.format(abs(rms_list[3] - rms_list[0])))

        rms_change = abs(min(rms_list) - max(rms_list))

        return rms_change

    def determing_born_barrier(sts):
        #here first and last structures should correspond to first and last images
        local_born_e = []
        i = find_moving_atom(sts[0], sts[-1])

        for st in sts:
            local_born_e.append(site_repulsive_e(st, i))

        # import matplotlib.pyplot as plt
        # plt.plot(local_born_e)
        # plt.show()

        return abs(min(local_born_e) - max(local_born_e))

    if params is None:
        params = {}

    if results_dic is None:

        results_dic = {}

    calc = header.calc
    path2mep_s = cl.project_path_cluster + '/' + cl.dir + '/mep.eps'
    itise = cl.id[0] + '.' + cl.id[1]
    # print(cl.ldauu)
    # sys.exit()
    name_without_ext = 'mep.' + itise + '.U' + str(max(cl.ldauu))
    path2mep_l = cl.dir + name_without_ext + '.eps'
    # print(path2mep_l)
    if not os.path.exists(path2mep_l) or '2' in up:
        ''
        get_from_server(
            files=path2mep_s,
            to_file=path2mep_l,
            addr=cl.cluster_address,
        )
        movie_to = cl.dir + '/movie.xyz'
        get_from_server(
            files=cl.project_path_cluster + '/' + cl.dir + '/movie.xyz',
            to_file=movie_to,
            addr=cl.cluster_address,
        )

        if os.path.exists(movie_to):
            makedir('figs/' + name_without_ext + '.xyz')
            shutil.copyfile(movie_to, 'figs/' + name_without_ext + '.xyz')

    # trying to get one image closest to the saddle point
    if old_behaviour and cl.version == 2:  #old behaviour, now created automatically in add callc
        im = cl.set.vasp_params['IMAGES']
        # if im % 2 > 0: #odd
        #     i = im//2 + 1
        # else:
        #     i = im/2
        # if choose_image:
        #     i = choose_image

        for i in range(im):
            i += 1
            cl_i = copy.deepcopy(cl)
            cl_i.version += i
            cl_i.id = (cl.id[0], cl.id[1], cl_i.version)
            cl_i.name = str(cl_i.id[0]) + '.' + str(cl_i.id[1]) + '.' + str(
                cl_i.id[2])
            # print cl_i.name
            cl_i.path["output"] = cl_i.dir + '0' + str(i) + "/OUTCAR"
            # for i in range():

            cl_i.associated_outcars = [
                aso[2:] for aso in cl_i.associated_outcars
            ]

            # print cl_i.path["output"]
            cl_i.state = '2. Ready to read outcar'
            # if not os.path.exists(cl_i.path["output"]):
            #     load = 'o'
            outst2 = ("%s" % cl_i.name).ljust(name_field_length)
            if readfiles:
                print(outst2 + '|' + cl_i.read_results(
                    loadflag, show=show, choose_outcar=choose_outcar))
            else:
                print_and_log(outst2 + ' | File was not read')

            if cl_i.id in calc:  #move creation of calcs with images to add_neb
                ''
                # print_and_log('Please test code below this message to save prev calcs')
                # if cl_i != calc[cl_i.id]
                #     if hasattr(calc[cl_i.id], 'prev') and calc[cl_i.id].prev:
                #         prevlist = calc[cl_i.id].prev
                #     else:
                #         prevlist = [calc[cl_i.id]]
                #     cl_i.prev = prevlist
                #     calc[cl_i.id] = cl_i
            else:
                calc[cl_i.id] = cl_i

    # print path2mep_l
    if 0:
        if os.path.exists(path2mep_l):
            # get_from_server(file = path2mep_s, to = path2mep_l, addr = cluster_address)

            runBash('evince ' + path2mep_l)
        else:
            a = glob.glob(cl.dir + '*mep*')
            if a:
                runBash('evince ' + a[0])

    cl1 = calc[cl.id[0], cl.id[1], 1]

    cl2 = calc[cl.id[0], cl.id[1], 2]

    atom_num = find_moving_atom(cl1.end, cl2.end)
    # cl1.poscar()
    # cl2.poscar()

    # print('atom_num',atom_num)
    # sys.exit()

    #prepare lists
    ni = cl.set.vasp_params['IMAGES']
    vlist = [1] + list(range(3, ni + 3)) + [2]
    # print( vlist)
    mep_energies = []
    atom_pos = []

    pols = []
    sts = []
    sts_loc = []
    dAO2 = []  # A-(O,F) distance for each image
    dAO4 = []  # A-(O,F) distance for each image
    dAO6 = []
    dAO6harm = []
    dAO6dev = []

    for v in vlist:
        cli = calc[cl.id[0], cl.id[1], v]
        # if v == 1:
        #     cli = db['NaVP2O7_a.su.s101015v100.n5Na1v1ms.ifn.1mls.1']

        # print(cl.id[0], cl.id[1], v, cli.state)
        if '4' not in cli.state and 'un' not in up:
            printlog('Attention! res_loop(): analys_type == neb, Calc', cli.id,
                     'is not finished; return')
            return {}, []
        # print cli.id
        # cli.end = return_to_cell(cli.end)
        # mep_energies.append(  min(cli.list_e_sigma0)   ) #use minimum energy - not very good, sometimes unconverged energy could be lower!

        e0 = cli.energy_sigma0
        if params and params.get(
                'neb_penult_e'
        ):  # allows to take  e from the previous relaxation step in case the calculation was aborted
            e0 = cli.list_e_sigma0[-2]

        mep_energies.append(e0)  #use last energy
        atom_pos.append(cli.end.xcart[atom_num])

        # Find polaron positions
        if 'polaron' in show:  # if 1 cause error for nomag calc
            pol, mag = find_polaron(cli.end, atom_num)
            if pol:
                for key in pol:
                    if np.any(pol[key]):
                        for n in pol[key]:
                            if n not in pols:
                                pols.append(n)
            else:
                ''
                # print('Mag_moments on trans,', mag.round(1))

        if 0 or 'neb_geo' in show:
            #visualization of path
            # print(atom_num)
            st = copy.deepcopy(cli.end)
            # print('moving_atom', st.xcart[atom_num])
            info = st.nn(atom_num, 15, from_one=False, silent=1)

            st.moving_atom_i = atom_num
            st_loc = info['st']

            # print(st_loc.xcart)
            # st_loc = st_loc.shift

            if v == vlist[0]:

                st1 = copy.deepcopy(st)

                vec = st.center_on(atom_num)
                # vec = np.asarray([0.,0.,0.])

                if params is not None and 'mep_shift_vector' in params:
                    # vec += np.array([0.11,0.11,0]) # path4
                    # print(params['mep_shift_vector'])
                    vec += np.array(params['mep_shift_vector'])  # path4

            # print(vec)
            st_loc = st_loc.shift_atoms(vec)
            if 0:
                st_loc.write_xyz()
            # st.write_cif('xyz/'+st.name)
            if 0:
                st.shift_atoms(vec).write_xyz()

            sts_loc.append(st_loc)

            st1 = st1.add_atom(st.xred[atom_num], 'Rb')

            sts.append(st.shift_atoms(vec))

            if 0 or 'neb_geo2' in show:
                printlog('\n\nVersion {:}:'.format(v), imp='y')
                info1 = st.nn(atom_num,
                              2,
                              from_one=False,
                              silent=1,
                              more_info=1)
                print('Av.         dist  A-2(O,F) {:.3f} A'.format(
                    info1['av(A-O,F)']))
                # print('Av. squared dist  A-2(O,F) {:.3f} A'.format(info1['avsq(A-O,F)']))
                dAO2.append(info1['av(A-O,F)'])

                info12 = st.nn(atom_num, 3, from_one=False, silent=1)
                print('Average distance  A-3(O,F) {:.2f} A'.format(
                    info12['av(A-O,F)']))

                info2 = st.nn(atom_num, 4, from_one=False, silent=1)
                print('Average distance  A-4(O,F) {:.2f} A'.format(
                    info2['av(A-O,F)']))
                dAO4.append(info2['av(A-O,F)'])

                info3 = st.nn(atom_num,
                              6,
                              from_one=False,
                              silent=1,
                              more_info=1)
                print('Average_distance  A-6(O,F) {:.2f} A '.format(
                    info3['av(A-O,F)']))
                print('Av. harm.   dist  A-6(O,F) {:.2f} A'.format(
                    info3['avharm(A-O,F)']))
                print('Average_deviation A-6(O,F) {:.1f} mA'.format(
                    info3['avdev(A-O,F)']))
                dAO6.append(info3['av(A-O,F)'])
                dAO6dev.append(info3['avdev(A-O,F)'])
                dAO6harm.append(info3['avharm(A-O,F)'])

    if 'neb_rms' in show:
        rms_change = determing_rms_for_surrounding_atoms(sts)
        results_dic['rms_change'] = rms_change

    if 'neb_born' in show:
        results_dic['born_barrier'] = determing_born_barrier(sts)
        print('Born barrier is {:.2f} eV '.format(results_dic['born_barrier']))

    # print(results_dic['rms_change'])
    # print('show is', show)
    # sys.exit()

    # print('flag ', 'neb_noxyz' not in show, show)
    if 'neb_noxyz' not in show and sts:
        write_xyz(sts=sts)  # write traectory
        write_xyz(sts=sts_loc)  # write traectory

        if 'jmol' in params:
            write_xyz(sts=sts, jmol=1, jmol_args=params['jmol'])  # write jmol

        st1 = st1.shift_atoms(vec)
        st1.name += '_all'
        # st1.write_cif('xyz/'+st1.name)
        st1.write_xyz()

    if dAO2:  # find maximum change of distance during migration
        dAO2_change = abs(min(dAO2) - max(dAO2))
        results_dic['dAO2_change'] = dAO2_change
    if dAO4:  # find maximum change of distance during migration
        dAO4_change = abs(min(dAO4) - max(dAO4))
        results_dic['dAO4_change'] = dAO4_change
    if dAO6:  #
        dAO6_change = abs(min(dAO6) - max(dAO6))
        results_dic['dAO6_change'] = dAO6_change
    if dAO6harm:  #
        results_dic['dAO6harm_change'] = abs(min(dAO6harm) - max(dAO6harm))
    if dAO6dev:  #
        results_dic['dAO6dev_change'] = abs(min(dAO6dev) - max(dAO6dev))

    results_dic[
        'sts_loc'] = sts_loc  # list of local structures, each structure contains dlist - distances from central cation to anions, and ellist - types of elements
    results_dic[
        'sts'] = sts  # list of mep structures, each structure contains moving_atom_i - number of moving atom

    if len(pols) > 0:
        print(
            'During migration of alkali ions polarons are detected on atoms:',
            pols)
    elif len(pols) > 1:
        printlog(
            'Attention! polaron is moving during migration! Obtained barrier is ambiguous'
        )
    else:
        printlog(
            'Compare magnetic moments above! In principle should be the same!')

    # print np.array(atom_pos)

    #test if the distances between points are not spoiled by PBC
    nbc = range(-1, 2)
    jj = 0
    for x in atom_pos:

        x2 = atom_pos[jj + 1]
        # x = np.array(x)
        # x2 = np.array(x2)
        r = cl.end.rprimd
        d1, _ = image_distance(x, x2, r, order=1)  #minimal distance
        x2_gen = (x2 + (r[0] * i + r[1] * j + r[2] * k) for i in nbc
                  for j in nbc for k in nbc)  #generator over PBC images
        x2c = copy.deepcopy(x2)
        ii = 0
        while np.linalg.norm(x -
                             x2c) > d1:  #find the closest PBC image position
            if ii > 100:
                break
            ii += 1
            x2c = next(x2_gen)
        atom_pos[jj + 1] = x2c
        jj += 1
        if jj == len(
                atom_pos
        ) - 1:  # the last point is not needed, we could not use slice since we need to use changed atom_pos in place
            break
        # print np.linalg.norm(x - x2c), d1

    _, diff_barrier = plot_mep(atom_pos,
                               mep_energies,
                               plot=0,
                               show=0,
                               fitplot_args=fitplot_args,
                               style_dic=style_dic)

    results_dic['barrier'] = diff_barrier

    middle_image = len(vlist) // 2
    results_dic['dEm1'] = mep_energies[middle_image] - mep_energies[0]

    cl1.barrier = diff_barrier
    cl2.barrier = diff_barrier

    results_dic['atom_pos'] = [list(pos) for pos in atom_pos]
    results_dic['mep_energies'] = mep_energies

    if 'mep' in show:
        if 'mepp' in show:
            show_flag = True
        else:
            show_flag = False
        # sys.exit()

        plot_mep(atom_pos,
                 mep_energies,
                 image_name='figs/' + name_without_ext + '_my.eps',
                 show=show_flag,
                 fitplot_args=fitplot_args,
                 style_dic=style_dic)

    if push2archive:
        path2saved, _ = plot_mep(atom_pos,
                                 mep_energies,
                                 image_name='figs/' + name_without_ext + '_my',
                                 fitplot_args=fitplot_args,
                                 style_dic=style_dic)
        push_figure_to_archive(local_figure_path=path2saved,
                               caption=description_for_archive)

        if 0:  #copy files according to chosen outcar to run nebresults locally
            wd = cl_i.dir
            out_i = cl_i.associated_outcars[choose_outcar - 1]
            out_1 = calc[cl.id[0], cl.id[1],
                         1].associated_outcars[choose_outcar - 1]
            out_2 = calc[cl.id[0], cl.id[1],
                         2].associated_outcars[choose_outcar - 1]
            # print out_1
            # print out_2
            shutil.copyfile(wd + out_1, wd + '00/OUTCAR')
            shutil.copyfile(wd + out_2, wd + '04/OUTCAR')
            for d in ['01/', '02/', '03/']:
                shutil.copyfile(wd + d + out_i, wd + d + 'OUTCAR')

                # print wd+d+out_i

    return results_dic
Beispiel #30
0
def add_neb(starting_calc=None,
            st=None,
            st_end=None,
            it_new=None,
            ise_new=None,
            i_atom_to_move=None,
            up='up2',
            search_type='vacancy_creation',
            images=None,
            r_impurity=None,
            calc_method=['neb'],
            inherit_option=None,
            mag_config=None,
            i_void_start=None,
            i_void_final=None,
            atom_to_insert=None,
            atom_to_move=None,
            rep_moving_atom=None,
            end_pos_types_z=None,
            replicate=None,
            it_new_folder=None,
            it_folder=None,
            inherit_magmom=False,
            x_start=None,
            xr_start=None,
            x_final=None,
            xr_final=None,
            upload_vts=False,
            center_on_moving=True,
            run=False,
            add_loop_dic=None,
            old_behaviour=None,
            params=None):
    """
    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*
        - None - just use st and st2 as initial and final

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

        - i_atom_to_move (int) - number of atom for moving starting from 0;
        - *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) - position numbers of voids (or atoms) from the suggested lists
        - atom_to_insert  (str) - element name of atom to insert
        - atom_to_move (str) - element name of atom to move
        - it_new_folder or it_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

        - end_pos_types_z (list of int) - list of Z - type of atoms, which could be considered as final positions in vacancy creation mode

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

        - x_start, x_final (array) - explicit xcart coordinates of moving atom for starting and final positions, combined with atom_to_insert
        - xr_start, xr_final (array) - explicit xred
        - rep_moving_atom (str)- replace moving atom by needed atom - can be useful than completly different atom is needed. 

        - upload_vts (bool) - if True upload Vasp.pm and nebmake.pl to server
        - run (bool)  - run on server

        - old_behaviour (str) - choose naming behavior before some date in the past for compatibility with your projects
            '020917'
            '261018' - after this moment new namig convention applied if end_pos_types_z is used

        - add_loop_dic - standart parameters of add()
        - params (dic) - provide additional parameters to add() # should be removed

    ###RETURN:
        None

    ###DEPENDS:

    ###TODO
    1. Take care of manually provided i_atom_to_move in case of replicate flag using init_numbers 
    2. For search_type == None x_m and x_del should be determined for magnetic searching and for saving their coordinates
    to struct_des; now their just (0,0,0) 


    """
    naming_conventions209 = True  # set False to reproduce old behavior before 2.09.2017
    if old_behaviour == '020917':
        naming_conventions209 = False  #

    # print('atom_to_insert', atom_to_insert)
    # sys.exit()

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

    if not add_loop_dic:
        add_loop_dic = {}

    if not end_pos_types_z:
        end_pos_types_z = []
        end_pos_types_z = sorted(end_pos_types_z)

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

    corenum = add_loop_dic.get('corenum')
    # print(corenum)
    # sys.exit()

    if corenum == None:
        if images == 3:
            corenum = 15
        elif images == 5:
            corenum = 15
        elif images == 7:
            corenum = 14
        else:
            printlog('add_neb(): Error! number of images', images,
                     'is unknown to me; please provide corenum!')

    # print(corenum)
    # sys.exit()

    # print(atom_to_insert)
    # sys.exit()

    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',
            images, corenum)

    if not ise_new:
        ise_new = starting_calc.id[1]
        printlog('I use', ise_new, 'as ise_new', imp='y')

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

    printlog('Search type is ', search_type)
    if search_type == None:

        if st_end == None:
            printlog(
                'Error! You have provided search_type == None, st_end should be provided!'
            )

        st1 = st
        st2 = st_end

        x_m = (0, 0, 0)
        x_del = (0, 0, 0)

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

        if is_list_like(xr_start):
            x_start = xred2xcart([xr_start], st.rprimd)[0]
            # print('atom_to_insert', atom_to_insert)
            # sys.exit()

            st1, i_m = st.add_atoms([x_start], atom_to_insert, return_ins=1)
            x_m = x_start
            # i_m = st1.find_atom_num_by_xcart(x_start)
            # print(st1.get_elements()[i_m])
            # sys.exit()

            if i_atom_to_move:
                nn = str(i_atom_to_move + 1)
            else:
                nn = str(i_void_start)

            name_suffix += atom_to_insert + nn
            write_xyz(st1, file_name=st.name + '_manually_start')
            printlog('Start position is created manually by adding xr_start',
                     xr_start, x_start)
            type_atom_to_move = atom_to_insert
            el_num_suffix = ''

        else:

            atoms_to_move = []
            atoms_to_move_types = []

            # print('d', i_atom_to_move)
            # sys.exit()

            if i_atom_to_move:
                typ = st.get_elements()[i_atom_to_move]
                printlog('add_neb(): atom', typ, 'will be moved', imp='y')
                atoms_to_move.append(
                    [i_atom_to_move, typ, st.xcart[i_atom_to_move]])
                atoms_to_move_types.append(typ)

                if naming_conventions209:
                    name_suffix += typ + str(i_atom_to_move + 1)

            else:
                #try to find automatically among alkali - special case for batteries
                for i, typ, x in zip(range(st.natom), st.get_elements(),
                                     st.xcart):
                    if typ in ['Li', 'Na', 'K', 'Rb', 'Mg']:
                        atoms_to_move.append([i, typ, x])
                        if typ not in atoms_to_move_types:
                            atoms_to_move_types.append(typ)

            if atoms_to_move:
                # print(atom_to_move)
                # sys.exit()
                if not atom_to_move:
                    atom_to_move = atoms_to_move_types[
                        0]  # taking first found element
                    if len(atoms_to_move_types) > 1:
                        printlog(
                            'Error! More than one type of atoms available for moving detected',
                            atoms_to_move_types,
                            'please specify needed atom with *atom_to_move*')

                type_atom_to_move = atom_to_move  #atoms_to_move[0][1]

                # printlog('atom ', type_atom_to_move, 'will be moved', imp ='y')

                if i_atom_to_move:
                    printlog('add_neb(): *i_atom_to_move* = ',
                             i_atom_to_move,
                             'is used',
                             imp='y')
                    numbers = [[i_atom_to_move]]
                    i_void_start = 1
                else:
                    printlog('add_neb(): determine_symmetry_positions ...',
                             imp='y')

                    numbers = determine_symmetry_positions(st, atom_to_move)

                # print(numbers)
                # sys.exit()
                if len(numbers) > 0:
                    printlog('Please choose position using *i_void_start* :',
                             [i + 1 for i in range(len(numbers))],
                             imp='y')
                    printlog('*i_void_start* = ', i_void_start)
                    i_m = numbers[i_void_start - 1][0]
                    printlog('Position',
                             i_void_start,
                             'chosen, atom:',
                             i_m + 1,
                             type_atom_to_move,
                             imp='y')

                else:
                    i_m = numbers[0][0]

                x_m = st.xcart[i_m]

                el_num_suffix = type_atom_to_move + str(i_m + 1)
                atom_to_insert = atom_to_move

                st1 = st
            # elif atom_to_replace:
            #     num = st.get_specific_elements(atom_to_replace)

            #     if len(n)>0:
            #         printlog('Please choose position using *i_void_start* :', [i+1 for i in range(len(num))],imp = 'y' )
            #         printlog('*i_void_start* = ', i_void_start)
            #         i_m = num[i_void_start-1]
            #         printlog('Position',i_void_start,'chosen, atom to replace:', i_m+1, atom_to_replace, imp = 'y' )
            #         sys.exit()

            else:

                print_and_log(
                    'No atoms to move found, you probably gave me deintercalated structure',
                    important='y')

                st_pores, sums, avds = determine_voids(st,
                                                       r_impurity,
                                                       step_dec=0.1,
                                                       fine=2)

                insert_positions = determine_unique_voids(st_pores, sums, avds)

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

                if i_void_start == None:
                    sys.exit()
                if atom_to_insert == None:
                    printlog('Error! atom_to_insert = None')

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

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

                st1 = st
        """2. Choose final position"""

        if is_list_like(xr_final):
            x_final = xred2xcart([xr_final], st.rprimd)[0]

            #old
            #check if i_atom_to_move should be removed
            # st2 = st1.del_atom(i_m)
            # st2 = st2.add_atoms([x_final], atom_to_insert)

            #new
            st2 = st1.mov_atoms(i_m, x_final)

            # st1.printme()
            # st2.printme()
            # sys.exit()

            x_del = x_final
            search_type = 'manual_insertion'
            name_suffix += 'v' + str(i_void_final)
            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, sums, avds = determine_voids(st, r_impurity)

            sur = determine_unique_final(st_pores, sums, avds, x_m)

            print_and_log('Please choose *i_void_final* from the Table above:',
                          end='\n',
                          imp='Y')

            if i_void_final == None:
                sys.exit()

            x_final = sur[0][i_void_final]  #

            printlog('You chose:',
                     np.array(x_final).round(2),
                     end='\n',
                     imp='Y')

            x_del = x_final  #please compare with vacancy creation mode

            write_xyz(st.add_atoms([x_final], 'H'),
                      replications=(2, 2, 2),
                      file_name=st.name + '_possible_positions2_replicated')

            print_and_log('Choosing the closest position as end',
                          important='n')

            st1 = st

            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',
                imp='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)

            final_pos_z = end_pos_types_z or [
                invert(type_atom_to_move)
            ]  # by default only moving atom is considered
            end_pos_types_el = [invert(z) for z in end_pos_types_z]

            sur = local_surrounding(x_m,
                                    st,
                                    n_neighbours=14,
                                    control='atoms',
                                    only_elements=final_pos_z,
                                    periodic=True)  #exclude the atom itself

            # print(x_m)
            # print(sur)

            # st.nn()
            end_pos_n = sur[2][1:]
            print_and_log(
                'I can suggest you ' + str(len(end_pos_n)) +
                ' end positions. The distances to them are : ',
                np.round(sur[3][1:], 2),
                ' A\n ',
                'They are ', [invert(z) for z in final_pos_z],
                'atoms, use *i_void_final* to choose required: 1, 2, 3 ..',
                imp='y')

            i_sym_final_l = []
            for j in end_pos_n:
                for i, l in enumerate(numbers):
                    if j in l:
                        i_sym_final_l.append(i + 1)
            printlog('Their symmetry positions are ', i_sym_final_l, imp='y')

            # sys.exit()

            if not i_void_final:
                printlog('Changing i_void_final: None -> 1', imp='y')
                i_void_final = 1  #since zero is itself
            chosen_dist = sur[3][i_void_final]
            print_and_log('Choosing position ',
                          i_void_final,
                          'with distance',
                          round(chosen_dist, 2),
                          'A',
                          imp='y')

            # print(end_pos_n)
            i_sym_final = 0
            n_final = sur[2][i_void_final]
            for i, l in enumerate(numbers):
                if n_final in l:
                    i_sym_final = i + 1
            printlog('It is symmetrically non-equiv position #',
                     i_sym_final,
                     imp='y')

            # sys.exit()

            header.temp_chosen_dist = chosen_dist

            if old_behaviour == '261018':
                name_suffix += el_num_suffix + 'v' + str(i_void_final)
            else:

                name_suffix += el_num_suffix + 'v' + str(
                    i_void_final) + list2string(end_pos_types_el, joiner='')

                # print(name_suffix)
                # sys.exit()

            x_del = sur[0][i_void_final]
            printlog('xcart of atom to delete', x_del)
            i_del = st.find_atom_num_by_xcart(x_del)
            # print(x_del)
            # print(st.xcart)
            # for x in st.xcart:
            #     if x[0] > 10:
            #         print(x)

            print_and_log('number of atom to delete = ', i_del, imp='y')
            if i_del == None:
                printlog('add_neb(): Error! I could find atom to delete!')

            # print st.magmom
            # print st1.magmom

            # try:
            if is_list_like(xr_start):
                st2 = st1.mov_atoms(
                    i_m, x_del)  # i_m and sur[0][neb_config] should coincide
                # i_del = st1.find_atom_num_by_xcart(x_del)

                st1 = st1.del_atom(i_del)

            else:
                print_and_log(
                    'Making vacancy at end position for starting configuration',
                    imp='y')
                st1 = st.del_atom(i_del)

                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
            # except:
            # st2 = st

            st2 = st2.del_atom(i_del)  # these two steps provide the same order
    """Checking correctness of path"""
    #if start and final positions are used, collisions with existing atoms are possible
    if is_list_like(xr_start) and is_list_like(xr_final):
        printlog('Checking correctness')
        st1, _, _ = st1.remove_close_lying()

        stt = st1.add_atoms([
            x_final,
        ], 'Pu')
        stt, x, _ = stt.remove_close_lying(
            rm_both=True
        )  # now the final position is empty for sure; however the order can be spoiled
        # print(st._removed)
        if stt._removed:
            st1 = stt  # only if overlapping was found we assign new structure

        st2, _, _ = st2.remove_close_lying(rm_first=stt._removed)
        stt = st2.add_atoms([
            x_start,
        ], 'Pu')
        stt, x, _ = stt.remove_close_lying(
            rm_both=True)  # now the start position is empty for sure
        if stt._removed:
            st2 = stt

        print(st2.get_elements())
        # sys.exit()

    elif is_list_like(xr_final) and not is_list_like(xr_start) or is_list_like(
            xr_start) and not is_list_like(xr_final):
        printlog(
            'Attention! only start or final position is provided, please check that everything is ok with start and final states!!!'
        )
    """ Determining magnetic moments  """
    vp = varset[ise_new].vasp_params

    if 'ISPIN' in vp and vp['ISPIN'] == 2:
        print_and_log(
            'Magnetic calculation detected. Preparing spin modifications ...',
            imp='y')
        cl_test = CalculationVasp(varset[ise_new])
        cl_test.init = st1
        # print 'asdfsdfasdfsadfsadf', st1.magmom
        if inherit_magmom and hasattr(st, 'magmom') and st.magmom and any(
                st.magmom):
            print_and_log(
                'inherit_magmom=True: You have chosen MAGMOM from provided structure',
                imp='y')
            name_suffix += 'mp'  #Magmom from Previous
        else:
            cl_test.init.magmom = None
            print_and_log(
                'inherit_magmom=False or no magmom in input structure : MAGMOM will be determined  from set',
                imp='y')
            name_suffix += 'ms'  #Magmom from Set

        cl_test.actualize_set()  #find magmom for current structure

        st1.magmom = copy.deepcopy(cl_test.init.magmom)
        st2.magmom = copy.deepcopy(cl_test.init.magmom)

        # sys.exit()
        # print_and_log('The magnetic moments from set:')
        # print cl_test.init.magmom
        if search_type != None:  # for None not implemented; x_m should be determined first for this
            #checking for closest atoms now only for Fe, Mn, Ni, Co
            sur = local_surrounding(x_m,
                                    st1,
                                    n_neighbours=3,
                                    control='atoms',
                                    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 and not it_folder:

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

    if rep_moving_atom:
        it_new += 'r' + rep_moving_atom

    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
    if search_type is not None:
        struct_des[it_new].x_m_ion_start = x_m
        struct_des[it_new].xr_m_ion_start = xcart2xred([x_m], st1.rprimd)[0]

        # st1, _, _ = st1.remove_close_lying()
        # st2, _, _ = st2.remove_close_lying()
        print('Trying to find x_m', x_m)
        i1 = st1.find_atom_num_by_xcart(
            x_m,
            prec=0.45,
        )

        # sys.exit()
        print('Trying to find x_del', x_del)

        i2 = st2.find_atom_num_by_xcart(
            x_del,
            prec=0.45,
        )

        if rep_moving_atom:  #replace the moving atom by required
            st1 = st1.replace_atoms([i1], rep_moving_atom)
            st2 = st2.replace_atoms([i2], rep_moving_atom)
        else:
            #allows to make correct order for nebmake.pl
            st1 = st1.replace_atoms([i1], type_atom_to_move)
            st2 = st2.replace_atoms([i2], type_atom_to_move)

        i1 = st1.find_atom_num_by_xcart(
            x_m,
            prec=0.45)  # the positions were changed # check if this is correct
        i2 = st2.find_atom_num_by_xcart(x_del, prec=0.45)

    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_'+str(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_'+str(search_type)+'.'+str(ver_new)+'.'+'geo'

    cl.write_siman_geo(geotype='end',
                       description='Final conf. for neb from ' + obtained_from,
                       override=True)

    if not rep_moving_atom and search_type is not None:
        st1s = st1.replace_atoms([i1], 'Pu')
        st2s = st2.replace_atoms([i2], 'Pu')
    else:
        st1s = copy.deepcopy(st1)
        st2s = copy.deepcopy(st2)

    if center_on_moving and search_type is not None:

        vec = st1.center_on(i1)
        st1s = st1s.shift_atoms(vec)
        st2s = st2s.shift_atoms(vec)
        write_xyz(st1s, file_name=it_new + '_start')
        write_xyz(st2s, file_name=it_new + '_end')

    st1s.write_poscar('xyz/POSCAR1')
    st2s.write_poscar('xyz/POSCAR2')
    # print(a)
    # runBash('cd xyz; mkdir '+it_new+'_all;'+"""for i in {00..04}; do cp $i/POSCAR """+ it_new+'_all/POSCAR$i; done; rm -r 00 01 02 03 04')

    with cd('xyz'):
        a = runBash(header.PATH2NEBMAKE + ' POSCAR1 POSCAR2 3')
        print(a)
        dst = it_new + '_all'
        makedir(dst + '/any')
        for f in ['00', '01', '02', '03', '04']:
            shutil.move(f + '/POSCAR', dst + '/POSCAR' + f)
            shutil.rmtree(f)

    #prepare calculations
    # sys.exit()

    #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])

    if run:
        add_loop_dic['run'] = run

    add_loop_dic['corenum'] = corenum
    # print(add_loop_dic)
    add_loop(
        it_new,
        ise_new,
        verlist=[1, 2],
        up=up,
        calc_method=calc_method,
        savefile='oc',
        inherit_option=inherit_option,
        n_neb_images=images,
        # params=params,
        **add_loop_dic)

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

    printlog('add_neb finished')
    return it_new