DOFMatrix.h 20.5 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// ============================================================================
// ==                                                                        ==
// == AMDiS - Adaptive multidimensional simulations                          ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
// ==  crystal growth group                                                  ==
// ==                                                                        ==
// ==  Stiftung caesar                                                       ==
// ==  Ludwig-Erhard-Allee 2                                                 ==
// ==  53175 Bonn                                                            ==
// ==  germany                                                               ==
// ==                                                                        ==
// ============================================================================
// ==                                                                        ==
// ==  http://www.caesar.de/cg/AMDiS                                         ==
// ==                                                                        ==
// ============================================================================

/** \file DOFMatrix.h */

#ifndef AMDIS_DOFMATRIX_H
#define AMDIS_DOFMATRIX_H

// ============================================================================
// ===== includes =============================================================
// ============================================================================

#include <vector>
Thomas Witkowski's avatar
Thomas Witkowski committed
30
#include <set>
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <memory>
#include <list>
#include "Global.h"
#include "Flag.h"
#include "RCNeighbourList.h"
#include "DOFAdmin.h"
#include "DOFIterator.h"
#include "DOFIndexed.h"
#include "MemoryManager.h"
#include "Boundary.h"
#include "Serializable.h"

namespace AMDiS {

  // ============================================================================
  // ===== forward declarations =================================================
  // ============================================================================

  class Mesh;
  class FiniteElemSpace;
  class ElInfo;
  class BasisFunction;
  class FillInfo;
  class Operator;
  class ElementMatrix;
  class BoundaryManager;

  template<typename T> class DOFVector;

  // ===========================================================================
  // ===== struct MatEntry =====================================================
  // ===========================================================================

  /** \brief
   * Represents one entry of a DOFMatrix
   */
  struct MatEntry
  {
    /** \brief
     * column index of entry (if >= 0; else unused)
     */
    DegreeOfFreedom col;

    /** \brief
     * matrix entry
     */
    double entry;
  };


  /** \brief
   * Is used to search for all entries of a matrix which column index is 
   * smaller than a given value.
   */
85
  class MatEntryValueLess : public std::unary_function<MatEntry, bool> {
86
87
88
89
90
  private:
    const double value_;
  public:
    MatEntryValueLess(const double& value) 
      : value_(value) 
91
    {}
92
93
94

    bool operator()(const MatEntry& m) {
      return (fabs(m.entry) < value_);
95
    }      
96
97
98
99
100
101
102
  };


  /** \brief
   * Is used to search for all entries of a matrix which value is smaller 
   * than a given value.
   */
103
  class MatEntryColLess : public std::unary_function<MatEntry, bool> {
104
105
106
107
108
  private:
    const int col_;
  public:
    MatEntryColLess(const int& col) 
      : col_(col) 
109
    {}
110
111
112

    bool operator()(const MatEntry& m) {
      return (fabs(m.col) < col_);
113
    }      
114
115
116
117
118
119
120
  };


  /** \brief
   * This function is required if two MatEntries are compared by their col
   * entry (for example when sorting a vector of MatEntries).
   */
121
  struct CmpMatEntryCol : public std::binary_function<MatEntry, MatEntry, bool> {
122
123
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return m1.col < m2.col;
124
    }
125
126
127
128
129
130
131
  };
  

  /** \brief
   * This function compares two matrix entries by their values. It returns true,
   * if the value of m2 is greater than the value of m1.
   */
132
  struct CmpMatEntryValue : public std::binary_function<MatEntry, MatEntry, bool> {
133
134
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return m1.entry < m2.entry;
135
    }
136
137
138
139
140
141
142
  };


  /** \brief
   * This function compares two matrix entries by their values. It returns true,
   * if the value of m2 is greater than the value of m1.
   */
143
  struct CmpMatEntryAbsValueLess : public std::binary_function<MatEntry, MatEntry, bool> {
144
145
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return fabs(m1.entry) < fabs(m2.entry);
146
    }
147
148
149
150
151
152
  };
  
  /** \brief
   * This function compares two matrix entries by their values. It returns true,
   * if the value of m1 is greater than the value of m2.
   */
153
  struct CmpMatEntryAbsValueGreater : public std::binary_function<MatEntry, MatEntry, bool> {
154
155
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return fabs(m1.entry) > fabs(m2.entry);
156
    }
157
158
159
160
161
162
163
164
165
166
167
168
169
  };

  // ============================================================================
  // ===== class DOFMatrix ======================================================
  // ============================================================================

  /** \ingroup DOFAdministration
   * \brief
   * A DOFMatrix is a sparse matrix representation for matrices that work
   * on DOFVectors. Every row of a matrix is realized as a vector of MatEntry 
   * objects. Each entry consists of a column DOF index and the corresponding 
   * double matrix entry. Unused entries are marked with a negative column index.
   */
170
  class DOFMatrix : public DOFIndexed< std::vector<MatEntry> >,
171
172
173
174
175
176
177
                    public Serializable
  {
  public:
    MEMORY_MANAGED(DOFMatrix);

    /** \ingroup DOFAdministration
     * \brief
178
     * Alias for DOFIterator< std::vector<MatEntry<T> > >. So one can access an
179
180
     * iterator working on a DOFMatrix via DOFMatrix::Iterator
     */
181
    class Iterator : public DOFIterator< std::vector<MatEntry> > {
182
    public:
183
      Iterator(DOFIndexed< std::vector<MatEntry> > *c, 
184
	       DOFIteratorType type)
185
	: DOFIterator< std::vector<MatEntry> >(c, type)
186
      {}
187
188
189
190
191
192
    };
    
    /** \brief
     * A MatrixRow represents one row of the sparse matrix. It is realized by
     * a STL vector of MatEntry<T> objects
     */
193
    typedef std::vector<MatEntry> MatrixRow;
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
    
    /** \brief
     * Symbolic constant for an unused matrix entry
     */
    static const int UNUSED_ENTRY = -1;
    
    /** \brief
     * Symbolic constant for an unused entry which is not followed by any
     * used entry in this row
     */
    static const int NO_MORE_ENTRIES = -2;

  public:    
    DOFMatrix();

    /** \brief
     * Constructs a DOFMatrix with name n and the given row and 
     * column FESpaces.
     */
    DOFMatrix(const FiniteElemSpace* rowFESpace,
	      const FiniteElemSpace* colFESpace,
Thomas Witkowski's avatar
Thomas Witkowski committed
215
	      std::string n = "");
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237

    /** \brief
     * Copy-Constructor
     */
    DOFMatrix(const DOFMatrix& rhs);


    /** \brief
     * Destructor
     */
    virtual ~DOFMatrix();
  
    /** \brief
     * operator=
     */
    DOFMatrix& operator=(const DOFMatrix& rhs);

    void copy(const DOFMatrix& rhs);

    /** \brief
     * Returns an iterator to the begin of matrix rows (\ref matrix.begin())
     */
238
    std::vector< std::vector<MatEntry> >::iterator begin() { 
239
      return matrix.begin();
240
    }
241
242
243
244

    /** \brief
     * Returns an iterator to the end of matrix rows (\ref matrix.end())
     */
245
    std::vector< std::vector<MatEntry> >::iterator end() { 
246
      return matrix.end(); 
247
    }
248
249
250
251
252
 
    /** \brief
     * Used by DOFAdmin to compress the DOFMatrix
     */
    virtual void compressDOFIndexed(int first, int last, 
253
				    std::vector<DegreeOfFreedom> &newDOF);
254
255
256
257
258
259
260
261
262
263
264

    /** \brief
     * Implements DOFIndexedBase::freeDOFContent()
     */ 
    virtual void freeDOFContent(int index);

    /** \brief
     * Returns whether entry matrix[a][b] is used
     */    
    inline bool entryUsed(DegreeOfFreedom a,int b) const {
      return (((matrix[a])[b]).col >= 0);
265
    }
266
267
268
269
270

    /** \brief
     * Returns true if matrix[a][b] has entry \ref NO_MORE_ENTRIES
     */
    inline bool noMoreEntries(DegreeOfFreedom a,int b) const {
Thomas Witkowski's avatar
Thomas Witkowski committed
271
      return (NO_MORE_ENTRIES == ((matrix[a])[b]).col);
272
    }
273
274
275
276

    /** \brief
     * Returns \ref coupleMatrix.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
277
278
    inline bool isCoupleMatrix() { 
      return coupleMatrix; 
279
    }
280
281
282
283

    /** \brief
     * Returns \ref coupleMatrix.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
284
285
    inline void setCoupleMatrix(bool c) { 
      coupleMatrix = c; 
286
    }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312

    /** \brief
     * Matrix-matrix multiplication.
     */
    void mm(MatrixTranspose aTranspose, DOFMatrix& a, 
	    MatrixTranspose bTranspose, DOFMatrix& b);
  
    /** \brief
     * a*x + y
     */
    void axpy(double a, 
	      const DOFMatrix& x,
	      const DOFMatrix& y);

    /** \brief
     * Multiplication with a scalar.
     */
    void scal(double s);

    inline void addOperator(Operator *op, 
			    double* factor = NULL,
			    double* estFactor = NULL) 
    { 
      operators.push_back(op);
      operatorFactor.push_back(factor);
      operatorEstFactor.push_back(estFactor);
313
    }
314

315
    inline std::vector<double*>::iterator getOperatorFactorBegin() {
316
      return operatorFactor.begin();
317
    }
318

319
    inline std::vector<double*>::iterator getOperatorFactorEnd() {
320
      return operatorFactor.end();
321
    }
322

323
    inline std::vector<double*>::iterator getOperatorEstFactorBegin() {
324
      return operatorEstFactor.begin();
325
    }
326

327
    inline std::vector<double*>::iterator getOperatorEstFactorEnd() {
328
      return operatorEstFactor.end();
329
    }
330

331
    inline std::vector<Operator*>::iterator getOperatorsBegin() {
332
      return operators.begin();
333
    }
334

335
    inline std::vector<Operator*>::iterator getOperatorsEnd() {
336
      return operators.end();
337
    }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363

    Flag getAssembleFlag();

    /** \brief
     * Updates the matrix matrix by traversing the underlying mesh and assembling
     * the element contributions into the matrix. Information about the 
     * computation of element matrices and connection of local and global DOFs is
     * stored in minfo; the flags for the mesh traversal are stored at 
     * minfo->fill_flags which specifies the elements to be visited and 
     * information that should be present on the elements for the calculation of 
     * the element matrices and boundary information (if minfo->boundBas is not
     * NULL). On the elements, information about the row DOFs is accessed by 
     * minfo->rowBas using info->row_admin; this vector is also used for the 
     * column DOFs if minfo->nCol is less or equal zero, or minfo->col_admin or 
     * minfo->colBas is a NULL pointer; if row and column DOFs are the same, the 
     * boundary type of the DOFs is accessed by minfo->boundBas if 
     * minfo->boundBas is not a NULL pointer; then the element matrix is 
     * computed by minfo->fillElementMatrix(el info, minfo->myFill); these 
     * contributions, multiplied by minfo->factor, are eventually added to matrix
     * by a call of addElementMatrix() with all information about row and column 
     * DOFs, the element matrix, and boundary types, if available;
     * updateMatrix() only adds element contributions; this makes several calls 
     * for the assemblage of one matrix possible; before the first call, the 
     * matrix should be cleared by calling clear dof matrix().
     */
  
364
365
    void assemble(double factor, ElInfo *elInfo, 
		  const BoundaryType *bound, Operator *op = NULL);
366
367


368
369
370
    void assemble(double factor, 
		  ElInfo *rowElInfo, ElInfo *colElInfo,
		  ElInfo *smallElInfo, ElInfo *largeElInfo,
371
		  const BoundaryType *bound, Operator *op = NULL);
372
    
373
374
375
376
377
378
379
380
381
382
383
384

    /** \brief
     * Adds an element matrix to \ref matrix
     */
    void addElementMatrix(double sign, 
			  const ElementMatrix& elMat, 
			  const BoundaryType *bound,
			  bool add = true);

    /** \brief
     * Returns \ref matrix
     */
385
    std::vector< std::vector<MatEntry> >& getMatrix() { 
386
      return matrix; 
387
    }
388

389
    void setMatrix(std::vector< std::vector<MatEntry> > m) {
390
      matrix = m;
391
    }
392
393
394
395

    /** \brief
     * Returns \ref matrix[n]
     */
396
    const std::vector<MatEntry>& getRow(int n) const { 
397
      return matrix[n];
398
    }
399
400
401
402

    /** \brief
     * Returns \ref matrix[n]
     */
403
    std::vector<MatEntry>& getRow(int n) { 
404
      return matrix[n];
405
    }
406
407
408
409
410
411
412

    /** \brief
     * Returns whether restriction should be performed after coarsening
     * (false by default)
     */
    virtual bool coarseRestrict() {
      return false;
413
    }
414
415
416
417
418
419

    /** \brief
     * Returns const \ref rowFESpace
     */
    const FiniteElemSpace* getRowFESpace() const { 
      return rowFESpace; 
420
    }
421
422
423
424
425
426

    /** \brief
     * Returns const \ref colFESpace
     */
    const FiniteElemSpace* getColFESpace() const { 
      return colFESpace; 
427
    }
428
429
430
431
432
433

    /** \brief
     * Returns const \ref rowFESpace
     */
    const FiniteElemSpace* getFESpace() const { 
      return rowFESpace; 
434
    }
435
436
437
438
439
440

    /** \brief
     * Returns number of rows (\ref matrix.size())
     */
    inline int getSize() const { 
      return matrix.size();
441
    }
442

Thomas Witkowski's avatar
Thomas Witkowski committed
443
444
445
446
447
448
    /** \brief
     * Returns the number of used rows (equal to number of used DOFs in
     * the row FE space).
     */
    inline int getUsedSize() const {
      return rowFESpace->getAdmin()->getUsedSize();
449
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
450

451
452
453
454
    /** \brief
     * Returns number of cols. For that, the function iteratos over all
     * rows and searchs for the entry with the highest col number.
     */
455
    int getNumCols() const;
456

457
458
459
    /** \brief
     * Returns \ref name
     */
460
    inline const std::string& getName() const { 
461
      return name; 
462
    }
463
464
465
466
467

    /** \brief
     * Resizes \ref matrix to n rows
     */
    inline void resize(int n) { 
468
      TEST_EXIT_DBG(n >= 0)("Can't resize DOFMatrix to negative size\n"); 
469
      matrix.resize(n);
470
    }
471
472
473
474

    /** \brief
     * Returns \ref matrix[i] which is the i-th row
     */
475
    inline const std::vector<MatEntry>& operator[](int i) const {
476
477
      TEST_EXIT_DBG((i >= 0) && (i < (static_cast<int>(matrix.size()))))
      	("Illegal matrix index %d.\n",i); 
478
      return matrix[i];
479
    }
480
481
482
483

    /** \brief
     * Returns \ref matrix[i] which is the i-th row
     */
484
    inline std::vector<MatEntry>& operator[](int i) {
485
486
      TEST_EXIT_DBG((i >= 0) && (i < (static_cast<int>(matrix.size()))))
      	("Illegal vector index %d.\n", i);
487
      return matrix[i];
488
    }
489
490
491
492

    /** \brief
     * Access to \ref matrix[a][b].entry
     */
493
    inline double physAcc(DegreeOfFreedom a, DegreeOfFreedom b) const { 
494
      return matrix[a][b].entry; 
495
    }
496
497
498
499
500
501
502
503

    /** \brief
     * Access to \ref matrix[a][b].col
     */
    inline DegreeOfFreedom physToLogIndex(DegreeOfFreedom a,
					  DegreeOfFreedom b) const 
    {
      return matrix[a][b].col;
504
    }
505
506
507
508

    /** \brief
     * Returns physical column index of logical index b in row a
     */
509
510
511
512
513
514
515
516
    inline DegreeOfFreedom logToPhysIndex(DegreeOfFreedom a, DegreeOfFreedom b) const
    {      
      int size = static_cast<int>(matrix[a].size());
      for (int j = 0; j < size; j++) 
	if (b == matrix[a][j].col) 
	  return j;

      return -1;
517
    }
518
519
520
521

    /** \brief
     * Returns value at logical indices a,b
     */
522
    double logAcc(DegreeOfFreedom a, DegreeOfFreedom b) const;
523
524
525
526

    /** \brief
     * Changes col at logical indices a,b to c 
     */
527
    void changeColOfEntry(DegreeOfFreedom a, DegreeOfFreedom b, DegreeOfFreedom c);
528
529
530
531
532
533
534
535
536

    /** \brief
     * Changes col of \ref matrix[a][b] to c
     */
    inline void changePhysColOfEntry(DegreeOfFreedom a,
				     DegreeOfFreedom b,
				     DegreeOfFreedom c) 
    { 
      matrix[a][b].col = c;
537
    }
538
539
540
541
542

    /** \brief
     * Creates an entry with logical indices irow, icol if there is no entry
     * yet. Than sign * entry is added to the value at this logical indices
     */
543
544
545
    void addSparseDOFEntry(double sign,
			   int irow, int jcol, double entry,
			   bool add = true);
546
547

    inline double *hasSparseDOFEntry(int irow, int jcol) {
548
549
      std::vector<MatEntry>::iterator it;
      std::vector<MatEntry>::iterator end = matrix[irow].end();
550
551
552
553
554
555
556
      for (it = matrix[irow].begin(); it != end; ++it) {
	if (it->col == NO_MORE_ENTRIES) 
	  return NULL;
	if (it->col == jcol) 
	  return &(it->entry);
      };
      return NULL;
557
    }
558
559
560
561
562

    void addMatEntry(int row, MatEntry entry);

    void addMatEntry(int row, int DegreeOfFreedom, double value);

563
    void addRow(std::vector<MatEntry> row);
564

Thomas Witkowski's avatar
Thomas Witkowski committed
565
566
    void removeRowsWithDBC(std::set<int> *rows);

567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
    /** \brief
     * Prints \ref matrix to stdout
     */
    void print() const;

    /** \brief
     * Prints a row of \ref matrix to stdout
     */
    void printRow(int i) const;

    /** \brief
     * Removes all matrix entries
     */
    void clear();

    /** \brief
     * Test whether \ref matrix is symmetric. Exits if not.
     */
    void test();

    bool symmetric();

589
    inline std::vector<Operator*> getOperators() { 
590
      return operators; 
591
    }
592
    
593
    inline std::vector<double*> getOperatorFactor() { 
594
      return operatorFactor; 
595
    }
596

597
    inline std::vector<double*> getOperatorEstFactor() { 
598
      return operatorEstFactor; 
599
    }
600
601
602

    inline BoundaryManager* getBoundaryManager() const { 
      return boundaryManager; 
603
    }
604

Thomas Witkowski's avatar
Thomas Witkowski committed
605
606
607
608
    std::set<int>* getApplyDBCs() {
      return &applyDBCs;
    }

609
610
    inline void setBoundaryManager(BoundaryManager *bm) {
      boundaryManager = bm;
611
    }
612
613
614
615
616

    void createPictureFile(const char* filename, int dim);

    // ===== Serializable implementation =====
    
617
    void serialize(std::ostream &out) 
618
619
620
621
622
623
624
625
626
627
    {
      unsigned int matrixSize = matrix.size();
      unsigned int vecSize = 0;

      out.write(reinterpret_cast<const char*>(&matrixSize), sizeof(unsigned int));
      for(unsigned int i = 0; i < matrixSize; i++) {
	vecSize = matrix[i].size();
	out.write(reinterpret_cast<const char*>(&vecSize), sizeof(unsigned int));
	out.write(reinterpret_cast<const char*>(&(matrix[i][0])), vecSize * sizeof(MatEntry));
      }
628
    }
629

630
    void deserialize(std::istream &in) {
631
632
633
634
635
636
637
638
639
      unsigned int matrixSize, vecSize;

      in.read(reinterpret_cast<char*>(&matrixSize), sizeof(unsigned int));
      matrix.resize(matrixSize);
      for(unsigned int i = 0; i < matrixSize; i++) {
	in.read(reinterpret_cast<char*>(&vecSize), sizeof(unsigned int));
	matrix[i].resize(vecSize);
	in.read(reinterpret_cast<char*>(&(matrix[i][0])), vecSize * sizeof(MatEntry));
      }
640
    }
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665

    int memsize();

  protected:
    /** \brief
     * Used by updateMatrix
     */
    //static int assembleFct(ElInfo *el_info);

  protected:
    /** \brief
     * Pointer to a FiniteElemSpace with information about corresponding row DOFs
     * and basis functions
     */
    const FiniteElemSpace *rowFESpace;

    /** \brief
     * Pointer to a FiniteElemSpace with information about corresponding 
     * column DOFs and basis functions
     */
    const FiniteElemSpace *colFESpace;

    /** \brief
     * Name of the DOFMatrix
     */
666
    std::string name;
667
668
669
670

    /** \brief
     * Sparse matrix stored in an STL vector of MatrixRow objects
     */
671
    std::vector<MatrixRow> matrix;
672
673
674
675
676
677
678
679
680
681

    /** \brief
     * Used while mesh traversal
     */
    static DOFMatrix *traversePtr;
  
    /** \brief
     * Pointers to all operators of the equation systems. Are used in the
     * assembling process.
     */
682
    std::vector<Operator*> operators;
683
684
685
686
687
    
    /** \brief
     * Defines for each operator a factor which is used to scal the element
     * matrix after the assembling process of the operator.
     */
688
    std::vector<double*> operatorFactor;
689

690
691
692
    /** \brief
     *
     */
693
    std::vector<double*> operatorEstFactor;
694

695
696
697
    /** \brief
     *
     */
698
699
    BoundaryManager *boundaryManager;

700
701
702
    /** \brief
     *
     */
703
704
    bool coupleMatrix;

Thomas Witkowski's avatar
Thomas Witkowski committed
705
706
707
708
709
    /** \brief
     * Temporary variable used in assemble()
     */
    ElementMatrix *elementMatrix;

Thomas Witkowski's avatar
Thomas Witkowski committed
710
711
    std::set<int> applyDBCs;

712
713
714
715
716
717
718
719
720
721
722
723
724
    friend class DOFAdmin;
    friend class DOFVector<double>;
    friend class DOFVector<unsigned char>;
    friend class DOFVector<int>;
    friend class DOFVector<WorldVector<double> >;
  };


  inline DegreeOfFreedom logToPhysIndex(DOFMatrix *m, DegreeOfFreedom a, DegreeOfFreedom b)
  {
    return m->logToPhysIndex(a, b);
  }

725
  double norm(std::vector<MatEntry> *row);
726

727
  double min(std::vector<MatEntry> *row);
728

729
  double max(std::vector<MatEntry> *row);
730

Thomas Witkowski's avatar
Thomas Witkowski committed
731
732
733
  /** \brief
   * Addes two matrices. The result matrix is overwritten.
   */
734
735
  void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a, const DOFMatrix *b);

Thomas Witkowski's avatar
Thomas Witkowski committed
736
737
738
739
740
  /** \brief
   * Addes matrix a to matrix result.
   */
  void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a);

741
742
743
}

#endif  // AMDIS_DOFMATRIX_H