Exemplo n.º 1
0
def freq(K, M, tol=0, sparse_solver=True, silent=False,
         sort=True, reduced_dof=False,
         num_eigvalues=25, num_eigvalues_print=5):
    """Frequency Analysis

    Parameters
    ----------
    K : sparse_matrix
        Stiffness matrix. Should include initial stress stiffness matrix,
        aerodynamic matrix and so forth when applicable.
    M : sparse_matrix
        Mass matrix.
    tol : float, optional
        A tolerance value passed to ``scipy.sparse.linalg.eigs``.
    sparse_solver : bool, optional
        Tells if solver :func:`scipy.linalg.eig` or
        :func:`scipy.sparse.linalg.eigs` should be used.

        .. note:: It is recommended ``sparse_solver=False``, because it
                  was verified that the sparse solver becomes unstable
                  for some cases, though the sparse solver is faster.
    silent : bool, optional
        A boolean to tell whether the log messages should be printed.
    sort : bool, optional
        Sort the output eigenvalues and eigenmodes.
    reduced_dof : bool, optional
        Considers only the contributions of `v` and `w` to the stiffness
        matrix and accelerates the run. Only effective when
        ``sparse_solver=False``.
    num_eigvalues : int, optional
        Number of calculated eigenvalues.
    num_eigvalues_print : int, optional
        Number of eigenvalues to print.

    Returns
    -------
    The extracted eigenvalues are stored in the ``eigvals`` parameter and
    the `i^{th}` eigenvector in the ``eigvecs[:, i-1]`` parameter.

    """
    msg('Running frequency analysis...', silent=silent)

    msg('Eigenvalue solver... ', level=2, silent=silent)

    k = min(num_eigvalues, M.shape[0]-2)
    if sparse_solver:
        msg('eigs() solver...', level=3, silent=silent)
        sizebkp = M.shape[0]
        K, M, used_cols = remove_null_cols(K, M, silent=silent,
                level=3)
        #NOTE Looking for better performance with symmetric matrices, I tried
        #     using compmech.sparse.is_symmetric and eigsh, but it seems not
        #     to improve speed (I did not try passing only half of the sparse
        #     matrices to the solver)
        eigvals, peigvecs = eigs(A=K, k=k, which='LM', M=M, tol=tol,
                                 sigma=-1.)
        eigvecs = np.zeros((sizebkp, num_eigvalues), dtype=peigvecs.dtype)
        eigvecs[used_cols, :] = peigvecs

        eigvals = np.sqrt(eigvals) # omega^2 to omega, in rad/s

    else:
        msg('eig() solver...', level=3, silent=silent)
        M = M.toarray()
        K = K.toarray()
        sizebkp = M.shape[0]
        col_sum = M.sum(axis=0)
        check = col_sum != 0
        used_cols = np.arange(M.shape[0])[check]
        M = M[:, check][check, :]
        K = K[:, check][check, :]

        if reduced_dof:
            i = np.arange(M.shape[0])
            take = np.column_stack((i[1::3], i[2::3])).flatten()
            M = M[:, take][take, :]
            K = K[:, take][take, :]
        #TODO did not try using eigh when input is symmetric to see if there
        #     will be speed improvements
        eigvals, peigvecs = eig(a=-M, b=K)
        eigvecs = np.zeros((sizebkp, K.shape[0]),
                           dtype=peigvecs.dtype)
        eigvecs[check, :] = peigvecs
        eigvals = np.sqrt(-1./eigvals) # -1/omega^2 to omega, in rad/s
        eigvals = eigvals

    msg('finished!', level=3, silent=silent)

    if sort:
        sort_ind = np.lexsort((np.round(eigvals.imag, 1),
                               np.round(eigvals.real, 1)))
        eigvals = eigvals[sort_ind]
        eigvecs = eigvecs[:, sort_ind]

        higher_zero = eigvals.real > 1e-6

        eigvals = eigvals[higher_zero]
        eigvecs = eigvecs[:, higher_zero]

    if not sparse_solver and reduced_dof:
        new_eigvecs = np.zeros((3*eigvecs.shape[0]//2, eigvecs.shape[1]),
                dtype=eigvecs.dtype)
        new_eigvecs[take, :] = eigvecs
        eigvecs = new_eigvecs


    msg('finished!', level=2, silent=silent)

    msg('first {0} eigenvalues:'.format(num_eigvalues_print), level=1,
        silent=silent)
    for eigval in eigvals[:num_eigvalues_print]:
        msg('{0} rad/s'.format(eigval), level=2, silent=silent)

    return eigvals, eigvecs
Exemplo n.º 2
0
                msg('eigs() solver...', level=3)
                eigvals, peigvecs = eigs(A=A, k=self.num_eigvalues,
                        which='SM', M=M, tol=tol, sigma=1.)
                msg('finished!', level=3)
                eigvecs = np.zeros((sizebkp, self.num_eigvalues),
                                   dtype=DOUBLE)
                eigvecs[used_cols, :] = peigvecs

            # Un-normalizing eigvals
            eigvals *= Amin

        else:
            from scipy.linalg import eigh

            size22 = A.shape[0]
            M, A, used_cols = remove_null_cols(M, A)
            M = M.toarray()
            A = A.toarray()
            msg('eigh() solver...', level=3)
            eigvals, peigvecs = eigh(a=A, b=M)
            msg('finished!', level=3)
            eigvecs = np.zeros((size22, self.num_eigvalues), dtype=DOUBLE)
            eigvecs[used_cols, :] = peigvecs[:, :self.num_eigvalues]

        eigvals = -1./eigvals

        self.eigvals = eigvals
        self.eigvecs = eigvecs

        msg('finished!', level=2)
Exemplo n.º 3
0
    def lb(self, tol=0, combined_load_case=None, sparse_solver=True,
            calc_kA=False):
        """Performs a linear buckling analysis

        The following parameters of the ``AeroPistonPlate`` object will affect
        the linear buckling analysis:

        =======================    =====================================
        parameter                  description
        =======================    =====================================
        ``num_eigenvalues``        Number of eigenvalues to be extracted
        ``num_eigvalues_print``    Number of eigenvalues to print after
                                   the analysis is completed
        =======================    =====================================

        Parameters
        ----------
        combined_load_case : int, optional
            It tells whether the linear buckling analysis must be computed
            considering combined load cases, each value will tell
            the algorithm to rearrange the linear matrices in a different
            way. The valid values are ``1``, or ``2``, where:

            - ``1`` : find the critical Fx for a fixed Fxy
            - ``2`` : find the critical Fx for a fixed Fy
            - ``3`` : find the critical Fy for a fixed Fyx
            - ``4`` : find the critical Fy for a fixed Fx
        sparse_solver : bool, optional
            Tells if solver :func:`scipy.linalg.eigh` or
            :func:`scipy.sparse.linalg.eigs` should be used.

        Notes
        -----
        The extracted eigenvalues are stored in the ``eigvals`` parameter
        of the ``AeroPistonPlate`` object and the `i^{th}` eigenvector in the
        ``eigvecs[:, i-1]`` parameter.

        """
        if not modelDB.db[self.model]['linear buckling']:
            msg('________________________________________________')
            msg('')
            warn('Model {} cannot be used in linear buckling analysis!'.
                 format(self.model))
            msg('________________________________________________')

        msg('Running linear buckling analysis...')

        self.calc_linear_matrices(combined_load_case=combined_load_case,
                calc_kM=False, calc_kA=calc_kA)

        msg('Eigenvalue solver... ', level=2)

        if calc_kA:
            kA = self.kA
        else:
            kA = self.k0*0

        if combined_load_case is None:
            M = self.k0 + kA
            A = self.kG0
        elif combined_load_case == 1:
            M = self.k0 - kA + self.kG0_Fxy
            A = self.kG0_Fx
        elif combined_load_case == 2:
            M = self.k0 - kA + self.kG0_Fy
            A = self.kG0_Fx
        elif combined_load_case == 3:
            M = self.k0 - kA + self.kG0_Fyx
            A = self.kG0_Fy
        elif combined_load_case == 4:
            M = self.k0 - kA + self.kG0_Fx
            A = self.kG0_Fy

        Amin = abs(A.min())
        # normalizing A to improve numerical stability
        A /= Amin

        if sparse_solver:
            try:
                msg('eigs() solver...', level=3)
                eigvals, eigvecs = eigs(A=A, k=self.num_eigvalues, which='SM',
                                        M=M, tol=tol, sigma=1.)
                msg('finished!', level=3)
            except Exception, e:
                warn(str(e), level=4)
                msg('aborted!', level=3)
                sizebkp = A.shape[0]
                M, A, used_cols = remove_null_cols(M, A)
                msg('eigs() solver...', level=3)
                eigvals, peigvecs = eigs(A=A, k=self.num_eigvalues,
                        which='SM', M=M, tol=tol, sigma=1.)
                msg('finished!', level=3)
                eigvecs = np.zeros((sizebkp, self.num_eigvalues),
                                   dtype=DOUBLE)
                eigvecs[used_cols, :] = peigvecs

            # Un-normalizing eigvals
            eigvals *= Amin
Exemplo n.º 4
0
def lb(K, KG, tol=0, sparse_solver=True, silent=False,
       num_eigvalues=25, num_eigvalues_print=5):
    """Linear Buckling Analysis

    It can also be used for more general eigenvalue analyzes if `K` is the
    tangent stiffness matrix of a given load state.

    Parameters
    ----------
    K : sparse_matrix
        Stiffness matrix. Should include all constant terms of the initial
        stress stiffness matrix, aerodynamic matrix and so forth when
        applicable.
    KG : sparse_matrix
        Initial stress stiffness matrix that multiplies the load multiplcator
        `\lambda` of the eigenvalue problem.
    tol : float, optional
        A float tolerance passsed to the eigenvalue solver.
    sparse_solver : bool, optional
        Tells if solver :func:`scipy.linalg.eigh` or
        :func:`scipy.sparse.linalg.eigsh` should be used.
    silent : bool, optional
        A boolean to tell whether the log messages should be printed.
    num_eigvalues : int, optional
        Number of calculated eigenvalues.
    num_eigvalues_print : int, optional
        Number of eigenvalues to print.

    Notes
    -----
    The extracted eigenvalues are stored in the ``eigvals`` parameter
    of the ``Panel`` object and the `i^{th}` eigenvector in the
    ``eigvecs[:, i-1]`` parameter.

    """
    msg('Running linear buckling analysis...', silent=silent)

    msg('Eigenvalue solver... ', level=2, silent=silent)

    k = min(num_eigvalues, KG.shape[0]-2)
    if sparse_solver:
        mode = 'cayley'
        try:
            msg('eigsh() solver...', level=3, silent=silent)
            eigvals, eigvecs = eigsh(A=KG, k=k,
                    which='SM', M=K, tol=tol, sigma=1., mode=mode)
            msg('finished!', level=3, silent=silent)
        except Exception as e:
            warn(str(e), level=4, silent=silent)
            msg('aborted!', level=3, silent=silent)
            sizebkp = KG.shape[0]
            K, KG, used_cols = remove_null_cols(K, KG, silent=silent)
            msg('eigsh() solver...', level=3, silent=silent)
            eigvals, peigvecs = eigsh(A=KG, k=k,
                    which='SM', M=K, tol=tol, sigma=1., mode=mode)
            msg('finished!', level=3, silent=silent)
            eigvecs = np.zeros((sizebkp, num_eigvalues),
                               dtype=peigvecs.dtype)
            eigvecs[used_cols, :] = peigvecs

    else:
        size = KG.shape[0]
        K, KG, used_cols = remove_null_cols(K, KG, silent=silent)
        K = K.toarray()
        KG = KG.toarray()
        msg('eigh() solver...', level=3, silent=silent)
        eigvals, peigvecs = eigh(a=KG, b=K)
        msg('finished!', level=3, silent=silent)
        eigvecs = np.zeros((size, num_eigvalues), dtype=peigvecs.dtype)
        eigvecs[used_cols, :] = peigvecs[:, :num_eigvalues]

    eigvals = -1./eigvals

    eigvals = eigvals
    eigvecs = eigvecs

    msg('finished!', level=2, silent=silent)

    msg('first {0} eigenvalues:'.format(num_eigvalues_print), level=1,
        silent=silent)

    for eig in eigvals[:num_eigvalues_print]:
        msg('{0}'.format(eig), level=2, silent=silent)

    return eigvals, eigvecs