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


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

    """Additional values"""
    # check_pore_vol = 1
    #if calctype in ("pore_vol","gb","grain_vol","all_local" ): check_pore_vol = 1 #something wrong with this function, especially for big cells

    """----Conversions of types for C++"""
    r1 = create_c_array(rprimd[0], float)
    r2 = create_c_array(rprimd[1], float)
    r3 = create_c_array(rprimd[2], float)

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

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

    pxred1 = (c_float * max_npores)(0) #make static arrays natoms + npore
    pxred2 = (c_float * max_npores)(0)
    pxred3 = (c_float * max_npores)(0)

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

    print "ntot is ", ntot.value
    print "l_npores[0] is ",l_npores[0]

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

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

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

        shift1 = shift2



    if shift2 != ntot.value: print "Error! final shift2 not equal to ntot"

    #print l_pxred[0]

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

    #print pxred
    """----End of C++; result is two lists: lpxred - local geometry of all pores, pxred - coordinates of all pores"""


    """ Analyse of pores """
    st_result = Structure()
    st_result.rprimd = rprimd
 
    targetp = np.array((0.,0.,0.))
    if find_close_to: 
        targetp = np.asarray(find_close_to) #targer point
        print "Target point is                        ",targetp
 
    a = step_dec/fine #the side of little cube formed by the mesh which is used to find spheres inside the pore.
    aaa = a*a*a


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


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

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

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

        #print "rprimd[0][0]", rprimd[0][0]
        print "Position of boundary is ",gbpos/rprimd[0][0]
     
        #x_min[0] = gbpos/rprimd[0][0]
        if find_close_to: print "The closest pore to the target point is [ %.2f  %.2f  %.2f ]"%(x_min[0], x_min[1], x_min[2])
        else: print "The closest pore to the gb has coordinates",x_min
        st_result.xred.append( x_min )
        #st_result.xred.append( x_pre )           
        #Calculate volume of the pore using local balls:
        print "The number of pore is ",i_min," ; It has ",l_npores[i_min], "local balls"
        print "Volume of pore is ", l_npores[i_min] * a*a*a, " A^3";
Exemple #2
0
    def write_geometry_files(
        dlist,
        in_calc,
        xcart_pores,
        segtyp,
        take_final_rprimd_from=None,
        add_name_before="",
        tlist=[],
        configver=False,
        add_typat=None,
    ):
        """Creating files
        dlist - list of pairs with distances and numbers
        in_calc - base calculation without pores

        tlist - list of additional atoms in the case of triples; list of structures
        configver - if True each configuration saved as a new version
        add_typat - manually determined; please automatize!
        """

        print "Warning! add_typat", add_typat
        if tlist == []:  # convert dlist to tlist - to do earlier
            for el in dlist:
                config = Structure()
                config.name = el[2]
                config.length = el[0]
                config.typat = add_typat
                config.xcart = [el[7], el[8]]
                tlist.append(config)

        for i, el in enumerate(tlist):  # by all found structures
            print "el name is ", el.name
            stn = copy.deepcopy(in_calc.init)
            calc = copy.deepcopy(in_calc)

            stn.typat.extend(el.typat)
            stn.xcart.extend(el.xcart)

            stn.xred = xcart2xred(stn.xcart, stn.rprimd)

            xcart_check = xred2xcart(stn.xred, stn.rprimd)
            assert len(xcart_check) == len(stn.xcart)  # test

            assert all(
                [all(np.around(v1, 8) == np.around(v2, 8)) for (v1, v2) in zip(stn.xcart, xcart_check)]
            )  # check if xcart2xred(stn.xcart,r) and xred2xcart(stn.xred,r) are working correctly up to the eight digits after

            stn.natom = len(stn.xcart)

            """Adapt new rprimd"""
            print "take final rprimd is ", take_final_rprimd_from
            if take_final_rprimd_from:  # read final rprimd and version
                print "Start to read rprimd and version from " + take_final_rprimd_from
                in_calc_rprimd = CalculationVasp()
                in_calc_rprimd.name = "temp"
                in_calc_rprimd.read_geometry(take_final_rprimd_from)

                stn.rprimd = in_calc_rprimd.init.rprimd
                stn.xcart = xred2xcart(stn.xred, stn.rprimd)

                calc.version = in_calc_rprimd.version
            elif configver:
                calc.version = i + 1

            calc.init = stn

            des = (
                " was obtained by the insertion of C-O pair into "
                + in_calc_name
                + "; final vectors taken from corresponding ver"
            )

            calc.build.ipairlen = el.length  # Initial length of pair
            if not hasattr(calc.build, "nadded") or calc.build.nadded == None:
                calc.build.nadded = 2
            else:
                calc.build.nadded += 2
            if not hasattr(calc.build, "listadded") or calc.build.listadded == [None]:
                calc.build.listadded = range(stn.natom - 2, stn.natom)  # list of atoms which were added
            else:
                calc.build.listadded.extend(range(stn.natom - 2, stn.natom))

            structure_name = calc.name + el.name.split(".")[0]
            # calc.name = add_name_before+calc.name+ '.' +el[2]+'.'+str(calc.version)
            print "Structure_name", structure_name
            if structure_name in struct_des:

                if configver:
                    fname = structure_name  # calc.name+'C2O2'
                    calc.path["input_geo"] = (
                        geo_folder
                        + struct_des[fname].sfolder
                        + "/"
                        + fname
                        + "/"
                        + structure_name
                        + "."
                        + segtyp
                        + "."
                        + str(calc.version)
                        + ".geo"
                    )
                else:
                    calc.path["input_geo"] = (
                        geo_folder
                        + struct_des[structure_name].sfolder
                        + "/"
                        + structure_name
                        + "/"
                        + structure_name
                        + "."
                        + segtyp
                        + "."
                        + str(calc.version)
                        + ".geo"
                    )
                print "write geo to ", calc.path["input_geo"]
                calc.write_geometry("init", des)

            print "write_geometry_files(): name ", el.name
            stn.name = add_name_before + calc.name + "" + str(el.name) + "." + str(calc.version)
            # stn = replic(stn, (1,2,2))
            write_xyz(stn)
            print "__________________________\n\n\n"
        return
Exemple #3
0
    def write_geometry_files(dlist,
                             in_calc,
                             xcart_pores,
                             segtyp,
                             take_final_rprimd_from=None,
                             add_name_before='',
                             tlist=[],
                             configver=False,
                             add_typat=None):
        """Creating files
        dlist - list of pairs with distances and numbers
        in_calc - base calculation without pores

        tlist - list of additional atoms in the case of triples; list of structures
        configver - if True each configuration saved as a new version
        add_typat - manually determined; please automatize!
        """

        print "Warning! add_typat", add_typat
        if tlist == []:  #convert dlist to tlist - to do earlier
            for el in dlist:
                config = Structure()
                config.name = el[2]
                config.length = el[0]
                config.typat = add_typat
                config.xcart = [el[7], el[8]]
                tlist.append(config)

        for i, el in enumerate(tlist):  #by all found structures
            print "el name is ", el.name
            stn = copy.deepcopy(in_calc.init)
            calc = copy.deepcopy(in_calc)

            stn.typat.extend(el.typat)
            stn.xcart.extend(el.xcart)

            stn.xred = xcart2xred(stn.xcart, stn.rprimd)

            xcart_check = xred2xcart(stn.xred, stn.rprimd)
            assert len(xcart_check) == len(stn.xcart)  #test

            assert all(
                [
                    all(np.around(v1, 8) == np.around(v2, 8))
                    for (v1, v2) in zip(stn.xcart, xcart_check)
                ]
            )  #check if xcart2xred(stn.xcart,r) and xred2xcart(stn.xred,r) are working correctly up to the eight digits after

            stn.natom = len(stn.xcart)
            """Adapt new rprimd"""
            print "take final rprimd is ", take_final_rprimd_from
            if take_final_rprimd_from:  #read final rprimd and version
                print "Start to read rprimd and version from " + take_final_rprimd_from
                in_calc_rprimd = CalculationVasp()
                in_calc_rprimd.name = 'temp'
                in_calc_rprimd.read_geometry(take_final_rprimd_from)

                stn.rprimd = in_calc_rprimd.init.rprimd
                stn.xcart = xred2xcart(stn.xred, stn.rprimd)

                calc.version = in_calc_rprimd.version
            elif configver:
                calc.version = i + 1

            calc.init = stn

            des = ' was obtained by the insertion of C-O pair into ' + in_calc_name + '; final vectors taken from corresponding ver'

            calc.build.ipairlen = el.length  # Initial length of pair
            if not hasattr(calc.build, 'nadded') or calc.build.nadded == None:
                calc.build.nadded = 2
            else:
                calc.build.nadded += 2
            if not hasattr(calc.build,
                           'listadded') or calc.build.listadded == [None]:
                calc.build.listadded = range(
                    stn.natom - 2, stn.natom)  #list of atoms which were added
            else:
                calc.build.listadded.extend(range(stn.natom - 2, stn.natom))

            structure_name = calc.name + el.name.split('.')[0]
            #calc.name = add_name_before+calc.name+ '.' +el[2]+'.'+str(calc.version)
            print 'Structure_name', structure_name
            if structure_name in struct_des:

                if configver:
                    fname = structure_name  # calc.name+'C2O2'
                    calc.path["input_geo"] = geo_folder + struct_des[
                        fname].sfolder + '/' + fname + '/' + structure_name + '.' + segtyp + '.' + str(
                            calc.version) + '.geo'
                else:
                    calc.path["input_geo"] = geo_folder + struct_des[
                        structure_name].sfolder + '/' + structure_name + '/' + structure_name + '.' + segtyp + '.' + str(
                            calc.version) + '.geo'
                print "write geo to ", calc.path["input_geo"]
                calc.write_geometry('init', des)

            print "write_geometry_files(): name ", el.name
            stn.name = add_name_before + calc.name + '' + str(
                el.name) + '.' + str(calc.version)
            #stn = replic(stn, (1,2,2))
            write_xyz(stn)
            print "__________________________\n\n\n"
        return
Exemple #4
0
    def triples(addatom=("O", 3), dlist=[], tlist=[], in_calc=None, xcart_pores=[], max_dist_to_next_atom=3):
        """
        Add addatom to all configurations in tlist; 

        addatom[1] - type of atom in typat
        dlist - list of configurations with two impurity atoms; Used if tlist == []; the format of dlist is quiet special
        tlist - list of configurations with arbirtary number of atoms;

        RETURN:
        tlist - list of configurations with add atoms
        """
        st = in_calc.init

        if dlist and tlist == []:
            for el in dlist:
                par = el
                print "pair 1", par,
                x1 = par[7]
                x2 = par[8]
                print "x1 = ", x1
                print "x2 = ", x2
                config = Structure()
                config.xcart = [x1, x2]
                config.typat = [2, 3]
                config.name = el[2]
                tlist.append(config)

        tlist_new = []
        for config in tlist:
            xcart = config.xcart
            typat = config.typat
            name = config.name
            print "\n\n\nStart to adding atom to ", name

            i = 1
            dlistlist = []

            diffprec = 0.001

            [dlistlist.append([]) for x in xcart]
            print len(dlistlist)

            for xpor in xcart_pores:

                skip = True
                for j, x in enumerate(xcart):  # list of 2 or 3 initial atoms to which additional atom will be added
                    if all(np.around(xpor, 5) == np.around(x, 5)):
                        skip = True
                        break

                    d1, d2 = image_distance(x, xpor, st.rprimd, 2)  # the minimum distance and the next minimum dist
                    if d1 > max_dist_to_next_atom:
                        skip = True
                        break  # if only one pore is larger from atom than limit, the pore is skiped

                    # suml = d11+d21+par[0]
                    # for dl in dlistlist:
                    # print 'j is ', j

                    i_min, smaller = min_diff(
                        d1, dlistlist[j], diffprec
                    )  # old condition - bad - removes unique configurations
                    # if smaller: skip = True; continue # symmetrical pores deleted

                    dlistlist[j].append(d1)
                    skip = False  # all conditions are fullfilled - this configuration is unique
                # else:
                # print 'List of distances to atoms'
                if skip:
                    continue  #

                # print "Pore can be used", xpor #sum of distances for triple

                new = Structure()
                new.name = name + addatom[0] + str(i)
                new.xcart = copy.deepcopy(xcart)
                new.xcart.append(xpor)
                new.typat = copy.deepcopy(typat)
                new.typat.append(addatom[1])
                # print 'new.typat  =', new.typat

                # calculate sum of lengths
                new.length = 0
                new.lengthCO = 0
                new.lengthCC = 0
                new.lengthOO = 0
                new.xcartC = []
                new.xcartO = []
                for m, x1 in enumerate(new.xcart):
                    if new.typat[m] == 2:
                        new.xcartC.append(x1)
                    if new.typat[m] == 3:
                        new.xcartO.append(x1)

                    for x2 in new.xcart:
                        d1, d2 = image_distance(x1, x2, st.rprimd, 2)
                        new.length += d1

                for xC in new.xcartC:
                    for xO in new.xcartO:
                        d1, d2 = image_distance(xC, xO, st.rprimd, 2)
                        new.lengthCO += d1

                for xC1 in new.xcartC:
                    for xC2 in new.xcartC:

                        d1, d2 = image_distance(xC1, xC2, st.rprimd, 2)
                        new.lengthCC += d1

                for xO1 in new.xcartO:
                    for xO2 in new.xcartO:

                        d1, d2 = image_distance(xO1, xO2, st.rprimd, 2)
                        new.lengthOO += d1

                skip = False
                n = len(new.xcart)

                """additional conditions to leave only unique configurations"""
                for config in tlist_new:
                    if 1:
                        nr = 0
                        for (v1, t1) in zip(new.xcart, new.typat):
                            for (v2, t2) in zip(config.xcart, config.typat):
                                if all(np.around(v1, 8) == np.around(v2, 8)) and t1 == t2:
                                    nr += 1
                        if nr == n:
                            print "The configurations", new.name, "and", config.name, "consist of the same atoms, continue"
                            skip = True
                            break

                    # print  all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(new.xcart, config.xcart) ])

                    # check identity using sum of distances
                    # i_min, smaller = min_diff(config.length, [new.length], diffprec)
                    # if smaller:
                    #     print "Configuration ", new.name, "has the same sum of lengths as", config.name
                    i_min, smaller1 = min_diff(config.lengthCO, [new.lengthCO], diffprec)
                    i_min, smaller2 = min_diff(config.lengthCC, [new.lengthCC], diffprec)
                    i_min, smaller3 = min_diff(config.lengthOO, [new.lengthOO], diffprec)
                    # print 'Compare', new.name, config.name, smaller1, smaller2, smaller3
                    if smaller1 and smaller2 and smaller3:
                        print "\nConfiguration ", new.name, "has the same sum of C-O, C-C  and O-O lengths as", config.name
                        print
                        skip = True
                        break

                if skip:
                    continue
                print "\nSum of CO lengths in :", new.name, new.lengthCC, new.lengthOO, new.lengthCO

                tlist_new.append(new)

                i += 1

        return tlist_new
Exemple #5
0
    def triples(addatom=('O', 3),
                dlist=[],
                tlist=[],
                in_calc=None,
                xcart_pores=[],
                max_dist_to_next_atom=3):
        """
        Add addatom to all configurations in tlist; 

        addatom[1] - type of atom in typat
        dlist - list of configurations with two impurity atoms; Used if tlist == []; the format of dlist is quiet special
        tlist - list of configurations with arbirtary number of atoms;

        RETURN:
        tlist - list of configurations with add atoms
        """
        st = in_calc.init

        if dlist and tlist == []:
            for el in dlist:
                par = el
                print 'pair 1', par,
                x1 = par[7]
                x2 = par[8]
                print 'x1 = ', x1
                print 'x2 = ', x2
                config = Structure()
                config.xcart = [x1, x2]
                config.typat = [2, 3]
                config.name = el[2]
                tlist.append(config)

        tlist_new = []
        for config in tlist:
            xcart = config.xcart
            typat = config.typat
            name = config.name
            print '\n\n\nStart to adding atom to ', name

            i = 1
            dlistlist = []

            diffprec = 0.001

            [dlistlist.append([]) for x in xcart]
            print len(dlistlist)

            for xpor in xcart_pores:

                skip = True
                for j, x in enumerate(
                        xcart
                ):  # list of 2 or 3 initial atoms to which additional atom will be added
                    if all(np.around(xpor, 5) == np.around(x, 5)):
                        skip = True
                        break

                    d1, d2 = image_distance(
                        x, xpor, st.rprimd,
                        2)  # the minimum distance and the next minimum dist
                    if d1 > max_dist_to_next_atom:
                        skip = True
                        break  #if only one pore is larger from atom than limit, the pore is skiped

                    # suml = d11+d21+par[0]
                    # for dl in dlistlist:
                    # print 'j is ', j

                    i_min, smaller = min_diff(
                        d1, dlistlist[j], diffprec
                    )  #old condition - bad - removes unique configurations
                    #if smaller: skip = True; continue # symmetrical pores deleted

                    dlistlist[j].append(d1)
                    skip = False  # all conditions are fullfilled - this configuration is unique
                # else:
                # print 'List of distances to atoms'
                if skip: continue  #

                #print "Pore can be used", xpor #sum of distances for triple

                new = Structure()
                new.name = name + addatom[0] + str(i)
                new.xcart = copy.deepcopy(xcart)
                new.xcart.append(xpor)
                new.typat = copy.deepcopy(typat)
                new.typat.append(addatom[1])
                # print 'new.typat  =', new.typat

                #calculate sum of lengths
                new.length = 0
                new.lengthCO = 0
                new.lengthCC = 0
                new.lengthOO = 0
                new.xcartC = []
                new.xcartO = []
                for m, x1 in enumerate(new.xcart):
                    if new.typat[m] == 2: new.xcartC.append(x1)
                    if new.typat[m] == 3: new.xcartO.append(x1)

                    for x2 in new.xcart:
                        d1, d2 = image_distance(x1, x2, st.rprimd, 2)
                        new.length += d1

                for xC in new.xcartC:
                    for xO in new.xcartO:
                        d1, d2 = image_distance(xC, xO, st.rprimd, 2)
                        new.lengthCO += d1

                for xC1 in new.xcartC:
                    for xC2 in new.xcartC:

                        d1, d2 = image_distance(xC1, xC2, st.rprimd, 2)
                        new.lengthCC += d1

                for xO1 in new.xcartO:
                    for xO2 in new.xcartO:

                        d1, d2 = image_distance(xO1, xO2, st.rprimd, 2)
                        new.lengthOO += d1

                skip = False
                n = len(new.xcart)
                """additional conditions to leave only unique configurations"""
                for config in tlist_new:
                    if 1:
                        nr = 0
                        for (v1, t1) in zip(new.xcart, new.typat):
                            for (v2, t2) in zip(config.xcart, config.typat):
                                if all(np.around(v1, 8) == np.around(
                                        v2, 8)) and t1 == t2:
                                    nr += 1
                        if nr == n:
                            print "The configurations", new.name, 'and', config.name, 'consist of the same atoms, continue'
                            skip = True
                            break

                    # print  all([ all( np.around(v1, 8) == np.around(v2, 8) ) for (v1, v2) in zip(new.xcart, config.xcart) ])

                    #check identity using sum of distances
                    # i_min, smaller = min_diff(config.length, [new.length], diffprec)
                    # if smaller:
                    #     print "Configuration ", new.name, "has the same sum of lengths as", config.name
                    i_min, smaller1 = min_diff(config.lengthCO, [new.lengthCO],
                                               diffprec)
                    i_min, smaller2 = min_diff(config.lengthCC, [new.lengthCC],
                                               diffprec)
                    i_min, smaller3 = min_diff(config.lengthOO, [new.lengthOO],
                                               diffprec)
                    # print 'Compare', new.name, config.name, smaller1, smaller2, smaller3
                    if smaller1 and smaller2 and smaller3:
                        print "\nConfiguration ", new.name, "has the same sum of C-O, C-C  and O-O lengths as", config.name
                        print
                        skip = True
                        break

                if skip: continue
                print '\nSum of CO lengths in :', new.name, new.lengthCC, new.lengthOO, new.lengthCO

                tlist_new.append(new)

                i += 1

        return tlist_new