RealTimeTransport 1.0.0
Real-time simulation of quantum transport processes
Loading...
Searching...
No Matches
BlockDiagonalMatrix.h
Go to the documentation of this file.
1//
2// This Source Code Form is subject to the terms of the Mozilla Public
3// License, v. 2.0. If a copy of the MPL was not distributed with this
4// file, You can obtain one at https://mozilla.org/MPL/2.0/.
5//
6
7///
8/// \file BlockDiagonalMatrix.h
9///
10/// \brief Contains a class representing block diagonal matrices.
11///
12
13#ifndef REAL_TIME_TRANSPORT_BLOCK_MATRICES_BLOCK_DIAGONAL_H
14#define REAL_TIME_TRANSPORT_BLOCK_MATRICES_BLOCK_DIAGONAL_H
15
16#include <vector>
17
18#include <SciCore/Definitions.h>
19
20#include "../Error.h"
21#include "../RealTimeTransport_export.h"
22#include "BlockHelper.h"
23
24namespace RealTimeTransport
25{
26
27///
28/// @brief Represents a block diagonal matrix.
29///
30/// This class represents a complex valued block diagonal matrix.
31///
33{
34 public:
35 /// @brief Type representing the matrix elements.
37
38 /// @brief Type representing a matrix block.
40
41 ///
42 /// @brief Constructs an empty block diagonal matrix.
43 ///
45
46 ///
47 /// @brief Move constructor.
48 ///
50
51 ///
52 /// @brief Copy constructor.
53 ///
55
56 ///
57 /// @brief Constructs a block diagonal matrix with given \a blocks.
58 ///
59 BlockDiagonalMatrix(std::vector<MatrixType>&& blocks) noexcept;
60
61 ///
62 /// @brief Constructs a block diagonal matrix from a dense \a matrix where the dimensions of the blocks are given by \a blockDimensions.
63 ///
64 template <typename DenseMatrixT>
65 BlockDiagonalMatrix(const DenseMatrixT& matrix, const std::vector<int>& blockDimensions)
66 {
67 fromDense(matrix, blockDimensions);
68 }
69
70 ///
71 /// @brief Move assignment operator.
72 ///
74
75 ///
76 /// @brief Copy assignment operator.
77 ///
79
80 ///
81 /// @brief Equality comparison operator.
82 ///
83 bool operator==(const BlockDiagonalMatrix& other) const;
84
85 ///
86 /// @brief Inequality comparison operator.
87 ///
88 bool operator!=(const BlockDiagonalMatrix& other) const;
89
90 ///
91 /// @brief Returns a matrix with given \a blockDimensions that is zero everywhere.
92 ///
93 static BlockDiagonalMatrix Zero(const std::vector<int>& blockDimensions);
94
95 ///
96 /// @brief Returns a matrix with given \a blockDimensions equal to the identity matrix.
97 ///
98 static BlockDiagonalMatrix Identity(const std::vector<int>& blockDimensions);
99
100 ///
101 /// @brief Adds the block diagonal matrix \a rhs to the object.
102 ///
104
105 ///
106 /// @brief Subtracts the block diagonal matrix \a rhs from the object.
107 ///
109
110 ///
111 /// @brief Multiplies the block diagonal matrix \a rhs from the right to object.
112 ///
114
115 ///
116 /// @brief Multiplies the object by the a \a scalar.
117 ///
118 BlockDiagonalMatrix& operator*=(SciCore::Real scalar);
119
120 ///
121 /// @brief Multiplies the object by the a \a scalar.
122 ///
123 BlockDiagonalMatrix& operator*=(SciCore::Complex scalar);
124
125 ///
126 /// @brief Multiplies the number of blocks.
127 ///
128 int numBlocks() const noexcept;
129
130 ///
131 /// @brief Returns the total number of rows.
132 ///
133 int totalRows() const noexcept;
134
135 ///
136 /// @brief Returns the total number of columns.
137 ///
138 int totalCols() const noexcept;
139
140 ///
141 /// @brief Returns a vector containing the dimensions of each block.
142 ///
144
145 ///
146 /// @brief Returns the matrix block with index \a i.
147 ///
149
150 ///
151 /// @brief Returns the matrix block with index \a i.
152 ///
153 const MatrixType& operator()(int i) const;
154
155 ///
156 /// @brief Creates a new block diagonal matrix from given \a blocks.
157 ///
158 void fromBlocks(std::vector<MatrixType>&& newBlocks);
159
160 ///
161 /// @brief Constructs a block diagonal matrix from a dense \a matrix where the dimensions of the blocks are given by \a blockDimensions.
162 ///
163 template <typename DenseMatrixT>
164 void fromDense(const DenseMatrixT& matrix, const std::vector<int>& blockDimensions)
165 {
166#ifdef REAL_TIME_TRANSPORT_DEBUG
167 if (isBlockDiagonal(matrix, blockDimensions) == false)
168 {
169 throw Error("Matrix is not block diagonal as required");
170 }
171#endif
172
173 size_t numBlocks = blockDimensions.size();
174 _blocks.resize(numBlocks);
175
176 // Partition the matrix into blocks and store them
177 for (int i = 0; i < static_cast<int>(numBlocks); ++i)
178 {
179 _blocks[i] = extractDenseBlock(matrix, i, i, blockDimensions);
180 }
181 }
182
183 ///
184 /// @brief Sets the matrix to zero with block dimensions \a blockDimensions.
185 ///
186 void setZero(const std::vector<int>& blockDimensions);
187
188 ///
189 /// @brief Returns a dense matrix representation.
190 ///
192
193 ///
194 /// @brief Returns the matrix element at a given \a row and \a column.
195 ///
196 const Scalar& element(int row, int column) const;
197
198 ///
199 /// @brief Returns the matrix element at a given \a row and \a column.
200 ///
202
203 template <class Archive>
204 void serialize(Archive& archive)
205 {
206 archive(_blocks);
207 }
208
209 private:
210 std::vector<MatrixType> _blocks; // Store each block of the matrix
211};
212
213REALTIMETRANSPORT_EXPORT SciCore::Real maxNorm(const BlockDiagonalMatrix& A);
214
218REALTIMETRANSPORT_EXPORT BlockDiagonalMatrix operator*(const BlockDiagonalMatrix& lhs, SciCore::Real scalar);
219REALTIMETRANSPORT_EXPORT BlockDiagonalMatrix operator*(const BlockDiagonalMatrix& lhs, SciCore::Complex scalar);
220REALTIMETRANSPORT_EXPORT BlockDiagonalMatrix operator*(SciCore::Real scalar, const BlockDiagonalMatrix& rhs);
221REALTIMETRANSPORT_EXPORT BlockDiagonalMatrix operator*(SciCore::Complex scalar, const BlockDiagonalMatrix& rhs);
222
223// Computes result += α * A * x, where α is a scalar, A is a block diagonal matrix and x is a vector
224template <typename ScalarT, typename T>
225void addProduct(
226 ScalarT alpha,
227 const BlockDiagonalMatrix& A,
228 const Eigen::Matrix<T, Eigen::Dynamic, 1>& x,
229 Eigen::Matrix<T, Eigen::Dynamic, 1>& result)
230{
231#ifdef REAL_TIME_TRANSPORT_DEBUG
232 if (A.totalCols() != x.size() || A.totalRows() != result.size())
233 {
234 throw Error("Vector size does not match the total size of the block diagonal matrix.");
235 }
236#endif // REAL_TIME_TRANSPORT_DEBUG
237
238 int currentRow = 0;
239 for (int i = 0; i < A.numBlocks(); ++i)
240 {
241 const auto& block = A(i);
242 result.segment(currentRow, block.rows()) += alpha * block * x.segment(currentRow, block.rows());
243
244 currentRow += block.rows();
245 }
246}
247
248// Returns α * A * x, where α is a scalar, A is a block diagonal matrix and x is a vector
249template <typename ScalarT, typename T>
250Eigen::Matrix<T, Eigen::Dynamic, 1> product(
251 ScalarT alpha,
252 const BlockDiagonalMatrix& A,
253 const Eigen::Matrix<T, Eigen::Dynamic, 1>& x)
254{
255 using ReturnType = Eigen::Matrix<T, Eigen::Dynamic, 1>;
256
257 ReturnType returnValue = ReturnType::Zero(x.size());
258 addProduct(alpha, A, x, returnValue);
259 return returnValue;
260}
261
262template <typename T>
263Eigen::Matrix<T, Eigen::Dynamic, 1> operator*(
264 const BlockDiagonalMatrix& A,
265 const Eigen::Matrix<T, Eigen::Dynamic, 1>& x)
266{
267 return product(1.0, A, x);
268}
269
270// Computes result += α * x * A, where α is a scalar, A is a block diagonal matrix and x is a rowvector
271template <typename ScalarT, typename T>
272void addProduct(
273 ScalarT alpha,
274 const Eigen::Matrix<T, 1, Eigen::Dynamic>& x,
275 const BlockDiagonalMatrix& A,
276 Eigen::Matrix<T, 1, Eigen::Dynamic>& result)
277{
278#ifdef REAL_TIME_TRANSPORT_DEBUG
279 if (A.totalRows() != x.size() || A.totalCols() != result.size())
280 {
281 throw Error("Vector size does not match the total size of the block diagonal matrix.");
282 }
283#endif // REAL_TIME_TRANSPORT_DEBUG
284
285 int currentCol = 0;
286 for (int i = 0; i < A.numBlocks(); ++i)
287 {
288 const auto& block = A(i);
289 result.segment(currentCol, block.cols()) += alpha * x.segment(currentCol, block.cols()) * block;
290
291 currentCol += block.cols();
292 }
293}
294
295// Returns α * x * A, where α is a scalar, A is a block diagonal matrix and x is a rowvector
296template <typename ScalarT, typename T>
297Eigen::Matrix<T, 1, Eigen::Dynamic> product(
298 ScalarT alpha,
299 const Eigen::Matrix<T, 1, Eigen::Dynamic>& x,
300 const BlockDiagonalMatrix& A)
301{
302 using ReturnType = Eigen::Matrix<T, 1, Eigen::Dynamic>;
303
304 ReturnType returnValue = ReturnType::Zero(x.size());
305 addProduct(alpha, x, A, returnValue);
306 return returnValue;
307}
308
309template <typename T>
310Eigen::Matrix<T, 1, Eigen::Dynamic> operator*(
311 const Eigen::Matrix<T, 1, Eigen::Dynamic>& x,
312 const BlockDiagonalMatrix& A)
313{
314
315 return product(1.0, x, A);
316}
317
318} // namespace RealTimeTransport
319
320#endif // REAL_TIME_TRANSPORT_BLOCK_MATRICES_BLOCK_DIAGONAL_H
#define REALTIMETRANSPORT_EXPORT
Definition RealTimeTransport_export.h:15
Represents a block diagonal matrix.
Definition BlockDiagonalMatrix.h:33
void setZero(const std::vector< int > &blockDimensions)
Sets the matrix to zero with block dimensions blockDimensions.
MatrixType & operator()(int i)
Returns the matrix block with index i.
void fromDense(const DenseMatrixT &matrix, const std::vector< int > &blockDimensions)
Constructs a block diagonal matrix from a dense matrix where the dimensions of the blocks are given b...
Definition BlockDiagonalMatrix.h:164
std::vector< int > blockDimensions() const
Returns a vector containing the dimensions of each block.
int totalRows() const noexcept
Returns the total number of rows.
const MatrixType & operator()(int i) const
Returns the matrix block with index i.
BlockDiagonalMatrix & operator*=(const BlockDiagonalMatrix &rhs)
Multiplies the block diagonal matrix rhs from the right to object.
int totalCols() const noexcept
Returns the total number of columns.
bool operator!=(const BlockDiagonalMatrix &other) const
Inequality comparison operator.
BlockDiagonalMatrix() noexcept
Constructs an empty block diagonal matrix.
Scalar & element(int row, int colum)
Returns the matrix element at a given row and column.
void fromBlocks(std::vector< MatrixType > &&newBlocks)
Creates a new block diagonal matrix from given blocks.
BlockDiagonalMatrix(const BlockDiagonalMatrix &other)
Copy constructor.
bool operator==(const BlockDiagonalMatrix &other) const
Equality comparison operator.
BlockDiagonalMatrix & operator+=(const BlockDiagonalMatrix &rhs)
Adds the block diagonal matrix rhs to the object.
const Scalar & element(int row, int column) const
Returns the matrix element at a given row and column.
BlockDiagonalMatrix & operator*=(SciCore::Real scalar)
Multiplies the object by the a scalar.
int numBlocks() const noexcept
Multiplies the number of blocks.
BlockDiagonalMatrix & operator=(const BlockDiagonalMatrix &other)
Copy assignment operator.
BlockDiagonalMatrix(std::vector< MatrixType > &&blocks) noexcept
Constructs a block diagonal matrix with given blocks.
BlockDiagonalMatrix & operator=(BlockDiagonalMatrix &&other) noexcept
Move assignment operator.
BlockDiagonalMatrix & operator-=(const BlockDiagonalMatrix &rhs)
Subtracts the block diagonal matrix rhs from the object.
static BlockDiagonalMatrix Zero(const std::vector< int > &blockDimensions)
Returns a matrix with given blockDimensions that is zero everywhere.
BlockDiagonalMatrix(const DenseMatrixT &matrix, const std::vector< int > &blockDimensions)
Constructs a block diagonal matrix from a dense matrix where the dimensions of the blocks are given b...
Definition BlockDiagonalMatrix.h:65
MatrixType toDense() const
Returns a dense matrix representation.
static BlockDiagonalMatrix Identity(const std::vector< int > &blockDimensions)
Returns a matrix with given blockDimensions equal to the identity matrix.
BlockDiagonalMatrix(BlockDiagonalMatrix &&other) noexcept
Move constructor.