Exemple #1
0
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
Exemple #2
0
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
Exemple #3
0
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 
    
Exemple #4
0
 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 
Exemple #5
0
 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