Exemple #1
0
def test_apply_inverse(operator_with_arrays):
    op, mu, _, V = operator_with_arrays
    for options in chain([None], op.invert_options, op.invert_options.itervalues()):
        for ind in valid_inds(V):
            try:
                U = op.apply_inverse(V, mu=mu, ind=ind, options=options)
            except InversionError:
                return
            assert U in op.source
            assert len(U) == V.len_ind(ind)
            VV = op.apply(U, mu=mu)
            if (isinstance(options, str) and options.startswith('least_squares')
                    or not isinstance(options, (str, type(None))) and options['type'].startswith('least_squares')):
                continue
            assert float_cmp_all(VV.l2_norm(), V.l2_norm(ind=ind), atol=1e-10, rtol=0.5)
Exemple #2
0
    def allclose(self, mu):
        """Compare two dicts of |parameter values| using :meth:`~pymor.tools.floatcmp.float_cmp_all`.

        Parameters
        ----------
        mu
            The |parameter values| with which to compare.

        Returns
        -------
        `True` if both |parameter value| dicts contain values for the same |Parameters| and all
        components of the parameter values are almost equal, else `False`.
        """
        assert isinstance(mu, Mu)
        return self.keys() == mu.keys() and all(
            float_cmp_all(v, mu[k]) for k, v in self.items())
Exemple #3
0
    def allclose(self, mu):
        """Compare to |Parameters| using :meth:`~pymor.tools.floatcmp.float_cmp_all`.

        Parameters
        ----------
        mu
            The |Parameter| with which to compare.

        Returns
        -------
        `True` if both |Parameters| have the same |ParameterType| and all parameter
        components are almost equal, else `False`.
        """
        assert isinstance(mu, Parameter)
        if self.viewkeys() != mu.viewkeys():
            return False
        elif not all(float_cmp_all(v, mu[k]) for k, v in self.iteritems()):
            return False
        else:
            return True
Exemple #4
0
    def allclose(self, mu):
        """Compare two |Parameters| using :meth:`~pymor.tools.floatcmp.float_cmp_all`.

        Parameters
        ----------
        mu
            The |Parameter| with which to compare.

        Returns
        -------
        `True` if both |Parameters| have the same |ParameterType| and all parameter
        components are almost equal, else `False`.
        """
        assert isinstance(mu, Parameter)
        if list(self.keys()) != list(mu.keys()):
            return False
        elif not all(float_cmp_all(v, mu[k]) for k, v in self.items()):
            return False
        else:
            return True
Exemple #5
0
def test_apply_inverse(operator_with_arrays):
    op, mu, _, V = operator_with_arrays
    for options in chain([None], op.invert_options,
                         op.invert_options.itervalues()):
        for ind in valid_inds(V):
            try:
                U = op.apply_inverse(V, mu=mu, ind=ind, options=options)
            except InversionError:
                return
            assert U in op.source
            assert len(U) == V.len_ind(ind)
            VV = op.apply(U, mu=mu)
            if (isinstance(options, str)
                    and options.startswith('least_squares')
                    or not isinstance(options, (str, type(None)))
                    and options['type'].startswith('least_squares')):
                continue
            assert float_cmp_all(VV.l2_norm(),
                                 V.l2_norm(ind=ind),
                                 atol=1e-10,
                                 rtol=0.5)
Exemple #6
0
 def test_points(self):
     for order in GaussQuadratures.orders:
         P, _ = GaussQuadratures.quadrature(order)
         assert float_cmp_all(P, np.sort(P))
         assert 0.0 < P[0]
         assert P[-1] < 1.0
Exemple #7
0
def pod(A,
        modes=None,
        product=None,
        rtol=4e-8,
        atol=0.,
        l2_err=0.,
        symmetrize=False,
        orthonormalize=True,
        check=True,
        check_tol=1e-10):
    """Proper orthogonal decomposition of `A`.

    Viewing the |VectorArray| `A` as a `A.dim` x `len(A)` matrix,
    the return value of this method is the |VectorArray| of left-singular
    vectors of the singular value decomposition of `A`, where the inner product
    on R^(`dim(A)`) is given by `product` and the inner product on R^(`len(A)`)
    is the Euclidean inner product.

    Parameters
    ----------
    A
        The |VectorArray| for which the POD is to be computed.
    modes
        If not `None`, only the first `modes` POD modes (singular vectors) are
        returned.
    product
        Inner product |Operator| w.r.t. which the POD is computed.
    rtol
        Singular values smaller than this value multiplied by the largest singular
        value are ignored.
    atol
        Singular values smaller than this value are ignored.
    l2_err
        Do not return more modes than needed to bound the l2-approximation
        error by this value. I.e. the number of returned modes is at most ::

            argmin_N { sum_{n=N+1}^{infty} s_n^2 <= l2_err^2 }

        where `s_n` denotes the n-th singular value.
    symmetrize
        If `True`, symmetrize the Gramian again before proceeding.
    orthonormalize
        If `True`, orthonormalize the computed POD modes again using
        the :func:`~pymor.algorithms.gram_schmidt.gram_schmidt` algorithm.
    check
        If `True`, check the computed POD modes for orthonormality.
    check_tol
        Tolerance for the orthonormality check.

    Returns
    -------
    POD
        |VectorArray| of POD modes.
    SVALS
        Sequence of singular values.
    """

    assert isinstance(A, VectorArrayInterface)
    assert len(A) > 0
    assert modes is None or modes <= len(A)
    assert product is None or isinstance(product, OperatorInterface)

    logger = getLogger('pymor.algorithms.pod.pod')

    with logger.block('Computing Gramian ({} vectors) ...'.format(len(A))):
        B = A.gramian() if product is None else product.apply2(A, A)

        if symmetrize:  # according to rbmatlab this is necessary due to rounding
            B = B + B.T
            B *= 0.5

    with logger.block('Computing eigenvalue decomposition ...'):
        eigvals = None if (modes is None or l2_err > 0.) else (len(B) - modes,
                                                               len(B) - 1)

        EVALS, EVECS = eigh(B, overwrite_a=True, turbo=True, eigvals=eigvals)
        EVALS = EVALS[::-1]
        EVECS = EVECS.T[::-1, :]  # is this a view? yes it is!

        tol = max(rtol**2 * EVALS[0], atol**2)
        above_tol = np.where(EVALS >= tol)[0]
        if len(above_tol) == 0:
            return A.space.empty(), np.array([])
        last_above_tol = above_tol[-1]

        errs = np.concatenate((np.cumsum(EVALS[::-1])[::-1], [0.]))
        below_err = np.where(errs <= l2_err**2)[0]
        first_below_err = below_err[0]

        selected_modes = min(first_below_err, last_above_tol + 1)
        if modes is not None:
            selected_modes = min(selected_modes, modes)

        SVALS = np.sqrt(EVALS[:selected_modes])
        EVECS = EVECS[:selected_modes]

    with logger.block(
            'Computing left-singular vectors ({} vectors) ...'.format(
                len(EVECS))):
        POD = A.lincomb(EVECS / SVALS[:, np.newaxis])

    if orthonormalize:
        with logger.block('Re-orthonormalizing POD modes ...'):
            POD = gram_schmidt(POD, product=product, copy=False)

    if check:
        logger.info('Checking orthonormality ...')
        if not product and not float_cmp_all(
                POD.dot(POD), np.eye(len(POD)), atol=check_tol, rtol=0.):
            err = np.max(np.abs(POD.dot(POD) - np.eye(len(POD))))
            raise AccuracyError(
                'result not orthogonal (max err={})'.format(err))
        elif product and not float_cmp_all(product.apply2(POD, POD),
                                           np.eye(len(POD)),
                                           atol=check_tol,
                                           rtol=0.):
            err = np.max(np.abs(product.apply2(POD, POD) - np.eye(len(POD))))
            raise AccuracyError(
                'result not orthogonal (max err={})'.format(err))
        if len(POD) < len(EVECS):
            raise AccuracyError(
                'additional orthonormalization removed basis vectors')

    return POD, SVALS
Exemple #8
0
 def almost_equal(self, other, rtol=None, atol=None):
     assert self.dim == other.dim
     return float_cmp_all(self._array, other._array, rtol=rtol, atol=atol)
Exemple #9
0
def pod(A, modes=None, product=None, tol=4e-8, symmetrize=False, orthonormalize=True,
        check=True, check_tol=1e-10):
    """Proper orthogonal decomposition of `A`.

    If the |VectorArray| `A` is viewed as a linear map ::

        A: R^(len(A)) ---> R^(dim(A))

    then the return value of this method is simply the |VectorArray| of left-singular
    vectors of the singular value decomposition of `A` with the scalar product
    on R^(dim(A) given by `product` and the scalar product on R^(len(A)) being
    the Euclidean product.

    Parameters
    ----------
    A
        The |VectorArray| for which the POD is to be computed.
    modes
        If not `None` only the first `modes` POD modes (singular vectors) are
        returned.
    products
        Scalar product |Operator| w.r.t. which the POD is computed.
    tol
        Singular values smaller than this value multiplied by the largest singular
        value are ignored.
    symmetrize
        If `True`, symmetrize the gramian again before proceeding.
    orthonormalize
        If `True`, orthonormalize the computed POD modes again using
        :func:`algorithms.gram_schmidt.gram_schmidt`.
    check
        If `True`, check the computed POD modes for orthonormality.
    check_tol
        Tolerance for the orthonormality check.

    Returns
    -------
    POD
        |VectorArray| of POD modes.
    SVALS
        Sequence of singular values.
    """

    assert isinstance(A, VectorArrayInterface)
    assert len(A) > 0
    assert modes is None or modes <= len(A)
    assert product is None or isinstance(product, OperatorInterface)

    B = A.gramian() if product is None else product.apply2(A, A)

    if symmetrize:     # according to rbmatlab this is necessary due to rounding
        B = B + B.T
        B *= 0.5

    eigvals = None if modes is None else (len(B) - modes, len(B) - 1)

    EVALS, EVECS = eigh(B, overwrite_a=True, turbo=True, eigvals=eigvals)
    EVALS = EVALS[::-1]
    EVECS = EVECS.T[::-1, :]  # is this a view? yes it is!

    above_tol = np.where(EVALS >= tol ** 2 * EVALS[0])[0]
    if len(above_tol) == 0:
        return type(A).empty(A.dim)
    last_above_tol = above_tol[-1]

    SVALS = np.sqrt(EVALS[:last_above_tol + 1])
    EVECS = EVECS[:last_above_tol + 1]

    POD = A.lincomb(EVECS / SVALS[:, np.newaxis])

    if orthonormalize:
        POD = gram_schmidt(POD, product=product, copy=False)

    if check:
        if not product and not float_cmp_all(POD.dot(POD), np.eye(len(POD)),
                                             atol=check_tol, rtol=0.):
            err = np.max(np.abs(POD.dot(POD) - np.eye(len(POD))))
            raise AccuracyError('result not orthogonal (max err={})'.format(err))
        elif product and not float_cmp_all(product.apply2(POD, POD), np.eye(len(POD)),
                                           atol=check_tol, rtol=0.):
            err = np.max(np.abs(product.apply2(POD, POD) - np.eye(len(POD))))
            raise AccuracyError('result not orthogonal (max err={})'.format(err))
        if len(POD) < len(EVECS):
            raise AccuracyError('additional orthonormalization removed basis vectors')

    return POD, SVALS
Exemple #10
0
 def test_points(self):
     for order in GaussQuadratures.orders:
         P, _ = GaussQuadratures.quadrature(order)
         assert float_cmp_all(P, np.sort(P))
         assert 0.0 < P[0]
         assert P[-1] < 1.0
Exemple #11
0
def pod(A, modes=None, product=None, rtol=4e-8, atol=0., l2_mean_err=0.,
        symmetrize=False, orthonormalize=True, check=True, check_tol=1e-10):
    """Proper orthogonal decomposition of `A`.

    If the |VectorArray| `A` is viewed as a linear map ::

        A: R^(len(A)) ---> R^(dim(A))

    then the return value of this method is simply the |VectorArray| of left-singular
    vectors of the singular value decomposition of `A` with the scalar product
    on R^(dim(A) given by `product` and the scalar product on R^(len(A)) being
    the Euclidean product.

    Parameters
    ----------
    A
        The |VectorArray| for which the POD is to be computed.
    modes
        If not `None` only the first `modes` POD modes (singular vectors) are
        returned.
    products
        Scalar product |Operator| w.r.t. which the POD is computed.
    rtol
        Singular values smaller than this value multiplied by the largest singular
        value are ignored.
    atol
        Singular values smaller than this value are ignored.
    l2_mean_err
        Do not return more modes than needed to bound the mean l2-approximation
        error by this value. I.e. the number of returned modes is at most ::

            argmin_N sqrt(1 / len(A) * sum_{n=N+1}^{infty} s_n^2) <= l2_mean_err

        where `s_n` denotes the n-th singular value.
    symmetrize
        If `True`, symmetrize the gramian again before proceeding.
    orthonormalize
        If `True`, orthonormalize the computed POD modes again using
        :func:`algorithms.gram_schmidt.gram_schmidt`.
    check
        If `True`, check the computed POD modes for orthonormality.
    check_tol
        Tolerance for the orthonormality check.

    Returns
    -------
    POD
        |VectorArray| of POD modes.
    SVALS
        Sequence of singular values.
    """

    assert isinstance(A, VectorArrayInterface)
    assert len(A) > 0
    assert modes is None or modes <= len(A)
    assert product is None or isinstance(product, OperatorInterface)

    logger = getLogger('pymor.algorithms.pod.pod')

    with logger.block('Computing Gramian ({} vectors) ...'.format(len(A))):
        B = A.gramian() if product is None else product.apply2(A, A)

        if symmetrize:     # according to rbmatlab this is necessary due to rounding
            B = B + B.T
            B *= 0.5

    with logger.block('Computing eigenvalue decomposition ...'):
        eigvals = None if (modes is None or l2_mean_err > 0.) else (len(B) - modes, len(B) - 1)

        EVALS, EVECS = eigh(B, overwrite_a=True, turbo=True, eigvals=eigvals)
        EVALS = EVALS[::-1]
        EVECS = EVECS.T[::-1, :]  # is this a view? yes it is!

        tol = max(rtol ** 2 * EVALS[0], atol ** 2)
        above_tol = np.where(EVALS >= tol)[0]
        if len(above_tol) == 0:
            return A.space.empty(), np.array([])
        last_above_tol = above_tol[-1]

        errs = np.concatenate((np.cumsum(EVALS[::-1])[::-1], [0.]))
        below_err = np.where(errs <= l2_mean_err**2 * len(A))[0]
        first_below_err = below_err[0]

        selected_modes = min(first_below_err, last_above_tol + 1)
        if modes is not None:
            selected_modes = min(selected_modes, modes)

        SVALS = np.sqrt(EVALS[:selected_modes])
        EVECS = EVECS[:selected_modes]

    with logger.block('Computing left-singular vectors ({} vectors) ...'.format(len(EVECS))):
        POD = A.lincomb(EVECS / SVALS[:, np.newaxis])

    if orthonormalize:
        with logger.block('Re-orthonormalizing POD modes ...'):
            POD = gram_schmidt(POD, product=product, copy=False)

    if check:
        logger.info('Checking orthonormality ...')
        if not product and not float_cmp_all(POD.dot(POD), np.eye(len(POD)),
                                             atol=check_tol, rtol=0.):
            err = np.max(np.abs(POD.dot(POD) - np.eye(len(POD))))
            raise AccuracyError('result not orthogonal (max err={})'.format(err))
        elif product and not float_cmp_all(product.apply2(POD, POD), np.eye(len(POD)),
                                           atol=check_tol, rtol=0.):
            err = np.max(np.abs(product.apply2(POD, POD) - np.eye(len(POD))))
            raise AccuracyError('result not orthogonal (max err={})'.format(err))
        if len(POD) < len(EVECS):
            raise AccuracyError('additional orthonormalization removed basis vectors')

    return POD, SVALS
Exemple #12
0
def pod(A, modes=None, product=None, tol=4e-8, symmetrize=False, orthonormalize=True,
        check=True, check_tol=1e-10):
    """Proper orthogonal decomposition of `A`.

    If the |VectorArray| `A` is viewed as a linear map ::

        A: R^(len(A)) ---> R^(dim(A))

    then the return value of this method is simply the |VectorArray| of left-singular
    vectors of the singular value decomposition of `A` with the scalar product
    on R^(dim(A) given by `product` and the scalar product on R^(len(A)) being
    the Euclidean product.

    Parameters
    ----------
    A
        The |VectorArray| for which the POD is to be computed.
    modes
        If not `None` only the first `modes` POD modes (singular vectors) are
        returned.
    products
        Scalar product |Operator| w.r.t. which the POD is computed.
    tol
        Singular values smaller than this value multiplied by the largest singular
        value are ignored.
    symmetrize
        If `True`, symmetrize the gramian again before proceeding.
    orthonormalize
        If `True`, orthonormalize the computed POD modes again using
        :func:`la.gram_schmidt.gram_schmidt`.
    check
        If `True`, check the computed POD modes for orthonormality.
    check_tol
        Tolerance for the orthonormality check.

    Returns
    -------
    POD
        |VectorArray| of POD modes.
    SVALS
        Sequence of singular values.
    """

    assert isinstance(A, VectorArrayInterface)
    assert len(A) > 0
    assert modes is None or modes <= len(A)
    assert product is None or isinstance(product, OperatorInterface)

    B = A.gramian() if product is None else product.apply2(A, A, pairwise=False)

    if symmetrize:     # according to rbmatlab this is necessary due to rounding
        B = B + B.T
        B *= 0.5

    eigvals = None if modes is None else (len(B) - modes, len(B) - 1)

    EVALS, EVECS = eigh(B, overwrite_a=True, turbo=True, eigvals=eigvals)
    EVALS = EVALS[::-1]
    EVECS = EVECS.T[::-1, :]  # is this a view? yes it is!

    above_tol = np.where(EVALS >= tol ** 2 * EVALS[0])[0]
    if len(above_tol) == 0:
        return type(A).empty(A.dim)
    last_above_tol = above_tol[-1]

    SVALS = np.sqrt(EVALS[:last_above_tol + 1])
    EVECS = EVECS[:last_above_tol + 1]

    POD = A.lincomb(EVECS / SVALS[:, np.newaxis])

    if orthonormalize:
        POD = gram_schmidt(POD, product=product, copy=False)

    if check:
        if not product and not float_cmp_all(POD.dot(POD, pairwise=False), np.eye(len(POD)),
                                             atol=check_tol, rtol=0.):
            err = np.max(np.abs(POD.dot(POD, pairwise=False) - np.eye(len(POD))))
            raise AccuracyError('result not orthogonal (max err={})'.format(err))
        elif product and not float_cmp_all(product.apply2(POD, POD, pairwise=False), np.eye(len(POD)),
                                           atol=check_tol, rtol=0.):
            err = np.max(np.abs(product.apply2(POD, POD, pairwise=False) - np.eye(len(POD))))
            raise AccuracyError('result not orthogonal (max err={})'.format(err))
        if len(POD) < len(EVECS):
            raise AccuracyError('additional orthonormalization removed basis vectors')

    return POD, SVALS
Exemple #13
0
 def almost_equal(self, other, rtol=None, atol=None):
     assert self.dim == other.dim
     return float_cmp_all(self._array, other._array, rtol=rtol, atol=atol)