Beispiel #1
0
def write_occmatrix(occs, folder):
    #create OCCMATRIX

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

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

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

            f.write(list2string([i + 1, l, s]) + '    #i, l, s\n')
            # for sp in range(s):
            f.write('spin 1\n')
            for row in occs[i][0:len(occs[i]) // s]:
                f.write(list2string(row) + '\n')
            if s == 2:
                f.write('spin 2\n')
                for row in occs[i][len(occs[i]) // s:]:
                    f.write(list2string(row) + '\n')
            f.write('\n')
    return filename
Beispiel #2
0
def insert_0weight_kpoints(ibzkpt='', list_kpoints=[], folder_kpoints=''):
    """
    The function is used to add k-points to the current IBZKPT file 
    and convert it to new KPOINTS file
    INPUT:
        
        - ibzkpt (str)             - path to IBZKPT file to insert k-points with zero weight 
        - list_kpoints (list)      - list of k-points with relative coordinates; 
                                     it has the following form ['a1, a2, a3 0\n',...]
        - folder_kpoints (str)     - name of folder to make the resulting KPOINTS file
    RETURN:
        None
    SOURCE
        None
    TODO
        Some improvements


    """
    f = open(ibzkpt)
    l = f.readlines()
    f.close()

    l[1] = str(int(l[1]) + len(list_kpoints)) + '\n'

    l_new = l + list_kpoints

    makedir(folder_kpoints)
    f = open(folder_kpoints + '/KPOINTS', 'w')
    f.writelines(l_new)
    f.close()
Beispiel #3
0
def generate_latex_report(text, filename):
    # 

    fn = filename+'.tex'
    makedir(fn)
    head = r"""
\documentclass{article}
% General document formatting
\usepackage[margin=0.7in]{geometry}
\usepackage[parfill]{parskip}
\usepackage[utf8]{inputenc}

% Related to math
\usepackage{amsmath,amssymb,amsfonts,amsthm}

\begin{document}"""
    

    with open(fn, 'w') as f:
        f.write(head+'\n')
        f.write(text+'\n')
        f.write(r'\end{document}')


    runBash('pdflatex '+os.path.basename(fn), cwd = os.path.dirname(fn))
def process_fig_filename(image_name, fig_format):

    makedir(image_name)

    if fig_format in image_name:
        path2saved = str(image_name)

    elif str(image_name).split('.')[-1] in ['eps', 'png', 'pdf']:
        path2saved = str(image_name)
        fig_format = str(image_name).split('.')[-1]

    else:
        path2saved = str(image_name) + '.' + fig_format

    dirname = os.path.dirname(image_name)
    if not dirname:
        dirname += '.'

    path2saved_png = dirname + '/png/' + os.path.basename(image_name) + '.png'
    makedir(path2saved_png)

    return path2saved, path2saved_png
Beispiel #5
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 #6
0
def fit_a(conv, n, description_for_archive, analysis_type, show, push2archive):
    """Fit equation of state for bulk systems.

    The following equation is used::

       sjeos (default)
           A third order inverse polynomial fit 10.1103/PhysRevB.67.026103

                           2      3        -1/3
       E(V) = c + c t + c t  + c t ,  t = V
               0   1     2      3

       taylor
           A third order Taylor series expansion about the minimum volume

       murnaghan
           PRB 28, 5480 (1983)

       birch
           Intermetallic compounds: Principles and Practice,
           Vol I: Principles. pages 195-210

       birchmurnaghan
           PRB 70, 224107

       pouriertarantola
           PRB 70, 224107

       vinet
           PRB 70, 224107

       antonschmidt
           Intermetallics 11, 23-32 (2003)

       p3
           A third order polynomial fit

        Use::

           eos = EquationOfState(volumes, energies, eos='sjeos')
           v0, e0, B = eos.fit()
           eos.plot()

    """
    # e, v, emin, vmin       = plot_conv( conv[n], calc,  "fit_gb_volume2")

    alist = []
    vlist = []
    etotlist = []
    magn1 = []
    magn2 = []
    alphas = []
    for id in conv[n]:
        cl = db[id]
        st = cl.end
        alist.append(cl.end.rprimd[0][0])
        etotlist.append(cl.energy_sigma0)
        vlist.append(cl.end.vol)
        magn1.append(cl.magn1)
        magn2.append(cl.magn2)
        alpha, beta, gamma = st.get_angles()
        alphas.append(alpha)
        print('alpha, energy: {:4.2f}, {:6.3f}'.format(alpha,
                                                       cl.energy_sigma0))

    fit_and_plot(U1=(alphas, etotlist, 'o-r'),
                 image_name='figs/angle',
                 ylabel='Total energy, eV',
                 xlabel='Angle, deg',
                 xlim=(89, 92.6))

    if ase_flag:
        if 'angle' in analysis_type:
            eos = EquationOfState(alphas, etotlist, eos='sjeos')
        else:
            eos = EquationOfState(vlist, etotlist, eos='sjeos')
        # import inspect

        # print (inspect.getfile(EquationOfState))

        v0, e0, B = eos.fit()
        #print "c = ", clist[2]
        printlog('''
        v0 = {0} A^3
        a0 = {1} A
        E0 = {2} eV
        B  = {3} eV/A^3'''.format(v0, v0**(1. / 3), e0, B),
                 imp='Y')

        savedpath = 'figs/' + cl.name + '.png'
        makedir(savedpath)

        cl.B = B * 160.218
        # plt.close()
        # plt.clf()
        # plt.close('all')
        if 'fit' in show:
            mpl.rcParams.update({'font.size': 14})

            eos.plot(savedpath, show=True)
            printlog('fit results are saved in ', savedpath, imp='y')
        else:
            printlog('To use fitting install ase: pip install ase')
    # plt.clf()

    if push2archive:
        push_figure_to_archive(local_figure_path=savedpath,
                               caption=description_for_archive)

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

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

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

    if natom != len(xred) != len(xcart) != len(typat) or len(znucl) != max(
            typat):
        printlog("Error! write_xyz: check your structure")

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

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

    filename += '.inp'

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

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

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

            f.write("\n")

        printlog('File', filename, 'was written', imp='y')

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

    if 0:
        """Write lammps.in file """
        with open('voronoi_analysis/voronoi.in', 'w') as f:
            f.write("""units           metal
                    atom_style atomic
                    boundary        p p p\n""")
            f.write(
                "read_data   /home/aksenov/programs/Simulation_wrapper/siman1/voronoi_analysis/structure.lammps\n"
            )
            #         f.write('lattice   custom 1 ')
            #         for i, a in enumerate(rprimd):
            #             f.write(' a'+str(i+1))
            #             for x in a:
            #                 f.write(' '+str(x))

            #         f.write(' &\n')
            #         for x in xred:
            #             f.write(' basis {0:f} {1:f} {2:f}&\n '.format(x[0], x[1], x[2]) )
            #         f.write("""\n
            # region 1 prism 0 1 0 1 0 1  1 0 0
            # create_box 1 prism
            # create_atoms 1 prism""")

            for i in range(ntypat):
                f.write('\nmass ' + str(i + 1) + ' ' + str(int(znucl[i])) +
                        '\n')

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

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

    return
Beispiel #8
0
def write_xyz(st=None,
              path=None,
              filename=None,
              file_name=None,
              include_vectors=True,
              repeat=1,
              shift_2view=1.0,
              replications=None,
              full_cell=False,
              analysis=None,
              show_around=None,
              show_around_x=None,
              nnumber=6,
              only_elements=None,
              gbpos2=None,
              gbwidth=1,
              withgb=False,
              include_boundary=2,
              imp_positions=[],
              imp_sub_positions=None,
              jmol=None,
              specialcommand=None,
              jmol_args=None,
              sts=None,
              mcif=0,
              suf=''):
    """Writes st structure in xyz format in the folder xyz/path
    #void are visualized with Pu
    if repeat == 2: produces jmol script
    shift_2view - in rprimd[1][1] - shift of the second view
    gbpos2 - position of grain boundary in A
    gbwidth - atoms aroung gbpos2 will be colored differently

    imp_positions - (x1,x2,x3, element, label)- xcart and element name coordinates additionally to be added to structure; to visulaze all impurity positions: for jmol, additional key 's', 'i' can be added after element
    imp_sub_positions - list of atom numbers; the typat of these atoms is changed: not used now


    analysis - additional processing, allows to show only specifice atoms, 
        'imp_surrounding' - shows Ti atoms only around impurity
        nnumber - number of neighbours to show
        show_around - choose atom number around which to show, from 1
        show_around_x - show atoms around point, has higher priority
        only_elements - see local_surrounding

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

    full_cell - returns atoms to cell and replicate boundary atoms

    include_vectors (bool) - write primitive vectors to xyz

    jmol - 1,0 -  use jmol to produce png picture
    jmol_args - see write_jmol()
    mcif - write magnetic cif for jmol


    specialcommand - any command at the end of jmol script
    suf - additional suffix for name

    sts - list of Structure - write several structures to xyz file - other options are not working in this regime
    """

    if jmol_args == None:
        jmol_args = {}

    if st == None:
        st = sts[0]

    if replications:
        st = replic(st, mul=replications, inv=1)

    def update_var(st):
        if st.natom != len(st.xred) != len(st.xcart) != len(st.typat) or len(
                st.znucl) != max(st.typat):
            printlog("Error! write_xyz: check your arrays.\n\n")

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

        return st.rprimd, st.xcart, st.xred, st.typat, st.znucl, len(st.xred)

    st = st.copy()
    rprimd, xcart, xred, typat, znucl, natom = update_var(st)

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

    if sts:
        name += '_traj'

    printlog("write_xyz(): Name is", name, important='n')

    if name == '':
        name = 'noname'

    if path:
        basepath = path
    else:
        basepath = 'xyz/'

    suf = ''
    """Processing section"""

    if analysis == 'imp_surrounding':
        printlog('analysis = imp_surrounding', imp='y')

        if show_around == 0:
            printlog('Error! number of atom *show_around* should start from 1')

        suf = '_loc' + str(show_around)
        lxcart = []
        ltypat = []
        i = 0

        if is_list_like(show_around_x):
            x = show_around_x
            x_t = local_surrounding(x,
                                    st,
                                    nnumber,
                                    control='atoms',
                                    periodic=True,
                                    only_elements=only_elements)
            # print('write_xyz: local_surround:', x_t)
            lxcart += x_t[0]
            ltypat += x_t[1]
        else:

            for t, x in zip(typat, xcart):

                condition = False
                # print show_around, 'show'
                if show_around:
                    # print i, condition
                    condition = (i + 1 == show_around)
                    # print i, condition

                else:
                    condition = (
                        t > 1
                    )  # compat with prev behav, to show around any impurities (all atoms with typat more than one)

                # print 'se', condition

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

        xcart = lxcart
        typat = ltypat
        natom = len(typat)
        # print natom, 'nat'
        # print('Number of neighbours', natom  )
        st.xcart = xcart
        st.typat = typat
        st.natom = natom
        st.update_xred()
    """Include atoms on the edge of cell"""
    if full_cell:
        # print xred
        # print natom
        # st = return_atoms_to_cell(st)
        # print xred
        st = replic(st,
                    mul=(1, 1, 2),
                    inv=0,
                    cut_one_cell=1,
                    include_boundary=include_boundary)
        # print natom, st.natom

        # print st.xred

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

    # asdegf

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

    #analyze imp_positions
    if imp_sub_positions == None:
        imp_sub_positions = []
    nsub = 0
    for pos in imp_positions:
        # if len(pos) > 4:
        #     if 's' not in pos[4]: continue # skip interstitial positions

        xs = np.asarray([pos[0], pos[1], pos[2]])
        nsub += 1
        # print xs
        for i, x in enumerate(xcart):
            # print np.linalg.norm( x-xs)
            if np.linalg.norm(x - xs) < 1:
                imp_sub_positions.append(i)

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

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

    if include_vectors:
        nvect = 3
    else:
        nvect = 0
    """Writing section"""
    name += suf
    xyzfile = os.path.join(basepath, name + ".xyz")
    makedir(xyzfile)

    def write(st):
        rprimd, xcart, xred, typat, znucl, natom = update_var(st)

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

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

            z = int(znucl[typ])

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

                f.write(el + " ")

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

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

    with open(xyzfile, 'w') as f:
        if sts:
            for st in sts:
                write(st)
        else:
            for i in range(repeat):
                write(st)

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

    pngfile = None

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

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

        if gbpos2:

            gbpos1 = gbpos2 - rprimd[0][0] / 2.
            gbatoms = []

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

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

        # xyzfile = os.getcwd()+'/'+xyzfile
        if mcif:
            xyzfile = st.write_cif(mcif=1)
        else:
            xyzfile = st.write_poscar()

        scriptfile = basepath + name + ".jmol"
        bn = (basepath + name).replace('.', '_')
        pngfile = os.getcwd() + '/' + bn + ".png"

        printlog('imp_positions = ', imp_positions)
        write_jmol(xyzfile,
                   pngfile,
                   scriptfile,
                   atomselection,
                   rprimd=rprimd,
                   shift=shift_2view,
                   label=[(pos[3], pos[4]) for pos in imp_positions],
                   specialcommand=specialcommand,
                   **jmol_args)

    return xyzfile, pngfile
Beispiel #9
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
Beispiel #10
0
    def fit_and_plot(x1,
                     y1,
                     x2,
                     y2,
                     power,
                     name="",
                     xlabel="",
                     ylabel="",
                     image_name="test",
                     lines=None):
        """Should be used in two below sections!
        Creates one plot with two dependecies and fit them;
        return minimum fitted value of x2 and corresponding valume of y2; 
        if name == "" image will not be plotted
        power - the power of polynom

        lines - add lines at x = 0 and y = 0

        """
        coeffs1 = np.polyfit(x1, y1, power)
        coeffs2 = np.polyfit(x2, y2, power)

        fit_func1 = np.poly1d(coeffs1)
        fit_func2 = np.poly1d(coeffs2)

        #x_min  = fit_func2.deriv().r[power-2] #derivative of function and the second cooffecient is minimum value of x.
        #y_min  = fit_func2(x_min)

        if name:

            x_range = np.linspace(min(x2), max(x2))
            fit_y1 = fit_func1(x_range)
            fit_y2 = fit_func2(x_range)

            plt.figure(figsize=(8, 6.1))
            # plt.title(name)
            plt.ylabel(ylabel)
            plt.xlabel(xlabel)
            plt.xlim(
                min(x2) - 0.1 * abs(min(x2)),
                max(x2) + 0.1 * abs(min(x2)))

            plt.plot(x1, y1, 'ro', label='initial')
            plt.plot(x2, y2, 'bo', label='relaxed')
            plt.plot(
                x_range,
                fit_y1,
                'r-',
            )  #label = 'init_fit')
            plt.plot(
                x_range,
                fit_y2,
                'b-',
            )  #label = 'r_fit'   )
            plt.legend(loc=9)

            if lines == 'xy':
                plt.axvline(color='k')
                plt.axhline(color='k')

            plt.tight_layout()
            #plt.savefig('images/'+image_name)
            file = header.path_to_images + '/' + str(image_name) + '.png'
            makedir(file)
            print_and_log('Saving file ...', file, imp='y')
            plt.savefig(file, format='png', dpi=300)
        return fit_func2
Beispiel #11
0
def plot_bands_old(vasprun_dos, vasprun_bands, kpoints, element, ylim = (None, None)):
    """
    This function is used to build plot of the electronic band structure along with
    the density of states (DOS) plot. It has feature to provide contributions from different
    elements to both band structure and DOS

    INPUT:
        - vasprun_dos (str) - path to the vasprun file of the DOS calculation
        - vasprun_band (str) - path to the vasprun file of the band structure calculation
        - kpoints (str) - path to the KPOINTS file of the band structure calculation
        - element (str) - label of the chemical element, for which the contribution
                          to the band structure and DOS
        - ylim (tuple of floats) - energy range of the band structure and DOS plots, units are eV
    RETURN:
        None
    SOURCE:
        Credit https://github.com/gVallverdu/bandstructureplots
    TODO:
        Some improvements
    """



    labels = read_kpoint_labels(kpoints)


    # density of states
    # dosrun = Vasprun(vasprun_dos)
    dosrun = Vasprun(vasprun_bands)
    spd_dos = dosrun.complete_dos.get_spd_dos()

    # bands
    run = Vasprun(vasprun_bands, parse_projected_eigen=True)
    bands = run.get_band_structure(kpoints,
                                   line_mode=True,
                                   efermi=dosrun.efermi)

    # set up matplotlib plot
    # ----------------------

    # general options for plot
    font = {'family': 'serif', 'size': 24}
    plt.rc('font', **font)

    # set up 2 graph with aspec ration 2/1
    # plot 1: bands diagram
    # plot 2: Density of States
    gs = GridSpec(1, 2, width_ratios=[2, 1])
    fig = plt.figure(figsize=(11.69, 8.27))
    # fig.suptitle("Bands diagram of copper")
    ax1 = plt.subplot(gs[0])
    ax2 = plt.subplot(gs[1])  # , sharey=ax1)

    # set ylim for the plot
    # ---------------------
    if ylim[0]:
        emin = ylim[0]
    else: 
        emin = -10.
    if ylim[1]:
        emax = ylim[1]
    else: 
        emax =  10.

    ax1.set_ylim(emin, emax)
    ax2.set_ylim(emin, emax)

    # Band Diagram
    # ------------
    name = element 
    pbands = bands.get_projections_on_elements_and_orbitals({name: ["s", "p", "d"]})
    # print(bands)

    # compute s, p, d normalized contributions
    contrib = np.zeros((bands.nb_bands, len(bands.kpoints), 3))
    # print(pbands)
    for b in range(bands.nb_bands):
        for k in range(len(bands.kpoints)):
            # print(Spin.up)
            sc = pbands[Spin.up][b][k][name]["s"]**2
            pc = pbands[Spin.up][b][k][name]["p"]**2
            dc = pbands[Spin.up][b][k][name]["d"]**2
            tot = sc + pc + dc
            if tot != 0.0:
                contrib[b, k, 0] = sc / tot
                contrib[b, k, 1] = pc / tot
                contrib[b, k, 2] = dc / tot

    # plot bands using rgb mapping
    for b in range(bands.nb_bands):
        rgbline(ax1,
                range(len(bands.kpoints)),
                [e - bands.efermi for e in bands.bands[Spin.up][b]],
                contrib[b, :, 0],
                contrib[b, :, 1],
                contrib[b, :, 2])

    # style
    ax1.set_xlabel("k-points")
    ax1.set_ylabel(r"$E - E_f$   /   eV")
    ax1.grid()

    # fermi level at 0
    ax1.hlines(y=0, xmin=0, xmax=len(bands.kpoints), color="k", linestyle = '--', lw=1)

    # labels
    nlabs = len(labels)
    step = len(bands.kpoints) / (nlabs - 1)
    for i, lab in enumerate(labels):
        ax1.vlines(i * step, emin, emax, "k")
    ax1.set_xticks([i * step for i in range(nlabs)])
    ax1.set_xticklabels(labels)

    ax1.set_xlim(0, len(bands.kpoints))

    # Density of states
    # ----------------

    ax2.set_yticklabels([])
    ax2.grid()
    ax2.set_xlim(1e-4, 5)
    ax2.set_xticklabels([])
    ax2.hlines(y=0, xmin=0, xmax=5, color="k", lw=2)
    ax2.set_xlabel("Density of States", labelpad=28)

    # spd contribution
    ax2.plot(spd_dos[OrbitalType.s].densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             "r-", label="3s", lw=2)
    ax2.plot(spd_dos[OrbitalType.p].densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             "g-", label="3p", lw=2)
    ax2.plot(spd_dos[OrbitalType.d].densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             "b-", label="3d", lw=2)

    # total dos
    ax2.fill_between(dosrun.tdos.densities[Spin.up],
                     0,
                     dosrun.tdos.energies - dosrun.efermi,
                     color=(0.7, 0.7, 0.7),
                     facecolor=(0.7, 0.7, 0.7))

    ax2.plot(dosrun.tdos.densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             color=(0.6, 0.6, 0.6),
             label="total DOS")

    # plot format style
    # -----------------
    ax2.legend(fancybox=True, shadow=True, prop={'size': 18})
    plt.subplots_adjust(wspace=0)

    # plt.show()
    makedir("figs/bands.png")
    plt.savefig("figs/bands.png")
Beispiel #12
0
def plot_bands(vasprun_dos, vasprun_bands, kpoints, element, ylim = (None, None), folder = '', renew_folder=True, vb_top=0, cb_bottom=1, vbm_pos=0, cbm_pos=0):
    """
    This function is used to build plot of the electronic band structure along with
    the density of states (DOS) plot. It has feature to provide contributions from different
    elements to both band structure and DOS. In addition, the band gap (in eV) is automatically
    calculated.

    INPUT:
        - vasprun_dos (str) - path to the vasprun file of the DOS calculation
        - vasprun_band (str) - path to the vasprun file of the band structure calculation
        - kpoints (str) - path to the KPOINTS file of the band structure calculation
        - element (str) - label of the chemical element, for which the contribution
                          to the band structure and DOS
        - ylim (tuple of floats) - energy range of the band structure and DOS plots, units are eV
        - folder (str) - directory where all the results will be built
        - renew_folder (bool) - if True then the folder will be renewed with removing old one
        - vb_top (int) - number of the last occupied band (valence band) (count starts from '1')
        - vbm_pos (int) - supposed number of the k-point in the IBZKPT file, at which the valence band maximum (VBM) is located (count starts from '0')
        - cb_bottom (int) - number of the first unoccupied band (conduction band) (count starts from '1')
        - cbm_pos (int) - supposed number of the k-point in the IBZKPT file, at which the conduction band minimum (CBM) is located (count starts from '0')
 
    RETURN:
        None
    SOURCE:
        Credit https://github.com/gVallverdu/bandstructureplots
    TODO:
        Some improvements
    """    

    from siman.small_functions import makedir
    # The folder to collect data necessary for graph building
    full_name_folder_data = folder+vasprun_bands.split('/')[-2]
    print('bands.py, string 274, full_name_folder_data ', full_name_folder_data)
    makedir(full_name_folder_data+'/', renew_folder = renew_folder)




    labels = read_kpoint_labels(kpoints)

    # density of states
    # dosrun = Vasprun(vasprun_dos)
    dosrun = Vasprun(vasprun_bands)
    spd_dos = dosrun.complete_dos.get_spd_dos()

    # bands
    run = Vasprun(vasprun_bands, parse_projected_eigen=True)
    bands = run.get_band_structure(kpoints,
                                   line_mode=True,
                                   efermi=dosrun.efermi)

    # set up matplotlib plot
    # ----------------------

    # general options for plot
    font = {'family': 'serif', 'size': 24}
    plt.rc('font', **font)

    # set up 2 graph with aspec ration 2/1
    # plot 1: bands diagram
    # plot 2: Density of States
    gs = GridSpec(1, 2, width_ratios=[2, 1])
    fig = plt.figure(figsize=(11.69, 8.27))
    # fig.suptitle("Bands diagram of copper")
    ax1 = plt.subplot(gs[0])
    ax2 = plt.subplot(gs[1])  # , sharey=ax1)

    # set ylim for the plot
    # ---------------------
    if ylim[0]:
        emin = ylim[0]
    else: 
        emin = -10.
    if ylim[1]:
        emax = ylim[1]
    else: 
        emax =  10.

    ax1.set_ylim(emin, emax)
    ax2.set_ylim(emin, emax)

    # Band Diagram
    # ------------
    name = element 
    pbands = bands.get_projections_on_elements_and_orbitals({name: ["s", "p", "d"]})
    # print(pbands)

    # compute s, p, d normalized contributions
    contrib = np.zeros((bands.nb_bands, len(bands.kpoints), 3))
    for b in range(bands.nb_bands):
        for k in range(len(bands.kpoints)):
            sc = pbands[Spin.up][b][k][name]["s"]**2
            pc = pbands[Spin.up][b][k][name]["p"]**2
            dc = pbands[Spin.up][b][k][name]["d"]**2
            tot = sc + pc + dc
            if tot != 0.0:
                contrib[b, k, 0] = sc / tot
                contrib[b, k, 1] = pc / tot
                contrib[b, k, 2] = dc / tot

    # plot bands using rgb mapping
    for b in range(bands.nb_bands):
        edif = [e - bands.efermi for e in bands.bands[Spin.up][b]]
        rgbline(ax1,
                range(len(bands.kpoints)),
                [e - bands.efermi for e in bands.bands[Spin.up][b]],
                contrib[b, :, 0],
                contrib[b, :, 1],
                contrib[b, :, 2])
        f = open(full_name_folder_data+'/band_'+str(b), 'w')
        for i in range(len(bands.kpoints)):
            f.write('{0:10d} {1:15.8f}'.format(i, edif[i])+'\n')
        f.close()

    f = open(full_name_folder_data+'/band_structure_full', 'w')
    for j in range(len(bands.kpoints)):
        s = str(j)+3*' '
        for i in range(bands.nb_bands):
            f1 = open(full_name_folder_data+'/band_'+str(i))
            l1 = f1.readlines()
            f1.close()
            s += l1[i].rstrip().split()[1]+3*' '
        s += '\n'
        f.write(s)
    f.close()

    # Calculating the band gap
    print('band_'+str(cb_bottom)+'_'+str(cbm_pos), bands.bands[Spin.up][cb_bottom-1][cbm_pos])
    print('band_'+str(vb_top)+'_'+str(vbm_pos), bands.bands[Spin.up][vb_top-1][vbm_pos])
    print('Eg = ', min(bands.bands[Spin.up][cb_bottom-1])-max(bands.bands[Spin.up][vb_top-1]), 'eV')
    print('Eg_man = ', bands.bands[Spin.up][cb_bottom-1][cbm_pos]-bands.bands[Spin.up][vb_top-1][vbm_pos], 'eV') 
    print('band_'+str(cb_bottom)+'_min', min(bands.bands[Spin.up][cb_bottom-1]))
    print('band_'+str(vb_top)+'_max', max(bands.bands[Spin.up][vb_top-1]))       
    print('band_'+str(cb_bottom)+'_min_point', list(bands.bands[Spin.up][cb_bottom-1]).index(min(bands.bands[Spin.up][cb_bottom-1])))
    print('band_'+str(vb_top)+'_max_point', list(bands.bands[Spin.up][vb_top-1]).index(max(bands.bands[Spin.up][vb_top-1])))


    # style
    ax1.set_xlabel("k-points")
    ax1.set_ylabel(r"$E - E_f$   /   eV")
    ax1.grid()

    # fermi level at 0
    ax1.hlines(y=0, xmin=0, xmax=len(bands.kpoints), color="k", linestyle = '--', lw=1)

    # labels
    nlabs = len(labels)
    step = len(bands.kpoints) / (nlabs - 1)
    for i, lab in enumerate(labels):
        ax1.vlines(i * step, emin, emax, "k")
    ax1.set_xticks([i * step for i in range(nlabs)])
    ax1.set_xticklabels(labels)

    ax1.set_xlim(0, len(bands.kpoints))

    # Density of states
    # ----------------

    ax2.set_yticklabels([])
    ax2.grid()
    ax2.set_xlim(1e-4, 5)
    ax2.set_xticklabels([])
    ax2.hlines(y=0, xmin=0, xmax=5, color="k", lw=2)
    ax2.set_xlabel("Density of States", labelpad=28)

    # spd contribution
    ax2.plot(spd_dos[OrbitalType.s].densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             "r-", label="s", lw=2)
    ax2.plot(spd_dos[OrbitalType.p].densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             "g-", label="p", lw=2)
    ax2.plot(spd_dos[OrbitalType.d].densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             "b-", label="d", lw=2)

    # total dos
    ax2.fill_between(dosrun.tdos.densities[Spin.up],
                     0,
                     dosrun.tdos.energies - dosrun.efermi,
                     color=(0.7, 0.7, 0.7),
                     facecolor=(0.7, 0.7, 0.7))

    ax2.plot(dosrun.tdos.densities[Spin.up],
             dosrun.tdos.energies - dosrun.efermi,
             color=(0.6, 0.6, 0.6),
             label="total DOS")

    edif1 = dosrun.tdos.energies - dosrun.efermi
    f = open(full_name_folder_data+'/dos_s_'+element, 'w')
    for i in range(len(spd_dos[OrbitalType.s].densities[Spin.up])):
        f.write('{0:15.8f} {1:15.8f}'.format(spd_dos[OrbitalType.s].densities[Spin.up][i], edif1[i])+'\n')
    f.close()

    f = open(full_name_folder_data+'/dos_p_'+element, 'w')
    for i in range(len(spd_dos[OrbitalType.p].densities[Spin.up])):
        f.write('{0:15.8f} {1:15.8f}'.format(spd_dos[OrbitalType.p].densities[Spin.up][i], edif1[i])+'\n')
    f.close()

    f = open(full_name_folder_data+'/dos_d_'+element, 'w')
    for i in range(len(spd_dos[OrbitalType.d].densities[Spin.up])):
        f.write('{0:15.8f} {1:15.8f}'.format(spd_dos[OrbitalType.d].densities[Spin.up][i], edif1[i])+'\n')
    f.close()

    f = open(full_name_folder_data+'/dos_tot', 'w')
    for i in range(len(dosrun.tdos.densities[Spin.up])):
        f.write('{0:15.8f} {1:15.8f}'.format(dosrun.tdos.densities[Spin.up][i], edif1[i])+'\n')
    f.close()

    # plot format style
    # -----------------
    ax2.legend(fancybox=True, shadow=True, prop={'size': 18})
    plt.subplots_adjust(wspace=0)
    plt.tight_layout()

    # plt.show()
    plt.savefig(folder+vasprun_bands.split('/')[-2]+".pdf", format='pdf', dpi=600)
    # print('bands.efermi ', bands.efermi)
    # print('dosrun.efermi', dosrun.efermi)
Beispiel #13
0
def add_to_archive_database(cl, subgroup):
    """
    cl is Calculation which should be added to database
    subgroup (str) - subgroup folder

    """

    from pymatgen.core.composition import Composition
    from pymatgen.io.cif import CifWriter
    from pymatgen.symmetry.analyzer import SpacegroupAnalyzer

    join = os.path.join
    basename = os.path.basename
    dirname = os.path.dirname

    save_format = 'azh'
    dbpath = header.PATH2DATABASE
    it = cl.id[0]

    # print(cl.path)
    sub_folder = cl.path['output'].split('/')[
        0]  # usually basic chemical formula
    # sub_folder = header.struct_des[it].sfolder.split('/')[0] # usually basic chemical formula

    print('Processing ', cl.id)
    cl.read_results()

    if '4' not in cl.state:
        return
    st = cl.end

    # print(cl.end.typat)
    # sys.exit()

    if 1:
        #determine x
        #universal method, supports several alkali elements
        #requires cl.base_formula in 'Na2FePO4F' format
        #requires pymatgen, would be nice to remove dependency
        cmb = Composition(cl.base_formula)
        cm = st.get_pm_composition()

        rc = cl.end.get_reduced_composition().as_dict(
        )  #reduced composition dict
        rcb = cmb.reduced_composition.as_dict()

        # print(rc, rcb)

        alk = list(set(st.get_specific_elements(
            header.ALKALI_ION_ELEMENTS)))  # list of unique alkali elements
        tra = list(set(st.get_specific_elements(header.TRANSITION_ELEMENTS)))
        # print(alk, tra)
        el_for_norm = tra[0]  #first element used for normalization

        nnb = rcb[el_for_norm]  #number of norm elements in base
        nn = rc[el_for_norm]  #number of norm elements in interesting structure
        # print(nb, n)
        mul = nn / nnb  # multiplier that garanties normalization

        # print(rcb)
        nab = sum([
            rcb[invert(z)] for z in header.ALKALI_ION_ELEMENTS
            if invert(z) in rcb
        ])

        na = sum([rc[el] for el in alk])
        x = na / mul / nab

        # determine formula
        # cm = st.get_pm_composition() #get pymatgen composition class
        # print( (cm/4).formula)

        # print('Material detected:', formula, 'sub_folder:', sub_folder)

        #obtain base without alk
        formula = (cm.reduced_composition / mul).formula
        # formula = formula.replace('1 ', '').replace(' ', '')
        # print(formula)
        cl.formula = formula
        # print(Composition('Na0.75'))
        print('Material detected:', formula, 'sub_folder:', sub_folder)

        # sys.exit()

    if 0:
        #Old method, not robust at all!
        #determine x for alkali ion from structure name
        parsed = re.findall(r'([A-Z][a-z]*)(\d*)', formula)
        parsed = [(el, x if x else '1') for (el, x) in parsed]
        print(parsed)
        print('detected element is ', parsed[0][0])

        if parsed[0][0] in [invert(z) for z in header.ALKALI_ION_ELEMENTS]:
            x = parsed[0][0]

            if hasattr(cl, 'max_alk_ion_content'):
                x = float(x) / cl.max_alk_ion_content
            else:
                x = '1'

        else:
            x = '0'

    sfolder = os.path.join(dbpath, sub_folder)

    name = []

    if 'azh' in save_format:
        #1. Single point calculation of total energy
        # print(sfolder)
        makedir(join(sfolder, 'dummy'))

        if x < 1:
            x = int(round(100 * x, 0))
        else:
            x = int(round(x, 0))

        print('Concentration x:', x)

        name.append('x' + str(x))
        # sys.exit()

        # if formula in ['LiCoO2', 'LiTiO2', 'LiFePO4', 'NaFePO4', 'LiMnPO4',
        # 'LiNiO2', 'LiTiS2', 'LiMn2O4', 'LiVP2O7', 'LiVPO4F',
        # 'NaMnAsO4', 'Na2FePO4F', 'Na2FeVF7', 'KFeSO4F', 'NaLiCoPO4F', 'KVPO4F' ]:
        sfolder = join(sfolder, subgroup)
        makedir(join(sfolder, 'dummy'))

        cl.set.update()

        # print(cl.potcar_lines)
        potcar1_m = cl.potcar_lines[0][0]

        if '_' in potcar1_m:
            (pot, _) = potcar1_m.split('_')
        else:
            pot = potcar1_m

        xc = cl.xc_inc
        if '-' in xc:
            xc = cl.xc_pot

        if xc == 'PE':
            func = 'PBE'
        elif xc == 'CA':
            func = 'LDA'
        elif xc == 'PS':
            func = 'PBEsol'
        else:
            print('uknown xc type:', xc)
            sys.exit()

        if cl.set.spin_polarized:
            func = 'U' + func  #unrestricted

        u_ramping_flag = False
        if hasattr(cl.set, 'u_ramping_nstep') and cl.set.u_ramping_nstep:
            func += '-UR'
            u_ramping_flag = True

        elif cl.set.dftu:
            func += '-U'
        else:
            func += '-'

        func += pot.lower()
        ecut = str(round(cl.set.ecut))

        func += ecut
        # print(func)
        name.append(func)

        name.extend([it.replace('.', '_')] + [cl.id[1]] + [str(cl.id[2])])

        name_str = '_'.join(name)
        # print('_'.join(name) )

        # sys.exit()

        outcar_name = name_str + '.out'

        shutil.copyfile(cl.path["output"], join(sfolder, outcar_name))

        if u_ramping_flag:
            print(cl.associated_outcars)
            for i, u_outcar in enumerate(
                    cl.associated_outcars[:-1]
            ):  # except the last one, which was copied above
                u = u_outcar.split('.')[1]
                # print(u)
                path_to_outcar = join(dirname(cl.path["output"]), u_outcar)

                cl.read_results(load='o', choose_outcar=i + 1, only_load=1)

                shutil.copyfile(path_to_outcar,
                                join(sfolder, name_str + '_' + u + '.out'))

            # sys.exit()

        cl.end.write_xyz(path=sfolder, filename=name_str)

        pickle_file = cl.serialize(os.path.join(sfolder, 'bin', name_str))
        # cl

        #write input, problem with fitted version 100, which does not have input geometry, since they are created on cluster
        # makedir(sfolder+'input/dummy')
        # shutil.copyfile(cl.path["input_geo"], sfolder+'input/'+name_str+'.geo')

        st_mp = cl.end.convert2pymatgen()
        sg_before = st_mp.get_space_group_info()
        # from pymatgen.symmetry.finder import SymmetryFinder
        # sf = SymmetryFinder(st_mp_prim)
        symprec = 0.1
        sf = SpacegroupAnalyzer(st_mp, symprec=symprec)

        st_mp_prim = sf.find_primitive()
        # st_mp_prim = sf.get_primitive_standard_structure()
        # st_mp_prim = sf.get_conventional_standard_structure()

        # st_mp_conv = sf.get_conventional_standard_structure()
        # print(st_mp_conv)
        # print(st_mp_conv.lattice.matrix)
        # print(st_mp_prim)
        # print(st_mp_prim.lattice)

        sg_after = st_mp_prim.get_space_group_info()

        if sg_before[0] != sg_after[0]:
            printlog(
                'Attention! the space group was changed after primitive cell searching',
                sg_before, sg_after)
            printlog('I will save supercell in cif and reduce symprec to 0.01')
            st_mp_prim = st_mp
            symprec = 0.01

        if st_mp_prim:
            cif = CifWriter(st_mp_prim, symprec=symprec)
            cif_name = name_str + '.cif'
            cif.write_file(join(sfolder, cif_name))
            printlog('Writing cif', cif_name)

        if 0:
            #get multiplication matrix which allows to obtain the supercell from primitive cell.
            #however this matrix is not integer which is not convinient.
            print(st_mp.lattice.matrix.round(2))
            print(st_mp_prim.lattice.matrix.round(2))

            mul_matrix = np.dot(st_mp.lattice.matrix,
                                np.linalg.inv(st_mp_prim.lattice.matrix))

            print(mul_matrix.round(1))

            rprimd = np.dot(mul_matrix, st_mp_prim.lattice.matrix)

            print(rprimd.round(2))

        #write chg
        if 1:
            path_to_chg = cl.get_chg_file('CHGCAR')
            if path_to_chg:
                makedir(join(sfolder, 'bin', 'dummy'))
                printlog('path to chgcar', path_to_chg)
                gz = '.gz'
                if gz not in path_to_chg:
                    gz = ''
                shutil.copyfile(path_to_chg,
                                join(sfolder, 'bin', name_str + '.chg' + gz))

        #write dos
        if subgroup in ['dos', 'DOS']:
            DOSCAR = cl.get_file('DOSCAR', nametype='asoutcar')
            if DOSCAR:
                printlog('path to DOSCAR', DOSCAR)
                gz = '.gz'
                if gz not in path_to_chg:
                    gz = ''
                shutil.copyfile(DOSCAR,
                                join(sfolder, 'bin', name_str + '.dos' + gz))

        if subgroup in ['BAD']:  #bader
            cl.get_bader_ACF()
            acf = cl.get_file(basename(cl.path['acf']))
            # print(acf)
            # sys.exit()
            if acf:
                shutil.copyfile(acf, join(sfolder, 'bin', name_str + '.acf'))

        if subgroup in ['ph', 'PH']:  #bader
            # cl.get_bader_ACF()
            xml = cl.get_file('vasprun.xml', nametype='asoutcar')
            # print(acf)
            # sys.exit()
            if xml:
                shutil.copyfile(xml, join(sfolder, 'bin', name_str + '.xml'))

        #make dat
        #incars
        makedir(join(sfolder, 'dat', 'dummy'))
        incars = glob.glob(join(cl.dir, '*INCAR*'))
        # print(incars)
        for inc in incars:

            dest = join(sfolder, 'dat')
            # inc_name =
            if not os.path.exists(join(dest, basename(inc))):
                shutil.copy(inc, dest)

        #kpoints
        if it in header.struct_des:
            with open(join(sfolder, 'dat', 'kpoints_for_kspacings.json'),
                      'w',
                      newline='') as fp:
                json.dump(
                    header.struct_des[it].ngkpt_dict_for_kspacings,
                    fp,
                )
        else:
            printlog('Warning!, it not in struct_des:', it)
        # print(cl.set.toJSON())

        #prepare for neb
        # makedir(sfolder+'neb_'+name_str+'/dummy')

    return
Beispiel #14
0
def get_from_database(x1,
                      x2,
                      mat,
                      inquiry_keys=None,
                      silent=None,
                      ssh_object=None):
    """
    inquiry_keys (list) - list of keys that should exist in filenames both for x1 and x2
    ssh_object (SSHTools) - ssh object based on paramiko with access details

    """
    from siman.classes import CalculationVasp

    def check(key, inquiry_keys):
        return all([k in key for k in inquiry_keys])

    path2database = '/home/Data/CEStorage/'

    hash_dict_file = 'hash_dict.json'

    cluster_path2hash = os.path.join(path2database, hash_dict_file)

    if inquiry_keys is None:
        inquiry_keys = []

    if ssh_object:
        # ssh_object.get()
        tempdir = tempfile.gettempdir()
        local_path2hash = os.path.join(tempdir, hash_dict_file)

        ssh_object.get(cluster_path2hash, local_path2hash)

        # sys.exit()

    with open(local_path2hash, 'r') as fp:
        hash_dict = json.load(fp)

    # print(hash_dict)
    x1s = []
    x2s = []
    # print(hash_dict)
    for key, val in hash_dict.items():
        if check(key, inquiry_keys + [x1, mat]):
            x1s.append(key)

        if check(key, inquiry_keys + [x2, mat]):
            x2s.append(key)

    x1s = sorted(x1s, key=lambda el: len(el))
    x2s = sorted(x2s, key=lambda el: len(el))

    for xi, xis in (x1, x1s), (x2, x2s):
        if not silent:
            print('\nFiles for', xi, ':')
        for i, f in enumerate(xis):
            if not silent:

                print(i + 1, f)

    if len(x1s) == 0 or len(x2s) == 0:
        print('No information in database for this inquire:', x1, x2, mat,
              str(inquiry_keys))
        return None, None

    key1 = x1s[0]
    key2 = x2s[0]

    if not silent:

        print('\nI choose first entries for both concentrations:', key1, 'and',
              key2, '\n')
    # print('Use *inquiry_keys* arg to clarify the output results.\n')

    #get files
    loc1 = os.path.join(tempdir, hash_dict[key1])
    loc2 = os.path.join(tempdir, hash_dict[key2])
    makedir(loc1)
    makedir(loc2)
    # print()/

    ssh_object.get(os.path.join(path2database, hash_dict[key1]), loc1)
    ssh_object.get(os.path.join(path2database, hash_dict[key2]), loc2)

    cl1 = CalculationVasp().deserialize(loc1)
    cl2 = CalculationVasp().deserialize(loc2)

    return cl1, cl2
Beispiel #15
0
def get_from_server(files=None, to=None, to_file=None, addr=None, trygz=True):
    """
    Download files using either  paramiko (higher priority) or rsync; 
    For paramiko header.ssh_object should be defined

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

    The gz file is also checked

    RETURN
        result of download

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


    """

    # print(addr)

    def download(file, to_file):

        if header.ssh_object:

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

        elif header.sshpass and header.sshpass == 'proxy':
            # com = 'ssh sdv "sshpass -f ~/.ssh/p ssh ' + addr + ' \\"tar zcf - '+ file +'\\"" | tar zxf - '+to_file # does not work?
            com = 'ssh sdv "sshpass -f ~/.ssh/p ssh ' + addr + ' \\"tar cf - ' + file + '\\"" > ' + to_file
            # print(com)
            # sys.exit()
            out = runBash(com)

        elif header.sshpass:
            com = 'rsync --rsh=' + "'sshpass -f /home/aksenov/.ssh/p ssh' " + ' -uaz  ' + addr + ':' + file + ' ' + to_file
            out = runBash(com)

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

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

        printlog('Download result is ', res)

        return out

    if '*' in files:
        printlog('get_from_server(): get by template')
        files = run_on_server('ls ' + files, addr).splitlines()
        # print(files)
        # sys.exit()
        printlog('get_from_server(): I download', files)

    elif not is_list_like(files):
        files = [files]

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

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

    for file in files:

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

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

        else:
            to_file_l = to_file

        makedir(to_file_l)

        out = download(file, to_file_l)

        if out and trygz:

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

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

    return out
Beispiel #16
0
def make_vaspkit_kpoints(type_calc='',
                         type_lattice='',
                         poscar='',
                         list_kpoints=[],
                         kpoints_density=0.02,
                         k_cutoff=0.015,
                         num_points=6,
                         folder_vaspkit=''):
    """
    The function is used to prepare KPOINTS using the "VASPKIT" package
    INPUT:
        
        - type_calc (str)             - quantity, which is calculated 
            - "effective mass" - prepare the KPOINTS file to calculate the effective mass along chosen directions in the reciprocal space
        - type_lattice (str)          - one of common lattices such as bcc, fcc, hcp etc.
            - "hcp" - hexagonal close-packed lattice
        - poscar (str)                - POSCAR file with structure, for which the KPOINTS file is built
        - list_kpoints (list of tuples)         - list of additional kpoints to add into the KPOINTS file with zero weights;
                                                  has format [((a1,a2,a3,label_a),(b1,b2,b3,label_b)),...], where "a" and "b" are 
                                                  the relative coordinates of points (floats) in the reciprocal space, "label" (str) is the name of the point
                                                  These two points determine the direction in the reciprocal space.
        - kpoints_density (float)     - density of k-points with non-zero weights
        - k_cutoff (float)            - distance along the choosen direction in the reciprocal space in A^{-1} unit
        - num_points (int)            - number of k-points along the choosen direction in the reciprocal space
        - folder_vaspkit (str)        - name of folder to make the KPOINTS file
    RETURN:
        None
    SOURCE:
        For more details see:
        https://vaspkit.com/tutorials.html#effective-mass 
    TODO:
        - Add more common lattices such as bcc, fcc etc.
        - Add another types of calculations requiring the specific KPOINTS files


    """

    makedir(folder_vaspkit)

    if type_lattice == 'hex':
        initial_list_kpoints = [
            ((0.000000, 0.000, 0.000, 'G'), (0.33333, 0.33333, 0.000, 'K')),
            ((0.000000, 0.000, 0.000, 'G'), (0.50000, 0.00000, 0.000, 'M')),
            ((0.000000, 0.000, 0.000, 'G'), (0.50000, 0.00000, 0.000, 'X')),
            ((0.000000, 0.000, 0.000, 'G'), (0.00000, 0.50000, 0.000, 'Y'))
        ]

    S.copy(poscar, folder_vaspkit + '/POSCAR')
    f = open(folder_vaspkit + 'info', 'w')
    f.write(poscar + ' = POSCAR')
    f.close()

    if type_calc == 'effective_mass':
        full_list_kpoints = initial_list_kpoints + list_kpoints

        f = open(folder_vaspkit + '/VPKIT.in', 'w')
        f.write(
            '1       # "1" for pre-process (generate KPOINTS), "2" for post-process(calculate m*)\n'
        )
        f.write(
            str(num_points) +
            '      #  number of points for quadratic function fitting.\n')
        f.write(str(k_cutoff) + '   # k-cutoff, unit Å-1.\n')
        f.write(
            str(len(full_list_kpoints)) +
            '       # number of tasks for effective mass calculation\n')
        for i in full_list_kpoints:
            f.write(
                '{0:10.7f} {1:10.7f} {2:10.7f} {3:10.7f} {4:10.7f} {5:10.7f}'.
                format(i[0][0], i[0][1], i[0][2], i[1][0], i[1][1], i[1][2]) +
                3 * ' ' + i[0][3] + '->' + i[1][3] + '\n')
        f.close()

        s = SP.Popen(header.PATH2VASPKIT + ' -task 912 -kpr ' +
                     str(kpoints_density),
                     cwd=folder_vaspkit,
                     shell=True)

        s.wait()

        print('File ' + folder_vaspkit + '/KPOINTS was built successfully')