Source code for Mordicus.Core.BasicAlgorithms.SVD

# -*- coding: utf-8 -*-
import os
from mpi4py import MPI
if MPI.COMM_WORLD.Get_size() > 1: # pragma: no cover
    os.environ["OMP_NUM_THREADS"] = "1"
    os.environ["OPENBLAS_NUM_THREADS"] = "1"
    os.environ["MKL_NUM_THREADS"] = "1"
    os.environ["VECLIB_MAXIMUM_THREADS"] = "1"
    os.environ["NUMEXPR_NUM_THREADS"] = "1"
import numpy as np


[docs]def TruncatedSVDSymLower(matrix, epsilon = None, nbModes = None): """ Computes a truncatd singular value decomposition of a symetric definite matrix in scipy.sparse.csr format. Only the lower triangular part needs to be defined Parameters ---------- matrix : scipy.sparse.csr the input matrix epsilon : float the truncation tolerence, determining the number of keps eigenvalues nbModes : int the number of keps eigenvalues Returns ------- np.ndarray kept eigenvalues, of size (numberOfEigenvalues) np.ndarray kept eigenvectors, of size (numberOfEigenvalues, numberOfSnapshots) """ if epsilon != None and nbModes != None:# pragma: no cover raise("cannot specify both epsilon and nbModes") eigenValues, eigenVectors = np.linalg.eigh(matrix, UPLO="L") idx = eigenValues.argsort()[::-1] eigenValues = eigenValues[idx] eigenVectors = eigenVectors[:, idx] if nbModes == None: if epsilon == None: nbModes = matrix.shape[0] else: nbModes = 0 bound = (epsilon ** 2) * eigenValues[0] for e in eigenValues: if e > bound: nbModes += 1 id_max2 = 0 bound = (1 - epsilon ** 2) * np.sum(eigenValues) temp = 0 for e in eigenValues: temp += e if temp < bound: id_max2 += 1 # pragma: no cover nbModes = max(nbModes, id_max2) if nbModes > matrix.shape[0]: print("nbModes taken to max possible value of "+str(matrix.shape[0])+" instead of provided value "+str(nbModes)) nbModes = matrix.shape[0] index = np.where(eigenValues<0) if len(eigenValues[index])>0: if index[0][0]<nbModes: #print(nbModes, index[0][0]) print("removing numerical noise from eigenvalues, nbModes is set to "+str(index[0][0])+" instead of "+str(nbModes)) nbModes = index[0][0] return eigenValues[0:nbModes], eigenVectors[:, 0:nbModes]
if __name__ == "__main__":# pragma: no cover from Mordicus import RunTestFile RunTestFile(__file__)