votca 2024.2-dev
Loading...
Searching...
No Matches
linalg.cc
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18// Standard includes
19#include <iostream>
20#include <sstream>
21
22// Local VOTCA includes
23#include "votca/tools/linalg.h"
24
25namespace votca {
26namespace tools {
27
28Eigen::VectorXd linalg_constrained_qrsolve(const Eigen::MatrixXd &A,
29 const Eigen::VectorXd &b,
30 const Eigen::MatrixXd &constr) {
31 // check matrix for zero column
32
33 bool nonzero_found = false;
34 for (Index j = 0; j < A.cols(); j++) {
35 nonzero_found = A.col(j).isApproxToConstant(0.0, 1e-9);
36 if (nonzero_found) {
37 throw std::runtime_error("constrained_qrsolve_zero_column_in_matrix");
38 }
39 }
40
41 const Index NoVariables = A.cols();
42 const Index NoConstrains =
43 constr.rows(); // number of constraints is number of rows of constr
44 const Index deg_of_freedom = NoVariables - NoConstrains;
45
46 Eigen::HouseholderQR<Eigen::MatrixXd> QR(constr.transpose());
47
48 // Calculate A * Q and store the result in A
49 auto A_new = A * QR.householderQ();
50 // A_new = [A1 A2], so A2 is just a block of A
51 // [A1 A2] has N rows. A1 has ysize columns
52 // A2 has 2*ngrid-ysize columns
53 Eigen::MatrixXd A2 = A_new.rightCols(deg_of_freedom);
54 // now perform QR-decomposition of A2 to solve the least-squares problem A2 *
55 // z = b A2 has N rows and (2*ngrid-ysize) columns ->
56 Eigen::HouseholderQR<Eigen::MatrixXd> QR2(A2);
57 Eigen::VectorXd z = QR2.solve(b);
58
59 // Next two steps assemble vector from y (which is zero-vector) and z
60 Eigen::VectorXd result = Eigen::VectorXd::Zero(NoVariables);
61 result.tail(deg_of_freedom) = z;
62 // To get the final answer this vector should be multiplied by matrix Q
63 return QR.householderQ() * result;
64}
65
66} // namespace tools
67} // namespace votca
Eigen::VectorXd linalg_constrained_qrsolve(const Eigen::MatrixXd &A, const Eigen::VectorXd &b, const Eigen::MatrixXd &constr)
solves A*x=b under the constraint B*x = 0
Definition linalg.cc:28
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26