00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef __MATRIX_H
00035 #define __MATRIX_H
00036
00037
00038 #include <valarray>
00039 #include <iostream>
00040 using std::valarray;
00041 using std::ostream;
00042
00043 #include "Mesh.h"
00044 #include "GraphOfMatrix.h"
00045 #include "Vect.h"
00046
00047 namespace OFELI {
00048
00049 template<class T_> class DMatrix;
00050
00051 class Mesh;
00052 class Element;
00053 class Side;
00054
00055 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00056 typedef std::pair<size_t,size_t> RC;
00057 #endif
00058
00059 #ifdef USE_MTL
00060 #include "mtl/mtl.h"
00061 typedef mtl::matrix<double,mtl::rectangle<>,mtl::compressed<int,mtl::external,mtl::index_from_one>,mtl::row_major>::type MTL_Mat;
00062 #endif
00063
00071 enum MatrixType {
00072 SKYLINE = 0x00800000,
00073 SPARSE = 0x01000000,
00074 DIAGONAL = 0x02000000,
00075 TRIDIAGONAL = 0x04000000,
00076 SYMMETRIC = 0x08000000,
00077 UNSYMMETRIC = 0x10000000,
00078 IDENTITY = 0x12000000
00079 };
00080
00084 enum Iteration {
00085 DIRECT_SOLVER = 0,
00086 CG_SOLVER = 1,
00087 CGS_SOLVER = 2,
00088 BICG_SOLVER = 3,
00089 BICG_STAB_SOLVER = 4,
00090 GMRES_SOLVER = 5,
00091 QMR_SOLVER = 6
00092 };
00093
00097 enum Preconditioner {
00098 IDENT_PREC = 0,
00099 DIAG_PREC = 1,
00100 ILU_PREC = 2
00101 };
00102
00103
00104
00113 template<class T_>
00114 class Matrix
00115 {
00116
00117 public:
00118
00121 Matrix();
00122
00124 Matrix(const Matrix<T_> &m);
00125
00127 virtual ~Matrix() { }
00128
00130 size_t getNbRows() const { return _nb_rows; }
00131
00133 size_t getNbColumns() const { return _nb_cols; }
00134
00136 void setPenal(double p) { _penal = p; }
00137
00140 T_ getDiag(size_t k) const { return _diag[k-1]; }
00141
00143 size_t getSize() const { return _size; }
00144
00146 virtual void MultAdd(const Vect<T_> &x, Vect<T_> &y) const = 0;
00147
00149 virtual void MultAdd(T_ a, const Vect<T_> &v, Vect<T_> &w) const = 0;
00150
00152 virtual void Mult(const Vect<T_> &x, Vect<T_> &y) const = 0;
00153
00155 virtual void TMult(const Vect<T_> &v, Vect<T_> &w) const = 0;
00156
00159 void setDiagonal(const class Mesh &mesh);
00160
00161 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00162 virtual void setMesh(const class Mesh &mesh, size_t dof=0, size_t type=0)
00163 {
00164 _init_set_mesh(mesh,dof,type);
00165 }
00166
00167 void _init_set_mesh(const class Mesh &mesh, size_t dof=0, size_t type=0);
00168 #endif
00169
00170 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00171 virtual void setMesh(size_t dof, const class Mesh &mesh, int code=0)=0;
00172 #endif
00173
00174 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00175 virtual void setMesh(size_t dof, size_t nb_eq, const class Mesh &mesh)=0;
00176 #endif
00177
00183 void Assembly(const Element *el, T_ *a);
00184
00190 void Assembly(const Element *el, const DMatrix<T_> &a);
00191
00197 void Assembly(const Side *sd, T_ *a);
00198
00204 void Assembly(const Side *sd, const DMatrix<T_> &a);
00205
00218 void Prescribe(const class Mesh &mesh, Vect<T_> &b, const Vect<T_> &u, int flag=0);
00219
00231 void Prescribe(const class Mesh &mesh, Vect<T_> &b, int flag=0);
00232
00247 void Prescribe(size_t dof, const class Mesh &mesh, Vect<T_> &b, const Vect<T_> &u, int flag=0);
00248
00249 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00250 void Prescribe1(const class Mesh &mesh, Vect<T_> &b, const Vect<T_> &u, int flag=0);
00251 #endif
00252
00253 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00254 void Prescribe(const class Mesh &mesh);
00255 #endif
00256
00266 void PrescribeSide(const class Mesh &mesh);
00267
00268 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00269 void Constraint(const class Mesh &mesh) { Prescribe(mesh); }
00270 #endif
00271
00273 virtual void Set(size_t i, size_t j, const T_ &x) = 0;
00274
00276 virtual void Add(size_t i, size_t j, const T_ &x) = 0;
00277
00279 virtual int Factor() = 0;
00280
00284 virtual int Solve(Vect<T_> &b) = 0;
00285
00293 int Solve(const Vect<T_> &b, Vect<T_> &x);
00294
00297 int FactorAndSolve(Vect<T_> &b);
00298
00300 unsigned long getLength() const { return _length; }
00301
00303 bool isDiagonal() const { return _is_diagonal; }
00304
00308 bool isFactorized() const { return _fact; }
00309
00311 virtual size_t getColInd(size_t i) const;
00312
00314 virtual size_t getRowPtr(size_t i) const;
00315
00320 virtual T_ & operator()(size_t i, size_t j) = 0;
00321
00327 virtual const T_ operator()(size_t i) const = 0;
00328
00333 virtual T_ operator()(size_t i, size_t j) const = 0;
00334
00339 T_ & operator[](size_t k) { return _a[k]; }
00340
00345 T_ operator[](size_t k) const { return _a[k]; }
00346
00349 Matrix & operator=(Matrix<T_> &m);
00350
00353 Matrix & operator+=(const Matrix<T_> &m);
00354
00357 Matrix & operator-=(const Matrix<T_> &m);
00358
00361 Matrix & operator=(const T_ &x);
00362
00365 Matrix & operator*=(const T_ &x);
00366
00369 Matrix & operator+=(const T_ &x);
00370
00373 Matrix & operator-=(const T_ &x);
00374
00376 virtual T_ getEntry(size_t i, size_t j) const = 0;
00377
00384 void setPrintView(size_t rmin, size_t rmax, size_t cmin, size_t cmax);
00385
00392 void getPrintView(size_t &rmin, size_t &rmax, size_t &cmin, size_t &cmax) const;
00393
00394 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00395
00396 #ifdef USE_MTL
00397 MTL_Mat *A_;
00398 #endif
00399 #endif
00400
00401 protected:
00402 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00403 size_t _rmin, _rmax, _cmin, _cmax;
00404 size_t _dof_type, _nb_rows, _nb_cols, _size, _dof;
00405 unsigned long _length;
00406 T_ _zero, _temp;
00407 valarray<T_> _a, _aU, _diag;
00408 valarray<unsigned long> _row_ptr;
00409 valarray<size_t> _col_ind, _ch;
00410 double _penal;
00411 bool _fact, _set_nodes, _set_elements, _set_sides, _is_diagonal;
00412 #endif
00413 };
00414
00415
00417
00419
00420
00421 template<class T_>
00422 Matrix<T_>::Matrix()
00423 {
00424 _penal = 1.e20;
00425 _zero = 0;
00426 _rmin = _cmin = 1;
00427 _rmax = _cmax = 10000;
00428 }
00429
00430
00431 template<class T_>
00432 Matrix<T_>::Matrix(const Matrix<T_> &m)
00433 {
00434 _zero = 0;
00435 _size = m._size;
00436 _nb_rows = m._nb_rows;
00437 _nb_cols = m._nb_cols;
00438 _length = m._length;
00439 _penal = m._penal;
00440 _ch.resize(_size);
00441 _diag.resize(_size);
00442 _ch = m._ch;
00443 _diag = m._diag;
00444 _rmin = m._rmin;
00445 _cmin = m._cmin;
00446 _rmax = m._rmax;
00447 _cmax = m._cmax;
00448 }
00449
00450
00451 template<class T_>
00452 void Matrix<T_>::setDiagonal(const class Mesh &mesh)
00453 {
00454 _init_set_mesh(mesh);
00455 _size = mesh.getNbEq();
00456 _a.resize(_size);
00457 _ch.resize(_size);
00458 _ch[0] = 0;
00459 for (size_t i=1; i<_size; i++)
00460 _ch[i] = i+1;
00461 Clear(_a);
00462 _fact = false;
00463 _dof = 0;
00464 _length = _nb_rows = _nb_cols = _size;
00465 }
00466
00467
00468 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00469 template<class T_>
00470 void Matrix<T_>::_init_set_mesh(const class Mesh &mesh, size_t dof, size_t type)
00471 {
00472 type = 0;
00473 _zero = T_(0);
00474 _dof_type = 0;
00475 if (mesh.NodesAreDOF())
00476 _dof_type = NODE_DOF;
00477 else if (mesh.SidesAreDOF())
00478 _dof_type = SIDE_DOF;
00479 else if (mesh.ElementsAreDOF())
00480 _dof_type = ELEMENT_DOF;
00481 _dof = dof;
00482 _size = _nb_rows = _nb_cols = mesh.getNbEq();
00483 if (_dof_type==NODE_DOF)
00484 if (_dof)
00485 _size = _nb_rows = _nb_cols = mesh.getNbNodes();
00486 else
00487 _size = _nb_rows = _nb_cols = mesh.getNbEq();
00488 else if (_dof_type==SIDE_DOF)
00489 if (_dof)
00490 _size = _nb_rows = _nb_cols = mesh.getNbSides();
00491 else
00492 _size = _nb_rows = _nb_cols = mesh.getNbEq();
00493 else if (_dof_type==ELEMENT_DOF)
00494 _size = _nb_rows = _nb_cols = mesh.getNbElements();
00495 else;
00496 }
00497 #endif
00498
00499
00500 template<class T_>
00501 void Matrix<T_>::Assembly(const Element *el, T_ *a)
00502 {
00503 size_t kk = 0;
00504 for (size_t in=1; in<=el->getNbNodes(); ++in) {
00505 Node *nd1 = el->getPtrNode(in);
00506 for (size_t k=1; k<=nd1->getNbDOF(); ++k) {
00507 for (size_t jn=1; jn<=el->getNbNodes(); ++jn) {
00508 Node *nd2 = el->getPtrNode(jn);
00509 for (size_t l=1; l<=nd2->getNbDOF(); ++l) {
00510 if (nd1->getDOF(k)!=0 && nd2->getDOF(l)!=0)
00511 Add(nd1->getDOF(k),nd2->getDOF(l),a[kk]);
00512 kk++;
00513 }
00514 }
00515 }
00516 }
00517 }
00518
00519
00520 template<class T_>
00521 void Matrix<T_>::Assembly(const Element *el, const DMatrix<T_> &a)
00522 {
00523 size_t i = 1;
00524 for (size_t in=1; in<=el->getNbNodes(); ++in) {
00525 Node *nd1 = el->getPtrNode(in);
00526 for (size_t k=1; k<=nd1->getNbDOF(); ++k) {
00527 size_t j = 1;
00528 for (size_t jn=1; jn<=el->getNbNodes(); ++jn) {
00529 Node *nd2 = el->getPtrNode(jn);
00530 for (size_t l=1; l<=nd2->getNbDOF(); ++l) {
00531 if (nd1->getDOF(k)!=0 && nd2->getDOF(l)!=0)
00532 Add(nd1->getDOF(k),nd2->getDOF(l),a(i,j));
00533 j++;
00534 }
00535 }
00536 i++;
00537 }
00538 }
00539 }
00540
00541
00542 template<class T_>
00543 void Matrix<T_>::Assembly(const Side *sd, T_ *a)
00544 {
00545 size_t kk = 0;
00546 for (size_t in=1; in<=sd->getNbNodes(); ++in) {
00547 Node *nd1 = sd->getPtrNode(in);
00548 for (size_t k=1; k<=nd1->getNbDOF(); ++k) {
00549 for (size_t jn=1; jn<=sd->getNbNodes(); ++jn) {
00550 Node *nd2 = sd->getPtrNode(jn);
00551 for (size_t l=1; l<=nd2->getNbDOF(); ++l) {
00552 if (nd1->getDOF(k)!=0 && nd2->getDOF(l)!=0)
00553 Add(nd1->getDOF(k),nd2->getDOF(l),a[kk]);
00554 kk++;
00555 }
00556 }
00557 }
00558 }
00559 }
00560
00561
00562 template<class T_>
00563 void Matrix<T_>::Assembly(const Side *sd, const DMatrix<T_> &a)
00564 {
00565 size_t i = 1;
00566 for (size_t in=1; in<=sd->getNbNodes(); ++in) {
00567 Node *nd1 = sd->getPtrNode(in);
00568 for (size_t k=1; k<=nd1->getNbDOF(); ++k) {
00569 size_t j = 1;
00570 for (size_t jn=1; jn<=sd->getNbNodes(); ++jn) {
00571 Node *nd2 = sd->getPtrNode(jn);
00572 for (size_t l=1; l<=nd2->getNbDOF(); ++l) {
00573 if (nd1->getDOF(k)!=0 && nd2->getDOF(l)!=0)
00574 Add(nd1->getDOF(k),nd2->getDOF(l),a(i,j));
00575 j++;
00576 }
00577 }
00578 i++;
00579 }
00580 }
00581 }
00582
00583
00584 template<class T_>
00585 void Matrix<T_>::Prescribe(const class Mesh &mesh, Vect<T_> &b, const Vect<T_> &u, int flag)
00586 {
00587 const Node *nd;
00588 for (mesh.topNode(); (nd=mesh.getNode());) {
00589 for (size_t i=1; i<=nd->getNbDOF(); ++i) {
00590 if (nd->getCode(i)>0) {
00591 size_t k = nd->getDOF(i) - 1;
00592 if (flag==0) {
00593 _diag[k] = getEntry(k+1,k+1)*_penal;
00594 Set(k+1,k+1,_diag[k]);
00595 }
00596 b[k] = u[k] * _diag[k];
00597 }
00598 }
00599 }
00600 }
00601
00602
00603 template<class T_>
00604 void Matrix<T_>::Prescribe(const class Mesh &mesh, Vect<T_> &b, int flag)
00605 {
00606 const Node *nd;
00607 for (mesh.topNode(); (nd=mesh.getNode());)
00608 for (size_t j=1; j<=nd->getNbDOF(); ++j)
00609 if (nd->getCode(j)>0) {
00610 size_t k = nd->getDOF(j) - 1;
00611 if (!flag) {
00612 _diag[k] = getEntry(k+1,k+1)*_penal;
00613 Set(k+1,k+1,_diag[k]);
00614 }
00615 b[k] = 0;
00616 }
00617 }
00618
00619
00620 template<class T_>
00621 void Matrix<T_>::Prescribe(size_t dof, const class Mesh &mesh, Vect<T_> &b, const Vect<T_> &u, int flag)
00622 {
00623 const Node *nd;
00624 for (mesh.topNode(); (nd=mesh.getNode());) {
00625 if (nd->getCode(dof)>0) {
00626 size_t k = nd->getLabel() - 1;
00627 if (!flag) {
00628 _diag[k] = getEntry(k+1,k+1)*_penal;
00629 Set(k+1,k+1,_diag[k]);
00630 }
00631 b[k] = u[k] * _diag[k];
00632 }
00633 }
00634 }
00635
00636
00637 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00638 template<class T_>
00639 void Matrix<T_>::Prescribe1(const class Mesh &mesh, Vect<T_> &b, const Vect<T_> &u, int flag)
00640 {
00641 const Node *nd;
00642 for (mesh.topNode(); (nd=mesh.getNode());) {
00643 for (size_t i=1; i<=nd->getNbDOF(); i++)
00644 if (nd->getCode(i)>0) {
00645 size_t k = nd->getDOF(i);
00646 if (!flag)
00647 Add(k,k,_penal);
00648 b(k) = u(k)*_penal;
00649 }
00650 }
00651 }
00652 #endif
00653
00654
00655 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00656 template<class T_>
00657 void Matrix<T_>::Prescribe(const class Mesh &mesh)
00658 {
00659 const Node *nd;
00660 for (mesh.topNode(); (nd=mesh.getNode());) {
00661 for (size_t i=1; i<=nd->getNbDOF(); i++)
00662 if (nd->getCode(i)>0) {
00663 size_t k = nd->getDOF(i);
00664 Set(k,k,getEntry(k,k)*_penal);
00665 }
00666 }
00667 }
00668 #endif
00669
00670
00671 template<class T_>
00672 void Matrix<T_>::PrescribeSide(const class Mesh &mesh)
00673 {
00674 const Side *sd;
00675 for (mesh.topSide(); (sd=mesh.getSide());) {
00676 for (size_t i=1; i<=sd->getNbDOF(); i++)
00677 if (sd->getCode(i)>0) {
00678 size_t k = sd->getDOF(i);
00679 Set(k,k,getEntry(k,k)*_penal);
00680 }
00681 }
00682 }
00683
00684
00685 template<class T_>
00686 int Matrix<T_>::Solve(const Vect<T_> &b, Vect<T_> &x)
00687 {
00688 x = b;
00689 return Solve(x);
00690 }
00691
00692
00693 template<class T_>
00694 int Matrix<T_>::FactorAndSolve(Vect<T_> &b)
00695 {
00696 Factor();
00697 return Solve(b);
00698 }
00699
00700
00701 template<class T_>
00702 size_t Matrix<T_>::getColInd(size_t i) const
00703 {
00704 i = 0;
00705 return 0;
00706 }
00707
00708
00709 template<class T_>
00710 size_t Matrix<T_>::getRowPtr(size_t i) const
00711 {
00712 i = 0;
00713 return 0;
00714 }
00715
00716
00717 template<class T_>
00718 Matrix<T_> & Matrix<T_>::operator=(Matrix<T_> &m)
00719 {
00720 _a = m._a;
00721 return *this;
00722 }
00723
00724
00725 template<class T_>
00726 Matrix<T_> & Matrix<T_>::operator+=(const Matrix<T_> &m)
00727 {
00728 for (size_t i=0; i<_length; ++i)
00729 _a[i] += m._a[i];
00730 return *this;
00731 }
00732
00733
00734 template<class T_>
00735 Matrix<T_> & Matrix<T_>::operator-=(const Matrix<T_> &m)
00736 {
00737 for (size_t i=0; i<_length; ++i)
00738 _a[i] -= m._a[i];
00739 return *this;
00740 }
00741
00742
00743 template<class T_>
00744 Matrix<T_> & Matrix<T_>::operator=(const T_ &x)
00745 {
00746 for (size_t i=0; i<_length; ++i)
00747 _a[i] = x;
00748 return *this;
00749 }
00750
00751
00752 template<class T_>
00753 Matrix<T_> & Matrix<T_>::operator*=(const T_ &x)
00754 {
00755 for (size_t i=0; i<_length; ++i)
00756 _a[i] *= x;
00757 return *this;
00758 }
00759
00760
00761 template<class T_>
00762 Matrix<T_> & Matrix<T_>::operator+=(const T_ &x)
00763 {
00764 for (size_t i=0; i<_length; ++i)
00765 _a[i] += x;
00766 return *this;
00767 }
00768
00769
00770 template<class T_>
00771 Matrix<T_> & Matrix<T_>::operator-=(const T_ &x)
00772 {
00773 for (size_t i=0; i<_length; ++i)
00774 _a[i] -= x;
00775 return *this;
00776 }
00777
00778
00779 template<class T_>
00780 void Matrix<T_>::setPrintView(size_t rmin, size_t rmax, size_t cmin, size_t cmax)
00781 {
00782 _rmin = rmin;
00783 _rmax = rmax;
00784 if (_rmin==0)
00785 _rmin = 1;
00786 if (_rmax>_size)
00787 _rmax = _size;
00788 _cmin = cmin;
00789 _cmax = cmax;
00790 if (_cmin==0)
00791 _cmin = 1;
00792 if (_cmax>_size)
00793 _cmax = _size;
00794 }
00795
00796
00797 template<class T_>
00798 void Matrix<T_>::getPrintView(size_t &rmin, size_t &rmax, size_t &cmin, size_t &cmax) const
00799 {
00800 rmin = _rmin;
00801 rmax = _rmax;
00802 cmin = _cmin;
00803 cmax = _cmax;
00804 if (rmin <= 0)
00805 rmin = 1;
00806 if (cmin <= 0)
00807 cmin = 1;
00808 if (rmax >= _nb_rows || rmax < rmin)
00809 rmax = _nb_rows;
00810 if (cmax >= _nb_cols || cmax < cmin)
00811 cmax = _nb_cols;
00812 }
00813
00814
00815 }
00816
00817 #endif