Free Electron
SparseMatrix2x2.h
Go to the documentation of this file.
1 /* Copyright (C) 2003-2021 Free Electron Organization
2  Any use of this software requires a license. If a valid license
3  was not distributed with this file, visit freeelectron.org. */
4 
5 /** @file */
6 
7 #ifndef __SparseMatrix2x2_h__
8 #define __SparseMatrix2x2_h__
9 
10 namespace fe
11 {
12 namespace ext
13 {
14 
15 template <typename T>
16 class FE_DL_EXPORT SparseMatrix2x2 : public Component
17 {
18  public:
19 typedef T t_real;
20 typedef Vector<2, t_real> t_v2;
21 typedef Matrix<2,2,t_real> t_matrix;
22 
23 virtual ~SparseMatrix2x2(void) {}
24 virtual void multiply(std::vector<t_v2> &a_b,
25  const std::vector<t_v2> &a_x) const = 0;
26 virtual void scale(t_real a_scale) = 0;
27 };
28 
29 
30 template <typename T>
31 class FE_DL_EXPORT FullBCRS2 : public SparseMatrix2x2<T>
32 {
33  public:
34 typedef T t_real;
35 typedef Vector<2, t_real> t_v2;
36 typedef Matrix<2,2,t_real> t_matrix;
37  FullBCRS2(void);
38 virtual ~FullBCRS2(void);
39 
40 
41 virtual void multiply(std::vector<t_v2> &a_b,
42  const std::vector<t_v2> &a_x) const;
43 virtual void scale(t_real a_scale);
44 
45  void clear(void);
46  void startrow(void);
47 virtual void done(void);
48  t_matrix &insert(unsigned int a_columnIndex,
49  const t_matrix &a_block);
50 
51  void sparse(const sp<FullBCRS2> &a_other);
52  void project(const sp<FullBCRS2> &a_other);
53 
54  public:
55  std::vector<t_matrix> &blocks(void) { return m_blocks; }
56  std::vector<unsigned int> &colind(void) { return m_colind; }
57  std::vector<unsigned int> &rowptr(void) { return m_rowptr; }
58 
59  protected:
60  std::vector<t_matrix> m_blocks;
61  std::vector<unsigned int> m_colind;
62  std::vector<unsigned int> m_rowptr;
63  unsigned int m_r;
64  t_v2 m_zeroVector;
65 };
66 
67 template <typename T>
68 class FE_DL_EXPORT UpperTriangularBCRS2 : public FullBCRS2<T>
69 {
70  public:
71 typedef T t_real;
72 typedef Vector<2, t_real> t_v2;
73 typedef Matrix<2,2,t_real> t_matrix;
74  UpperTriangularBCRS2(void){}
75 virtual ~UpperTriangularBCRS2(void){}
76 
77 virtual void multiply(std::vector<t_v2> &a_b,
78  const std::vector<t_v2> &a_x) const;
79 
80  void incompleteSqrt(void);
81  void incompleteSqrtOpt(void);
82  void backSub(std::vector<t_v2> &a_x, const std::vector<t_v2> &a_b);
83  void transposeForeSub(std::vector<t_v2> &a_x, const std::vector<t_v2> &a_b);
84  void backSolve(std::vector<t_v2> &a_x, const std::vector<t_v2> &a_b);
85 virtual void done(void);
86 
87  private:
88  std::vector<unsigned int> m_ptr; // buffer for transposeForeSub
89  std::vector<t_v2> m_y; // buffer for backSolve
90 
91 };
92 
93 
94 
95 template <typename T>
96 inline FullBCRS2<T>::FullBCRS2(void)
97 {
98  m_r = 0;
99  m_zeroVector = t_v2(0.0,0.0);
100 }
101 
102 template <typename T>
103 inline FullBCRS2<T>::~FullBCRS2(void)
104 {
105 }
106 
107 template <typename T>
108 inline void FullBCRS2<T>::clear(void)
109 {
110  m_blocks.clear();
111  m_colind.clear();
112  m_rowptr.clear();
113  m_r = 0;
114 }
115 
116 template <typename T>
117 inline void FullBCRS2<T>::startrow(void)
118 {
119  m_rowptr.push_back(m_r);
120 }
121 
122 template <typename T>
123 inline void FullBCRS2<T>::done(void)
124 {
125  m_rowptr.push_back(m_r);
126 }
127 
128 template <typename T>
129 inline void UpperTriangularBCRS2<T>::done(void)
130 {
131  m_y.resize(FullBCRS2<T>::m_rowptr.size());
132  FullBCRS2<T>::m_rowptr.push_back(FullBCRS2<T>::m_r);
133  m_ptr.resize(FullBCRS2<T>::m_rowptr.size());
134 }
135 
136 template <typename T>
137 inline Matrix<2,2,T> &FullBCRS2<T>::insert(unsigned int a_columnIndex, const t_matrix &a_block)
138 {
139  m_blocks.push_back(a_block);
140  m_colind.push_back(a_columnIndex);
141  m_r++;
142  return m_blocks.back();
143 }
144 
145 template <typename T>
146 inline void FullBCRS2<T>::multiply(std::vector<t_v2> &a_b, const std::vector<t_v2> &a_x) const
147 {
148  unsigned int n = (unsigned int)(m_rowptr.size() - 1);
149  for(unsigned int i = 0; i < n; i++)
150  {
151  a_b[i] = m_zeroVector;
152  for(unsigned int k = m_rowptr[i]; k < m_rowptr[i+1]; k++)
153  {
154  a_b[i] += fe::multiply(m_blocks[k], a_x[m_colind[k]]);
155  }
156  }
157 }
158 
159 template <typename T>
160 inline void FullBCRS2<T>::scale(t_real a_scale)
161 {
162  unsigned int n = (unsigned int)m_blocks.size();
163  for(unsigned int i = 0; i < n; i++)
164  {
165  m_blocks[i] *= a_scale;
166  }
167 }
168 
169 template <typename T>
170 inline void UpperTriangularBCRS2<T>::multiply(std::vector<t_v2> &a_b, const std::vector<t_v2> &a_x) const
171 {
172  unsigned int n = (unsigned int)(FullBCRS2<T>::m_rowptr.size() - 1);
173  for(unsigned int i = 0; i < n; i++)
174  {
175  a_b[i] = FullBCRS2<T>::m_zeroVector;
176  }
177  for(unsigned int i = 0; i < n; i++)
178  {
179  unsigned int k = FullBCRS2<T>::m_rowptr[i];
180  a_b[i] += fe::multiply(FullBCRS2<T>::m_blocks[k], a_x[i]);
181  for(k=k+1; k < FullBCRS2<T>::m_rowptr[i+1]; k++)
182  {
183  a_b[i] += fe::multiply(FullBCRS2<T>::m_blocks[k], a_x[FullBCRS2<T>::m_colind[k]]);
184  a_b[FullBCRS2<T>::m_colind[k]] += fe::transposeMultiply(FullBCRS2<T>::m_blocks[k], a_x[i]);
185  }
186  }
187 }
188 
189 template <typename T>
190 inline void just_upper(Matrix<2,2,T> &a_m)
191 {
192  a_m(1,0) = 0.0;
193 }
194 
195 
196 template <typename T>
197 inline void FullBCRS2<T>::sparse(const sp<FullBCRS2> &a_other)
198 {
199  m_blocks.clear();
200  m_colind.clear();
201  m_rowptr.clear();
202  m_r = 0;
203  t_matrix zero;
204  setAll(zero, 0.0);
205  unsigned int n = a_other->m_rowptr.size()-1;
206  for(unsigned int i = 0; i < n; i++)
207  {
208  startrow();
209  int d = a_other->m_rowptr[i];
210  for(int k=d; k < a_other->m_rowptr[i+1]; k++)
211  {
212  int c = a_other->m_colind[k];
213  if(!(zero == a_other->m_blocks[k]))
214  {
215  insert(c, a_other->m_blocks[k]);
216  }
217  }
218  }
219  done();
220 }
221 
222 template <typename T>
223 inline void FullBCRS2<T>::project(const sp<FullBCRS2> &a_other)
224 {
225  unsigned int n = a_other->m_rowptr.size()-1;
226  for(unsigned int i = 0; i < n; i++)
227  {
228  int d = a_other->m_rowptr[i];
229  int d_self = m_rowptr[i];
230  for(int k=d; k < a_other->m_rowptr[i+1]; k++)
231  {
232  int c = a_other->m_colind[k];
233  for(int k_self=d_self; k_self < m_rowptr[i+1]; k_self++)
234  {
235  int c_self = m_colind[k_self];
236  if(c_self == c)
237  {
238  m_blocks[k_self] = a_other->m_blocks[k];
239  }
240  }
241  }
242  }
243 }
244 
245 template <typename T>
246 inline void UpperTriangularBCRS2<T>::backSub(std::vector<t_v2> &a_x, const std::vector<t_v2> &a_b)
247 {
248 #if 0
249 t_matrix zero;
250 setAll(zero, 0.0);
251 #endif
252  unsigned int n = (unsigned int)(FullBCRS2<T>::m_rowptr.size()-1);
253 //fe_fprintf(stderr, "root %d %d\n", n-1, m_colind[m_rowptr[n-1]]);
254  fe::backSub(FullBCRS2<T>::m_blocks[FullBCRS2<T>::m_rowptr[n-1]], a_x[n-1], a_b[n-1]);
255  t_v2 tmp;
256 
257  for(int i = n-2; i >= 0; i--)
258  {
259 //fe_fprintf(stderr, "bs i %d\n", i);
260  a_x[i] = a_b[i];
261  int d = FullBCRS2<T>::m_rowptr[i];
262  for(unsigned int k=d+1; k < FullBCRS2<T>::m_rowptr[i+1]; k++)
263  {
264  int c = FullBCRS2<T>::m_colind[k];
265  fe::multiply(tmp, FullBCRS2<T>::m_blocks[k], a_x[c]);
266  a_x[i] -= tmp;
267 #if 0
268 if(! (zero == m_blocks[k]))
269 {
270 fe_fprintf(stderr, "bs c %d -- %d <- T %d\n", c, i, k);
271 fprint(stderr, m_blocks[k]);
272 fe_fprintf(stderr, "\n");
273 }
274 #endif
275  //a_x[i] -= fe::transposeMultiply(m_blocks[k], a_x[c]);
276  }
277  fe::backSub(FullBCRS2<T>::m_blocks[d], a_x[i], a_x[i]);
278 //fprint(stderr, m_blocks[d]);
279 //fe_fprintf(stderr, "\n");
280  }
281 }
282 
283 // operates on upper tri as if it is a transpose of the upper and is lower
284 template <typename T>
285 inline void UpperTriangularBCRS2<T>::transposeForeSub(std::vector<t_v2> &a_x, const std::vector<t_v2> &a_b)
286 {
287 //t_matrix zero;
288 //setAll(zero, 0.0);
289  unsigned int n = (unsigned int)(FullBCRS2<T>::m_rowptr.size()-1);
290  //std::vector<unsigned int> ptr = FullBCRS2<T>::m_rowptr;
291  for(unsigned int i = 0 ; i < FullBCRS2<T>::m_rowptr.size(); i++)
292  {
293  m_ptr[i] = FullBCRS2<T>::m_rowptr[i];
294  }
295  fe::transposeForeSub(FullBCRS2<T>::m_blocks[FullBCRS2<T>::m_rowptr[0]], a_x[0], a_b[0]);
296  t_v2 tmp;
297 
298  for(unsigned int i = 1; i < n; i++)
299  {
300 //fe_fprintf(stderr, "fs i %d\n", i);
301  a_x[i] = a_b[i];
302  for(unsigned int m = 0; m < i; m++)
303  {
304  unsigned int c = FullBCRS2<T>::m_colind[m_ptr[m]];
305  while(c < i && m_ptr[m] < FullBCRS2<T>::m_rowptr[m+1]-1)
306  {
307  m_ptr[m]++;
308  c = FullBCRS2<T>::m_colind[m_ptr[m]];
309  }
310  if(c == i)
311  {
312 //if(! (zero == m_blocks[ptr[m]]))
313 //{
314 //fe_fprintf(stderr, "fs m %d -- i %d <- T ptr[m] %d m_rowptr[m+1] %d\n", m, i, ptr[m], m_rowptr[m+1]);
315 //fprint(stderr, m_blocks[ptr[m]]);
316 //fe_fprintf(stderr, "\n");
317 //}
318  //fe::multiply(tmp, m_blocks[ptr[m]], a_x[m]);
319  //a_x[i] -= tmp;
320  a_x[i] -= fe::transposeMultiply(FullBCRS2<T>::m_blocks[m_ptr[m]], a_x[m]);
321  }
322  }
323 //fe_fprintf(stderr, "fs m_rowptr[%d] %d col %d\n", i, m_rowptr[i], m_colind[m_rowptr[i]]);
324  fe::transposeForeSub(FullBCRS2<T>::m_blocks[FullBCRS2<T>::m_rowptr[i]], a_x[i], a_x[i]);
325 //fprint(stderr, m_blocks[m_rowptr[i]]);
326 //fe_fprintf(stderr, "\n");
327  }
328 }
329 
330 template <typename T>
331 inline void UpperTriangularBCRS2<T>::backSolve(std::vector<t_v2> &a_x, const std::vector<t_v2> &a_b)
332 {
333  //std::vector<t_v2> y(a_x.size());
334 
335  transposeForeSub(m_y, a_b);
336  backSub(a_x, m_y);
337 }
338 
339 
340 template <typename T>
341 inline void UpperTriangularBCRS2<T>::incompleteSqrt(void)
342 {
343  unsigned int d;
344  unsigned int n = (unsigned int)(FullBCRS2<T>::m_rowptr.size()-1);
345  t_matrix inv_z;
346  t_matrix z;
347  for(unsigned int k = 0; k < n-1; k++)
348  {
349  d = FullBCRS2<T>::m_rowptr[k];
350  just_upper(FullBCRS2<T>::m_blocks[d]);
351  //t_matrix tz = m_blocks[d] + transpose(m_blocks[d]);
352  //fprint(stderr, m_blocks[d]); fe_fprintf(stderr, "\n");
353  //nanCheck(m_blocks[d], "pre squareroot");
354  squareroot(FullBCRS2<T>::m_blocks[d], FullBCRS2<T>::m_blocks[d]);
355  //nanCheck(m_blocks[d], "post squareroot");
356  z = FullBCRS2<T>::m_blocks[d];
357  //fprint(stderr, m_blocks[d]); fe_fprintf(stderr, "\n");
358 
359  just_upper(z);
360 
361  //t_v2 sv(0.2,0.5,0.7);
362  //t_v2 x, y;
363 
364  invert(inv_z, z);
365 
366  for(unsigned int i=d+1; i < FullBCRS2<T>::m_rowptr[k+1]; i++)
367  {
368  //fe::multiply(m_blocks[i], inv_z, m_blocks[i]);
369  //fprint(stderr, m_blocks[i]); fe_fprintf(stderr, "\n");
370  //fprint(stderr, inv_z); fe_fprintf(stderr, "\n");
371 
372  //nanCheck(m_blocks[i], "pre multiply A");
373  //nanCheck(inv_z, "pre multiply inv_z");
374  fe::multiply(z, FullBCRS2<T>::m_blocks[i], inv_z);
375  setTranspose(z);
376 
377  //fe::multiply(m_blocks[i], inv_z, m_blocks[i]);
378  //setTranspose(m_blocks[i]);
379 
380  //fprint(stderr, m_blocks[i]); fe_fprintf(stderr, "\n");
381  //fprint(stderr, z); fe_fprintf(stderr, "\n");
382  FullBCRS2<T>::m_blocks[i] = z;
383  }
384 
385  for(unsigned int i=d+1; i < FullBCRS2<T>::m_rowptr[k+1]; i++)
386  {
387  z = transpose(FullBCRS2<T>::m_blocks[i]);
388  unsigned int h = FullBCRS2<T>::m_colind[i];
389  unsigned int g = i;
390 
391  t_matrix t;
392 
393  for(unsigned int j = FullBCRS2<T>::m_rowptr[h]; j < FullBCRS2<T>::m_rowptr[h+1]; j++)
394  {
395  for(; g < FullBCRS2<T>::m_rowptr[k+1] && FullBCRS2<T>::m_colind[g] <= FullBCRS2<T>::m_colind[j]; g++)
396  {
397  if (FullBCRS2<T>::m_colind[g] == FullBCRS2<T>::m_colind[j])
398  {
399 #if 0
400  fe::multiply(t, z, FullBCRS2<T>::m_blocks[g]);
401  setTranspose(t);
402  subtract(FullBCRS2<T>::m_blocks[j], FullBCRS2<T>::m_blocks[j], t);
403 #endif
404 
405 #if 1
406  const t_matrix &A = z;
407  const t_matrix &B = FullBCRS2<T>::m_blocks[g];
408  for(unsigned int ii = 0;ii < 2; ii++)
409  {
410  for(unsigned int jj = 0;jj < 2; jj++)
411  {
412  t_real sum=0.0;
413  sum += A(ii,0)*B(0,jj);
414  sum += A(ii,1)*B(1,jj);
415  t(ii,jj)=sum;
416  }
417  }
418 
419  t_matrix &R = FullBCRS2<T>::m_blocks[j];
420  R(0,0) = R(0,0)-t(0,0);
421  R(0,1) = R(0,1)-t(1,0);
422  R(1,0) = R(1,0)-t(0,1);
423  R(1,1) = R(1,1)-t(1,1);
424 #endif
425  }
426  }
427  }
428  }
429  }
430  d = FullBCRS2<T>::m_rowptr[n-1];
431  t_matrix tmp;
432  just_upper(FullBCRS2<T>::m_blocks[d]);
433  squareroot(tmp, FullBCRS2<T>::m_blocks[d]);
434  FullBCRS2<T>::m_blocks[d] = tmp;
435 }
436 
437 
438 
439 } /* namespace */
440 } /* namespace */
441 
442 #endif /* __SparseMatrix2x2_h__ */
443 
kernel
Definition: namespace.dox:3
Matrix< 4, 4, T > & invert(Matrix< 4, 4, T > &a_inverted, const Matrix< 4, 4, T > &a_matrix)
4x4 full matrix inversion
Definition: Matrix.h:1033
void project(Vector< 4, T > &a_r, const Matrix< 4, 4, T > &a_m, const Vector< 4, T > &a_v)
project vector through matrix. divides by transformed w
Definition: Matrix.h:1182
void squareroot(Matrix< M, N, T > &a_U, const Matrix< M, N, T > &a_A)
Square root of a matrix.
Definition: Matrix.h:567