BELFEM 0.9.3
Berkeley Lab Finite Element Framework
Loading...
Searching...
No Matches
fn_Smith.hpp
Go to the documentation of this file.
1/*
2 * BELFEM -- The Berkeley Lab Finite Element Framework
3 * Copyright (c) 2026, The Regents of the University of California,
4 * through Lawrence Berkeley National Laboratory (subject to receipt of any required
5 * approvals from the U.S. Dept. of Energy). All rights reserved.
6 *
7 * Developers: Christian Messe, Gregory Giard
8 *
9 * See the top-level LICENSE file for the complete license and disclaimer.
10 */
11
12#include "cl_Matrix.hpp"
13#include <tuple>
14#include <cstdlib>
15#include "fn_trans.hpp"
16
17#ifndef BELFEM_FN_SMITH_HPP
18#define BELFEM_FN_SMITH_HPP
19
20namespace belfem
21{
22//------------------------------------------------------------------------------
23
24 template<typename T>
25 void
26 rowExchange(Matrix< T > &aMat, const uint i, const uint j)
27 {
28 const uint n = aMat.n_cols();
29 int v;
30 for (uint k = 0; k < n; k++)
31 {
32 v = aMat(i-1,k);
33 aMat(i-1,k) = aMat(j-1,k);
34 aMat(j-1,k)=v;
35 }
36 }
37
38
39//------------------------------------------------------------------------------
40
41 template<typename T>
42 void
43 columnExchange(Matrix< T > &aMat, const uint i, const uint j)
44 {
45 const uint m = aMat.n_rows();
46 int v;
47 for (uint k = 0; k < m; k++)
48 {
49 v = aMat(k,i-1);
50 aMat(k,i-1) = aMat(k,j-1);
51 aMat(k,j-1)=v;
52 }
53 }
54
55//------------------------------------------------------------------------------
56
57 template<typename T>
58 void
60 {
61 const uint n = aMat.n_cols();
62 for (uint k = 0; k < n; k++)
63 {
64 aMat(i-1,k)*=-1 ;
65 }
66 }
67
68//------------------------------------------------------------------------------
69
70 template<typename T>
71 void
73 {
74 const uint m = aMat.n_rows();
75 for (uint k = 0; k < m; k++)
76 {
77 aMat(k,i-1)*=-1 ;
78 }
79 }
80
81//------------------------------------------------------------------------------
82
83 template<typename T>
84 void
85 rowAdd(Matrix< T > &aMat, const uint i, const uint j, const int q)
86 {
87 const uint n = aMat.n_cols();
88 for (uint k = 0; k < n; k++)
89 {
90 aMat(i-1,k) += q*aMat(j-1,k) ;
91 }
92 }
93
94//------------------------------------------------------------------------------
95
96 template<typename T>
97 void
98 columnAdd(Matrix< T > &aMat, const uint i, const uint j, const int q)
99 {
100 const uint m = aMat.n_rows();
101 for (uint k = 0; k < m; k++)
102 {
103 aMat(k,j-1) += q*aMat(k,i-1) ;
104 }
105 }
106
107//------------------------------------------------------------------------------
108
109 template<typename T>
110 void
112 {
113 rowExchange(aMat,i,j) ;
114 rowExchange(aQ_,i,j) ;
115 columnExchange(aQ,i,j) ;
116 }
117
118//------------------------------------------------------------------------------
119
120 template<typename T>
121 void
123 {
124 rowMultiply(aMat,i) ;
125 rowMultiply(aQ_,i) ;
126 columnMultiply(aQ,i) ;
127 }
128
129//------------------------------------------------------------------------------
130
131 template<typename T>
132 void
133 rowAddOperation(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint i, const uint j, const int q)
134 {
135 rowAdd(aMat,i,j,q) ;
136 rowAdd(aQ_,i,j,q) ;
137 columnAdd(aQ,i,j,-q) ;
138 }
139
140//------------------------------------------------------------------------------
141
142 template<typename T>
143 void
145 {
146 columnExchange(aMat,i,j) ;
147 rowExchange(aR_,i,j) ;
148 columnExchange(aR,i,j) ;
149 }
150
151//------------------------------------------------------------------------------
152
153 template<typename T>
154 void
156 {
157 columnMultiply(aMat,i) ;
158 rowMultiply(aR_,i) ;
159 columnMultiply(aR,i) ;
160 }
161
162//------------------------------------------------------------------------------
163
164 template<typename T>
165 void
166 columnAddOperation(Matrix< T > &aMat, Matrix< T > &aR, Matrix< T > &aR_, const uint i, const uint j, const int q)
167 {
168 columnAdd(aMat,i,j,q) ;
169 rowAdd(aR_,i,j,-q) ;
170 columnAdd(aR,i,j,q) ;
171 }
172
173//------------------------------------------------------------------------------
174
175 template<typename T>
176 void
177 partRowReduce(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint k, const uint l)
178 {
179 const uint m = aMat.n_rows();
180 for(uint i = k+1; i < m+1; ++i)
181 {
182 const int q = aMat(i-1,l-1)/aMat(k-1,l-1);
183 rowAddOperation(aMat,aQ,aQ_,i,k,-q);
184 }
185 }
186
187//------------------------------------------------------------------------------
188
189 template<typename T>
190 void
191 partColumnReduce(Matrix< T > &aMat, Matrix< T > &aR, Matrix< T > &aR_, const uint k, const uint l)
192 {
193 const uint n = aMat.n_cols();
194 for(uint i = l+1; i < n+1; ++i)
195 {
196 const int q = aMat(k-1,i-1)/aMat(k-1,l-1);
197 columnAddOperation(aMat,aR,aR_,l,i,-q);
198 }
199 }
200
201//------------------------------------------------------------------------------
202
203 template<typename T>
204 std::pair<uint, uint>
206 {
207 uint alpha = std::abs(v(k-1));
208 uint i0 = k;
209 while (alpha == 0 && k < v.length())
210 {
211 k+=1;
212 alpha = std::abs(v(k-1));
213 i0 = k;
214 }
215 for(uint i = k; i < v.length(); ++i)
216 {
217 if (std::abs(v(i)) < alpha && std::abs(v(i)) != 0)
218 {
219 alpha = std::abs(v(i));
220 i0 = i+1;
221 }
222 }
223 return std::pair(alpha,i0);
224 }
225
226//------------------------------------------------------------------------------
227
228 template<typename T>
229 void
230 rowPrepare(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint k, const uint l)
231 {
232 Vector< T > v = aMat.col(l-1);
233 std::pair<uint, uint> tPair = smallestNonzero(v, k);
234 rowExchangeOperation(aMat, aQ, aQ_, k, tPair.second);
235 }
236
237//------------------------------------------------------------------------------
238
239 template<typename T>
240 void
241 rowReduce(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint k, const uint l)
242 {
243 const uint m = aMat.n_rows();
244
245 // todo: Optimize this to put directly in the while (cont) statement...
246 bool cont = false;
247 for (uint i = k; i < m; ++i)
248 {
249 if (aMat(i,l-1) != 0)
250 {
251 cont = true;
252 break;
253 }
254 }
255 while (cont)
256 {
257 rowPrepare(aMat, aQ, aQ_,k,l);
258 partRowReduce(aMat, aQ, aQ_,k,l);
259
260 // todo: Optimize this to put directly in the while (cont) statement...
261 cont = false;
262 for (uint i = k; i < m; ++i)
263 {
264 if (aMat(i,l-1) != 0)
265 {
266 cont = true;
267 break;
268 }
269 }
270 }
271 }
272
273//------------------------------------------------------------------------------
274
275 template<typename T>
276 std::tuple< Matrix< T >, Matrix< T >, uint >
278 {
279 const uint m = aMat.n_rows();
280 const uint n = aMat.n_cols();
281 Matrix< T > tQ = Matrix< T >(m,m,0);
282 Matrix< T > tQ_ = Matrix< T >(m,m,0);
283 for(uint i = 0; i < m; ++i)
284 {
285 tQ(i,i) = 1;
286 tQ_(i,i) = 1;
287 }
288
289 uint k = 0;
290 uint l = 1;
291 bool cont;
292
293 while (k < m and n > 0)
294 {
295 // todo: Optimize this to put directly in the while (cont) statement...
296 cont = true;
297 for (uint i = k; i < m; ++i)
298 {
299 if (aMat(i,l-1) != 0)
300 {
301 cont = false;
302 break;
303 }
304 }
305 while ( cont )
306 {
307 l+=1;
308 if (l == n+1)
309 {
310 break;
311 }
312 // todo: Optimize this to put directly in the while (cont) statement...
313 cont = true;
314 for ( uint i = k; i < m; i++ )
315 {
316 if ( aMat( i, l-1 ) != 0 )
317 {
318 cont = false;
319 break;
320 }
321 }
322 }
323 if (l == n+1)
324 {
325 break;
326 }
327 k+=1;
328 rowReduce(aMat,tQ,tQ_,k,l);
329 }
330 return std::tuple< Matrix< T >, Matrix< T >, uint > (tQ, tQ_, k);
331 }
332
333//------------------------------------------------------------------------------
334
335 template<typename T>
336 std::tuple< Matrix< T >, Matrix< T > >
338 {
339 const uint n = aMat.n_cols();
340 Matrix< T > tMatT = trans(aMat);
341 auto [tP, tP_, k] = rowEchelon(tMatT);
342 tMatT = trans(tMatT);
343 Matrix< T > tPT = trans(tP_);
344
345 Matrix< T > tKer = Matrix< T >(tPT.n_rows(),n-k,0);
346
347 uint tCount;
348 tCount = 0;
349 for(uint i = k; i < n; ++i)
350 {
351 for(uint j = 0; j < tPT.n_rows(); ++j)
352 {
353 tKer(j,tCount) = tPT(j,i);
354 }
355 tCount++;
356 }
357
358 Matrix< T > tIm = Matrix< T >(tMatT.n_rows(),k,0);
359 for(uint i = 0; i < k; ++i)
360 {
361 for(uint j = 0; j < tMatT.n_rows(); ++j)
362 {
363 tIm(j,i) = tMatT(j,i);
364 }
365 }
366
367 return std::tuple< Matrix< T >, Matrix< T > > (tKer, tIm);
368
369 }
370
371//------------------------------------------------------------------------------
372
373 std::pair<uint, uint>
374 minNonzero(Matrix< int > &aMat, const uint k);
375
376//------------------------------------------------------------------------------
377
378 void
379 moveMinNonzero(Matrix< int > &aMat, Matrix< int > &aQ, Matrix< int > &aQ_, Matrix< int > &aR, Matrix< int > &aR_, const uint k);
380
381//------------------------------------------------------------------------------
382
383 std::tuple< bool, uint, uint, int >
384 checkForDivisibility(Matrix< int > &aMat, const uint k);
385
386//------------------------------------------------------------------------------
387
388 void
389 partSmithForm(Matrix< int > &aMat, Matrix< int > &aQ, Matrix< int > &aQ_, Matrix< int > &aR, Matrix< int > &aR_, const uint k);
390
391//------------------------------------------------------------------------------
392
393 std::tuple< Matrix< int >, Matrix< int >,Matrix< int >,Matrix< int >, uint, uint >
394 smithForm(Matrix< int > &aMat);
395
396//------------------------------------------------------------------------------
397
398 Matrix< int >
399 SolveInt(Matrix< int > aMat, Matrix< int > &aVec);
400
401//------------------------------------------------------------------------------
402}
403
404#endif //BELFEM_FN_SMITH_HPP
Dense column-major matrix.
Definition cl_BZ_Matrix.hpp:28
auto col(const size_t aColIndex) -> decltype(mMatrix.col(aColIndex))
Definition cl_AR_Matrix.hpp:325
size_t n_rows() const
Definition cl_AR_Matrix.hpp:183
Matrix()=default
size_t n_cols() const
Definition cl_AR_Matrix.hpp:191
Column vector.
Definition cl_BZ_Vector.hpp:41
Matrix transpose.
USER GUIDES:
Definition cl_Capacitor.cpp:16
void rowReduce(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint k, const uint l)
Definition fn_Smith.hpp:241
Matrix< int > SolveInt(Matrix< int > aMat, Matrix< int > &aVec)
Definition fn_Smith.cpp:224
void columnMultiplyOperation(Matrix< T > &aMat, Matrix< T > &aR, Matrix< T > &aR_, const uint i)
Definition fn_Smith.hpp:155
std::tuple< Matrix< T >, Matrix< T > > kernelImage(Matrix< T > &aMat)
Definition fn_Smith.hpp:337
std::tuple< bool, uint, uint, int > checkForDivisibility(Matrix< int > &aMat, const uint k)
Definition fn_Smith.cpp:61
void columnAdd(Matrix< T > &aMat, const uint i, const uint j, const int q)
Definition fn_Smith.hpp:98
void rowPrepare(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint k, const uint l)
Definition fn_Smith.hpp:230
void rowExchangeOperation(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint i, const uint j)
Definition fn_Smith.hpp:111
void rowAddOperation(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint i, const uint j, const int q)
Definition fn_Smith.hpp:133
std::pair< uint, uint > minNonzero(Matrix< int > &aMat, const uint k)
Definition fn_Smith.cpp:26
unsigned int uint
Definition typedefs.hpp:30
void rowExchange(Matrix< T > &aMat, const uint i, const uint j)
Definition fn_Smith.hpp:26
auto trans(Matrix< T > &aMatrix) -> decltype(trans(aMatrix.matrix_data()))
Definition fn_trans.hpp:74
void rowAdd(Matrix< T > &aMat, const uint i, const uint j, const int q)
Definition fn_Smith.hpp:85
std::tuple< Matrix< int >, Matrix< int >, Matrix< int >, Matrix< int >, uint, uint > smithForm(Matrix< int > &aMat)
Definition fn_Smith.cpp:143
void rowMultiply(Matrix< T > &aMat, const uint i)
Definition fn_Smith.hpp:59
void columnMultiply(Matrix< T > &aMat, const uint i)
Definition fn_Smith.hpp:72
std::tuple< Matrix< T >, Matrix< T >, uint > rowEchelon(Matrix< T > &aMat)
Definition fn_Smith.hpp:277
void partSmithForm(Matrix< int > &aMat, Matrix< int > &aQ, Matrix< int > &aQ_, Matrix< int > &aR, Matrix< int > &aR_, const uint k)
Definition fn_Smith.cpp:84
@ alpha
Definition cl_Material.hpp:161
@ q
Definition cl_Material.hpp:176
void columnExchange(Matrix< T > &aMat, const uint i, const uint j)
Definition fn_Smith.hpp:43
void rowMultiplyOperation(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint i)
Definition fn_Smith.hpp:122
void moveMinNonzero(Matrix< int > &aMat, Matrix< int > &aQ, Matrix< int > &aQ_, Matrix< int > &aR, Matrix< int > &aR_, const uint k)
Definition fn_Smith.cpp:50
void columnExchangeOperation(Matrix< T > &aMat, Matrix< T > &aR, Matrix< T > &aR_, const uint i, const uint j)
Definition fn_Smith.hpp:144
void columnAddOperation(Matrix< T > &aMat, Matrix< T > &aR, Matrix< T > &aR_, const uint i, const uint j, const int q)
Definition fn_Smith.hpp:166
void partColumnReduce(Matrix< T > &aMat, Matrix< T > &aR, Matrix< T > &aR_, const uint k, const uint l)
Definition fn_Smith.hpp:191
std::pair< uint, uint > smallestNonzero(Vector< T > &v, uint k)
Definition fn_Smith.hpp:205
void partRowReduce(Matrix< T > &aMat, Matrix< T > &aQ, Matrix< T > &aQ_, const uint k, const uint l)
Definition fn_Smith.hpp:177