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