def similarity(self): mdff = self.param["filtering"]["final"]["max_diff_report"] if len(self.finals) != 0: c = self.finals[0] eles, ne = elem_num(c.elems) for i, c in enumerate(self.finals): mj = -1 md = None for j, d in enumerate(self.finals[:i]): if isinstance(c, ClusterAtSurface): v, _ = surface_compare(d, c, ne, eles, mdff) else: v, _ = at_comp(d.atoms, c.atoms, ne, eles, mdff) if mj == -1 or md > v: md = v mj = j if mj != -1 and md != mdff: c.similar = [mj, md] else: c.similar = None
def surface_match(a, b, dmax, dmin=1E-2, nd=20): from cluster.base import elem_num assert isinstance(a, Surface) assert isinstance(b, Surface) adir = to_direct(a.atoms, a.cell) bdir = to_direct(b.atoms, a.cell) if len(a.elems) == len(b.elems): # efficient way assert (a.elems == b.elems).all() cellmat = to_cellmat(a.cell) eles, ne = elem_num(a.elems) ww = weights(a.atoms, b.atoms, ne, eles, cellmat) v, vx = kmc_comp(ww, ne, eles) vg = np.zeros(vx.shape, dtype=int) for i, ii in enumerate(vx): vg[ii - 1] = i + 1 return v, vg else: # old way cl = np.linalg.norm(to_cellmat(a.cell), axis=1) dstep = (dmax / dmin)**(1.0 / nd) d = dmin mt = [-1] * a.n mx = range(b.n) cell = [1.0, 1.0, None] for _ in range(nd): for i in range(a.n): if mt[i] == -1: for ij, j in enumerate(mx): if check_imagex(adir[i], a.elems[i], bdir[j], b.elems[j], cell, d, cl): mt[i] = j del mx[ij] break if len(mx) == 0: break d *= dstep # diff, march indices return d, np.array(mt) + 1
def build_surf_ref(self): cax = self.clus surf = cax[0].surf # align atoms eles, ne = elem_num(cax[0].elems) cellmat = to_cellmat(surf.cell) for i in [0, -1]: _, b = surface_compare(cax[i], self.ref_structs[i], ne, eles, 0.5) self.adjust_surf(cax[i], self.ref_structs[i], b) mdiff, _ = km_comp(cax[0].atoms, cax[-1].atoms, ne, eles, cellmat) lscax = [cax] nmax = self.nimages + 1 assert (len(self.ref_structs) == nmax + 1) uimgs = [] mishort = 0 for cax in lscax: imgs = [] for i in range(0, nmax + 1): if i == 0: cc = cax[0] elif i == nmax: cc = cax[1] else: cc = self.ref_structs[i] cc = copy.deepcopy(cc) cc.surf.forces = None if cc.mag is None: cc.mag = 0.0 cc.label = "CONN-%d-%d:%%d.%d:%.2f" % (self.endp[0], self.endp[1], i, cc.mag) imgs.append(cc) uimgs.append(imgs) return uimgs, [ self.endp[0], self.endp[1], len(uimgs), 1, mishort, 0, 0, mdiff ]
csdir = to_direct(surf.atoms, surf.cell) if deep: csdir[:, 0:2] -= ctrref csdir = apply_trans(csdir, cxdmin[2], ucell) csdir[:, 0:2] += ctrref csdir += cxdmin[3] for ii, _ in enumerate(csdir): for k in range(2): csdir[ii, k] += num_adjust(TOLS - csdir[ii, k], 1.0) surf.atoms = to_cartesian(csdir, surf.cell) if __name__ == "__main__": from surface.base import read_surface surf = read_surface('../PGOPT/surfaces/mgo.xyz') surf.space_group = "-F 4 2 3" surf.unit_cell = np.array([4.257, 4.257, 4.257]) from cluster.base import read_clusters, elem_num clus = read_clusters( "/Users/fszix/Projects/test/master/1.1/par_local.xyz.0") cla = [] nx = 72 for c in clus: aa = ClusterAtSurface(c.n - nx, surf) surfmin = c.atoms[:nx].min(axis=0).reshape(1, 3) aa.atoms = c.atoms[nx:] - surfmin aa.elems = c.elems[nx:] cla.append(aa) eles, ne = elem_num(aa.elems) print surface_compare(cla[8], cla[9], ne, eles, 1.0)
def filter(self, prefix='FIL', iprint=True): if iprint: print('filtering ...') self.corrs = [] n = self.cn dmax_rep = self.max_diff_report dmax = self.max_diff eles = None self.finals = [] holder = 76 if iprint: print('Number of structs: %d' % n) if iprint: print(('%%%ds' % (holder)) % ('-' * holder, )) self.corrs.append('#%6s %3s %-8s %15s %-8s %15s %6s %5s ' % ('new #', '%', 'orig #', 'this E', 'sim. #', 'sim. E', 'mindm', 'time')) if iprint: print(self.corrs[-1]) self.min_ener = None if iprint: print(('%%%ds' % (holder)) % ('-' * holder, )) init_time = start_time = time.time() for ci, c in enumerate(self.clus): if c.label == '': c.label = 'PRE:%d' % (ci, ) if eles is None: eles, ne = elem_num(c.elems) # if n >= 10 and ci % (n / 10) == 0: print '{:.0f} %'.format(ci / (n / 100.0)) min_dmax, mini = dmax_rep, None ok = True for di, d in enumerate(self.finals): if min_dmax == 0.0: v = 1.0 elif isinstance(c, ClusterAtSurface): v, _ = surface_compare(d, c, ne, eles, min_dmax) else: v, _ = at_comp(d.atoms, c.atoms, ne, eles, min_dmax) if v < min_dmax: min_dmax, mini = v, d if v < dmax: ok = False if self.post_reject is not None: self.post_reject() break finish_time = time.time() self.corrs.append( ('{:7} {:2d}% {:8} {:15.6f} {:24} {mindm:6.4f} ' + '{time:5.2f} {star}').format( len(self.finals) if ok else '', int((len(self.finals) if self.flimit else ci) / ((n + 1 if self.flimit else n) / 100.0)), c.label, c.energy, '{:8} {:15.6f}'.format(mini.label, mini.energy) if mini is not None else '{:8} {:>15}'.format('-', '-'), mindm=min_dmax, time=finish_time - start_time, star='*' if ok else ' ')) start_time = finish_time if iprint: print(self.corrs[-1]) if ok: self.finals.append(c) c.multi = 1 c.new_label = prefix + ':' + str(len(self.finals) - 1) else: mini.multi += 1 if hasattr(mini, "props") and "nrep" in mini.props: mini.props["nrep"] += c.props["nrep"] if len(self.finals) == n: break if ci >= 100000: raise RuntimeError("Cannot generate enough " + "distinct structures after %d trials!" % ci) if iprint: print(('%%%ds' % (holder)) % ('-' * holder, )) total_time = finish_time - init_time if iprint: print(('%%%ds' % (holder)) % ('total time used: %d:%02d:%02d' % (total_time / 3600, (total_time / 60) % 60, total_time % 60), )) if iprint: print(('%%%ds' % (holder)) % ('-' * holder, ))
def run(self): # for surface case, need to solve the km_comp with cell periodic problem # interp needs to deal with crossing bounday problem conn = [] clus_match = [] # use ref paths to build if len(self.ref_nebmin) != 0: print("## number of ref-isomers = %d" % len(self.ref_nebmin)) eles, ne = elem_num(self.ref_nebmin.values()[0].elems) for i in range(len(self.clus)): kmm = -1 for k, v in self.ref_nebmin.items(): aa = surface_compare(self.clus[i], v, ne, eles, 5)[0] if kmm == -1 or aa < kmm: kmm = aa ki = (k, v) if kmm <= 0.15: clus_match.append([ki, kmm]) print("matched [ %4d -> %4s ] %.4f *" % (i, ki[0], kmm)) else: clus_match.append([("", None), -1]) print("failed [ %4d -> %4s ] %.4f" % (i, ki[0], kmm)) else: for i in range(len(self.clus)): clus_match.append([("", None), -1]) for i in range(len(self.clus)): eles, ne = elem_num(self.clus[i].elems) for j in range(i): if clus_match[i][1] != -1 and clus_match[j][ 1] != -1 and clus_match[i][0][0] != clus_match[j][0][0]: xi, xj = clus_match[i][0][0], clus_match[j][0][0] oft = "%s.%s" % (xi, xj) rft = "%s.%s" % (xj, xi) if oft in self.ref_path_dict or rft in self.ref_path_dict: if oft in self.ref_path_dict: rstr = self.ref_path_dict[oft].structs elif rft in self.ref_path_dict: rstr = self.ref_path_dict[rft].structs[::-1] print("[%4d -> %4d ] projected to [%4s -> %4s ] *" % (i, j, xi, xj)) conn.append( Connection([self.clus[i], self.clus[j]], self.iprp, (i, j), len(conn), ref_structs=rstr)) else: # no ref paths if self.surf is None: d, _ = at_comp(self.clus[i].atoms, self.clus[j].atoms, ne, eles, self.max_diff + 0.1) else: d, _ = surface_compare(self.clus[i], self.clus[j], ne, eles, self.max_diff + 0.1) if d < self.max_diff: print("[%4d -> %4d ] diff = %5.2f *" % (i, j, d)) conn.append( Connection([self.clus[i], self.clus[j]], self.iprp, (i, j), len(conn))) else: print("[%4d -> %4d ] diff = %5.2f" % (i, j, d)) if len(self.ref_nebmin) != 0: for cc in conn: cc.max_trials_surf = 4 print("## number of isomers = %d" % len(self.clus)) print("## number of pairs = %d" % len(conn)) series = [] title = "[from -> to ] accepted ntrial nshort nhighd nsymm min-diff" holder = len(title) print(('%%%ds' % (holder)) % ('-' * holder, )) print(title) print(('%%%ds' % (holder)) % ('-' * holder, )) for c in conn: ser, prt = c.build() series.extend(ser) print("[%4d -> %4d ] %8d %6d %6d %6d %6d %8.2f" % tuple(prt)) print(('%%%ds' % (holder)) % ('-' * holder, )) print("## number of final connections = %d" % len(series)) conn_fn = new_file_name(self.p.conn_images_name) print("write images: " + conn_fn) writter = RecordWritter() apd = False for it, s in enumerate(series): for c in s: c.label = c.label % it writter.write_clusters(conn_fn, s, apd) apd = True
def interp_surf(self, ibest=None): if ibest is None: ibest = self.max_trials_surf cax = self.clus surf = cax[0].surf # align atoms eles, ne = elem_num(cax[0].elems) cellmat = to_cellmat(surf.cell) lscax = [] mdiff = None mdmax = None misinglelong = 0 if len(cax) == 2: bs = surface_compare(cax[0], cax[1], ne, eles, self.max_diff + 0.1, best=ibest) for md, b in bs: if len(lscax) != 0 and (md > self.max_diff or md > mdiff * 1.5): break cxx = copy.deepcopy(cax) self.adjust_surf(cxx[0], cxx[1], b) mdx = np.linalg.norm(cxx[0].atoms - cxx[1].atoms, axis=1).max() if len(lscax) != 0 and (mdx > self.max_diff * 4): misinglelong += 1 break lscax.append(cxx) if mdiff is None or md < mdiff: mdiff = md if mdmax is None or mdx < mdmax: mdmax = mdx else: for cai in range(len(cax) - 1, 0, -1): _, b = surface_compare(cax[cai - 1], cax[cai], ne, eles, self.max_diff + 0.1) self.adjust_surf(cax[cai - 1], cax[cai], b) mdiff, _ = km_comp(cax[0].atoms, cax[-1].atoms, ne, eles, cellmat) lscax.append(cax) # construct final images nmax = self.nimages + 1 dc = 1.0 * nmax / (len(cax) - 1) for cax in lscax: for cai in range(0, len(cax)): cax[cai].idx = cai * dc uimgs = [] mishort = 0 for cax in lscax: imgs = [] ishort = False for i in range(0, nmax + 1): cc = ClusterAtSurface(cax[0].n, copy.deepcopy(cax[0].surf)) cc.elems = cax[0].elems for cai in range(1, len(cax)): if cax[cai].idx >= i - 1E-8: break cx, cy = cax[cai - 1], cax[cai] rx = (cax[cai].idx - i) / dc cc.atoms = cx.atoms * rx + cy.atoms * (1 - rx) cc.surf.atoms = cx.surf.atoms * rx + cy.surf.atoms * (1 - rx) cc.mag = None if np.abs(rx - 1) < 1E-8: cc.mag, cc.energy = cx.mag, cx.energy cc.surf.forces = cx.surf.forces elif np.abs(rx) < 1E-8: cc.mag, cc.energy = cy.mag, cy.energy cc.surf.forces = cy.surf.forces else: cc.surf.forces = None if cc.mag is None: cc.mag = 0.0 cc.label = "CONN-%d-%d:%%d.%d:%.2f" % (self.endp[0], self.endp[1], i, cc.mag) if i != 0 and i != nmax: pcc = PreOptimization(cc, self.adjusted_short_length_factor) pcc.maxiter = 12 lpp = pcc.opt() if not lpp: ishort = True break cc = pcc.traj[-1] imgs.append(cc) if not ishort: uimgs.append(imgs) else: mishort += 1 return uimgs, [ self.endp[0], self.endp[1], len(uimgs), ibest, mishort, misinglelong, 0, mdiff ]
def build_gas_phase(self): if len(self.RotFunc) == 0: self.init_func() ca = self.clus[0] cb = self.clus[1] eles, ne = elem_num(ca.elems) eles2, ne2 = elem_num(list(ca.elems) * 2) nmax = self.nimages + 1 # initial measurement atomsa, atomsb = np.array(ca.atoms), np.array(cb.atoms) dd, _ = at_comp(atomsa, atomsb, ne, eles, self.max_diff + 0.1) dcl = np.array(self.max_trials) uph = self.trail_tolerance # build trial set dcf = None while dcl == self.max_trials and uph > 0.05: dcx = at_comp_list(atomsa, atomsb, ne, eles, dd + uph, dcl) dcx = dcx[:dcl - 1] if dcf is None or dcl == self.max_trials: dcf = np.array(dcx) uph /= np.sqrt(2) # solve rotation non-linear problem ntrial = len(dcf) nshort = 0 nhigh = 0 nsymm = 0 mdiff = self.max_diff finals = [] task = LBFGS(6) task.log_file = 0 task.max_iter = 500 for idx in dcf: caa, cab = np.array(atomsa), np.array(atomsb) caa = caa[idx - 1] xi = [0.0] * 6 task.p.eval = lambda x: self.RotFunc[0](caa, cab, x) task.p.evald = lambda x: self.RotFunc[1](caa, cab, x) task.start(xi) task.opt() caf = self.RotFunc[2](caa, task.x) hdiff = self.RotFunc[0](caa, cab, task.x) if hdiff > self.max_diff: nhigh += 1 continue if not check(ca.elems, caf, cab, nmax, self.acceptable_short_length_factor): nshort += 1 continue finals.append([caf, cab, hdiff]) if hdiff < mdiff: mdiff = hdiff finals.sort(key=lambda x: x[2]) if len(finals) > 1: ufinals = [finals[0]] ufinalsrf = [np.concatenate(finals[0][:2])] for ff in finals[1:]: crg = np.concatenate(ff[:2]) okay = True for crf in ufinalsrf: crd, _ = at_comp(crf, crg, ne2, eles2, self.path_min_diff + 0.02) if crd < self.path_min_diff: okay = False break if not okay: nsymm += 1 else: ufinals.append(ff) ufinalsrf.append(np.concatenate(ff[:2])) finals = ufinals # construct final images finalimgs = [] for caa, cab, _ in finals: imgs = [] for i in range(0, nmax + 1): cc = Cluster(ca.n, ca.elems) cc.atoms = caa + (cab - caa) * i / nmax cc.mag = None if i == 0: cc.mag, cc.energy = ca.mag, ca.energy elif i == nmax: cc.mag, cc.energy = cb.mag, cb.energy if cc.mag is None: cc.mag = 0.0 cc.label = "CONN-%d-%d:%%d.%d:%.2f" % (self.endp[0], self.endp[1], i, cc.mag) if i != 0 and i != nmax: pcc = PreOptimization(cc, self.adjusted_short_length_factor) pcc.opt() cc = pcc.traj[-1] imgs.append(cc) finalimgs.append(imgs) return finalimgs, [ self.endp[0], self.endp[1], len(finalimgs), ntrial, nshort, nhigh, nsymm, mdiff ]