Exemple #1
0
    def __init__(self, blocks):
        blocks = np.array(blocks)
        assert isinstance(blocks, np.ndarray) and blocks.ndim == 2
        self._blocks = blocks

        assert all(
            isinstance(op, OperatorInterface) for op in self._operators())
        assert all(
            any(self._blocks[i, j] is not None
                for j in range(self._blocks.shape[1]))
            for i in range(self._blocks.shape[0]))
        assert all(
            any(self._blocks[i, j] is not None
                for i in range(self._blocks.shape[0]))
            for j in range(self._blocks.shape[1]))

        source_types = [None for j in range(self._blocks.shape[1])]
        range_types = [None for i in range(self._blocks.shape[0])]
        for (i, j), op in np.ndenumerate(self._blocks):
            if op is not None:
                assert source_types[j] is None or op.source == source_types[j]
                source_types[j] = op.source
                assert range_types[i] is None or op.range == range_types[i]
                range_types[i] = op.range

        self.source = VectorSpace(BlockVectorArray, tuple(source_types))
        self.range = VectorSpace(BlockVectorArray, tuple(range_types))
        self._source_dims = tuple(space.dim for space in self.source.subtype)
        self._range_dims = tuple(space.dim for space in self.range.subtype)
        self.num_source_blocks = len(source_types)
        self.num_range_blocks = len(range_types)
        self.linear = all(op.linear for op in self._operators())
        self.build_parameter_type(inherits=list(self._operators()))
Exemple #2
0
 def __init__(self, op):
     assert isinstance(op, DiffusionOperator)
     self._impl = op
     self.source = VectorSpace(ListVectorArray,
                               (WrappedVector, op.dim_source))
     self.range = VectorSpace(ListVectorArray,
                              (WrappedVector, op.dim_range))
     self.linear = True
Exemple #3
0
 def __init__(self, matrix, functional=False, vector=False, solver_options=None, name=None):
     assert not (functional and vector)
     super().__init__(matrix, solver_options=solver_options, name=name)
     if not vector:
         self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
     if not functional:
         self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
     self.functional = functional
     self.vector = vector
Exemple #4
0
 def __init__(self,
              obj_id,
              operators,
              functionals,
              vector_operators,
              products=None,
              pickle_subtypes=True,
              array_type=MPIVectorArray):
     d = mpi.get_object(obj_id)
     visualizer = MPIVisualizer(obj_id)
     super().__init__(operators,
                      functionals,
                      vector_operators,
                      products=products,
                      visualizer=visualizer,
                      cache_region=None,
                      name=d.name)
     self.obj_id = obj_id
     subtypes = mpi.call(_MPIDiscretization_get_subtypes, obj_id,
                         pickle_subtypes)
     if all(subtype == subtypes[0] for subtype in subtypes):
         subtypes = (subtypes[0], )
     self.solution_space = VectorSpace(array_type,
                                       (d.solution_space.type, subtypes))
     self.build_parameter_type(inherits=(d, ))
     self.parameter_space = d.parameter_space
Exemple #5
0
 def __init__(self, matrix, functional=False, vector=False, solver_options=None, name=None):
     assert not (functional and vector)
     super(NumpyListVectorArrayMatrixOperator, self).__init__(matrix, solver_options=solver_options, name=name)
     if not vector:
         self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
     if not functional:
         self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
     self.functional = functional
     self.vector = vector
Exemple #6
0
 def __init__(self,
              obj_id,
              functional=False,
              vector=False,
              with_apply2=False,
              pickle_subtypes=True,
              array_type=MPIVectorArray):
     assert not (functional and vector)
     self.obj_id = obj_id
     self.op = op = mpi.get_object(obj_id)
     self.functional = functional
     self.vector = vector
     self.with_apply2 = with_apply2
     self.pickle_subtypes = pickle_subtypes
     self.array_type = array_type
     self.linear = op.linear
     self.name = op.name
     self.build_parameter_type(inherits=(op, ))
     if vector:
         self.source = NumpyVectorSpace(1)
         assert self.source == op.source
     else:
         subtypes = mpi.call(_MPIOperator_get_source_subtypes, obj_id,
                             pickle_subtypes)
         if all(subtype == subtypes[0] for subtype in subtypes):
             subtypes = (subtypes[0], )
         self.source = VectorSpace(array_type, (op.source.type, subtypes))
     if functional:
         self.range = NumpyVectorSpace(1)
         assert self.range == op.range
     else:
         subtypes = mpi.call(_MPIOperator_get_range_subtypes, obj_id,
                             pickle_subtypes)
         if all(subtype == subtypes[0] for subtype in subtypes):
             subtypes = (subtypes[0], )
         self.range = VectorSpace(array_type, (op.range.type, subtypes))
Exemple #7
0
 def FenicsVectorSpace(V):
     return VectorSpace(ListVectorArray, (FenicsVector, V))
Exemple #8
0
class NumpyListVectorArrayMatrixOperator(NumpyMatrixOperator):
    """Variant of |NumpyMatrixOperator| using |ListVectorArray| instead of |NumpyVectorArray|."""

    def __init__(self, matrix, functional=False, vector=False, solver_options=None, name=None):
        assert not (functional and vector)
        super(NumpyListVectorArrayMatrixOperator, self).__init__(matrix, solver_options=solver_options, name=name)
        if not vector:
            self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
        if not functional:
            self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
        self.functional = functional
        self.vector = vector

    def apply(self, U, ind=None, mu=None):
        assert U in self.source
        assert U.check_ind(ind)

        if self.vector:
            V = super(NumpyListVectorArrayMatrixOperator, self).apply(U, ind=ind, mu=mu)
            return ListVectorArray([NumpyVector(v, copy=False) for v in V.data], subtype=self.range.subtype)

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)
        V = [self._matrix.dot(v._array) for v in vectors]

        if self.functional:
            return NumpyVectorArray(V) if len(V) > 0 else self.range.empty()
        else:
            return ListVectorArray([NumpyVector(v, copy=False) for v in V], subtype=self.range.subtype)

    def apply_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None):
        raise NotImplementedError

    def apply_inverse(self, V, ind=None, mu=None, least_squares=False):
        assert V in self.range
        assert V.check_ind(ind)
        assert not self.functional and not self.vector

        if V.dim == 0:
            if self.source.dim == 0 and least_squares:
                return ListVectorArray(
                    [NumpyVector(np.zeros(0), copy=False) for _ in range(V.len_ind(ind))], subtype=self.source.subtype
                )
            else:
                raise InversionError

        options = (
            self.solver_options.get("inverse") if self.solver_options else "least_squares" if least_squares else None
        )

        if options and not least_squares:
            solver_type = options if isinstance(options, str) else options["type"]
            if solver_type.startswith("least_squares"):
                self.logger.warn('Least squares solver selected but "least_squares == False"')

        if ind is None:
            vectors = V._list
        elif isinstance(ind, Number):
            vectors = [V._list[ind]]
        else:
            vectors = (V._list[i] for i in ind)

        try:
            return ListVectorArray(
                [
                    NumpyVector(
                        _apply_inverse(self._matrix, v._array.reshape((1, -1)), options=options).ravel(), copy=False
                    )
                    for v in vectors
                ],
                subtype=self.source.subtype,
            )
        except InversionError as e:
            if least_squares and options:
                solver_type = options if isinstance(options, str) else options["type"]
                if not solver_type.startswith("least_squares"):
                    msg = (
                        str(e)
                        + "\nNote: linear solver was selected for solving least squares problem (maybe not invertible?)"
                    )
                    raise InversionError(msg)
            raise e

    def as_vector(self, mu=None):
        if self.source.dim != 1 and self.range.dim != 1:
            raise TypeError("This operator does not represent a vector or linear functional.")
        return ListVectorArray([NumpyVector(self._matrix.ravel(), copy=True)])

    def assemble_lincomb(self, operators, coefficients, solver_options=None, name=None):
        lincomb = super(NumpyListVectorArrayMatrixOperator, self).assemble_lincomb(operators, coefficients)
        if lincomb is None:
            return None
        else:
            return NumpyListVectorArrayMatrixOperator(lincomb._matrix, solver_options=solver_options, name=name)
Exemple #9
0
def NumpyVectorSpace(dim):
    """Shorthand for |VectorSpace| `(NumpyVectorArray, dim)`."""
    return VectorSpace(NumpyVectorArray, dim)
Exemple #10
0
class NumpyListVectorArrayMatrixOperator(NumpyMatrixOperator):
    """Variant of |NumpyMatrixOperator| using |ListVectorArray| instead of |NumpyVectorArray|."""

    def __init__(self, matrix, functional=False, vector=False, solver_options=None, name=None):
        assert not (functional and vector)
        super().__init__(matrix, solver_options=solver_options, name=name)
        if not vector:
            self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
        if not functional:
            self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
        self.functional = functional
        self.vector = vector

    def apply(self, U, ind=None, mu=None):
        assert U in self.source
        assert U.check_ind(ind)

        if self.vector:
            V = super().apply(U, ind=ind, mu=mu)
            return ListVectorArray([NumpyVector(v, copy=False) for v in V.data],
                                   subtype=self.range.subtype)

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)
        V = [self._matrix.dot(v._array) for v in vectors]

        if self.functional:
            return NumpyVectorArray(V) if len(V) > 0 else self.range.empty()
        else:
            return ListVectorArray([NumpyVector(v, copy=False) for v in V], subtype=self.range.subtype)

    def apply_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None):
        raise NotImplementedError

    def apply_inverse(self, V, ind=None, mu=None, least_squares=False):
        assert V in self.range
        assert V.check_ind(ind)
        assert not self.functional and not self.vector

        if V.dim == 0:
            if self.source.dim == 0 and least_squares:
                return ListVectorArray([NumpyVector(np.zeros(0), copy=False) for _ in range(V.len_ind(ind))],
                                       subtype=self.source.subtype)
            else:
                raise InversionError

        options = (self.solver_options.get('inverse') if self.solver_options else
                   'least_squares' if least_squares else
                   None)

        if options and not least_squares:
            solver_type = options if isinstance(options, str) else options['type']
            if solver_type.startswith('least_squares'):
                self.logger.warn('Least squares solver selected but "least_squares == False"')

        if ind is None:
            vectors = V._list
        elif isinstance(ind, Number):
            vectors = [V._list[ind]]
        else:
            vectors = (V._list[i] for i in ind)

        try:
            return ListVectorArray([NumpyVector(_apply_inverse(self._matrix, v._array.reshape((1, -1)),
                                                               options=options).ravel(),
                                                copy=False)
                                    for v in vectors],
                                   subtype=self.source.subtype)
        except InversionError as e:
            if least_squares and options:
                solver_type = options if isinstance(options, str) else options['type']
                if not solver_type.startswith('least_squares'):
                    msg = str(e) \
                        + '\nNote: linear solver was selected for solving least squares problem (maybe not invertible?)'
                    raise InversionError(msg)
            raise e

    def as_vector(self, mu=None):
        if self.source.dim != 1 and self.range.dim != 1:
            raise TypeError('This operator does not represent a vector or linear functional.')
        return ListVectorArray([NumpyVector(self._matrix.ravel(), copy=True)])

    def assemble_lincomb(self, operators, coefficients, solver_options=None, name=None):
        lincomb = super().assemble_lincomb(operators, coefficients)
        if lincomb is None:
            return None
        else:
            return NumpyListVectorArrayMatrixOperator(lincomb._matrix, solver_options=solver_options, name=name)
Exemple #11
0
class NumpyListVectorArrayMatrixOperator(NumpyMatrixOperator):
    """Variant of |NumpyMatrixOperator| using |ListVectorArray| instead of |NumpyVectorArray|."""

    def __init__(self, matrix, functional=False, vector=False, name=None):
        assert not (functional and vector)
        super(NumpyListVectorArrayMatrixOperator, self).__init__(matrix, name)
        if not vector:
            self.source = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[1]))
        if not functional:
            self.range = VectorSpace(ListVectorArray, (NumpyVector, matrix.shape[0]))
        self.functional = functional
        self.vector = vector

    def apply(self, U, ind=None, mu=None):
        assert U in self.source
        assert U.check_ind(ind)

        if self.vector:
            V = super(NumpyListVectorArrayMatrixOperator, self).apply(U, ind=ind, mu=mu)
            return ListVectorArray([NumpyVector(v, copy=False) for v in V.data],
                                   subtype=self.range.subtype)

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)
        V = [self._matrix.dot(v._array) for v in vectors]

        if self.functional:
            return NumpyVectorArray(V) if len(V) > 0 else self.range.empty()
        else:
            return ListVectorArray([NumpyVector(v, copy=False) for v in V], subtype=self.range.subtype)

    def apply_adjoint(self, U, ind=None, mu=None, source_product=None, range_product=None):
        raise NotImplementedError

    def apply_inverse(self, U, ind=None, mu=None, options=None):
        assert U in self.range
        assert U.check_ind(ind)
        assert not self.functional and not self.vector

        if U.dim == 0:
            if (self.source.dim == 0
                    or isinstance(options, str) and options.startswith('least_squares')
                    or isinstance(options, dict) and options['type'].startswith('least_squares')):
                return ListVectorArray([NumpyVector(np.zeros(0), copy=False) for _ in range(U.len_ind(ind))],
                                       subtype=self.source.subtype)
            else:
                raise InversionError

        if ind is None:
            vectors = U._list
        elif isinstance(ind, Number):
            vectors = [U._list[ind]]
        else:
            vectors = (U._list[i] for i in ind)

        return ListVectorArray([NumpyVector(_apply_inverse(self._matrix, v._array, options=options), copy=False)
                                for v in vectors],
                               subtype=self.source.subtype)

    def as_vector(self, mu=None):
        if self.source.dim != 1 and self.range.dim != 1:
            raise TypeError('This operator does not represent a vector or linear functional.')
        return ListVectorArray([NumpyVector(self._matrix.ravel(), copy=True)])

    def assemble_lincomb(self, operators, coefficients, name=None):
        lincomb = super(NumpyListVectorArrayMatrixOperator, self).assemble_lincomb(operators, coefficients)
        if lincomb is None:
            return None
        else:
            return NumpyListVectorArrayMatrixOperator(lincomb._matrix, name=name)