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
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
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
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