DOFMatrix.h 20.7 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

    /** \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
263
    inline bool entryUsed(DegreeOfFreedom a, int b) const {
264
      return (((matrix[a])[b]).col >= 0);
265
    }
266
267
268
269

    /** \brief
     * Returns true if matrix[a][b] has entry \ref NO_MORE_ENTRIES
     */
Thomas Witkowski's avatar
Thomas Witkowski committed
270
    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

    /** \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
297
    void axpy(double a, const DOFMatrix& x, const DOFMatrix& y);
298
299
300
301
302
303

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

Thomas Witkowski's avatar
Thomas Witkowski committed
304
305
306
307
308
309
    /** \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);
310

311
    inline std::vector<double*>::iterator getOperatorFactorBegin() {
312
      return operatorFactor.begin();
313
    }
314

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

319
    inline std::vector<double*>::iterator getOperatorEstFactorBegin() {
320
      return operatorEstFactor.begin();
321
    }
322

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

327
    inline std::vector<Operator*>::iterator getOperatorsBegin() {
328
      return operators.begin();
329
    }
330

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

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

362
363
    void assemble(double factor, ElInfo *elInfo, const BoundaryType *bound,
		  Operator *op);
364

365
366
367
    void assemble(double factor, 
		  ElInfo *rowElInfo, ElInfo *colElInfo,
		  ElInfo *smallElInfo, ElInfo *largeElInfo,
Thomas Witkowski's avatar
Thomas Witkowski committed
368
369
		  const BoundaryType *bound,
		  Operator *op = NULL);
370

Thomas Witkowski's avatar
Thomas Witkowski committed
371
372
373
374
375
376
377
    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
378
379
380
381
382
    void addElementMatrix(double sign, 
			  const ElementMatrix& elMat, 
			  const BoundaryType *bound,
			  bool add = true);

Thomas Witkowski's avatar
Thomas Witkowski committed
383
    /// Returns \ref matrix
384
    std::vector< std::vector<MatEntry> >& getMatrix() { 
385
      return matrix; 
386
    }
387

Thomas Witkowski's avatar
Thomas Witkowski committed
388
    ///
389
    void setMatrix(std::vector< std::vector<MatEntry> > m) {
390
      matrix = m;
391
    }
392

Thomas Witkowski's avatar
Thomas Witkowski committed
393
    /// Returns \ref matrix[n]
394
    const std::vector<MatEntry>& getRow(int n) const { 
395
      return matrix[n];
396
    }
397

Thomas Witkowski's avatar
Thomas Witkowski committed
398
    /// Returns \ref matrix[n]
399
    std::vector<MatEntry>& getRow(int n) { 
400
      return matrix[n];
401
    }
402
403
404
405
406
407
408

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

Thomas Witkowski's avatar
Thomas Witkowski committed
411
    /// Returns const \ref rowFESpace
412
413
    const FiniteElemSpace* getRowFESpace() const { 
      return rowFESpace; 
414
    }
415
416
417
418
419
420

    /** \brief
     * Returns const \ref colFESpace
     */
    const FiniteElemSpace* getColFESpace() const { 
      return colFESpace; 
421
    }
422
423
424
425
426
427

    /** \brief
     * Returns const \ref rowFESpace
     */
    const FiniteElemSpace* getFESpace() const { 
      return rowFESpace; 
428
    }
429
430
431
432
433
434

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

Thomas Witkowski's avatar
Thomas Witkowski committed
437
438
439
440
441
442
    /** \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();
443
    }
Thomas Witkowski's avatar
Thomas Witkowski committed
444

445
446
447
448
    /** \brief
     * Returns number of cols. For that, the function iteratos over all
     * rows and searchs for the entry with the highest col number.
     */
449
    int getNumCols() const;
450

451
452
453
    /** \brief
     * Returns \ref name
     */
454
    inline const std::string& getName() const { 
455
      return name; 
456
    }
457
458
459
460
461

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

    /** \brief
     * 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
476
477

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

    /** \brief
     * Access to \ref matrix[a][b].entry
     */
487
    inline double physAcc(DegreeOfFreedom a, DegreeOfFreedom b) const { 
488
      return matrix[a][b].entry; 
489
    }
490
491
492
493
494
495
496
497

    /** \brief
     * Access to \ref matrix[a][b].col
     */
    inline DegreeOfFreedom physToLogIndex(DegreeOfFreedom a,
					  DegreeOfFreedom b) const 
    {
      return matrix[a][b].col;
498
    }
499
500
501
502

    /** \brief
     * Returns physical column index of logical index b in row a
     */
503
504
505
506
507
508
509
510
    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;
511
    }
512
513
514
515

    /** \brief
     * Returns value at logical indices a,b
     */
516
    double logAcc(DegreeOfFreedom a, DegreeOfFreedom b) const;
517
518
519
520

    /** \brief
     * Changes col at logical indices a,b to c 
     */
521
    void changeColOfEntry(DegreeOfFreedom a, DegreeOfFreedom b, DegreeOfFreedom c);
522
523
524
525
526
527
528
529
530

    /** \brief
     * Changes col of \ref matrix[a][b] to c
     */
    inline void changePhysColOfEntry(DegreeOfFreedom a,
				     DegreeOfFreedom b,
				     DegreeOfFreedom c) 
    { 
      matrix[a][b].col = c;
531
    }
532
533
534
535
536

    /** \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
     */
537
538
539
    void addSparseDOFEntry(double sign,
			   int irow, int jcol, double entry,
			   bool add = true);
540
541

    inline double *hasSparseDOFEntry(int irow, int jcol) {
542
543
      std::vector<MatEntry>::iterator it;
      std::vector<MatEntry>::iterator end = matrix[irow].end();
544
545
546
547
548
      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
549
      }
550
      return NULL;
551
    }
552
553
554
555
556

    void addMatEntry(int row, MatEntry entry);

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

557
    void addRow(std::vector<MatEntry> row);
558

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

561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
    /** \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();

583
    inline std::vector<Operator*> getOperators() { 
584
      return operators; 
585
    }
586
    
587
    inline std::vector<double*> getOperatorFactor() { 
588
      return operatorFactor; 
589
    }
590

591
    inline std::vector<double*> getOperatorEstFactor() { 
592
      return operatorEstFactor; 
593
    }
594
595
596

    inline BoundaryManager* getBoundaryManager() const { 
      return boundaryManager; 
597
    }
598

Thomas Witkowski's avatar
Thomas Witkowski committed
599
600
601
602
    std::set<int>* getApplyDBCs() {
      return &applyDBCs;
    }

603
604
    inline void setBoundaryManager(BoundaryManager *bm) {
      boundaryManager = bm;
605
    }
606
607
608
609
610

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

    // ===== Serializable implementation =====
    
611
    void serialize(std::ostream &out) 
612
613
614
615
616
617
618
619
620
621
    {
      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));
      }
622
    }
623

624
    void deserialize(std::istream &in) {
625
626
627
628
629
630
631
632
633
      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));
      }
634
    }
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659

    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
     */
660
    std::string name;
661
662
663
664

    /** \brief
     * Sparse matrix stored in an STL vector of MatrixRow objects
     */
665
    std::vector<MatrixRow> matrix;
666
667
668
669
670
671
672
673
674
675

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

684
685
686
    /** \brief
     *
     */
687
    std::vector<double*> operatorEstFactor;
688

689
690
691
    /** \brief
     *
     */
692
693
    BoundaryManager *boundaryManager;

694
695
696
    /** \brief
     *
     */
697
698
    bool coupleMatrix;

Thomas Witkowski's avatar
Thomas Witkowski committed
699
700
701
702
703
    /** \brief
     * Temporary variable used in assemble()
     */
    ElementMatrix *elementMatrix;

Thomas Witkowski's avatar
Thomas Witkowski committed
704
705
    std::set<int> applyDBCs;

706
707
708
709
710
711
712
713
714
715
716
717
718
    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);
  }

719
  double norm(std::vector<MatEntry> *row);
720

721
  double min(std::vector<MatEntry> *row);
722

723
  double max(std::vector<MatEntry> *row);
724

Thomas Witkowski's avatar
Thomas Witkowski committed
725
726
727
  /** \brief
   * Addes two matrices. The result matrix is overwritten.
   */
728
729
  void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a, const DOFMatrix *b);

Thomas Witkowski's avatar
Thomas Witkowski committed
730
731
732
733
734
  /** \brief
   * Addes matrix a to matrix result.
   */
  void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a);

735
736
737
}

#endif  // AMDIS_DOFMATRIX_H