📄 matricecreuse.hpp
字号:
KN_<R> & operator/=(KN_<R> & x ,const MatriceProfile<R> & a) ;enum FactorizationType { FactorizationNO=0, FactorizationCholeski=1, FactorizationCrout=2, FactorizationLU=3};template <class R> class MatriceProfile:public MatriceCreuse<R> {public: mutable R *L; // lower mutable R *U; // upper mutable R *D; // diagonal int *pL; // profile L int *pU; // profile U mutable FactorizationType typefac; FactorizationType typesolver; ostream& dump (ostream&) const ; MatriceProfile(const int n,const R *a); template<class FESpace> MatriceProfile(const FESpace &,bool VF=false); MatriceProfile(int NbOfDF,R* d, R* u, int * pu, R* l, int * pl, FactorizationType tf=FactorizationNO) : MatriceCreuse<R>(NbOfDF),L(l),U(u),D(d),pL(pl),pU(pu), typefac(tf),typesolver(FactorizationNO){} const MatriceProfile t() const {return MatriceProfile(this->n,D,L,pL,U,pU,typefac);} const MatriceProfile lt() const {return MatriceProfile(this->n,0,L,pL,0,0);} const MatriceProfile l() const {return MatriceProfile(this->n,0,0,0,L,pL);} const MatriceProfile d() const {return MatriceProfile(this->n,D,0,0,0,0);} const MatriceProfile ld() const {return MatriceProfile(this->n,D,0,0,L,pL);} const MatriceProfile ldt() const {return MatriceProfile(this->n,D,L,pL,0,0);} const MatriceProfile du() const {return MatriceProfile(this->n,D,U,pU,0,0);} const MatriceProfile u() const {return MatriceProfile(this->n,0,U,pU,0,0);} const MatriceProfile ut() const {return MatriceProfile(this->n,0,0,0,U,pU);} void Solve(KN_<R> &x,const KN_<R> &b) const { /*if (typefac==0) code faux // FH nov 2006 switch(typefac) { FactorizationCholeski: cholesky() ; break; FactorizationCrout: crout(); break; FactorizationLU: LU(); break; }*/ if (&x != &b) x=b;x/=*this;} int size() const ; void resize(int n,int m) { AFAIRE("MatriceProfile::resize");} // a faire ... add march 2009 FH ~MatriceProfile(); // KN_<R> operator* (const KN_<R> & ) const ; void addMatMul(const KN_<R> &x,KN_<R> &ax) const; void addMatTransMul(const KN_<R> &x,KN_<R> &ax) const { this->t().addMatMul(x,ax);} MatriceCreuse<R> & operator +=(MatriceElementaire<R> &); void operator=(const R & v); // Mise a zero void cholesky(double = EPSILON/8.) const ; // void crout(double = EPSILON/8.) const ; // void LU(double = EPSILON/8.) const ; // R & diag(int i) { return D[i];} R & operator()(int i,int j) { if(i!=j) ffassert(0); return D[i];} // a faire R * pij(int i,int j) const { if(i!=j) ffassert(0); return &D[i];} // a faire Modif FH 31102005 MatriceMorse<R> *toMatriceMorse(bool transpose=false,bool copy=false) const ; template<class F> void map(const F & f) { for(int i=0;i<this->n;++i) D[i]=f(D[i]); if (L) for(int i=0;i<pL[this->n];++i) L[i]=f(L[i]); if (L && (L != U) ) for(int i=0;i<pL[this->m];++i) U[i]=f(U[i]); } template<class RR> MatriceProfile(const MatriceProfile<RR> & A) : MatriceCreuse<R>(A.n,A.m,0) { typefac=A.typefac; pL= docpy<int,int>(A.pL,this->n+1); D = docpy<R,RR>(A.D,this->n); if ( A.pL == A.pU ) pU=pL; else pU= docpy<int,int>(A.pU,this->m+1); L= docpy<R,RR>(A.L,pL[this->n]); if ( A.L == A.U ) U=L; else U= docpy<R,RR>(A.U,pU[this->m]); } bool addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans=false,int ii00=0,int jj00=0,bool cnj=false); // Add FH april 2005 R pscal(const KN_<R> & x,const KN_<R> & y); // produit scalaire double psor(KN_<R> & x,const KN_<R> & gmin,const KN_<R> & gmax , double omega); void setdiag(const KN_<R> & x) ; void getdiag( KN_<R> & x) const ; // end add // Add FH oct 2005 int NbCoef() const ; void setcoef(const KN_<R> & x); void getcoef( KN_<R> & x) const ; // end add /*---------------------------------------------------------------- D[i] = A[ii] L[k] = A[ij] j < i avec: pL[i]<= k < pL[i+1] et j = pL[i+1]-k U[k] = A[ij] i < j avec: pU[j]<= k < pU[j+1] et i = pU[i+1]-k remarque pL = pU generalement si L = U => la matrice est symetrique ------------------------------------------------------------------- */ private: void operator=(const MatriceProfile & A);};template <class R> class MatriceMorse:public MatriceCreuse<R> {// numebering is no-symmetric// the all line i : // k= lg[i] .. lg[i+1]+1// j = cl[k]// aij=a[k]// otherwise symmetric case// same but just the LOWER part is store (j <= i) // and aii exist always in symmetric case// -----------------------------------------public: int nbcoef; bool symetrique; R * a; int * lg; int * cl; public: class VirtualSolver :public RefCounter { friend class MatriceMorse; virtual void Solver(const MatriceMorse<R> &a,KN_<R> &x,const KN_<R> &b) const =0;}; MatriceMorse():MatriceCreuse<R>(0),nbcoef(0),symetrique(true),a(0),lg(0),cl(0),solver(0) {}; MatriceMorse(KNM_<R> & A, double tol) ; MatriceMorse(const int n,const R *a);// :MatriceCreuse<R>(n),solver(0) {} MatriceMorse(istream & f); template<class FESpace> explicit MatriceMorse(const FESpace & Uh,bool sym,bool VF=false) :MatriceCreuse<R>(Uh.NbOfDF),solver(0) {Build(Uh,Uh,sym,VF);} template<class FESpace> explicit MatriceMorse(const FESpace & Uh,const FESpace & Vh,bool VF=false) :MatriceCreuse<R>(Uh.NbOfDF,Vh.NbOfDF,0),solver(0) {Build(Uh,Vh,false,VF);} template<class FESpace> explicit MatriceMorse(const FESpace & Uh,const FESpace & Vh, void (*build)(MatriceMorse *,const FESpace & Uh,const FESpace & Vh,void *data),void *data=0 ) :MatriceCreuse<R>(Uh.NbOfDF,Vh.NbOfDF,0),solver(0) {build(this,Uh,Vh,data); } MatriceMorse(int nn,int mm,int nbc,bool sym,R *aa,int *ll,int *cc,bool dd, const VirtualSolver * s=0,bool transpose=false ) :MatriceCreuse<R>(nn,mm,dd && !transpose), nbcoef(nbc), symetrique(sym), // transpose = true => dummy false (new matrix) a(docpyornot(this->dummy,aa,nbc)), lg(docpyornot(this->dummy,ll,nn+1)), cl(docpyornot(this->dummy,cc,nbc)), solver(s) { if(transpose) dotransposition(); }; void Solve(KN_<R> &x,const KN_<R> &b) const; int size() const ; void addMatMul(const KN_<R> &x,KN_<R> &ax) const; void addMatTransMul(const KN_<R> &x,KN_<R> &ax) const; MatriceMorse & operator +=(MatriceElementaire<R> &); void operator=(const R & v) { for (int i=0;i< nbcoef;i++) a[i]=v;} virtual ~MatriceMorse(){ if (!this->dummy) { delete [] a; delete [] cl;delete [] lg;}} ostream& dump(ostream & f) const ; R * pij(int i,int j) const ; R operator()(int i,int j) const {R * p= pij(i,j) ;throwassert(p); return *p;} R & operator()(int i,int j) {R * p= pij(i,j) ;throwassert(p); return *p;} R & diag(int i) {R * p= pij(i,i) ;throwassert(p); return *p;} void SetSolver(const VirtualSolver & s){solver=&s;} void SetSolverMaster(const VirtualSolver * s){solver.master(s);} bool sym() const {return symetrique;} // Add FH april 2005 R pscal(const KN_<R> & x,const KN_<R> & y); // produit scalaire double psor(KN_<R> & x,const KN_<R> & gmin,const KN_<R> & gmax , double omega); void setdiag(const KN_<R> & x) ; void getdiag( KN_<R> & x) const ; // end add // Add FH oct 2005 int NbCoef() const ; void setcoef(const KN_<R> & x); void getcoef( KN_<R> & x) const ; // end addvoid resize(int n,int m) ; // add march 2009 ...template<class K> MatriceMorse(int nn,int mm, std::map< pair<int,int>, K> & m, bool sym); template<class RB,class RAB> void prod(const MatriceMorse<RB> & B, MatriceMorse<RAB> & AB); MatriceMorse<R> *toMatriceMorse(bool transpose=false,bool copy=false) const { return new MatriceMorse(this->n,this->m,nbcoef,symetrique,a,lg,cl,copy, solver,transpose);} bool addMatTo(R coef,std::map< pair<int,int>, R> &mij,bool trans=false,int ii00=0,int jj00=0,bool cnj=false); template<class K> MatriceMorse(const MatriceMorse<K> & ); private: void dotransposition () ; // do the transposition CountPointer<const VirtualSolver> solver; void operator=(const MatriceMorse & ); template<class FESpace> void Build(const FESpace & Uh,const FESpace & Vh,bool sym,bool VF=false); };template<class R,class M,class P> int ConjuguedGradient(const M & A,const P & C,const KN_<R> &b,KN_<R> &x,const int nbitermax, double &eps,long kprint=1000000000){// ConjuguedGradient lineare A*x est appele avec des conditions au limites // non-homogene puis homogene pour calculer le gradient if (verbosity>50) kprint=2; if (verbosity>99) cout << A << endl; throwassert(&x && &b && &A && &C); typedef KN<R> Rn; int n=b.N(); throwassert(n==x.N()); Rn g(n), h(n), Ah(n), & Cg(Ah); // on utilise Ah pour stocke Cg g = A*x; double xx= real((x,conj(x))); double epsold=eps; g -= b;// g = Ax-b Cg = C*g; // gradient preconditionne h =-Cg; double g2 = real((Cg,conj(g))); if (g2 < 1e-30) { if(verbosity>1) cout << "GC g^2 =" << g2 << " < 1.e-30 Nothing to do " << endl; return 2; } double reps2 =eps >0 ? eps*eps*g2 : -eps; // epsilon relatif eps = reps2; for (int iter=0;iter<=nbitermax;iter++) { Ah = A*h; double hAh =real((h,conj(Ah))); // if (Abs(hAh)<1e-30) ExecError("CG2: Matrix non defined, sorry "); R ro = - real((g,conj(h)))/ hAh; // ro optimal (produit scalaire usuel) x += ro *h; g += ro *Ah; // plus besoin de Ah, on utilise avec Cg optimisation Cg = C*g; double g2p=g2; g2 = real((Cg,conj(g))); if ( !(iter%kprint) && iter && (verbosity>3) ) cout << "CG:" <<iter << " ro = " << ro << " ||g||^2 = " << g2 << endl; if (g2 < reps2) { if ( !iter && !xx && g2 && epsold >0 ) { // change fo eps converge to fast due to the // penalization of boundary condition. eps = epsold*epsold*g2; if (verbosity>3 ) cout << "CG converge to fast (pb of BC) restart: " << iter << " ro = " << ro << " ||g||^2 = " << g2 << " <= " << reps2 << " new eps2 =" << eps <<endl; reps2=eps; } else { if (verbosity>1 ) cout << "CG converge: " << iter << " ro = " << ro << " ||g||^2 = " << g2 << endl; return 1;// ok } } double gamma = g2/g2p; h *= gamma; h -= Cg; // h = -Cg * gamma* h } cout << " GC: method doesn't converge in " << nbitermax << " iteration , xx= " << xx<< endl; return 0; }template<class R,class M,class P> int ConjuguedGradient2(const M & A,const P & C,KN_<R> &x,const KN_<R> &b,const int nbitermax, double &eps,long kprint=1000000000){// ConjuguedGradient2 affine A*x = 0 est toujours appele avec les condition aux limites // ------------- throwassert(&x && &A && &C); typedef KN<R> Rn; int n=x.N(); if (verbosity>99) kprint=1; R ro=1; Rn g(n),h(n),Ah(n), & Cg(Ah); // on utilise Ah pour stocke Cg g = A*x; g -= b; Cg = C*g; // gradient preconditionne h =-Cg; R g2 = (Cg,g); if (g2 < 1e-30) { if(verbosity>1) cout << "GC g^2 =" << g2 << " < 1.e-30 Nothing to do " << endl; return 2; } if (verbosity>5 ) cout << " 0 GC g^2 =" << g2 << endl; R reps2 =eps >0 ? eps*eps*g2 : -eps; // epsilon relatif eps = reps2; for (int iter=0;iter<=nbitermax;iter++) { R rop = ro; x += rop*h; // x+ rop*h , g=Ax (x old) // ((Ah = A*x - b) - g); // Ah -= b; // Ax + rop*Ah = rop*Ah + g = // Ah -= g; // Ah*rop Ah = A*x; Ah -= b; // Ax + rop*Ah = rop*Ah + g = Ah -= g; // Ah*rop R hAh =(h,Ah); if (norm(hAh)<1e-60) ExecError("CG2: Matrix is not defined (/0), sorry "); ro = - (g,h)*rop/hAh ; // ro optimal (produit scalaire usuel) x += (ro-rop) *h; g += (ro/rop) *Ah; // plus besoin de Ah, on utilise avec Cg optimisation Cg = C*g; R g2p=g2; g2 = (Cg,g); if ( ( (iter%kprint) == kprint-1) && verbosity >1 ) cout << "CG:" <<iter << " ro = " << ro << " ||g||^2 = " << g2 << endl; if (g2 < reps2) { if (verbosity ) cout << "CG converges " << iter << " ro = " << ro << " ||g||^2 = " << g2 << endl; return 1;// ok } R gamma = g2/g2p; h *= gamma; h -= Cg; // h = -Cg * gamma* h } if (verbosity ) cout << "CG does'nt converge: " << nbitermax << " ||g||^2 = " << g2 << " reps2= " << reps2 << endl; return 0; }template <class R>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -