Mantid
Loading...
Searching...
No Matches
EigenComplexMatrix.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
11
12namespace Mantid::CurveFitting {
13
19ComplexMatrix::ComplexMatrix(const size_t nx, const size_t ny) : m_matrix(Eigen::MatrixXcd(nx, ny)) { zero(); }
20
23ComplexMatrix::ComplexMatrix(const ComplexMatrix &M) : m_matrix(M.eigen()) {}
24
32ComplexMatrix::ComplexMatrix(const ComplexMatrix &M, const size_t row, const size_t col, const size_t nRows,
33 const size_t nCols) {
34 if (row + nRows > M.size1() || col + nCols > M.size2()) {
35 throw std::runtime_error("Submatrix exceeds matrix size.");
36 }
37
38 m_matrix = complex_matrix_map_type(M.eigen().data() + (col * M.size1()) + row, nRows, nCols,
39 dynamic_stride(M.eigen().outerStride(), M.eigen().innerStride()));
40}
41
43ComplexMatrix::ComplexMatrix(ComplexMatrix &&m) noexcept : m_matrix(std::move(m.m_matrix)) {}
44
46ComplexMatrix::ComplexMatrix(Eigen::MatrixXcd &&m) noexcept : m_matrix(std::move(m)) {}
47
50 m_matrix = M.eigen();
51 return *this;
52}
53
56 m_matrix = std::move(M.m_matrix);
57 return *this;
58}
59
61ComplexMatrix &ComplexMatrix::operator=(const Eigen::MatrixXcd eigenMatrix) {
62 m_matrix = eigenMatrix;
63 return *this;
64}
65
67bool ComplexMatrix::isEmpty() const { return m_matrix.size() == 0; }
68
72void ComplexMatrix::resize(const size_t nx, const size_t ny) {
73 if (nx == size1() && ny == size2()) {
74 return;
75 }
76 m_matrix.resize(nx, ny);
77 zero();
78}
79
81size_t ComplexMatrix::size1() const { return m_matrix.rows(); }
82
84size_t ComplexMatrix::size2() const { return m_matrix.cols(); }
85
90void ComplexMatrix::set(const size_t i, const size_t j, const ComplexType value) {
91 if (i < size1() && j < size2()) {
92 m_matrix(i, j) = value;
93 } else {
94 throw std::out_of_range("ComplexMatrix indices are out of range.");
95 }
96}
97
101ComplexType ComplexMatrix::get(const size_t i, const size_t j) const {
102 if (i < size1() && j < size2()) {
103 return m_matrix(i, j);
104 }
105 throw std::out_of_range("ComplexMatrix indices are out of range.");
106}
107
109ComplexType ComplexMatrix::operator()(const size_t i, const size_t j) const {
110 return const_cast<ComplexMatrix &>(*this)(i, j);
111}
112
114ComplexType &ComplexMatrix::operator()(const size_t i, const size_t j) { return m_matrix(i, j); }
115
117void ComplexMatrix::identity() { m_matrix.setIdentity(); }
118
120void ComplexMatrix::zero() { m_matrix.setZero(); }
121
125 const auto n = d.size();
126 resize(n, n);
127 zero();
128 for (size_t i = 0; i < n; ++i) {
129 set(i, i, d.get(i));
130 }
131}
132
136 m_matrix += M.eigen();
137 return *this;
138}
142 m_matrix.array() += d;
143 return *this;
144}
148 m_matrix -= M.eigen();
149 return *this;
150}
154 m_matrix *= d;
155 return *this;
156}
157
160 if (m.size1() != size2()) {
161 throw std::invalid_argument("Matrix by matrix multiplication: matricies are of incompatible sizes.");
162 }
163
164 ComplexMatrix res(m.size1(), size2());
165 res.eigen() = eigen() * m.inspector();
166 return res;
167}
168
171 if (m.size1() != size2()) {
172 throw std::invalid_argument("Matrix by matrix multiplication: matricies are of incompatible sizes.");
173 }
174
175 ComplexMatrix res(m.size1(), size2());
176 res.eigen() = eigen() * m.eigen();
177 return res;
178}
179
185 if (size1() != size2()) {
186 throw std::invalid_argument("System of linear equations: the matrix must be square.");
187 }
188 size_t n = size1();
189 if (rhs.size() != n) {
190 throw std::invalid_argument("System of linear equations: right-hand side vector has wrong size.");
191 }
192 if (det() == ComplexType(0, 0)) {
193 throw std::invalid_argument("Matrix A is singular.");
194 }
195
196 Eigen::MatrixXcd b = rhs.eigen();
197 Eigen::ColPivHouseholderQR<Eigen::MatrixXcd> dec(eigen());
198 Eigen::VectorXcd res = dec.solve(b);
199 x = res;
200
201 if (!rhs.eigen().isApprox(eigen() * x.eigen())) {
202 throw std::runtime_error("Matrix Solution Error: solution does not exist.");
203 }
204}
205
208 if (size1() != size2()) {
209 throw std::runtime_error("Matrix inverse: the matrix must be square.");
210 }
211 m_matrix = m_matrix.inverse();
212}
213
216 if (size1() != size2()) {
217 throw std::runtime_error("Matrix inverse: the matrix must be square.");
218 }
219
220 return m_matrix.determinant();
221}
222
229 size_t n = size1();
230 if (n != size2()) {
231 throw std::runtime_error("Matrix eigenSystem: the matrix must be square.");
232 }
233 eigenValues.resize(n);
234
235 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXcd> solver;
236 solver.compute(m_matrix);
237
238 eigenValues = solver.eigenvalues();
239 eigenVectors = solver.eigenvectors();
240}
241
245 if (i >= size1()) {
246 throw std::out_of_range("EigenMatrix row index is out of range.");
247 }
248
249 Eigen::VectorXcd row = complex_vector_map_type(eigen().data() + i, size2(), dynamic_stride(0, eigen().outerStride()));
250 return ComplexVector(row);
251}
252
256 if (i >= size2()) {
257 throw std::out_of_range("ComplexMatrix column index is out of range.");
258 }
259
260 Eigen::VectorXcd col =
261 complex_vector_map_type(eigen().data() + (i * size1()), size1(), dynamic_stride(0, eigen().innerStride()));
262 return ComplexVector(col);
263}
264
267void ComplexMatrix::sortColumns(const std::vector<size_t> &indices) {
268 Eigen::MatrixXcd matrix = Eigen::MatrixXcd(size1(), size2());
269 for (size_t col = 0; col < size2(); ++col) {
270 auto col1 = indices[col];
271 for (size_t row = 0; row < size1(); ++row) {
272 matrix(row, col) = m_matrix(row, col1);
273 }
274 }
275 m_matrix = matrix;
276}
277
280std::vector<double> ComplexMatrix::packToStdVector() const {
281 const size_t n1 = size1();
282 const size_t n2 = size2();
283
284 std::vector<double> packed(2 * n1 * n2);
285 for (size_t i = 0; i < n1; ++i) {
286 for (size_t j = 0; j < n2; ++j) {
287 auto k = 2 * (i * n2 + j);
288 ComplexType value = get(i, j);
289 packed[k] = value.real();
290 packed[k + 1] = value.imag();
291 }
292 }
293 return packed;
294}
295
300void ComplexMatrix::unpackFromStdVector(const std::vector<double> &packed) {
301 const size_t n1 = size1();
302 const size_t n2 = size2();
303 if (2 * n1 * n2 != packed.size()) {
304 throw std::runtime_error("Cannot unpack vector into ComplexMatrix: size mismatch.");
305 }
306 for (size_t i = 0; i < n1; ++i) {
307 for (size_t j = 0; j < n2; ++j) {
308 auto k = 2 * (i * n2 + j);
309 ComplexType value(packed[k], packed[k + 1]);
310 set(i, j, value);
311 }
312 }
313}
314
317 ComplexMatrix res = *this;
318 res.eigen() = m_matrix.transpose();
319 return res;
320}
321
324 ComplexMatrix res = *this;
325 res.eigen() = m_matrix.adjoint();
326 return res;
327}
328
329} // namespace Mantid::CurveFitting
const std::vector< double > & rhs
Eigen::Map< const Eigen::VectorXcd, 0, Mantid::CurveFitting::dynamic_stride > complex_vector_map_type
Eigen::Map< const Eigen::MatrixXcd, 0, Mantid::CurveFitting::dynamic_stride > complex_matrix_map_type
double value
The value of the point.
Definition: FitMW.cpp:51
A complex-valued matrix for linear algebra computations.
ComplexMatrix operator*(const EigenMatrix &m) const
Multiply this matrix by a matrix.
Eigen::MatrixXcd m_matrix
The pointer to the complex Eigen matrix.
void resize(const size_t nx, const size_t ny)
Resize the matrix.
size_t size2() const
Second size of the matrix.
void identity()
Set this matrix to identity matrix.
void zero()
Set all elements to zero.
size_t size1() const
First size of the matrix.
ComplexType det()
Calculate the determinant.
void sortColumns(const std::vector< size_t > &indices)
Sort columns in order defined by an index array.
Eigen::MatrixXcd & eigen()
Get the reference to the eigen matrix.
ComplexMatrix ctr() const
Get "conjugate transposed" matrix to be used in multiplications.
std::vector< double > packToStdVector() const
Pack the matrix into a single std vector of doubles (for passing in and out of algorithms)
ComplexMatrix & operator*=(const ComplexType &d)
Multiply this matrix by a number.
void solve(const ComplexVector &rhs, ComplexVector &x)
Solve system of linear equations M*x == rhs, M is this matrix This matrix is destroyed.
ComplexMatrix tr() const
Get "transposed" matrix to be used in multiplications.
bool isEmpty() const
Is matrix empty.
ComplexVector copyRow(const size_t i) const
Copy a row into a GSLVector.
void unpackFromStdVector(const std::vector< double > &v)
Unpack an std vector into this matrix.
ComplexVector copyColumn(const size_t i) const
Copy a column into a GSLVector.
ComplexMatrix & operator+=(const ComplexMatrix &M)
Add a matrix to this.
void eigenSystemHermitian(EigenVector &eigenValues, ComplexMatrix &eigenVectors)
Calculate the eigensystem of a Hermitian matrix.
ComplexType get(const size_t i, const size_t j) const
Get an element.
ComplexMatrix & operator-=(const ComplexMatrix &M)
Subtract a matrix from this.
ComplexMatrix & operator=(const ComplexMatrix &M)
Copy assignment operator.
void set(const size_t i, const size_t j, const ComplexType value)
Set an element.
ComplexType operator()(const size_t i, const size_t j) const
The "index" operator.
void diag(const ComplexVector &d)
Set the matrix to be diagonal.
A complex-valued vector for linear algebra computations.
A wrapper around Eigen::Matrix.
Definition: EigenMatrix.h:33
A wrapper around Eigen::Vector.
Definition: EigenVector.h:27
void resize(const size_t n)
Resize the vector.
Definition: EigenVector.cpp:96
std::complex< double > ComplexType
Eigen::Stride< Eigen::Dynamic, Eigen::Dynamic > dynamic_stride