def numv1_calcA(all_points, all_svals, grads, hess_idxsBW, hess_idxsFW): ''' svals: the list of s values grads: the list of gradients hess_idxs: a list of indices indicating where v^(1) has to be calculated this is given in two list, one for the bw and another for the fw part of the MEP why? although each coordinate of the gradient is continuous along the mep, this behavior is not found for the v^(0) vector. ''' dv1 = {} for indices in [hess_idxsBW, hess_idxsFW]: for idx in indices: # label for this point label = all_points[idx] # Choose the points if idx == indices[0]: idx_a, idx_b, idx_c = idx, idx + 1, idx + 2 elif idx == indices[-1]: idx_a, idx_b, idx_c = idx - 2, idx - 1, idx else: idx_a, idx_b, idx_c = idx - 1, idx, idx + 1 # s for the three points of mep si = all_svals[idx] sa = all_svals[idx_a] sb = all_svals[idx_b] sc = all_svals[idx_c] # Get v^(0) at each point v0_a = -fncs.normalize_vec(grads[idx_a]) v0_b = -fncs.normalize_vec(grads[idx_b]) v0_c = -fncs.normalize_vec(grads[idx_c]) # Parabolic function for each coordinate ncoords = len(v0_a) v1 = [] for coord in range(ncoords): x1, x2, x3 = sa, sb, sc y1, y2, y3 = v0_a[coord], v0_b[coord], v0_c[coord] # Get a in a*x^2 + b*x + c num_a = (y1 - y2) * (x1 - x3) - (y1 - y3) * (x1 - x2) den_a = (x1**2 - x2**2) * (x1 - x3) - (x1**2 - x3**2) * (x1 - x2) a = num_a / den_a # Get b in b*x^2 + b*x + c b = ((y1 - y2) - a * (x1**2 - x2**2)) / (x1 - x2) # Get c in b*x^2 + b*x + c c = y1 - a * x1**2 - b * x1 # Get derivative at x=s (y' = 2*a*x+b) v1_coord = 2 * a * si + b v1.append(v1_coord) dv1[label] = np.array(v1) return dv1
def numv1_calcB(points, svals, grads, hess_idxs): ''' average of linear interpolation it is equivalent to numv1_calcA, but faster _cu for current point _m1 for previous point to current _m2 for previous point to _m1 _p1 for next point with regard to current _p2 for next point with regard to _p1 et cetera ''' dv1 = {} saddle_idx = None for idx, label in enumerate(points): if idx not in hess_idxs: continue # Current point s_cu = svals[idx] g_cu = np.array(grads[idx]) # Skip if saddle point if s_cu == 0.0: continue # v0 vector v0_cu = -fncs.normalize_vec(g_cu) # Previous point if idx != 0: s_m1 = svals[idx - 1] g_m1 = np.array(grads[idx - 1]) v0_m1 = -fncs.normalize_vec(g_m1) # Get left derivative v1_left = (v0_cu - v0_m1) / (s_cu - s_m1) else: v1_left = None # Next point if idx != len(points) - 1: s_p1 = svals[idx + 1] g_p1 = np.array(grads[idx + 1]) v0_p1 = -fncs.normalize_vec(g_p1) # Get right derivative v1_right = (v0_p1 - v0_cu) / (s_p1 - s_cu) else: v1_right = None # average if v1_left is None: v1 = v1_right elif v1_right is None: v1 = v1_left else: v1 = (v1_right + v1_left) / 2.0 # save dv1[label] = v1 return dv1
def mep_first(xcc, gcc, Fcc, symbols, masses, var_first, spc_fnc, spc_args, drst={}, parallel=False): #global PARALLEL, delayed, multiprocessing, Parallel #PARALLEL, delayed, multiprocessing, Parallel = fncs.set_parallel(parallel) ds, mu, cubic, idir = var_first # convert cubic variable to d3 (in bohr) d3 = cubic2float(cubic) # mass-scaled xcc = fncs.shift2com(xcc, masses) xms = fncs.cc2ms_x(xcc, masses, mu) gms = fncs.cc2ms_g(gcc, masses, mu) Fms = fncs.cc2ms_F(Fcc, masses, mu) # Data in backup? if TSLABEL in drst.keys(): si, E, xms2, gms, Fms, v0, v1, t = drst[TSLABEL] gms = np.array(gms) Fms = np.array(Fms) v0 = np.array(v0) if v1 is not None: v1 = np.array(v1) same = fncs.same_geom(xms, xms2) if not same: raise Exc.RstDiffTS(Exception) else: # Calculation of v0 freqs, evals, evecs = fncs.calc_ccfreqs(Fcc, masses, xcc) ifreq, Lms = get_imagfreq(freqs, evecs) v0 = fncs.normalize_vec(Lms) v0 = correctdir_v0(xms, v0, idir, masses, mu) # Calculation of v1 if d3 is None: v1 = None else: v1 = calculate_v1(xms, v0, Fms, symbols, masses, mu, d3, spc_fnc, spc_args, parallel) # Final structures if d3 is None: xms_bw = sd_taylor(xms, ds, v0=-v0) xms_fw = sd_taylor(xms, ds, v0=+v0) else: xms_bw = sd_taylor(xms, ds, v0=-v0, v1=-v1) xms_fw = sd_taylor(xms, ds, v0=+v0, v1=+v1) return (xms, gms, Fms), (v0, v1), (xms_bw, xms_fw)
def puckering_normal(list_Rj): ''' JACS 1975, 97:6, 1354-1358; eq (10) ''' N = len(list_Rj) Rp = np.array([0.0,0.0,0.0]) Rpp = np.array([0.0,0.0,0.0]) for j in range(N): Rj = list_Rj[j] sin = np.sin(2*np.pi*j/N) cos = np.cos(2*np.pi*j/N) Rp += sin * Rj Rpp += cos * Rj normal = np.cross(Rp,Rpp) return fncs.normalize_vec(normal)