예제 #1
0
    def transform_forcefield(self, ff, to_representation):
        self.freeze()
        to_representation.freeze()
        if sanity_checking_enabled and ff.representation is not self:
            raise ValueError(
                "int_rep.transform_forcefield must be given a force field whose"
                " representation is int_rep")
        rv = ForceField(to_representation, ff.max_order, ff.molecular_property,
                        ff.property_units)
        if isinstance(to_representation, CartesianRepresentation):
            B = self.b_tensor(cartesian_representation=to_representation)
            rv.for_order(1)[...] = self.transform_tensor(
                ff.for_order(1), to_representation)
            for o in xrange(1, ff.max_order + 1):
                B.for_order(o).fill()
            if ff.max_order >= 2:
                # Do this by hand to speed things up...
                rv['i1,i2'] = ff['p1'] * B['p1,i1,i2'] + ff['p1,p2'] * B[
                    'p1,i1'] * B['p2,i2']
                # TODO Permutational symmetry?
                #if ff.max_order >= 3:
                #    # Do this by hand also to speed things up...
                #    # The three middle terms could be done more efficiently by first summing
                #    #   over them and then doing the contraction, but this is not yet implemented
                #    #   for einstein summation
                #    rv['i1,i2,i3'] = ff['p1']*B['p1,i1,i2,i3'] + ff['p1,p2,p3']*B['p1,i1']*B['p2,i2']*B['p3,i3']
                #    for s in I_lubar(3, 2, ('i1','i2','i3')):
                #        rv['i1,i2,i3'] += ff['p1,p2']*B[('p1',)+s[0]]*B[('p2',) + s[1]]
                if ff.max_order >= 3:

                    def idxstrs(letter, num):
                        return tuple(
                            map(lambda x: letter + str(x), xrange(num)))

                    for order in xrange(3, ff.max_order + 1):
                        iidxs = idxstrs('i', order)
                        for k in xrange(1, order + 1):
                            for cartsets in I_lubar(order, k, iidxs):
                                rv[iidxs] += ff[idxstrs('p', k)] * prod(
                                    B[('p' + str(m), ) + cartsets[m]]
                                    for m in xrange(k))
            return rv
        elif isinstance(to_representation, InternalRepresentation):
            # use an intermediary
            intermed = self.molecule.cartesian_representation
            return ff.in_representation(intermed).in_representation(
                to_representation)
        elif isinstance(to_representation, NormalRepresentation):
            # use an intermediary
            intermed = self.molecule.cartesian_representation
            return ff.in_representation(intermed).in_representation(
                to_representation)
        else:
            raise NotImplementedError
예제 #2
0
 def transform_forcefield(self, ff, to_representation):
     self.freeze()
     to_representation.freeze()
     if sanity_checking_enabled and ff.representation is not self:
         raise ValueError("int_rep.transform_forcefield must be given a force field whose"
                          " representation is int_rep")
     rv = ForceField(to_representation, ff.max_order, ff.molecular_property, ff.property_units)
     if isinstance(to_representation, CartesianRepresentation):
         B = self.b_tensor(cartesian_representation=to_representation)
         rv.for_order(1)[...] = self.transform_tensor(ff.for_order(1), to_representation)
         for o in xrange(1, ff.max_order+1):
             B.for_order(o).fill()
         if ff.max_order >= 2:
             # Do this by hand to speed things up...
             rv['i1,i2'] = ff['p1']*B['p1,i1,i2'] + ff['p1,p2']*B['p1,i1']*B['p2,i2']
             # TODO Permutational symmetry?
             #if ff.max_order >= 3:
             #    # Do this by hand also to speed things up...
             #    # The three middle terms could be done more efficiently by first summing
             #    #   over them and then doing the contraction, but this is not yet implemented
             #    #   for einstein summation
             #    rv['i1,i2,i3'] = ff['p1']*B['p1,i1,i2,i3'] + ff['p1,p2,p3']*B['p1,i1']*B['p2,i2']*B['p3,i3']
             #    for s in I_lubar(3, 2, ('i1','i2','i3')):
             #        rv['i1,i2,i3'] += ff['p1,p2']*B[('p1',)+s[0]]*B[('p2',) + s[1]]
             if ff.max_order >= 3:
                 def idxstrs(letter, num): return tuple(map(lambda x: letter + str(x), xrange(num)))
                 for order in xrange(3, ff.max_order + 1):
                     iidxs = idxstrs('i', order)
                     for k in xrange(1, order+1):
                         for cartsets in I_lubar(order, k, iidxs):
                             rv[iidxs] += ff[idxstrs('p', k)] * prod(
                                 B[('p'+str(m),) + cartsets[m]] for m in xrange(k)
                             )
         return rv
     elif isinstance(to_representation, InternalRepresentation):
         # use an intermediary
         intermed = self.molecule.cartesian_representation
         return ff.in_representation(intermed).in_representation(to_representation)
     elif isinstance(to_representation, NormalRepresentation):
         # use an intermediary
         intermed = self.molecule.cartesian_representation
         return ff.in_representation(intermed).in_representation(to_representation)
     else:
         raise NotImplementedError
예제 #3
0
    def transform_forcefield(self, ff, to_representation):
        self.freeze()
        to_representation.freeze()
        if sanity_checking_enabled and ff.representation is not self:
            raise ValueError(
                "cart_rep.transform_forcefield must be given a force field whose"
                " representation is cart_rep")
        rv = ForceField(to_representation, ff.max_order, ff.molecular_property,
                        ff.property_units)
        if isinstance(to_representation, CartesianRepresentation):
            for order in xrange(1, ff.max_order + 1):
                rv[...] = self.transform_tensor(ff.for_order(order),
                                                to_representation)
            return rv
        elif isinstance(to_representation, NormalRepresentation):
            for order in xrange(1, ff.max_order + 1):
                rv[...] = self.transform_tensor(ff.for_order(order),
                                                to_representation)
            return rv
        elif isinstance(to_representation, InternalRepresentation):
            # Units should take care of themselves here.  This is because
            #   the B tensor should have units (to-representation units)/(cart-representation units)**order
            # TODO write a test that checks the fact that units take care of themselves
            A = DerivativeCollection(
                representation=self,
                first_dimension_different=True,
                secondary_representation=to_representation,
                uncomputed=False)
            A.for_order(1)[...] = to_representation.a_matrix
            B = to_representation.b_tensor(cartesian_representation=self)
            rv.for_order(1)[...] = A.for_order(1).view(
                Matrix).T * ff.for_order(1).view(Vector)
            if ff.max_order >= 2:
                C = DerivativeCollection(representation=to_representation,
                                         uncomputed=False)
                C['q,p1,p2'] = B['q,i1,i2'] * A['i1,p1'] * A['i2,p2']
                rv['p1,p2'] = ff['i1,i2'] * A['i1,p1'] * A['i2,p2'] - rv[
                    'q'] * C['q,p1,p2']
                #--------------------------------------------------------------------------------#
                if ff.max_order >= 3:
                    # Do third order by hand...
                    C['q,p1,p2,p3'] = B['q,i1,i2,i3'] * A['i1,p1'] * A[
                        'i2,p2'] * A['i3,p3']
                    rv['p1,p2,p3'] = ff['i1,i2,i3'] * A['i1,p1'] * A[
                        'i2,p2'] * A['i3,p3']
                    rv['p1,p2,p3'] -= rv['q,p1'] * C['q,p2,p3']
                    rv['p1,p2,p3'] -= rv['q,p2'] * C['q,p1,p3']
                    rv['p1,p2,p3'] -= rv['q,p3'] * C['q,p1,p2']
                    rv['p1,p2,p3'] -= rv['q'] * C['q,p1,p2,p3']
                    if ff.max_order >= 4:

                        def idxstrs(letter, num):
                            return tuple(
                                map(lambda x: letter + str(x), xrange(num)))

                        for order in xrange(4, ff.max_order + 1):
                            p_s = idxstrs('p', order)
                            i_s = idxstrs('i', order)
                            C[('q', ) + p_s] = B[('q', ) + i_s] * prod(
                                A[i, p] for i, p in zip(i_s, p_s))
                            rv[p_s] = ff[i_s] * prod(A[i, p]
                                                     for i, p in zip(i_s, p_s))
                            rv[p_s] -= rv['q'] * C[('q', ) + p_s]
                            for k in xrange(2, order):
                                q_s = idxstrs('q', k)
                                for s in I_lubar(order, k, p_s):
                                    if any(len(seg) == 1 for seg in s):
                                        continue
                                    rv[p_s] -= rv[q_s] * prod(
                                        C[(q_s[m], ) + s[m]]
                                        for m in xrange(k))
                                q_s = idxstrs('q', k - 1)
                                for part1len in xrange(1, order - 2 * (k - 1) +
                                                       1):
                                    part2len = order - part1len
                                    for p1idxs, p2idxs in m_way_ordered_combinations(
                                            order, [part1len, part2len]):
                                        p1s = tuple(p_s[pidx]
                                                    for pidx in p1idxs)
                                        p2s = tuple(p_s[pidx]
                                                    for pidx in p2idxs)
                                        print(p1s, p2s, k)
                                        for s in I_lubar(part2len, k - 1, p2s):
                                            rv[p_s] -= rv[q_s + p1s] * prod(
                                                C[(alpha, ) + betas]
                                                for alpha, betas in zip(
                                                    q_s, s))
            return rv
        else:
            raise NotImplementedError
예제 #4
0
    def transform_forcefield(self, ff, to_representation):
        self.freeze()
        to_representation.freeze()
        if sanity_checking_enabled and ff.representation is not self:
            raise ValueError(
                "cart_rep.transform_forcefield must be given a force field whose" " representation is cart_rep"
            )
        rv = ForceField(to_representation, ff.max_order, ff.molecular_property, ff.property_units)
        if isinstance(to_representation, CartesianRepresentation):
            for order in xrange(1, ff.max_order + 1):
                rv[...] = self.transform_tensor(ff.for_order(order), to_representation)
            return rv
        elif isinstance(to_representation, NormalRepresentation):
            for order in xrange(1, ff.max_order + 1):
                rv[...] = self.transform_tensor(ff.for_order(order), to_representation)
            return rv
        elif isinstance(to_representation, InternalRepresentation):
            # Units should take care of themselves here.  This is because
            #   the B tensor should have units (to-representation units)/(cart-representation units)**order
            # TODO write a test that checks the fact that units take care of themselves
            A = DerivativeCollection(
                representation=self,
                first_dimension_different=True,
                secondary_representation=to_representation,
                uncomputed=False,
            )
            A.for_order(1)[...] = to_representation.a_matrix
            B = to_representation.b_tensor(cartesian_representation=self)
            rv.for_order(1)[...] = A.for_order(1).view(Matrix).T * ff.for_order(1).view(Vector)
            if ff.max_order >= 2:
                C = DerivativeCollection(representation=to_representation, uncomputed=False)
                C["q,p1,p2"] = B["q,i1,i2"] * A["i1,p1"] * A["i2,p2"]
                rv["p1,p2"] = ff["i1,i2"] * A["i1,p1"] * A["i2,p2"] - rv["q"] * C["q,p1,p2"]
                # --------------------------------------------------------------------------------#
                if ff.max_order >= 3:
                    # Do third order by hand...
                    C["q,p1,p2,p3"] = B["q,i1,i2,i3"] * A["i1,p1"] * A["i2,p2"] * A["i3,p3"]
                    rv["p1,p2,p3"] = ff["i1,i2,i3"] * A["i1,p1"] * A["i2,p2"] * A["i3,p3"]
                    rv["p1,p2,p3"] -= rv["q,p1"] * C["q,p2,p3"]
                    rv["p1,p2,p3"] -= rv["q,p2"] * C["q,p1,p3"]
                    rv["p1,p2,p3"] -= rv["q,p3"] * C["q,p1,p2"]
                    rv["p1,p2,p3"] -= rv["q"] * C["q,p1,p2,p3"]
                    if ff.max_order >= 4:

                        def idxstrs(letter, num):
                            return tuple(map(lambda x: letter + str(x), xrange(num)))

                        for order in xrange(4, ff.max_order + 1):
                            p_s = idxstrs("p", order)
                            i_s = idxstrs("i", order)
                            C[("q",) + p_s] = B[("q",) + i_s] * prod(A[i, p] for i, p in zip(i_s, p_s))
                            rv[p_s] = ff[i_s] * prod(A[i, p] for i, p in zip(i_s, p_s))
                            rv[p_s] -= rv["q"] * C[("q",) + p_s]
                            for k in xrange(2, order):
                                q_s = idxstrs("q", k)
                                for s in I_lubar(order, k, p_s):
                                    if any(len(seg) == 1 for seg in s):
                                        continue
                                    rv[p_s] -= rv[q_s] * prod(C[(q_s[m],) + s[m]] for m in xrange(k))
                                q_s = idxstrs("q", k - 1)
                                for part1len in xrange(1, order - 2 * (k - 1) + 1):
                                    part2len = order - part1len
                                    for p1idxs, p2idxs in m_way_ordered_combinations(order, [part1len, part2len]):
                                        p1s = tuple(p_s[pidx] for pidx in p1idxs)
                                        p2s = tuple(p_s[pidx] for pidx in p2idxs)
                                        print(p1s, p2s, k)
                                        for s in I_lubar(part2len, k - 1, p2s):
                                            rv[p_s] -= rv[q_s + p1s] * prod(
                                                C[(alpha,) + betas] for alpha, betas in zip(q_s, s)
                                            )
            return rv
        else:
            raise NotImplementedError