def collect_vector_ranges(op, image): if isinstance(op, (LincombOperator, SelectionOperator)): for o in op.operators: collect_vector_ranges(o, image) elif isinstance(op, AdjointOperator): if op.source not in image_space: raise ImageCollectionError(op) # Not implemented operator = Concatenation( op.range_product, op.operator) if op.range_product else op.operator collect_operator_ranges(operator, NumpyVectorArray(np.ones(1)), image) elif op.linear and not op.parametric: image.append(op.as_vector()) else: raise ImageCollectionError(op)
def collect_operator_ranges(op, source, image): if isinstance(op, (LincombOperator, SelectionOperator)): for o in op.operators: collect_operator_ranges(o, source, image) elif isinstance(op, EmpiricalInterpolatedOperator): if hasattr(op, 'collateral_basis') and not extends: image.append(op.collateral_basis) elif isinstance(op, Concatenation): firstrange = op.first.range.empty() collect_operator_ranges(op.first, source, firstrange) collect_operator_ranges(op.second, firstrange, image) elif op.linear and not op.parametric: image.append(op.apply(source)) else: raise ImageCollectionError(op)
def estimate_image(operators=(), vectors=(), domain=None, extends=False, orthonormalize=True, product=None, riesz_representatives=False): """Estimate the image of given |Operators| for all mu. Let `operators` be a list of |Operators| with common source and range, and let `vectors` be a list of |VectorArrays| or vector-like |Operators| in the range of these operators. Given a |VectorArray| `domain` of vectors in the source of the operators, this algorithms determines a |VectorArray| `image` of range vectors such that the linear span of `image` contains: - `op.apply(U, mu=mu)` for all operators `op` in `operators`, for all possible |Parameters| `mu` and for all |VectorArrays| `U` contained in the linear span of `domain`, - `U` for all |VectorArrays| in `vectors`, - `v.as_range_array(mu)` for all |Operators| in `vectors` and all possible |Parameters| `mu`. The algorithm will try to choose `image` as small as possible. However, no optimality is guaranteed. The image estimation algorithm is specified by :class:`CollectOperatorRangeRules` and :class:`CollectVectorRangeRules`. Parameters ---------- operators See above. vectors See above. domain See above. If `None`, an empty `domain` |VectorArray| is assumed. extends For some operators, e.g. |EmpiricalInterpolatedOperator|, as well as for all elements of `vectors`, `image` is estimated independently from the choice of `domain`. If `extends` is `True`, such operators are ignored. (This is useful in case these vectors have already been obtained by earlier calls to this function.) orthonormalize Compute an orthonormal basis for the linear span of `image` using the :func:`~pymor.algorithms.gram_schmidt.gram_schmidt` algorithm. product Inner product |Operator| w.r.t. which to orthonormalize. riesz_representatives If `True`, compute Riesz representatives of the vectors in `image` before orthonormalizing (useful for dual norm computation when the range of the `operators` is a dual space). Returns ------- The |VectorArray| `image`. Raises ------ ImageCollectionError Is raised when for a given |Operator| no image estimate is possible. """ assert operators or vectors domain_space = operators[0].source if operators else None image_space = operators[0].range if operators \ else vectors[0].space if isinstance(vectors[0], VectorArrayInterface) \ else vectors[0].range assert all(op.source == domain_space and op.range == image_space for op in operators) assert all( isinstance(v, VectorArrayInterface) and (v in image_space) or isinstance(v, OperatorInterface) and (v.range == image_space and isinstance(v.source, NumpyVectorSpace) and v.linear) for v in vectors) assert domain is None or domain_space is None or domain in domain_space assert product is None or product.source == product.range == image_space image = image_space.empty() if not extends: for v in vectors: try: CollectVectorRangeRules.apply(v, image) except NoMatchingRuleError as e: raise ImageCollectionError(e.obj) if operators and domain is None: domain = domain_space.empty() for op in operators: try: CollectOperatorRangeRules.apply(op, domain, image, extends) except NoMatchingRuleError as e: raise ImageCollectionError(e.obj) if riesz_representatives and product: image = product.apply_inverse(image) if orthonormalize: gram_schmidt(image, product=product, copy=False) return image