def hardness_XX(self, initial_cutoff_radius=0.8, use_laplacian=True): bonds, coordination, cutoff_radius = self.bonds_coordination( initial_cutoff_radius=initial_cutoff_radius, use_laplacian=use_laplacian) sigma = 3.0 c_hard = 1300.0 xprod = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 atomicnumbers = atomic_number(self.structure.species) pcm_log.debug('Atomic numbers in the structure : %s' % str(atomicnumbers)) for i in atomicnumbers: f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) if f_d == 0: pcm_log.debug('Returning zero as hardness. f_d= %10.3f' % f_d) return 0.0 f = 1.0 - (self.structure.nspecies * f_n**(1.0 / self.structure.nspecies) / f_d)**2 diff_bonds = [x for x in bonds if len(bonds[x]) > 0] for pair in diff_bonds: i1 = pair[0] i2 = pair[1] ei = valence(self.structure.symbols[i1]) / covalent_radius( self.structure.symbols[i1]) ej = valence(self.structure.symbols[i2]) / covalent_radius( self.structure.symbols[i2]) for dij in bonds[pair]: sij = math.sqrt( ei * ej) / (coordination[i1] * coordination[i2]) / dij xprod *= sij num_i_j_bonds = len(bonds[pair]) pcm_log.debug('Number of bonds for pair %s = %d' % (str(pair), num_i_j_bonds)) tot += num_i_j_bonds vol = self.structure.volume pcm_log.debug("Structure volume: %7.3f" % vol) pcm_log.debug("Total number of bonds: %d" % tot) pcm_log.debug("Bonds: %s" % str(bonds)) hardness_value = (c_hard / vol) * tot * (xprod**(1. / tot)) * math.exp( -sigma * f) return round(hardness_value, 3), cutoff_radius, coordination
def hardness_XX(self, initial_cutoff_radius=0.8, use_laplacian=True): """ Implementation of Hardness algorithm: First-principles structural design of superhard materials J. Chem. Phys. 138, 114101 (2013); https://doi.org/10.1063/1.4794424 Xinxin Zhang, et al. """ bonds, coordination, cutoff_radius = self.bonds_coordination(initial_cutoff_radius=initial_cutoff_radius, use_laplacian=use_laplacian) sigma = 3.0 c_hard = 1300.0 xprod = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 atomicnumbers = atomic_number(self.structure.species) pcm_log.debug('Atomic numbers in the structure : %s' % str(atomicnumbers)) for i in atomicnumbers: f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) if f_d == 0: pcm_log.debug('Returning zero as hardness. f_d= %10.3f' % f_d) return 0.0 f = 1.0 - (self.structure.nspecies * f_n ** (1.0 / self.structure.nspecies) / f_d) ** 2 diff_bonds = [x for x in bonds if len(bonds[x]) > 0] for pair in diff_bonds: i1 = pair[0] i2 = pair[1] ei = valence(self.structure.symbols[i1]) / covalent_radius(self.structure.symbols[i1]) ej = valence(self.structure.symbols[i2]) / covalent_radius(self.structure.symbols[i2]) for dij in bonds[pair]: sij = math.sqrt(ei * ej) / (coordination[i1] * coordination[i2]) / dij xprod *= sij num_i_j_bonds = len(bonds[pair]) pcm_log.debug('Number of bonds for pair %s = %d' % (str(pair), num_i_j_bonds)) tot += num_i_j_bonds vol = self.structure.volume pcm_log.debug("Structure volume: %7.3f" % vol) pcm_log.debug("Total number of bonds: %d" % tot) pcm_log.debug("Bonds: %s" % str(bonds)) hardness_value = (c_hard / vol) * tot * (xprod ** (1. / tot)) * math.exp(-sigma * f) return round(hardness_value, 3), cutoff_radius, coordination
def hardness_XX(self, initial_cutoff_radius=0.8, use_laplacian=True): bonds, coordination, cutoff_radius = self.bonds_coordination(initial_cutoff_radius=initial_cutoff_radius, use_laplacian=use_laplacian, verbose=True) sigma = 3.0 c_hard = 1300.0 xprod = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 atomicnumbers = atomic_number(self.structure.species) pcm_log.debug('Atomic numbers in the structure : %s' % str(atomicnumbers)) for i in atomicnumbers: f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) if f_d == 0: pcm_log.debug('Returning zero as hardness. f_d= %10.3f' % f_d) return 0.0 f = 1.0 - (self.structure.nspecies * f_n ** (1.0 / self.structure.nspecies) / f_d) ** 2 diff_bonds = [x for x in bonds if len(bonds[x]) > 0] for pair in diff_bonds: i1 = pair[0] i2 = pair[1] ei = valence(self.structure.symbols[i1]) / covalent_radius(self.structure.symbols[i1]) ej = valence(self.structure.symbols[i2]) / covalent_radius(self.structure.symbols[i2]) for dij in bonds[pair]: sij = math.sqrt(ei * ej) / (coordination[i1] * coordination[i2]) / dij xprod *= sij num_i_j_bonds = len(bonds[pair]) pcm_log.debug('Number of bonds for pair %s = %d' % (str(pair), num_i_j_bonds)) tot += num_i_j_bonds vol = self.structure.volume pcm_log.debug("Structure volume: %7.3f" % vol) pcm_log.debug("Total number of bonds: %d" % tot) pcm_log.debug("Bonds: %s" % str(bonds)) hardness_value = (c_hard / vol) * tot * (xprod ** (1. / tot)) * math.exp(-sigma * f) return round(hardness_value, 3), cutoff_radius, coordination
def hardness_old(self, noupdate=False, verbose=False, tolerance=0.05): """ Calculates the hardness of a structure based in the model of XX We use the covalent radii from pychemia.utils.periodic. If noupdate=False the Laplacian matrix method is not used and rcut is 2*max(cov_radii) :param noupdate: (bool) If True, the Laplacian method is used :param verbose: (bool) To print some debug info :param tolerance: (float) :rtype : (float) """ superc = self.structure.copy() superc.supercell(2, 2, 2) structure_analisys = StructureAnalysis(superc) natom = superc.natom volume = superc.volume max_covalent_radius = max(covalent_radius(superc.symbols)) if verbose: print('Number of atoms', natom) print('Volume ', volume) print('Covalent rad max', max_covalent_radius) rcut, coord, dis_dic = structure_analisys.get_bonds(2.0 * max_covalent_radius, noupdate, verbose, tolerance) sigma = 3.0 c_hard = 1300.0 x = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 dic_atms = {} for i in superc.symbols: dic_atms[i] = atomic_number(i) for i in dic_atms.keys(): f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) f = 1.0 - (len(dic_atms) * f_n ** (1.0 / len(dic_atms)) / f_d) ** 2 if verbose: print('BONDS') print(dis_dic) print('COORDINATION') print(coord) for i in dis_dic.keys(): i1 = dis_dic[i][2][0] i2 = dis_dic[i][2][1] ei = valence(superc.symbols[i1]) / covalent_radius(superc.symbols[i1]) ej = valence(superc.symbols[i2]) / covalent_radius(superc.symbols[i2]) sij = math.sqrt(ei * ej) / (coord[i1] * coord[i2]) / dis_dic[i][0] tot += dis_dic[i][1] x *= sij * dis_dic[i][1] if verbose: print("V:", volume) print("f:", f) print("x:", x) hardness_value = c_hard / volume * (len(dis_dic) * x ** (1. / (len(dis_dic)))) * math.exp(-sigma * f) if verbose: print(hardness_value) return round(hardness_value, 3)
def hardness(self, verbose=False, initial_cutoff_radius=0.8, ensure_conectivity=False, use_laplacian=True, use_jump=True): """ Calculates the hardness of a structure based in the model of XX We use the covalent radii from pychemia.utils.periodic. If noupdate=False the Laplacian matrix method is not used and rcut is 2*max(cov_radii) :param use_jump: :param ensure_conectivity: :param verbose: (bool) To print some debug info :param initial_cutoff_radius: (float) :param use_laplacian: (bool) If True, the Laplacian method is used :rtype : (float) """ if self._supercell == (1, 1, 1) and verbose: print('''Only internal connectivity can be ensure, for complete connectivity in the crystal you must use a supercell at of (2,2,2)''') bonds, coordination, all_distances, tolerances, cutoff_radius = \ self.get_bonds_coordination(initial_cutoff_radius=initial_cutoff_radius, ensure_conectivity=ensure_conectivity, use_laplacian=use_laplacian, verbose=verbose, use_jump=use_jump) if verbose: print('Structure coordination : ', coordination) sigma = 3.0 c_hard = 1300.0 x = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 atomicnumbers = atomic_number(self.structure.species) if verbose: print('Atomic numbers in the structure :', atomicnumbers) for i in atomicnumbers: f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) # if verbose: # print 'fd', f_d # print 'fn', f_n # print atomicnumbers if f_d == 0: return 0.0 f = 1.0 - (len(atomicnumbers) * f_n ** (1.0 / len(atomicnumbers)) / f_d) ** 2 # Selection of different bonds diff_bonds = np.unique(np.array(reduce(lambda xx, y: xx + y, bonds))) if verbose: print('Number of different bonds : ', len(diff_bonds)) for i in diff_bonds: i1 = all_distances[i]['pair'][0] i2 = all_distances[i]['pair'][1] ei = valence(self.structure.symbols[i1]) / covalent_radius(self.structure.symbols[i1]) ej = valence(self.structure.symbols[i2]) / covalent_radius(self.structure.symbols[i2]) # print 'bond ->', sqrt(ei * ej), (coordination[i1] * coordination[i2]), all_distances[i]['distance'] sij = math.sqrt(ei * ej) / (coordination[i1] * coordination[i2]) / all_distances[i]['distance'] num_i_j_bonds = len([j for j in diff_bonds if i1 in all_distances[j]['pair'] and i2 in all_distances[j]['pair']]) # print 'sij', sij # print 'num_i_j_bonds', num_i_j_bonds tot += num_i_j_bonds x *= sij # print 'x', x vol = self.structure.volume if verbose: print("Structure volume:", vol) # print("f:", f) # print("x:", x) # print 'len_bonds', len(diff_bonds hardness_value = c_hard / vol * (len(diff_bonds) * x ** (1. / (len(diff_bonds)))) * math.exp(-sigma * f) return round(hardness_value, 3), cutoff_radius, coordination
def valence_electrons(self): ret = 0 for key, value in self.composition.items(): ret += value * valence(key) return ret
def hardness_old(self, noupdate=False, verbose=False, tolerance=0.05): """ Calculates the hardness of a structure based in the model of XX We use the covalent radii from pychemia.utils.periodic. If noupdate=False the Laplacian matrix method is not used and rcut is 2*max(cov_radii) :param noupdate: (bool) If True, the Laplacian method is used :param verbose: (bool) To print some debug info :param tolerance: (float) :rtype : (float) """ superc = self.structure.copy() superc.supercell(2, 2, 2) structure_analisys = StructureAnalysis(superc) natom = superc.natom volume = superc.volume max_covalent_radius = max(covalent_radius(superc.symbols)) if verbose: print('Number of atoms', natom) print('Volume ', volume) print('Covalent rad max', max_covalent_radius) rcut, coord, dis_dic = structure_analisys.get_bonds( 2.0 * max_covalent_radius, noupdate, verbose, tolerance) sigma = 3.0 c_hard = 1300.0 x = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 dic_atms = {} for i in superc.symbols: dic_atms[i] = atomic_number(i) for i in dic_atms.keys(): f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) f = 1.0 - (len(dic_atms) * f_n**(1.0 / len(dic_atms)) / f_d)**2 if verbose: print('BONDS') print(dis_dic) print('COORDINATION') print(coord) for i in dis_dic.keys(): i1 = dis_dic[i][2][0] i2 = dis_dic[i][2][1] ei = valence(superc.symbols[i1]) / covalent_radius( superc.symbols[i1]) ej = valence(superc.symbols[i2]) / covalent_radius( superc.symbols[i2]) sij = math.sqrt(ei * ej) / (coord[i1] * coord[i2]) / dis_dic[i][0] tot += dis_dic[i][1] x *= sij * dis_dic[i][1] if verbose: print("V:", volume) print("f:", f) print("x:", x) hardness_value = c_hard / volume * ( len(dis_dic) * x**(1. / (len(dis_dic)))) * math.exp(-sigma * f) if verbose: print(hardness_value) return round(hardness_value, 3)
def hardness(self, verbose=True, initial_cutoff_radius=0.8, ensure_conectivity=False, use_laplacian=True, use_jump=True, tol=1E-15): """ Calculates the hardness of a structure based in the model of XX We use the covalent radii from pychemia.utils.periodic. If noupdate=False the Laplacian matrix method is not used and rcut is 2*max(cov_radii) :param use_jump: :param ensure_conectivity: :param verbose: (bool) To print some debug info :param initial_cutoff_radius: (float) :param use_laplacian: (bool) If True, the Laplacian method is used :param tol: (float) Tolerance for considering two atoms bonded :rtype : (float) """ if self._supercell == (1, 1, 1) and verbose: print( '''Only internal connectivity can be ensure, for complete connectivity in the crystal you must use a supercell at of (2,2,2)''') bonds, coordination, all_distances, tolerances, cutoff_radius = \ self.get_bonds_coordination(initial_cutoff_radius=initial_cutoff_radius, ensure_conectivity=ensure_conectivity, use_laplacian=use_laplacian, verbose=verbose, use_jump=use_jump, tol=tol) if verbose: print('Structure coordination : ', coordination) sigma = 3.0 c_hard = 1300.0 x = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 atomicnumbers = atomic_number(self.structure.species) if verbose: print('Atomic numbers in the structure :', atomicnumbers) for i in atomicnumbers: f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) # if verbose: # print 'fd', f_d # print 'fn', f_n # print atomicnumbers if f_d == 0: return 0.0 f = 1.0 - (len(atomicnumbers) * f_n**(1.0 / len(atomicnumbers)) / f_d)**2 # Selection of different bonds diff_bonds = np.unique( np.array(functools.reduce(lambda xx, y: xx + y, bonds))) if verbose: print('Number of different bonds : ', len(diff_bonds)) for i in diff_bonds: i1 = all_distances[i]['pair'][0] i2 = all_distances[i]['pair'][1] ei = valence(self.structure.symbols[i1]) / covalent_radius( self.structure.symbols[i1]) ej = valence(self.structure.symbols[i2]) / covalent_radius( self.structure.symbols[i2]) # print 'bond ->', sqrt(ei * ej), (coordination[i1] * coordination[i2]), all_distances[i]['distance'] sij = math.sqrt(ei * ej) / (coordination[i1] * coordination[i2] ) / all_distances[i]['distance'] num_i_j_bonds = len([ j for j in diff_bonds if i1 in all_distances[j]['pair'] and i2 in all_distances[j]['pair'] ]) # print 'sij', sij # print 'num_i_j_bonds', num_i_j_bonds tot += num_i_j_bonds x *= sij # print 'x', x vol = self.structure.volume if verbose: print("Structure volume:", vol) # print("f:", f) # print("x:", x) # print 'len_bonds', len(diff_bonds hardness_value = c_hard / vol * ( len(diff_bonds) * x**(1. / (len(diff_bonds)))) * math.exp(-sigma * f) return round(hardness_value, 3), cutoff_radius, coordination
def hardness_OLD(self, noupdate=False, verbose=False, tolerance=0.05): """ Calculates the hardness of a structure based in the model of XX We use the covalent radii from pychemia.utils.periodic. If noupdate=False the Laplacian matrix method is not used and rcut is 2*max(cov_radii) :param noupdate: (bool) If True, the Laplacian method is used :param verbose: (bool) To print some debug info :param tolerance: (float) :rtype : (float) """ #from ase.data import covalent_radii #atms=atms.repeat([2,2,2]) spc = self.copy() spc.supercell(2, 2, 2) natom = spc.natom volume = spc.volume #max_covalent_radius = max([covalent_radii[i.number] for i in atms]) max_covalent_radius = max(covalent_radius(spc.symbols)) if verbose: print('Number of atoms', natom) print('Volume ', volume) print('Covalent rad max', max_covalent_radius) #rcut, coord, dis_dic = get_bonds(atms,2.0*max_covalent_radius, noupdate,verbose,tolerance) rcut, coord, dis_dic = spc.get_bonds(2.0 * max_covalent_radius, noupdate, verbose, tolerance) sigma = 3.0 c_hard = 1300.0 x = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 dic_atms = {} #for i in atms: # dic_atms[i.symbol] = i.number for i in spc.symbols: dic_atms[i] = atomic_number(i) #for i in dic_atms.keys(): # f_d += Z[i] / covalent_radii[dic_atms[i]] # f_n *= Z[i] / covalent_radii[dic_atms[i]] #f = 1.0 - (len(dic_atms)*f_n**(1.0/len(dic_atms)) / f_d)**2 for i in dic_atms.keys(): f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) f = 1.0 - (len(dic_atms) * f_n ** (1.0 / len(dic_atms)) / f_d) ** 2 if verbose: print 'BONDS' print dis_dic print 'COORDINATION' print coord for i in dis_dic.keys(): i1 = dis_dic[i][2][0] i2 = dis_dic[i][2][1] #ei = Z[atms[i1].symbol] / covalent_radii[atms[i1].number] #ej = Z[atms[i2].symbol] / covalent_radii[atms[i2].number] ei = valence(spc.symbols[i1]) / covalent_radius(spc.symbols[i1]) ej = valence(spc.symbols[i2]) / covalent_radius(spc.symbols[i2]) #print 'bond ->', sqrt(ei * ej), (coord[i1] * coord[i2]), dis_dic[i][0] # print atms[i1].symbol, ei, atms[i2].symbol, ej sij = sqrt(ei * ej) / (coord[i1] * coord[i2]) / dis_dic[i][0] #print 'sij', sij #print 'num_i_j_bonds', dis_dic[i][1] tot += dis_dic[i][1] x *= sij * dis_dic[i][1] #print 'x', x if verbose: print("V:", volume) print("f:", f) print("x:", x) #print 'len_bonds', len(dis_dic) #print 'hardness_value =', c_hard, volume, (len(dis_dic)), ( x ** (1. / (len(dis_dic)))), exp(-sigma * f) hardness_value = c_hard / volume * (len(dis_dic) * x ** (1. / (len(dis_dic)))) * exp(-sigma * f) if verbose: print hardness_value return round(hardness_value, 3)
def hardness(self, noupdate=False, verbose=False, tolerance=1): """ Calculates the hardness of a structure based in the model of XX We use the covalent radii from pychemia.utils.periodic. If noupdate=False the Laplacian matrix method is not used and rcut is 2*max(cov_radii) :param noupdate: (bool) If True, the Laplacian method is used :param verbose: (bool) To print some debug info :param tolerance: (float) :rtype : (float) """ bonds, coordination, all_distances, tolerances = self.get_bonds_coordination(tolerance=tolerance, ensure_conectivity=True) if verbose: print 'BONDS' print bonds print 'COORDINATION' print coordination sigma = 3.0 c_hard = 1300.0 x = 1. tot = 0.0 f_d = 0.0 f_n = 1.0 atomicnumbers = atomic_number(self.get_composition().species) if verbose: print atomicnumbers for i in atomicnumbers: f_d += valence(i) / covalent_radius(i) f_n *= valence(i) / covalent_radius(i) f = 1.0 - (len(atomicnumbers) * f_n ** (1.0 / len(atomicnumbers)) / f_d) ** 2 # Selection of different bonds diff_bonds = _np.unique(_np.array(reduce(lambda x, y: x+y, bonds))) for i in diff_bonds: i1 = all_distances[i]['pair'][0] i2 = all_distances[i]['pair'][1] ei = valence(self.symbols[i1]) / covalent_radius(self.symbols[i1]) ej = valence(self.symbols[i2]) / covalent_radius(self.symbols[i2]) #print 'bond ->', sqrt(ei * ej), (coordination[i1] * coordination[i2]), all_distances[i]['distance'] sij = sqrt(ei * ej) / (coordination[i1] * coordination[i2]) / all_distances[i]['distance'] num_i_j_bonds = len([j for j in diff_bonds if i1 in all_distances[j]['pair'] and i2 in all_distances[j]['pair']]) #print 'sij', sij #print 'num_i_j_bonds', num_i_j_bonds tot += num_i_j_bonds x *= sij #print 'x', x if verbose: print("V:", self.volume) print("f:", f) print("x:", x) #print 'len_bonds', len(diff_bonds) #print 'hardness_value =', c_hard, self.volume, (len(diff_bonds)), ( x ** (1. / (len(diff_bonds)))), exp(-sigma * f) hardness_value = c_hard / self.volume * (len(diff_bonds) * x ** (1. / (len(diff_bonds)))) * exp(-sigma * f) if verbose: print hardness_value return round(hardness_value, 3)