Esempio n. 1
0
    def get_G(self, mvals=None, customdir=None):
        """Computes the objective function contribution and its gradient.

        First the low-level 'get' method is called with the analytic gradient
        switch turned on.  Then we loop through the fd1_pids and compute
        the corresponding elements of the gradient by finite difference,
        if the 'fdgrad' switch is turned on.  Alternately we can compute
        the gradient elements and diagonal Hessian elements at the same time
        using central difference if 'fdhessdiag' is turned on.

        In this function we also record which parameters cause a
        nonzero change in the objective function contribution.
        Parameters which do not change the objective function will
        not be differentiated in subsequent calculations.  This is
        recorded in a text file in the targets directory.

        """
        Ans = self.meta_get(mvals, 1, 0, customdir=customdir)
        for i in self.pgrad:
            if any([j in self.FF.plist[i]
                    for j in self.fd1_pids]) or 'ALL' in self.fd1_pids:
                if self.fdhessdiag:
                    Ans['G'][i], Ans['H'][i,
                                          i] = f12d3p(fdwrap_G(self, mvals, i),
                                                      self.h,
                                                      f0=Ans['X'])
                elif self.fdgrad:
                    Ans['G'][i] = f1d2p(fdwrap_G(self, mvals, i),
                                        self.h,
                                        f0=Ans['X'])
        self.gct += 1
        if Counter() == self.zerograd and self.zerograd >= 0:
            self.write_0grads(Ans)
        return Ans
Esempio n. 2
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
Esempio n. 3
0
def energy_dipole_derivatives(mvals,h,FF,xyz,tky,AGrad=True):

    """
    Compute the first and second derivatives of a set of snapshot
    energies with respect to the force field parameters.

    This basically calls the finite difference subroutine on the
    energy_driver subroutine also in this script.

    @todo This is a sufficiently general function to be merged into openmmio.py?
    @param[in] mvals Mathematical parameter values
    @param[in] pdb OpenMM PDB object
    @param[in] FF ForceBalance force field object
    @param[in] xyzs List of OpenMM positions
    @param[in] settings OpenMM settings for creating the System
    @param[in] boxes Periodic box vectors
    @return G First derivative of the energies in a N_param x N_coord array

    """
    ED0      = energy_driver(mvals, FF, xyz=xyz, tky=tky, dipole=True)
    ns       = ED0.shape[0]
    G        = np.zeros((FF.np,ns))
    GDx      = np.zeros((FF.np,ns))
    GDy      = np.zeros((FF.np,ns))
    GDz      = np.zeros((FF.np,ns))
    if not AGrad:
        return G, GDx, GDy, GDz
    CheckFDPts = False
    for i in range(FF.np):
        EDG, _   = f12d3p(fdwrap(energy_driver,mvals,i,FF=FF,xyz=xyz,tky=tky,dipole=True),h,f0=ED0)
        G[i,:]   = EDG[:,0]
        GDx[i,:] = EDG[:,1]
        GDy[i,:] = EDG[:,2]
        GDz[i,:] = EDG[:,3]
    return G, GDx, GDy, GDz
Esempio n. 4
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
Esempio n. 5
0
    def get_H(self,mvals=None):
        """Computes the objective function contribution and its gradient / Hessian.

        First the low-level 'get' method is called with the analytic gradient
        and Hessian both turned on.  Then we loop through the fd1_pids and compute
        the corresponding elements of the gradient by finite difference,
        if the 'fdgrad' switch is turned on.

        This is followed by looping through the fd2_pids and computing the corresponding
        Hessian elements by finite difference.  Forward finite difference is used
        throughout for the sake of speed.
        """
        Ans = self.meta_get(mvals,1,1)
        if self.fdhess:
            for i in self.pgrad:
                if any([j in self.FF.plist[i] for j in self.fd1_pids]) or 'ALL' in self.fd1_pids:
                    Ans['G'][i] = f1d2p(fdwrap_G(self,mvals,i),self.h,f0 = Ans['X'])
            for i in self.pgrad:
                if any([j in self.FF.plist[i] for j in self.fd2_pids]) or 'ALL' in self.fd2_pids:
                    FDSlice = f1d2p(fdwrap_H(self,mvals,i),self.h,f0 = Ans['G'])
                    Ans['H'][i,:] = FDSlice
                    Ans['H'][:,i] = FDSlice
        elif self.fdhessdiag:
            for i in self.pgrad:
                if any([j in self.FF.plist[i] for j in self.fd2_pids]) or 'ALL' in self.fd2_pids:
                    Ans['G'][i], Ans['H'][i,i] = f12d3p(fdwrap_G(self,mvals,i),self.h, f0 = Ans['X'])
        self.write_0grads(Ans)
        self.hct += 1
        return Ans
Esempio n. 6
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
Esempio n. 7
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
Esempio n. 8
0
    def get_H(self,mvals=None,customdir=None):
        """Computes the objective function contribution and its gradient / Hessian.

        First the low-level 'get' method is called with the analytic gradient
        and Hessian both turned on.  Then we loop through the fd1_pids and compute
        the corresponding elements of the gradient by finite difference,
        if the 'fdgrad' switch is turned on.

        This is followed by looping through the fd2_pids and computing the corresponding
        Hessian elements by finite difference.  Forward finite difference is used
        throughout for the sake of speed.
        """
        Ans = self.meta_get(mvals,1,1,customdir=customdir)
        if self.fdhess:
            for i in self.pgrad:
                if any([j in self.FF.plist[i] for j in self.fd1_pids]) or 'ALL' in self.fd1_pids:
                    Ans['G'][i] = f1d2p(fdwrap_G(self,mvals,i),self.h,f0 = Ans['X'])
            for i in self.pgrad:
                if any([j in self.FF.plist[i] for j in self.fd2_pids]) or 'ALL' in self.fd2_pids:
                    FDSlice = f1d2p(fdwrap_H(self,mvals,i),self.h,f0 = Ans['G'])
                    Ans['H'][i,:] = FDSlice
                    Ans['H'][:,i] = FDSlice
        elif self.fdhessdiag:
            for i in self.pgrad:
                if any([j in self.FF.plist[i] for j in self.fd2_pids]) or 'ALL' in self.fd2_pids:
                    Ans['G'][i], Ans['H'][i,i] = f12d3p(fdwrap_G(self,mvals,i),self.h, f0 = Ans['X'])
        if Counter() == self.zerograd and self.zerograd >= 0: 
            self.write_0grads(Ans)
        self.hct += 1
        return Ans
Esempio n. 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_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
Esempio n. 10
0
def energy_derivatives(mvals,h,FF,xyz,tky,AGrad=True):

    """
    Compute the first and second derivatives of a set of snapshot
    energies with respect to the force field parameters.

    This basically calls the finite difference subroutine on the
    energy_driver subroutine also in this script.

    @todo This is a sufficiently general function to be merged into openmmio.py?
    @param[in] mvals Mathematical parameter values
    @param[in] pdb OpenMM PDB object
    @param[in] FF ForceBalance force field object
    @param[in] xyzs List of OpenMM positions
    @param[in] settings OpenMM settings for creating the System
    @param[in] boxes Periodic box vectors
    @return G First derivative of the energies in a N_param x N_coord array

    """
    E0       = energy_driver(mvals, FF, xyz, tky)
    ns       = len(E0)
    G        = np.zeros((FF.np,ns))
    if not AGrad:
        return G
    CheckFDPts = False
    for i in range(FF.np):
        G[i,:], _ = f12d3p(fdwrap(energy_driver,mvals,i,FF=FF,xyz=xyz,tky=tky),h,f0=E0)
        if CheckFDPts:
            # Check whether the number of finite difference points is sufficient.  Forward difference still gives residual error of a few percent.
            G1 = f1d7p(fdwrap(energy_driver,mvals,i,FF=FF,xyz=xyz,tky=tky),h)
            dG = G1 - G[i,:]
            dGfrac = (G1 - G[i,:]) / G[i,:]
            print "Parameter %3i 7-pt vs. central derivative : RMS, Max error (fractional) = % .4e % .4e (% .4e % .4e)" % (i, np.sqrt(np.mean(dG**2)), max(np.abs(dG)), np.sqrt(np.mean(dGfrac**2)), max(np.abs(dGfrac)))
    return G
Esempio n. 11
0
    def get_G(self,mvals=None):
        """Computes the objective function contribution and its gradient.

        First the low-level 'get' method is called with the analytic gradient
        switch turned on.  Then we loop through the fd1_pids and compute
        the corresponding elements of the gradient by finite difference,
        if the 'fdgrad' switch is turned on.  Alternately we can compute
        the gradient elements and diagonal Hessian elements at the same time
        using central difference if 'fdhessdiag' is turned on.

        In this function we also record which parameters cause a
        nonzero change in the objective function contribution.
        Parameters which do not change the objective function will
        not be differentiated in subsequent calculations.  This is
        recorded in a text file in the targets directory.

        """
        Ans = self.meta_get(mvals,1,0)
        for i in self.pgrad:
            if any([j in self.FF.plist[i] for j in self.fd1_pids]) or 'ALL' in self.fd1_pids:
                if self.fdhessdiag:
                    Ans['G'][i], Ans['H'][i,i] = f12d3p(fdwrap_G(self,mvals,i),self.h,f0 = Ans['X'])
                elif self.fdgrad:
                    Ans['G'][i] = f1d2p(fdwrap_G(self,mvals,i),self.h,f0 = Ans['X'])
        self.gct += 1
        self.write_0grads(Ans)
        return Ans
Esempio n. 12
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
Esempio n. 13
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
Esempio n. 14
0
def energy_derivatives(engine,
                       FF,
                       mvals,
                       h,
                       pgrad,
                       length,
                       AGrad=True,
                       dipole=False):
    """
    Compute the first and second derivatives of a set of snapshot
    energies with respect to the force field parameters.

    This basically calls the finite difference subroutine on the
    energy_driver subroutine also in this script.

    @param[in] mvals Mathematical parameter values
    @param[in] h Finite difference step size
    @param[in] phase The phase (liquid, gas) to perform the calculation on
    @param[in] AGrad Switch to turn derivatives on or off; if off, return all zeros
    @param[in] dipole Switch for dipole derivatives.
    @return G First derivative of the energies in a N_param x N_coord array
    @return GDx First derivative of the box dipole moment x-component in a N_param x N_coord array
    @return GDy First derivative of the box dipole moment y-component in a N_param x N_coord array
    @return GDz First derivative of the box dipole moment z-component in a N_param x N_coord array

    """
    G = np.zeros((FF.np, length))
    GDx = np.zeros((FF.np, length))
    GDy = np.zeros((FF.np, length))
    GDz = np.zeros((FF.np, length))
    if not AGrad:
        return G, GDx, GDy, GDz

    def energy_driver(mvals_):
        FF.make(mvals_)
        if dipole:
            return engine.energy_dipole()
        else:
            return engine.energy()

    ED0 = energy_driver(mvals)
    for i in pgrad:
        logger.info("%i %s\r" % (i, (FF.plist[i] + " " * 30)))
        EDG, _ = f12d3p(fdwrap(energy_driver, mvals, i), h, f0=ED0)
        if dipole:
            G[i, :] = EDG[:, 0]
            GDx[i, :] = EDG[:, 1]
            GDy[i, :] = EDG[:, 2]
            GDz[i, :] = EDG[:, 3]
        else:
            G[i, :] = EDG[:]
    #reset FF parameters
    FF.make(mvals)
    return G, GDx, GDy, GDz
Esempio n. 15
0
 def get_sp(self, mvals, AGrad=False, AHess=False):
     """ Get the hydration free energy and first parameteric derivatives using single point energy evaluations. """
     def get_hfe(mvals_):
         self.FF.make(mvals_)
         self.hfe_dict = self.hydration_driver_sp()
         return np.array(self.hfe_dict.values())
     calc_hfe = get_hfe(mvals)
     D = calc_hfe - np.array(self.expval.values())
     dD = np.zeros((self.FF.np,len(self.IDs)))
     if AGrad or AHess:
         for p in self.pgrad:
             dD[p,:], _ = f12d3p(fdwrap(get_hfe, mvals, p), h = self.h, f0 = calc_hfe)
     return D, dD
Esempio n. 16
0
 def get_sp(self, mvals, AGrad=False, AHess=False):
     """ Get the hydration free energy and first parameteric derivatives using single point energy evaluations. """
     def get_hfe(mvals_):
         self.FF.make(mvals_)
         self.hfe_dict = self.hydration_driver_sp()
         return np.array(list(self.hfe_dict.values()))
     calc_hfe = get_hfe(mvals)
     D = calc_hfe - np.array(list(self.expval.values()))
     dD = np.zeros((self.FF.np,len(self.IDs)))
     if AGrad or AHess:
         for p in self.pgrad:
             dD[p,:], _ = f12d3p(fdwrap(get_hfe, mvals, p), h = self.h, f0 = calc_hfe)
     return D, dD
Esempio n. 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))}

        # 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
Esempio n. 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)
            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
Esempio n. 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))}

        # 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
Esempio n. 20
0
def energy_derivatives(engine, FF, mvals, h, pgrad, length, AGrad=True, dipole=False):

    """
    Compute the first and second derivatives of a set of snapshot
    energies with respect to the force field parameters.

    This basically calls the finite difference subroutine on the
    energy_driver subroutine also in this script.

    @param[in] mvals Mathematical parameter values
    @param[in] h Finite difference step size
    @param[in] phase The phase (liquid, gas) to perform the calculation on
    @param[in] AGrad Switch to turn derivatives on or off; if off, return all zeros
    @param[in] dipole Switch for dipole derivatives.
    @return G First derivative of the energies in a N_param x N_coord array
    @return GDx First derivative of the box dipole moment x-component in a N_param x N_coord array
    @return GDy First derivative of the box dipole moment y-component in a N_param x N_coord array
    @return GDz First derivative of the box dipole moment z-component in a N_param x N_coord array

    """
    G        = np.zeros((FF.np,length))
    GDx      = np.zeros((FF.np,length))
    GDy      = np.zeros((FF.np,length))
    GDz      = np.zeros((FF.np,length))
    if not AGrad:
        return G, GDx, GDy, GDz
    def energy_driver(mvals_):
        FF.make(mvals_)
        if dipole:
            return engine.energy_dipole()
        else:
            return engine.energy()

    ED0      = energy_driver(mvals)
    for i in pgrad:
        logger.info("%i %s\r" % (i, (FF.plist[i] + " "*30)))
        EDG, _   = f12d3p(fdwrap(energy_driver,mvals,i),h,f0=ED0)
        if dipole:
            G[i,:]   = EDG[:,0]
            GDx[i,:] = EDG[:,1]
            GDy[i,:] = EDG[:,2]
            GDz[i,:] = EDG[:,3]
        else:
            G[i,:]   = EDG[:]
    #reset FF parameters
    FF.make(mvals)
    return G, GDx, GDy, GDz
Esempio n. 21
0
def energy_derivatives(engine, FF, mvals, h, pgrad, dipole=False):

    """
    Compute the first and second derivatives of a set of snapshot
    energies with respect to the force field parameters.

    This basically calls the finite difference subroutine on the
    energy_driver subroutine also in this script.

    In the future we may need to be more sophisticated with
    controlling the quantities which are differentiated, but for
    now this is okay..

    @param[in] engine Engine object for calculating energies
    @param[in] FF Force field object
    @param[in] mvals Mathematical parameter values
    @param[in] h Finite difference step size
    @param[in] pgrad List of active parameters for differentiation
    @param[in] dipole Switch for dipole derivatives.
    @return G First derivative of the energies in a N_param x N_coord array
    @return GDx First derivative of the box dipole moment x-component in a N_param x N_coord array
    @return GDy First derivative of the box dipole moment y-component in a N_param x N_coord array
    @return GDz First derivative of the box dipole moment z-component in a N_param x N_coord array

    """
    def single_point(mvals_):
        FF.make(mvals_)
        if dipole:
            return engine.energy_dipole()
        else:
            return engine.energy()

    ED0 = single_point(mvals)
    G   = OrderedDict()
    G['potential'] = np.zeros((FF.np, ED0.shape[0]))
    if dipole:
        G['dipole'] = np.zeros((FF.np, ED0.shape[0], 3))
    for i in pgrad:
        logger.info("%i %s\r" % (i, (FF.plist[i] + " "*30)))
        edg, _ = f12d3p(fdwrap(single_point,mvals,i),h,f0=ED0)
        if dipole:
            G['potential'][i] = edg[:,0]
            G['dipole'][i]    = edg[:,1:]
        else:
            G['potential'][i] = edg[:]
    return G
Esempio n. 22
0
def energy_derivatives(engine, FF, mvals, h, pgrad, length, AGrad=True):
    """Compute the first derivatives of a set of snapshot energies with respect
    to the force field parameters. The function calls the finite
    difference subroutine on the energy_driver subroutine also in this
    script.

    Parameters
    ----------
    engine : Engine
        Use this Engine (`GMX`,`TINKER`,`OPENMM` etc.) object to get the energy
        snapshots.
    FF : FF
       Force field object.
    mvals : list
        Mathematical parameter values.
    h : float
        Finite difference step size.
    length : int
        Number of snapshots (length of energy trajectory).
    AGrad : Boolean
        Switch that turns derivatives on or off; if off, return all zeros.

    Returns
    -------
    G : np.array
        Derivative of the energy in a FF.np x length array.
    
    """
    G = np.zeros((FF.np, length))

    if not AGrad:
        return G

    def energy_driver(mvals_):
        FF.make(mvals_)
        return engine.energy()

    ED0 = energy_driver(mvals)

    for i in pgrad:
        logger.info("%i %s\r" % (i, (FF.plist[i] + " " * 30)))
        EDG, _ = f12d3p(fdwrap(energy_driver, mvals, i), h, f0=ED0)

        G[i, :] = EDG[:]
    return G
Esempio n. 23
0
def energy_derivatives(engine, FF, mvals, h, pgrad, length, AGrad=True):
    """Compute the first derivatives of a set of snapshot energies with respect
    to the force field parameters. The function calls the finite
    difference subroutine on the energy_driver subroutine also in this
    script.

    Parameters
    ----------
    engine : Engine
        Use this Engine (`GMX`,`TINKER`,`OPENMM` etc.) object to get the energy
        snapshots.
    FF : FF
       Force field object.
    mvals : list
        Mathematical parameter values.
    h : float
        Finite difference step size.
    length : int
        Number of snapshots (length of energy trajectory).
    AGrad : Boolean
        Switch that turns derivatives on or off; if off, return all zeros.

    Returns
    -------
    G : np.array
        Derivative of the energy in a FF.np x length array.
    
    """
    G = np.zeros((FF.np, length))
    
    if not AGrad:
        return G
    def energy_driver(mvals_):
        FF.make(mvals_)
        return engine.energy()

    ED0 = energy_driver(mvals)
        
    for i in pgrad:
        logger.info("%i %s\r" % (i, (FF.plist[i] + " "*30)))
        EDG, _   = f12d3p(fdwrap(energy_driver, mvals, i), h, f0=ED0)

        G[i,:]   = EDG[:]
    return G
Esempio n. 24
0
    def get_G(self,mvals=None):
        """Computes the objective function contribution and its gradient.

        First the low-level 'get' method is called with the analytic gradient
        switch turned on.  Then we loop through the fd1_pids and compute
        the corresponding elements of the gradient by finite difference,
        if the 'fdgrad' switch is turned on.  Alternately we can compute
        the gradient elements and diagonal Hessian elements at the same time
        using central difference if 'fdhessdiag' is turned on.
        """
        Ans = self.sget(mvals,1,0)
        for i in range(self.FF.np):
            if any([j in self.FF.plist[i] for j in self.fd1_pids]) or 'ALL' in self.fd1_pids:
                if self.fdhessdiag:
                    Ans['G'][i], Ans['H'][i,i] = f12d3p(fdwrap_G(self,mvals,i),self.h,f0 = Ans['X'])
                elif self.fdgrad:
                    Ans['G'][i] = f1d2p(fdwrap_G(self,mvals,i),self.h,f0 = Ans['X'])
        self.gct += 1
        return Ans
Esempio n. 25
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
Esempio n. 26
0
def rpmd_energy_derivatives(engine, FF, mvals, h, pgrad, length, AGrad=True, dipole=False):
    """
    Compute the first and second derivatives of a set of snapshot
    energies with respect to the force field parameters.
 
    This is analagous to the energy_derivatives function above, but is 
    specific for calculating derivatives for rpmd, which has 
    an additional term due to the force term in the centroid virial
    estimator.
    """
    G              = np.zeros((FF.np,length))
    GDx            = np.zeros((FF.np,length))
    GDy            = np.zeros((FF.np,length))
    GDz            = np.zeros((FF.np,length))
    RPMDG          = np.zeros((FF.np,length))
    RPMDG_frc_term = np.zeros((FF.np,length))  
    if not AGrad:
        return G, GDx, GDy, GDz, RPMDG, RPMDG_frc_term
    def rpmd_energy_driver(mvals_):
        FF.make(mvals_)
        if dipole:
            return engine.energy_dipole_rpmd()
        else:
            return engine.energy_rpmd()

    ED0 = rpmd_energy_driver(mvals)
    for i in pgrad:
        logger.info("%i %s\r" % (i, (FF.plist[i] + " "*30)))
        ERPMDG, _   = f12d3p(fdwrap(rpmd_energy_driver,mvals,i),h,f0=ED0)
        if dipole:
            G[i,:]              = ERPMDG[:,0] 
            GDx[i,:]            = ERPMDG[:,1] 
            GDy[i,:]            = ERPMDG[:,2]
            GDz[i,:]            = ERPMDG[:,3]
            RPMDG[i,:]          = ERPMDG[:,4]    
            RPMDG_frc_term[i,:] = ERPMDG[:,5]
        else:
            G[i,:]              = ERPMDG[:,0]
            RPMDG[i,:]          = ERPMDG[:,1]
            RPMDG_frc_term[i,:] = ERPMDG[:,2]
    return G, GDx, GDy, GDz, RPMDG, RPMDG_frc_term
Esempio n. 27
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
Esempio n. 28
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_ = []

            # 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_)
                    
        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
Esempio n. 29
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
Esempio n. 30
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}
Esempio n. 31
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
Esempio n. 32
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}
Esempio n. 33
0
    def submit_jobs(self, mvals, AGrad=True, AHess=True):
        # This routine is called by Objective.stage() will run before "get".
        # It submits the jobs to the Work Queue and the stage() function will wait for jobs to complete.
        #
        self.tdir = os.getcwd()
        wq = getWorkQueue()
        if wq is None:
            return

        def submit_psi(this_apath, dname, these_mvals):
            """ Create a grid file and a psi4 input file in the absolute path and submit it to the work queue. """
            cwd = os.getcwd()
            if not os.path.exists(this_apath): os.makedirs(this_apath)
            os.chdir(this_apath)
            self.FF.make(these_mvals)
            o = wopen('objective.dat')
            for line in self.objfiles[d]:
                s = line.split()
                if len(s) > 2 and s[0] == 'path' and s[1] == '=':
                    print("path = '%s'" % os.getcwd(), file=o)
                elif len(s) > 2 and s[0] == 'set' and s[1] == 'objective_path':
                    print("opath = '%s'" % os.getcwd(), file=o)
                    print("set objective_path $opath", file=o)
                else:
                    print(line, end=' ', file=o)
            o.close()
            os.system("rm -f objective.out")
            if wq is None:
                logger.info("There is no Work Queue!!!\n")
                sys.exit()
            else:
                input_files = [(os.path.join(this_apath, i), i)
                               for i in glob.glob("*")]
                input_files += [(os.path.join(self.root, self.tgtdir, dname,
                                              "build.dat"), "build.dat")]
                input_files += [(os.path.join(
                    os.path.split(__file__)[0], "data",
                    "run_psi_rdvr3_objective.sh"),
                                 "run_psi_rdvr3_objective.sh")]
                logger.info("\r")
                queue_up_src_dest(
                    wq,
                    "sh run_psi_rdvr3_objective.sh -c %s &> run_psi_rdvr3_objective.log"
                    % os.path.join(self.root, self.tgtdir, dname),
                    input_files=input_files,
                    output_files=[
                        (os.path.join(this_apath, i), i)
                        for i in ["run_psi_rdvr3_objective.log", "output.dat"]
                    ],
                    verbose=False)
            os.chdir(cwd)

        for d in self.objfiles:
            logger.info("\rNow working on" + str(d) + 50 * ' ' + '\r')
            odir = os.path.join(os.getcwd(), d)
            #if os.path.exists(odir):
            #    shutil.rmtree(odir)
            if not os.path.exists(odir): os.makedirs(odir)
            apath = os.path.join(odir, "current")
            submit_psi(apath, d, mvals)
            for p in range(self.FF.np):

                def subjob(mvals_, h):
                    apath = os.path.join(odir, str(p), str(h))
                    submit_psi(apath, d, mvals_)
                    #logger.info("Will set up a job for %s, parameter %i\n" % (d, p))
                    return 0.0

                if self.callderivs[d][p]:
                    if AHess:
                        f12d3p(fdwrap(subjob, mvals, p, h=self.h),
                               h=self.h,
                               f0=0.0)
                    elif AGrad:
                        if self.bidirect:
                            f12d3p(fdwrap(subjob, mvals, p, h=self.h),
                                   h=self.h,
                                   f0=0.0)
                        else:
                            f1d2p(fdwrap(subjob, mvals, p, h=self.h),
                                  h=self.h,
                                  f0=0.0)
Esempio n. 34
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
Esempio n. 35
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()

        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
Esempio n. 36
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
Esempio n. 37
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
Esempio n. 38
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
Esempio n. 39
0
    def submit_jobs(self, mvals, AGrad=True, AHess=True):
        # This routine is called by Objective.stage() will run before "get".
        # It submits the jobs to the Work Queue and the stage() function will wait for jobs to complete.
        #
        self.tdir = os.getcwd()
        wq = getWorkQueue()
        if wq == None:
            return

        def submit_psi(this_apath, mname, these_mvals):
            """ Create a grid file and a psi4 input file in the absolute path and submit it to the work queue. """
            cwd = os.getcwd()
            if not os.path.exists(this_apath) : os.makedirs(this_apath)
            os.chdir(this_apath)
            self.FF.make(these_mvals)
            o = wopen('objective.dat')
            for line in self.objfiles[d]:
                s = line.split()
                if len(s) > 2 and s[0] == 'path' and s[1] == '=':
                    print >> o, "path = '%s'" % os.getcwd()
                elif len(s) > 2 and s[0] == 'set' and s[1] == 'objective_path':
                    print >> o, "opath = '%s'" % os.getcwd()
                    print >> o, "set objective_path $opath"
                else:
                    print >> o, line,
            o.close()
            os.system("rm -f objective.out")
            if wq == None:
                logger.info("There is no Work Queue!!!\n")
                sys.exit()
            else:
                input_files = [(os.path.join(this_apath, i), i) for i in glob.glob("*")]
                # input_files += [(os.path.join(self.tgtdir,d,"build.dat"), "build.dat")]
                input_files += [(os.path.join(os.path.split(__file__)[0],"data","run_psi_rdvr3_objective.sh"), "run_psi_rdvr3_objective.sh")]
                logger.info("\r")
                queue_up_src_dest(wq,"sh run_psi_rdvr3_objective.sh %s &> run_psi_rdvr3_objective.log" % mname,
                                  input_files=input_files,
                                  output_files=[(os.path.join(this_apath, i),i) for i in ["run_psi_rdvr3_objective.log", "output.dat"]], verbose=False)
            os.chdir(cwd)

        for d in self.objfiles:
            logger.info("\rNow working on" + str(d) + 50*' ' + '\r')
            odir = os.path.join(os.getcwd(),d)
            #if os.path.exists(odir):
            #    shutil.rmtree(odir)
            if not os.path.exists(odir): os.makedirs(odir)
            apath = os.path.join(odir, "current")
            submit_psi(apath, d, mvals)
            for p in range(self.FF.np):
                def subjob(mvals_,h):
                    apath = os.path.join(odir, str(p), str(h))
                    submit_psi(apath, d, mvals_)
                    #logger.info("Will set up a job for %s, parameter %i\n" % (d, p))
                    return 0.0
                if self.callderivs[d][p]:
                    if AHess:
                        f12d3p(fdwrap(subjob, mvals, p, h=self.h), h = self.h, f0 = 0.0)
                    elif AGrad:
                        if self.bidirect:
                            f12d3p(fdwrap(subjob, mvals, p, h=self.h), h = self.h, f0 = 0.0)
                        else:
                            f1d2p(fdwrap(subjob, mvals, p, h=self.h), h = self.h, f0 = 0.0)
Esempio n. 40
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}