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*avgmore entries than expected. - (c) The given
avgvalue 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
avgvalue and rows having more entries than this. - (e)
compress()may fail depending on the row order: The following will fail forrow=0but succeed forrow=5using 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.