Commit 5e529972 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Fixed UMFPACK problem for solving with multiple RHS vectors.

parent 169b9d9a
...@@ -54,9 +54,11 @@ namespace AMDiS { ...@@ -54,9 +54,11 @@ namespace AMDiS {
int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A, int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A,
SystemVector& x, SystemVector& x,
SystemVector& b, SystemVector& b,
VectorialMapper& m) VectorialMapper& m,
bool createMatrixData,
bool storeMatrixData)
{ {
return MTL4Solver< MTLTypes::MTLMatrix, MTLTypes::MTLVector, ITL_OEMSolver_runner< ITLSolver, MTLTypes::MTLMatrix, MTLTypes::MTLVector > >::solve(A,x,b,m); return MTL4Solver< MTLTypes::MTLMatrix, MTLTypes::MTLVector, ITL_OEMSolver_runner< ITLSolver, MTLTypes::MTLMatrix, MTLTypes::MTLVector > >::solve(A, x, b, m, createMatrixData, storeMatrixData);
} }
...@@ -96,9 +98,11 @@ namespace AMDiS { ...@@ -96,9 +98,11 @@ namespace AMDiS {
int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A, int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A,
SystemVector& x, SystemVector& x,
SystemVector& b, SystemVector& b,
VectorialMapper& m) VectorialMapper& m,
bool createMatrixData,
bool storeMatrixData)
{ {
return MTL4Solver< MTLMatrix, MTLVector, ITL_OEMSolver_para_runner< ITLSolver, MTLTypes::MTLMatrix, MTLTypes::MTLVector > >::solve(A,x,b,m); return MTL4Solver< MTLMatrix, MTLVector, ITL_OEMSolver_para_runner< ITLSolver, MTLTypes::MTLMatrix, MTLTypes::MTLVector > >::solve(A, x, b, m, createMatrixData, storeMatrixData);
} }
~ITL_OEMSolver_para() {} ~ITL_OEMSolver_para() {}
......
...@@ -66,16 +66,18 @@ namespace AMDiS { ...@@ -66,16 +66,18 @@ namespace AMDiS {
} }
template< typename Matrix, typename Vector, typename Mapper > template< typename Matrix, typename Vector, typename Mapper >
int solve(const Matrix& A, Vector& x, Vector& b, Mapper& mapper) int solve(const Matrix& A, Vector& x, Vector& b, Mapper& mapper,
bool createMatrixData,
bool storeMatrixData)
{ {
FUNCNAME("MTL4Solver::solve()"); FUNCNAME("MTL4Solver::solve()");
Timer t; Timer t;
if (num_rows(matrix) == 0 || !getMultipleRhs()) { if (createMatrixData) {
init(mapper, mtl::traits::is_distributed<MTLMatrix>()); init(mapper, mtl::traits::is_distributed<MTLMatrix>());
set_to_zero(matrix); set_to_zero(matrix);
MatMap< const Matrix, Mapper > matMap(A,mapper); MatMap< const Matrix, Mapper > matMap(A, mapper);
matrix << matMap; matrix << matMap;
worker.init(matrix); worker.init(matrix);
} }
...@@ -120,9 +122,11 @@ namespace AMDiS { ...@@ -120,9 +122,11 @@ namespace AMDiS {
virtual int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A, virtual int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A,
SystemVector& x, SystemVector& x,
SystemVector& b, SystemVector& b,
VectorialMapper& m) VectorialMapper& m,
bool createMatrixData,
bool storeMatrixData)
{ {
return solve(A,x,b,m); return solve(A, x, b, m, createMatrixData, storeMatrixData);
} }
......
...@@ -71,8 +71,7 @@ namespace AMDiS { ...@@ -71,8 +71,7 @@ namespace AMDiS {
residual(0), residual(0),
print_cycle(100), print_cycle(100),
iterations(-1), iterations(-1),
error(-1), error(-1)
multipleRhs(false)
{} {}
/// ///
...@@ -95,7 +94,9 @@ namespace AMDiS { ...@@ -95,7 +94,9 @@ namespace AMDiS {
virtual int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A, virtual int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A,
SystemVector& x, SystemVector& x,
SystemVector& b, SystemVector& b,
VectorialMapper&) VectorialMapper&,
bool createMatrixData,
bool storeMatrixData)
{ {
FUNCNAME("OEMSolver::solveSystem()"); FUNCNAME("OEMSolver::solveSystem()");
TEST_EXIT(false) TEST_EXIT(false)
...@@ -105,10 +106,12 @@ namespace AMDiS { ...@@ -105,10 +106,12 @@ namespace AMDiS {
inline int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A, inline int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A,
SystemVector& x, SystemVector& x,
SystemVector& b) SystemVector& b,
bool createMatrixData,
bool storeMatrixData)
{ {
VectorialMapper mapper(A); VectorialMapper mapper(A);
return solveSystem(A, x, b, mapper); return solveSystem(A, x, b, mapper, createMatrixData, storeMatrixData);
} }
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
...@@ -182,12 +185,6 @@ namespace AMDiS { ...@@ -182,12 +185,6 @@ namespace AMDiS {
return relative; return relative;
} }
/// Returns \ref multipleRhs
inline bool getMultipleRhs() const
{
return multipleRhs;
}
/** \} */ /** \} */
...@@ -235,11 +232,6 @@ namespace AMDiS { ...@@ -235,11 +232,6 @@ namespace AMDiS {
info = i; info = i;
} }
inline void setMultipleRhs(bool b)
{
multipleRhs = b;
}
/** \} */ /** \} */
protected: protected:
...@@ -269,11 +261,6 @@ namespace AMDiS { ...@@ -269,11 +261,6 @@ namespace AMDiS {
/// Error code in last solver (not set by UmfPack) /// Error code in last solver (not set by UmfPack)
int error; int error;
/// If true, the solver has to solve multiple right hand sides with the same
/// matrix. Some solvers, e.g. direct once, may take advanteges from this knowledge,
/// as they can do the factorization of the matrix only once.
bool multipleRhs;
}; };
/** /**
......
...@@ -201,9 +201,9 @@ namespace AMDiS { ...@@ -201,9 +201,9 @@ namespace AMDiS {
if (solver) { if (solver) {
WARNING("solver already created\n"); WARNING("solver already created\n");
} else { } else {
if (initFlag.isSet(INIT_SOLVER)) { if (initFlag.isSet(INIT_SOLVER))
createSolver(); createSolver();
}
if (adoptProblem && adoptFlag.isSet(INIT_SOLVER)) { if (adoptProblem && adoptFlag.isSet(INIT_SOLVER)) {
TEST_EXIT(!solver)("solver already created\n"); TEST_EXIT(!solver)("solver already created\n");
solver = adoptProblem->getSolver(); solver = adoptProblem->getSolver();
...@@ -576,11 +576,12 @@ namespace AMDiS { ...@@ -576,11 +576,12 @@ namespace AMDiS {
void ProblemStatSeq::doOtherStuff() void ProblemStatSeq::doOtherStuff()
{ {}
}
void ProblemStatSeq::solve(AdaptInfo *adaptInfo, bool, bool) void ProblemStatSeq::solve(AdaptInfo *adaptInfo,
bool createMatrixData,
bool storeMatrixData)
{ {
FUNCNAME("Problem::solve()"); FUNCNAME("Problem::solve()");
...@@ -591,7 +592,8 @@ namespace AMDiS { ...@@ -591,7 +592,8 @@ namespace AMDiS {
clock_t first = clock(); clock_t first = clock();
solver->solveSystem(solverMatrix, *solution, *rhs); solver->solveSystem(solverMatrix, *solution, *rhs,
createMatrixData, storeMatrixData);
INFO(info, 8)("solution of discrete system needed %.5f seconds\n", INFO(info, 8)("solution of discrete system needed %.5f seconds\n",
TIME_USED(first, clock())); TIME_USED(first, clock()));
...@@ -709,9 +711,6 @@ namespace AMDiS { ...@@ -709,9 +711,6 @@ namespace AMDiS {
{ {
FUNCNAME("ProblemStat::buildAfterCoarsen()"); FUNCNAME("ProblemStat::buildAfterCoarsen()");
// buildAfterCoarsen_sebastianMode(adaptInfo, flag);
// return;
if (dualMeshTraverseRequired()) { if (dualMeshTraverseRequired()) {
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
ERROR_EXIT("Dual mesh assemble does not work in parallel code!\n"); ERROR_EXIT("Dual mesh assemble does not work in parallel code!\n");
...@@ -858,12 +857,9 @@ namespace AMDiS { ...@@ -858,12 +857,9 @@ namespace AMDiS {
} }
if (asmMatrix) { if (asmMatrix) {
solver->setMultipleRhs(false);
solverMatrix.setMatrix(*systemMatrix); solverMatrix.setMatrix(*systemMatrix);
INFO(info, 8)("fillin of assembled matrix: %d\n", nnz); INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
} else {
solver->setMultipleRhs(true);
} }
...@@ -878,187 +874,6 @@ namespace AMDiS { ...@@ -878,187 +874,6 @@ namespace AMDiS {
} }
void ProblemStatSeq::buildAfterCoarsen_sebastianMode(AdaptInfo *adaptInfo, Flag flag)
{
FUNCNAME("ProblemStat::buildAfterCoarsen()");
clock_t first = clock();
for (int i = 0; i < static_cast<int>(meshes.size()); i++)
meshes[i]->dofCompress();
Flag assembleFlag =
flag |
(*systemMatrix)[0][0]->getAssembleFlag() |
rhs->getDOFVector(0)->getAssembleFlag() |
Mesh::CALL_LEAF_EL |
Mesh::FILL_COORDS |
Mesh::FILL_DET |
Mesh::FILL_GRD_LAMBDA |
Mesh::FILL_NEIGH;
if (useGetBound)
assembleFlag |= Mesh::FILL_BOUND;
traverseInfo.updateStatus();
// Used to calculate the overall number of non zero entries.
int nnz = 0;
/// === INITIALIZE ===
for (int i = 0; i < nComponents; i++) {
MSG("%d DOFs for %s\n",
componentSpaces[i]->getAdmin()->getUsedSize(),
componentSpaces[i]->getName().c_str());
rhs->getDOFVector(i)->set(0.0);
for (int j = 0; j < nComponents; j++) {
// Only if this variable is true, the current matrix will be assembled.
bool assembleMatrix = true;
// The DOFMatrix which should be assembled (or not, if assembleMatrix
// will be set to false).
DOFMatrix *matrix = (*systemMatrix)[i][j];
if (matrix)
matrix->calculateNnz();
// If the matrix was assembled before and it is marked to be assembled
// only once, it will not be assembled.
if (assembleMatrixOnlyOnce[i][j] && assembledMatrix[i][j]) {
assembleMatrix = false;
} else if (matrix) {
matrix->getBaseMatrix().
change_dim(componentSpaces[i]->getAdmin()->getUsedSize(),
componentSpaces[j]->getAdmin()->getUsedSize());
set_to_zero(matrix->getBaseMatrix());
}
// If there is no DOFMatrix, e.g., if it is completly 0, do not assemble.
if (!matrix || !assembleMatrix)
assembleMatrix = false;
// If the matrix should not be assembled, the rhs vector has to be considered.
// This will be only done, if i == j. So, if both is not true, we can jump
// to the next matrix.
if (!assembleMatrix && i != j) {
if (matrix)
nnz += matrix->getBaseMatrix().nnz();
continue;
}
if (assembleMatrix && matrix->getBoundaryManager())
matrix->getBoundaryManager()->initMatrix(matrix);
if (matrix && assembleMatrix)
matrix->startInsertion(matrix->getNnz());
}
}
// === TRAVERSE ===
Mesh *mesh = componentMeshes[0];
const FiniteElemSpace *feSpace = componentSpaces[0];
const BasisFunction *basisFcts = feSpace->getBasisFcts();
ElementMatrix elMat(basisFcts->getNumber(), basisFcts->getNumber());
ElementMatrix tmpElMat(elMat);
ElementVector elVec(basisFcts->getNumber());
ElementVector tmpElVec(elVec);
TraverseStack stack;
BoundaryType *bound =
useGetBound ? new BoundaryType[basisFcts->getNumber()] : NULL;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag);
while (elInfo) {
if (useGetBound)
basisFcts->getBound(elInfo, bound);
for (map<Operator*, vector<OperatorPos> >::iterator opIt = operators.begin();
opIt != operators.end(); ++opIt) {
if (opIt->first->getNeedDualTraverse() == true)
continue;
if (opFlags[opIt->first].isSet(Operator::MATRIX_OPERATOR)) {
set_to_zero(elMat);
opIt->first->getElementMatrix(elInfo, elMat, 1.0);
}
if (opFlags[opIt->first].isSet(Operator::VECTOR_OPERATOR)) {
set_to_zero(elVec);
opIt->first->getElementVector(elInfo, elVec, 1.0);
}
for (vector<OperatorPos>::iterator posIt = opIt->second.begin();
posIt != opIt->second.end(); ++posIt) {
if (posIt->operatorType.isSet(Operator::MATRIX_OPERATOR)) {
if (!posIt->factor || *(posIt->factor) == 1.0) {
(*systemMatrix)[posIt->row][posIt->col]->addElementMatrix(elMat, bound, elInfo, NULL);
} else {
tmpElMat = *(posIt->factor) * elMat;
(*systemMatrix)[posIt->row][posIt->col]->addElementMatrix(tmpElMat, bound, elInfo, NULL);
}
}
if (posIt->operatorType.isSet(Operator::VECTOR_OPERATOR)) {
if (!posIt->factor || *(posIt->factor) == 1.0) {
rhs->getDOFVector(posIt->row)->addElementVector(1.0, elVec, bound, elInfo);
} else {
tmpElVec = *(posIt->factor) * elVec;
rhs->getDOFVector(posIt->row)->addElementVector(1.0, tmpElVec, bound, elInfo);
}
}
}
}
elInfo = stack.traverseNext(elInfo);
}
if (useGetBound)
delete [] bound;
// === FINELIZE ===
for (int i = 0; i < nComponents; i++) {
for (int j = 0; j < nComponents; j++) {
bool assembleMatrix = true;
DOFMatrix *matrix = (*systemMatrix)[i][j];
if (assembleMatrixOnlyOnce[i][j] && assembledMatrix[i][j])
assembleMatrix = false;
if (!matrix || !assembleMatrix)
assembleMatrix = false;
if (!assembleMatrix && i != j)
continue;
assembledMatrix[i][j] = true;
if (assembleMatrix) {
matrix->clearDirichletRows();
matrix->finishInsertion();
}
if (assembleMatrix && matrix->getBoundaryManager())
matrix->getBoundaryManager()->exitMatrix(matrix);
if (matrix)
nnz += matrix->getBaseMatrix().nnz();
}
assembleBoundaryConditions(rhs->getDOFVector(i),
solution->getDOFVector(i),
componentMeshes[i],
assembleFlag);
}
solverMatrix.setMatrix(*systemMatrix);
INFO(info, 8)("fillin of assembled matrix: %d\n", nnz);
INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n",
TIME_USED(first, clock()));
}
bool ProblemStatSeq::dualMeshTraverseRequired() bool ProblemStatSeq::dualMeshTraverseRequired()
{ {
FUNCNAME("ProblemStat::dualMeshTraverseRequired()"); FUNCNAME("ProblemStat::dualMeshTraverseRequired()");
......
...@@ -140,8 +140,6 @@ namespace AMDiS { ...@@ -140,8 +140,6 @@ namespace AMDiS {
bool assembleMatrix = true, bool assembleMatrix = true,
bool assembleVector = true); bool assembleVector = true);
void buildAfterCoarsen_sebastianMode(AdaptInfo *adaptInfo, Flag flag);
bool dualMeshTraverseRequired(); bool dualMeshTraverseRequired();
void dualAssemble(AdaptInfo *adaptInfo, Flag flag, void dualAssemble(AdaptInfo *adaptInfo, Flag flag,
......
...@@ -64,8 +64,12 @@ namespace AMDiS { ...@@ -64,8 +64,12 @@ namespace AMDiS {
void init(const Matrix& A) void init(const Matrix& A)
{ {
FUNCNAME("Umfpack_runner::init()") FUNCNAME("Umfpack_runner::init()")
if(solver != NULL)
if (solver != NULL) {
delete solver; delete solver;
solver = NULL;
}
solver = new mtl::matrix::umfpack::solver<matrix_type>(A, symmetric_strategy, alloc_init); solver = new mtl::matrix::umfpack::solver<matrix_type>(A, symmetric_strategy, alloc_init);
} }
...@@ -75,12 +79,10 @@ namespace AMDiS { ...@@ -75,12 +79,10 @@ namespace AMDiS {
FUNCNAME("Umfpack_runner::solve()"); FUNCNAME("Umfpack_runner::solve()");
TEST_EXIT(solver != NULL)("The umfpack solver was not initialized\n"); TEST_EXIT(solver != NULL)("The umfpack solver was not initialized\n");
#if 0 #if 0
if (!oem.getMultipleRhs()) {
if (store_symbolic) if (store_symbolic)
solver->update_numeric(); solver->update_numeric();
else else
solver->update(); solver->update();
}
#endif #endif
int code = (*solver)(x, b); int code = (*solver)(x, b);
...@@ -101,8 +103,10 @@ namespace AMDiS { ...@@ -101,8 +103,10 @@ namespace AMDiS {
~Umfpack_runner() ~Umfpack_runner()
{ {
if (solver != NULL) if (solver != NULL) {
delete solver; delete solver;
solver == NULL;
}
} }
private: private:
...@@ -142,12 +146,12 @@ namespace AMDiS { ...@@ -142,12 +146,12 @@ namespace AMDiS {
int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A, int solveSystem(const SolverMatrix<Matrix<DOFMatrix*> >& A,
SystemVector& x, SystemVector& x,
SystemVector& b, SystemVector& b,
VectorialMapper& m) VectorialMapper& m,
bool createMatrixData,
bool storeMatrixData)
{ {
return solve(A,x,b,m); return solve(A, x, b, m, createMatrixData, storeMatrixData);
} }
private:
}; };
} }
......
...@@ -84,14 +84,11 @@ namespace AMDiS { ...@@ -84,14 +84,11 @@ namespace AMDiS {
MSG("iter. | this->residual | red. | n |\n"); MSG("iter. | this->residual | red. | n |\n");
for (iter = 1; iter <= this->maxIter; iter++) { for (iter = 1; iter <= this->maxIter; iter++) {
if (iter == 1 || (buildCycle > 0 && (iter-1) % buildCycle == 0)) {
this->getLinearSolver()->setMultipleRhs(false);
// Assemble DF(x) and F(x) // Assemble DF(x) and F(x)
if (iter == 1 || (buildCycle > 0 && (iter-1) % buildCycle == 0))
prob->buildAfterCoarsen(adaptInfo, 0, true, true); prob->buildAfterCoarsen(adaptInfo, 0, true, true);
} else { else
this->getLinearSolver()->setMultipleRhs(true);
prob->buildAfterCoarsen(adaptInfo, 0, false, true); prob->buildAfterCoarsen(adaptInfo, 0, false, true);
}
// Initial guess is zero // Initial guess is zero
b->set(0.0); b->set(0.0);
......
...@@ -91,14 +91,11 @@ namespace AMDiS { ...@@ -91,14 +91,11 @@ namespace AMDiS {
MSG("iter. | this->residual | red. | n | lambda |\n"); MSG("iter. | this->residual | red. | n | lambda |\n");
for (iter = 1; iter <= this->maxIter; iter++) { for (iter = 1; iter <= this->maxIter; iter++) {
if (iter == 1 || (buildCycle > 0 && (iter-1) % buildCycle == 0)) {
this->getLinearSolver()->setMultipleRhs(false);
// Assemble DF(x) and F(x) // Assemble DF(x) and F(x)
if (iter == 1 || (buildCycle > 0 && (iter-1) % buildCycle == 0))
prob->buildAfterCoarsen(adaptInfo, 0, true, true); prob->buildAfterCoarsen(adaptInfo, 0, true, true);
} else { else
this->getLinearSolver()->setMultipleRhs(true);
prob->buildAfterCoarsen(adaptInfo, 0, false, true); prob->buildAfterCoarsen(adaptInfo, 0, false, true);
}