11 #include <boost/numeric/ublas/vector.hpp> 12 #include <boost/numeric/ublas/vector_proxy.hpp> 13 #include <boost/numeric/ublas/matrix.hpp> 14 #include <boost/numeric/ublas/triangular.hpp> 15 #include <boost/numeric/ublas/lu.hpp> 16 #include <boost/numeric/ublas/io.hpp> 18 namespace ublas = boost::numeric::ublas;
27 class FE_DL_EXPORT Preconditioner
31 typedef Vector<3, t_real> t_v3;
32 typedef Matrix<3,3,t_real> t_matrix;
33 virtual ~Preconditioner(
void){}
34 virtual void apply( std::vector<t_v3> &a_r,
35 const std::vector<t_v3> &a_x)
const = 0;
39 class FE_DL_EXPORT BlockDiagonalPreconditioner :
public Preconditioner<T>
43 typedef Vector<3, t_real> t_v3;
44 typedef Matrix<3,3,t_real> t_matrix;
45 BlockDiagonalPreconditioner(
void);
46 virtual ~BlockDiagonalPreconditioner(
void);
48 virtual void apply( std::vector<t_v3> &a_r,
49 const std::vector<t_v3> &a_x)
const;
51 std::vector<t_matrix> &diagonal(
void);
54 std::vector<t_matrix> m_diagonal;
58 class FE_DL_EXPORT OverlappedInversionPreconditioner :
public Preconditioner
61 OverlappedInversionPreconditioner(
void){}
62 virtual ~OverlappedInversionPreconditioner(
void){}
64 virtual void apply( std::vector<t_v3> &a_r,
65 const std::vector<t_v3> &a_x)
const;
70 ublas::matrix<t_real> m_inverse;
77 std::vector<Block> &block(
void) {
return m_block; }
80 std::vector<Block> m_block;
85 class FE_DL_EXPORT FilterConstraint
89 typedef Vector<3, t_real> t_v3;
90 typedef Matrix<3,3,t_real> t_matrix;
91 FilterConstraint(
void);
92 virtual ~FilterConstraint(
void);
94 const t_matrix &filter(
void)
const;
95 void setIndex(
unsigned long a_index);
96 unsigned long index(
void)
const;
98 void makePointConstraint(
void);
99 void makeLineConstraint(
const t_v3 &a_direction);
100 void makePlaneConstraint(
const t_v3 &a_normal);
101 void makeInequalityConstraint(
const t_v3 &a_axis, t_real a_delta);
103 const t_v3 &axis(
void)
const {
return m_axis;}
104 t_real delta(
void)
const;
105 bool isInequality(
void)
const;
110 unsigned long m_index;
116 template <
typename T>
117 class FE_DL_EXPORT BlockPCG
121 typedef Vector<3, t_real> t_v3;
122 typedef Matrix<3,3,t_real> t_matrix;
124 virtual ~BlockPCG(
void);
126 bool solve( std::vector<t_v3> &a_x,
127 const sp< SparseMatrix3x3<t_real> > a_A,
128 const std::vector<t_v3> &a_b,
129 const Preconditioner<T> &a_P,
130 std::vector< FilterConstraint<T> > &a_filters);
132 const std::vector<t_v3> &residual(
void)
const;
134 unsigned int iterations(
void)
const {
return m_iter; }
137 t_real inner(
const std::vector<t_v3> &a_left,
138 const std::vector<t_v3> &a_right);
140 void residual( std::vector<t_v3> &a_r,
141 const sp< SparseMatrix3x3<t_real> > a_A,
142 const std::vector<t_v3> &a_x,
143 const std::vector<t_v3> &a_b);
145 void setSize(
unsigned long a_size);
147 void applyFilters(std::vector<t_v3> &a_r,
148 std::vector< FilterConstraint<T> > &a_filters);
152 unsigned int m_maxIterations;
154 std::vector<t_v3> m_r;
155 std::vector<t_v3> m_q;
156 std::vector<t_v3> m_d;
157 std::vector<t_v3> m_s;
158 std::vector<t_v3> m_tmp0;
159 std::vector<t_v3> m_tmp1;
161 std::vector<t_v3> *m_x;
165 template <
typename T>
167 BlockPCG<T>::BlockPCG(
void)
171 m_maxIterations = 100000;
177 template <
typename T>
179 BlockPCG<T>::~BlockPCG(
void)
183 template <
typename T>
185 T BlockPCG<T>::inner(
const std::vector<t_v3> &a_left,
const std::vector<t_v3> &a_right)
188 unsigned int n = a_left.size();
189 for(
unsigned int i = 0; i < n; i++)
191 s += dot(a_left[i], a_right[i]);
196 template <
typename T>
198 void BlockPCG<T>::residual(std::vector<t_v3> &a_r, sp< SparseMatrix3x3<t_real> > a_A,
const std::vector<t_v3> &a_x,
const std::vector<t_v3> &a_b)
200 unsigned int n = a_b.size();
202 a_A->multiply(a_r, a_x);
204 for(
unsigned int i = 0; i < n; i++)
206 a_r[i] = a_b[i] - a_r[i];
210 template <
typename T>
212 void BlockPCG<T>::setSize(
unsigned long a_size)
226 template <
typename T>
228 void BlockPCG<T>::applyFilters(std::vector<t_v3> &a_r, std::vector< FilterConstraint<T> > &a_filters)
230 for(
unsigned int i = 0; i < a_filters.size(); i++)
232 unsigned long index = a_filters[i].index();
235 if(a_filters[i].isInequality())
237 t_v3 &v = (*m_x)[index];
238 t_real d = dot(a_filters[i].axis(), v);
240 d = (*m_x)[index][2];
243 if(d < a_filters[i].delta())
248 (*m_x)[index][2] = a_filters[i].delta();
249 a_r[index] = fe::multiply(a_filters[i].filter(), a_r[index]);
250 a_filters[i].m_inequality =
false;
256 a_r[index] = fe::multiply(a_filters[i].filter(), a_r[index]);
262 template <
typename T>
264 const std::vector< Vector<3,T> > &BlockPCG<T>::residual(
void)
const 270 template <
typename T>
272 bool BlockPCG<T>::solve(std::vector<t_v3> &a_x,
const sp< SparseMatrix3x3<t_real> > a_A,
const std::vector<t_v3> &a_b,
const Preconditioner<T> &a_P, std::vector< FilterConstraint<T> > &a_filters)
274 bool converged =
false;
278 t_real delta0, deltaNew, deltaOld, deltaStop;
280 #ifdef FE_BLOCKPCG_RESTART 281 unsigned int modn = 50;
287 applyFilters(m_tmp0, a_filters);
288 a_P.apply(m_tmp1, m_tmp0);
289 delta0 = inner(m_tmp0, m_tmp1);
291 residual(m_r, a_A, a_x, a_b);
292 applyFilters(m_r, a_filters);
295 applyFilters(m_d, a_filters);
297 deltaNew = inner(m_r,m_d);
298 deltaStop = m_tol * m_tol * delta0;
302 while((m_iter < m_maxIterations) && (deltaNew > deltaStop))
304 a_A->multiply(m_q, m_d);
305 applyFilters(m_q, a_filters);
307 t_real alpha = deltaNew / inner(m_d, m_q);
309 for(
unsigned int i = 0; i < m_n; i++)
311 a_x[i] += alpha * m_d[i];
318 residual(m_r, a_A, a_x, a_b);
319 applyFilters(m_r, a_filters);
323 for(
unsigned int i = 0; i < m_n; i++)
325 m_r[i] -= alpha * m_q[i];
329 for(
unsigned int i = 0; i < m_n; i++)
331 m_r[i] -= alpha * m_q[i];
338 fe_fprintf(stderr,
"CONV HARD RESTART %d\n", m_iter);
341 applyFilters(m_tmp0, a_filters);
342 a_P.apply(m_tmp1, m_tmp0);
343 delta0 = inner(m_tmp0, m_tmp1);
345 residual(m_r, a_A, a_x, a_b);
346 applyFilters(m_r, a_filters);
349 applyFilters(m_d, a_filters);
351 deltaNew = inner(m_r,m_d);
352 deltaStop = m_tol * m_tol * delta0;
354 a_A->multiply(m_q, m_d);
355 applyFilters(m_q, a_filters);
357 t_real alpha = deltaNew / inner(m_d, m_q);
359 for(
unsigned int i = 0; i < m_n; i++)
361 a_x[i] += alpha * m_d[i];
366 for(
unsigned int i = 0; i < m_n; i++)
368 m_r[i] -= alpha * m_q[i];
374 #ifdef FE_BLOCKPCG_RESTART 377 residual(m_r, a_A, a_x, a_b);
378 applyFilters(m_r, a_filters);
383 for(
unsigned int i = 0; i < m_n; i++)
385 m_r[i] -= alpha * m_q[i];
387 #ifdef FE_BLOCKPCG_RESTART 396 deltaNew = inner(m_r, m_s);
398 t_real beta = deltaNew/deltaOld;
400 for(
unsigned int i = 0; i < m_n; i++)
402 m_d[i] = m_s[i] + beta*m_d[i];
405 applyFilters(m_d, a_filters);
410 if(m_iter < m_maxIterations)
414 residual(m_r, a_A, a_x, a_b);
421 template <
typename T>
423 BlockDiagonalPreconditioner<T>::BlockDiagonalPreconditioner(
void)
427 template <
typename T>
429 BlockDiagonalPreconditioner<T>::~BlockDiagonalPreconditioner(
void)
433 template <
typename T>
435 std::vector< Matrix<3,3,T> > &BlockDiagonalPreconditioner<T>::diagonal(
void)
440 template <
typename T>
442 void BlockDiagonalPreconditioner<T>::apply(std::vector<t_v3> &a_r,
const std::vector<t_v3> &a_x)
const 444 unsigned int n = a_r.size();
445 for(
unsigned int i = 0; i < n; i++)
447 multiply(a_r[i], m_diagonal[i], a_x[i]);
454 void OverlappedInversionPreconditioner::apply(std::vector<t_v3> &a_r,
const std::vector<t_v3> &a_x)
const 456 fe_fprintf(stderr,
".");
457 for(
unsigned int i = 0; i < a_r.size(); i++)
461 unsigned int n = m_block.size();
462 for(
unsigned int i = 0; i < n; i++)
464 ublas::vector<t_real> v, vr;
465 unsigned int nn = 3*(m_block[i].m_H - m_block[i].m_L);
467 for(
unsigned int j = m_block[i].m_L; j < m_block[i].m_H; j++)
470 v[(j-m_block[i].m_L)*3+0] = a_x[j][0];
471 v[(j-m_block[i].m_L)*3+1] = a_x[j][1];
472 v[(j-m_block[i].m_L)*3+2] = a_x[j][2];
475 fe_fprintf(stderr,
">>>>>>> ");
476 for(
unsigned int k = 0; k < v.size(); k++)
478 fe_fprintf(stderr,
"%f ", v[k]);
480 fe_fprintf(stderr,
"\n");
481 std::cerr << m_block[i].m_inverse <<
"\n";
483 v = prod(m_block[i].m_inverse, v);
485 fe_fprintf(stderr,
"<<<<<<< ");
486 for(
unsigned int k = 0; k < v.size(); k++)
488 fe_fprintf(stderr,
"%f ", v[k]);
490 fe_fprintf(stderr,
"\n");
494 for(
unsigned int j = m_block[i].m_L; j < m_block[i].m_H; j++)
496 if(j < m_block[i].m_m0)
continue;
497 if(j >= m_block[i].m_m1)
continue;
499 a_r[j][0] = v[(j-m_block[i].m_L)*3+0];
500 a_r[j][1] = v[(j-m_block[i].m_L)*3+1];
501 a_r[j][2] = v[(j-m_block[i].m_L)*3+2];
507 template <
typename T>
509 FilterConstraint<T>::FilterConstraint(
void)
511 m_inequality =
false;
514 template <
typename T>
516 FilterConstraint<T>::~FilterConstraint(
void)
520 template <
typename T>
522 void FilterConstraint<T>::setIndex(
unsigned long a_index)
527 template <
typename T>
529 const Matrix<3,3,T> &FilterConstraint<T>::filter(
void)
const 534 template <
typename T>
536 unsigned long FilterConstraint<T>::index(
void)
const 541 template <
typename T>
543 void FilterConstraint<T>::makePointConstraint(
void)
545 setAll(m_filter, 0.0);
546 m_inequality =
false;
549 template <
typename T>
551 void FilterConstraint<T>::makeLineConstraint(
const t_v3 &a_direction)
553 setAll(m_filter, 0.0);
554 outerProduct(m_filter, a_direction, a_direction);
555 m_inequality =
false;
558 template <
typename T>
560 void FilterConstraint<T>::makePlaneConstraint(
const t_v3 &a_normal)
563 setAll(m_filter, 0.0);
564 m_filter(0,0) = 1.0 - a_normal[0] * a_normal[0];
565 m_filter(0,1) = - a_normal[0] * a_normal[1];
566 m_filter(0,2) = - a_normal[0] * a_normal[2];
567 m_filter(1,0) = m_filter(0,1);
568 m_filter(1,1) = 1.0 - a_normal[1] * a_normal[1];
569 m_filter(1,2) = - a_normal[1] * a_normal[2];
570 m_filter(2,0) = m_filter(0,2);
571 m_filter(2,1) = m_filter(1,2);
572 m_filter(2,2) = 1.0 - a_normal[2] * a_normal[2];
574 m_inequality =
false;
577 template <
typename T>
579 void FilterConstraint<T>::makeInequalityConstraint(
const t_v3 &a_axis, t_real a_delta)
583 makePlaneConstraint(m_axis);
589 template <
typename T>
591 bool FilterConstraint<T>::isInequality(
void)
const 596 template <
typename T>
598 T FilterConstraint<T>::delta(
void)
const kernel
Definition: namespace.dox:3