Beispiel #1
0
 def Target_Terms(self, mvals, Order=0, verbose=False, customdir=None):
     ## This is the objective function; it's a dictionary containing the value, first and second derivatives
     Objective = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np,self.FF.np))}
     # Loop through the targets, stage the directories and submit the Work Queue processes.
     for Tgt in self.Targets:
         Tgt.stage(mvals, AGrad = Order >= 1, AHess = Order >= 2, customdir=customdir)
     if self.asynchronous:
         # Asynchronous evaluation of objective function and Work Queue tasks.
         # Create a list of the targets, and remove them from the list as they are finished.
         Need2Evaluate = self.Targets[:]
         # This ensures that the OrderedDict doesn't get out of order.
         for Tgt in self.Targets:
             self.ObjDict[Tgt.name] = None
         # Loop through the targets and compute the objective function for ones that are finished.
         while len(Need2Evaluate) > 0:
             for Tgt in Need2Evaluate:
                 if Tgt.wq_complete():
                     # List of functions that I can call.
                     Funcs   = [Tgt.get_X, Tgt.get_G, Tgt.get_H]
                     # Call the appropriate function
                     Ans = Funcs[Order](mvals, customdir=customdir)
                     # Print out the qualitative indicators
                     if verbose:
                         Tgt.meta_indicate(customdir=customdir)
                     # Note that no matter which order of function we call, we still increment the objective / gradient / Hessian the same way.
                     if not in_fd():
                         self.ObjDict[Tgt.name] = {'w' : Tgt.weight/self.WTot , 'x' : Ans['X']}
                     for i in range(3):
                         Objective[Letters[i]] += Ans[Letters[i]]*Tgt.weight/self.WTot
                     Need2Evaluate.remove(Tgt)
                     break
                 else:
                     pass
     else:
         wq = getWorkQueue()
         if wq != None:
             wq_wait(wq)
         for Tgt in self.Targets:
             # The first call is always done at the midpoint.
             Tgt.bSave = True
             # List of functions that I can call.
             Funcs   = [Tgt.get_X, Tgt.get_G, Tgt.get_H]
             # Call the appropriate function
             Ans = Funcs[Order](mvals, customdir=customdir)
             # Print out the qualitative indicators
             if verbose:
                 Tgt.meta_indicate(customdir=customdir)
             # Note that no matter which order of function we call, we still increment the objective / gradient / Hessian the same way.
             if not in_fd():
                 self.ObjDict[Tgt.name] = {'w' : Tgt.weight/self.WTot , 'x' : Ans['X']}
             for i in range(3):
                 Objective[Letters[i]] += Ans[Letters[i]]*Tgt.weight/self.WTot
     # The target has evaluated at least once.
     for Tgt in self.Targets:
         Tgt.evaluated = True
     # Safeguard to make sure we don't have exact zeros on Hessian diagonal
     for i in range(self.FF.np):
         if Objective['H'][i,i] == 0.0:
             Objective['H'][i,i] = 1.0
     return Objective
Beispiel #2
0
 def Target_Terms(self, mvals, Order=0, verbose=False, customdir=None):
     ## This is the objective function; it's a dictionary containing the value, first and second derivatives
     Objective = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np,self.FF.np))}
     # Loop through the targets, stage the directories and submit the Work Queue processes.
     for Tgt in self.Targets:
         Tgt.stage(mvals, AGrad = Order >= 1, AHess = Order >= 2, customdir=customdir)
     if self.asynchronous:
         # Asynchronous evaluation of objective function and Work Queue tasks.
         # Create a list of the targets, and remove them from the list as they are finished.
         Need2Evaluate = self.Targets[:]
         # This ensures that the OrderedDict doesn't get out of order.
         for Tgt in self.Targets:
             self.ObjDict[Tgt.name] = None
         # Loop through the targets and compute the objective function for ones that are finished.
         while len(Need2Evaluate) > 0:
             for Tgt in Need2Evaluate:
                 if Tgt.wq_complete():
                     # List of functions that I can call.
                     Funcs   = [Tgt.get_X, Tgt.get_G, Tgt.get_H]
                     # Call the appropriate function
                     Ans = Funcs[Order](mvals, customdir=customdir)
                     # Print out the qualitative indicators
                     if verbose:
                         Tgt.meta_indicate(customdir=customdir)
                     # Note that no matter which order of function we call, we still increment the objective / gradient / Hessian the same way.
                     if not in_fd():
                         self.ObjDict[Tgt.name] = {'w' : Tgt.weight/self.WTot , 'x' : Ans['X']}
                     for i in range(3):
                         Objective[Letters[i]] += Ans[Letters[i]]*Tgt.weight/self.WTot
                     Need2Evaluate.remove(Tgt)
                     break
                 else:
                     pass
     else:
         wq = getWorkQueue()
         if wq is not None:
             wq_wait(wq)
         for Tgt in self.Targets:
             # The first call is always done at the midpoint.
             Tgt.bSave = True
             # List of functions that I can call.
             Funcs   = [Tgt.get_X, Tgt.get_G, Tgt.get_H]
             # Call the appropriate function
             Ans = Funcs[Order](mvals, customdir=customdir)
             # Print out the qualitative indicators
             if verbose:
                 Tgt.meta_indicate(customdir=customdir)
             # Note that no matter which order of function we call, we still increment the objective / gradient / Hessian the same way.
             if not in_fd():
                 self.ObjDict[Tgt.name] = {'w' : Tgt.weight/self.WTot , 'x' : Ans['X']}
             for i in range(3):
                 Objective[Letters[i]] += Ans[Letters[i]]*Tgt.weight/self.WTot
     # The target has evaluated at least once.
     for Tgt in self.Targets:
         Tgt.evaluated = True
     # Safeguard to make sure we don't have exact zeros on Hessian diagonal
     for i in range(self.FF.np):
         if Objective['H'][i,i] == 0.0:
             Objective['H'][i,i] = 1.0
     return Objective
 def compute(mvals, p_idx=None):
     ''' Compute total objective value for each system '''
     self.FF.make(mvals)
     v_obj_list = []
     for sysname, sysopt in self.sys_opts.items():
         # ref values of each type
         vref_bonds = self.internal_coordinates[sysname]['vref_bonds']
         vref_angles = self.internal_coordinates[sysname]['vref_angles']
         vref_dihedrals = self.internal_coordinates[sysname]['vref_dihedrals']
         vref_impropers = self.internal_coordinates[sysname]['vref_impropers']
         # counts of each type
         n_bonds = len(vref_bonds)
         n_angles = len(vref_angles)
         n_dihedrals = len(vref_dihedrals)
         n_impropers = len(vref_impropers)
         # use self.system_mval_masks to skip evaluations when computing gradients
         if enable_system_mval_mask and in_fd() and (p_idx is not None) and (self.system_mval_masks[sysname][p_idx] == False):
             v_obj_list += [0] * (n_bonds + n_angles + n_dihedrals + n_impropers)
             continue
         # read denominators from system options
         bond_denom = sysopt['bond_denom']
         angle_denom = sysopt['angle_denom']
         dihedral_denom = sysopt['dihedral_denom']
         improper_denom = sysopt['improper_denom']
         # inverse demon to be scaling factors, 0 for denom 0
         scale_bond = 1.0 / bond_denom if bond_denom != 0 else 0.0
         scale_angle = 1.0 / angle_denom if angle_denom != 0 else 0.0
         scale_dihedral = 1.0 / dihedral_denom if dihedral_denom != 0 else 0.0
         scale_improper = 1.0 / improper_denom if improper_denom != 0 else 0.0
         # calculate new internal coordinates
         v_ic = self.system_driver(sysname)
         # objective contribution from bonds
         vtar_bonds = v_ic['bonds']
         diff_bond = ((vref_bonds - vtar_bonds) * scale_bond).tolist() if n_bonds > 0 else []
         # objective contribution from angles
         vtar_angles = v_ic['angles']
         diff_angle = (periodic_diff(vref_angles, vtar_angles, 360) * scale_angle).tolist() if n_angles > 0 else []
         # objective contribution from dihedrals
         vtar_dihedrals = v_ic['dihedrals']
         diff_dihedral = (periodic_diff(vref_dihedrals, vtar_dihedrals, 360) * scale_dihedral).tolist() if n_dihedrals > 0 else []
         # objective contribution from improper dihedrals
         vtar_impropers = v_ic['impropers']
         diff_improper = (periodic_diff(vref_impropers, vtar_impropers, 360) * scale_improper).tolist() if n_impropers > 0 else []
         # combine objective values into a big result list
         sys_obj_list = diff_bond + diff_angle + diff_dihedral + diff_improper
         # extend the result v_obj_list by individual terms in this system
         v_obj_list += sys_obj_list
         # save print string
         if not in_fd():
             # For printing, we group the RMSD by type
             rmsd_bond = compute_rmsd(vref_bonds, vtar_bonds)
             rmsd_angle = compute_rmsd(vref_angles, vtar_angles, v_periodic=360)
             rmsd_dihedral = compute_rmsd(vref_dihedrals, vtar_dihedrals, v_periodic=360)
             rmsd_improper = compute_rmsd(vref_impropers, vtar_impropers, v_periodic=360)
             obj_total = sum(v**2 for v in sys_obj_list)
             self.PrintDict[sysname] = "% 9.3f % 7.2f % 9.3f % 7.2f % 9.3f % 7.2f % 9.3f % 7.2f %17.3f" % (rmsd_bond, \
                 bond_denom, rmsd_angle, angle_denom, rmsd_dihedral, dihedral_denom, rmsd_improper, improper_denom, obj_total)
     return np.array(v_obj_list, dtype=float)
Beispiel #4
0
 def compute(mvals_):
     # This function has automatically assigned variable names from the interaction master file
     # Thus, all variable names in here are protected using an underscore.
     self.FF.make(mvals_)
     VectorD_ = []
     for sys_ in self.sys_opts:
         Energy_, RMSD_ = self.system_driver(sys_)
         #print "Setting %s to" % sys_, Energy_
         exec("%s = Energy_" % sys_) in locals()
         RMSDNrm_ = RMSD_ / self.rmsd_denom
         w_ = self.sys_opts[sys_][
             'rmsd_weight'] if 'rmsd_weight' in self.sys_opts[
                 sys_] else 1.0
         VectorD_.append(np.sqrt(w_) * RMSDNrm_)
         if not in_fd() and RMSD_ != 0.0:
             self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_,
                                                       w_ * RMSDNrm_**2)
     VectorE_ = []
     for inter_ in self.inter_opts:
         Calculated_ = eval(self.inter_opts[inter_]['equation'])
         Reference_ = self.inter_opts[inter_]['reference_physical']
         Delta_ = Calculated_ - Reference_
         Denom_ = self.energy_denom
         if self.cauchy:
             Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
         elif self.attenuate:
             if Reference_ < Denom_:
                 Divisor_ = Denom_
             else:
                 Divisor_ = np.sqrt(Denom_**2 +
                                    (Reference_ - Denom_)**2)
         else:
             Divisor_ = Denom_
         DeltaNrm_ = Delta_ / Divisor_
         w_ = self.inter_opts[inter_][
             'weight'] if 'weight' in self.inter_opts[inter_] else 1.0
         VectorE_.append(np.sqrt(w_) * DeltaNrm_)
         if not in_fd():
             self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (
                 Calculated_, Reference_, Delta_, w_ * DeltaNrm_**2)
         # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
     # The return value is an array of normalized interaction energy differences.
     if not in_fd():
         self.rmsd_part = np.dot(np.array(VectorD_), np.array(VectorD_))
         if len(VectorE_) > 0:
             self.energy_part = np.dot(np.array(VectorE_),
                                       np.array(VectorE_))
         else:
             self.energy_part = 0.0
     if len(VectorE_) > 0 and len(VectorD_) > 0:
         return np.array(VectorD_ + VectorE_)
     elif len(VectorD_) > 0:
         return np.array(VectorD_)
     elif len(VectorE_) > 0:
         return np.array(VectorE_)
Beispiel #5
0
 def compute(mvals_):
     # This function has automatically assigned variable names from the interaction master file
     # Thus, all variable names in here are protected using an underscore.
     self.FF.make(mvals_)
     VectorD_ = []
     for sys_ in self.sys_opts:
         Energy_, RMSD_ = self.system_driver(sys_)
         # Energies are stored in a dictionary.
         EnergyDict[sys_] = Energy_
         RMSDNrm_ = RMSD_ / self.rmsd_denom
         w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
         VectorD_.append(np.sqrt(w_)*RMSDNrm_)
         if not in_fd() and RMSD_ != 0.0:
             self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)
     VectorE_ = []
     for inter_ in self.inter_opts:
         def encloseInDictionary(matchobj):
             return 'EnergyDict["' + matchobj.group(0)+'"]'
         # Here we need to evaluate a mathematical expression of the stored variables in EnergyDict.
         # We start by enclosing every variable in EnergyDict[""] and then calling eval on it.
         evalExpr = re.sub('[A-Za-z_][A-Za-z0-9_]*', encloseInDictionary, self.inter_opts[inter_]['equation'])
         Calculated_ = eval(evalExpr)
         Reference_ = self.inter_opts[inter_]['reference_physical']
         Delta_ = Calculated_ - Reference_
         Denom_ = self.energy_denom
         if self.cauchy:
             Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
         elif self.attenuate:
             if Reference_ < Denom_:
                 Divisor_ = Denom_
             else:
                 Divisor_ = np.sqrt(Denom_**2 + (Reference_-Denom_)**2)
         else:
             Divisor_ = Denom_
         DeltaNrm_ = Delta_ / Divisor_
         w_ = self.inter_opts[inter_]['weight'] if 'weight' in self.inter_opts[inter_] else 1.0
         VectorE_.append(np.sqrt(w_)*DeltaNrm_)
         if not in_fd():
             self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (Calculated_, Reference_, Delta_, w_*DeltaNrm_**2)
         # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
     # The return value is an array of normalized interaction energy differences.
     if not in_fd():
         self.rmsd_part = np.dot(np.array(VectorD_),np.array(VectorD_))
         if len(VectorE_) > 0:
             self.energy_part = np.dot(np.array(VectorE_),np.array(VectorE_))
         else:
             self.energy_part = 0.0
     if len(VectorE_) > 0 and len(VectorD_) > 0:
         return np.array(VectorD_ + VectorE_)
     elif len(VectorD_) > 0:
         return np.array(VectorD_)
     elif len(VectorE_) > 0:
         return np.array(VectorE_)
Beispiel #6
0
 def compute(mvals_):
     # This function has automatically assigned variable names from the interaction master file
     # Thus, all variable names in here are protected using an underscore.
     self.FF.make(mvals_)
     VectorD_ = []
     for sys_ in self.sys_opts:
         Energy_, RMSD_ = self.system_driver(sys_)
         # Energies are stored in a dictionary.
         EnergyDict[sys_] = Energy_
         RMSDNrm_ = RMSD_ / self.rmsd_denom
         w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
         VectorD_.append(np.sqrt(w_)*RMSDNrm_)
         if not in_fd() and RMSD_ != 0.0:
             self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)
     VectorE_ = []
     for inter_ in self.inter_opts:
         def encloseInDictionary(matchobj):
             return 'EnergyDict["' + matchobj.group(0)+'"]'
         # Here we need to evaluate a mathematical expression of the stored variables in EnergyDict.
         # We start by enclosing every variable in EnergyDict[""] and then calling eval on it.
         evalExpr = re.sub('[A-Za-z_][A-Za-z0-9_]*', encloseInDictionary, self.inter_opts[inter_]['equation'])
         Calculated_ = eval(evalExpr)
         Reference_ = self.inter_opts[inter_]['reference_physical']
         Delta_ = Calculated_ - Reference_
         Denom_ = self.energy_denom
         if self.attenuate:
             if Reference_ < Denom_:
                 Divisor_ = Denom_
             else:
                 Divisor_ = np.sqrt(Denom_**2 + (Reference_-Denom_)**2)
         else:
             Divisor_ = Denom_
         DeltaNrm_ = Delta_ / Divisor_
         w_ = self.inter_opts[inter_]['weight'] if 'weight' in self.inter_opts[inter_] else 1.0
         VectorE_.append(np.sqrt(w_)*DeltaNrm_)
         if not in_fd():
             self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (Calculated_, Reference_, Delta_, w_*DeltaNrm_**2)
         # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
     # The return value is an array of normalized interaction energy differences.
     if not in_fd():
         self.rmsd_part = np.dot(np.array(VectorD_),np.array(VectorD_))
         if len(VectorE_) > 0:
             self.energy_part = np.dot(np.array(VectorE_),np.array(VectorE_))
         else:
             self.energy_part = 0.0
     if len(VectorE_) > 0 and len(VectorD_) > 0:
         return np.array(VectorD_ + VectorE_)
     elif len(VectorD_) > 0:
         return np.array(VectorD_)
     elif len(VectorE_) > 0:
         return np.array(VectorE_)
Beispiel #7
0
 def compute(mvals_):
     # This function has automatically assigned variable names from the interaction master file
     # Thus, all variable names in here are protected using an underscore.
     self.FF.make(mvals_)
     VectorD_ = []
     for sys_ in self.sys_opts:
         Energy_, RMSD_ = self.system_driver(sys_)
         #print "Setting %s to" % sys_, Energy_
         exec("%s = Energy_" % sys_) in locals()
         RMSDNrm_ = RMSD_ / self.rmsd_denom
         w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
         VectorD_.append(np.sqrt(w_)*RMSDNrm_)
         if not in_fd() and RMSD_ != 0.0:
             self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)
     VectorE_ = []
     for inter_ in self.inter_opts:
         Calculated_ = eval(self.inter_opts[inter_]['equation'])
         Reference_ = self.inter_opts[inter_]['reference_physical']
         Delta_ = Calculated_ - Reference_
         Denom_ = self.energy_denom
         if self.cauchy:
             Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
         elif self.attenuate:
             if Reference_ < Denom_:
                 Divisor_ = Denom_
             else:
                 Divisor_ = np.sqrt(Denom_**2 + (Reference_-Denom_)**2)
         else:
             Divisor_ = Denom_
         DeltaNrm_ = Delta_ / Divisor_
         w_ = self.inter_opts[inter_]['weight'] if 'weight' in self.inter_opts[inter_] else 1.0
         VectorE_.append(np.sqrt(w_)*DeltaNrm_)
         if not in_fd():
             self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (Calculated_, Reference_, Delta_, w_*DeltaNrm_**2)
         # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
     # The return value is an array of normalized interaction energy differences.
     if not in_fd():
         self.rmsd_part = np.dot(np.array(VectorD_),np.array(VectorD_))
         if len(VectorE_) > 0:
             self.energy_part = np.dot(np.array(VectorE_),np.array(VectorE_))
         else:
             self.energy_part = 0.0
     if len(VectorE_) > 0 and len(VectorD_) > 0:
         return np.array(VectorD_ + VectorE_)
     elif len(VectorD_) > 0:
         return np.array(VectorD_)
     elif len(VectorE_) > 0:
         return np.array(VectorE_)
Beispiel #8
0
 def get(self, mvals, AGrad=False, AHess=False):
     """ Evaluate objective function. """
     Answer = {
         'X': 0.0,
         'G': np.zeros(self.FF.np),
         'H': np.zeros((self.FF.np, self.FF.np))
     }
     if self.hfemode.lower() == 'single' or self.hfemode.lower() == 'sp':
         D, dD = self.get_sp(mvals, AGrad, AHess)
     elif self.hfemode.lower() == 'ti2':
         D, dD = self.get_ti2(mvals, AGrad, AHess)
     elif self.hfemode.lower() in ['exp_gas', 'exp_liq', 'exp_both']:
         D, dD = self.get_exp(mvals, AGrad, AHess)
     Answer['X'] = np.dot(D, D) / self.denom**2 / (np.sum(self.whfe)
                                                   if self.normalize else 1)
     for p in self.pgrad:
         Answer['G'][p] = 2 * np.dot(D, dD[p, :]) / self.denom**2 / (np.sum(
             self.whfe) if self.normalize else 1)
         for q in self.pgrad:
             Answer['H'][p, q] = 2 * np.dot(
                 dD[p, :], dD[q, :]) / self.denom**2 / (np.sum(
                     self.whfe) if self.normalize else 1)
     if not in_fd():
         self.calc = self.hfe_dict
         if hasattr(self, 'hfe_err'):
             self.calc_err = self.hfe_err
         self.objective = Answer['X']
     return Answer
Beispiel #9
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':zeros(self.FF.np, dtype=float), 'H':zeros((self.FF.np, self.FF.np), dtype=float)}
        def get_momvals(mvals_):
            self.FF.make(mvals_)
            moments = self.moments_driver()
            # Unpack from dictionary.
            return self.unpack_moments(moments)

        self.FF.make(mvals)
        ref_momvals = self.unpack_moments(self.ref_moments)
        calc_moments = self.moments_driver()
        calc_momvals = self.unpack_moments(calc_moments)

        D = calc_momvals - ref_momvals
        dV = zeros((self.FF.np,len(calc_momvals)),dtype=float)

        if AGrad or AHess:
            for p in range(self.FF.np):
                dV[p,:], _ = f12d3p(fdwrap(get_momvals, mvals, p), h = self.h, f0 = calc_momvals)
                
        Answer['X'] = dot(D,D)
        for p in range(self.FF.np):
            Answer['G'][p] = 2*dot(D, dV[p,:])
            for q in range(self.FF.np):
                Answer['H'][p,q] = 2*dot(dV[p,:], dV[q,:])

        if not in_fd():
            self.FF.make(mvals)
            self.calc_moments = calc_moments
            self.objective = Answer['X']

        return Answer
Beispiel #10
0
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            eigvecs_nrm, eigvecs_nrm_mw = self.process_vectors(eigvecs)
            # The overlap metric may take into account some frequency differences
            dev = np.array([[(np.abs(i-j)/1000)/(1.0+np.abs(i-j)/1000) for j in self.ref_eigvals] for i in eigvals])
            for i in range(dev.shape[0]):
                dev[i, :] /= max(dev[i, :])

            if self.reassign in ['permute', 'overlap']:
                # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
                # that are mapped to the row numbers (calculated mode numbers)
                if self.reassign == 'permute':
                    a = np.array([[int(1e6*(1.0-np.dot(v1.flatten(),v2.flatten())**2)) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    c2r = Assign(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    a = np.array([[(1.0-np.dot(v1.flatten(),v2.flatten())**2) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    a += dev
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs_nrm_mw = eigvecs_nrm_mw[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_nrm_mw_p = []
                    for j in c2r:
                        eigvecs_nrm_mw_p.append(eigvecs_nrm_mw[j])
                    eigvecs_nrm_mw = np.array(eigvecs_nrm_mw_p)
                self.overlaps = np.array([np.abs(np.dot(v1.flatten(),v2.flatten())) for v1, v2 in zip(self.ref_eigvecs_nrm, eigvecs_nrm_mw)])
            return eigvals
Beispiel #11
0
 def driver(self):
     ## Actually run PSI4.
     if not in_fd() and CheckBasis():
         logger.info("Now checking for linear dependencies.\n")
         _exec("cp %s %s.bak" % (self.GBSfnm, self.GBSfnm), print_command=False)
         ln0 = self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save)
         o = wopen(".lindep.dat")
         for line in open(self.DATfnm).readlines():
             s = line.split("#")[0].split()
             if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower() == 'file':
                 print >> o, "basis file %s" % self.GBSfnm
             else:
                 print >> o, line,
         o.close()
         _exec("mv .lindep.dat %s" % self.DATfnm, print_command=False)
         _exec("psi4 %s" % self.DATfnm, print_command=False)
         LI = GBS_Reader()
         LI_lines = {}
         ## Read in the commented linindep.gbs file and ensure that these same lines are commented in the new .gbs file
         for line in open('linindep.gbs'):
             LI.feed(line,linindep=True)
             key = '.'.join([str(i) for i in LI.element,LI.amom,LI.basis_number[LI.element],LI.contraction_number])
             if LI.isdata:
                 if key in LI_lines:
                     logger.info("Duplicate key found:\n")
                     logger.info("%s\n" % key)
                     logger.info(str(LI_lines[key]))
                     logger.info(line)
                     warn_press_key("In %s, the LI_lines dictionary should not contain repeated keys!" % __file__)
                 LI_lines[key] = (line, LI.destroy)
Beispiel #12
0
 def get_eigvals(mvals_):
     self.FF.make(mvals_)
     eigvals, eigvecs = self.vibration_driver()
     eigvecs_nrm, eigvecs_nrm_mw = self.process_vectors(eigvecs)
     if self.reassign in ['permute', 'overlap']:
         a = np.array([[int(1e6*(1.0-np.dot(v1.flatten(),v2.flatten())**2)) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
         # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
         # that are mapped to the row numbers (calculated mode numbers)
         if self.reassign == 'permute':
             c2r = Assign(a)
             eigvals = eigvals[c2r]
         elif self.reassign == 'overlap':
             c2r = np.argmin(a, axis=0)
             eigvals_p = []
             for j in c2r:
                 eigvals_p.append(eigvals[j])
             eigvals = np.array(eigvals_p)
     if not in_fd():
         if self.reassign == 'permute':
             eigvecs_nrm_mw = eigvecs_nrm_mw[c2r]
         elif self.reassign == 'overlap':
             self.c2r = c2r
             eigvecs_nrm_mw_p = []
             for j in c2r:
                 eigvecs_nrm_mw_p.append(eigvecs_nrm_mw[j])
             eigvecs_nrm_mw = np.array(eigvecs_nrm_mw_p)
         self.overlaps = np.array([np.abs(np.dot(v1.flatten(),v2.flatten())) for v1, v2 in zip(self.ref_eigvecs_nrm, eigvecs_nrm_mw)])
     return eigvals
Beispiel #13
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':zeros(self.FF.np, dtype=float), 'H':zeros((self.FF.np, self.FF.np), dtype=float)}
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            # Put reference eigenvectors in the rows and calculated eigenvectors in the columns.
            # Square the dot product (pointing in opposite direction is still the same eigenvector)
            # Convert to integer for the "Assign" subroutine, subtract from a million.
            a = array([[int(1e6*(1.0-min(1.0,dot(v1.flatten(),v2.flatten())**2))) for v2 in self.ref_eigvecs] for v1 in eigvecs])
            # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
            # that are mapped to the row numbers (calculated mode numbers)
            c2r = Assign(a)
            return eigvals[c2r]

        calc_eigvals = get_eigvals(mvals)
        D = calc_eigvals - self.ref_eigvals
        dV = zeros((self.FF.np,len(calc_eigvals)),dtype=float)

        if AGrad or AHess:
            for p in range(self.FF.np):
                dV[p,:], _ = f12d3p(fdwrap(get_eigvals, mvals, p), h = self.h, f0 = calc_eigvals)
                
        Answer['X'] = dot(D,D) / self.denom**2
        for p in range(self.FF.np):
            Answer['G'][p] = 2*dot(D, dV[p,:]) / self.denom**2
            for q in range(self.FF.np):
                Answer['H'][p,q] = 2*dot(dV[p,:], dV[q,:]) / self.denom**2

        if not in_fd():
            self.calc_eigvals = calc_eigvals
            self.objective = Answer['X']

        return Answer
Beispiel #14
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}
        def get_momvals(mvals_):
            self.FF.make(mvals_)
            moments = self.engine.multipole_moments(polarizability='polarizability' in self.ref_moments, optimize=self.optimize_geometry)
            # Unpack from dictionary.
            return self.unpack_moments(moments)

        self.FF.make(mvals)
        ref_momvals = self.unpack_moments(self.ref_moments)
        calc_moments = self.engine.multipole_moments(polarizability='polarizability' in self.ref_moments, optimize=self.optimize_geometry)
        calc_momvals = self.unpack_moments(calc_moments)

        D = calc_momvals - ref_momvals
        dV = np.zeros((self.FF.np,len(calc_momvals)))

        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(get_momvals, mvals, p), h = self.h, f0 = calc_momvals)
                
        Answer['X'] = np.dot(D,D)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(D, dV[p,:])
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:])

        if not in_fd():
            self.calc_moments = calc_moments
            self.objective = Answer['X']

        return Answer
Beispiel #15
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        if not hasattr(self, 'ref_eigvecs_nrm'):
            self.ref_eigvecs_nrm, self.ref_eigvecs_nrm_mw = self.process_vectors(self.ref_eigvecs)
        
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            eigvecs_nrm, eigvecs_nrm_mw = self.process_vectors(eigvecs)
            # The overlap metric may take into account some frequency differences
            dev = np.array([[(np.abs(i-j)/1000)/(1.0+np.abs(i-j)/1000) for j in self.ref_eigvals] for i in eigvals])
            for i in range(dev.shape[0]):
                dev[i, :] /= max(dev[i, :])

            if self.reassign in ['permute', 'overlap']:
                # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
                # that are mapped to the row numbers (calculated mode numbers)
                if self.reassign == 'permute':
                    a = np.array([[int(1e6*(1.0-np.dot(v1.flatten(),v2.flatten())**2)) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    row, c2r = optimize.linear_sum_assignment(a)
                    # Commented out dependency on assignment code
                    # c2r = Assign(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    a = np.array([[(1.0-np.dot(v1.flatten(),v2.flatten())**2) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    a += dev
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs_nrm_mw = eigvecs_nrm_mw[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_nrm_mw_p = []
                    for j in c2r:
                        eigvecs_nrm_mw_p.append(eigvecs_nrm_mw[j])
                    eigvecs_nrm_mw = np.array(eigvecs_nrm_mw_p)
                self.overlaps = np.array([np.abs(np.dot(v1.flatten(),v2.flatten())) for v1, v2 in zip(self.ref_eigvecs_nrm, eigvecs_nrm_mw)])
            return eigvals

        calc_eigvals = get_eigvals(mvals)
        D = calc_eigvals - self.ref_eigvals
        dV = np.zeros((self.FF.np,len(calc_eigvals)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(get_eigvals, mvals, p), h = self.h, f0 = calc_eigvals)
        Answer['X'] = np.dot(D,D) / self.denom**2 / (len(D) if self.normalize else 1)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(D, dV[p,:]) / self.denom**2 / (len(D) if self.normalize else 1)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:]) / self.denom**2 / (len(D) if self.normalize else 1)
        if not in_fd():
            self.calc_eigvals = calc_eigvals
            self.objective = Answer['X']
        return Answer
Beispiel #16
0
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            eigvecs_nrm, eigvecs_nrm_mw = self.process_vectors(eigvecs)
            # The overlap metric may take into account some frequency differences
            dev = np.array([[(np.abs(i-j)/1000)/(1.0+np.abs(i-j)/1000) for j in self.ref_eigvals] for i in eigvals])
            for i in range(dev.shape[0]):
                dev[i, :] /= max(dev[i, :])

            if self.reassign in ['permute', 'overlap']:
                # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
                # that are mapped to the row numbers (calculated mode numbers)
                if self.reassign == 'permute':
                    a = np.array([[int(1e6*(1.0-np.dot(v1.flatten(),v2.flatten())**2)) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    c2r = Assign(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    a = np.array([[(1.0-np.dot(v1.flatten(),v2.flatten())**2) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    a += dev
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs_nrm_mw = eigvecs_nrm_mw[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_nrm_mw_p = []
                    for j in c2r:
                        eigvecs_nrm_mw_p.append(eigvecs_nrm_mw[j])
                    eigvecs_nrm_mw = np.array(eigvecs_nrm_mw_p)
                self.overlaps = np.array([np.abs(np.dot(v1.flatten(),v2.flatten())) for v1, v2 in zip(self.ref_eigvecs_nrm, eigvecs_nrm_mw)])
            return eigvals
Beispiel #17
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}
        def get_momvals(mvals_):
            self.FF.make(mvals_)
            moments = self.engine.multipole_moments(polarizability='polarizability' in self.ref_moments, optimize=self.optimize_geometry)
            # Unpack from dictionary.
            return self.unpack_moments(moments)

        self.FF.make(mvals)
        ref_momvals = self.unpack_moments(self.ref_moments)
        calc_moments = self.engine.multipole_moments(polarizability='polarizability' in self.ref_moments, optimize=self.optimize_geometry)
        calc_momvals = self.unpack_moments(calc_moments)

        D = calc_momvals - ref_momvals
        dV = np.zeros((self.FF.np,len(calc_momvals)))

        if AGrad or AHess:
            for p in range(self.FF.np):
                dV[p,:], _ = f12d3p(fdwrap(get_momvals, mvals, p), h = self.h, f0 = calc_momvals)
                
        Answer['X'] = np.dot(D,D)
        for p in range(self.FF.np):
            Answer['G'][p] = 2*np.dot(D, dV[p,:])
            for q in range(self.FF.np):
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:])

        if not in_fd():
            self.calc_moments = calc_moments
            self.objective = Answer['X']

        return Answer
Beispiel #18
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        if not hasattr(self, 'ref_eigvecs_nrm'):
            self.ref_eigvecs_nrm, self.ref_eigvecs_nrm_mw = self.process_vectors(self.ref_eigvecs)
        
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            eigvecs_nrm, eigvecs_nrm_mw = self.process_vectors(eigvecs)
            # The overlap metric may take into account some frequency differences
            dev = np.array([[(np.abs(i-j)/1000)/(1.0+np.abs(i-j)/1000) for j in self.ref_eigvals] for i in eigvals])
            for i in range(dev.shape[0]):
                dev[i, :] /= max(dev[i, :])

            if self.reassign in ['permute', 'overlap']:
                # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
                # that are mapped to the row numbers (calculated mode numbers)
                if self.reassign == 'permute':
                    a = np.array([[int(1e6*(1.0-np.dot(v1.flatten(),v2.flatten())**2)) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    c2r = Assign(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    a = np.array([[(1.0-np.dot(v1.flatten(),v2.flatten())**2) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                    a += dev
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs_nrm_mw = eigvecs_nrm_mw[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_nrm_mw_p = []
                    for j in c2r:
                        eigvecs_nrm_mw_p.append(eigvecs_nrm_mw[j])
                    eigvecs_nrm_mw = np.array(eigvecs_nrm_mw_p)
                self.overlaps = np.array([np.abs(np.dot(v1.flatten(),v2.flatten())) for v1, v2 in zip(self.ref_eigvecs_nrm, eigvecs_nrm_mw)])
            return eigvals

        calc_eigvals = get_eigvals(mvals)
        D = calc_eigvals - self.ref_eigvals
        dV = np.zeros((self.FF.np,len(calc_eigvals)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(get_eigvals, mvals, p), h = self.h, f0 = calc_eigvals)
        Answer['X'] = np.dot(D,D) / self.denom**2 / (len(D) if self.normalize else 1)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(D, dV[p,:]) / self.denom**2 / (len(D) if self.normalize else 1)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:]) / self.denom**2 / (len(D) if self.normalize else 1)
        if not in_fd():
            self.calc_eigvals = calc_eigvals
            self.objective = Answer['X']
        return Answer
Beispiel #19
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            # The overlap metric may take into account some frequency differences.
            # Here, an element of dev is equal to 2/3 if (for example) the frequencies differ by 1000.
            dev = np.array([[(np.abs(i-j)/1000)/(1.0+np.abs(i-j)/1000) for j in eigvals] for i in self.ref_eigvals])
            for i in range(dev.shape[0]):
                dev[i, :] /= max(dev[i, :])

            if self.reassign in ['permute', 'overlap']:
                # The elements of "a" matrix are the column numbers (reference mode numbers) 
                # that are mapped to the row numbers (calculated mode numbers).
                # Highly similar eigenvectors are assigned small values because
                # the assignment problem is a cost minimization problem.
                a = np.array([[(1.0-vib_overlap(self.engine, v1, v2)) for v2 in eigvecs] for v1 in self.ref_eigvecs])
                a += dev
                if self.reassign == 'permute':
                    row, c2r = optimize.linear_sum_assignment(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs = eigvecs[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_p = []
                    for j in c2r:
                        eigvecs_p.append(eigvecs[j])
                    eigvecs = np.array(eigvecs_p)
                self.overlaps = np.array([vib_overlap(self.engine, v1, v2) for v1, v2 in zip(self.ref_eigvecs, eigvecs)])
            return eigvals

        calc_eigvals = get_eigvals(mvals)
        D = calc_eigvals - self.ref_eigvals
        dV = np.zeros((self.FF.np,len(calc_eigvals)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(get_eigvals, mvals, p), h = self.h, f0 = calc_eigvals)
        Answer['X'] = np.dot(D,D) / self.denom**2 / (len(D) if self.normalize else 1)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(D, dV[p,:]) / self.denom**2 / (len(D) if self.normalize else 1)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:]) / self.denom**2 / (len(D) if self.normalize else 1)
        if not in_fd():
            self.calc_eigvals = calc_eigvals
            self.objective = Answer['X']
        return Answer
Beispiel #20
0
    def meta_get(self, mvals, AGrad=False, AHess=False, customdir=None):
        """ 
        Wrapper around the get function.  
        Create the directory for the target, and then calls 'get'.
        If we are reading existing data, go into the appropriate read directory and call read() instead.
        The 'get' method should not worry about the directory that it's running in.
        
        """
        ## Directory of the current iteration; if not None, then the simulation runs under
        ## temp/target_name/iteration_number
        ## The 'customdir' is customizable and can go below anything
        cwd = os.getcwd()

        absgetdir = os.path.join(self.root, self.tempdir)
        if Counter() is not None:
            # Not expecting more than ten thousand iterations
            if Counter() > 10000:
                logger.error(
                    'Cannot handle more than 10000 iterations due to current directory structure.  Consider revising code.\n'
                )
                raise RuntimeError
            iterdir = "iter_%04i" % Counter()
            absgetdir = os.path.join(absgetdir, iterdir)
        if customdir is not None:
            absgetdir = os.path.join(absgetdir, customdir)

        if not os.path.exists(absgetdir):
            os.makedirs(absgetdir)
        os.chdir(absgetdir)
        self.link_from_tempdir(absgetdir)
        self.rundir = absgetdir.replace(self.root + '/', '')
        ## Read existing information from disk (i.e. when recovering an aborted run)
        # Note that reading information is not supported for custom folders (e.g. microiterations during search)
        if self.rd is not None and (
                not self.evaluated
        ) and self.read_objective and customdir is None:
            os.chdir(self.absrd())
            logger.info("Reading objective function information from %s\n" %
                        os.getcwd())
            Answer = self.read(mvals, AGrad, AHess)
            os.chdir(absgetdir)
        else:
            ## Evaluate the objective function.
            Answer = self.get(mvals, AGrad, AHess)
            if self.write_objective:
                forcebalance.nifty.lp_dump(Answer, 'objective.p')

        ## Save the force field files to this directory, so that it
        ## reflects the objective function and properties that were
        ## printed out.
        if not in_fd():
            self.FF.make(mvals)

        os.chdir(cwd)

        return Answer
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        # If the weight is zero, turn all derivatives off.
        if (self.weight == 0.0):
            AGrad = False
            AHess = False

        def callM(mvals_, dielectric=False):
            logger.info("\r")
            pvals = self.FF.make(mvals_)
            return self.engine.interaction_energy(self.select1, self.select2)

        logger.info("Executing\r")
        emm = callM(mvals)

        D = emm - self.eqm
        dV = np.zeros((self.FF.np,len(emm)))

        # Dump interaction energies to disk.
        np.savetxt('M.txt',emm)
        np.savetxt('Q.txt',self.eqm)

        # Do the finite difference derivative.
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = emm)
            # Create the force field one last time.
            pvals  = self.FF.make(mvals)

        Answer['X'] = np.dot(self.prefactor*D/self.divisor,D/self.divisor)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(self.prefactor*D/self.divisor, dV[p,:]/self.divisor)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(self.prefactor*dV[p,:]/self.divisor, dV[q,:]/self.divisor)

        if not in_fd():
            self.emm = emm
            self.objective = Answer['X']

        ## QYD: try to clean up OpenMM engine.simulation objects to free up GPU memory
        try:
            if self.engine.name == 'openmm':
                if hasattr(self.engine, 'simulation'): del self.engine.simulation
                if hasattr(self.engine, 'A'): del self.engine.A
                if hasattr(self.engine, 'B'): del self.engine.B
        except:
            pass

        return Answer
Beispiel #22
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        # If the weight is zero, turn all derivatives off.
        if (self.weight == 0.0):
            AGrad = False
            AHess = False

        def callM(mvals_, dielectric=False):
            logger.info("\r")
            pvals = self.FF.make(mvals_)
            return self.engine.interaction_energy(self.select1, self.select2)

        logger.info("Executing\r")
        emm = callM(mvals)

        D = emm - self.eqm
        dV = np.zeros((self.FF.np,len(emm)))

        # Dump interaction energies to disk.
        np.savetxt('M.txt',emm)
        np.savetxt('Q.txt',self.eqm)

        # Do the finite difference derivative.
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = emm)
            # Create the force field one last time.
            pvals  = self.FF.make(mvals)

        Answer['X'] = np.dot(self.prefactor*D/self.divisor,D/self.divisor)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(self.prefactor*D/self.divisor, dV[p,:]/self.divisor)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(self.prefactor*dV[p,:]/self.divisor, dV[q,:]/self.divisor)

        if not in_fd():
            self.emm = emm
            self.objective = Answer['X']

        ## QYD: try to clean up OpenMM engine.simulation objects to free up GPU memory
        try:
            if self.engine.name == 'openmm':
                if hasattr(self.engine, 'simulation'): del self.engine.simulation
                if hasattr(self.engine, 'A'): del self.engine.A
                if hasattr(self.engine, 'B'): del self.engine.B
        except:
            pass

        return Answer
Beispiel #23
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        if not hasattr(self, 'ref_eigvecs_nrm'):
            self.ref_eigvecs_nrm, self.ref_eigvecs_nrm_mw = self.process_vectors(self.ref_eigvecs)
        
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            eigvecs_nrm, eigvecs_nrm_mw = self.process_vectors(eigvecs)
            if self.reassign in ['permute', 'overlap']:
                a = np.array([[int(1e6*(1.0-np.dot(v1.flatten(),v2.flatten())**2)) for v2 in self.ref_eigvecs_nrm] for v1 in eigvecs_nrm_mw])
                # In the matrix that we constructed, these are the column numbers (reference mode numbers) 
                # that are mapped to the row numbers (calculated mode numbers)
                if self.reassign == 'permute':
                    c2r = Assign(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs_nrm_mw = eigvecs_nrm_mw[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_nrm_mw_p = []
                    for j in c2r:
                        eigvecs_nrm_mw_p.append(eigvecs_nrm_mw[j])
                    eigvecs_nrm_mw = np.array(eigvecs_nrm_mw_p)
                self.overlaps = np.array([np.abs(np.dot(v1.flatten(),v2.flatten())) for v1, v2 in zip(self.ref_eigvecs_nrm, eigvecs_nrm_mw)])
            return eigvals

        calc_eigvals = get_eigvals(mvals)
        D = calc_eigvals - self.ref_eigvals
        dV = np.zeros((self.FF.np,len(calc_eigvals)))
        if AGrad or AHess:
            for p in range(self.FF.np):
                dV[p,:], _ = f12d3p(fdwrap(get_eigvals, mvals, p), h = self.h, f0 = calc_eigvals)
        Answer['X'] = np.dot(D,D) / self.denom**2
        for p in range(self.FF.np):
            Answer['G'][p] = 2*np.dot(D, dV[p,:]) / self.denom**2
            for q in range(self.FF.np):
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:]) / self.denom**2
        if not in_fd():
            self.calc_eigvals = calc_eigvals
            self.objective = Answer['X']
        return Answer
Beispiel #24
0
    def meta_get(self, mvals, AGrad=False, AHess=False, customdir=None):
        """ 
        Wrapper around the get function.  
        Create the directory for the target, and then calls 'get'.
        If we are reading existing data, go into the appropriate read directory and call read() instead.
        The 'get' method should not worry about the directory that it's running in.
        
        """
        ## Directory of the current iteration; if not None, then the simulation runs under
        ## temp/target_name/iteration_number
        ## The 'customdir' is customizable and can go below anything
        cwd = os.getcwd()
        
        absgetdir = os.path.join(self.root,self.tempdir)
        if Counter() is not None:
            # Not expecting more than ten thousand iterations
            if Counter() > 10000:
                logger.error('Cannot handle more than 10000 iterations due to current directory structure.  Consider revising code.\n')
                raise RuntimeError
            iterdir = "iter_%04i" % Counter()
            absgetdir = os.path.join(absgetdir,iterdir)
        if customdir is not None:
            absgetdir = os.path.join(absgetdir,customdir)

        if not os.path.exists(absgetdir):
            os.makedirs(absgetdir)
        os.chdir(absgetdir)
        self.link_from_tempdir(absgetdir)
        self.rundir = absgetdir.replace(self.root+'/','')
        ## Read existing information from disk (i.e. when recovering an aborted run)
        # Note that reading information is not supported for custom folders (e.g. microiterations during search)
        if self.rd is not None and (not self.evaluated) and self.read_objective and customdir is None:
            os.chdir(self.absrd())
            logger.info("Reading objective function information from %s\n" % os.getcwd())
            Answer = self.read(mvals, AGrad, AHess)
            os.chdir(absgetdir)
        else:
            ## Evaluate the objective function.
            Answer = self.get(mvals, AGrad, AHess)
            if self.write_objective:
                forcebalance.nifty.lp_dump(Answer, 'objective.p')

        ## Save the force field files to this directory, so that it
        ## reflects the objective function and properties that were
        ## printed out.
        if not in_fd(): 
            self.FF.make(mvals)

        os.chdir(cwd)
        
        return Answer
Beispiel #25
0
 def Full(self, mvals, Order=0, verbose=False):
     Objective = self.Target_Terms(mvals, Order, verbose)
     ## Compute the penalty function.
     Extra = self.Penalty.compute(mvals,Objective)
     Objective['X0'] = Objective['X']
     Objective['G0'] = Objective['G'].copy()
     Objective['H0'] = Objective['H'].copy()
     if not in_fd():
         self.ObjDict['Regularization'] = {'w' : 1.0, 'x' : Extra[0]}
         if verbose:
             self.Indicate()
     for i in range(3):
         Objective[Letters[i]] += Extra[i]
     return Objective
Beispiel #26
0
 def Full(self, mvals, Order=0, verbose=False):
     Objective = self.Target_Terms(mvals, Order, verbose)
     ## Compute the penalty function.
     Extra = self.Penalty.compute(mvals, Objective)
     Objective['X0'] = Objective['X']
     Objective['G0'] = Objective['G'].copy()
     Objective['H0'] = Objective['H'].copy()
     if not in_fd():
         self.ObjDict['Regularization'] = {'w': 1.0, 'x': Extra[0]}
         if verbose:
             self.Indicate()
     for i in range(3):
         Objective[Letters[i]] += Extra[i]
     return Objective
Beispiel #27
0
    def stage(self,
              mvals,
              AGrad=False,
              AHess=False,
              use_iterdir=True,
              customdir=None,
              firstIteration=False):
        """

        Stages the directory for the target, and then launches Work Queue processes if any.
        The 'get' method should not worry about the directory that it's running in.

        """
        if self.sleepy > 0:
            logger.info("Sleeping for %i seconds as directed...\n" %
                        self.sleepy)
            time.sleep(self.sleepy)
        ## Directory of the current iteration; if not None, then the simulation runs under
        ## temp/target_name/iteration_number
        ## The 'customdir' is customizable and can go below anything
        cwd = os.getcwd()

        absgetdir = os.path.join(self.root, self.tempdir)
        if use_iterdir and Counter() is not None:
            ## Not expecting more than ten thousand iterations
            iterdir = "iter_%04i" % Counter()
            absgetdir = os.path.join(absgetdir, iterdir)
        if customdir is not None:
            absgetdir = os.path.join(absgetdir, customdir)
        ## Go into the directory where get() will be executed.
        if not os.path.exists(absgetdir):
            os.makedirs(absgetdir)
        os.chdir(absgetdir)
        self.link_from_tempdir(absgetdir)
        ## Write mathematical parameters to file; will be used to checkpoint calculation.
        if not in_fd():
            np.savetxt('mvals.txt', mvals)
        ## Read in file that specifies which derivatives may be skipped.
        if Counter() >= self.zerograd and self.zerograd >= 0:
            self.read_0grads()
        self.rundir = absgetdir.replace(self.root + '/', '')
        ## Submit jobs to the Work Queue.
        if self.rd is None or (not firstIteration):
            self.submit_jobs(mvals, AGrad, AHess)
        elif customdir is not None:
            # Allows us to submit micro-iteration jobs for remote targets
            self.submit_jobs(mvals, AGrad, AHess)
        os.chdir(cwd)

        return
Beispiel #28
0
 def get(self, mvals, AGrad=False, AHess=False):
     """ Evaluate objective function. """
     Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}
     if self.hfemode.lower() == 'single' or self.hfemode.lower() == 'sp':
         D, dD = self.get_sp(mvals, AGrad, AHess)
     elif self.hfemode.lower() == 'ti2':
         D, dD = self.get_ti2(mvals, AGrad, AHess)
     Answer['X'] = np.dot(D,D) / self.denom**2 / (np.sum(self.whfe) if self.normalize else 1)
     for p in self.pgrad:
         Answer['G'][p] = 2*np.dot(D, dD[p,:]) / self.denom**2 / (np.sum(self.whfe) if self.normalize else 1)
         for q in self.pgrad:
             Answer['H'][p,q] = 2*np.dot(dD[p,:], dD[q,:]) / self.denom**2 / (np.sum(self.whfe) if self.normalize else 1)
     if not in_fd():
         self.calc = self.hfe_dict
         self.objective = Answer['X']
     return Answer
Beispiel #29
0
 def Full(self, vals, Order=0, verbose=False, customdir=None):
     Objective = self.Target_Terms(vals, Order, verbose, customdir)
     ## Compute the penalty function.
     if self.FF.use_pvals:
         Extra = self.Penalty.compute(self.FF.create_mvals(vals), Objective)
     else:
         Extra = self.Penalty.compute(vals, Objective)
     Objective['X0'] = Objective['X']
     Objective['G0'] = Objective['G'].copy()
     Objective['H0'] = Objective['H'].copy()
     if not in_fd():
         self.ObjDict['Regularization'] = {'w': 1.0, 'x': Extra[0]}
         if verbose:
             self.Indicate()
     for i in range(3):
         Objective[Letters[i]] += Extra[i]
     return Objective
Beispiel #30
0
 def Full(self, vals, Order=0, verbose=False, customdir=None):
     Objective = self.Target_Terms(vals, Order, verbose, customdir)
     ## Compute the penalty function.
     if self.FF.use_pvals:
         Extra = self.Penalty.compute(self.FF.create_mvals(vals),Objective)
     else:
         Extra = self.Penalty.compute(vals,Objective)
     Objective['X0'] = Objective['X']
     Objective['G0'] = Objective['G'].copy()
     Objective['H0'] = Objective['H'].copy()
     if not in_fd():
         self.ObjDict['Regularization'] = {'w' : 1.0, 'x' : Extra[0]}
         if verbose:
             self.Indicate()
     for i in range(3):
         Objective[Letters[i]] += Extra[i]
     return Objective
Beispiel #31
0
        def get_eigvals(mvals_):
            self.FF.make(mvals_)
            eigvals, eigvecs = self.vibration_driver()
            # The overlap metric may take into account some frequency differences.
            # Here, an element of dev is equal to 2/3 if (for example) the frequencies differ by 1000.
            dev = np.array([[
                (np.abs(i - j) / 1000) / (1.0 + np.abs(i - j) / 1000)
                for j in eigvals
            ] for i in self.ref_eigvals])
            for i in range(dev.shape[0]):
                dev[i, :] /= max(dev[i, :])

            if self.reassign in ['permute', 'overlap']:
                # The elements of "a" matrix are the column numbers (reference mode numbers)
                # that are mapped to the row numbers (calculated mode numbers).
                # Highly similar eigenvectors are assigned small values because
                # the assignment problem is a cost minimization problem.
                a = np.array([[(1.0 - vib_overlap(self.engine, v1, v2))
                               for v2 in eigvecs] for v1 in self.ref_eigvecs])
                a += dev
                if self.reassign == 'permute':
                    row, c2r = optimize.linear_sum_assignment(a)
                    eigvals = eigvals[c2r]
                elif self.reassign == 'overlap':
                    c2r = np.argmin(a, axis=0)
                    eigvals_p = []
                    for j in c2r:
                        eigvals_p.append(eigvals[j])
                    eigvals = np.array(eigvals_p)
            if not in_fd():
                if self.reassign == 'permute':
                    eigvecs = eigvecs[c2r]
                elif self.reassign == 'overlap':
                    self.c2r = c2r
                    eigvecs_p = []
                    for j in c2r:
                        eigvecs_p.append(eigvecs[j])
                    eigvecs = np.array(eigvecs_p)
                self.overlaps = np.array([
                    vib_overlap(self.engine, v1, v2)
                    for v1, v2 in zip(self.ref_eigvecs, eigvecs)
                ])
            return eigvals
Beispiel #32
0
    def stage(self, mvals, AGrad=False, AHess=False, customdir=None, firstIteration=False):
        """ 

        Stages the directory for the target, and then launches Work Queue processes if any.
        The 'get' method should not worry about the directory that it's running in.
        
        """
        if self.sleepy > 0:
            logger.info("Sleeping for %i seconds as directed...\n" % self.sleepy)
            time.sleep(self.sleepy)
        ## Directory of the current iteration; if not None, then the simulation runs under
        ## temp/target_name/iteration_number
        ## The 'customdir' is customizable and can go below anything
        cwd = os.getcwd()
        
        absgetdir = os.path.join(self.root,self.tempdir)
        if Counter() is not None:
            ## Not expecting more than ten thousand iterations
            iterdir = "iter_%04i" % Counter()
            absgetdir = os.path.join(absgetdir,iterdir)
        if customdir is not None:
            absgetdir = os.path.join(absgetdir,customdir)
        ## Go into the directory where get() will be executed.
        if not os.path.exists(absgetdir):
            os.makedirs(absgetdir)
        os.chdir(absgetdir)
        self.link_from_tempdir(absgetdir)
        ## Write mathematical parameters to file; will be used to checkpoint calculation.
        if not in_fd():
            np.savetxt('mvals.txt', mvals)
        ## Read in file that specifies which derivatives may be skipped.
        if Counter() >= self.zerograd and self.zerograd >= 0: 
            self.read_0grads()
        self.rundir = absgetdir.replace(self.root+'/','')
        ## Submit jobs to the Work Queue.
        if self.rd is None or (not firstIteration): 
            self.submit_jobs(mvals, AGrad, AHess)
        elif customdir is not None:
            # Allows us to submit micro-iteration jobs for remote targets
            self.submit_jobs(mvals, AGrad, AHess)
        os.chdir(cwd)
        
        return
Beispiel #33
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':zeros(self.FF.np, dtype=float), 'H':zeros((self.FF.np, self.FF.np), dtype=float)}
        
        # If the weight is zero, turn all derivatives off.
        if (self.weight == 0.0):
            AGrad = False
            AHess = False

        def callM(mvals_, dielectric=False):
            logger.info("\r")
            pvals = self.FF.make(mvals_)
            return self.interaction_driver_all(dielectric)

        logger.info("Executing\r")
        emm = callM(mvals)

        D = emm - self.eqm
        dV = zeros((self.FF.np,len(emm)),dtype=float)

        # Dump interaction energies to disk.
        savetxt('M.txt',emm)
        savetxt('Q.txt',self.eqm)

        # Do the finite difference derivative.
        if AGrad or AHess:
            for p in range(self.FF.np):
                dV[p,:], _ = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = emm)
            # Create the force field one last time.
            pvals  = self.FF.make(mvals)
                
        Answer['X'] = dot(self.prefactor*D/self.divisor,D/self.divisor)
        for p in range(self.FF.np):
            Answer['G'][p] = 2*dot(self.prefactor*D/self.divisor, dV[p,:]/self.divisor)
            for q in range(self.FF.np):
                Answer['H'][p,q] = 2*dot(self.prefactor*dV[p,:]/self.divisor, dV[q,:]/self.divisor)

        if not in_fd():
            self.emm = emm
            self.objective = Answer['X']

        return Answer
Beispiel #34
0
        def compute(mvals_):
            # This function has automatically assigned variable names from the interaction master file
            # Thus, all variable names in here are protected using an underscore.
            self.FF.make(mvals_)
            VectorD_ = []

            # The following code was odified by Chengwen Liu to accelarate the tinker analyze and optimize jobs
            def Energy_RMSD(systems):
              tinkerhome = os.environ["TINKERPATH"]
              f1 = open("runAna.sh", "w") 
              f2 = open("runMin.sh", "w") 
              i = 0
              for sys_ in systems: 
                opts = systems[sys_]
                optimize = (opts['optimize'] if 'optimize' in opts else False)
                if not optimize: 
                  if (i+1)%24 == 0:
                    cmd = "rm -f %s.out\n%s/analyze %s.xyz -k %s.key E > %s.out \n"%(sys_, os.environ["TINKERPATH"], sys_, sys_, sys_)
                    i += 1
                  else:
                    cmd = "rm -f %s.out\n%s/analyze %s.xyz -k %s.key E > %s.out & \n"%(sys_, os.environ["TINKERPATH"], sys_, sys_, sys_)
                    i += 1
                  f1.write(cmd)
                else:
                  if (i+1)%24 == 0:
                    cmd = "rm -f %s.xyz_2 %s.out \n%s/optimize %s.xyz -k %s.key 0.0001 > %s.out \n"%(sys_, sys_, os.environ["TINKERPATH"], sys_, sys_, sys_)
                    i += 1
                  else:
                    cmd = "rm -f %s.xyz_2 %s.out \n%s/optimize %s.xyz -k %s.key 0.0001 > %s.out & \n"%(sys_, sys_, os.environ["TINKERPATH"], sys_, sys_, sys_)
                    i += 1
                  f2.write(cmd)
              f1.write("wait\n")
              f2.write("wait\n")
              f1.close()
              f2.close()
              os.system("sh runAna.sh")
              os.system("sh runMin.sh")
              for sys_ in systems:
                while not os.path.isfile(os.path.join(os.getcwd(), sys_ + ".out")):
                  time.sleep(1.0)
              Es = {} 
              RMSDs = {} 
              for sys_ in systems:
                energ = 0.0
                rmsd = 0.0
                for line in open("%s.out"%sys_).readlines():
                  if "Total Potential Energy" in line:
                    energ = float(line.split()[-2].replace('D','e'))
                    Es[sys_] = energ
                    RMSDs[sys_] = 0.0
                  if "Final Function Value :" in line:
                    energ = float(line.split()[-1].replace('D','e'))
                    Es[sys_] = energ
                    M1 = Molecule("%s.xyz" % sys_, ftype="tinker")
                    M2 = Molecule("%s.xyz_2" % sys_, ftype="tinker")
                    M1 += M2
                    RMSDs[sys_] = M1.ref_rmsd(0)[1]
              return Es,RMSDs 

            Es, RMSDs = Energy_RMSD(self.sys_opts)
            for sys_ in self.sys_opts: 
                Energy_ = Es[sys_] 
                RMSD_ = RMSDs[sys_]
                exec("%s = Energy_" % sys_) in locals()
                RMSDNrm_ = RMSD_ / self.rmsd_denom
                w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
                VectorD_.append(np.sqrt(w_)*RMSDNrm_)
                if not in_fd() and RMSD_ != 0.0:
                    self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)

            VectorE_ = []
            for inter_ in self.inter_opts:
                Calculated_ = eval(self.inter_opts[inter_]['equation'])
                Reference_ = self.inter_opts[inter_]['reference_physical']
                Delta_ = Calculated_ - Reference_
                Denom_ = self.energy_denom
                if self.cauchy:
                    Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
                elif self.attenuate:
                    if Reference_ < Denom_:
                        Divisor_ = Denom_
                    else:
                        Divisor_ = np.sqrt(Denom_**2 + (Reference_-Denom_)**2)
                else:
                    Divisor_ = Denom_
                DeltaNrm_ = Delta_ / Divisor_
                w_ = self.inter_opts[inter_]['weight'] if 'weight' in self.inter_opts[inter_] else 1.0
                VectorE_.append(np.sqrt(w_)*DeltaNrm_)
                if not in_fd():
                    self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (Calculated_, Reference_, Delta_, w_*DeltaNrm_**2)
                # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
            # The return value is an array of normalized interaction energy differences.
            if not in_fd():
                self.rmsd_part = np.dot(np.array(VectorD_),np.array(VectorD_))
                if len(VectorE_) > 0:
                    self.energy_part = np.dot(np.array(VectorE_),np.array(VectorE_))
                else:
                    self.energy_part = 0.0
            if len(VectorE_) > 0 and len(VectorD_) > 0:
                return np.array(VectorD_ + VectorE_)
            elif len(VectorD_) > 0:
                return np.array(VectorD_)
            elif len(VectorE_) > 0:
                return np.array(VectorE_)
Beispiel #35
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}
        def compute(mvals_):
            self.FF.make(mvals_)
            Xx, Gx, Hx, freqs, normal_modes, M_opt = self.hessian_driver()
            # convert into internal hessian
            Xx *= 1/ Bohr2nm
            Gx *= Bohr2nm/ Hartree2kJmol
            Hx *= Bohr2nm**2/ Hartree2kJmol
            Hq = self.IC.calcHess(Xx, Gx, Hx)
            compute.Hq_flat = Hq.flatten()
            compute.freqs = freqs
            compute.normal_modes = normal_modes
            compute.M_opt = M_opt
            diff = Hq - self.ref_Hq

            return (np.sqrt(self.wts)/self.denom) * (compute.Hq_flat - self.ref_Hq_flat)

        V = compute(mvals)
        Answer['X'] = np.dot(V,V) * len(compute.freqs) # HJ: len(compute.freqs) is multiplied to match the scale of X2 with vib freq target X2
        # compute gradients and hessian
        dV = np.zeros((self.FF.np,len(V)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(compute, mvals, p), h = self.h, f0 = V)

        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(V, dV[p,:]) * len(compute.freqs)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:]) * len(compute.freqs)

        if not in_fd():
            self.Hq_flat = compute.Hq_flat
            self.Hq = self.Hq_flat.reshape(self.ref_Hq.shape)
            self.objective = Answer['X']
            self.FF.make(mvals)

        if self.writelevel > 0:
            # 1. write HessianCompare.txt
            hessian_comparison = np.array([
                self.ref_Hq_flat,
                compute.Hq_flat,
                compute.Hq_flat - self.ref_Hq_flat,
                np.sqrt(self.wts)/self.denom
            ]).T
            np.savetxt("HessianCompare.txt", hessian_comparison, header="%11s  %12s  %12s  %12s" % ("QMHessian", "MMHessian", "Delta(MM-QM)", "Weight"), fmt="% 12.6e")

            # 2. rearrange MM vibrational frequencies using overlap between normal modes in redundant internal coordinates
            ref_int_normal_modes = self.calc_int_normal_mode(self.ref_xyz, self.ref_eigvecs)
            int_normal_modes = self.calc_int_normal_mode(np.array(compute.M_opt.xyzs[0]), compute.normal_modes)
            a = np.array([[(1.0-np.abs(np.dot(v1/np.linalg.norm(v1),v2/np.linalg.norm(v2)))) for v2 in int_normal_modes] for v1 in ref_int_normal_modes])
            row, c2r = optimize.linear_sum_assignment(a)
            # old arrangement method, which uses overlap between mass weighted vibrational modes in cartesian coordinates
            # a = np.array([[(1.0-self.vib_overlap(v1, v2)) for v2 in compute.normal_modes] for v1 in self.ref_eigvecs])
            # row, c2r = optimize.linear_sum_assignment(a)

            freqs_rearr = compute.freqs[c2r]
            normal_modes_rearr = compute.normal_modes[c2r]

            # 3. Save rearranged frequencies and normal modes into a file for post-analysis
            with open('mm_vdata.txt', 'w') as outfile:
                outfile.writelines('%s\n' % line for line in compute.M_opt.write_xyz([0]))
                outfile.write('\n')
                for freq, normal_mode in zip(freqs_rearr, normal_modes_rearr):
                    outfile.write(f'{freq}\n')
                    for nx, ny, nz in normal_mode:
                        outfile.write(f'{nx:13.4f} {ny:13.4f} {nz:13.4f}\n')
                    outfile.write('\n')
            outfile.close()

            # 4. draw a scatter plot of vibrational frequencies and an overlap matrix of normal modes in cartessian coordinates
            draw_vibfreq_scatter_plot_n_overlap_matrix(self.name, self.engine, self.ref_eigvals, self.ref_eigvecs, freqs_rearr, normal_modes_rearr)
            return Answer
Beispiel #36
0
    def driver(self):
        ## Actually run PSI4.
        if not in_fd() and CheckBasis():
            logger.info("Now checking for linear dependencies.\n")
            _exec("cp %s %s.bak" % (self.GBSfnm, self.GBSfnm), print_command=False)
            ln0 = self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save)
            o = wopen(".lindep.dat")
            for line in open(self.DATfnm).readlines():
                s = line.split("#")[0].split()
                if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower() == 'file':
                    print("basis file %s" % self.GBSfnm, file=o)
                else:
                    print(line, end=' ', file=o)
            o.close()
            _exec("mv .lindep.dat %s" % self.DATfnm, print_command=False)
            _exec("psi4 %s" % self.DATfnm, print_command=False)
            LI = GBS_Reader()
            LI_lines = {}
            ## Read in the commented linindep.gbs file and ensure that these same lines are commented in the new .gbs file
            for line in open('linindep.gbs'):
                LI.feed(line,linindep=True)
                key = '.'.join([str(i) for i in (LI.element,LI.amom,LI.basis_number[LI.element],LI.contraction_number)])
                if LI.isdata:
                    if key in LI_lines:
                        logger.info("Duplicate key found:\n")
                        logger.info("%s\n" % key)
                        logger.info(str(LI_lines[key]))
                        logger.info(line)
                        warn_press_key("In %s, the LI_lines dictionary should not contain repeated keys!" % __file__)
                    LI_lines[key] = (line, LI.destroy)
            ## Now build a "Frankenstein" .gbs file composed of the original .gbs file but with data from the linindep.gbs file!
            FK = GBS_Reader()
            FK_lines = []
            self.FF.linedestroy_this = []
            self.FF.prmdestroy_this = []
            for ln, line in enumerate(open(self.GBSfnm).readlines()):
                FK.feed(line)
                key = '.'.join([str(i) for i in (FK.element,FK.amom,FK.basis_number[FK.element],FK.contraction_number)])
                if FK.isdata and key in LI_lines:
                    if LI_lines[key][1]:
                        logger.info("Destroying line %i (originally %i): " % (ln, ln0[ln]))
                        logger.info(line)
                        self.FF.linedestroy_this.append(ln)
                        for p_destroy in [i for i, fld in enumerate(self.FF.pfields) if any([subfld[0] == self.GBSfnm and subfld[1] == ln0[ln] for subfld in fld])]:
                            logger.info("Destroying parameter %i located at line %i (originally %i) with fields given by: %s" % (p_destroy, ln, ln0[ln], str(self.FF.pfields[p_destroy])))
                            self.FF.prmdestroy_this.append(p_destroy)
                    FK_lines.append(LI_lines[key][0])
                else:
                    FK_lines.append(line)
            o = wopen('franken.gbs')
            for line in FK_lines:
                print(line, end=' ', file=o)
            o.close()
            _exec("cp %s.bak %s" % (self.GBSfnm, self.GBSfnm), print_command=False)
            
            if len(list(itertools.chain(*(self.FF.linedestroy_save + [self.FF.linedestroy_this])))) > 0:
                logger.info("All lines removed: " + self.FF.linedestroy_save + [self.FF.linedestroy_this] + '\n')
                logger.info("All prms removed: " + self.FF.prmdestroy_save + [self.FF.prmdestroy_this] + '\n')

        self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save + [self.FF.linedestroy_this])
        _exec("psi4", print_command=False, outfnm="psi4.stdout")
        if not in_fd():
            for line in open('psi4.stdout').readlines():
                if "MP2 Energy:" in line:
                    self.MP2_Energy = float(line.split()[-1])
                elif "DF Energy:" in line:
                    self.DF_Energy = float(line.split()[-1])
        Ans = np.array([[float(i) for i in line.split()] for line in open("objective.dat").readlines()])
        os.unlink("objective.dat")
        return Ans
Beispiel #37
0
    def driver(self):
        ## Actually run PSI4.
        if not in_fd() and CheckBasis():
            logger.info("Now checking for linear dependencies.\n")
            _exec("cp %s %s.bak" % (self.GBSfnm, self.GBSfnm),
                  print_command=False)
            ln0 = self.write_nested_destroy(self.GBSfnm,
                                            self.FF.linedestroy_save)
            o = wopen(".lindep.dat")
            for line in open(self.DATfnm).readlines():
                s = line.split("#")[0].split()
                if len(s) == 3 and s[0].lower() == 'basis' and s[1].lower(
                ) == 'file':
                    print("basis file %s" % self.GBSfnm, file=o)
                else:
                    print(line, end=' ', file=o)
            o.close()
            _exec("mv .lindep.dat %s" % self.DATfnm, print_command=False)
            _exec("psi4 %s" % self.DATfnm, print_command=False)
            LI = GBS_Reader()
            LI_lines = {}
            ## Read in the commented linindep.gbs file and ensure that these same lines are commented in the new .gbs file
            for line in open('linindep.gbs'):
                LI.feed(line, linindep=True)
                key = '.'.join([
                    str(i)
                    for i in (LI.element, LI.amom, LI.basis_number[LI.element],
                              LI.contraction_number)
                ])
                if LI.isdata:
                    if key in LI_lines:
                        logger.info("Duplicate key found:\n")
                        logger.info("%s\n" % key)
                        logger.info(str(LI_lines[key]))
                        logger.info(line)
                        warn_press_key(
                            "In %s, the LI_lines dictionary should not contain repeated keys!"
                            % __file__)
                    LI_lines[key] = (line, LI.destroy)
            ## Now build a "Frankenstein" .gbs file composed of the original .gbs file but with data from the linindep.gbs file!
            FK = GBS_Reader()
            FK_lines = []
            self.FF.linedestroy_this = []
            self.FF.prmdestroy_this = []
            for ln, line in enumerate(open(self.GBSfnm).readlines()):
                FK.feed(line)
                key = '.'.join([
                    str(i)
                    for i in (FK.element, FK.amom, FK.basis_number[FK.element],
                              FK.contraction_number)
                ])
                if FK.isdata and key in LI_lines:
                    if LI_lines[key][1]:
                        logger.info("Destroying line %i (originally %i): " %
                                    (ln, ln0[ln]))
                        logger.info(line)
                        self.FF.linedestroy_this.append(ln)
                        for p_destroy in [
                                i for i, fld in enumerate(self.FF.pfields)
                                if any([
                                    subfld[0] == self.GBSfnm
                                    and subfld[1] == ln0[ln] for subfld in fld
                                ])
                        ]:
                            logger.info(
                                "Destroying parameter %i located at line %i (originally %i) with fields given by: %s"
                                % (p_destroy, ln, ln0[ln],
                                   str(self.FF.pfields[p_destroy])))
                            self.FF.prmdestroy_this.append(p_destroy)
                    FK_lines.append(LI_lines[key][0])
                else:
                    FK_lines.append(line)
            o = wopen('franken.gbs')
            for line in FK_lines:
                print(line, end=' ', file=o)
            o.close()
            _exec("cp %s.bak %s" % (self.GBSfnm, self.GBSfnm),
                  print_command=False)

            if len(
                    list(
                        itertools.chain(*(self.FF.linedestroy_save +
                                          [self.FF.linedestroy_this])))) > 0:
                logger.info("All lines removed: " + self.FF.linedestroy_save +
                            [self.FF.linedestroy_this] + '\n')
                logger.info("All prms removed: " + self.FF.prmdestroy_save +
                            [self.FF.prmdestroy_this] + '\n')

        self.write_nested_destroy(
            self.GBSfnm, self.FF.linedestroy_save + [self.FF.linedestroy_this])
        _exec("psi4", print_command=False, outfnm="psi4.stdout")
        if not in_fd():
            for line in open('psi4.stdout').readlines():
                if "MP2 Energy:" in line:
                    self.MP2_Energy = float(line.split()[-1])
                elif "DF Energy:" in line:
                    self.DF_Energy = float(line.split()[-1])
        Ans = np.array([[float(i) for i in line.split()]
                        for line in open("objective.dat").readlines()])
        os.unlink("objective.dat")
        return Ans
Beispiel #38
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {
            'X': 0.0,
            'G': np.zeros(self.FF.np),
            'H': np.zeros((self.FF.np, self.FF.np))
        }

        # If the weight is zero, turn all derivatives off.
        if (self.weight == 0.0):
            AGrad = False
            AHess = False

        def callM(mvals_, dielectric=False):
            logger.info("\r")
            pvals = self.FF.make(mvals_)
            return self.engine.interaction_energy(self.select1, self.select2)

        logger.info("Executing\r")
        emm = callM(mvals)

        D = emm - self.eqm
        dV = np.zeros((self.FF.np, len(emm)))

        if self.writelevel > 0:
            # Dump interaction energies to disk.
            np.savetxt('M.txt', emm)
            np.savetxt('Q.txt', self.eqm)
            import pickle
            pickle.dump((self.name, self.label, self.prefactor, self.eqm, emm),
                        open("qm_vs_mm.p", 'w'))
            # select the qm and mm data that has >0 weight to plot
            qm_data, mm_data = [], []
            for i in range(len(self.eqm)):
                if self.prefactor[i] != 0:
                    qm_data.append(self.eqm[i])
                    mm_data.append(emm[i])
            plot_interaction_qm_vs_mm(qm_data,
                                      mm_data,
                                      title="Interaction Energy " + self.name)

        # Do the finite difference derivative.
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p, :], _ = f12d3p(fdwrap(callM, mvals, p), h=self.h, f0=emm)
            # Create the force field one last time.
            pvals = self.FF.make(mvals)

        Answer['X'] = np.dot(self.prefactor * D / self.divisor,
                             D / self.divisor)
        for p in self.pgrad:
            Answer['G'][p] = 2 * np.dot(self.prefactor * D / self.divisor,
                                        dV[p, :] / self.divisor)
            for q in self.pgrad:
                Answer['H'][p, q] = 2 * np.dot(
                    self.prefactor * dV[p, :] / self.divisor,
                    dV[q, :] / self.divisor)

        if not in_fd():
            self.emm = emm
            self.objective = Answer['X']

        ## QYD: try to clean up OpenMM engine.simulation objects to free up GPU memory
        try:
            if self.engine.name == 'openmm':
                if hasattr(self.engine, 'simulation'):
                    del self.engine.simulation
                if hasattr(self.engine, 'A'): del self.engine.A
                if hasattr(self.engine, 'B'): del self.engine.B
        except:
            pass

        return Answer
Beispiel #39
0
    def get(self, mvals, AGrad=False, AHess=False):
	"""
        LPW 04-17-2013
        
        This subroutine builds the objective function from Psi4.

        @param[in] mvals Mathematical parameter values
        @param[in] AGrad Switch to turn on analytic gradient
        @param[in] AHess Switch to turn on analytic Hessian
        @return Answer Contribution to the objective function
        """
        Answer = {}
        Fac = 1000000
        n = len(mvals)
        X = 0.0
        G = np.zeros(n,dtype=float)
        H = np.zeros((n,n),dtype=float)
        pvals = self.FF.make(mvals)
        self.tdir = os.getcwd()
        self.objd = OrderedDict()
        self.gradd = OrderedDict()
        self.hdiagd = OrderedDict()
        bidirect = False

        def fdwrap2(func,mvals0,pidx,qidx,key=None,**kwargs):
            def func2(arg1,arg2):
                mvals = list(mvals0)
                mvals[pidx] += arg1
                mvals[qidx] += arg2
                print "\rfdwrap2:", func.__name__, "[%i] = % .1e , [%i] = % .1e" % (pidx, arg1, qidx, arg2), ' '*50,
                if key != None:
                    return func(mvals,**kwargs)[key]
                else:
                    return func(mvals,**kwargs)
            return func2

        def f2d5p(f, h):
            fpp, fpm, fmp, fmm = [f(i*h,j*h) for i,j in [(1,1),(1,-1),(-1,1),(-1,-1)]]
            fpp = (fpp-fpm-fmp+fmm)/(4*h*h)
            return fpp

        def f2d4p(f, h, f0 = None):
            if f0 == None:
                fpp, fp0, f0p, f0 = [f(i*h,j*h) for i,j in [(1,1),(1,0),(0,1),(0,0)]]
            else:
                fpp, fp0, f0p = [f(i*h,j*h) for i,j in [(1,1),(1,0),(0,1)]]
            fpp = (fpp-fp0-f0p+f0)/(h*h)
            return fpp

        for d in self.objfiles:
            print "\rNow working on", d, 50*' ','\r',
            x = self.driver(mvals, d)
            grad  = np.zeros(n,dtype=float)
            hdiag = np.zeros(n,dtype=float)
            hess  = np.zeros((n,n),dtype=float)
            for p in range(self.FF.np):
                if self.callderivs[d][p]:
                    if AHess:
                        grad[p], hdiag[p] = f12d3p(fdwrap(self.driver, mvals, p, d=d), h = self.h, f0 = x)
                        hess[p,p] = hdiag[p]
                        # for q in range(p):
                        #     if self.callderivs[d][q]:
                        #         if bidirect:
                        #             hessentry = f2d5p(fdwrap2(self.driver, mvals, p, q, d=d), h = self.h)
                        #         else:
                        #             hessentry = f2d4p(fdwrap2(self.driver, mvals, p, q, d=d), h = self.h, f0 = x)
                        #         hess[p,q] = hessentry
                        #         hess[q,p] = hessentry
                    elif AGrad:
                        if bidirect:
                            grad[p], _ = f12d3p(fdwrap(self.driver, mvals, p, d=d), h = self.h, f0 = x)
                        else:
                            grad[p] = f1d2p(fdwrap(self.driver, mvals, p, d=d), h = self.h, f0 = x)
                            
            self.objd[d] = x
            self.gradd[d] = grad
            self.hdiagd[d] = hdiag
            X += x
            G += grad
            #H += np.diag(hdiag)
            H += hess
        if not in_fd():
            self.objective = X
            self.objvals = self.objd
        # print self.objd
        # print self.gradd
        # print self.hdiagd
                    
        if float('Inf') in pvals:
            return {'X' : 1e10, 'G' : G, 'H' : H}
        return {'X' : X, 'G' : G, 'H' : H}
Beispiel #40
0
    def get(self, mvals, AGrad=False, AHess=False):
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}
        self.PrintDict = OrderedDict()
        self.RMSDDict = OrderedDict()
        #pool = Pool(processes=4)
        def compute(mvals_):
            # This function has automatically assigned variable names from the interaction master file
            # Thus, all variable names in here are protected using an underscore.
            self.FF.make(mvals_)
            VectorD_ = []
            for sys_ in self.sys_opts:
                Energy_, RMSD_ = self.system_driver(sys_)
                #print "Setting %s to" % sys_, Energy_
                exec("%s = Energy_" % sys_) in locals()
                RMSDNrm_ = RMSD_ / self.rmsd_denom
                w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
                VectorD_.append(np.sqrt(w_)*RMSDNrm_)
                if not in_fd() and RMSD_ != 0.0:
                    self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)
            VectorE_ = []
            for inter_ in self.inter_opts:
                Calculated_ = eval(self.inter_opts[inter_]['equation'])
                Reference_ = self.inter_opts[inter_]['reference_physical']
                Delta_ = Calculated_ - Reference_
                Denom_ = self.energy_denom
                if self.cauchy:
                    Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
                elif self.attenuate:
                    if Reference_ < Denom_:
                        Divisor_ = Denom_
                    else:
                        Divisor_ = np.sqrt(Denom_**2 + (Reference_-Denom_)**2)
                else:
                    Divisor_ = Denom_
                DeltaNrm_ = Delta_ / Divisor_
                w_ = self.inter_opts[inter_]['weight'] if 'weight' in self.inter_opts[inter_] else 1.0
                VectorE_.append(np.sqrt(w_)*DeltaNrm_)
                if not in_fd():
                    self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (Calculated_, Reference_, Delta_, w_*DeltaNrm_**2)
                # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
            # The return value is an array of normalized interaction energy differences.
            if not in_fd():
                self.rmsd_part = np.dot(np.array(VectorD_),np.array(VectorD_))
                if len(VectorE_) > 0:
                    self.energy_part = np.dot(np.array(VectorE_),np.array(VectorE_))
                else:
                    self.energy_part = 0.0
            if len(VectorE_) > 0 and len(VectorD_) > 0:
                return np.array(VectorD_ + VectorE_)
            elif len(VectorD_) > 0:
                return np.array(VectorD_)
            elif len(VectorE_) > 0:
                return np.array(VectorE_)
                    
        V = compute(mvals)

        dV = np.zeros((self.FF.np,len(V)))
        if AGrad or AHess:
            for p in range(self.FF.np):
                dV[p,:], _ = f12d3p(fdwrap(compute, mvals, p), h = self.h, f0 = V)

        Answer['X'] = np.dot(V,V)
        for p in range(self.FF.np):
            Answer['G'][p] = 2*np.dot(V, dV[p,:])
            for q in range(self.FF.np):
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:])

        if not in_fd():
            self.objective = Answer['X']
            self.FF.make(mvals)

        return Answer
Beispiel #41
0
    def get(self, mvals, AGrad=False, AHess=False):
        Answer = {
            'X': 0.0,
            'G': np.zeros(self.FF.np),
            'H': np.zeros((self.FF.np, self.FF.np))
        }
        self.PrintDict = OrderedDict()
        self.RMSDDict = OrderedDict()
        EnergyDict = OrderedDict()

        #pool = Pool(processes=4)
        def compute(mvals_):
            # This function has automatically assigned variable names from the interaction master file
            # Thus, all variable names in here are protected using an underscore.
            self.FF.make(mvals_)
            VectorD_ = []
            for sys_ in self.sys_opts:
                Energy_, RMSD_ = self.system_driver(sys_)
                # Energies are stored in a dictionary.
                EnergyDict[sys_] = Energy_
                RMSDNrm_ = RMSD_ / self.rmsd_denom
                w_ = self.sys_opts[sys_][
                    'rmsd_weight'] if 'rmsd_weight' in self.sys_opts[
                        sys_] else 1.0
                VectorD_.append(np.sqrt(w_) * RMSDNrm_)
                if not in_fd() and RMSD_ != 0.0:
                    self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_,
                                                              w_ * RMSDNrm_**2)
            VectorE_ = []
            for inter_ in self.inter_opts:

                def encloseInDictionary(matchobj):
                    return 'EnergyDict["' + matchobj.group(0) + '"]'

                # Here we need to evaluate a mathematical expression of the stored variables in EnergyDict.
                # We start by enclosing every variable in EnergyDict[""] and then calling eval on it.
                evalExpr = re.sub('[A-Za-z_][A-Za-z0-9_]*',
                                  encloseInDictionary,
                                  self.inter_opts[inter_]['equation'])
                Calculated_ = eval(evalExpr)
                Reference_ = self.inter_opts[inter_]['reference_physical']
                Delta_ = Calculated_ - Reference_
                Denom_ = self.energy_denom
                if self.cauchy:
                    Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
                elif self.attenuate:
                    if Reference_ < Denom_:
                        Divisor_ = Denom_
                    else:
                        Divisor_ = np.sqrt(Denom_**2 +
                                           (Reference_ - Denom_)**2)
                else:
                    Divisor_ = Denom_
                DeltaNrm_ = Delta_ / Divisor_
                w_ = self.inter_opts[inter_][
                    'weight'] if 'weight' in self.inter_opts[inter_] else 1.0
                VectorE_.append(np.sqrt(w_) * DeltaNrm_)
                if not in_fd():
                    self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (
                        Calculated_, Reference_, Delta_, w_ * DeltaNrm_**2)
                # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
            # The return value is an array of normalized interaction energy differences.
            if not in_fd():
                self.rmsd_part = np.dot(np.array(VectorD_), np.array(VectorD_))
                if len(VectorE_) > 0:
                    self.energy_part = np.dot(np.array(VectorE_),
                                              np.array(VectorE_))
                else:
                    self.energy_part = 0.0
            if len(VectorE_) > 0 and len(VectorD_) > 0:
                return np.array(VectorD_ + VectorE_)
            elif len(VectorD_) > 0:
                return np.array(VectorD_)
            elif len(VectorE_) > 0:
                return np.array(VectorE_)

        V = compute(mvals)

        dV = np.zeros((self.FF.np, len(V)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p, :], _ = f12d3p(fdwrap(compute, mvals, p), h=self.h, f0=V)

        Answer['X'] = np.dot(V, V)
        for p in self.pgrad:
            Answer['G'][p] = 2 * np.dot(V, dV[p, :])
            for q in self.pgrad:
                Answer['H'][p, q] = 2 * np.dot(dV[p, :], dV[q, :])

        if not in_fd():
            self.objective = Answer['X']
            self.FF.make(mvals)

        return Answer
Beispiel #42
0
    def get(self, mvals, AGrad=False, AHess=False):
	"""
        LPW 05-30-2012
        
        This subroutine builds the objective function (and optionally
        its derivatives) from a general software.  

        This subroutine interfaces with simulation software 'drivers'.
        The driver is expected to give exact values, fitting values, and weights.

        @param[in] mvals Mathematical parameter values
        @param[in] AGrad Switch to turn on analytic gradient
        @param[in] AHess Switch to turn on analytic Hessian
        @return Answer Contribution to the objective function
        """
        global LAST_MVALS, CHECK_BASIS
        # print mvals
        # print LAST_MVALS
        # print mvals == LAST_MVALS
        if LAST_MVALS is None or not (mvals == LAST_MVALS).all():
            CHECK_BASIS = False
        else:
            CHECK_BASIS = False
        Answer = {}
        Fac = 1000000
        ## Dictionary for derivative terms
        dM = {}
        # Create the new force field!!
        NP = len(mvals)
        G = np.zeros(NP)
        H = np.zeros((NP,NP))
        pvals = self.FF.make(mvals)
        if float('Inf') in pvals:
            return {'X' : 1e10, 'G' : G, 'H' : H}
        Ans = self.driver()
        W = Ans[:,2]
        M = Ans[:,1]
        Q = Ans[:,0]
        D = M - Q

        self.MAQ = np.mean(np.abs(Q))

        ns = len(M)
        # Wrapper to the driver, which returns just the part that changes.
        def callM(mvals_):
            self.FF.make(mvals_)
            Ans2 = self.driver()
            M_ = Ans2[:,1]
            D_ = M_ - Q
	    return Ans2[:,1]
        if AGrad:
            # Leaving comment here if we want to reintroduce second deriv someday.
            #     dM[p,:], ddM[p,:] = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = M)
            xgrad = []
            for p in self.pgrad:
                dM_arr = f1d2p(fdwrap(callM, mvals, p), h = self.h, f0 = M)
                if np.max(np.abs(dM_arr)) == 0.0 and (not self.evaluated):
                    logger.info("\r Simulation %s will skip over parameter %i in subsequent steps\n" % (self.name, p))
                    xgrad.append(p)
                else:
                    dM[p] = dM_arr.copy()
            for p in xgrad:
                self.pgrad.remove(p)
	Objective = np.dot(W, D**2) * Fac
        if AGrad:
            for p in self.pgrad:
                G[p] = 2 * np.dot(W, D*dM[p])
                if not AHess: continue
                H[p, p] = 2 * np.dot(W, dM[p]**2)
                for q in range(p):
                    if q not in self.pgrad: continue
                    GNP = 2 * np.dot(W, dM[p] * dM[q])
                    H[q,p] = GNP
                    H[p,q] = GNP
        G *= Fac
        H *= Fac
        Answer = {'X':Objective, 'G':G, 'H':H}
        if not in_fd():
            self.D = D
            self.objective = Answer['X']
            LAST_MVALS = mvals.copy()
        return Answer
Beispiel #43
0
        def compute(mvals_):
            # This function has automatically assigned variable names from the interaction master file
            # Thus, all variable names in here are protected using an underscore.
            self.FF.make(mvals_)
            VectorD_ = []

            # original code
            #for sys_ in self.sys_opts:
            #    Energy_, RMSD_ = self.system_driver(sys_)
            #    # Energies are stored in a dictionary.
            #    EnergyDict[sys_] = Energy_
            #    RMSDNrm_ = RMSD_ / self.rmsd_denom
            #    w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
            #    VectorD_.append(np.sqrt(w_)*RMSDNrm_)
            #    if not in_fd() and RMSD_ != 0.0:
            #        self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)

            # Added by Chengwen
            def Energy_RMSD(systems):
                tinkerhome = os.environ["TINKERPATH"]
                f1 = open("runAna.sh", "w")
                f2 = open("runMin.sh", "w")
                i = 0
                for sys_ in systems:
                    opts = systems[sys_]
                    optimize = (opts['optimize']
                                if 'optimize' in opts else False)
                    if not optimize:
                        if (i + 1) % 24 == 0:
                            cmd = "rm -f %s.out\n%s/analyze %s.xyz -k %s.key E > %s.out \n" % (
                                sys_, os.environ["TINKERPATH"], sys_, sys_,
                                sys_)
                            i += 1
                        else:
                            cmd = "rm -f %s.out\n%s/analyze %s.xyz -k %s.key E > %s.out & \n" % (
                                sys_, os.environ["TINKERPATH"], sys_, sys_,
                                sys_)
                            i += 1
                        f1.write(cmd)
                    else:
                        if (i + 1) % 24 == 0:
                            cmd = "rm -f %s.xyz_2 %s.out \n%s/optimize %s.xyz -k %s.key 0.0001 > %s.out \n" % (
                                sys_, sys_, os.environ["TINKERPATH"], sys_,
                                sys_, sys_)
                            i += 1
                        else:
                            cmd = "rm -f %s.xyz_2 %s.out \n%s/optimize %s.xyz -k %s.key 0.0001 > %s.out & \n" % (
                                sys_, sys_, os.environ["TINKERPATH"], sys_,
                                sys_, sys_)
                            i += 1
                        f2.write(cmd)
                f1.write("wait\n")
                f2.write("wait\n")
                f1.close()
                f2.close()
                os.system("sh runAna.sh")
                os.system("sh runMin.sh")
                for sys_ in systems:
                    while not os.path.isfile(
                            os.path.join(os.getcwd(), sys_ + ".out")):
                        time.sleep(1.0)
                Es = {}
                RMSDs = {}
                for sys_ in systems:
                    energ = 0.0
                    rmsd = 0.0
                    for line in open("%s.out" % sys_).readlines():
                        if "Total Potential Energy" in line:
                            energ = float(line.split()[-2].replace('D', 'e'))
                            Es[sys_] = energ
                            RMSDs[sys_] = 0.0
                        if "Final Function Value :" in line:
                            energ = float(line.split()[-1].replace('D', 'e'))
                            Es[sys_] = energ
                            M1 = Molecule("%s.xyz" % sys_, ftype="tinker")
                            M2 = Molecule("%s.xyz_2" % sys_, ftype="tinker")
                            M1 += M2
                            RMSDs[sys_] = M1.ref_rmsd(0)[1]
                return Es, RMSDs

            Es, RMSDs = Energy_RMSD(self.sys_opts)
            for sys_ in self.sys_opts:
                Energy_ = Es[sys_]
                RMSD_ = RMSDs[sys_]
                EnergyDict[sys_] = Energy_
                RMSDNrm_ = RMSD_ / self.rmsd_denom
                w_ = self.sys_opts[sys_][
                    'rmsd_weight'] if 'rmsd_weight' in self.sys_opts[
                        sys_] else 1.0
                VectorD_.append(np.sqrt(w_) * RMSDNrm_)
                if not in_fd() and RMSD_ != 0.0:
                    self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_,
                                                              w_ * RMSDNrm_**2)
            #====== Above =====

            VectorE_ = []
            for inter_ in self.inter_opts:

                def encloseInDictionary(matchobj):
                    return 'EnergyDict["' + matchobj.group(0) + '"]'

                # Here we need to evaluate a mathematical expression of the stored variables in EnergyDict.
                # We start by enclosing every variable in EnergyDict[""] and then calling eval on it.
                evalExpr = re.sub('[A-Za-z_][A-Za-z0-9_]*',
                                  encloseInDictionary,
                                  self.inter_opts[inter_]['equation'])
                Calculated_ = eval(evalExpr)
                Reference_ = self.inter_opts[inter_]['reference_physical']
                Delta_ = Calculated_ - Reference_
                Denom_ = self.energy_denom
                if self.attenuate:
                    if Reference_ < Denom_:
                        Divisor_ = Denom_
                    else:
                        Divisor_ = np.sqrt(Denom_**2 +
                                           (Reference_ - Denom_)**2)
                else:
                    Divisor_ = Denom_
                DeltaNrm_ = Delta_ / Divisor_
                w_ = self.inter_opts[inter_][
                    'weight'] if 'weight' in self.inter_opts[inter_] else 1.0
                VectorE_.append(np.sqrt(w_) * DeltaNrm_)
                if not in_fd():
                    self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (
                        Calculated_, Reference_, Delta_, w_ * DeltaNrm_**2)
                # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
            # The return value is an array of normalized interaction energy differences.
            if not in_fd():
                self.rmsd_part = np.dot(np.array(VectorD_), np.array(VectorD_))
                if len(VectorE_) > 0:
                    self.energy_part = np.dot(np.array(VectorE_),
                                              np.array(VectorE_))
                else:
                    self.energy_part = 0.0
            if len(VectorE_) > 0 and len(VectorD_) > 0:
                return np.array(VectorD_ + VectorE_)
            elif len(VectorD_) > 0:
                return np.array(VectorD_)
            elif len(VectorE_) > 0:
                return np.array(VectorE_)
Beispiel #44
0
    def get(self, mvals, AGrad=False, AHess=False):
        """
        LPW 05-30-2012
        
        This subroutine builds the objective function (and optionally
        its derivatives) from a general software.  

        This subroutine interfaces with simulation software 'drivers'.
        The driver is expected to give exact values, fitting values, and weights.

        @param[in] mvals Mathematical parameter values
        @param[in] AGrad Switch to turn on analytic gradient
        @param[in] AHess Switch to turn on analytic Hessian
        @return Answer Contribution to the objective function
        """
        global LAST_MVALS, CHECK_BASIS
        # print mvals
        # print LAST_MVALS
        # print mvals == LAST_MVALS
        if LAST_MVALS is None or not (mvals == LAST_MVALS).all():
            CHECK_BASIS = False
        else:
            CHECK_BASIS = False
        Answer = {}
        Fac = 1000000
        ## Dictionary for derivative terms
        dM = {}
        # Create the new force field!!
        NP = len(mvals)
        G = np.zeros(NP)
        H = np.zeros((NP, NP))
        pvals = self.FF.make(mvals)
        if float('Inf') in pvals:
            return {'X': 1e10, 'G': G, 'H': H}
        Ans = self.driver()
        W = Ans[:, 2]
        M = Ans[:, 1]
        Q = Ans[:, 0]
        D = M - Q

        self.MAQ = np.mean(np.abs(Q))

        ns = len(M)

        # Wrapper to the driver, which returns just the part that changes.
        def callM(mvals_):
            self.FF.make(mvals_)
            Ans2 = self.driver()
            M_ = Ans2[:, 1]
            D_ = M_ - Q
            return Ans2[:, 1]

        if AGrad:
            # Leaving comment here if we want to reintroduce second deriv someday.
            #     dM[p,:], ddM[p,:] = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = M)
            xgrad = []
            for p in self.pgrad:
                dM_arr = f1d2p(fdwrap(callM, mvals, p), h=self.h, f0=M)
                if np.max(np.abs(dM_arr)) == 0.0 and (not self.evaluated):
                    logger.info(
                        "\r Simulation %s will skip over parameter %i in subsequent steps\n"
                        % (self.name, p))
                    xgrad.append(p)
                else:
                    dM[p] = dM_arr.copy()
            for p in xgrad:
                self.pgrad.remove(p)
        Objective = np.dot(W, D**2) * Fac
        if AGrad:
            for p in self.pgrad:
                G[p] = 2 * np.dot(W, D * dM[p])
                if not AHess: continue
                H[p, p] = 2 * np.dot(W, dM[p]**2)
                for q in range(p):
                    if q not in self.pgrad: continue
                    GNP = 2 * np.dot(W, dM[p] * dM[q])
                    H[q, p] = GNP
                    H[p, q] = GNP
        G *= Fac
        H *= Fac
        Answer = {'X': Objective, 'G': G, 'H': H}
        if not in_fd():
            self.D = D
            self.objective = Answer['X']
            LAST_MVALS = mvals.copy()
        return Answer
Beispiel #45
0
    def get(self, mvals, AGrad=True, AHess=True):
        """Return the contribution to the total objective function. This is a
        weighted average of the calculated quantities.

        Parameters
        ----------
        mvals : list
            Mathematical parameter values.
        AGrad : Boolean
            Switch to turn on analytic gradient.
        AHess : Boolean
            Switch to turn on analytic Hessian.

        Returns
        -------
        Answer : dict
            Contribution to the objective function. `Answer` is a dict with keys
            `X` for the objective function, `G` for its gradient and `H` for its
            Hessian.
                    
        """
        Answer   = {}

        Objective = 0.0
        Gradient  = np.zeros(self.FF.np)
        Hessian   = np.zeros((self.FF.np, self.FF.np))

        for pt in self.points:
            # Update data point with MD results
            self.retrieve(pt)

        obj        = OrderedDict()
        reweighted = []
        for q in self.quantities:
            # Returns dict with keys "X"=objective term value, "G"=the
            # gradient, "H"=the hessian, and "info"=printed info about points
            obj[q] = self.objective_term(q)
        
            # Apply weights for quantities (normalized)
            if obj[q]["X"] == 0:
                self.weights[q] = 0.0

            # Store weights sorted in the order of self.quantities
            reweighted.append(self.weights[q])
        
        # Normalize weights
        reweighted  = np.array(reweighted)
        wtot        = np.sum(reweighted)
        reweighted  = reweighted/wtot if wtot > 0 else reweighted
         
        # Picks out the "X", "G" and "H" keys for the quantities sorted in the
        # order of self.quantities. Xs is N-array, Gs is NxM-array and Hs is
        # NxMxM-array, where N is number of quantities and M is number of
        # parameters.
        Xs = np.array([dic["X"] for dic in obj.values()])
        Gs = np.array([dic["G"] for dic in obj.values()])
        Hs = np.array([dic["H"] for dic in obj.values()])
                                
        # Target contribution is (normalized) weighted averages of the
        # individual quantity terms.
        Objective    = np.average(Xs, weights=(None if np.all(reweighted == 0) else \
                                               reweighted), axis=0)
        if AGrad:
            Gradient = np.average(Gs, weights=(None if np.all(reweighted == 0) else \
                                               reweighted), axis=0)
        if AHess:
            Hessian  = np.average(Hs, weights=(None if np.all(reweighted == 0) else \
                                               reweighted), axis=0)

        if not in_fd():
            # Store results to show with indicator() function
            self.Xp = {q : dic["X"] for (q, dic) in obj.items()}
            self.Wp = {q : reweighted[self.quantities.index(q)]
                       for (q, dic) in obj.items()}
            self.Pp = {q : dic["info"] for (q, dic) in obj.items()}

            if AGrad:
                self.Gp = {q : dic["G"] for (q, dic) in obj.items()}

            self.Objective = Objective
        
        Answer = { "X": Objective, "G": Gradient, "H": Hessian }
        return Answer
Beispiel #46
0
    def get(self, mvals, AGrad=False, AHess=False):
        """
        LPW 04-17-2013
        
        This subroutine builds the objective function from Psi4.

        @param[in] mvals Mathematical parameter values
        @param[in] AGrad Switch to turn on analytic gradient
        @param[in] AHess Switch to turn on analytic Hessian
        @return Answer Contribution to the objective function
        """
        Answer = {}
        Fac = 1000000
        n = len(mvals)
        X = 0.0
        G = np.zeros(n)
        H = np.zeros((n, n))
        pvals = self.FF.make(mvals)
        self.tdir = os.getcwd()
        self.objd = OrderedDict()
        self.gradd = OrderedDict()
        self.hdiagd = OrderedDict()
        wq = getWorkQueue()

        def fdwrap2(func, mvals0, pidx, qidx, key=None, **kwargs):
            def func2(arg1, arg2):
                mvals = list(mvals0)
                mvals[pidx] += arg1
                mvals[qidx] += arg2
                logger.info("\rfdwrap2:" + func.__name__ +
                            "[%i] = % .1e , [%i] = % .1e" %
                            (pidx, arg1, qidx, arg2) + ' ' * 50)
                if key is not None:
                    return func(mvals, **kwargs)[key]
                else:
                    return func(mvals, **kwargs)

            return func2

        def f2d5p(f, h):
            fpp, fpm, fmp, fmm = [
                f(i * h, j * h)
                for i, j in [(1, 1), (1, -1), (-1, 1), (-1, -1)]
            ]
            fpp = (fpp - fpm - fmp + fmm) / (4 * h * h)
            return fpp

        def f2d4p(f, h, f0=None):
            if f0 is None:
                fpp, fp0, f0p, f0 = [
                    f(i * h, j * h)
                    for i, j in [(1, 1), (1, 0), (0, 1), (0, 0)]
                ]
            else:
                fpp, fp0, f0p = [
                    f(i * h, j * h) for i, j in [(1, 1), (1, 0), (0, 1)]
                ]
            fpp = (fpp - fp0 - f0p + f0) / (h * h)
            return fpp

        for d in self.objfiles:
            logger.info("\rNow working on" + str(d) + 50 * ' ' + '\r')
            if wq is None:
                x = self.driver(mvals, d)
            grad = np.zeros(n)
            hdiag = np.zeros(n)
            hess = np.zeros((n, n))
            apath = os.path.join(self.tdir, d, "current")
            x = float(
                open(os.path.join(
                    apath,
                    'objective.out')).readlines()[0].split()[1]) * self.factor
            for p in range(self.FF.np):
                if self.callderivs[d][p]:

                    def reader(mvals_, h):
                        apath = os.path.join(self.tdir, d, str(p), str(h))
                        answer = float(
                            open(os.path.join(apath, 'objective.out')).
                            readlines()[0].split()[1]) * self.factor
                        return answer

                    if AHess:
                        if wq is not None:
                            apath = os.path.join(self.tdir, d, "current")
                            x = float(
                                open(os.path.join(apath, 'objective.out')).
                                readlines()[0].split()[1]) * self.factor
                            grad[p], hdiag[p] = f12d3p(fdwrap(reader,
                                                              mvals,
                                                              p,
                                                              h=self.h),
                                                       h=self.h,
                                                       f0=x)
                        else:
                            grad[p], hdiag[p] = f12d3p(fdwrap(self.driver,
                                                              mvals,
                                                              p,
                                                              d=d),
                                                       h=self.h,
                                                       f0=x)
                        hess[p, p] = hdiag[p]
                    elif AGrad:
                        if self.bidirect:
                            if wq is not None:
                                apath = os.path.join(self.tdir, d, "current")
                                x = float(
                                    open(os.path.join(apath, 'objective.out')).
                                    readlines()[0].split()[1]) * self.factor
                                grad[p], _ = f12d3p(fdwrap(reader,
                                                           mvals,
                                                           p,
                                                           h=self.h),
                                                    h=self.h,
                                                    f0=x)
                            else:
                                grad[p], _ = f12d3p(fdwrap(self.driver,
                                                           mvals,
                                                           p,
                                                           d=d),
                                                    h=self.h,
                                                    f0=x)
                        else:
                            if wq is not None:
                                # Since the calculations are submitted as 3-point finite difference, this part of the code
                                # actually only reads from half of the completed calculations.
                                grad[p] = f1d2p(fdwrap(reader,
                                                       mvals,
                                                       p,
                                                       h=self.h),
                                                h=self.h,
                                                f0=x)
                            else:
                                grad[p] = f1d2p(fdwrap(self.driver,
                                                       mvals,
                                                       p,
                                                       d=d),
                                                h=self.h,
                                                f0=x)

            self.objd[d] = x
            self.gradd[d] = grad
            self.hdiagd[d] = hdiag
            X += x
            G += grad
            #H += np.diag(hdiag)
            H += hess
        if not in_fd():
            self.objective = X
            self.objvals = self.objd
        # print self.objd
        # print self.gradd
        # print self.hdiagd

        if float('Inf') in pvals:
            return {'X': 1e10, 'G': G, 'H': H}
        return {'X': X, 'G': G, 'H': H}
Beispiel #47
0
    def get(self, mvals, AGrad=False, AHess=False):
        """
        LPW 05-30-2012
        
        This subroutine builds the objective function (and optionally
        its derivatives) from a general software.  

        This subroutine interfaces with simulation software 'drivers'.
        The driver is expected to give exact values, fitting values, and weights.

        @param[in] mvals Mathematical parameter values
        @param[in] AGrad Switch to turn on analytic gradient
        @param[in] AHess Switch to turn on analytic Hessian
        @return Answer Contribution to the objective function
        """
        global LAST_MVALS, CHECK_BASIS
        # print mvals
        # print LAST_MVALS
        # print mvals == LAST_MVALS
        if LAST_MVALS == None or not (mvals == LAST_MVALS).all():
            CHECK_BASIS = False
        else:
            CHECK_BASIS = False
        Answer = {}
        Fac = 1000000
        ## Dictionary for derivative terms
        dM = {}
        # Create the new force field!!
        np = len(mvals)
        G = zeros(np, dtype=float)
        H = zeros((np, np), dtype=float)
        pvals = self.FF.make(mvals)
        if float("Inf") in pvals:
            return {"X": 1e10, "G": G, "H": H}
        Ans = self.driver()
        W = Ans[:, 2]
        M = Ans[:, 1]
        Q = Ans[:, 0]
        D = M - Q

        self.MAQ = mean(abs(Q))

        ns = len(M)
        # Wrapper to the driver, which returns just the part that changes.
        def callM(mvals_):
            self.FF.make(mvals_)
            Ans2 = self.driver()
            M_ = Ans2[:, 1]
            D_ = M_ - Q
            return Ans2[:, 1]

        if AGrad:
            # Leaving comment here if we want to reintroduce second deriv someday.
            #     dM[p,:], ddM[p,:] = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = M)
            for p in range(np):
                if self.call_derivatives[p] == False:
                    continue
                dM_arr = f1d2p(fdwrap(callM, mvals, p), h=self.h, f0=M)
                if max(abs(dM_arr)) == 0.0 and Counter() == 0:
                    print "\r Simulation %s will skip over parameter %i in subsequent steps" % (self.name, p)
                    self.call_derivatives[p] = False
                else:
                    dM[p] = dM_arr.copy()
        Objective = dot(W, D ** 2) * Fac
        if AGrad:
            for p in range(np):
                if self.call_derivatives[p] == False:
                    continue
                G[p] = 2 * dot(W, D * dM[p])
                if not AHess:
                    continue
                H[p, p] = 2 * dot(W, dM[p] ** 2)
                for q in range(p):
                    if self.call_derivatives[q] == False:
                        continue
                    GNP = 2 * dot(W, dM[p] * dM[q])
                    H[q, p] = GNP
                    H[p, q] = GNP
        G *= Fac
        H *= Fac
        Answer = {"X": Objective, "G": G, "H": H}
        if not in_fd():
            self.D = D
            self.objective = Answer["X"]
            LAST_MVALS = mvals.copy()
        return Answer
    def get(self, mvals, AGrad=False, AHess=False):
        Answer = {
            'X': 0.0,
            'G': np.zeros(self.FF.np),
            'H': np.zeros((self.FF.np, self.FF.np))
        }
        self.PrintDict = OrderedDict()

        def compute(mvals_, indicate=False):
            self.FF.make(mvals_)
            M_opts = None
            compute.emm = []
            compute.rmsd = []
            for i in range(self.ns):
                energy, rmsd, M_opt = self.engine.optimize(shot=i, align=False)
                # Create a molecule object to hold the MM-optimized structures
                compute.emm.append(energy)
                compute.rmsd.append(rmsd)
                if M_opts is None:
                    M_opts = deepcopy(M_opt)
                else:
                    M_opts += M_opt
            compute.emm = np.array(compute.emm)
            compute.emm -= compute.emm[self.smin]
            compute.rmsd = np.array(compute.rmsd)
            if indicate:
                if self.writelevel > 0:
                    M_opts.write('mm_minimized.xyz')
                    if self.ndim == 1:
                        import matplotlib.pyplot as plt
                        plt.switch_backend('agg')
                        fig, ax = plt.subplots()
                        dihedrals = np.array(
                            [i[0] for i in self.metadata['torsion_grid_ids']])
                        dsort = np.argsort(dihedrals)
                        ax.plot(dihedrals[dsort], self.eqm[dsort], label='QM')
                        if hasattr(self, 'emm_orig'):
                            ax.plot(dihedrals[dsort],
                                    compute.emm[dsort],
                                    label='MM Current')
                            ax.plot(dihedrals[dsort],
                                    self.emm_orig[dsort],
                                    label='MM Initial')
                        else:
                            ax.plot(dihedrals[dsort],
                                    compute.emm[dsort],
                                    label='MM Initial')
                            self.emm_orig = compute.emm.copy()
                        ax.legend()
                        ax.set_xlabel('Dihedral (degree)')
                        ax.set_ylabel('Energy (kcal/mol)')
                        fig.suptitle(
                            'Torsion profile: iteration %i\nSystem: %s' %
                            (Counter(), self.name))
                        fig.savefig('plot_torsion.pdf')
            return (np.sqrt(self.wts) / self.energy_denom) * (compute.emm -
                                                              self.eqm)

        compute.emm = None
        compute.rmsd = None

        V = compute(mvals, indicate=True)

        Answer['X'] = np.dot(V, V)

        # Energy RMSE
        e_rmse = np.sqrt(np.dot(self.wts, (compute.emm - self.eqm)**2))

        self.PrintDict[
            self.
            name] = '%10s %10s    %6.3f - %-6.3f   % 6.3f - %-6.3f    %6.3f    %7.4f   % 7.4f' % (
                ','.join([
                    '%i' % i
                    for i in self.metadata['torsion_grid_ids'][self.smin]
                ]), ','.join([
                    '%i' % i for i in self.metadata['torsion_grid_ids'][
                        np.argmin(compute.emm)]
                ]), min(self.eqm), max(self.eqm), min(compute.emm),
                max(compute.emm), max(compute.rmsd), e_rmse, Answer['X'])

        # compute gradients and hessian
        dV = np.zeros((self.FF.np, len(V)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p, :], _ = f12d3p(fdwrap(compute, mvals, p), h=self.h, f0=V)

        for p in self.pgrad:
            Answer['G'][p] = 2 * np.dot(V, dV[p, :])
            for q in self.pgrad:
                Answer['H'][p, q] = 2 * np.dot(dV[p, :], dV[q, :])
        if not in_fd():
            self.objective = Answer['X']
            self.FF.make(mvals)
        return Answer
Beispiel #49
0
                    FK_lines.append(LI_lines[key][0])
                else:
                    FK_lines.append(line)
            o = wopen('franken.gbs')
            for line in FK_lines:
                print >> o, line,
            o.close()
            _exec("cp %s.bak %s" % (self.GBSfnm, self.GBSfnm), print_command=False)
            
            if len(list(itertools.chain(*(self.FF.linedestroy_save + [self.FF.linedestroy_this])))) > 0:
                logger.info("All lines removed: " + self.FF.linedestroy_save + [self.FF.linedestroy_this] + '\n')
                logger.info("All prms removed: " + self.FF.prmdestroy_save + [self.FF.prmdestroy_this] + '\n')

        self.write_nested_destroy(self.GBSfnm, self.FF.linedestroy_save + [self.FF.linedestroy_this])
        _exec("psi4", print_command=False, outfnm="psi4.stdout")
        if not in_fd():
            for line in open('psi4.stdout').readlines():
                if "MP2 Energy:" in line:
                    self.MP2_Energy = float(line.split()[-1])
                elif "DF Energy:" in line:
                    self.DF_Energy = float(line.split()[-1])
        Ans = np.array([[float(i) for i in line.split()] for line in open("objective.dat").readlines()])
        os.unlink("objective.dat")
        return Ans

class Grid_Reader(BaseReader):
    """Finite state machine for parsing DVR grid files.
    
    """
    
    def __init__(self,fnm=None):
Beispiel #50
0
    def get(self, mvals, AGrad=False, AHess=False):
        Answer = {
            'X': 0.0,
            'G': np.zeros(self.FF.np),
            'H': np.zeros((self.FF.np, self.FF.np))
        }
        self.PrintDict = OrderedDict()
        # enable self.system_mval_masks (supported by OptGeoTarget_SMIRNOFF)
        enable_system_mval_mask = hasattr(self, 'system_mval_masks')

        def compute(mvals, p_idx=None):
            ''' Compute total objective value for each system '''
            self.FF.make(mvals)
            v_obj_list = []
            for sysname, sysopt in self.sys_opts.items():
                # ref values of each type
                vref_bonds = self.internal_coordinates[sysname]['vref_bonds']
                vref_angles = self.internal_coordinates[sysname]['vref_angles']
                vref_dihedrals = self.internal_coordinates[sysname][
                    'vref_dihedrals']
                vref_impropers = self.internal_coordinates[sysname][
                    'vref_impropers']
                # counts of each type
                n_bonds = len(vref_bonds)
                n_angles = len(vref_angles)
                n_dihedrals = len(vref_dihedrals)
                n_impropers = len(vref_impropers)
                # use self.system_mval_masks to skip evaluations when computing gradients
                if enable_system_mval_mask and in_fd() and (
                        p_idx is not None) and (
                            self.system_mval_masks[sysname][p_idx] == False):
                    v_obj_list += [0] * (n_bonds + n_angles + n_dihedrals +
                                         n_impropers)
                    continue
                # read denominators from system options
                bond_denom = sysopt['bond_denom']
                angle_denom = sysopt['angle_denom']
                dihedral_denom = sysopt['dihedral_denom']
                improper_denom = sysopt['improper_denom']
                # inverse demon to be scaling factors, 0 for denom 0
                scale_bond = 1.0 / bond_denom if bond_denom != 0 else 0.0
                scale_angle = 1.0 / angle_denom if angle_denom != 0 else 0.0
                scale_dihedral = 1.0 / dihedral_denom if dihedral_denom != 0 else 0.0
                scale_improper = 1.0 / improper_denom if improper_denom != 0 else 0.0
                # calculate new internal coordinates
                v_ic = self.system_driver(sysname)
                # objective contribution from bonds
                vtar_bonds = v_ic['bonds']
                diff_bond = ((vref_bonds - vtar_bonds) *
                             scale_bond).tolist() if n_bonds > 0 else []
                # objective contribution from angles
                vtar_angles = v_ic['angles']
                diff_angle = (periodic_diff(vref_angles, vtar_angles, 360) *
                              scale_angle).tolist() if n_angles > 0 else []
                # objective contribution from dihedrals
                vtar_dihedrals = v_ic['dihedrals']
                diff_dihedral = (
                    periodic_diff(vref_dihedrals, vtar_dihedrals, 360) *
                    scale_dihedral).tolist() if n_dihedrals > 0 else []
                # objective contribution from improper dihedrals
                vtar_impropers = v_ic['impropers']
                diff_improper = (
                    periodic_diff(vref_impropers, vtar_impropers, 360) *
                    scale_improper).tolist() if n_impropers > 0 else []
                # combine objective values into a big result list
                sys_obj_list = diff_bond + diff_angle + diff_dihedral + diff_improper
                # extend the result v_obj_list by individual terms in this system
                v_obj_list += sys_obj_list
                # save print string
                if not in_fd():
                    # For printing, we group the RMSD by type
                    rmsd_bond = compute_rmsd(vref_bonds, vtar_bonds)
                    rmsd_angle = compute_rmsd(vref_angles,
                                              vtar_angles,
                                              v_periodic=360)
                    rmsd_dihedral = compute_rmsd(vref_dihedrals,
                                                 vtar_dihedrals,
                                                 v_periodic=360)
                    rmsd_improper = compute_rmsd(vref_impropers,
                                                 vtar_impropers,
                                                 v_periodic=360)
                    obj_total = sum(v**2 for v in sys_obj_list)
                    self.PrintDict[sysname] = "% 9.3f % 7.2f % 9.3f % 7.2f % 9.3f % 7.2f % 9.3f % 7.2f %17.3f" % (rmsd_bond, \
                        bond_denom, rmsd_angle, angle_denom, rmsd_dihedral, dihedral_denom, rmsd_improper, improper_denom, obj_total)
            return np.array(v_obj_list, dtype=float)

        V = compute(mvals)
        Answer['X'] = np.dot(V, V)
        # write objective decomposition if wanted
        if self.writelevel > 0:
            # recover mvals
            self.FF.make(mvals)
            with open('rmsd_decomposition.txt', 'w') as fout:
                for sysname in self.internal_coordinates:
                    fout.write("\n[ %s ]\n" % sysname)
                    fout.write('%-25s %15s %15s %15s\n' %
                               ("Internal Coordinate", "Ref QM Value",
                                "Cur MM Value", "Difference"))
                    # reference data
                    sys_data = self.internal_coordinates[sysname]
                    sys_data['ic_bonds']
                    # compute all internal coordinate values again
                    v_ic = self.system_driver(sysname)
                    for p in ['bonds', 'angles', 'dihedrals', 'impropers']:
                        fout.write('--- ' + p + ' ---\n')
                        ic_list = sys_data['ic_' + p]
                        ref_v = sys_data['vref_' + p]
                        tar_v = v_ic[p]
                        # print each value
                        for ic, v1, v2 in zip(ic_list, ref_v, tar_v):
                            diff = periodic_diff(
                                v1, v2,
                                v_periodic=360) if p != 'bonds' else v1 - v2
                            fout.write('%-25s %15.5f %15.5f %+15.3e\n' %
                                       (ic, v1, v2, diff))

        # compute gradients and hessian
        dV = np.zeros((self.FF.np, len(V)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p, :], _ = f12d3p(fdwrap(compute, mvals, p, p_idx=p),
                                     h=self.h,
                                     f0=V)

        for p in self.pgrad:
            Answer['G'][p] = 2 * np.dot(V, dV[p, :])
            for q in self.pgrad:
                Answer['H'][p, q] = 2 * np.dot(dV[p, :], dV[q, :])
        if not in_fd():
            self.objective = Answer['X']
            self.FF.make(mvals)
        return Answer
Beispiel #51
0
    def get(self, mvals, AGrad=False, AHess=False):
	"""
        LPW 04-17-2013
        
        This subroutine builds the objective function from Psi4.

        @param[in] mvals Mathematical parameter values
        @param[in] AGrad Switch to turn on analytic gradient
        @param[in] AHess Switch to turn on analytic Hessian
        @return Answer Contribution to the objective function
        """
        Answer = {}
        Fac = 1000000
        n = len(mvals)
        X = 0.0
        G = np.zeros(n)
        H = np.zeros((n,n))
        pvals = self.FF.make(mvals)
        self.tdir = os.getcwd()
        self.objd = OrderedDict()
        self.gradd = OrderedDict()
        self.hdiagd = OrderedDict()
        wq = getWorkQueue()

        def fdwrap2(func,mvals0,pidx,qidx,key=None,**kwargs):
            def func2(arg1,arg2):
                mvals = list(mvals0)
                mvals[pidx] += arg1
                mvals[qidx] += arg2
                logger.info("\rfdwrap2:" + func.__name__ + "[%i] = % .1e , [%i] = % .1e" % (pidx, arg1, qidx, arg2) + ' '*50)
                if key != None:
                    return func(mvals,**kwargs)[key]
                else:
                    return func(mvals,**kwargs)
            return func2

        def f2d5p(f, h):
            fpp, fpm, fmp, fmm = [f(i*h,j*h) for i,j in [(1,1),(1,-1),(-1,1),(-1,-1)]]
            fpp = (fpp-fpm-fmp+fmm)/(4*h*h)
            return fpp

        def f2d4p(f, h, f0 = None):
            if f0 == None:
                fpp, fp0, f0p, f0 = [f(i*h,j*h) for i,j in [(1,1),(1,0),(0,1),(0,0)]]
            else:
                fpp, fp0, f0p = [f(i*h,j*h) for i,j in [(1,1),(1,0),(0,1)]]
            fpp = (fpp-fp0-f0p+f0)/(h*h)
            return fpp

        for d in self.objfiles:
            logger.info("\rNow working on" + str(d) + 50*' ' + '\r')
            if wq == None:
                x = self.driver(mvals, d)
            grad  = np.zeros(n)
            hdiag = np.zeros(n)
            hess  = np.zeros((n,n))
            apath = os.path.join(self.tdir, d, "current")
            x = float(open(os.path.join(apath,'objective.out')).readlines()[0].split()[1])*self.factor
            for p in range(self.FF.np):
                if self.callderivs[d][p]:
                    def reader(mvals_,h):
                        apath = os.path.join(self.tdir, d, str(p), str(h))
                        answer = float(open(os.path.join(apath,'objective.out')).readlines()[0].split()[1])*self.factor
                        return answer
                    if AHess:
                        if wq != None:
                            apath = os.path.join(self.tdir, d, "current")
                            x = float(open(os.path.join(apath,'objective.out')).readlines()[0].split()[1])*self.factor
                            grad[p], hdiag[p] = f12d3p(fdwrap(reader, mvals, p, h=self.h), h = self.h, f0 = x)
                        else:
                            grad[p], hdiag[p] = f12d3p(fdwrap(self.driver, mvals, p, d=d), h = self.h, f0 = x)
                        hess[p,p] = hdiag[p]
                    elif AGrad:
                        if self.bidirect:
                            if wq != None:
                                apath = os.path.join(self.tdir, d, "current")
                                x = float(open(os.path.join(apath,'objective.out')).readlines()[0].split()[1])*self.factor
                                grad[p], _ = f12d3p(fdwrap(reader, mvals, p, h=self.h), h = self.h, f0 = x)
                            else:
                                grad[p], _ = f12d3p(fdwrap(self.driver, mvals, p, d=d), h = self.h, f0 = x)
                        else:
                            if wq != None:
                                # Since the calculations are submitted as 3-point finite difference, this part of the code
                                # actually only reads from half of the completed calculations.
                                grad[p] = f1d2p(fdwrap(reader, mvals, p, h=self.h), h = self.h, f0 = x)
                            else:
                                grad[p] = f1d2p(fdwrap(self.driver, mvals, p, d=d), h = self.h, f0 = x)
                            
            self.objd[d] = x
            self.gradd[d] = grad
            self.hdiagd[d] = hdiag
            X += x
            G += grad
            #H += np.diag(hdiag)
            H += hess
        if not in_fd():
            self.objective = X
            self.objvals = self.objd
        # print self.objd
        # print self.gradd
        # print self.hdiagd
                    
        if float('Inf') in pvals:
            return {'X' : 1e10, 'G' : G, 'H' : H}
        return {'X' : X, 'G' : G, 'H' : H}
Beispiel #52
0
    def get(self, mvals, AGrad=False, AHess=False):
        """ Evaluate objective function. """
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}

        # If the weight is zero, turn all derivatives off.
        if (self.weight == 0.0):
            AGrad = False
            AHess = False

        def callM(mvals_, dielectric=False):
            logger.info("\r")
            pvals = self.FF.make(mvals_)
            return self.engine.interaction_energy(self.select1, self.select2)

        logger.info("Executing\r")
        emm = callM(mvals)

        D = emm - self.eqm
        dV = np.zeros((self.FF.np,len(emm)))

        if self.writelevel > 0:
            # Dump interaction energies to disk.
            np.savetxt('M.txt',emm)
            np.savetxt('Q.txt',self.eqm)
            import pickle
            pickle.dump((self.name, self.label, self.prefactor, self.eqm, emm), open("qm_vs_mm.p",'w'))
            # select the qm and mm data that has >0 weight to plot
            qm_data, mm_data = [], []
            for i in xrange(len(self.eqm)):
                if self.prefactor[i] != 0:
                    qm_data.append(self.eqm[i])
                    mm_data.append(emm[i])
            plot_interaction_qm_vs_mm(qm_data, mm_data, title="Interaction Energy "+self.name)

        # Do the finite difference derivative.
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(callM, mvals, p), h = self.h, f0 = emm)
            # Create the force field one last time.
            pvals  = self.FF.make(mvals)

        Answer['X'] = np.dot(self.prefactor*D/self.divisor,D/self.divisor)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(self.prefactor*D/self.divisor, dV[p,:]/self.divisor)
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(self.prefactor*dV[p,:]/self.divisor, dV[q,:]/self.divisor)

        if not in_fd():
            self.emm = emm
            self.objective = Answer['X']

        ## QYD: try to clean up OpenMM engine.simulation objects to free up GPU memory
        try:
            if self.engine.name == 'openmm':
                if hasattr(self.engine, 'simulation'): del self.engine.simulation
                if hasattr(self.engine, 'A'): del self.engine.A
                if hasattr(self.engine, 'B'): del self.engine.B
        except:
            pass

        return Answer
Beispiel #53
0
    def get(self, mvals, AGrad=False, AHess=False):
        Answer = {'X':0.0, 'G':np.zeros(self.FF.np), 'H':np.zeros((self.FF.np, self.FF.np))}
        self.PrintDict = OrderedDict()
        self.RMSDDict = OrderedDict()
        EnergyDict = OrderedDict()
        #pool = Pool(processes=4)
        def compute(mvals_):
            # This function has automatically assigned variable names from the interaction master file
            # Thus, all variable names in here are protected using an underscore.
            self.FF.make(mvals_)
            VectorD_ = []
            for sys_ in self.sys_opts:
                Energy_, RMSD_ = self.system_driver(sys_)
                # Energies are stored in a dictionary.
                EnergyDict[sys_] = Energy_
                RMSDNrm_ = RMSD_ / self.rmsd_denom
                w_ = self.sys_opts[sys_]['rmsd_weight'] if 'rmsd_weight' in self.sys_opts[sys_] else 1.0
                VectorD_.append(np.sqrt(w_)*RMSDNrm_)
                if not in_fd() and RMSD_ != 0.0:
                    self.RMSDDict[sys_] = "% 9.3f % 12.5f" % (RMSD_, w_*RMSDNrm_**2)
            VectorE_ = []
            for inter_ in self.inter_opts:
                def encloseInDictionary(matchobj):
                    return 'EnergyDict["' + matchobj.group(0)+'"]'
                # Here we need to evaluate a mathematical expression of the stored variables in EnergyDict.
                # We start by enclosing every variable in EnergyDict[""] and then calling eval on it.
                evalExpr = re.sub('[A-Za-z_][A-Za-z0-9_]*', encloseInDictionary, self.inter_opts[inter_]['equation'])
                Calculated_ = eval(evalExpr)
                Reference_ = self.inter_opts[inter_]['reference_physical']
                Delta_ = Calculated_ - Reference_
                Denom_ = self.energy_denom
                if self.cauchy:
                    Divisor_ = np.sqrt(Denom_**2 + Reference_**2)
                elif self.attenuate:
                    if Reference_ < Denom_:
                        Divisor_ = Denom_
                    else:
                        Divisor_ = np.sqrt(Denom_**2 + (Reference_-Denom_)**2)
                else:
                    Divisor_ = Denom_
                DeltaNrm_ = Delta_ / Divisor_
                w_ = self.inter_opts[inter_]['weight'] if 'weight' in self.inter_opts[inter_] else 1.0
                VectorE_.append(np.sqrt(w_)*DeltaNrm_)
                if not in_fd():
                    self.PrintDict[inter_] = "% 9.3f % 9.3f % 9.3f % 12.5f" % (Calculated_, Reference_, Delta_, w_*DeltaNrm_**2)
                # print "%-20s" % inter_, "Calculated:", Calculated_, "Reference:", Reference_, "Delta:", Delta_, "DeltaNrm:", DeltaNrm_
            # The return value is an array of normalized interaction energy differences.
            if not in_fd():
                self.rmsd_part = np.dot(np.array(VectorD_),np.array(VectorD_))
                if len(VectorE_) > 0:
                    self.energy_part = np.dot(np.array(VectorE_),np.array(VectorE_))
                else:
                    self.energy_part = 0.0
            if len(VectorE_) > 0 and len(VectorD_) > 0:
                return np.array(VectorD_ + VectorE_)
            elif len(VectorD_) > 0:
                return np.array(VectorD_)
            elif len(VectorE_) > 0:
                return np.array(VectorE_)
                    
        V = compute(mvals)

        dV = np.zeros((self.FF.np,len(V)))
        if AGrad or AHess:
            for p in self.pgrad:
                dV[p,:], _ = f12d3p(fdwrap(compute, mvals, p), h = self.h, f0 = V)

        Answer['X'] = np.dot(V,V)
        for p in self.pgrad:
            Answer['G'][p] = 2*np.dot(V, dV[p,:])
            for q in self.pgrad:
                Answer['H'][p,q] = 2*np.dot(dV[p,:], dV[q,:])

        if not in_fd():
            self.objective = Answer['X']
            self.FF.make(mvals)

        return Answer