def find_pores(st_in, r_matrix=1.4, r_impurity = 0.6, step_dec = 0.05, fine = 0.3, prec = 0.1, calctype = 'central', gbpos = 0, find_close_to = (), check_pore_vol = 0): """ st_in - input Structure() object r_impurity (A)- all pores smaller than this radius will be found r_matrix (A) - radius of matrix atoms disregarding to their type step_dec - scanning step of the cell in Angstroms fine - allows to change density of local points; local_step = step_dec/fine prec - precicion of pore center determination check_pore_vol - allows to estimate volume of pores; has problems for big cells 'find_close_to' - works in the cases of gb and grain_vol; allows to ignore all and find pore close to provided three reduced coordinates return - instance of Structure() class with coordinates of pores. Number and type of included pores depend on the argument of 'calctype'. """ xred = st_in.xred natom = len(xred) rprimd = st_in.rprimd name = st_in.name #print xred """Additional values""" # check_pore_vol = 1 #if calctype in ("pore_vol","gb","grain_vol","all_local" ): check_pore_vol = 1 #something wrong with this function, especially for big cells """----Conversions of types for C++""" r1 = create_c_array(rprimd[0], float) r2 = create_c_array(rprimd[1], float) r3 = create_c_array(rprimd[2], float) xred1 = (c_float * len(xred))(*[x[0] for x in xred]) xred2 = (c_float * len(xred))(*[x[1] for x in xred]) xred3 = (c_float * len(xred))(*[x[2] for x in xred]) max_npores = 10000; ntot = ctypes.c_int32(); npores = ctypes.c_int32() l_pxred1 = (c_float * max_npores)(0) #make static arrays fol local points l_pxred2 = (c_float * max_npores)(0) l_pxred3 = (c_float * max_npores)(0) l_npores = (ctypes.c_int32 * max_npores)(0) pxred1 = (c_float * max_npores)(0) #make static arrays natoms + npore pxred2 = (c_float * max_npores)(0) pxred3 = (c_float * max_npores)(0) """----Run C++ function""" print_and_log("Starting C++ function lib.findpores()...\n") lib.findpores ( check_pore_vol, \ max_npores, \ byref(ntot), l_pxred1, l_pxred2, l_pxred3, l_npores, \ byref(npores), pxred1, pxred2, pxred3, \ natom, xred1, xred2, xred3, \ c_float(r_matrix), c_float(r_impurity), c_float(step_dec), c_float(fine), c_float(prec), \ r1, r2, r3 ) print_and_log( "ntot is ", ntot.value) print_and_log( "l_npores[0] is ",l_npores[0]) v = np.zeros((3)) l_pxred = [] shift1 = 0; shift2 = 0 for i_por in range(npores.value): l_pxred.append( [] ) shift2+=l_npores[i_por] for i in range(shift1, shift2): v[0] = l_pxred1[i]; v[1] = l_pxred2[i]; v[2] = l_pxred3[i] l_pxred[i_por].append( v.copy() ) shift1 = shift2 if shift2 != ntot.value: print_and_log( "Error! final shift2 not equal to ntot") #print l_pxred[0] pxred = [] # only coordinates of pores #print pxred1[natom] for i in range(npores.value): v[0] = pxred1[i+natom]; v[1]= pxred2[i+natom]; v[2] = pxred3[i+natom] #with shift, because first natom elements are coordinates of atoms pxred.append( v.copy() ) #print pxred """----End of C++; result is two lists: lpxred - local geometry of all pores, pxred - coordinates of all pores""" """ Analyse of pores """ st_result = Structure() st_result.rprimd = rprimd targetp = np.array((0.,0.,0.)) if find_close_to: targetp = np.asarray(find_close_to) #targer point print_and_log( "Target point is ",targetp) a = step_dec/fine #the side of little cube formed by the mesh which is used to find spheres inside the pore. aaa = a*a*a #find most central pore if calctype == 'central': #return coordinates of the most central pore st_result.name = "central_pore_from "+name center = np.array((0.5,0.5,0.5))#center of cell d_min = 100 for x in pxred: d = np.linalg.norm(x - center) #print x, x-center, d if d < d_min and x[0] <= 0.5 and x[1] <= 0.5 and x[2] <= 0.5: d_min = d x_min = x print_and_log( "The closest pore to the center has coordinates",x_min) st_result.xred.append( x_min ) elif calctype == 'gb': #add impurity at gb st_result.name = "gb_pore_from "+name d_min = 100; #d2_min = 100 dt_min =100 i_min = 0; x_min = np.zeros((3)) for i, x in enumerate(pxred): #print "l_npores ",l_npores[i] d = abs(x[0] - gbpos/rprimd[0][0]) # #print x[0], d if find_close_to: closer = (np.linalg.norm(targetp - x) < dt_min) else: closer = ( d < d_min ) # and x[1]>0.3 and x[2]>0.3: if closer: x_pre = x_min i_pre = i_min d_min = d dt_min = np.linalg.norm(targetp - x) x_min = x i_min = i #find and add impurity in bulk #d2 = abs( x[0] - (gbpos/rprimd[0][0] - 0.25) ) #if d2 < d2_min: # d2_min = d2 # x2_min = x # i2_min = i #print "rprimd[0][0]", rprimd[0][0] print_and_log( "Position of boundary is ",gbpos/rprimd[0][0]) #x_min[0] = gbpos/rprimd[0][0] if find_close_to: print_and_log( "The closest pore to the target point is [ %.2f %.2f %.2f ]"%(x_min[0], x_min[1], x_min[2])) else: print_and_log( "The closest pore to the gb has coordinates",x_min) st_result.xred.append( x_min ) #st_result.xred.append( x_pre ) #Calculate volume of the pore using local balls: print_and_log( "The number of pore is ",i_min," ; It has ",l_npores[i_min], "local balls") print_and_log( "Volume of pore is ", l_npores[i_min] * a*a*a, " A^3") #st_result.xred.extend( l_pxred[i_min] ) #st_result.xred.extend( l_pxred[i_pre] ) #print "The closest pore to the center of bulk has coordinates",x2_min #st_result.xred.append( x2_min ) #Calculate volume of the pore using local balls: #print "The number of bulk pore is ",i2_min," ; It has ",l_npores[i2_min], "local balls" #print "Volume of pore is ", l_npores[i2_min] * a*a*a, " A^3"; #st_result.xred.extend( l_pxred[i2_min] ) elif calctype == 'grain_vol': #add impurity to volume of grain st_result.name = "grain_volume_pore_from "+name d2_min = 100 dt_min = 100 i_min = 0; x_min = np.zeros((3)) for i, x in enumerate(pxred): #find and add impurity to the bulk d2 = abs( x[0] - (gbpos/rprimd[0][0] - 0.25) ) if find_close_to: closer = (np.linalg.norm(targetp - x) < dt_min) else: closer = ( d2 < d2_min ) # and x[1]>0.3 and x[2]>0.3: if closer: dt_min = np.linalg.norm(targetp - x) d2_min = d2 x2_min = x i2_min = i if find_close_to: print_and_log( "The closest pore to the target point is [ %.2f %.2f %.2f ]"%(x2_min[0], x2_min[1], x2_min[2])) else: print_and_log( "The closest pore to the center of bulk has coordinates",x2_min) st_result.xred.append( x2_min ) #Calculate volume of the pore using local balls: print_and_log( "The number of bulk pore is ",i2_min," ; It has ",l_npores[i2_min], "local balls") print_and_log( "Volume of pore is ", l_npores[i2_min] * a*a*a, " A^3") st_result.xred.extend( l_pxred[i2_min] ) elif calctype == 'all_local': st_result.name = "all_local_points_from "+name v_max = 0 i_max = 0 for i in range(npores.value): v_pore = l_npores[i] * aaa print_and_log( "Volume of pore is ", l_npores[i] * aaa, " A^3") if v_pore > v_max: v_max = v_pore; i_max = i print_and_log( "Pore number ", i_max,"has the largest volume ", v_max," A^3") # st_result.xred = l_pxred[i_max] # here coordinates of all local points to show geometry of pore with largerst volume st_result.xred = [x for group in l_pxred for x in group ] # all pores elif calctype == 'all_pores': st_result.name = "all_local_pores_from "+name st_result.xred = pxred st_result.xcart = xred2xcart(st_result.xred, rprimd) st_result.typat = [1 for x in st_result.xred] st_result.natom = len(st_result.typat) st_result.znucl = [200] st_ntypat = 1 return st_result
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
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
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
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