Esempio n. 1
0
    def _matvec(self, x):

        from bempp.api.utils.data_types import combined_type

        if x.ndim == 1:
            x_new = _np.expand_dims(x, 1)
            return self.matvec(x_new).ravel()

        if not self._fill_complete():
            raise ValueError("Not all rows or columns contain operators.")

        row_dim = 0
        res = _np.zeros((self.shape[0], x.shape[1]), dtype=combined_type(self.dtype, x.dtype))

        for i in range(self._m):
            col_dim = 0
            local_res = res[row_dim:row_dim + self._rows[i], :]
            for j in range(self._n):
                local_x = x[col_dim:col_dim + self._cols[j], :]
                if self._operators[i, j] is not None:
                    op_is_complex = _np.iscomplexobj(self._operators[i, j].dtype.type(1))
                    if _np.iscomplexobj(x) and not op_is_complex:
                        local_res[:] += (self._operators[i, j] * _np.real(local_x) +
                                         1j * self._operators[i, j] * _np.imag(local_x))
                    else:
                        local_res[:] += self._operators[i, j].dot(local_x)
                col_dim += self._cols[j]
            row_dim += self._rows[i]
        return res
Esempio n. 2
0
    def _matvec(self, x):
        from bempp.api.utils.data_types import combined_type

        expand_input_dim = False
        if x.ndim == 1:
            x_new = _np.expand_dims(x, 1)
            expand_input_dim = True
            return self.matvec(x_new).ravel()

        if not self._fill_complete():
            raise ValueError("Not all rows or columns contain operators.")

        row_dim = 0
        res = _np.zeros((self.shape[0], x.shape[1]),
                        dtype=combined_type(self.dtype, x.dtype))

        for i in range(self.ndims[0]):
            col_dim = 0
            local_res = res[row_dim:row_dim + self._rows[i], :]
            for j in range(self.ndims[1]):
                local_x = x[col_dim:col_dim + self._cols[j], :]
                op_is_complex = _np.iscomplexobj(
                    self._operators[i, j].dtype.type(1))
                if _np.iscomplexobj(x) and not op_is_complex:
                    local_res[:] += (
                        self._operators[i, j].dot(_np.real(local_x)) +
                        1j * self._operators[i, j].dot(_np.imag(local_x)))
                else:
                    local_res[:] += self._operators[i, j].dot(local_x)
                col_dim += self._cols[j]
            row_dim += self._rows[i]
        if expand_input_dim:
            return res.ravel()
        else:
            return res
Esempio n. 3
0
    def _matmat(self, x):
        from bempp.api.utils.data_types import combined_type

        if not self._fill_complete():
            raise ValueError("Not all rows or columns contain operators.")

        row_dim = 0
        res = _np.zeros((self.shape[0], x.shape[1]),
                        dtype=combined_type(self.dtype, x.dtype))

        for i in range(self._ndims[0]):
            col_dim = 0
            local_res = res[row_dim:row_dim + self._rows[i], :]
            for j in range(self._ndims[1]):
                local_x = x[col_dim:col_dim + self._cols[j], :]
                op_is_complex = _np.iscomplexobj(
                    self._operators[i, j].dtype.type(1))
                if _np.iscomplexobj(x) and not op_is_complex:
                    local_res[:] += self._operators[i, j].dot(
                        _np.real(local_x)) + 1j * self._operators[i, j].dot(
                            _np.imag(local_x))
                else:
                    local_res[:] += self._operators[i, j].dot(local_x)
                col_dim += self._cols[j]
            row_dim += self._rows[i]
        return res
Esempio n. 4
0
    def _get_dtype(self):

        from bempp.api.utils.data_types import combined_type

        d = 'float64'
        for obj in self._operators.ravel():
            if obj is not None:
                d = combined_type(d, obj.dtype)

        return d
Esempio n. 5
0
    def __init__(self, op1, op2):
        """Construct a product of the form op1 * op2."""
        if _np.any(op1.column_dimensions != op2.row_dimensions):
            raise ValueError("Incompatible dimensions. {0} != {1}".format(
                op1.column_dimensions, op2.row_dimensions))

        self._op1 = op1
        self._op2 = op2

        from bempp.api.utils.data_types import combined_type

        super(BlockedDiscreteOperatorProduct,
              self).__init__(op1.ndims[0], op2.ndims[1],
                             combined_type(op1.dtype, op2.dtype),
                             (op1.shape[0], op2.shape[1]))
Esempio n. 6
0
    def _matvec(self, x):
        """Perform matrix vector multiplication."""
        from bempp.api.utils.data_types import combined_type

        if not self._fill_complete():
            raise ValueError("Not all rows or columns contain operators.")

        ndims = len(x.shape)
        x = x.ravel()

        row_dim = 0
        res = _np.zeros(self.shape[0],
                        dtype=combined_type(self.dtype, x.dtype))

        compute_tasks = []

        # Submit the computations
        for i in range(self._ndims[0]):
            col_dim = 0
            for j in range(self._ndims[1]):
                if self._tags[i, j] != -1:
                    # If self._tags[i, j] == -1 the operator is None
                    local_x = x[col_dim:col_dim + self._cols[j]]
                    compute_tasks.append((self._operators[i, j], local_x))
                col_dim += self._cols[j]
            row_dim += self._rows[i]

        # Execute computations

        compute_results = self._manager.compute_parallel(compute_tasks)

        # Get results back
        row_dim = 0
        task_count = 0
        for i in range(self._ndims[0]):
            col_dim = 0
            for j in range(self._ndims[1]):
                if self._tags[i, j] == -1:
                    continue
                res[row_dim:row_dim +
                    self._rows[i]] += compute_results[task_count]
                task_count += 1
            row_dim += self._rows[i]

        if ndims == 2:
            res = res.reshape(-1, 1)

        return res
Esempio n. 7
0
    def _matmat(self, other):
        """Implement the matrix/vector product."""
        from bempp.api.utils.data_types import combined_type

        row_count = 0
        output = _np.zeros(
            (self.shape[0], other.shape[1]),
            dtype=combined_type(self.dtype, other.dtype),
        )

        for row in self._operators:
            row_dim = row[0].shape[0]
            column_count = 0
            for elem in row:
                output[row_count:row_count + row_dim, :] += (
                    elem @ other[column_count:column_count + elem.shape[1], :])
                column_count += elem.shape[1]
            row_count += row_dim

        return output
Esempio n. 8
0
    def __init__(self, operators):
        """Initialize a generalized blocked operator."""
        from bempp.api.utils.data_types import combined_type

        self._operators = operators

        row_dimensions = []

        shape = [0, 0]
        # Get column dimension
        for elem in operators[0]:
            shape[1] += elem.shape[1]
        # Get row dimension
        for row in operators:
            shape[0] += row[0].shape[0]

        shape = tuple(shape)

        # Get dtype

        dtype = operators[0][0].dtype
        for row in operators:
            for elem in row:
                dtype = combined_type(dtype, elem.dtype)

        # Sanity check of dimensions

        for row in operators:
            row_dim = row[0].shape[0]
            column_dim = 0
            for elem in row:
                if elem.shape[0] != row_dim:
                    raise ValueError("Incompatible dimensions detected.")
                column_dim += elem.shape[1]
            if column_dim != shape[1]:
                raise ValueError("Incompatible dimensions detected.")

        super().__init__(dtype, shape)
Esempio n. 9
0
    def __init__(self, ops):
        """
        Construct an operator from a two dimensional Numpy array of operators.

        ops is a list of list containing discrete boundary operators or None.
        A None entry is equivalent to a zero discrete boundary operator.

        """
        # pylint: disable=too-many-branches
        from bempp.api.utils.data_types import combined_type
        from bempp.api.assembly.discrete_boundary_operator import (
            ZeroDiscreteBoundaryOperator, )

        if not isinstance(ops, _np.ndarray):
            ops = _np.array(ops)

        rows = ops.shape[0]
        cols = ops.shape[1]

        self._ndims = (rows, cols)

        self._operators = _np.empty((rows, cols), dtype=_np.object)
        self._rows = -_np.ones(rows, dtype=int)
        self._cols = -_np.ones(cols, dtype=int)

        for i in range(rows):
            for j in range(cols):
                if ops[i, j] is None:
                    continue
                if self._rows[i] != -1:
                    if ops[i, j].shape[0] != self._rows[i]:
                        raise ValueError(
                            "Block row {0} has incompatible ".format(i) +
                            " operator sizes.")
                else:
                    self._rows[i] = ops[i, j].shape[0]

                if self._cols[j] != -1:
                    if ops[i, j].shape[1] != self._cols[j]:
                        raise ValueError(
                            "Block column {0} has incompatible".format(j) +
                            "operator sizes.")
                else:
                    self._cols[j] = ops[i, j].shape[1]
                self._operators[i, j] = ops[i, j]

        if not self._fill_complete():
            raise ValueError(
                "Each row and column must contain at least one operator.")

        for i in range(rows):
            for j in range(cols):
                if self._operators[i, j] is None:
                    self._operators[i, j] = ZeroDiscreteBoundaryOperator(
                        self._rows[i], self._cols[j])

        shape = (_np.sum(self._rows), _np.sum(self._cols))

        dtype = "float32"
        for obj in self._operators.ravel():
            if obj is not None:
                dtype = combined_type(dtype, obj.dtype)

        super().__init__(dtype, shape)