Mechanics of Defect Evolution Library
Loading...
Searching...
No Matches
SmithDecomposition.h
Go to the documentation of this file.
1/* This file is part of MoDELib, the Mechanics Of Defects Evolution Library.
2 *
3 *
4 * MODEL is distributed without any warranty under the
5 * GNU General Public License (GPL) v2 <http://www.gnu.org/licenses/>.
6 */
7
8#ifndef model_SmithDecomposition_h_
9#define model_SmithDecomposition_h_
10
11#include <utility> // std::pair, std::make_pair
12#include <assert.h>
13#include <Eigen/Core>
14
15namespace model
16{
29 template <int N>
31 {
32 typedef long long int IntValueType;
33 typedef Eigen::Matrix<IntValueType,N,N> MatrixNi;
34
35 /**********************************************************************/
36 static IntValueType gcd(const IntValueType& a,const IntValueType& b)
37 {
38 return b>0? gcd(b, a % b) : a;
39 }
40
41 /**********************************************************************/
42 template <typename Derived>
43 static IntValueType gcd(const Eigen::MatrixBase<Derived>& v)
44 {
45 IntValueType g=v(0);
46 for(int n=1;n<v.size();++n)
47 {
48 g=gcd(g,v(n));
49 }
50 return g;
51 }
52
53 /**********************************************************************/
54 static std::pair<int,int> findNonZero(const MatrixNi& A)
55 {
56 for(int i=0;i<N;++i)
57 {
58 for(int j=0;j<N;++j)
59 {
60 if(A(i,j)!=0)
61 {
62 return std::make_pair(i,j);
63 }
64 }
65 }
66 return std::make_pair(-1,-1);
67 }
68
69 /**********************************************************************/
70 static std::pair<int,int> findNonDivisible(const MatrixNi& A)
71 {
72 for(int i=1;i<N;++i)
73 {
74 for(int j=1;j<N;++j)
75 {
76 if(A(i,j)%A(0,0)) // D(i,j) is no divisible by D(0,0)
77 {
78 return std::make_pair(i,j);
79 }
80 }
81 }
82 return std::make_pair(-1,-1);
83 }
84
85 /**********************************************************************/
86 void row_signChange(const int& ID)
87 {/* unimodular matrix changing the sign of row/col ID
88 */
89 MatrixNi T(MatrixNi::Identity());
90 T(ID,ID)=-1;
91 U=T*U;
92 X=X*T;
93 D=T*D;
94 }
95
96 /**********************************************************************/
97 void col_signChange(const int& ID)
98 {/* unimodular matrix changing the sign of row/col ID
99 */
100 MatrixNi T(MatrixNi::Identity());
101 T(ID,ID)=-1;
102 V=V*T;
103 Y=T*Y;
104 D=D*T;
105 }
106
107 /**********************************************************************/
108 void row_swap(const int& i, const int& j)
109 {/* unimodular matrix swapping rows/cols i and j
110 */
111 MatrixNi T(MatrixNi::Identity());
112 T(i,i)=0;
113 T(j,j)=0;
114 T(i,j)=1;
115 T(j,i)=1;
116 U=T*U;
117 X=X*T;
118 D=T*D;
119 }
120
121 /**********************************************************************/
122 void col_swap(const int& i, const int& j)
123 {/* unimodular matrix swapping rows/cols i and j
124 */
125 MatrixNi T(MatrixNi::Identity());
126 T(i,i)=0;
127 T(j,j)=0;
128 T(i,j)=1;
129 T(j,i)=1;
130 V=V*T;
131 Y=T*Y;
132 D=D*T;
133 }
134
135 /**********************************************************************/
136 void row_add_multiply(const int& i, const int& j,const IntValueType& n)
137 {/* unimodular matrix adding n times row (col) j to row (col) i
138 */
139 // note that add applied to colums needs transpose!
140 MatrixNi T(MatrixNi::Identity());
141 T(i,j)=n;
142 U=T*U;
143 D=T*D;
144 T(i,j)=-n;
145 X=X*T;
146 }
147
148 /**********************************************************************/
149 void col_add_multiply(const int& i, const int& j,const IntValueType& n)
150 {/* unimodular matrix adding n times row (col) j to row (col) i
151 */
152 // note that add applied to colums needs transpose!
153 MatrixNi T(MatrixNi::Identity());
154 T(j,i)=n;
155 V=V*T;
156 D=D*T;
157 T(j,i)=-n;
158 Y=T*Y;
159 }
160
161 /**********************************************************************/
162 bool reduceFirstRow()
163 {
164 // Operate on first row so that D(0,j) is divisible by D(0,0)
165 bool didOperate=false;
166 int j=1;
167 while (j<N)
168 {
169 const IntValueType r=D(0,j)%D(0,0);
170 const IntValueType q=D(0,j)/D(0,0);
171 if(r)
172 {
173 col_add_multiply(j,0,-q);
174 col_swap(0,j);
175 j=1;
176 didOperate=true;
177 }
178 else
179 {
180 j++;
181 }
182 }
183 return didOperate;
184 }
185
186 /**********************************************************************/
187 bool reduceFirstCol()
188 {
189 // Operate on first row so that D(0,j) is divisible by D(0,0)
190 bool didOperate=false;
191 int j=1;
192 while (j<N)
193 {
194 const IntValueType r=D(j,0)%D(0,0);
195 const IntValueType q=D(j,0)/D(0,0);
196 if(r)
197 {
198 row_add_multiply(j,0,-q);
199 row_swap(0,j);
200 j=1;
201 didOperate=true;
202 }
203 else
204 {
205 j++;
206 }
207 }
208 return didOperate;
209 }
210
211 MatrixNi D;
212 MatrixNi U;
213 MatrixNi V;
214 MatrixNi X;
215 MatrixNi Y;
216
217
218 public:
219
220 // /**********************************************************************/
221 // SmithDecomposition(const Eigen::Matrix<int,N,N>& A) :
222 // /* delegate constructor */ SmithDecomposition(A.template cast<IntValueType>())
223 // {
224 // }
225
226 /**********************************************************************/
227 SmithDecomposition(const MatrixNi& A) :
228 /* init */ D(A),
229 /* init */ U(MatrixNi::Identity()),
230 /* init */ V(MatrixNi::Identity()),
231 /* init */ X(MatrixNi::Identity()),
232 /* init */ Y(MatrixNi::Identity())
233 {
237
238 std::pair<int,int> rc=std::make_pair(0,0);
239 while (rc.first>=0)
240 {
241 std::pair<int,int> ij=findNonZero(D);
242 if(ij.first>=0)
243 {
244 // Swap row(i) and col (j) to amke D(0,0) non-zero.
245 row_swap(0,ij.first);
246 col_swap(0,ij.second);
247
248 // Operate on first row and col so that all entried are divisible by D(0,0)
249 bool didOperate=true;
250 while (didOperate)
251 {
252 didOperate=reduceFirstRow()+reduceFirstCol();
253 }
254
255 // If D(0,0) is negative make it positive
256 if(D(0,0)<0)
257 {
258 row_signChange(0);
259 }
260
261 // Subtract suitable multiples of the first row from the other
262 // rows to replace each entry in the first column, except a(0,0), by zero
263 for (int i=1;i<N;++i)
264 {
265 const IntValueType q=D(i,0)/D(0,0);
266 row_add_multiply(i,0,-q);
267 }
268
269 // Subtract suitable multiples of the first column from the other
270 // columns to replace each entry in the first row, except a(0,0), by zero
271 for (int j=1;j<N;++j)
272 {
273 const IntValueType q=D(0,j)/D(0,0);
274 col_add_multiply(j,0,-q);
275 }
276
277 // Now D is in the form [D(0,0) 0s;0s D'] where D' is a (N-1)x(N-1) matrix
278 rc=findNonDivisible(D);
279 if(rc.first>0)
280 {
281 row_add_multiply(0,rc.first,1);
282 }
283
284
285
286
287 }
288 else
289 {
290 rc=std::make_pair(-1,-1); // end main while loop immediately
291 }
292
293
294 }
295
296 // Recursive iteration
297 const SmithDecomposition<N-1> sd(D.template block<N-1,N-1>(1,1));
298 D.template block<N-1,N-1>(1,1)=sd.matrixD();
299 U.template block<N-1,N>(1,0)=sd.matrixU()*U.template block<N-1,N>(1,0);
300 V.template block<1,N-1>(0,1)=V.template block<1,N-1>(0,1)*sd.matrixV();
301 V.template block<N-1,N-1>(1,1)=V.template block<N-1,N-1>(1,1)*sd.matrixV();
302
303 Y.template block<N-1,N>(1,0)=sd.matrixY()*Y.template block<N-1,N>(1,0);
304 X.template block<1,N-1>(0,1)=X.template block<1,N-1>(0,1)*sd.matrixX();
305 X.template block<N-1,N-1>(1,1)=X.template block<N-1,N-1>(1,1)*sd.matrixX();
306
307
308 // Find a non-zero value of A and make it D(0,0)
309
310
311 assert((U*A*V-D).squaredNorm()==0);
312 assert((X*D*Y-A).squaredNorm()==0);
313
314 }
315
316 /**********************************************************************/
317 const MatrixNi& matrixU() const
318 {
319 return U;
320 }
321
322 /**********************************************************************/
323 const MatrixNi& matrixD() const
324 {
325 return D;
326 }
327
328 /**********************************************************************/
329 const MatrixNi& matrixV() const
330 {
331 return V;
332 }
333
334 /**********************************************************************/
335 const MatrixNi& matrixX() const
336 {
337 return X;
338 }
339
340 /**********************************************************************/
341 const MatrixNi& matrixY() const
342 {
343 return Y;
344 }
345 };
346
347 /**************************************************************************/
348 /**************************************************************************/
349 template <>
351 {
352 typedef long long int IntValueType;
353 typedef Eigen::Matrix<IntValueType,1,1> MatrixNi;
354
355 const MatrixNi D;
356 const MatrixNi U;
357 const MatrixNi V;
358 const MatrixNi X;
359 const MatrixNi Y;
360
361 public:
362
363 /**********************************************************************/
364 SmithDecomposition(const MatrixNi& A) :
365 /* init */ D(A),
366 /* init */ U(MatrixNi::Identity()),
367 /* init */ V(MatrixNi::Identity()),
368 /* init */ X(MatrixNi::Identity()),
369 /* init */ Y(MatrixNi::Identity())
370
371 {
372 }
373 /**********************************************************************/
374 const MatrixNi& matrixU() const
375 {
376 return U;
377 }
378
379 /**********************************************************************/
380 const MatrixNi& matrixD() const
381 {
382 return D;
383 }
384
385 /**********************************************************************/
386 const MatrixNi& matrixV() const
387 {
388 return V;
389 }
390
391 /**********************************************************************/
392 const MatrixNi& matrixX() const
393 {
394 return X;
395 }
396
397 /**********************************************************************/
398 const MatrixNi& matrixY() const
399 {
400 return Y;
401 }
402 };
403
404}
405#endif
const MatrixNi & matrixX() const
const MatrixNi & matrixV() const
const MatrixNi & matrixY() const
const MatrixNi & matrixU() const
const MatrixNi & matrixD() const
const MatrixNi & matrixU() const
const MatrixNi & matrixV() const
SmithDecomposition(const MatrixNi &A)
const MatrixNi & matrixY() const
const MatrixNi & matrixD() const
const MatrixNi & matrixX() const
function infiniteDisplacement syms Ax Ay Az Bx By Bz qx qy qz u L x y z real A
the magnitude of the R vector q
a
Definition int_R.m:14
b
Definition int_R.m:16
REAL D[16]
int j
int i
REAL v[4]