def calc_V_matrix_adf(x): """ Calculate the lower triangle (row order) of the diabatic matrix given adf input """ a0 = n2.constants.a0 RCC = x[0] / a0 # C--C bond length, convert angstroms to bohr RCH = x[1] / a0 # C--H bond length, convert angstroms to bohr theta = x[2] # C--C--H angle, degrees n = Cijk.shape[0] # The number of expansion terms # For each surface function v = [] for p in range(4): dCC = RCC - RCC_ref[p] dCH = RCH - RCH_ref[p] dtheta = (theta - theta_ref[p]) * (n2.pi/180.0) # convert to radians dCC_pow = pows(dCC, round(max(Cijk[:,0]))) dCH_pow = pows(dCH, round(max(Cijk[:,1]))) dtheta_pow = pows(dtheta, round(max(Cijk[:,2]))) vp = 0 for i in range(n): c = Cijk[i,p + 3] # The coefficient of this surface vp += c * dCC_pow[round(Cijk[i,0])] * \ dCH_pow[round(Cijk[i,1])] * \ dtheta_pow[round(Cijk[i,2])] if p == 3: # The V12 surface vp *= adf.sin( dtheta ) * \ (1.0 - adf.tanh(dCC)) * (1.0 - adf.tanh(dCH)) # Convert from Hartree to cm^-1 vp *= n2.constants.Eh v.append(vp) # v contains [V11, V22, V33, V12] # Now build the lower triangle # in row major order: # V11 # V21 = V12, V22 # V31 = 0, V32 = 0, V33 # V31 = adf.const_like(0.0,v[0]) V32 = adf.const_like(0.0,v[0]) lower = [v[0], v[3], v[1], V31, V32, v[2]] return lower
def calcsurf(q): max_pow = [5, 5, 5, 6, 6, 6] # max_pow[5] is really the max freq. of dihedral qpow = [] for i in range(5): qi = [adf.const_like(1.0, q[i]), q[i]] for p in range(2, max_pow[i] + 1): qi.append(qi[1] * qi[p - 1]) # qi ** p qpow.append(qi) # Calculate cos(n*q6) cosq = [adf.cos(n * q[5]) for n in range(max_pow[5] + 1)] qpow.append(cosq) v = 0.0 nterms = powers.shape[0] for i in range(nterms): c = coeffs[i] v += c * \ qpow[0][powers[i,0]] * \ qpow[1][powers[i,1]] * \ qpow[2][powers[i,2]] * \ qpow[3][powers[i,3]] * \ qpow[4][powers[i,4]] * \ qpow[5][powers[i,5]] return v
def calcPolySurf(r1,r2,theta): """ r1,r2: Angstroms theta: degrees """ Rref,Rscale = 1.7023, 0.2 thetaRef, thetaScale = 180.0, 50.0 thetaPowMax = 14 rPowMax = 7 Nterms = 288 # Calculate scaled coordinates and # their powers # r1S = [adf.const_like(1.0, r1), (r1 - Rref)/Rscale] for i in range(2,rPowMax+1): r1S.append(r1S[1] * r1S[i-1]) r2S = [adf.const_like(1.0, r2), (r2 - Rref)/Rscale] for i in range(2,rPowMax+1): r2S.append(r2S[1] * r2S[i-1]) thS = [adf.const_like(1.0, theta), (theta - thetaRef)/thetaScale ] for i in range(2,thetaPowMax+1): thS.append(thS[1] * thS[i-1]) v = adf.const_like(0.0, r1) for i in range(Nterms): v += coeffs[i] * r1S[r1Pows[i]] * r2S[r2Pows[i]] * thS[thPows[i]] return v
def _Philm(self, X, deriv = 0, out = None, var = None): # Setup nd,nvar = dfun.ndnvar(deriv, var, self.nx) if out is None: base_shape = X.shape[1:] out = np.ndarray( (nd, self.nf) + base_shape, dtype = X.dtype) # Make adf objects for theta and phi x = dfun.X2adf(X, deriv, var) theta = x[0] phi = x[1] ######################################### # # Calculate F and f factors first # sinth = adf.sin(theta) costh = adf.cos(theta) lmax = np.max(self.l) # Calculate the associated Legendre factors Flm = [] amuni = np.unique(abs(self.m)) # list of unique |m| for aM in amuni: # Order aM = |M| sinM = adf.powi(sinth, aM) # Calculate F^M up to l <= lmax Flm.append(_leg_gen(sinM, costh, aM, lmax)) #Flm is now a nested list # Calculate the phi factors smuni = np.unique(self.m) # list of unique signed m fm = [] for sM in smuni: if sM == 0: fm.append(adf.const_like(1/np.sqrt(2*np.pi), phi)) elif sM < 0: fm.append(1/np.sqrt(np.pi) * adf.sin(abs(sM) * phi)) else: #sM > 0 fm.append(1/np.sqrt(np.pi) * adf.cos(sM * phi)) # ############################################## ########################################### # Now calculate the list of real spherical harmonics Phi = [] for i in range(self.nf): l = self.l[i] m = self.m[i] # signed m # Gather the associated Legendre polynomial (theta factor) aM_idx = np.where(amuni == abs(m))[0][0] l_idx = l - abs(m) F_i = Flm[aM_idx][l_idx] # Gather the sine/cosine (phi factor) sM_idx = np.where(smuni == m)[0][0] f_i = fm[sM_idx] # Add their product to the list of functions Phi.append(F_i * f_i) # ########################################### # Convert the list to a single # DFun derivative array dfun.adf2array(Phi, out) # and return return out
def _chinell(self, X, deriv = 0, out = None, var = None): # Setup nd,nvar = dfun.ndnvar(deriv, var, self.nx) if out is None: base_shape = X.shape[1:] out = np.ndarray( (nd, self.nf) + base_shape, dtype = X.dtype) # Make adf objects for theta and phi x = dfun.X2adf(X, deriv, var) r = x[0] # Cylindrical radius phi = x[1] if self._rad else x[1] * np.pi/180.0 # Angular coordinate ######################################### # # Calculate R and f factors first # # Calculate the radial wavefunctions Rnell = [] abs_ell_uni = np.unique(abs(self.ell)) # list of unique |ell| expar2 = adf.exp(-0.5 * self.alpha * (r*r)) # The exponential radial factor for aELL in abs_ell_uni: nmax = round(np.floor(self.vmax - aELL) / 2) Rnell.append(_radialHO_gen(r, expar2, nmax, aELL, 2, self.alpha)) # Calculate the phi factors, f_ell(phi) sig_ell_uni = np.unique(self.ell) # list of unique signed ell fell = [] if self._rad: # Normalization assuming radians for sELL in sig_ell_uni: if sELL == 0: fell.append(adf.const_like(1/np.sqrt(2*np.pi), phi)) elif sELL < 0: fell.append(1/np.sqrt(np.pi) * adf.sin(abs(sELL) * phi)) else: #sELL > 0 fell.append(1/np.sqrt(np.pi) * adf.cos(sELL * phi)) else: # Normalization for degrees for sELL in sig_ell_uni: if sELL == 0: fell.append(adf.const_like(1/np.sqrt(360.00), phi)) elif sELL < 0: fell.append(1/np.sqrt(180.0) * adf.sin(abs(sELL) * phi)) else: #sELL > 0 fell.append(1/np.sqrt(180.0) * adf.cos(sELL * phi)) # ############################################## ########################################### # Now calculate the list of real 2-D HO wavefunctions chi = [] for i in range(self.nf): ell = self.ell[i] n = self.n[i] # Gather the radial factor abs_ELL_idx = np.where(abs_ell_uni == abs(ell))[0][0] R_i = Rnell[abs_ELL_idx][n] # Gather the angular factor sig_ELL_idx = np.where(sig_ell_uni == ell)[0][0] f_i = fell[sig_ELL_idx] # Add their product to the list of functions chi.append(R_i * f_i) # ########################################### # Convert the list to a single # DFun derivative array dfun.adf2array(chi, out) # and return return out