Unexpected behaviour of BCRSMatrix implict buildmode
The behaviour of the implicit build mode is in several ways unexpected and does not fit its documentation:
- (a) In contrast to the documentation, the allocated overflow area is not used while filling the matrix in favour of a separate
std::map
. - (b) The allocated overflow area does always contain
4*avg
more entries than expected. - (c) The given
avg
value is not really related to average row sizes. If you give the exact average,compres()
may fail if the overflow size is zero. - (d) The allocated overflow area is in fact used to balance the mismatch between the given
avg
value and rows having more entries than this. - (e)
compress()
may fail depending on the row order: The following will fail forrow=0
but succeed forrow=5
using M = Dune::BCRSMatrix<Dune::FieldMatrix<double,1,1>>; M m(6, 6, 1, 0.0, M::implicit); for(std::size_t i=0; i<6; ++i) m.entry(row,i) = i; m.compress();
Explanation for this behaviour: When allocating storage, this is partitioned into the overflow area followed by avg
reserved entries per row.
When more than avg
entries are used in a row, they are stored in an additional std::map
. On compress()
all entries are shifted forward towards the first
free position, inserting intermediate entries from the overflow map when necessary. This explains, why early rows cannot have more than avg
+overflow
entries, while later ones may consume remaining space left by preceding less populated rows.
Due to (a) there is a possible fix for several of those problems. Before compressing forward with insertion of overflow entries, one can compress backwards without this insertion. This would solve (c)-(e) at the price of an additional shifting operation. Even more, this would allow to compute the number of non-zeros in the first sweep and than allocate new storage if the overflow was to small instead of throwing an exception and letting the user assemble all entries again with a hopefully better guess.