DOFMatrix.h 20.6 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
#include <memory>
#include <list>
33

34
35
36
37
38
39
40
41
42
43
#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"

44
45
46
47
#ifdef HAVE_PARALLEL_AMDIS
#include "petscao.h"
#endif

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
85
86
87
88
89
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.
   */
90
  class MatEntryValueLess : public std::unary_function<MatEntry, bool> {
91
92
93
94
95
  private:
    const double value_;
  public:
    MatEntryValueLess(const double& value) 
      : value_(value) 
96
    {}
97
98
99

    bool operator()(const MatEntry& m) {
      return (fabs(m.entry) < value_);
100
    }      
101
102
103
104
105
106
107
  };


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

    bool operator()(const MatEntry& m) {
      return (fabs(m.col) < col_);
118
    }      
119
120
121
122
123
124
125
  };


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

  /** \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.
   */
137
  struct CmpMatEntryValue : public std::binary_function<MatEntry, MatEntry, bool> {
138
139
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return m1.entry < m2.entry;
140
    }
141
142
143
144
145
146
147
  };


  /** \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.
   */
148
  struct CmpMatEntryAbsValueLess : public std::binary_function<MatEntry, MatEntry, bool> {
149
150
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return fabs(m1.entry) < fabs(m2.entry);
151
    }
152
153
154
155
156
157
  };
  
  /** \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.
   */
158
  struct CmpMatEntryAbsValueGreater : public std::binary_function<MatEntry, MatEntry, bool> {
159
160
    bool operator()(const MatEntry& m1, const MatEntry m2) const {
      return fabs(m1.entry) > fabs(m2.entry);
161
    }
162
163
164
165
166
167
168
169
170
171
172
173
174
  };

  // ============================================================================
  // ===== 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.
   */
175
  class DOFMatrix : public DOFIndexed< std::vector<MatEntry> >,
176
177
178
179
180
181
182
                    public Serializable
  {
  public:
    MEMORY_MANAGED(DOFMatrix);

    /** \ingroup DOFAdministration
     * \brief
183
     * Alias for DOFIterator< std::vector<MatEntry<T> > >. So one can access an
184
185
     * iterator working on a DOFMatrix via DOFMatrix::Iterator
     */
186
    class Iterator : public DOFIterator< std::vector<MatEntry> > {
187
    public:
188
      Iterator(DOFIndexed< std::vector<MatEntry> > *c, 
189
	       DOFIteratorType type)
190
	: DOFIterator< std::vector<MatEntry> >(c, type)
191
      {}
192
193
194
195
196
197
    };
    
    /** \brief
     * A MatrixRow represents one row of the sparse matrix. It is realized by
     * a STL vector of MatEntry<T> objects
     */
198
    typedef std::vector<MatEntry> MatrixRow;
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
    
    /** \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
220
	      std::string n = "");
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

    /** \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())
     */
243
    std::vector< std::vector<MatEntry> >::iterator begin() { 
244
      return matrix.begin();
245
    }
246
247
248
249

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

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

    /** \brief
     * Returns whether entry matrix[a][b] is used
     */    
Thomas Witkowski's avatar
Thomas Witkowski committed
268
    inline bool entryUsed(DegreeOfFreedom a, int b) const {
269
      return (((matrix[a])[b]).col >= 0);
270
    }
271
272
273
274

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

    /** \brief
     * Returns \ref coupleMatrix.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
282
283
    inline bool isCoupleMatrix() { 
      return coupleMatrix; 
284
    }
285
286
287
288

    /** \brief
     * Returns \ref coupleMatrix.
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
289
290
    inline void setCoupleMatrix(bool c) { 
      coupleMatrix = c; 
291
    }
292
293
294
295
296
297
298
299
300
301

    /** \brief
     * Matrix-matrix multiplication.
     */
    void mm(MatrixTranspose aTranspose, DOFMatrix& a, 
	    MatrixTranspose bTranspose, DOFMatrix& b);
  
    /** \brief
     * a*x + y
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
302
    void axpy(double a, const DOFMatrix& x, const DOFMatrix& y);
303
304
305
306
307
308

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

Thomas Witkowski's avatar
Thomas Witkowski committed
309
310
311
312
313
314
    /** \brief
     * Adds an operator to the DOFMatrix. A factor, that is multipled
     * to the operator, and a multilier factor for the estimator may be
     * also given.
     */
    void addOperator(Operator *op, double* factor = NULL, double* estFactor = NULL);
315

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

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

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

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

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

336
    inline std::vector<Operator*>::iterator getOperatorsEnd() {
337
      return operators.end();
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
364

    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().
     */
  
365
    void assemble(double factor, ElInfo *elInfo, const BoundaryType *bound);
366

367
368
    void assemble(double factor, ElInfo *elInfo, const BoundaryType *bound,
		  Operator *op);
369

370
371
372
    void assemble(double factor, 
		  ElInfo *rowElInfo, ElInfo *colElInfo,
		  ElInfo *smallElInfo, ElInfo *largeElInfo,
Thomas Witkowski's avatar
Thomas Witkowski committed
373
374
		  const BoundaryType *bound,
		  Operator *op = NULL);
375

Thomas Witkowski's avatar
Thomas Witkowski committed
376
377
378
379
380
381
382
    void assemble2(double factor, 
		   ElInfo *mainElInfo, ElInfo *auxElInfo,
		   ElInfo *smallElInfo, ElInfo *largeElInfo,
		   const BoundaryType *bound, 
		   Operator *op = NULL);

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

Thomas Witkowski's avatar
Thomas Witkowski committed
388
389
390
391
392
393
394
    /* \brief
     * That function must be called after the matrix assembling has been finished. 
     * This makes it possible to start some cleanup or matrix data compressing 
     * procedures.
     */
    void finishAssembling();

Thomas Witkowski's avatar
Thomas Witkowski committed
395
    /// Returns \ref matrix
396
    std::vector< std::vector<MatEntry> >& getMatrix() { 
397
      return matrix; 
398
    }
399

Thomas Witkowski's avatar
Thomas Witkowski committed
400
    ///
401
    void setMatrix(std::vector< std::vector<MatEntry> > m) {
402
      matrix = m;
403
    }
404

Thomas Witkowski's avatar
Thomas Witkowski committed
405
    /// Returns \ref matrix[n]
406
    const std::vector<MatEntry>& getRow(int n) const { 
407
      return matrix[n];
408
    }
409

Thomas Witkowski's avatar
Thomas Witkowski committed
410
    /// Returns \ref matrix[n]
411
    std::vector<MatEntry>& getRow(int n) { 
412
      return matrix[n];
413
    }
414
415
416
417
418
419
420

    /** \brief
     * Returns whether restriction should be performed after coarsening
     * (false by default)
     */
    virtual bool coarseRestrict() {
      return false;
421
    }
422

Thomas Witkowski's avatar
Thomas Witkowski committed
423
    /// Returns const \ref rowFESpace
424
425
    const FiniteElemSpace* getRowFESpace() const { 
      return rowFESpace; 
426
    }
427

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

433
    /// Returns const \ref rowFESpace
434
435
    const FiniteElemSpace* getFESpace() const { 
      return rowFESpace; 
436
    }
437

438
    /// Returns number of rows (\ref matrix.size())
439
440
    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
    /// Returns \ref name
458
    inline const std::string& getName() const { 
459
      return name; 
460
    }
461

462
    /// Resizes \ref matrix to n rows
463
    inline void resize(int n) { 
464
      TEST_EXIT_DBG(n >= 0)("Can't resize DOFMatrix to negative size\n"); 
465
      matrix.resize(n);
466
    }
467

468
    /// Returns \ref matrix[i] which is the i-th row
469
    inline const std::vector<MatEntry>& operator[](int i) const {
470
471
      TEST_EXIT_DBG((i >= 0) && (i < (static_cast<int>(matrix.size()))))
      	("Illegal matrix index %d.\n",i); 
472
      return matrix[i];
473
    }
474

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

482
    /// Access to \ref matrix[a][b].entry
483
    inline double physAcc(DegreeOfFreedom a, DegreeOfFreedom b) const { 
484
      return matrix[a][b].entry; 
485
    }
486

487
    /// Access to \ref matrix[a][b].col
488
489
490
491
    inline DegreeOfFreedom physToLogIndex(DegreeOfFreedom a,
					  DegreeOfFreedom b) const 
    {
      return matrix[a][b].col;
492
    }
493

494
    /// Returns physical column index of logical index b in row a
495
496
497
498
499
500
501
502
    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;
503
    }
504

505
    /// Returns value at logical indices a,b
506
    double logAcc(DegreeOfFreedom a, DegreeOfFreedom b) const;
507

508
    /// Changes col at logical indices a,b to c 
509
    void changeColOfEntry(DegreeOfFreedom a, DegreeOfFreedom b, DegreeOfFreedom c);
510

511
    /// Changes col of \ref matrix[a][b] to c
512
513
514
515
516
    inline void changePhysColOfEntry(DegreeOfFreedom a,
				     DegreeOfFreedom b,
				     DegreeOfFreedom c) 
    { 
      matrix[a][b].col = c;
517
    }
518
519
520
521
522

    /** \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
     */
523
524
525
    void addSparseDOFEntry(double sign,
			   int irow, int jcol, double entry,
			   bool add = true);
526
527

    inline double *hasSparseDOFEntry(int irow, int jcol) {
528
529
      std::vector<MatEntry>::iterator it;
      std::vector<MatEntry>::iterator end = matrix[irow].end();
530
531
532
533
534
      for (it = matrix[irow].begin(); it != end; ++it) {
	if (it->col == NO_MORE_ENTRIES) 
	  return NULL;
	if (it->col == jcol) 
	  return &(it->entry);
Thomas Witkowski's avatar
Thomas Witkowski committed
535
      }
536
      return NULL;
537
    }
538
539
540
541
542

    void addMatEntry(int row, MatEntry entry);

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

543
    void addRow(std::vector<MatEntry> row);
544

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

547
    /// Prints \ref matrix to stdout
548
549
    void print() const;

550
    /// Prints a row of \ref matrix to stdout
551
552
    void printRow(int i) const;

553
    /// Removes all matrix entries
554
555
    void clear();

556
    /// Test whether \ref matrix is symmetric. Exits if not.
557
558
559
560
    void test();

    bool symmetric();

561
    inline std::vector<Operator*> getOperators() { 
562
      return operators; 
563
    }
564
    
565
    inline std::vector<double*> getOperatorFactor() { 
566
      return operatorFactor; 
567
    }
568

569
    inline std::vector<double*> getOperatorEstFactor() { 
570
      return operatorEstFactor; 
571
    }
572
573
574

    inline BoundaryManager* getBoundaryManager() const { 
      return boundaryManager; 
575
    }
576

Thomas Witkowski's avatar
Thomas Witkowski committed
577
578
579
580
    std::set<int>* getApplyDBCs() {
      return &applyDBCs;
    }

581
582
    inline void setBoundaryManager(BoundaryManager *bm) {
      boundaryManager = bm;
583
    }
584
585

    void createPictureFile(const char* filename, int dim);
586
   
587
    void serialize(std::ostream &out) 
588
589
590
591
592
593
594
595
596
597
    {
      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));
      }
598
    }
599

600
    void deserialize(std::istream &in) {
601
602
603
604
605
606
607
608
609
      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));
      }
610
    }
611

612
    ///
613
614
    int memsize();

615
616
617
618
619
620
#ifdef HAVE_PARALLEL_AMDIS
    /// Sets the petsc application ordering object to map dof indices.
    void useApplicationOrdering(AO *ao) {
      applicationOrdering = ao;
    }
#endif
621
622
623
624
625
626
627
628
629
630
631
632
633
634

  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;

635
    /// Name of the DOFMatrix
636
    std::string name;
637

638
    /// Sparse matrix stored in an STL vector of MatrixRow objects
639
    std::vector<MatrixRow> matrix;
640

641
    /// Used while mesh traversal
642
643
644
645
646
647
    static DOFMatrix *traversePtr;
  
    /** \brief
     * Pointers to all operators of the equation systems. Are used in the
     * assembling process.
     */
648
    std::vector<Operator*> operators;
649
650
651
652
653
    
    /** \brief
     * Defines for each operator a factor which is used to scal the element
     * matrix after the assembling process of the operator.
     */
654
    std::vector<double*> operatorFactor;
655

656
    ///
657
    std::vector<double*> operatorEstFactor;
658

659
    ///
660
661
    BoundaryManager *boundaryManager;

662
    ///
663
664
    bool coupleMatrix;

665
    /// Temporary variable used in assemble()
Thomas Witkowski's avatar
Thomas Witkowski committed
666
667
    ElementMatrix *elementMatrix;

668
    ///
Thomas Witkowski's avatar
Thomas Witkowski committed
669
670
    std::set<int> applyDBCs;

671
672
673
674
675
#ifdef HAVE_PARALLEL_AMDIS
    /// Petsc application ordering to map dof indices.
    AO *applicationOrdering;
#endif

676
677
678
679
680
681
682
683
    friend class DOFAdmin;
    friend class DOFVector<double>;
    friend class DOFVector<unsigned char>;
    friend class DOFVector<int>;
    friend class DOFVector<WorldVector<double> >;
  };


684
685
  inline DegreeOfFreedom logToPhysIndex(DOFMatrix *m, 
					DegreeOfFreedom a, DegreeOfFreedom b) 
686
687
688
689
  {
    return m->logToPhysIndex(a, b);
  }

690
  double norm(std::vector<MatEntry> *row);
691

692
  double min(std::vector<MatEntry> *row);
693

694
  double max(std::vector<MatEntry> *row);
695

696
  /// Addes two matrices. The result matrix is overwritten.
697
698
  void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a, const DOFMatrix *b);

699
  /// Addes matrix a to matrix result.
Thomas Witkowski's avatar
Thomas Witkowski committed
700
  void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a);
701
702
703
}

#endif  // AMDIS_DOFMATRIX_H