def calcDistanceMatrix(coords, cutoff=None): """Calculate matrix of distances between coordinates within *cutoff*. Other matrix entries are set to maximum of calculated distances. :arg coords: a coordinate set or an object with :meth:`getCoords` method. :type coords: :class:`~numpy.ndarray`, :class:`.Atomic` :arg cutoff: cutoff distance for searching the KDTree. Default (**None**) is to use the length of the longest coordinate axis. :type cutoff: None, float """ try: coords = (coords._getCoords() if hasattr(coords, '_getCoords') else coords.getCoords()) except AttributeError: try: checkCoords(coords) except TypeError: raise TypeError('coords must be a Numpy array or an object ' 'with `getCoords` method') n_atoms = coords.shape[0] dist_mat = zeros((n_atoms, n_atoms)) if cutoff is None: cutoff = max(coords.max(axis=0) - coords.min(axis=0)) kdtree = KDTree(coords) kdtree.search(cutoff) dists = kdtree.getDistances() r = 0 for i, j in kdtree.getIndices(): dist_mat[i, j] = dist_mat[j, i] = dists[r] r += 1 for i in range(n_atoms): for j in range(i + 1, n_atoms): if dist_mat[i, j] == 0.: dist_mat[i, j] = dist_mat[j, i] = max(dists) return dist_mat
def buildKirchhoff(self, coords, cutoff=10., gamma=1., **kwargs): """Build Kirchhoff matrix for given coordinate set. :arg coords: a coordinate set or an object with ``getCoords`` method :type coords: :class:`numpy.ndarray` or :class:`.Atomic` :arg cutoff: cutoff distance (Å) for pairwise interactions default is 10.0 Å, , minimum is 4.0 Å :type cutoff: float :arg gamma: spring constant, default is 1.0 :type gamma: float :arg sparse: elect to use sparse matrices, default is **False**. If Scipy is not found, :class:`ImportError` is raised. :type sparse: bool :arg kdtree: elect to use KDTree for building Kirchhoff matrix faster, default is **True** :type kdtree: bool Instances of :class:`Gamma` classes and custom functions are accepted as *gamma* argument. When Scipy is available, user can select to use sparse matrices for efficient usage of memory at the cost of computation speed.""" try: coords = (coords._getCoords() if hasattr(coords, '_getCoords') else coords.getCoords()) except AttributeError: try: checkCoords(coords) except TypeError: raise TypeError('coords must be a Numpy array or an object ' 'with `getCoords` method') cutoff, g, gamma = checkENMParameters(cutoff, gamma) self._reset() self._cutoff = cutoff self._gamma = g n_atoms = coords.shape[0] start = time.time() if kwargs.get('sparse', False): try: from scipy import sparse as scipy_sparse except ImportError: raise ImportError('failed to import scipy.sparse, which is ' 'required for sparse matrix calculations') kirchhoff = scipy_sparse.lil_matrix((n_atoms, n_atoms)) else: kirchhoff = np.zeros((n_atoms, n_atoms), 'd') if kwargs.get('kdtree', True): kdtree = KDTree(coords) kdtree.search(cutoff) dist2 = kdtree.getDistances() ** 2 r = 0 for i, j in kdtree.getIndices(): g = gamma(dist2[r], i, j) kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] + g kirchhoff[j, j] = kirchhoff[j, j] + g r += 1 else: LOGGER.info('Using slower method for building the Kirchhoff.') cutoff2 = cutoff * cutoff mul = np.multiply for i in range(n_atoms): xyz_i = coords[i, :] i_p1 = i+1 i2j = coords[i_p1:, :] - xyz_i mul(i2j, i2j, i2j) for j, dist2 in enumerate(i2j.sum(1)): if dist2 > cutoff2: continue j += i_p1 g = gamma(dist2, i, j) kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] + g kirchhoff[j, j] = kirchhoff[j, j] + g LOGGER.debug('Kirchhoff was built in {0:.2f}s.' .format(time.time()-start)) self._kirchhoff = kirchhoff self._n_atoms = n_atoms self._dof = n_atoms
def buildHessian(self, coords, cutoff=15., gamma=1., **kwargs): """Build Hessian matrix for given coordinate set. :arg coords: a coordinate set or an object with ``getCoords`` method :type coords: :class:`numpy.ndarray` :arg cutoff: cutoff distance (Å) for pairwise interactions, default is 15.0 Å, minimum is 4.0 Å :type cutoff: float :arg gamma: spring constant, default is 1.0 :type gamma: float, :class:`Gamma` :arg sparse: elect to use sparse matrices, default is **False**. If Scipy is not found, :class:`ImportError` is raised. :type sparse: bool :arg kdtree: elect to use KDTree for building Hessian matrix, default is **False** since KDTree method is slower :type kdtree: bool Instances of :class:`Gamma` classes and custom functions are accepted as *gamma* argument. When Scipy is available, user can select to use sparse matrices for efficient usage of memory at the cost of computation speed.""" try: coords = (coords._getCoords() if hasattr(coords, '_getCoords') else coords.getCoords()) except AttributeError: try: checkCoords(coords) except TypeError: raise TypeError('coords must be a Numpy array or an object ' 'with `getCoords` method') cutoff, g, gamma = checkENMParameters(cutoff, gamma) self._reset() self._cutoff = cutoff self._gamma = g n_atoms = coords.shape[0] dof = n_atoms * 3 LOGGER.timeit('_anm_hessian') if kwargs.get('sparse', False): try: from scipy import sparse as scipy_sparse except ImportError: raise ImportError('failed to import scipy.sparse, which is ' 'required for sparse matrix calculations') kirchhoff = scipy_sparse.lil_matrix((n_atoms, n_atoms)) hessian = scipy_sparse.lil_matrix((dof, dof)) else: kirchhoff = np.zeros((n_atoms, n_atoms), 'd') hessian = np.zeros((dof, dof), float) if kwargs.get('kdtree', False): LOGGER.info('Using KDTree for building the Hessian.') kdtree = KDTree(coords) kdtree.search(cutoff) for i, j in kdtree.getIndices(): i2j = coords[j] - coords[i] dist2 = np.dot(i2j, i2j) g = gamma(dist2, i, j) super_element = np.outer(i2j, i2j) * (- g / dist2) res_i3 = i*3 res_i33 = res_i3+3 res_j3 = j*3 res_j33 = res_j3+3 hessian[res_i3:res_i33, res_j3:res_j33] = super_element hessian[res_j3:res_j33, res_i3:res_i33] = super_element hessian[res_i3:res_i33, res_i3:res_i33] = \ hessian[res_i3:res_i33, res_i3:res_i33] - super_element hessian[res_j3:res_j33, res_j3:res_j33] = \ hessian[res_j3:res_j33, res_j3:res_j33] - super_element kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] - g kirchhoff[j, j] = kirchhoff[j, j] - g else: cutoff2 = cutoff * cutoff for i in range(n_atoms): res_i3 = i*3 res_i33 = res_i3+3 i_p1 = i+1 i2j_all = coords[i_p1:, :] - coords[i] for j, dist2 in enumerate((i2j_all ** 2).sum(1)): if dist2 > cutoff2: continue i2j = i2j_all[j] j += i_p1 g = gamma(dist2, i, j) res_j3 = j*3 res_j33 = res_j3+3 super_element = np.outer(i2j, i2j) * (- g / dist2) hessian[res_i3:res_i33, res_j3:res_j33] = super_element hessian[res_j3:res_j33, res_i3:res_i33] = super_element hessian[res_i3:res_i33, res_i3:res_i33] = \ hessian[res_i3:res_i33, res_i3:res_i33] - super_element hessian[res_j3:res_j33, res_j3:res_j33] = \ hessian[res_j3:res_j33, res_j3:res_j33] - super_element kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] - g kirchhoff[j, j] = kirchhoff[j, j] - g LOGGER.report('Hessian was built in %.2fs.', label='_anm_hessian') self._kirchhoff = kirchhoff self._hessian = hessian self._n_atoms = n_atoms self._dof = dof
def buildHessian(self, coords, cutoff=15., gamma=1., **kwargs): """Build Hessian matrix for given coordinate set. :arg coords: a coordinate set or an object with ``getCoords`` method :type coords: :class:`numpy.ndarray` :arg cutoff: cutoff distance (Å) for pairwise interactions, default is 15.0 Å, minimum is 4.0 Å :type cutoff: float :arg gamma: spring constant, default is 1.0 :type gamma: float, :class:`Gamma` :arg sparse: elect to use sparse matrices, default is **False**. If Scipy is not found, :class:`ImportError` is raised. :type sparse: bool :arg kdtree: elect to use KDTree for building Hessian matrix, default is **False** since KDTree method is slower :type kdtree: bool Instances of :class:`Gamma` classes and custom functions are accepted as *gamma* argument. When Scipy is available, user can select to use sparse matrices for efficient usage of memory at the cost of computation speed.""" try: coords = (coords._getCoords() if hasattr(coords, '_getCoords') else coords.getCoords()) except AttributeError: try: checkCoords(coords) except TypeError: raise TypeError('coords must be a Numpy array or an object ' 'with `getCoords` method') cutoff, g, gamma = checkENMParameters(cutoff, gamma) self._reset() self._cutoff = cutoff self._gamma = g n_atoms = coords.shape[0] dof = n_atoms * 3 LOGGER.timeit('_anm_hessian') if kwargs.get('sparse', False): try: from scipy import sparse as scipy_sparse except ImportError: raise ImportError('failed to import scipy.sparse, which is ' 'required for sparse matrix calculations') kirchhoff = scipy_sparse.lil_matrix((n_atoms, n_atoms)) hessian = scipy_sparse.lil_matrix((dof, dof)) else: kirchhoff = np.zeros((n_atoms, n_atoms), 'd') hessian = np.zeros((dof, dof), float) if kwargs.get('kdtree', False): LOGGER.info('Using KDTree for building the Hessian.') kdtree = KDTree(coords) kdtree.search(cutoff) for i, j in kdtree.getIndices(): i2j = coords[j] - coords[i] dist2 = np.dot(i2j, i2j) g = gamma(dist2, i, j) super_element = np.outer(i2j, i2j) * (- g / dist2) res_i3 = i*3 res_i33 = res_i3+3 res_j3 = j*3 res_j33 = res_j3+3 hessian[res_i3:res_i33, res_j3:res_j33] = super_element hessian[res_j3:res_j33, res_i3:res_i33] = super_element hessian[res_i3:res_i33, res_i3:res_i33] = \ hessian[res_i3:res_i33, res_i3:res_i33] - super_element hessian[res_j3:res_j33, res_j3:res_j33] = \ hessian[res_j3:res_j33, res_j3:res_j33] - super_element kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] - g kirchhoff[j, j] = kirchhoff[j, j] - g else: cutoff2 = cutoff * cutoff for i in range(n_atoms): res_i3 = i*3 res_i33 = res_i3+3 i_p1 = i+1 i2j_all = coords[i_p1:, :] - coords[i] for j, dist2 in enumerate((i2j_all ** 2).sum(1)): if dist2 > cutoff2: continue i2j = i2j_all[j] j += i_p1 g = gamma(dist2, i, j) res_j3 = j*3 res_j33 = res_j3+3 super_element = np.outer(i2j, i2j) * (- g / dist2) hessian[res_i3:res_i33, res_j3:res_j33] = super_element hessian[res_j3:res_j33, res_i3:res_i33] = super_element hessian[res_i3:res_i33, res_i3:res_i33] = \ hessian[res_i3:res_i33, res_i3:res_i33] - super_element hessian[res_j3:res_j33, res_j3:res_j33] = \ hessian[res_j3:res_j33, res_j3:res_j33] - super_element kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] - g kirchhoff[j, j] = kirchhoff[j, j] - g LOGGER.report('Hessian was built in %.2fs.', label='_anm_hessian') self._kirchhoff = kirchhoff self._hessian = hessian self._n_atoms = n_atoms self._dof = dof
def buildKirchhoff(self, coords, cutoff=10., gamma=1., **kwargs): """Build Kirchhoff matrix for given coordinate set. :arg coords: a coordinate set or an object with ``getCoords`` method :type coords: :class:`numpy.ndarray` or :class:`.Atomic` :arg cutoff: cutoff distance (Å) for pairwise interactions default is 10.0 Å, , minimum is 4.0 Å :type cutoff: float :arg gamma: spring constant, default is 1.0 :type gamma: float :arg sparse: elect to use sparse matrices, default is **False**. If Scipy is not found, :class:`ImportError` is raised. :type sparse: bool :arg kdtree: elect to use KDTree for building Kirchhoff matrix faster, default is **True** :type kdtree: bool Instances of :class:`Gamma` classes and custom functions are accepted as *gamma* argument. When Scipy is available, user can select to use sparse matrices for efficient usage of memory at the cost of computation speed.""" try: coords = (coords._getCoords() if hasattr(coords, '_getCoords') else coords.getCoords()) except AttributeError: try: checkCoords(coords) except TypeError: raise TypeError('coords must be a Numpy array or an object ' 'with `getCoords` method') cutoff, g, gamma = checkENMParameters(cutoff, gamma) self._reset() self._cutoff = cutoff self._gamma = g n_atoms = coords.shape[0] start = time.time() if kwargs.get('sparse', False): try: from scipy import sparse as scipy_sparse except ImportError: raise ImportError('failed to import scipy.sparse, which is ' 'required for sparse matrix calculations') kirchhoff = scipy_sparse.lil_matrix((n_atoms, n_atoms)) else: kirchhoff = np.zeros((n_atoms, n_atoms), 'd') if kwargs.get('kdtree', True): kdtree = KDTree(coords) kdtree.search(cutoff) dist2 = kdtree.getDistances()**2 r = 0 for i, j in kdtree.getIndices(): g = gamma(dist2[r], i, j) kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] + g kirchhoff[j, j] = kirchhoff[j, j] + g r += 1 else: LOGGER.info('Using slower method for building the Kirchhoff.') cutoff2 = cutoff * cutoff mul = np.multiply for i in range(n_atoms): xyz_i = coords[i, :] i_p1 = i + 1 i2j = coords[i_p1:, :] - xyz_i mul(i2j, i2j, i2j) for j, dist2 in enumerate(i2j.sum(1)): if dist2 > cutoff2: continue j += i_p1 g = gamma(dist2, i, j) kirchhoff[i, j] = -g kirchhoff[j, i] = -g kirchhoff[i, i] = kirchhoff[i, i] + g kirchhoff[j, j] = kirchhoff[j, j] + g LOGGER.debug('Kirchhoff was built in {0:.2f}s.'.format(time.time() - start)) self._kirchhoff = kirchhoff self._n_atoms = n_atoms self._dof = n_atoms