Пример #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(
                "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