def do_bendcharm(self, thresshold=2 * deg): ''' No Harmonic bend can have a rest value equal to are large than 180 deg - thresshold. If a master (or its slaves) has such a rest value, convert master and all slaves to BendCharm with cos(phis0)=-1. ''' for master in self.valence.iter_masters(label='BendAHarm'): indices = [master.index] for slave in master.slaves: indices.append(slave) found = False for index in indices: rv = self.valence.get_params(index, only='rv') if rv >= 180.0 * deg - thresshold: found = True break if found: log.dump( '%s has rest value > 180-%.0f deg, converted to BendCHarm with cos(phi0)=-1' % (master.basename, thresshold / deg)) for index in indices: term = self.valence.terms[index] self.valence.modify_term( index, Harmonic, [BendCos(*term.get_atoms())], term.basename.replace('BendAHarm', 'BendCHarm'), ['HC_FC_DIAG'], ['kjmol', 'au']) self.valence.set_params(index, fc=0.0, rv0=-1.0) for traj in self.trajectories: if traj.term.index == index: traj.rv = None traj.fc = None traj.active = False
def do_squarebend(self, thresshold=20 * deg): ''' Identify bend patterns in which 4 atoms of type A surround a central atom of type B with A-B-A angles of 90/180 degrees. A simple harmonic pattern will not be adequate since a rest value of 90 and 180 degrees is possible for the same A-B-A term. Therefore, a cosine term with multiplicity of 4 is used (which corresponds to a chebychev4 potential with sign=-1): V = K/2*[1-cos(4*theta)] To identify the patterns, it is assumed that the rest values have already been estimated from the perturbation trajectories. For each master and slave of a BENDAHARM term, its rest value is computed and checked if it lies either the interval [90-thresshold,90+thresshold] or [180-thresshold,180]. If this is the case, the new cosine term is used. **Optional arguments** thresshold the (half) the width of the interval around 180 deg (90 degrees) to check if a square BA4 ''' for master in self.valence.iter_masters(label='BendAHarm'): rvs = np.zeros([len(master.slaves) + 1], float) rvs[0] = self.valence.get_params(master.index, only='rv') for i, islave in enumerate(master.slaves): rvs[1 + i] = self.valence.get_params(islave, only='rv') n90 = 0 n180 = 0 nother = 0 for i, rv in enumerate(rvs): if 90 * deg - thresshold <= rv and rv <= 90 * deg + thresshold: n90 += 1 elif 180 * deg - thresshold <= rv and rv <= 180 * deg + thresshold: n180 += 1 else: nother += 1 if n90 > 0 and n180 > 0: log.dump( '%s has rest values around 90 deg and 180 deg, converted to BendCheby4' % master.basename) #modify master and slaves indices = [master.index] for slave in master.slaves: indices.append(slave) for index in indices: term = self.valence.terms[index] self.valence.modify_term( index, Chebychev4, [BendCos(*term.get_atoms())], term.basename.replace('BendAHarm', 'BendCheby4'), ['HC_FC_DIAG'], ['kjmol', 'au']) self.valence.set_params(index, sign=-1) for traj in self.trajectories: if traj.term.index == index: traj.active = False traj.fc = None traj.rv = None