Skip to content
Snippets Groups Projects
Commit 7ac6cdab authored by Oliver Sander's avatar Oliver Sander
Browse files

Do not create a temporary copy of the matrix even if the ignoreNodes bitset is not empty

This save some memory when the matrix is large.  The dune-istl UMFPack solver
(which we use internally here) actually has support for sending only submatrices
to UMFPack proper.  Unfortunately, this feature is not well-documented...
Also, it only works if all dofs in a block-vector block are either completely
ignored or completely un-ignored.
parent 81cb6037
No related branches found
No related tags found
No related merge requests found
...@@ -68,7 +68,7 @@ public: ...@@ -68,7 +68,7 @@ public:
virtual void solve() virtual void solve()
{ {
// We may use the original rhs, but ISTL modifies it, so we need a non-const type here // We may use the original rhs, but ISTL modifies it, so we need a non-const type here
VectorType modifiedRhs = *rhs_; VectorType mutableRhs = *rhs_;
if (not this->ignoreNodes_) if (not this->ignoreNodes_)
{ {
...@@ -78,49 +78,67 @@ public: ...@@ -78,49 +78,67 @@ public:
Dune::InverseOperatorResult statistics; Dune::InverseOperatorResult statistics;
Dune::UMFPack<MatrixType> solver(*matrix_); Dune::UMFPack<MatrixType> solver(*matrix_);
solver.setOption(UMFPACK_PRL, 0); // no output at all solver.setOption(UMFPACK_PRL, 0); // no output at all
solver.apply(*x_, modifiedRhs, statistics); solver.apply(*x_, mutableRhs, statistics);
} }
else else
{ {
MatrixType modifiedStiffness = *matrix_; ///////////////////////////////////////////////////////////////////////////////////////////
//Dune::printmatrix(std::cout, modifiedStiffness, "mod stiffness", "--"); // Extract the set of matrix rows that do not correspond to ignored degrees of freedom.
// Unfortunately, not all cases are handled by the ISTL UMFPack solver. Currently,
/////////////////////////////////////////// // you can only remove complete block rows. If a block is only partially ignored,
// Modify Dirichlet rows // the dune-istl UMFPack solver cannot do it, and the code here will throw an exception.
/////////////////////////////////////////// // All this can be fixed, but it needs going into the istl UMFPack code.
///////////////////////////////////////////////////////////////////////////////////////////
std::set<std::size_t> nonIgnoreRows;
for (size_t i=0; i<matrix_->N(); i++)
{
auto ignoreCount = (*this->ignoreNodes_)[i].count();
if (ignoreCount==0)
nonIgnoreRows.insert(i);
else if (ignoreCount!=blocksize)
DUNE_THROW(Dune::NotImplemented, "Individual blocks must be either ignored completely, or not at all");
}
for (size_t j=0; j<modifiedStiffness.N(); j++) // Construct the solver
Dune::InverseOperatorResult statistics;
Dune::UMFPack<MatrixType> solver;
solver.setOption(UMFPACK_PRL, 0); // no output at all
// We eliminate all rows and columns(!) from the matrix that correspond to ignored degrees of freedom.
// Here is where the sparse LU decomposition is happenening.
solver.setSubMatrix(*matrix_,nonIgnoreRows);
// We need to modify the rhs vector by static condensation.
VectorType shortRhs(nonIgnoreRows.size());
int shortRowCount=0;
for (auto it = nonIgnoreRows.begin(); it!=nonIgnoreRows.end(); ++shortRowCount, ++it)
shortRhs[shortRowCount] = mutableRhs[*it];
shortRowCount = 0;
for (size_t i=0; i<matrix_->N(); i++)
{ {
auto cIt = modifiedStiffness[j].begin(); if ((*this->ignoreNodes_)[i][0])
auto cEndIt = modifiedStiffness[j].end(); continue;
auto cIt = (*matrix_)[i].begin();
auto cEndIt = (*matrix_)[i].end();
for (; cIt!=cEndIt; ++cIt) for (; cIt!=cEndIt; ++cIt)
{ if ((*this->ignoreNodes_)[cIt.index()][0])
for (int k=0; k<blocksize; k++) cIt->mmv((*x_)[cIt.index()], shortRhs[shortRowCount]);
if ((*this->ignoreNodes_)[j][k])
{ shortRowCount++;
(*cIt)[k] = 0;
if (cIt.index()==j)
(*cIt)[k][k] = 1.0;
}
}
for (int k=0; k<blocksize; k++)
if ((*this->ignoreNodes_)[j][k])
modifiedRhs[j][k] = (*x_)[j][k];
} }
//Dune::printmatrix(std::cout, modifiedStiffness, "mod stiffness", "--"); // Solve the reduced system
VectorType shortX(nonIgnoreRows.size());
solver.apply(shortX, shortRhs, statistics);
// Blow up the solution vector
shortRowCount=0;
for (auto it = nonIgnoreRows.begin(); it!=nonIgnoreRows.end(); ++shortRowCount, ++it)
(*x_)[*it] = shortX[shortRowCount];
/////////////////////////////////////////////////////////////////
// Solve the system
/////////////////////////////////////////////////////////////////
Dune::InverseOperatorResult statistics;
Dune::UMFPack<MatrixType> solver(modifiedStiffness);
solver.setOption(UMFPACK_PRL, 0); // no output at all
solver.apply(*x_, modifiedRhs, statistics);
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment