コード例 #1
0
ファイル: internal_cartesians.py プロジェクト: xwang862/psi4
def generate_fixed_fragment_coords(a, b, c, *others):
    """
    TODO Document this
    """
    ret_val = [BondLength(a, b), BondLength(a, c), BondAngle(b, a, c)]
    for d in others:
        ret_val.append(InternalCartesianX(a, b, c, d))
        ret_val.append(InternalCartesianY(a, b, c, d))
        ret_val.append(InternalCartesianZ(a, b, c, d))
    return ret_val
コード例 #2
0
 def value_for_xyz(cls, xyz):
     def e(j, k):
         ev = LightVector.l_sub(xyz[k-1], xyz[j-1]); ev.normalize()
         return ev
     eab, eac, ead = e(1,2), e(1,3), e(1,4)
     tmp = eab.l_cross(eac).normalized()
     return BondLength.value_for_positions(xyz[0], xyz[3]) * tmp.dot(ead)
コード例 #3
0
ファイル: internal_cartesians.py プロジェクト: xwang862/psi4
    def value_for_xyz(cls, xyz):
        def e(j, k):
            ev = LightVector.l_sub(xyz[k - 1], xyz[j - 1])
            ev.normalize()
            return ev

        return BondLength.value_for_positions(xyz[0], xyz[3]) * (e(1, 2).dot(
            e(1, 4)))
コード例 #4
0
ファイル: internal_cartesians.py プロジェクト: xwang862/psi4
    def value_for_xyz(cls, xyz):
        def e(j, k):
            ev = LightVector.l_sub(xyz[k - 1], xyz[j - 1])
            ev.normalize()
            return ev

        eab, eac, ead = e(1, 2), e(1, 3), e(1, 4)
        tmp = eab.l_cross(eac).normalized()
        return BondLength.value_for_positions(xyz[0], xyz[3]) * tmp.dot(ead)
コード例 #5
0
 def __init__(self, molecule, coords_string, one_based=True, units=None):
     off = 1 if one_based else 0
     self.molecule = molecule
     atoms = self.molecule.atoms
     coords = []
     for line in coords_string.splitlines():
         # ignore blank lines
         if len(line.strip()) == 0: continue
         vals = line.split()
         name = vals[0]
         nums = vals[1:]
         #TODO More coordinate types
         if name.lower() in self.STRE_NAMES:
             if len(nums) != 2:
                 raise StandardError(
                     "Invalid coordinate specification string:  " + line)
             coord = BondLength(
                 [atoms[int(nums[0]) - off], atoms[int(nums[1]) - off]],
                 parent=self,
                 index=len(coords))
             coords.append(coord)
         elif name.lower() in self.BEND_NAMES:
             if len(nums) != 3:
                 raise StandardError(
                     "Invalid coordinate specification string:  " + line)
             coord = BondAngle([
                 atoms[int(nums[0]) - off], atoms[int(nums[1]) - off],
                 atoms[int(nums[2]) - off]
             ],
                               parent=self,
                               index=len(coords))
             coords.append(coord)
         elif name.lower() in self.TORS_NAMES:
             if len(nums) != 4:
                 raise StandardError(
                     "Invalid coordinate specification string:  " + line)
             coord = Torsion([
                 atoms[int(nums[0]) - off], atoms[int(nums[1]) - off],
                 atoms[int(nums[2]) - off], atoms[int(nums[3]) - off]
             ],
                             parent=self,
                             index=len(coords))
             coords.append(coord)
         else:
             raise StandardError(
                 "Unknown or unimplemented internal coordinate string:  " +
                 line)
     self.__init__(molecule=molecule, coords=coords, units=units)
コード例 #6
0
ファイル: internal_cartesians.py プロジェクト: xwang862/psi4
 def R(i, j):
     # This is ugly...
     # TODO figure out a better way to do this
     mol = Molecule([Atom('H', args[i - 1]), Atom('H', args[j - 1])])
     return BondLength(mol[0], mol[1])
コード例 #7
0
ファイル: bond_angle.py プロジェクト: xwang862/psi4
    def analytic_b_tensor_for_order(self, order):
        #--------------------------------------------------------------------------------#
        # Now check the cache
        cache_key = (self.__class__, order) + tuple(a.pos for a in self.atoms)
        cache_resp = SimpleInternalCoordinate._check_b_tensor_cache(*cache_key)
        if cache_resp is not None:
            return cache_resp
        #--------------------------------------------------------------------------------#
        B = partial(SimpleInternalCoordinate.b_tensor_element_reindexed, self)
        #--------------------------------------------------------------------------------#
        # First order is already done elsewhere...
        if order == 1:
            # We can't use the `b_vector` attribute since that vector is indexed in the parent
            #   molecule's indexing scheme
            my_b = Vector(
                self.__class__.b_vector_for_positions(
                    *[a.pos for a in self.atoms]))
            # Return now, to avoid double-caching
            return my_b
        #--------------------------------------------------------------------------------#
        # Second order terms
        if order == 2:
            # BondAngles are composed of 3 atoms (3 CartesianCoordinates each), and the
            #   order is 2, so the output Tensor will be a 9x9 Tensor
            my_b = np.ndarray(shape=(9, ) * 2)
            # some precomputed values
            phi = self.value * self.units.to(Radians)
            cotphi = 1.0 / tan(phi)
            cscphi = 1.0 / sin(phi)
            #========================================#
            # see comments in BondLength version
            # First, handle the terminal atom entries
            for (a_idx, a), (c_idx, c) in product(zip([0, 2],
                                                      self.terminal_atoms),
                                                  repeat=2):
                # Generate the temporary coordinates
                if a_idx == 0:
                    Rab = BondLength(self.atoms[0], self.atoms[1])
                    Rbc = BondLength(self.atoms[1], self.atoms[2])
                else:  # a_idx == 2
                    Rab = BondLength(self.atoms[2], self.atoms[1])
                    Rbc = BondLength(self.atoms[1], self.atoms[0])
                #----------------------------------------#
                # Now iterate over the possible sets of cartesian coordinates
                for alpha, beta in product([X, Y, Z], repeat=2):
                    a_alpha, c_beta = a_idx * 3 + alpha, c_idx * 3 + beta
                    if a_idx == c_idx:
                        # From equation 19 in Allen, et al. Mol. Phys. 89 (1996), 1213-1221
                        a_beta = c_beta
                        other_terminal_index = 2 if a_idx == 0 else 0
                        my_b[a_alpha, a_beta] = (
                            -cotphi * B(self, a_alpha) * B(self, a_beta) -
                            cscphi * sum(
                                B(Rab, a_idx * 3 + sigma, a_alpha, a_beta) *
                                B(Rbc, other_terminal_index * 3 + sigma)
                                for sigma in [X, Y, Z]))
                    else:
                        # From equation 20 in Allen, et al. Mol. Phys. 89 (1996), 1213-1221
                        my_b[a_alpha, c_beta] = (
                            -cotphi * B(self, a_alpha) * B(self, c_beta) -
                            cscphi * sum(
                                B(Rab, a_idx * 3 + sigma, a_alpha) *
                                B(Rbc, c_idx * 3 + sigma, c_beta)
                                for sigma in [X, Y, Z]))
            # Now fill in the middle atom entries utilizing translational invariance
            # From equation 32 in Allen, et al. Mol. Phys. 89 (1996), 1213-1221
            for alpha, beta in product([X, Y, Z], repeat=2):
                b_beta = 3 + beta
                for a_idx, a in zip([0, 2], self.terminal_atoms):
                    a_alpha = 3 * a_idx + alpha
                    my_b[b_beta, a_alpha] = my_b[a_alpha, b_beta] = \
                        -sum(my_b[a_alpha, t + beta]
                            for t in [0, 6] # 0 and 6 are the offsets for the terminal atoms
                        )
                # Now the b_alpha, b_beta entry:
                my_b[3 + alpha, 3 + beta] = sum(
                    my_b[atom1 * 3 + alpha, atom2 * 3 + beta]
                    for atom1, atom2 in product([0, 2], repeat=2))
        #--------------------------------------------------------------------------------#
        else:
            # behold, the general formula!
            # BondAngles are composed of 3 atoms (3 CartesianCoordinates each),
            #   so the output will be a 9x9x...x9 (`order`-dimensional) tensor
            my_b = Tensor(indices=','.join('v' * order),
                          index_range_set=self.__class__._btens_idx_range_set)
            #Bphi = self._btensor
            Rab = self.get_coord(BondLength, self.atoms[0], self.atoms[1])
            Rbc = self.get_coord(BondLength, self.atoms[1], self.atoms[2])
            #Brab = Rab._btensor
            #Brbc = Rbc._btensor
            #for o in xrange(1, order):
            #    t = Bphi.for_order(o)
            #    rab = Brab.for_order(o)
            #    rbc = Rbc._btensor.for_order(o)
            #    if isinstance(t, ComputableTensor): t.fill()
            #    if isinstance(rab, ComputableTensor): rab.fill()
            #    if isinstance(rbc, ComputableTensor): rab.fill()
            #Brab.for_order(order).fill()
            #Brbc.for_order(order).fill()
            #remap_set = IndexRangeSet()
            #DeclareIndexRange('v', 6, index_range_set=remap_set).with_subranges(
            #    IndexRange('b', 3, 6, index_range_set=remap_set),
            #    IndexRange('c', 0, 3, index_range_set=remap_set)
            #)
            ##Brbc = DerivativeCollection(coordinate=Rbc, einsum_index='v', index_range_set=remap_set)
            #ba = Vector([Brab[(0,) + (Ellipsis,)*order]])
            #for o in xrange(1, order+1):
            #    Brbc.for_order(o).index_range_set = remap_set
            ## some precomputed values
            phi = self.value * self.units.to(Radians)
            cotphi = 1.0 / tan(phi)
            cscphi = 1.0 / sin(phi)

            #========================================#
            # First take care of the terminal atoms...
            def f_K(k):
                if k % 2 == 1:
                    if (k + 1) / 2 % 2 == 0:
                        return 1
                    else:  # (k+1)/2 % 2 == 1
                        return -1
                elif k / 2 % 2 == 0:
                    return cotphi
                else:  # k/2 % 2 == 1
                    return -cotphi

            #----------------------------------------#
            a_idx, c_idx = 0, 2
            for num_a_coords in xrange(0, order + 1):
                # outer loop over possible alphas
                for alphas in product([X, Y, Z], repeat=order):
                    a_alphas = tuple(3 * a_idx + alpha
                                     for alpha in alphas[:num_a_coords])
                    c_alphas = tuple(3 * c_idx + alpha
                                     for alpha in alphas[num_a_coords:])
                    # Now we have all of the specifics for the left-hand side, so compute the
                    #   right-hand side to go with it...
                    cum_sum = 0.0
                    for sigma in [X, Y, Z]:
                        cum_sum += B(Rab, 3 * a_idx + sigma, *a_alphas) * B(
                            Rbc, 3 * c_idx + sigma, *c_alphas)
                    cum_sum *= -cscphi
                    for k in range(2, order + 1):
                        inner_sum = 0.0
                        for s in I_lubar(order, k, a_alphas + c_alphas):
                            prod = 1.0
                            for i in range(k):
                                prod *= B(self, *s[i])
                            inner_sum += prod
                        cum_sum += f_K(k) * inner_sum
                    # Spread over permutations
                    for idxs in permutations(a_alphas + c_alphas):
                        my_b[idxs] = cum_sum
            #========================================#
            # now compute the terms involving the middle atom
            a1_idx, a2_idx, a3_idx = 0, 1, 2
            for num_a2s in xrange(1, order + 1):
                # Now fill in the middle atom entries utilizing translational invariance
                # From equation 32 in Allen, et al. Mol. Phys. 89 (1996), 1213-1221
                for first_a2_position in xrange(0, order - num_a2s + 1):
                    for alphas in product([X, Y, Z], repeat=order):
                        a1_alphas = tuple(
                            3 * a1_idx + alpha
                            for alpha in alphas[:first_a2_position])
                        middle_alphas = alphas[
                            first_a2_position:first_a2_position + num_a2s]
                        a2_alphas = tuple(3 * a2_idx + alpha
                                          for alpha in middle_alphas)
                        a3_alphas = tuple(
                            3 * a3_idx + alpha
                            for alpha in alphas[first_a2_position + num_a2s:])
                        val_to_spread = 0.0
                        for midatoms in product([a1_idx, a3_idx],
                                                repeat=num_a2s):
                            idxs = a1_alphas
                            idxs += tuple(ai * 3 + middle_alphas[i]
                                          for i, ai in enumerate(midatoms))
                            idxs += a3_alphas
                            val_to_spread += my_b[idxs]
                        if num_a2s % 2 == 1:
                            val_to_spread *= -1.0
                        for perm in permutations(a1_alphas + a2_alphas +
                                                 a3_alphas):
                            my_b[perm] = val_to_spread
        #--------------------------------------------------------------------------------#
        # Cache the value we got
        SimpleInternalCoordinate._set_b_tensor_cache_entry(my_b, *cache_key)
        #--------------------------------------------------------------------------------#
        return my_b
コード例 #8
0
 def value_for_xyz(cls, xyz):
     def e(j, k):
         ev = LightVector.l_sub(xyz[k-1], xyz[j-1]); ev.normalize()
         return ev
     return BondLength.value_for_positions(xyz[0], xyz[3]) * (e(1,2).dot(e(1,4)))