13#ifndef SCHUR_SOLVER_HH
14#define SCHUR_SOLVER_HH
25#include <boost/timer/timer.hpp>
28#include "dune/common/fmatrix.hh"
29#include "dune/istl/matrix.hh"
46void printVec(std::vector<double>
const&v,
int vend=1000000);
49template<
class Factorization=UMFFactorization<
double> >
59 lin.getMatrixBlocks(matL,start3,end3,start2,end2);
61 lin.getMatrixBlocks(
matA,start2,end2,start2,end2);
62 boost::timer::cpu_timer timer;
73 void solve(std::vector<double>
const& rhs, std::vector<double>& sol,
int nr=1);
78void printVec(std::vector<double>
const&v,
int vend)
81 if(vend < v.size()) endv=vend;
82 for(
int i=0; i< endv; ++i)
84 if(i%5 == 0) std::cout <<
". " << v[i] << std::endl;
85 else std::cout <<
" " << v[i] << std::endl;
90template<
class Factorization>
93 int r=rhs.size()/2/nr;
94 std::vector<double> rhs1(r*nr);
95 std::vector<double> rhs2(r*nr);
96 std::vector<double> sol1(r*nr);
97 std::vector<double> sol2(r*nr);
98 for(
int i=0; i<nr; ++i)
99 for(
int j=0; j<r; ++j)
101 rhs1[i*r+j]=rhs[i*2*r+j];
102 rhs2[i*r+j]=-rhs[i*2*r+r+j];
104 factoredL->solve(rhs2,sol2,
false);
106 matA.axpy(rhs1,sol2,1.0,nr);
107 factoredL->solve(rhs1,sol1,
true);
110 for(
int i=0; i<nr; ++i)
111 for(
int j=0; j<r; ++j)
113 sol[i*2*r+j]=-sol2[i*r+j];
114 sol[i*2*r+r+j]=sol1[i*r+j];
141template<
class Factorization,
class VariableSet>
143 typename VariableSet::Descriptions::template CoefficientVectorRepresentation<>::type>
146 typedef typename VariableSet::Descriptions::template CoefficientVectorRepresentation<>::type
Domain;
158 report(false), paras(doregularize)
165 std::vector<double> r(rows1),s(rows2),t(rows3), sol1(rows1+rows2+rows3);
167 d.write(sol1.begin());
169 for(
int i=0; i<rows1; ++i) r[i]=sol1[i];
170 for(
int i=0; i<rows2; ++i) s[i]=sol1[i+rows1];
171 for(
int i=0; i<rows3; ++i) t[i]=sol1[i+rows1+rows2];
173 resolveN(sol1,r,s,t);
175 v.read(sol1.begin());
198 buildNewSchurComplement(lins);
200 std::vector<double> r,s,t, sol1, sol2;
206 std::vector<double> r0(r.size(),0.0),s0(s.size(),0.0),t0(t.size(),0.0);
207 resolveN(sol1,r0,s0,t);
208 resolveN(sol2,r,s,t0);
213 adjointCorrection *= -1.0;
220 std::vector<double> t, sol1;
222 std::vector<double> r0(rows1,0.0),s0(rows2,0.0);
223 resolveN(sol1,r0,s0,t);
230 void resolveN(std::vector<double>& sol, std::vector<double>
const &rhs0,std::vector<double>
const &rhs1, std::vector<double>
const &rhs2)
const;
232 void fwd(std::vector<double>& sol, std::vector<double>
const &r,std::vector<double>
const &s,std::vector<double>
const &t)
const;
233 void bwd(std::vector<double>& sol, std::vector<double>
const &x2,std::vector<double>
const &s,std::vector<double>
const &t)
const;
238 std::unique_ptr<BlockLUFactorization<Factorization> > factorization;
241 std::vector<double> B,AinvB;
243 int rowsB, colsBC, rowsC;
244 int rows1, rows2, rows3;
254template<
class Factorization,
class VariableSet>
255void DirectBlockSchurSolver<Factorization, VariableSet>::buildNewSchurComplement(SparseLinearSystem
const& lin,
int task=0)
257 boost::timer::cpu_timer timer;
258 if(report) std::cout <<
"Schur Complement: " << std::flush;
260 MatrixAsTriplet<double> matB, matC;
261 rowsB=lin.rows(start2,end3);
262 colsBC=lin.cols(start1,end1);
263 rowsC=lin.rows(start1,end1);
266 rows1=lin.rows(start1,end1);
267 rows2=lin.rows(start2,end2);
268 rows3=lin.rows(start3,end3);
271 if(paras.refactorizeOuter || !factorization.get() || B.size()==0)
273 if(report) std::cout <<
"Outer, " << std::flush;
276 flushFactorization();
279 if((task==0 && paras.refactorizeInner) || !factorization.get())
281 factorization.reset(
new BlockLUFactorization<Factorization>(lin,start2,end2,start3,end3));
282 lin.getMatrixBlocks(matANormal,start2,end2, start2, end2);
286 MatrixAsTriplet<double> matA;
287 lin.getMatrixBlocks(matA,start2,end2, start2, end2);
288 factorization->resetBlock22(matA);
295 if(task==0 || B.size()==0)
298 lin.getMatrixBlocks(matB,start2,end3, start1, end1);
305 factorization->solve(B,AinvB,colsBC);
312 lin.getMatrixBlocks(matC,start1,end1, start1, end1);
313 mC.setSize(rowsC, colsBC);
315 matC.addToMatrix(mC);
318 for(
int i=0; i<rowsC; ++i)
319 for(
int j=0; j<colsBC; ++j)
322 for(
int k=0; k<rowsB; ++k) mC[i][j] += B[i*rowsB+k]*AinvB[j*rowsB+k];
326 mCNormal.setSize(rowsC, colsBC);
329 if(report) std::cout <<
"Finished: " << (double)(timer.elapsed().user)/1e9 <<
" sec." << std::endl;
332template<
class Factorization,
class VariableSet>
333void DirectBlockSchurSolver<Factorization,VariableSet>::resolveN(std::vector<double>& sol, std::vector<double>
const &r,std::vector<double>
const &s,std::vector<double>
const &t)
const
335 std::vector<double> xx2;
339 std::vector<double> x2(xx2.size(),0.0);
348template<
class Factorization,
class VariableSet>
349void DirectBlockSchurSolver<Factorization,VariableSet>::fwd(std::vector<double>& sol, std::vector<double>
const &r,std::vector<double>
const &s,std::vector<double>
const &t)
const
351 std::vector<double> xx1, r1;
353 r1.reserve(s.size()+t.size());
355 for(
int i=0; i<s.size();++i) r1.push_back(s[i]);
356 for(
int i=0; i<t.size();++i) r1.push_back(t[i]);
359 xx1.resize(r1.size());
360 factorization->solve(r1,xx1);
364 sol.resize(r.size());
365 for(
int i=0; i<r.size(); ++i)
368 for(
int k=0; k<xx1.size(); ++k)
369 sol[i]+=B[i*rowsB+k]*xx1[k];
373template<
class Factorization,
class VariableSet>
374void DirectBlockSchurSolver<Factorization,VariableSet>::bwd
375(std::vector<double>& sol, std::vector<double>
const &x2,std::vector<double>
const &s,std::vector<double>
const &t)
const
377 std::vector<double> xx1,x1;
379 xx1.reserve(s.size()+t.size());
381 for(
int i=0; i<s.size();++i) xx1.push_back(s[i]);
382 for(
int i=0; i<t.size();++i) xx1.push_back(t[i]);
385 for(
int i=0; i<xx1.size(); ++i)
386 for(
int k=0; k<x2.size(); ++k)
387 xx1[i]-=B[k*rowsB+i]*x2[k];
390 factorization->solve(xx1,x1);
393 sol.reserve(x2.size()+x1.size());
394 sol.resize(x2.size()+x1.size(),0.0);
396 for(
int i=0; i< x2.size(); ++i)
401 for(
int i=0; i< x1.size(); ++i)
std::unique_ptr< Factorization > factoredL
void solve(std::vector< double >const &rhs, std::vector< double > &sol, int nr=1)
MatrixAsTriplet< double > matA
static const bool needMatrix
needs a matrix
BlockLUFactorization(Sys const &lin, int start2, int end2, int start3, int end3)
void resetBlock22(MatrixAsTriplet< double >const &matA_)
Mathematical Vector that supports copy-on-write, implements AbstractFunctionSpaceElement.
regularized preconditioned conjugate gradient method
virtual void computeCorrectionAndAdjointCorrection(AbstractVector &correction, AbstractVector &adjointCorrection, AbstractLinearization &linearization)
virtual void pre(Domain &x, Range &b)
DirectBlockSchurSolver(bool doregularize=false)
virtual void post(Domain &x)
virtual void computeSimplifiedCorrection(AbstractVector &correction, AbstractLinearization const &lin) const
virtual void apply(Domain &v, const Range &d)
void resetParameters(BlockSchurParameters const &p_)
void onChangedLinearization()
static const bool needMatrix
needs a matrix
VariableSet::Descriptions::template CoefficientVectorRepresentation ::type Domain
void flushFactorization()
Abstract base class for matrix factorizations.
SparseIndexInt nrows() const
Returns number of rows (computes them, if not known)
std::vector< SparseIndexInt > ridx
row indices
std::vector< SparseIndexInt > cidx
column indices
std::vector< Scalar > data
data
void resize(size_t s)
Resizes the memory.
Abstract base class for a sparse linear system.
virtual void getRHSBlocks(std::vector< double > &rhs, int rbegin, int rend) const =0
Return components of the right hand side of the linear system.
void printVec(std::vector< double > const &v, int vend=1000000)
Adapter class for DUNE::IterativeSolver.
void LeastSquares(SLAPMatrix< double > a, std::vector< double > const &b, std::vector< double > &x)
Solve linear least squares problem, given by a*x=b.
Bridge classes that connect low level FE algorithms to higher level algorithms.
Simple interface to acml (AMD Core Math Library), to be augmented.
RegularizationMethod regularizationMethod
BlockSchurParameters(bool reg_, bool innerf_, bool outerf_)
BlockSchurParameters(bool reg_)