Mimetic Operators Library Enhanced 4.0
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1/*
2* SPDX-License-Identifier: GPL-3.0-or-later
3* © 2008-2024 San Diego State University Research Foundation (SDSURF).
4* See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html for details.
5*/
6
7
8/*
9 * @file utils.cpp
10 * @brief Helpers for sparse operations and MATLAB analogs
11 * @date 2024/10/15
12 *
13 * Sparse operations that repeatedly are needed, but not
14 * necessarily part of the Armadillo library. Some other MATLAB
15 * type functions are also here, like meshgrid.
16 */
17
18#include "utils.h"
19#include <cassert>
20
21#ifdef EIGEN
22#include <eigen3/Eigen/SparseLU>
23
24vec Utils::spsolve_eigen(const sp_mat &A, const vec &b) {
25 Eigen::SparseMatrix<Real> eigen_A(A.n_rows, A.n_cols);
26 std::vector<Eigen::Triplet<Real>> triplets;
27 Eigen::SparseLU<Eigen::SparseMatrix<Real>, Eigen::COLAMDOrdering<int>> solver;
28
29 Eigen::VectorXd eigen_x(A.n_rows);
30 triplets.reserve(5 * A.n_rows);
31
32 auto it = A.begin();
33 while (it != A.end()) {
34 triplets.push_back(Eigen::Triplet<Real>(it.row(), it.col(), *it));
35 ++it;
36 }
37
38 eigen_A.setFromTriplets(triplets.begin(), triplets.end());
39 triplets.clear();
40
41 auto b_ = conv_to<std::vector<Real>>::from(b);
42 Eigen::Map<Eigen::VectorXd> eigen_b(b_.data(), b_.size());
43
44 solver.analyzePattern(eigen_A);
45 solver.factorize(eigen_A);
46 eigen_x = solver.solve(eigen_b);
47
48 return vec(eigen_x.data(), eigen_x.size());
49}
50#endif
51
52// Basic implementation of Kronecker product
53/*
54sp_mat Utils::spkron(const sp_mat &A, const sp_mat &B)
55{
56 sp_mat result;
57
58 for (u32 i = 0; i < A.n_rows; i++) {
59 sp_mat BLOCK;
60 for (u32 j = 0; j < A.n_cols; j++) {
61 BLOCK = join_rows(BLOCK, A(i, j)*B);
62 }
63 result = join_cols(result, BLOCK);
64 }
65
66 return result;
67}
68*/
69
70sp_mat Utils::spkron(const sp_mat &A, const sp_mat &B) {
71 sp_mat::const_iterator itA = A.begin();
72 sp_mat::const_iterator endA = A.end();
73 sp_mat::const_iterator itB = B.begin();
74 sp_mat::const_iterator endB = B.end();
75 u32 j = 0;
76
77 vec a = nonzeros(A);
78 vec b = nonzeros(B);
79
80 umat locations(2, a.n_elem * b.n_elem);
81 vec values(a.n_elem * b.n_elem);
82
83 while (itA != endA) {
84 while (itB != endB) {
85 locations(0, j) = itA.row() * B.n_rows + itB.row();
86 locations(1, j) = itA.col() * B.n_cols + itB.col();
87 values(j) = (*itA) * (*itB);
88 ++j;
89 ++itB;
90 }
91
92 ++itA;
93 itB = B.begin();
94 }
95
96 sp_mat result(locations, values, A.n_rows * B.n_rows, A.n_cols * B.n_cols,
97 true);
98
99 return result;
100}
101
102
103sp_mat Utils::spjoin_rows(const sp_mat &A, const sp_mat &B) {
104 sp_mat::const_iterator itA = A.begin();
105 sp_mat::const_iterator endA = A.end();
106 sp_mat::const_iterator itB = B.begin();
107 sp_mat::const_iterator endB = B.end();
108 u32 j = 0;
109
110 vec a = nonzeros(A);
111 vec b = nonzeros(B);
112
113 umat locations(2, a.n_elem + b.n_elem);
114 vec values(a.n_elem + b.n_elem);
115
116 while (itA != endA) {
117 locations(0, j) = itA.row();
118 locations(1, j) = itA.col();
119 values(j) = (*itA);
120 ++itA;
121 ++j;
122 }
123
124 while (itB != endB) {
125 locations(0, j) = itB.row();
126 locations(1, j) = itB.col() + A.n_cols;
127 values(j) = (*itB);
128 ++itB;
129 ++j;
130 }
131
132 sp_mat result(locations, values, A.n_rows, A.n_cols + B.n_cols, true);
133
134 return result;
135}
136
137
138sp_mat Utils::spjoin_cols(const sp_mat &A, const sp_mat &B) {
139 sp_mat::const_iterator itA = A.begin();
140 sp_mat::const_iterator endA = A.end();
141 sp_mat::const_iterator itB = B.begin();
142 sp_mat::const_iterator endB = B.end();
143 u32 j = 0;
144
145 vec a = nonzeros(A);
146 vec b = nonzeros(B);
147
148 umat locations(2, a.n_elem + b.n_elem);
149 vec values(a.n_elem + b.n_elem);
150
151 while (itA != endA) {
152 locations(0, j) = itA.row();
153 locations(1, j) = itA.col();
154 values(j) = (*itA);
155 ++itA;
156 ++j;
157 }
158
159 while (itB != endB) {
160 locations(0, j) = itB.row() + A.n_rows;
161 locations(1, j) = itB.col();
162 values(j) = (*itB);
163 ++itB;
164 ++j;
165 }
166
167 sp_mat result(locations, values, A.n_rows + B.n_rows, A.n_cols, true);
168
169 return result;
170}
171
172
173void Utils::meshgrid(const vec &x, const vec &y, mat &X, mat &Y) {
174 int m = x.n_elem;
175 int n = y.n_elem;
176
177 assert(m > 0);
178 assert(n > 0);
179
180 // Build X
181 vec t(n, fill::ones);
182
183 X.zeros(n, m);
184 Y.zeros(n, m);
185
186 for (int ii = 0; ii < m; ++ii) {
187 X.col(ii) = x(ii) * t;
188 t.ones();
189 }
190
191 for (int ii = 0; ii < m; ++ii)
192 Y.col(ii) = y;
193}
194
195
196void Utils::meshgrid(const vec &x, const vec &y, const vec &z, cube &X, cube &Y,
197 cube &Z) {
198 int m = x.n_elem;
199 int n = y.n_elem;
200 int o = z.n_elem;
201
202 assert(m > 0);
203 assert(n > 0);
204 assert(o > 0);
205
206 // Temporary Holder of sheet of cube
207 mat sheet(m, n, fill::zeros);
208
209 // Build X
210 vec t(n, fill::ones);
211
212 X.zeros(m, n, o);
213 Y.zeros(m, n, o);
214 Z.zeros(m, n, o);
215
216 // Sheet that repeats each slice
217 for (int ii = 0; ii < m; ++ii) {
218 sheet.row(ii) = x(ii) * t.t();
219 t.ones();
220 }
221
222 for (int kk = 0; kk < o; ++kk)
223 X.slice(kk) = sheet;
224
225 // Y Cube, repeats same sheet as well
226 for (int ii = 0; ii < m; ++ii)
227 sheet.row(ii) = y.t();
228
229 for (int kk = 0; kk < o; ++kk)
230 Y.slice(kk) = sheet;
231
232 // Z cube goes by slices each with same value
233 for (int kk = 0; kk < o; ++kk)
234 Z.slice(kk).fill(z(kk));
235}
static sp_mat spjoin_cols(const sp_mat &A, const sp_mat &B)
An in place operation for joining two matrices by columns.
Definition utils.cpp:138
static sp_mat spjoin_rows(const sp_mat &A, const sp_mat &B)
An in place operation for joining two matrices by rows.
Definition utils.cpp:103
static vec spsolve_eigen(const sp_mat &A, const vec &b)
A wrappper for implementing a sparse solve using Eigen from SuperLU.
static sp_mat spkron(const sp_mat &A, const sp_mat &B)
A wrappper for implementing a sparse Kroenecker product.
Definition utils.cpp:70
void meshgrid(const vec &x, const vec &y, mat &X, mat &Y)
An analog to the MATLAB 2D meshgrid operation.
Definition utils.cpp:173