def satisfy(self, vterm, pars, part, system): if self.pars == pars: part_valence = ForcePartValence(system) part_valence.add_term(vterm) energy = part_valence.compute() ic_index = part_valence.vlist.vtab[0]['ic0'] ic = part_valence.vlist.iclist.ictab[ic_index]['value'] return np.abs(ic - self.rv) < self.eps else: return True
def __init__(self, system, term, other_terms, cart_penalty=1e-3 * angstrom): ''' A class deriving from the Yaff ForceField class to implement the strain of a molecular geometry associated with the term defined by term_index. **Arguments** system A Yaff System instance containing all system information. term a Term instance representing the term of the perturbation trajectory of the current strain other_terms a list of Term instances representing all other terms for ICs for which a strain contribution should be added **Keyword Arguments** cart_penalty Magnitude of an extra term added to the strain that penalises a deviation of the cartesian coordinates of each atom with respect to the equilibrium coordinates. This penalty is equal to norm(R-R_eq)**2/(2.0*3*Natoms*cart_penalty**2) and prevents global translations, global rotations as well as rotations of molecular fragments far from the IC under consideration. ''' self.coords0 = system.pos.copy() self.ndof = np.prod(self.coords0.shape) self.cart_penalty = cart_penalty self.cons_ic_atindexes = term.get_atoms() #construct main strain strain = ForcePartValence(system) for other in other_terms: if other.kind == 3: continue #no cross terms strain.add_term(Harmonic(1.0, None, other.ics[0])) #set the rest values to the equilibrium values strain.dlist.forward() strain.iclist.forward() for iterm in range(strain.vlist.nv): vterm = strain.vlist.vtab[iterm] ic = strain.iclist.ictab[vterm['ic0']] vterm['par1'] = ic['value'] ForceField.__init__(self, system, [strain]) #Abuse the Chebychev1 polynomial to simply get the value of q-1 and #implement the contraint constraint = ForcePartValence(system) constraint.add_term(Chebychev1(-2.0, term.ics[0])) self.constraint = ForceField(system, [constraint]) self.constrain_target = None self.constrain_value = None self.value = None
def get_hessian_contrib(self, index, fc=None): ''' Get the contribution to the covalent hessian of term with given index (and its slaves). If fc is given, set the fc of the master and its slave to the given fc. ''' val = ForcePartValence(self.system) kind = self.vlist.vtab[index]['kind'] masterslaves = [index] + self.terms[index].slaves if kind == 4: #Cosine m, k, rv = self.get_params(index) if fc is not None: k = fc for jterm in masterslaves: ics = self.terms[jterm].ics args = (m, k, rv) + tuple(ics) val.add_term(Cosine(*args)) elif kind == 3: #cross k, rv0, rv1 = self.get_params(index) if fc is not None: k = fc for jterm in masterslaves: ics = self.terms[jterm].ics args = (k, rv0, rv1) + tuple(ics) val.add_term(Cross(*args)) elif kind == 1: #Polyfour a0, a1, a2, a3 = list(self.get_params(index)) if fc is not None: a3 = 2.0 * fc a1 = -4.0 * fc * np.cos(a0)**2 for jterm in masterslaves: ics = self.terms[jterm].ics args = ([0.0, a1, 0.0, a3], ) + tuple(ics) val.add_term(PolyFour(*args)) elif kind == 0: #Harmonic: k, rv = self.get_params(index) if fc is not None: k = fc for jterm in masterslaves: ics = self.terms[jterm].ics args = (k, rv) + tuple(ics) val.add_term(Harmonic(*args)) else: raise ValueError('Term kind %i not supported' % kind) ff = ForceField(self.system, [val]) hcov = estimate_cart_hessian(ff) return hcov
def __init__(self, system, specs=None): ''' **Arguments** system an instance of the Yaff System class containing all system properties **Keyword Arguments** specs Not yet implemented ''' with log.section('VAL', 2, timer='Initializing'): log.dump('Initializing valence force field') self.system = system self.terms = [] ForcePartValence.__init__(self, system) self.init_bond_terms() self.init_bend_terms() self.init_dihedral_terms() self.init_oop_terms()
def __init__(self, system, term, other_terms, cart_penalty=1e-3*angstrom): ''' A class deriving from the Yaff ForceField class to implement the strain of a molecular geometry associated with the term defined by term_index. **Arguments** system A Yaff System instance containing all system information. term a Term instance representing the term of the perturbation trajectory of the current strain other_terms a list of Term instances representing all other terms for ICs for which a strain contribution should be added **Keyword Arguments** cart_penalty Magnitude of an extra term added to the strain that penalises a deviation of the cartesian coordinates of each atom with respect to the equilibrium coordinates. This penalty is equal to norm(R-R_eq)**2/(2.0*3*Natoms*cart_penalty**2) and prevents global translations, global rotations as well as rotations of molecular fragments far from the IC under consideration. ''' self.coords0 = system.pos.copy() self.ndof = np.prod(self.coords0.shape) self.cart_penalty = cart_penalty self.cons_ic_atindexes = term.get_atoms() #construct main strain strain = ForcePartValence(system) for other in other_terms: if other.kind == 3: continue #no cross terms strain.add_term(Harmonic(1.0, None, other.ics[0])) #set the rest values to the equilibrium values strain.dlist.forward() strain.iclist.forward() for iterm in range(strain.vlist.nv): vterm = strain.vlist.vtab[iterm] ic = strain.iclist.ictab[vterm['ic0']] vterm['par1'] = ic['value'] ForceField.__init__(self, system, [strain]) #Abuse the Chebychev1 polynomial to simply get the value of q-1 and #implement the contraint constraint = ForcePartValence(system) constraint.add_term(Chebychev1(-2.0,term.ics[0])) self.constraint = ForceField(system, [constraint]) self.constrain_target = None self.constrain_value = None self.value = None
def __init__(self, system, cons_ic, cons_ic_atindexes, ics, cart_penalty=1e-3 * angstrom): ''' A class deriving from the Yaff ForceField class to implement the strain of a molecular geometry associated with the term defined by term_index. **Arguments** system A Yaff System instance containing all system information. cons_ic An instance of Yaff Internal Coordinate representing the constrained term in the strain. cons_ic_atindexes A list of the atoms involved in the constrained IC. This is required for the implementation of the cartesian penalty. In principle this could be extracted from the information stored in cons_ic, but this is the lazy solution. ics A list of Yaff Internal Coordinate instances for which the strain needs to be minimized. cart_penalty Magnitude of an extra term added to the strain that penalises a deviation of the cartesian coordinates of each atom with respect to the equilibrium coordinates. This penalty is equal to norm(R-R_eq)**2/(2.0*3*Natoms*cart_penalty**2) and prevents global translations, global rotations as well as rotations of molecular fragments far from the IC under consideration. ''' self.coords0 = system.pos.copy() self.ndof = np.prod(self.coords0.shape) self.cart_penalty = cart_penalty self.cons_ic_atindexes = cons_ic_atindexes part = ForcePartValence(system) for ic in ics: part.add_term(Harmonic(1.0, None, ic)) #set the rest values to the equilibrium values part.dlist.forward() part.iclist.forward() for iterm in xrange(part.vlist.nv): term = part.vlist.vtab[iterm] ic = part.iclist.ictab[term['ic0']] term['par1'] = ic['value'] ForceField.__init__(self, system, [part]) #Abuse the Chebychev1 polynomial to simply get the value of q-1 and #implement the contraint part = ForcePartValence(system) part.add_term(Chebychev1(-2.0, cons_ic)) self.constraint = ForceField(system, [part]) self.constrain_target = None self.constrain_value = None self.value = None
def add_term(self, pot, ics, atypes, tasks, units): ''' Adds new term both to the Yaff vlist object and a new QuickFF list (self.terms) which holds all information about the term for easy access later in QuickFF. **Arguments** pot an instance of ValenceTerm from `yaff.pes.vlist.py` representing the potential chosen for the term ics list of InternalCoordinate instances from `yaff.pes.iclist.py` atypes ordered string of atom types (required to assign name to the term) tasks List of strings defining all tasks that have to be performed for this term. Possible tasks are: PT_ALL, HC_FC_DIAG, HC_FC_CROSS, EQ_RV. units Units for all parameters in this term (ordered in the same way as parameters are stored in `yaff.vlist.vtab`) ''' index = len(self.terms) #define the name if len(ics) == 1: tmp = { (0, 0): 'BondHarm/', (2, 0): 'BendAHarm/', (4, 4): 'Torsion/', (3, 1): 'TorsC2Harm/', (10, 0): 'Oopdist/', (11, 0): 'SqOopdist/', } prefix = tmp[(ics[0].kind, pot.kind)] suffix = '' else: assert len(ics) == 2 and pot.kind == 3 prefix = 'Cross/' if ics[0].kind == 0 and ics[1].kind == 0: suffix = '/bb' #first bond and second bond elif ics[0].kind == 0 and ics[1].kind == 2: if set(ics[0].index_pairs[0]) == set(ics[1].index_pairs[0]): suffix = '/b0a' #first bond and angle elif set(ics[0].index_pairs[0]) == set(ics[1].index_pairs[1]): suffix = '/b1a' #second bond and angle else: raise ValueError( 'Incompatible bond/angle given in cross term') else: raise ValueError('Incompatible ICs given in cross term') basename = prefix + '.'.join(atypes) + suffix #search for possible master and update slaves master = None slaves = None for i, term in enumerate(self.terms): if term.basename == basename: if term.is_master(): master = term.index term.slaves.append(index) else: assert master == term.master if master is None: master = index slaves = [] #add term to self.terms and self.vlist.vtab term = Term(index, basename, pot.kind, ics, tasks, units, master=master, slaves=slaves) self.terms.append(term) if pot.kind == 1: #all 4 parameters of PolyFour are given as 1 tuple args = [(None, ) * len(units)] + ics else: args = [ None, ] * len(units) + ics ForcePartValence.add_term(self, pot(*args)) return term