Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
sparsematrix_impl.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2010-2015: G-CSC, Goethe University Frankfurt
3 * Author: Martin Rupp
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef __H__UG__CPU_ALGEBRA__SPARSEMATRIX_IMPL__
34#define __H__UG__CPU_ALGEBRA__SPARSEMATRIX_IMPL__
35
36// creation etc
37
38#include <fstream>
39#include <cstring>
40
43#include "sparsematrix.h"
44#include <vector>
45#include <algorithm>
46
47
48
49namespace ug{
50
51// defined in C99, and sometimes part of <math.h>, <cmath>
52template <class __T> inline bool
53iszero (__T __val)
54{
55 return __val == 0;
56}
57
58template<typename T>
60{
61 PROFILE_SPMATRIX(SparseMatrix_constructor);
62 bNeedsValues = true;
63 iIterators=0;
64 nnz = 0;
65 m_numCols = 0;
66 maxValues = 0;
67 cols.resize(32);
68 if(bNeedsValues) values.resize(32);
69}
70
71template<typename T>
73{
74 std::vector<int>().swap(rowStart);
75 std::vector<int>().swap(rowMax);
76 std::vector<int>().swap(rowEnd);
77 m_numCols = 0;
78 nnz = 0;
79
80 std::vector<int>().swap(cols);
81 std::vector<value_type>().swap(values);
82 maxValues = 0;
83
84#ifdef CHECK_ROW_ITERATORS
85 std::vector<int>().swap(nrOfRowIterators);
86#endif
87}
88
89
90template<typename T>
91void SparseMatrix<T>::resize_and_clear(size_t newRows, size_t newCols)
92{
93 PROFILE_SPMATRIX(SparseMatrix_resize_and_clear);
94 rowStart.clear(); rowStart.resize(newRows+1, -1);
95 rowMax.clear(); rowMax.resize(newRows);
96 rowEnd.clear(); rowEnd.resize(newRows, -1);
97 m_numCols = newCols;
98 nnz = 0;
99
100 cols.clear(); cols.resize(newRows);
101 values.clear();
102 if(bNeedsValues) values.resize(newRows);
103 maxValues = 0;
104
105#ifdef CHECK_ROW_ITERATORS
106 nrOfRowIterators.clear();
107 nrOfRowIterators.resize(newRows, 0);
108#endif
109}
110
111template<typename T>
112void SparseMatrix<T>::resize_and_keep_values(size_t newRows, size_t newCols)
113{
114 PROFILE_SPMATRIX(SparseMatrix_resize_and_keep_values);
115 //UG_LOG("SparseMatrix resize " << newRows << "x" << newCols << "\n");
116 if(newRows == 0 && newCols == 0)
117 return resize_and_clear(0,0);
118
119 if(newRows != num_rows())
120 {
121 size_t oldrows = num_rows();
122 rowStart.resize(newRows+1, -1);
123 rowMax.resize(newRows);
124 rowEnd.resize(newRows, -1);
125#ifdef CHECK_ROW_ITERATORS
126 nrOfRowIterators.resize(newRows, 0);
127#endif
128 for(size_t i=oldrows; i<newRows; i++)
129 {
130 rowStart[i] = -1;
131 rowEnd[i] = -1;
134 if((int)newCols < m_numCols)
135 copyToNewSize(get_nnz_max_cols(newCols), newCols);
136
137 m_numCols = newCols;
138}
139
140
141template<typename T>
143{
144 std::fill(values.begin(), values.end(), value_type(0));
145}
146
147
148template<typename T>
151 PROFILE_SPMATRIX(SparseMatrix_set_as_transpose_of);
152 resize_and_clear(B.num_cols(), B.num_rows());
153 /*rowStart.resize(B.num_cols(), 0);
154 rowMax.resize(B.num_cols(), 0);
155 rowEnd.resize(B.num_cols(), 0);
156 nnz = B.nnz;
157 bNeedsValues = B.bNeedsValues;
158 if(bNeedsValues) values.resize(nnz);
159 cols.resize(nnz);
160 maxValues = B.maxValues;
161 fragmented = 0;
162 m_numCols = B.num_rows();
163 size_t r, c;
164 for(r=0; r<num_rows(); r++)
165 for(const_row_iterator it = B.begin_row(r); it != B.end_row(r); ++it)
166 rowMax[it.index()]++;
167 rowEnd[0] = rowMax[0];
168 rowEnd[0] = 0;
169 for(c=1; c<B.num_cols(); c++)
170 {
171 rowStart[c] = rowMax[c-1];
172 rowMax[c] = rowStart[c]+rowMax[c];
173 rowEnd[c] = rowStart[c];
174 }*/
175
176 for(size_t r=0; r<B.num_rows(); r++)
177 {
178 const_row_iterator itEnd = B.end_row(r);
179 for(const_row_iterator it = B.begin_row(r); it != itEnd; ++it)
180 operator()(it.index(), r) = MatrixTranspose(scale*it.value());
181 }
182 // todo: sort rows
183}
184
185template<typename T>
187{
188 PROFILE_SPMATRIX(SparseMatrix_set_as_transpose_of2);
189 resize_and_clear(B.num_cols(), B.num_rows());
190 assert(num_cols() == B.num_rows());
191 assert(num_rows() == B.num_cols());
192 size_t r, c;
193
194 for(r=0; r<num_rows(); ++r){
195 assert(rowMax[r] == 0);
196 }
197
198 std::vector<int> rowsize(num_rows());
199 nnz = 0;
200 bNeedsValues = B.bNeedsValues; // allocate value array
201
202 maxValues = B.maxValues;
203 fragmented = 0;
204
205 for(r=0; r<num_cols(); r++){
206 for(const_row_iterator it = B.begin_row(r); it != B.end_row(r); ++it){
207 if(iszero(it.value())){
208 }else{
209 ++nnz;
210 ++rowMax[it.index()];
211 }
212 }
213 }
214
215 rowStart[0] = 0;
216 rowEnd[0] = 0;
217 for(c=1; c<num_rows(); ++c) {
218 rowStart[c] = rowMax[c-1];
219 rowMax[c] = rowStart[c]+rowMax[c];
220 rowEnd[c] = rowStart[c];
221 }
222
223 cols.resize(nnz);
224 if(bNeedsValues){
225 values.resize(nnz);
226 }else{
227 }
228
229 for(r=0; r<num_cols(); ++r){
230 for(const_row_iterator it = B.begin_row(r); it != B.end_row(r); ++it){
231 if(iszero(it.value())){
232 }else{
233 int idx = rowEnd[it.index()]++;
234 if(bNeedsValues){
235 values[idx] = scale * it.value();
236 }else{
237 }
238 cols[idx] = r;
240 }
241 }
243#ifndef NDEBUG
244 for(r=0; r<num_rows(); ++r){
245 assert(rowMax[r] == rowEnd[r]);
246 }
247
248 assert(nnz <= B.nnz);
249
250 for(r=1; r<num_rows(); ++r) {
251 assert(rowEnd[r] == rowMax[r]);
252 }
253#endif
254
255}
256
257template<typename T>
258template<typename vector_t>
259inline void SparseMatrix<T>::mat_mult_add_row(size_t row, typename vector_t::value_type &dest, double alpha, const vector_t &v) const
260{
261
262 size_t itEnd=rowEnd[row];
263 for(size_t rowIt=rowStart[row]; rowIt != itEnd; ++rowIt)
264 MatMultAdd(dest, 1.0, dest, alpha, values[rowIt], v[cols[rowIt]]);
265
266 //for(const_row_iterator conn = begin_row(row); conn != end_row(row); ++conn)
267 //MatMultAdd(dest, 1.0, dest, alpha, conn.value(), v[conn.index()]);
268}
269
270
271template<typename T>
272template<typename vector_t>
274 const number &beta1, const vector_t &w1) const
275{
276 for(size_t i=0; i < num_rows(); i++)
277 {
278 size_t rowIt=rowStart[i];
279 size_t itEnd=rowEnd[i];
280 if(rowIt == itEnd)
281 continue;
282
283 MatMult(dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
284 for(++rowIt; rowIt != itEnd; ++rowIt)
285 // res[i] += conn.value() * x[conn.index()];
286 MatMultAdd(dest[i], 1.0, dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
287 }
288}
289
290
291// calculate dest = alpha1*v1 + beta1*A*w1 (A = this matrix)
292template<typename T>
293template<typename vector_t>
294void SparseMatrix<T>::axpy(vector_t &dest,
295 const number &alpha1, const vector_t &v1,
296 const number &beta1, const vector_t &w1) const
297{
298 PROFILE_SPMATRIX(SparseMatrix_axpy);
299 check_fragmentation();
300 if(alpha1 == 0.0)
301 {
302 for(size_t i=0; i < num_rows(); i++)
303 {
304 size_t rowIt=rowStart[i];
305 size_t itEnd=rowEnd[i];
306 if(rowIt == itEnd)
307 {
308 dest[i] = 0.0;
309 continue;
310 }
311 MatMult(dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
312 for(++rowIt; rowIt != itEnd; ++rowIt)
313 // res[i] += conn.value() * x[conn.index()];
314 MatMultAdd(dest[i], 1.0, dest[i], beta1, values[rowIt], w1[cols[rowIt]]);
315 }
316 }
317 else if(&dest == &v1)
318 {
319 if(alpha1 != 1.0) {
320 for(size_t i=0; i < num_rows(); i++)
321 {
322 dest[i] *= alpha1;
323 mat_mult_add_row(i, dest[i], beta1, w1);
325 }
326 else
327 for(size_t i=0; i < num_rows(); i++)
328 mat_mult_add_row(i, dest[i], beta1, w1);
330 }
331 else
332 {
333 for(size_t i=0; i < num_rows(); i++)
334 {
335 VecScaleAssign(dest[i], alpha1, v1[i]);
336 mat_mult_add_row(i, dest[i], beta1, w1);
337 }
338 }
339}
340
341// calculate dest = alpha1*v1 + beta1*A^T*w1 (A = this matrix)
342template<typename T>
343template<typename vector_t>
345 const number &alpha1, const vector_t &v1,
346 const number &beta1, const vector_t &w1) const
347{
348 PROFILE_SPMATRIX(SparseMatrix_axpy_transposed);
349 check_fragmentation();
350 if(&dest == &v1) {
351 if(alpha1 == 0.0)
352 dest.set(0.0);
353 else if(alpha1 != 1.0)
354 dest *= alpha1;
355 }
356 else if(alpha1 == 0.0)
357 dest.set(0.0);
358 else
359 VecScaleAssign(dest, alpha1, v1);
360
361 for(size_t i=0; i<num_rows(); i++)
362 {
363
364 size_t itEnd=rowEnd[i];
365 for(size_t rowIt=rowStart[i]; rowIt != itEnd; ++rowIt)
366 // dest[conn.index()] += beta1 * conn.value() * w1[i];
367 if(values[rowIt] != 0.0)
368 MatMultTransposedAdd(dest[cols[rowIt]], 1.0, dest[cols[rowIt]], beta1, values[rowIt], w1[i]);
369 }
370}
371
372
373template<typename T>
374template<typename vector_t>
376 const number &beta1, const vector_t &w1) const
377{
378 for(size_t i=0; i<num_rows(); i++)
379 {
380 row_iterator itEnd = end_row(i);
381 for(const_row_iterator conn = begin_row(i); conn != itEnd; ++conn)
382 dest[conn.index()] = 0.0;
383 }
384
385 for(size_t i=0; i<num_rows(); i++)
386 {
387 size_t itEnd=rowEnd[i];
388 for(size_t rowIt=rowStart[i]; rowIt != itEnd; ++rowIt)
389 // dest[conn.index()] += beta1 * conn.value() * w1[i];
390 if(values[rowIt] != 0.0)
391 MatMultTransposedAdd(dest[cols[rowIt]], 1.0, dest[cols[rowIt]], beta1, values[rowIt], w1[i]);
392 }
393}
394
395
396template<typename T>
398{
399 PROFILE_SPMATRIX(SparseMatrix_set);
400 check_fragmentation();
401 for(size_t row=0; row<num_rows(); row++)
402 {
403 row_iterator itEnd = end_row(row);
404 for(row_iterator it = begin_row(row); it != itEnd; ++it)
405 {
406 if(it.index() == row)
407 it.value() = a;
408 else
409 it.value() = 0.0;
410 }
411 }
412}
413
414
415template<typename T>
416inline bool SparseMatrix<T>::is_isolated(size_t i) const
417{
418 UG_ASSERT(i < num_rows() && i >= 0, *this << ": " << i << " out of bounds.");
419
420 const_row_iterator itEnd = end_row(i);
421 for(const_row_iterator it = begin_row(i); it != itEnd; ++it)
422 if(it.index() != i && it.value() != 0.0)
423 return false;
424 return true;
425}
426
427
428template<typename T>
429void SparseMatrix<T>::set_matrix_row(size_t row, connection *c, size_t nr)
430{
431 /*PROFILE_SPMATRIX(SparseMatrix_set_matrix_row);
432 bool bSorted=false;
433 for(size_t i=0; bSorted && i+1 < nr; i++)
434 bSorted = c[i].iIndex < c[i+1].iIndex;
435 if(bSorted)
436 {
437 int start;
438 if(rowStart[row] == -1 || rowMax[row] - rowStart[row] < (int)nr)
439 {
440 assureValuesSize(maxValues+nr);
441 start = maxValues;
442 rowMax[row] = start+nr;
443 rowStart[row] = start;
444 maxValues+=nr;
445 }
446 else
447 start = rowStart[row];
448 rowEnd[row] = start+nr;
449 for(size_t i=0; i<nr; i++)
450 {
451 cols[start+i] = c[i].iIndex;
452 values[start+i] = c[i].dValue;
453 }
454 }
455 else*/
456 {
457 for(size_t i=0; i<nr; i++)
458 operator()(row, c[i].iIndex) = c[i].dValue;
459 }
460}
461
462template<typename T>
463void SparseMatrix<T>::add_matrix_row(size_t row, connection *c, size_t nr)
464{
465 //PROFILE_SPMATRIX(SparseMatrix_add_matrix_row);
466 for(size_t i=0; i<nr; i++)
467 operator()(row, c[i].iIndex) += c[i].dValue;
468}
469
470
471template<typename T>
473{
474 //PROFILE_SPMATRIX(SparseMatrix_set_as_copy_of);
475 resize_and_clear(B.num_rows(), B.num_cols());
476 for(size_t i=0; i < B.num_rows(); i++)
477 {
478 const_row_iterator itEnd = B.end_row(i);
479 for(const_row_iterator it = B.begin_row(i); it != itEnd; ++it)
480 operator()(i, it.index()) = scale*it.value();
481 }
482}
483
484
485
486template<typename T>
488{
489 //PROFILE_SPMATRIX(SparseMatrix_scale);
490 for(size_t i=0; i < num_rows(); i++)
491 {
492 row_iterator itEnd = end_row(i);
493 for(row_iterator it = begin_row(i); it != itEnd; ++it)
494 it.value() *= d;
495 }
496}
497
498
499
500
501
502//======================================================================================================
503// submatrix set/get
504
505template<typename T>
506template<typename M>
507void SparseMatrix<T>::add(const M &mat)
508{
509 for(size_t i=0; i < mat.num_rows(); i++)
510 {
511 int r = mat.row_index(i);
512 for(size_t j=0; j < mat.num_cols(); j++)
513 {
514 int c = mat.col_index(j);
515 (*this)(r,c) += mat(i,j);
516 }
517 }
518}
519
520
521template<typename T>
522template<typename M>
523void SparseMatrix<T>::set(const M &mat)
524{
525 for(size_t i=0; i < mat.num_rows(); i++)
526 {
527 int r = mat.row_index(i);
528 for(size_t j=0; j < mat.num_cols(); j++)
529 {
530 int c = mat.col_index(j);
531 (*this)(r,c) = mat(i,j);
532 }
533 }
534}
535
536template<typename T>
537template<typename M>
538void SparseMatrix<T>::get(M &mat) const
539{
540 for(size_t i=0; i < mat.num_rows(); i++)
541 {
542 int r = mat.row_index(i);
543 for(size_t j=0; j < mat.num_cols(); j++)
544 {
545 int c = mat.col_index(j);
546 mat(i,j) = (*this)(r,c);
547 }
548 }
549}
550
551
552template<typename T>
553int SparseMatrix<T>::get_index_internal(size_t row, int col) const
554{
555// PROFILE_SPMATRIX(SP_get_index_internal);
556 assert(rowStart[row] != -1);
557 int l = rowStart[row];
558 int r = rowEnd[row];
559 int mid=0;
560 while(l < r)
561 {
562 mid = (l+r)/2;
563 if(cols[mid] < col)
564 l = mid+1;
565 else if(cols[mid] > col)
566 r = mid-1;
567 else
568 return mid;
569 }
570 mid = (l+r)/2;
571 int ret;
572 if(mid < rowStart[row])
573 ret = rowStart[row];
574 else if(mid == rowEnd[row] || col <= cols[mid])
575 ret = mid;
576 else ret = mid+1;
577 UG_ASSERT(ret <= rowEnd[row] && ret >= rowStart[row], "row iterator row " << row << " pos " << ret << " out of bounds [" << rowStart[row] << ", " << rowEnd[row] << "]");
578 return ret;
579}
580
581
582
583template<typename T>
584int SparseMatrix<T>::get_index_const(int r, int c) const
585{
586 if(rowStart[r] == -1 || rowStart[r] == rowEnd[r]) return -1;
587 int index=get_index_internal(r, c);
588 if(index >= rowStart[r] && index < rowEnd[r] && cols[index] == c)
589 return index;
590 else
591 return -1;
592}
593
594
595template<typename T>
597{
598// UG_LOG("get_index " << r << ", " << c << "\n");
599// UG_LOG(rowStart[r] << " - " << rowMax[r] << " - " << rowEnd[r] << " - " << cols.size() << " - " << maxValues << "\n");
600 if(rowStart[r] == -1 || rowStart[r] == rowEnd[r])
601 {
602// UG_LOG("new row\n");
603 // row did not start, start new row at the end of cols array
604 assureValuesSize(maxValues+1);
605 rowStart[r] = maxValues;
606 rowEnd[r] = maxValues+1;
607 rowMax[r] = maxValues+1;
608 if(bNeedsValues) values[maxValues] = 0.0;
609 cols[maxValues] = c;
610 maxValues++;
611 nnz++;
612 return maxValues-1;
613 }
614
615 /* for(int i=rowStart[r]; i<rowEnd[r]; i++)
616 if(cols[i] == c)
617 return i;*/
618
619 // get the index where (r,c) _should_ be
620 int index=get_index_internal(r, c);
621
622 if(index < rowEnd[r]
623 && cols[index] == c)
624 {
625// UG_LOG("found\n");
626 return index; // we found it
627 }
628
629 // we did not find it, so we have to add it
630
631 check_row_modifiable(r);
632
633#ifndef NDEBUG
634 assert(index == rowEnd[r] || cols[index] > c);
635 assert(index == rowStart[r] || cols[index-1] < c);
636 for(int i=rowStart[r]+1; i<rowEnd[r]; i++)
637 assert(cols[i] > cols[i-1]);
638#endif
639 if(rowEnd[r] == rowMax[r] && rowEnd[r] == maxValues
640 && maxValues < (int)cols.size())
641 {
642// UG_LOG("at end\n");
643 // this row is stored at the end, so we can easily make more room
644 rowMax[r]++;
645 maxValues++;
646 }
647
648 if(rowEnd[r] == rowMax[r])
649 {
650// UG_LOG("renew\n");
651 // row is full, we need to copy it to another place
652 int newSize = (rowEnd[r]-rowStart[r])*2;
653 if(maxValues+newSize > (int)cols.size())
654 {
655// UG_LOG("ass\n");
656 assureValuesSize(maxValues+newSize);
657 index=get_index_internal(r, c);
658 }
659 // copy it to the end and insert index
660 fragmented += rowEnd[r]-rowStart[r];
661 index = index-rowStart[r]+maxValues;
662 int j=rowEnd[r]-rowStart[r]+maxValues;
663 if(rowEnd[r] != 0)
664 for(int i=rowEnd[r]-1; i>=rowStart[r]; i--, j--)
665 {
666 if(j==index) j--;
667 if(bNeedsValues) values[j] = values[i];
668 cols[j] = cols[i];
669 if(i==rowStart[r]) break;
670 }
671 rowEnd[r] = maxValues+rowEnd[r]-rowStart[r]+1;
672 rowStart[r] = maxValues;
673 rowMax[r] = maxValues+newSize;
674 maxValues += newSize;
675 }
676 else
677 {
678// UG_LOG("enlength\n");
679 // move part > index so we can insert the index
680 if(rowEnd[r] != 0)
681 for(int i=rowEnd[r]-1; i>=index; i--)
682 {
683 if(bNeedsValues) values[i+1] = values[i];
684 cols[i+1] = cols[i];
685 if(i==index) break;
686 }
687 rowEnd[r]++;
688 }
689 if(bNeedsValues) values[index] = 0.0;
690 cols[index] = c;
691
692 nnz++;
693#ifndef NDEBUG
694 assert(index >= rowStart[r] && index < rowEnd[r]);
695 for(int i=rowStart[r]+1; i<rowEnd[r]; i++)
696 assert(cols[i] > cols[i-1]);
697#endif
698 return index;
699
700}
701
702template<typename T>
703void SparseMatrix<T>::copyToNewSize(size_t newSize, size_t maxCol)
704{
705 PROFILE_SPMATRIX(SparseMatrix_copyToNewSize);
706 /*UG_LOG("copyToNewSize: from " << values.size() << " to " << newSize << "\n");
707 UG_LOG("sizes are " << cols.size() << " and " << values.size() << ", ");
708 UG_LOG(reset_floats << "capacities are " << cols.capacity() << " and " << values.capacity() << ", NNZ = " << nnz << ", fragmentation = " <<
709 (1-((double)nnz)/cols.size())*100.0 << "%\n");
710 if(newSize == nnz) { UG_LOG("Defragmenting to NNZ."); }*/
711 if( (iIterators > 0)
712 || (newSize > values.size() && (100.0*nnz)/newSize < 20 && newSize <= cols.capacity()) )
714 UG_ASSERT(newSize > values.size(), "no nnz-defragmenting while using iterators.");
715 //UG_LOG("copyToNew not defragmenting because of iterators or low fragmentation.\n");}
716 cols.resize(newSize);
717 cols.resize(cols.capacity());
718 if(bNeedsValues) { values.resize(newSize); values.resize(cols.size()); }
719 return;
722 std::vector<value_type> v(newSize);
723 std::vector<int> c(newSize);
724 size_t j=0;
725 for(size_t r=0; r<num_rows(); r++)
726 {
727 if(rowStart[r] == -1)
728 rowStart[r] = rowEnd[r] = rowMax[r] = j;
729 else
730 {
731 size_t start=j;
732 for(int k=rowStart[r]; k<rowEnd[r]; k++)
733 {
734 if(cols[k] < (int)maxCol)
735 {
736 if(bNeedsValues) v[j] = values[k];
737 c[j] = cols[k];
738 j++;
739 }
740 }
741 rowStart[r] = start;
742 rowEnd[r] = rowMax[r] = j;
743 }
744 }
745 rowStart[num_rows()] = rowEnd[num_rows()-1];
746 fragmented = 0;
747 maxValues = j;
748 if(bNeedsValues) values.swap(v);
749 cols.swap(c);
750}
751
752template<typename T>
754{
755 if((double)nnz/(double)maxValues < 0.9)
756 defragment();
757}
758
759template<typename T>
761{
762 if(s <= cols.size()) return;
763 size_t newSize = nnz*2;
764 if(newSize < s) newSize = s;
765 copyToNewSize(newSize);
766
767}
768
769template<typename T>
771{
772 int j=0;
773 for(size_t r=0; r<num_rows(); r++)
774 {
775 if(rowStart[r] == -1) continue;
776 for(int k=rowStart[r]; k<rowEnd[r]; k++)
777 if(cols[k] < (int)maxCols)
778 j++;
779 }
780 return j;
781}
782
783} // namespace ug
784
785#endif
786
parameterString s
Definition connection.h:40
size_t iIndex
Definition connection.h:42
Definition sparsematrix.h:421
Definition sparsematrix.h:366
value_type & value()
Definition sparsematrix.h:413
sparse matrix for big, variable sparse matrices.
Definition sparsematrix.h:99
void apply_transposed_ignore_zero_rows(vector_t &dest, const number &beta1, const vector_t &w1) const
calculated dest = beta1*A*w1 . For empty cols of A (=empty rows of A^T), dest will not be changed
Definition sparsematrix_impl.h:375
int get_index_internal(size_t row, int col) const
Definition sparsematrix_impl.h:553
int get_index_const(int r, int c) const
Definition sparsematrix_impl.h:584
void axpy(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const vector_t &w1) const
calculate dest = alpha1*v1 + beta1*A*w1 (A = this matrix)
Definition sparsematrix_impl.h:294
size_t nnz
Definition sparsematrix.h:742
void resize_and_clear(size_t newRows, size_t newCols)
resizes the SparseMatrix
Definition sparsematrix_impl.h:91
void copyToNewSize(size_t newSize)
Definition sparsematrix.h:716
void set_as_transpose_of2(const SparseMatrix< value_type > &B, double scale=1.0)
Definition sparsematrix_impl.h:186
void resize_and_keep_values(size_t newRows, size_t newCols)
Definition sparsematrix_impl.h:112
TValueType value_type
Definition sparsematrix.h:101
void assureValuesSize(size_t s)
Definition sparsematrix_impl.h:760
size_t num_rows() const
returns number of rows
Definition sparsematrix.h:342
void add(const M &mat)
Definition sparsematrix_impl.h:507
int maxValues
Definition sparsematrix.h:746
void check_fragmentation() const
Definition sparsematrix_impl.h:753
SparseMatrix()
constructor for empty SparseMatrix
Definition sparsematrix_impl.h:59
void mat_mult_add_row(size_t row, typename vector_t::value_type &dest, double alpha, const vector_t &v) const
calculates dest += alpha * A[row, .] v;
Definition sparsematrix_impl.h:259
bool is_isolated(size_t i) const
check for isolated condition of an index
Definition sparsematrix_impl.h:416
row_iterator end_row(size_t r)
Definition sparsematrix.h:485
void set_as_copy_of(const SparseMatrix< value_type > &B, double scale=1.0)
create/recreate this as a copy of SparseMatrix B
Definition sparsematrix_impl.h:472
void set_as_transpose_of(const SparseMatrix< value_type > &B, double scale=1.0)
write in a empty SparseMatrix (this) the transpose SparseMatrix of B.
Definition sparsematrix_impl.h:149
void set_matrix_row(size_t row, connection *c, size_t nr)
Definition sparsematrix_impl.h:429
void add_matrix_row(size_t row, connection *c, size_t nr)
Definition sparsematrix_impl.h:463
void apply_ignore_zero_rows(vector_t &dest, const number &beta1, const vector_t &w1) const
calculated dest = beta1*A*w1 . For empty rows, dest will not be changed
Definition sparsematrix_impl.h:273
int get_index(int r, int c)
Definition sparsematrix_impl.h:596
void scale(double d)
Definition sparsematrix_impl.h:487
size_t num_cols() const
returns the number of cols
Definition sparsematrix.h:345
void get(M &mat) const
get local matrix
Definition sparsematrix_impl.h:538
void clear_and_free()
Clears the matrix vectors and frees their memory.
Definition sparsematrix_impl.h:72
row_iterator begin_row(size_t r)
Definition sparsematrix.h:484
void clear_retain_structure()
Definition sparsematrix_impl.h:142
void axpy_transposed(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const vector_t &w1) const
calculate dest = alpha1*v1 + beta1*A^T*w1 (A = this matrix)
Definition sparsematrix_impl.h:344
int get_nnz_max_cols(size_t maxCols)
Definition sparsematrix_impl.h:770
bool bNeedsValues
Definition sparsematrix.h:743
void set(const M &mat)
set local matrix
Definition sparsematrix_impl.h:523
DenseMatrix< TStorage > MatrixTranspose(const DenseMatrix< TStorage > &A)
Definition densematrix.h:240
#define UG_ASSERT(expr, msg)
Definition assert.h:70
double number
Definition types.h:124
the ug namespace
bool iszero(__T __val)
Definition sparsematrix_impl.h:53
bool MatMultTransposedAdd(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const matrix_t &A1, const vector_t &w1)
calculates dest = alpha1*v1 + beta1 * A1 *w1;
Definition operations_mat.h:121
bool MatMultAdd(vector_t &dest, const number &alpha1, const vector_t &v1, const number &beta1, const matrix_t &A1, const vector_t &w1)
calculates dest = alpha1*v1 + beta1 * A1 *w1;
Definition operations_mat.h:68
bool MatMult(vector_t &dest, const number &beta1, const matrix_t &A1, const vector_t &w1)
calculates dest = beta1 * A1;
Definition operations_mat.h:59
void VecScaleAssign(double &dest, double alpha1, const double &v1)
calculates dest = alpha1*v1. for doubles
Definition operations_vec.h:49
#define PROFILE_SPMATRIX(name)
Definition sparsematrix.h:47
size_t num_rows() const
Definition sparsematrix_interface.h:38
const_row_iterator end_row(size_t row) const
void defragment()
const_row_iterator begin_row(size_t row) const
size_t num_cols() const
Definition sparsematrix_interface.h:39