Geophysical Inversion and Modelling Library v1.5.4
Loading...
Searching...
No Matches
sparsematrix.h
1/******************************************************************************
2 * Copyright (C) 2006-2024 by the GIMLi development team *
3 * Carsten Rücker carsten@resistivity.net *
4 * *
5 * Licensed under the Apache License, Version 2.0 (the "License"); *
6 * you may not use this file except in compliance with the License. *
7 * You may obtain a copy of the License at *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
14 * See the License for the specific language governing permissions and *
15 * limitations under the License. *
16 * *
17 ******************************************************************************/
18
19#ifndef GIMLI_SPARSEMATRIX__H
20#define GIMLI_SPARSEMATRIX__H
21
22#include "gimli.h"
23#include "elementmatrix.h"
24#include "vector.h"
25#include "vectortemplates.h"
26#include "matrix.h"
27#include "mesh.h"
28#include "meshentities.h"
29#include "node.h"
30#include "stopwatch.h"
31
32#include <map>
33#include <set>
34#include <vector>
35#include <algorithm>
36#include <cassert>
37#include <iostream>
38#include <cmath>
39
40namespace GIMLI{
41
42#define SPARSE_NOT_VALID throwError(WHERE_AM_I + " no data/or sparsity pattern defined.");
43
45template< class ValueType, class IndexType, class ContainerType > class MatrixElement {
46public:
47 typedef std::pair< IndexType, IndexType > IndexPair;
48 typedef MatrixElement< ValueType, IndexType, ContainerType > & Reference;
49
50 MatrixElement(ContainerType & Cont, IndexType r, IndexType c)
51 : C(Cont), I(C.find(IndexPair(r, c))), row(r), column(c) {
52 }
53
54 /* An assignment operator is required which in turn requires a
55 reference to an object of type MatrixElement. When both the
56 left- and right-hand side are identical, nothing has to happen.
57 Otherwise, as above, it has to be checked whether the value of
58 the right-hand element is 0 or not. The resulting behavior is
59 described together with the above assignment operator, so that
60 here it is simply called: */
61
62 Reference operator = (Reference rhs) {
63 if (this != & rhs) { // not identical?
64 return operator = (rhs.asValue()); // see above
65 } return *this;
66 }
67
68 /* The constructor initializes the private variables with all
69 information that is needed. The container itself is located in
70 the sparseMatrix class; here, the reference to it is entered.
71 If the passed indices for row and column belong to an element
72 not yet stored in the container, the iterator has the value
73 C.end(). */
74
75 ValueType asValue() const {
76 if (I == C.end()) return ValueType(0); else return (*I).second;
77 }
78
79 //** type conversion operator;
80 operator ValueType () const { return asValue(); }
81
82 /* According to the definition of the sparse matrix, 0 is returned
83 if the element is not present in the container. Otherwise, the
84 result is the second part of the object of type value_type
85 stored in the container. */
86
87 Reference operator = (const ValueType & x) {
88 // not equal 0?
89 if (x != ValueType(0) || 1) { // we need the element to force some sought matrix shape
90 /* If the element does not yet exist, it is put, together
91 with the indices, into an object of type value_type and
92 inserted with insert(): */
93
94 if (I == C.end()) {
95 assert(C.size() < C.max_size());
96 I = (C.insert(typename ContainerType::value_type(IndexPair(row, column), x))).first;
97 } else (*I).second = x;
98 }
99
100 /* insert() returns a pair whose first part is an iterator
101 pointing to the inserted object. The second part is of type
102 bool and indicates whether the insertion took place because
103 no element with this key existed. This is, however, not
104 evaluated here because, due to the precondition (I ==
105 C.end()), the second part must always have the value true.
106 If, instead, the element already exists, the value is
107 entered into the second part of the value_type object. If
108 the value is equal 0, in order to save space the element is
109 deleted if it existed. */
110
111 else { // x = 0
112 if (I != C.end()) {
113 C.erase(I);
114 I = C.end();
115 }
116 } return *this;
117 }
118
119 Reference operator += (const ValueType & x) {
120 if (x != ValueType(0) || 1 ) { // we need the element to force some sought matrix shape
121 if (I == C.end()) {
122 assert(C.size() < C.max_size());
123 I = (C.insert(typename ContainerType::value_type(IndexPair(row, column), x))).first;
124 } else (*I).second += x;
125 }
126 return *this;
127 }
128
129 Reference operator -= (const ValueType & x) {
130 if (x != ValueType(0) || 1) {
131 if (I == C.end()) {
132 assert(C.size() < C.max_size());
133 I = (C.insert(typename ContainerType::value_type(IndexPair(row, column), -x))).first;
134 } else (*I).second -= x;
135 }
136 return *this;
137 }
138
139private:
140 ContainerType & C;
141 typename ContainerType::iterator I;
142 IndexType row, column;
143
144}; // class MatrixElement
145
146
148template< class ValueType, class IndexType >
150public:
151 typedef std::pair< IndexType, IndexType > IndexPair;
152 typedef std::map< IndexPair, ValueType, std::less< IndexPair > > ContainerType;
153 typedef typename ContainerType::iterator iterator;
154 typedef typename ContainerType::const_iterator const_iterator;
156
158 SparseMapMatrix(IndexType r=0, IndexType c=0, int stype=0)
159 : MatrixBase(), rows_(r), cols_(c), stype_(stype) {
160 }
161
162 SparseMapMatrix(const std::string & filename)
163 : MatrixBase(), rows_(0), cols_(0), stype_(0) {
164 this->load(filename);
165 }
166
168 : MatrixBase(){
169 clear();
170 cols_ = S.cols();
171 rows_ = S.rows();
172 stype_ = S.stype();
173
174 for (const_iterator it = S.begin(); it != S.end(); it ++){
175 this->setVal(it->first.first, it->first.second, it->second);
176 }
177 }
178 SparseMapMatrix(const SparseMatrix< ValueType > & S)
179 : MatrixBase(){
180 this->copy_(S);
181 }
182
185 SparseMapMatrix(const IndexArray & i, const IndexArray & j, const RVector & v)
186 : MatrixBase(){
187 ASSERT_EQUAL(i.size(), j.size())
188 ASSERT_EQUAL(i.size(), v.size())
189 stype_ = 0;
190 cols_ = max(j)+1;
191 rows_ = max(i)+1;
192 for (Index n = 0; n < i.size(); n ++ ) (*this)[i[n]][j[n]] = v[n];
193 }
194
196 if (this != &S){
197 clear();
198 cols_ = S.cols();
199 rows_ = S.rows();
200 stype_ = S.stype();
201 for (const_iterator it = S.begin(); it != S.end(); it ++){
202 this->setVal(it->first.first, it->first.second, it->second);
203 }
204 } return *this;
205 }
206
207 SparseMapMatrix & operator = (const SparseMatrix< ValueType > & S){
208 this->copy_(S);
209 return *this;
210 }
211
212 virtual ~SparseMapMatrix() {}
213
215 virtual uint rtti() const { return GIMLI_SPARSE_MAP_MATRIX_RTTI; }
216
217 void resize(Index rows, Index cols){
218 rows_ = rows;
219 cols_ = cols;
220 }
221
222 void copy_(const SparseMatrix< double > & S);
223 void copy_(const SparseMatrix< Complex > & S);
224
226 inline void add(const IndexArray & rows, const IndexArray & cols,
227 const RVector & vals) {
228 ASSERT_EQUAL(vals.size(), rows.size())
229 ASSERT_EQUAL(vals.size(), cols.size())
230
231 for (Index i = 0; i < vals.size(); i ++){
232 (*this)[rows[i]][cols[i]] += vals[i];
233 }
234 }
235
236 virtual void clear() {
237 C_.clear();
238 cols_ = 0; rows_ = 0; stype_ = 0;
239 }
240
241 void cleanRow(IndexType row){
242 ASSERT_RANGE(row, 0, this->rows())
243
244 for (auto it = begin(); it != end();){
245 if (idx1(it) == row){
246 it = C_.erase(it);
247 } else {
248 ++it;
249 }
250 }
251 }
252
253 void cleanCol(IndexType col){
254 ASSERT_RANGE(col, 0, this->cols())
255 for (auto it = begin(); it != end();){
256 if (idx2(it) == col){
257 it = C_.erase(it);
258 } else {
259 ++it;
260 }
261 }
262 }
263
265 inline int stype() const {return stype_;}
266
267 inline void setRows(IndexType r) { rows_ = r ; }
268 virtual IndexType rows() const { return rows_; }
269 virtual IndexType nRows() const { return rows_; }
270
271 inline void setCols(IndexType c) { cols_ = c ; }
272 virtual IndexType cols() const { return cols_; }
273 virtual IndexType nCols() const { return cols_; }
274
275 inline IndexType size() const { return C_.size(); }
276 inline IndexType max_size() const { return C_.max_size(); }
277 inline IndexType nVals() const { return C_.size(); }
278
279 inline iterator begin() { return C_.begin(); }
280 inline iterator end() { return C_.end(); }
281
282 inline const_iterator begin() const { return C_.begin(); }
283 inline const_iterator end() const { return C_.end(); }
284
286 void add(const ElementMatrix < double > & A, ValueType scale=1.0);
287 void add(const ElementMatrix < double > & A, const Pos & scale);
288 void add(const ElementMatrix < double > & A, const Matrix< ValueType> & scale);
290 void add(const ElementMatrix < double > & A,
291 const Vector < ValueType > & scale);
292
293 void addToCol(Index id, const ElementMatrix < double > & A,
294 ValueType scale=1.0, bool isDiag=false);
295 void addToRow(Index id, const ElementMatrix < double > & A,
296 ValueType scale=1.0, bool isDiag=false);
297
298#define DEFINE_SPARSEMAPMATRIX_UNARY_MOD_OPERATOR__(OP) \
299 SparseMapMatrix< ValueType, IndexType > & operator OP##= (const ValueType & v){\
300 for (iterator it = begin(); it != end(); it ++) (*it).second OP##= v; \
301 return *this; \
302 } \
303
304 DEFINE_SPARSEMAPMATRIX_UNARY_MOD_OPERATOR__(+)
305 DEFINE_SPARSEMAPMATRIX_UNARY_MOD_OPERATOR__(-)
306 DEFINE_SPARSEMAPMATRIX_UNARY_MOD_OPERATOR__(*)
307 DEFINE_SPARSEMAPMATRIX_UNARY_MOD_OPERATOR__(/)
308
309#undef DEFINE_SPARSEMMAPATRIX_UNARY_MOD_OPERATOR__
310
312 for (const_iterator it = A.begin(); it != A.end(); it ++){
313 this->addVal(it->first.first, it->first.second, it->second);
314 }
315 return *this;
316 }
318 for (const_iterator it = A.begin(); it != A.end(); it ++){
319 this->addVal(it->first.first, it->first.second, -it->second);
320 }
321 return *this;
322 }
323
324 //SparseMatrix< T > & operator += (const ElementMatrix < T > & A){
325 void operator += (const ElementMatrix < double > & A){
326 for (Index i = 0, imax = A.size(); i < imax; i++){
327 for (Index j = 0, jmax = A.size(); j < jmax; j++){
328 (*this)[A.idx(i)][A.idx(j)] += A.getVal(i, j);
329 }
330 }
331 }
332
333 class Aux { // for index operator below
334 public:
335 Aux(IndexType r, IndexType maxs, ContainerType & Cont, int stype)
336 : Row(r), maxColumns(maxs), C(Cont), stype_(stype) { }
337
338 MatElement operator [] (IndexType c) {
339// __MS( stype_ << " " << c << " " << Row )
340 if ((c < 0 || c >= maxColumns) || (stype_ < 0 && c < Row) || (stype_ > 0 && c > Row)) {
341 throwLengthError(
342 WHERE_AM_I + " idx = " + str(c) + ", " + str(Row) + " maxcol = "
343 + str(maxColumns) + " stype: " + str(stype_));
344 }
345 return MatElement(C, Row, c);
346 }
347 protected:
348 IndexType Row, maxColumns;
349 ContainerType & C;
350 int stype_;
351 };
352
353 Aux operator [] (IndexType r) {
354 if (r < 0 || r >= rows_){
355 throwLengthError(
356 WHERE_AM_I + " idx = " + str(r) + " maxrow = "
357 + str(rows_));
358 }
359 return Aux(r, cols(), C_, stype_);
360 }
361
362 inline IndexType idx1(const const_iterator & I) const { return (*I).first.first; }
363 inline IndexType idx2(const const_iterator & I) const { return (*I).first.second; }
364
365// inline IndexType idx1(iterator & I) { return (*I).first.first; }
366// inline IndexType idx2(iterator & I) { return (*I).first.second; }
367
368 inline const ValueType & val(const const_iterator & I) const { return (*I).second; }
369
370 inline ValueType & val(const iterator & I) { return (*I).second; }
371
372 inline Vector< ValueType > values() const {
373 Vector< ValueType > ret(C_.size());
374 Index i = 0;
375 for (const_iterator it = this->begin(); it != this->end(); it ++, i ++){
376 ret[i] = val(it);
377 }
378 return ret;
379 }
380
381 inline ValueType getVal(IndexType i, IndexType j) { return (*this)[i][j]; }
382
383 inline void setVal(IndexType i, IndexType j, const ValueType & val) {
384 if ((stype_ < 0 && i > j) || (stype_ > 0 && i < j)) return;
385
386 if (i >= rows_) rows_ = i+1;
387 if (j >= cols_) cols_ = j+1;
388 (*this)[i][j] = val;
389 // if ((i >= 0 && i < rows_) && (j >=0 && j < cols_)) {
390 // } else {
391 // throwLengthError(
392 // WHERE_AM_I +
393 // " i = " + str(i) + " max_row = " + str(rows_) +
394 // " j = " + str(j) + " max_col = " + str(cols_)
395 // );
396 // }
397 }
398 inline void addVal(IndexType i, IndexType j, const ValueType & val) {
399 if ((stype_ < 0 && i > j) || (stype_ > 0 && i < j)) return;
400 if (i >= rows_) rows_ = i+1;
401 if (j >= cols_) cols_ = j+1;
402 (*this)[i][j] += val;
403
404 // if ((i >= 0 && i < rows_) && (j >=0 && j < cols_)) {
405 // (*this)[i][j] += val;
406 // } else {
407 // throwLengthError(
408 // WHERE_AM_I +
409 // " i = " + str(i) + " max_row = " + str(rows_) +
410 // " j = " + str(j) + " max_col = " + str(cols_)
411 // );
412 // }
413 }
414
415
417 virtual Vector < ValueType > mult(const Vector < ValueType > & a) const {
418 Vector < ValueType > ret(this->rows(), 0.0);
419
420 ASSERT_EQUAL(this->cols(), a.size())
421
422 if (stype_ == 0){
423 for (const_iterator it = this->begin(); it != this->end(); it ++){
424 ret[it->first.first] += a[it->first.second] * it->second;
425 }
426 } else if (stype_ == -1){
427
428 for (const_iterator it = this->begin(); it != this->end(); it ++){
429 IndexType I = it->first.first;
430 IndexType J = it->first.second;
431
432 ret[I] += a[J] * conj(it->second);
433
434 if (J > I){
435 ret[J] += a[I] * it->second;
436 }
437 }
438 } else if (stype_ == 1){
439 for (const_iterator it = this->begin(); it != this->end(); it ++){
440 IndexType I = it->first.first;
441 IndexType J = it->first.second;
442
443 ret[I] += a[J] * conj(it->second);
444
445 if (J < I){
446 ret[J] += a[I] * it->second;
447 }
448 }
449
450 }
451 return ret;
452 }
453
455 virtual Vector < ValueType > transMult(const Vector < ValueType > & a) const {
456 Vector < ValueType > ret(this->cols(), 0.0);
457
458 ASSERT_EQUAL(this->rows(), a.size())
459
460 if (stype_ == 0){
461 for (const_iterator it = this->begin(); it != this->end(); it ++){
462 ret[it->first.second] += a[it->first.first] * it->second;
463 }
464 } else if (stype_ == -1){
465 THROW_TO_IMPL
466 } else if (stype_ == 1){
467 THROW_TO_IMPL
468 }
469 return ret;
470 }
471
472 virtual Vector < ValueType > col(const Index i) {
473 Vector < ValueType > null(this->cols(), 0.0);
474 null[i] = 1.0;
475
476 return this->mult(null);
477 }
478
479 virtual Vector < ValueType > row(const Index i) {
480 Vector < ValueType > null(this->rows(), 0.0);
481 null[i] = 1.0;
482
483 return this->transMult(null);
484 }
485
486 void save(const std::string & filename) const {
487 std::fstream file; openOutFile(filename, &file);
488
489 for (const_iterator it = begin(); it != end(); it ++){
490 file << idx1(it) << " " << idx2(it) << " " << val(it) << std::endl;
491 }
492
493 file.close();
494 }
495
496 void load(const std::string & filename){
497 std::fstream file; openInFile(filename, &file);
498 std::vector < IndexType > vi, vj;
499 std::vector < ValueType > vval;
500 IndexType i, j;
501 ValueType val;
502 while (file >> i >> j >> val){
503 vi.push_back(i);
504 vj.push_back(j);
505 vval.push_back(val);
506 }
507 file.close();
508 setRows(IndexType(max(vi) + 1));
509 setCols(IndexType(max(vj) + 1));
510
511 for (Index i = 0; i < vi.size(); i ++){
512 (*this)[vi[i]][vj[i]] = vval[i];
513 }
514 }
515
517 void importCol(const std::string & filename, double dropTol, Index colOffset){
518 //std::cout << "rows: " << Jcluster.rows() << " cols: " << Jcluster.cols()<< std::endl;
519
520 FILE *file; file = fopen(filename.c_str(), "r+b");
521 if (!file) {
522 throwError(WHERE_AM_I + " " + filename + ": " + strerror(errno));
523 }
524 Index ret = 0;
525
526
527 uint32 rows = 0;
528 ret = fread(&rows, sizeof(uint32), 1, file);
529 if (ret == 0) throwError("fail reading file " + filename);
530 uint32 cols = 0;
531 ret = fread(&cols, sizeof(uint32), 1, file);
532 if (ret == 0) throwError("fail reading file " + filename);
533 ValueType val;
534 for (uint i = 0; i < rows; i ++){
535 for (uint j = 0; j < cols; j ++){
536 ret = fread(&val, sizeof(ValueType), 1, file);
537 if (ret == 0) throwError("fail reading file " + filename);
538 if (abs(val) > dropTol) this->setVal(i, j + colOffset, val);
539 }
540 }
541
542 fclose(file);
543 }
544 // no default arg here .. pygimli@win64 linker bug
545 void importCol(const std::string & filename, double dropTol=1e-3){
546 importCol(filename, dropTol, 0);
547 }
548
551 void fillArrays(Vector < ValueType > & vals, IndexArray & rows, IndexArray & cols){
552 vals.resize(C_.size());
553 rows.resize(C_.size());
554 cols.resize(C_.size());
555 Index i = 0;
556
557 for (const_iterator it = this->begin(); it != this->end(); it ++, i ++){
558 rows[i] = idx1(it);
559 cols[i] = idx2(it);
560 vals[i] = val(it);
561 }
562 }
563
564protected:
565
566 IndexType rows_, cols_;
567 ContainerType C_;
568 // 0 .. nonsymmetric, -1 symmetric lower part, 1 symmetric upper part
569 int stype_;
570};// class SparseMapMatrix
571
572
573template < class ValueType, class IndexType >
574void save(const SparseMapMatrix< ValueType, IndexType > & S,
575 const std::string & fname){
576 S.save(fname);
577}
578
579template < class ValueType, class IndexType >
581 const std::string & fname){
582 return S.load(fname);
583}
584
585inline RVector operator * (const RSparseMapMatrix & A, const RVector & b){
586 return A.mult(b);
587}
588
589inline CVector operator * (const CSparseMapMatrix & A, const CVector & b){
590 return A.mult(b);
591}
592
593inline CVector operator * (const CSparseMapMatrix & A, const RVector & b){
594 return A.mult(toComplex(b));
595}
596
597inline RVector transMult(const RSparseMapMatrix & A, const RVector & b){
598 return A.transMult(b);
599}
600
601inline CVector transMult(const CSparseMapMatrix & A, const CVector & b){
602 return A.transMult(b);
603}
604
605inline CVector transMult(const CSparseMapMatrix & A, const RVector & b){
606 return A.transMult(toComplex(b));
607}
608
609inline RSparseMapMatrix real(const CSparseMapMatrix & A){
610 RSparseMapMatrix R(A.rows(), A.cols());
611 for (CSparseMapMatrix::const_iterator it = A.begin(); it != A.end(); it ++){
612 R.setVal(it->first.first, it->first.second, it->second.real());
613 }
614 return R;
615}
616
617inline RSparseMapMatrix imag(const CSparseMapMatrix & A){
618 RSparseMapMatrix R(A.rows(), A.cols());
619 for (CSparseMapMatrix::const_iterator it = A.begin(); it != A.end(); it ++){
620 R.setVal(it->first.first, it->first.second, it->second.imag());
621 }
622 return R;
623}
624
625inline RSparseMapMatrix operator + (const RSparseMapMatrix & A, const RSparseMapMatrix & B){
626 RSparseMapMatrix tmp(A);
627 return tmp += B;
628}
629
630inline RSparseMapMatrix operator - (const RSparseMapMatrix & A, const RSparseMapMatrix & B){
631 RSparseMapMatrix tmp(A);
632 return tmp -= B;
633}
634
635#define DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(OP) \
636 inline RSparseMapMatrix operator OP (const RSparseMapMatrix & A, const double & v){\
637 return RSparseMapMatrix(A) OP##= v; \
638 } \
639
640 DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(+)
641 DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(-)
642 DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(*)
643 DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(/)
644
645#undef DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__
646
647#define DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(OP) \
648 inline RSparseMapMatrix operator OP (const double & v, const RSparseMapMatrix & A){\
649 return RSparseMapMatrix(A) OP##= v; \
650 } \
651
652 DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(+)
653 DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__(*)
654
655#undef DEFINE_SPARSEMAPMATRIX_EXPR_OPERATOR__
656
657
658
660template< class Vec >
662 const Vec & l, const Vec & r) {
663
664 if (S.cols() != r.size())
665 throwLengthError(WHERE_AM_I + " " + str(S.cols())
666 + " != " + str(r.size()));
667 if (S.rows() != l.size())
668 throwLengthError(WHERE_AM_I + " " + str(S.rows())
669 + " != " + str(l.size()));
670
671 for (SparseMapMatrix< double, Index >::iterator it = S.begin(); it != S.end(); it ++){
672 S.val(it) *= l[S.idx1(it)] * r[S.idx2(it)];
673// int i = S.idx1(it);
674// int j = S.idx2(it);
675// S[i][j] *= (l[i] * r[j]);
676 }
677 return;
678}
679
681template< class Vec >
682void rank1Update(SparseMapMatrix< double, Index > & S, const Vec & u, const Vec & v) {
683
684 if (S.cols() != v.size())
685 throwLengthError(WHERE_AM_I + " " + str(S.cols())
686 + " != " + str(v.size()));
687 if (S.rows() != u.size())
688 throwLengthError(WHERE_AM_I + " " + str(S.rows())
689 + " != " + str(u.size()));
690
691 for (SparseMapMatrix< double, Index >::iterator it = S.begin(); it != S.end(); it ++){
692 S.val(it) += u[S.idx1(it)] * v[S.idx2(it)];
693 }
694 return;
695}
696
697// template < class ValueType, class IndexType, class V2, class T, class A >
698// Vector < V2 > operator * (const SparseMapMatrix< ValueType, IndexType > & S,
699// const VectorExpr< T, A > & a) {
700// return S * Vector< V2 >(a);
701// }
702
704
707template < class ValueType > class SparseMatrix : public MatrixBase{
708public:
709
712 : MatrixBase(), valid_(false), stype_(0), rows_(0), cols_(0){ }
713
716 : MatrixBase(),
717 colPtr_(S.vecColPtr()),
718 rowIdx_(S.vecRowIdx()),
719 vals_(S.vecVals()), valid_(true), stype_(0){
720 rows_ = S.rows();
721 cols_ = S.cols();
722 }
723
726 : MatrixBase(), valid_(true){
727 copy_(S);
728 }
729 SparseMatrix(const IndexArray & colPtr,
730 const IndexArray & rowIdx,
731 const Vector < ValueType > vals, int stype=0)
732 : MatrixBase(){
733 colPtr_ = std::vector < int >(colPtr.size());
734 rowIdx_ = std::vector < int >(rowIdx.size());
735 for (Index i = 0; i < colPtr_.size(); i ++ ) colPtr_[i] = colPtr[i];
736 for (Index i = 0; i < rowIdx_.size(); i ++ ) rowIdx_[i] = rowIdx[i];
737 vals_ = vals;
738 stype_ = stype;
739 valid_ = true;
740 cols_ = max(rowIdx_) + 1;
741 rows_ = colPtr_.size() - 1;
742 }
743
744 SparseMatrix(const std::vector < int > & colPtr,
745 const std::vector < int > & rowIdx,
746 const Vector < ValueType > vals, int stype=0)
747 : MatrixBase(){
748 colPtr_ = colPtr;
749 rowIdx_ = rowIdx;
750 vals_ = vals;
751 stype_ = stype;
752 valid_ = true;
753 cols_ = max(rowIdx_) + 1;
754 rows_ = colPtr_.size() - 1;
755 }
756
758 virtual ~SparseMatrix(){ }
759
762 if (this != &S){
763 colPtr_ = S.vecColPtr();
764 rowIdx_ = S.vecRowIdx();
765 vals_ = S.vecVals();
766 stype_ = S.stype();
767 valid_ = true;
768 cols_ = S.cols();
769 rows_ = S.rows();
770
771 } return *this;
772 }
773
775 this->copy_(S);
776 return *this;
777 }
778
779 #define DEFINE_SPARSEMATRIX_UNARY_MOD_OPERATOR__(OP, FUNCT) \
780 void FUNCT(int i, int j, ValueType val){ \
781 if ((stype_ < 0 && i > j) || (stype_ > 0 && i < j)) return; \
782 if (abs(val) > TOLERANCE || 1){ \
783 for (int k = colPtr_[i]; k < colPtr_[i + 1]; k ++){ \
784 if (rowIdx_[k] == j) { \
785 vals_[k] OP##= val; return; \
786 } \
787 } \
788 std::cerr << WHERE_AM_I << " pos " << i << " " << j << " is not part of the sparsity pattern " << std::endl; \
789 } \
790 }\
791 SparseMatrix< ValueType > & operator OP##= (const ValueType & v){\
792 vals_ OP##= v; \
793 return *this;\
794 }\
795
796 DEFINE_SPARSEMATRIX_UNARY_MOD_OPERATOR__(+, addVal)
797 DEFINE_SPARSEMATRIX_UNARY_MOD_OPERATOR__(-, subVal)
798 DEFINE_SPARSEMATRIX_UNARY_MOD_OPERATOR__(*, mulVal)
799 DEFINE_SPARSEMATRIX_UNARY_MOD_OPERATOR__(/, divVal)
800
801 #undef DEFINE_SPARSEMATRIX_UNARY_MOD_OPERATOR__
802
804 vals_ += A.vecVals();
805 return *this;
806 }
808 vals_ -= A.vecVals();
809 return *this;
810 }
811
812 SparseMatrix< ValueType > & operator += (const ElementMatrix< double > & A){
813 if (!valid_) SPARSE_NOT_VALID;
814 for (Index i = 0, imax = A.size(); i < imax; i++){
815 for (Index j = 0, jmax = A.size(); j < jmax; j++){
816 addVal(A.idx(i), A.idx(j), A.getVal(i, j));
817 }
818 }
819 return *this;
820 }
821
822 virtual uint rtti() const { return GIMLI_SPARSE_CRS_MATRIX_RTTI; }
823
825 virtual Vector < ValueType > mult(const Vector < ValueType > & a) const {
826 if (a.size() < this->cols()){
827 throwLengthError(WHERE_AM_I + " SparseMatrix size(): " + str(this->cols()) + " a.size(): " +
828 str(a.size())) ;
829 }
830
831 Vector < ValueType > ret(this->rows(), 0.0);
832
833 if (stype_ == 0){
834 // for each row
835 for (Index i = 0; i < this->rows(); i++){
836 // iterate through compressed col
837 for (int j = this->vecColPtr()[i]; j < this->vecColPtr()[i + 1]; j ++){
838 ret[i] += a[this->vecRowIdx()[j]] * this->vecVals()[j];
839 }
840 }
841 } else if (stype_ == -1){
842 Index J;
843 for (Index i = 0; i < ret.size(); i++){
844 for (int j = this->vecColPtr()[i]; j < this->vecColPtr()[i + 1]; j ++){
845 J = this->vecRowIdx()[j];
846
847// __MS( i << " " << J << " " << this->vecVals()[j])
848 ret[i] += a[J] * conj(this->vecVals()[j]);
849
850 if (J > i){
851// __MS( J << " " << i << " " << this->vecVals()[j])
852 ret[J] += a[i] * this->vecVals()[j];
853 }
854 }
855 }
856
857 //#THROW_TO_IMPL
858 } else if (stype_ == 1){
859 Index J;
860 for (Index i = 0; i < ret.size(); i++){
861 for (int j = this->vecColPtr()[i]; j < this->vecColPtr()[i + 1]; j ++){
862 J = this->vecRowIdx()[j];
863
864// __MS( i << " " << J << " " << this->vecVals()[j])
865 ret[i] += a[J] * conj(this->vecVals()[j]);
866
867 if (J < i){
868// __MS( J << " " << i << " " << this->vecVals()[j])
869 ret[J] += a[i] * this->vecVals()[j];
870 }
871 }
872 }
873 }
874 return ret;
875 }
876
878 virtual Vector < ValueType > transMult(const Vector < ValueType > & a) const {
879
880 if (a.size() < this->rows()){
881 throwLengthError(WHERE_AM_I + " SparseMatrix size(): " + str(this->rows()) + " a.size(): " +
882 str(a.size())) ;
883 }
884
885 Vector < ValueType > ret(this->cols(), 0.0);
886
887 if (stype_ == 0){
888 for (Index i = 0; i < this->rows(); i++){
889 for (int j = this->vecColPtr()[i]; j < this->vecColPtr()[i + 1]; j ++){
890 ret[this->vecRowIdx()[j]] += a[i] * this->vecVals()[j];
891 }
892 }
893
894 } else if (stype_ == -1){
895 THROW_TO_IMPL
896 } else if (stype_ == 1){
897 THROW_TO_IMPL
898 }
899 return ret;
900 }
901
902 void add(const ElementMatrix< double > & A){
903 return add(A, ValueType(1.0));
904 }
905 void add(const ElementMatrix< double > & A,
906 ValueType scale);
907 void add(const ElementMatrix< double > & A,
908 const Pos & scale);
909 void add(const ElementMatrix< double > & A,
910 const Matrix < ValueType > & scale);
911
912 void clean(){ for (Index i = 0, imax = nVals(); i < imax; i++) vals_[i] = (ValueType)(0); }
913
914 void clear(){
915 colPtr_.clear();
916 rowIdx_.clear();
917 vals_.clear();
918 valid_ = false;
919 cols_ = 0;
920 rows_ = 0;
921 }
922
923 void setVal(int i, int j, ValueType val){
924 if (abs(val) > TOLERANCE || 1){
925 for (int k = colPtr_[i]; k < colPtr_[i + 1]; k ++){
926 if (rowIdx_[k] == j) {
927 vals_[k] = val; return;
928 }
929 }
930 std::cerr << WHERE_AM_I << " pos " << i << " " << j << " is not part of the sparsity pattern " << std::endl;
931 }
932 }
933
937 ValueType getVal(int i, int j, bool warn=true) const {
938 for (int k = colPtr_[i]; k < colPtr_[i + 1]; k ++){
939 if (rowIdx_[k] == j) {
940 return vals_[k];
941 }
942 }
943 if (warn) std::cerr << WHERE_AM_I << " pos " << i << " "
944 << j << " is not part of the sparsity pattern " << std::endl;
945 return ValueType(0);
946 }
947
948 void cleanRow(int row){
949 ASSERT_RANGE(row, 0, (int)this->rows())
950 for (int col = colPtr_[row]; col < colPtr_[row + 1]; col ++){
951 vals_[col] = ValueType(0);
952 }
953 }
954
955 void cleanCol(int col){
956 ASSERT_RANGE(col, 0, (int)this->cols())
957 for (int i = 0; i < (int)this->rowIdx_.size(); i++){
958 if (rowIdx_[i] == col) {
959 vals_[i] = ValueType(0);
960 }
961 }
962 }
965
966 void buildSparsityPattern(const Mesh & mesh){
967 Stopwatch swatch(true);
968
969 colPtr_.resize(mesh.nodeCount() + 1);
970
971 //*** much to slow
972 //RSparseMapMatrix S(mesh.nodeCount(), mesh.nodeCount());
973
974 Index col = 0, row = 0;
975
976 // need unique(sort) maybe to slow
977// std::vector < std::vector< Index > > idxMap(mesh.nodeCount());
978// for (std::vector < std::vector< Index > >::iterator mIt = idxMap.begin(); mIt != idxMap.end(); mIt++){
979// (*mIt).reserve(100);
980// }
981
982// using set is by a factor of approx 5 more expensive
983 std::vector < std::set< Index > > idxMap(mesh.nodeCount());
984
985 Cell *cell = 0;
986 uint nc = 0;
987
988 for (uint c = 0; c < mesh.cellCount(); c ++){
989 cell = &mesh.cell(c);
990 nc = cell->nodeCount();
991
992 for (uint i = 0; i < nc; i ++){
993 for (uint j = 0; j < nc; j ++){
994 row = cell->node(i).id();
995 col = cell->node(j).id();
996 //idxMap[col].push_back(row);
997 idxMap[col].insert(row);
998 //S[col][row] = 1;
999 }
1000 }
1001 }
1002
1003 int nVals = 0;
1004 for (std::vector < std::set< Index > >::iterator mIt = idxMap.begin();
1005 mIt != idxMap.end(); mIt++){
1006 //std::sort((*mIt).begin(), (*mIt).end());
1007 nVals += (*mIt).size();
1008 }
1009
1010// std::cout << "timwe: " << swatch.duration( true) << std::endl;
1011// exit(0);
1012
1013 rowIdx_.reserve(nVals);
1014 rowIdx_.resize(nVals);
1015 vals_.resize(nVals);
1016
1017 colPtr_[0] = 0;
1018 Index k = 0;
1019 row = 0;
1020 for (std::vector < std::set< Index > >::iterator mIt = idxMap.begin(); mIt != idxMap.end(); mIt++){
1021 for (std::set< Index >::iterator sIt = (*mIt).begin(); sIt != (*mIt).end(); sIt++){
1022 rowIdx_[k] = (*sIt);
1023 vals_[k] = (ValueType)0.0;
1024 k++;
1025 }
1026 row++;
1027 colPtr_[row] = k;
1028 }
1029 valid_ = true;
1030
1031 rows_ = colPtr_.size() - 1;
1032 cols_ = max(rowIdx_) + 1;
1033 //** freeing idxMap ist expensive
1034 }
1035
1036 void fillStiffnessMatrix(const Mesh & mesh){
1037 RVector a(mesh.cellCount(), 1.0);
1038 fillStiffnessMatrix(mesh, a);
1039 }
1040
1041 void fillStiffnessMatrix(const Mesh & mesh, const RVector & a){
1042 clean();
1043 buildSparsityPattern(mesh);
1044 ElementMatrix < double > A_l;
1045
1046 for (uint i = 0; i < mesh.cellCount(); i ++){
1047 A_l.ux2uy2uz2(mesh.cell(i));
1048 A_l *= a[mesh.cell(i).id()];
1049 *this += A_l;
1050 }
1051 }
1052 void fillMassMatrix(const Mesh & mesh){
1053 RVector a(mesh.cellCount(), 1.0);
1054 fillMassMatrix(mesh, a);
1055 }
1056
1057 void fillMassMatrix(const Mesh & mesh, const RVector & a){
1058 clean();
1059 buildSparsityPattern(mesh);
1060 ElementMatrix < double > A_l;
1061
1062 for (uint i = 0; i < mesh.cellCount(); i ++){
1063 A_l.u2(mesh.cell(i));
1064 A_l *= a[mesh.cell(i).id()];
1065 *this += A_l;
1066 }
1067 }
1068
1070 inline int stype() const {return stype_;}
1071
1072 inline int * colPtr() { if (valid_) return &colPtr_[0]; else SPARSE_NOT_VALID; return 0; }
1073 inline const int & colPtr() const { if (valid_) return colPtr_[0]; else SPARSE_NOT_VALID; return colPtr_[0]; }
1074 inline const std::vector < int > & vecColPtr() const { return colPtr_; }
1075
1076 inline int * rowIdx() { if (valid_) return &rowIdx_[0]; else SPARSE_NOT_VALID; return 0; }
1077 inline const int & rowIdx() const { if (valid_) return rowIdx_[0]; else SPARSE_NOT_VALID; return rowIdx_[0]; }
1078 inline const std::vector < int > & vecRowIdx() const { return rowIdx_; }
1079
1080 inline ValueType * vals() { if (valid_) return &vals_[0]; else SPARSE_NOT_VALID; return 0; }
1081// inline const ValueType * vals() const { if (valid_) return &vals_[0]; else SPARSE_NOT_VALID; return 0; }
1082// inline const ValueType & vals() const { if (valid_) return vals_[0]; else SPARSE_NOT_VALID; return vals_[0]; }
1083 inline const Vector < ValueType > & vecVals() const { return vals_; }
1084 inline Vector < ValueType > & vecVals() { return vals_; }
1085
1086 inline Index size() const { return rows(); }
1087 inline Index nVals() const { return vals_.size(); }
1088 inline Index cols() const { return cols_; }
1089 inline Index rows() const { return rows_; }
1090 inline Index nCols() const { return cols(); }
1091 inline Index nRows() const { return rows(); }
1092
1093 void save(const std::string & fileName) const {
1094 if (!valid_) SPARSE_NOT_VALID;
1095 std::fstream file;
1096 openOutFile(fileName, & file);
1097
1098 file.setf(std::ios::scientific, std::ios::floatfield);
1099 file.precision(14);
1100
1101 for (Index i = 0; i < size(); i++){
1102 for (SIndex j = colPtr_[i]; j < colPtr_[i + 1]; j ++){
1103 file << i << "\t" << rowIdx_[j]
1104 << "\t" << vals_[j] << std::endl;
1105 }
1106 }
1107 file.close();
1108 }
1109
1110 bool valid() const { return valid_; }
1111
1112protected:
1113
1114 // int to be cholmod compatible!!!!!!!!
1115
1116 std::vector < int > colPtr_;
1117 std::vector < int > rowIdx_;
1118 Vector < ValueType > vals_;
1119
1120 bool valid_;
1121 int stype_;
1122 Index rows_;
1123 Index cols_;
1124};
1125
1126template < class ValueType >
1128 const SparseMatrix< ValueType > & B){
1130 return ret += B;
1131}
1132
1133template < class ValueType >
1135 const SparseMatrix< ValueType > & B){
1137 return ret -= B;
1138}
1139
1140template < class ValueType >
1141SparseMatrix < ValueType > operator * (const SparseMatrix < ValueType > & A,
1142 const ValueType & b){
1144 return ret *= b;
1145}
1146
1147template < class ValueType >
1148SparseMatrix < ValueType > operator * (const ValueType & b,
1149 const SparseMatrix < ValueType > & A){
1151 return ret *= b;
1152}
1153
1154inline RVector operator * (const RSparseMatrix & A, const RVector & b){return A.mult(b);}
1155inline RVector transMult(const RSparseMatrix & A, const RVector & b){return A.transMult(b);}
1156
1157inline CVector operator * (const CSparseMatrix & A, const CVector & b){return A.mult(b);}
1158inline CVector operator * (const CSparseMatrix & A, const RVector & b){return A.mult(toComplex(b));}
1159inline CVector transMult(const CSparseMatrix & A, const CVector & b){return A.transMult(b);}
1160inline CVector transMult(const CSparseMatrix & A, const RVector & b){return A.transMult(toComplex(b));}
1161
1162inline CSparseMatrix operator + (const CSparseMatrix & A, const RSparseMatrix & B){
1163 CSparseMatrix ret(A);
1164 ret.vecVals() += toComplex(B.vecVals());
1165 return ret;
1166}
1167
1168inline RSparseMatrix real(const CSparseMatrix & A){
1169 return RSparseMatrix(A.vecColPtr(), A.vecRowIdx(),
1170 real(A.vecVals()), A.stype());
1171}
1172inline RSparseMatrix imag(const CSparseMatrix & A){
1173 return RSparseMatrix(A.vecColPtr(), A.vecRowIdx(),
1174 imag(A.vecVals()), A.stype());
1175}
1176
1178template< typename ValueType >
1180template< typename ValueType >
1182
1184template <> DLLEXPORT void SparseMapMatrix< double, Index >::copy_(const SparseMatrix<double> & S);
1185
1186template< typename ValueType, typename Index >
1187void SparseMapMatrix< ValueType, Index >::copy_(const SparseMatrix< double > & S){THROW_TO_IMPL}
1188template< typename ValueType, typename Index >
1189void SparseMapMatrix< ValueType, Index >::copy_(const SparseMatrix< Complex > & S){THROW_TO_IMPL}
1190
1191
1192
1193template <> DLLEXPORT void SparseMapMatrix< double, Index >::
1194 add(const ElementMatrix < double > & A, double scale);
1195template <> DLLEXPORT void SparseMapMatrix< double, Index >::
1196 add(const ElementMatrix < double > & A, const Pos & scale);
1197template <> DLLEXPORT void SparseMapMatrix< double, Index >::
1198 add(const ElementMatrix < double > & A, const RMatrix & scale);
1199template <> DLLEXPORT void SparseMapMatrix< double, Index >::
1200 add(const ElementMatrix < double > & A, const Vector < double > & scale);
1201
1202template <> DLLEXPORT void SparseMapMatrix< Complex, Index >::
1203 add(const ElementMatrix < double > & A, Complex scale);
1204template <> DLLEXPORT void SparseMapMatrix< Complex, Index >::
1205 add(const ElementMatrix < double > & A, const Pos & scale);
1206template <> DLLEXPORT void SparseMapMatrix< Complex, Index >::
1207 add(const ElementMatrix < double > & A, const Matrix < Complex > & scale);
1208template <> DLLEXPORT void SparseMapMatrix< Complex, Index >::
1209 add(const ElementMatrix < double > & A, const Vector < Complex > & scale);
1210
1211
1212template <> DLLEXPORT void SparseMapMatrix< double, Index >::
1213 addToCol(Index id, const ElementMatrix < double > & A, double scale, bool isDiag);
1214template <> DLLEXPORT void SparseMapMatrix< double, Index >::
1215 addToRow(Index id, const ElementMatrix < double > & A, double scale, bool isDiag);
1216template <> DLLEXPORT void SparseMapMatrix< Complex, Index >::
1217 addToCol(Index id, const ElementMatrix < double > & A, Complex scale, bool isDiag);
1218template <> DLLEXPORT void SparseMapMatrix< Complex, Index >::
1219 addToRow(Index id, const ElementMatrix < double > & A, Complex scale, bool isDiag);
1220
1221template <> DLLEXPORT void SparseMatrix<double>::copy_(const SparseMapMatrix< double, Index > & S);
1222template <> DLLEXPORT void SparseMatrix<Complex>::copy_(const SparseMapMatrix< Complex, Index > & S);
1223
1224template <> DLLEXPORT void SparseMatrix< double >::
1225 add(const ElementMatrix < double > & A, double scale);
1226template <> DLLEXPORT void SparseMatrix< double >::
1227 add(const ElementMatrix < double > & A, const Pos & scale);
1228template <> DLLEXPORT void SparseMatrix< double >::
1229 add(const ElementMatrix < double > & A, const RMatrix & scale);
1230
1231template <> DLLEXPORT void SparseMatrix< Complex >::
1232 add(const ElementMatrix < double > & A, Complex scale);
1233template <> DLLEXPORT void SparseMatrix< Complex >::
1234 add(const ElementMatrix < double > & A, const Pos & scale);
1235template <> DLLEXPORT void SparseMatrix< Complex >::
1236 add(const ElementMatrix < double > & A, const CMatrix & scale);
1237
1238
1239} // namespace GIMLI
1240
1241#endif //GIMLI_SPARSEMATRIX__H
int id() const
Definition baseentity.h:59
A abstract cell.
Definition meshentities.h:261
Interface class for matrices.
Definition matrix.h:137
MatrixBase(bool verbose=false)
Definition matrix.h:141
based on: Ulrich Breymann, Addison Wesley Longman 2000 , revised edition ISBN 0-201-67488-2,...
Definition sparsematrix.h:45
Simple row-based dense matrix based on Vector.
Definition matrix.h:324
Definition mesh.h:128
3 dimensional vector
Definition pos.h:73
Definition sparsematrix.h:333
based on: Ulrich Breymann, Addison Wesley Longman 2000 , revised edition ISBN 0-201-67488-2,...
Definition sparsematrix.h:149
SparseMapMatrix(const IndexArray &i, const IndexArray &j, const RVector &v)
Definition sparsematrix.h:185
virtual Vector< ValueType > transMult(const Vector< ValueType > &a) const
Definition sparsematrix.h:455
void add(const ElementMatrix< double > &A, ValueType scale=1.0)
virtual IndexType rows() const
Definition sparsematrix.h:268
SparseMapMatrix(IndexType r=0, IndexType c=0, int stype=0)
Definition sparsematrix.h:158
void add(const ElementMatrix< double > &A, const Vector< ValueType > &scale)
void resize(Index rows, Index cols)
Definition sparsematrix.h:217
void add(const IndexArray &rows, const IndexArray &cols, const RVector &vals)
Definition sparsematrix.h:226
int stype() const
Definition sparsematrix.h:265
void fillArrays(Vector< ValueType > &vals, IndexArray &rows, IndexArray &cols)
Definition sparsematrix.h:551
void importCol(const std::string &filename, double dropTol, Index colOffset)
Definition sparsematrix.h:517
virtual Vector< ValueType > mult(const Vector< ValueType > &a) const
Definition sparsematrix.h:417
virtual IndexType cols() const
Definition sparsematrix.h:272
virtual void clear()
Definition sparsematrix.h:236
virtual uint rtti() const
Definition sparsematrix.h:215
void save(const std::string &filename) const
Definition sparsematrix.h:486
virtual ~SparseMatrix()
Definition sparsematrix.h:758
int stype() const
Definition sparsematrix.h:1070
virtual Vector< ValueType > mult(const Vector< ValueType > &a) const
Definition sparsematrix.h:825
void clear()
Definition sparsematrix.h:914
void copy_(const SparseMapMatrix< double, Index > &S)
Definition sparsematrix.h:1179
SparseMatrix(const SparseMatrix< ValueType > &S)
Definition sparsematrix.h:715
SparseMatrix()
Definition sparsematrix.h:711
void save(const std::string &fileName) const
Definition sparsematrix.h:1093
SparseMatrix(const SparseMapMatrix< ValueType, Index > &S)
Definition sparsematrix.h:725
SparseMatrix< ValueType > & operator=(const SparseMatrix< ValueType > &S)
Definition sparsematrix.h:761
virtual uint rtti() const
Definition sparsematrix.h:822
Index rows() const
Definition sparsematrix.h:1089
ValueType getVal(int i, int j, bool warn=true) const
Definition sparsematrix.h:937
void clean()
Definition sparsematrix.h:912
Index cols() const
Definition sparsematrix.h:1088
virtual Vector< ValueType > transMult(const Vector< ValueType > &a) const
Definition sparsematrix.h:878
Definition stopwatch.h:62
void resize(Index n, ValueType fill)
Definition vector.h:698
GIMLi main namespace for the Geophyiscal Inversion and Modelling Library.
Definition baseentity.h:24
RVector x(const R3Vector &rv)
Definition pos.cpp:107
bool load(Matrix< ValueType > &A, const std::string &filename)
Definition matrix.h:828