diff --git a/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc b/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc index a7247f50e6c13329780477a4ae785c5b37a867a5..558dc46a5e08466b41fb4108a1b09be102f69bc1 100644 --- a/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc +++ b/AMDiS/src/parallel/ParallelCoarseSpaceSolver.cc @@ -154,14 +154,13 @@ namespace AMDiS { MatCreateSeqAIJ(mpiCommLocal, nRankInteriorRows, nRankInteriorRows, 0, nnz[0][0].dnnz, &mat[0][0]); - MatSetOption(mat[0][0], MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); } else { MatCreateAIJ(mpiCommGlobal, nRankInteriorRows, nRankInteriorRows, nOverallInteriorRows, nOverallInteriorRows, 0, nnz[0][0].dnnz, 0, nnz[0][0].onnz, - &mat[0][0]); - MatSetOption(mat[0][0], MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); + &mat[0][0]); } + MatSetOption(mat[0][0], MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); VecCreateMPI(mpiCommGlobal, nRankInteriorRows, nOverallInteriorRows, &vecSol[0]); VecCreateMPI(mpiCommGlobal, nRankInteriorRows, nOverallInteriorRows, &vecRhs[0]); @@ -178,6 +177,7 @@ namespace AMDiS { nOverallCoarseRows, nOverallCoarseRows, 0, nnz[i + 1][i + 1].dnnz, 0, nnz[i + 1][i + 1].onnz, &mat[i + 1][i + 1]); + MatSetOption(mat[i + 1][i + 1], MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE); cMap->createVec(vecSol[i + 1]); cMap->createVec(vecRhs[i + 1]); } diff --git a/AMDiS/src/parallel/ParallelCoarseSpaceSolver.h b/AMDiS/src/parallel/ParallelCoarseSpaceSolver.h index 452bb0c0eb6f10d5f8a3741a7d9c26b16e2bea2b..f4c21fd61313e9efc326dbe7aca8f94a88b50e49 100644 --- a/AMDiS/src/parallel/ParallelCoarseSpaceSolver.h +++ b/AMDiS/src/parallel/ParallelCoarseSpaceSolver.h @@ -234,6 +234,12 @@ namespace AMDiS { } + /// Returns whether the solver has a coarse grid. + inline bool hasCoarseSpace() + { + return (!coarseSpaceMap.empty()); + } + protected: /// Prepare internal data structures. First, it create \ref uniqueCoarseMap /// and \ref componentIthCoarseMap . Both are used to create the correct diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index 6597dc2c57e437a568280c0d33d73de7e86c4a3f..5cdc1ce415ace8847bc8f527e1e66763ca548810 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -108,7 +108,8 @@ namespace AMDiS { if (subdomain == NULL) { subdomain = new PetscSolverGlobalMatrix(""); subdomain->setSymmetric(isSymmetric); - subdomain->setHandleDirichletRows(false); + // subdomain->setHandleDirichletRows(false); + subdomain->setHandleDirichletRows(true); if (meshLevel == 0) { subdomain->setMeshDistributor(meshDistributor, @@ -142,6 +143,8 @@ namespace AMDiS { { FUNCNAME("PetscSolverFeti::createDirichletData()"); + return; + int nComponents = mat.getSize(); for (int component = 0; component < nComponents; component++) { DOFMatrix* dofMat = mat[component][component]; diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc index 18e75fa99b630f5bf47064a046da8c90b1825bfe..a7b916a4c92d22cbf37a2978800610d1db43019d 100644 --- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc +++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc @@ -17,6 +17,17 @@ namespace AMDiS { + + PetscSolverGlobalMatrix::PetscSolverGlobalMatrix(string name) + : PetscSolver(name), + zeroStartVector(false), + printMatInfo(false) + { + Parameters::get("parallel->use zero start vector", zeroStartVector); + Parameters::get("parallel->print matrix info", printMatInfo); + } + + void PetscSolverGlobalMatrix::fillPetscMatrix(Matrix<DOFMatrix*> *seqMat) { FUNCNAME("PetscSolverGlobalMatrix::fillPetscMatrix()"); @@ -54,7 +65,7 @@ namespace AMDiS { matAssembly(); - removeDirichletRows(seqMat, dofMap, getMatInterior()); + removeDirichletRows(seqMat); if (printMatInfo) { MatInfo matInfo; @@ -225,6 +236,8 @@ namespace AMDiS { matAssembly(); + removeDirichletRows(seqMat); + // === Create solver for the non primal (thus local) variables. === KSPCreate(mpiCommLocal, &kspInterior); @@ -266,7 +279,7 @@ namespace AMDiS { vecRhsAssembly(); - removeDirichletRows(vec, dofMap, getVecRhsInterior()); + removeDirichletRows(vec); // === For debugging allow to write the rhs vector to a file. === @@ -456,26 +469,25 @@ namespace AMDiS { } - void PetscSolverGlobalMatrix::removeDirichletRows(Matrix<DOFMatrix*> *seqMat, - ParallelDofMapping &dofMap, - Mat mpiMat) + void PetscSolverGlobalMatrix::removeDirichletRows(Matrix<DOFMatrix*> *seqMat) { FUNCNAME("PetscSolverGlobalMatrix::removeDirichletRows()"); if (!handleDirichletRows) return; + vector<int> dRowsInterior, dRowsCoarse; + vector<int> dColsInterior, dColsCoarse; + vector<double> dValuesInterior, dValuesCoarse; + int nComponents = seqMat->getSize(); - vector<int> dirichletRows; - vector<int> dirichletCols; - vector<double> dirichletValues; - for (int i = 0; i < nComponents; i++) { + for (int rowComp = 0; rowComp < nComponents; rowComp++) { bool dirichletRow = false; int dirichletMainCol = -1; - for (int j = 0; j < nComponents; j++) { - DOFMatrix *dofMat = (*seqMat)[i][j]; + for (int colComp = 0; colComp < nComponents; colComp++) { + DOFMatrix *dofMat = (*seqMat)[rowComp][colComp]; if (!dofMat) continue; @@ -486,7 +498,7 @@ namespace AMDiS { if (bIt->second && bIt->second->isDirichlet()) { dirichletRow = true; if ((dynamic_cast<DirichletBC*>(bIt->second))->applyBoundaryCondition()) { - dirichletMainCol = j; + dirichletMainCol = colComp; break; } } @@ -496,65 +508,152 @@ namespace AMDiS { if (!dirichletRow) continue; - DOFMatrix *dofMat = (*seqMat)[i][dirichletMainCol]; - const FiniteElemSpace *feSpace = dofMat->getRowFeSpace(); + DOFMatrix *dofMat = (*seqMat)[rowComp][dirichletMainCol]; TEST_EXIT(dofMat->getRowFeSpace() == dofMat->getColFeSpace()) ("I have to think about this scenario! Really possible?\n"); + std::set<DegreeOfFreedom> &dRows = dofMat->getDirichletRows(); for (std::set<DegreeOfFreedom>::iterator dofIt = dRows.begin(); dofIt != dRows.end(); ++dofIt) { - MultiIndex multiIndex; - if (dofMap[feSpace].find(*dofIt, multiIndex) && - dofMap[feSpace].isRankDof(*dofIt)) { - int rowIndex = dofMap.getMatIndex(i, multiIndex.global); - int colIndex = dofMap.getMatIndex(dirichletMainCol, multiIndex.global); - dirichletRows.push_back(rowIndex); - dirichletCols.push_back(colIndex); - dirichletValues.push_back(1.0); + if (hasCoarseSpace()) { + bool isRowCoarse = isCoarseSpace(rowComp, *dofIt); + bool isColCoarse = isCoarseSpace(dirichletMainCol, *dofIt); + TEST_EXIT(isRowCoarse == isColCoarse) + ("Really possible? So reimplement AMDiS from the scratch!\n"); + + if (isRowCoarse) { + ParallelDofMapping *rowCoarseSpace = coarseSpaceMap[rowComp]; + ParallelDofMapping *colCoarseSpace = coarseSpaceMap[dirichletMainCol]; + + MultiIndex multiIndex; + if ((*rowCoarseSpace)[rowComp].find(*dofIt, multiIndex) && + (*rowCoarseSpace)[rowComp].isRankDof(*dofIt)) { + int rowIndex = rowCoarseSpace->getLocalMatIndex(rowComp, *dofIt); + int colIndex = colCoarseSpace->getLocalMatIndex(dirichletMainCol, *dofIt); + dRowsCoarse.push_back(rowIndex); + dColsCoarse.push_back(colIndex); + dValuesCoarse.push_back(1.0); + } + } else { + + MultiIndex multiIndex; + if ((*interiorMap)[rowComp].find(*dofIt, multiIndex) && + (*interiorMap)[rowComp].isRankDof(*dofIt)) { + int rowIndex = interiorMap->getLocalMatIndex(rowComp, *dofIt); + int colIndex = interiorMap->getLocalMatIndex(dirichletMainCol, *dofIt); + dRowsInterior.push_back(rowIndex); + dColsInterior.push_back(colIndex); + dValuesInterior.push_back(1.0); + } + } + } else { + MultiIndex multiIndex; + if ((*interiorMap)[rowComp].find(*dofIt, multiIndex) && + (*interiorMap)[rowComp].isRankDof(*dofIt)) { + int rowIndex = interiorMap->getMatIndex(rowComp, multiIndex.global); + int colIndex = interiorMap->getMatIndex(dirichletMainCol, multiIndex.global); + dRowsInterior.push_back(rowIndex); + dColsInterior.push_back(colIndex); + dValuesInterior.push_back(1.0); + } } } } - MatZeroRows(mpiMat, dirichletRows.size(), &(dirichletRows[0]), 0.0, - PETSC_NULL, PETSC_NULL); + { + Mat mpiMat = getMatInterior(); + MatZeroRows(mpiMat, dRowsInterior.size(), &(dRowsInterior[0]), 0.0, + PETSC_NULL, PETSC_NULL); + + for (int i = 0; i < static_cast<int>(dRowsInterior.size()); i++) + MatSetValue(mpiMat, dRowsInterior[i], dColsInterior[i], + dValuesInterior[i], INSERT_VALUES); + + MatAssemblyBegin(mpiMat, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(mpiMat, MAT_FINAL_ASSEMBLY); + } - for (int i = 0; i < static_cast<int>(dirichletRows.size()); i++) - MatSetValue(mpiMat, dirichletRows[i], dirichletCols[i], dirichletValues[i], INSERT_VALUES); - - MatAssemblyBegin(mpiMat, MAT_FINAL_ASSEMBLY); - MatAssemblyEnd(mpiMat, MAT_FINAL_ASSEMBLY); + if (hasCoarseSpace()) { + Mat mpiMat = getMatCoarse(); + MatZeroRows(mpiMat, dRowsCoarse.size(), &(dRowsCoarse[0]), 0.0, + PETSC_NULL, PETSC_NULL); + + for (int i = 0; i < static_cast<int>(dRowsCoarse.size()); i++) + MatSetValue(mpiMat, dRowsCoarse[i], dColsCoarse[i], + dValuesCoarse[i], INSERT_VALUES); + + MatAssemblyBegin(mpiMat, MAT_FINAL_ASSEMBLY); + MatAssemblyEnd(mpiMat, MAT_FINAL_ASSEMBLY); + } } - void PetscSolverGlobalMatrix::removeDirichletRows(SystemVector *seqVec, - ParallelDofMapping &dofMap, - Vec mpiVec) + void PetscSolverGlobalMatrix::removeDirichletRows(SystemVector *seqVec) { FUNCNAME("PetscSolverGlobalMatrix::removeDirichletRows()"); if (!handleDirichletRows) return; - int nComponents = seqVec->getSize(); - - for (int i = 0; i < nComponents; i++) { - DOFVector<double> *dofVec = seqVec->getDOFVector(i); - const FiniteElemSpace *feSpace = dofVec->getFeSpace(); + int cInterior = 0; + int cCoarse = 0; + int nComponents = seqVec->getSize(); + for (int component = 0; component < nComponents; component++) { + DOFVector<double> *dofVec = seqVec->getDOFVector(component); map<DegreeOfFreedom, double>& dValues = dofVec->getDirichletValues(); + for (map<DegreeOfFreedom, double>::iterator dofIt = dValues.begin(); dofIt != dValues.end(); ++dofIt) { - MultiIndex multiIndex; - if (dofMap[feSpace].find(dofIt->first, multiIndex) && - dofMap[feSpace].isRankDof(dofIt->first)) - VecSetValue(mpiVec, dofMap.getMatIndex(i, multiIndex.global), - dofIt->second, INSERT_VALUES); + if (hasCoarseSpace()) { + if (isCoarseSpace(component, dofIt->first)) { + ParallelDofMapping *rowCoarseSpace = coarseSpaceMap[component]; + MultiIndex multiIndex; + if ((*rowCoarseSpace)[component].find(dofIt->first, multiIndex) && + (*rowCoarseSpace)[component].isRankDof(dofIt->first)) { + if (dofIt->second > 0.5) + cCoarse++; + VecSetValue(getVecRhsCoarse(), + rowCoarseSpace->getMatIndex(component, multiIndex.global), + dofIt->second, INSERT_VALUES); + } + } else { + MultiIndex multiIndex; + if ((*interiorMap)[component].find(dofIt->first, multiIndex) && + (*interiorMap)[component].isRankDof(dofIt->first)) { + if (dofIt->second > 0.5) + cInterior++; + VecSetValue(getVecRhsInterior(), + interiorMap->getLocalMatIndex(component, dofIt->first), + dofIt->second, INSERT_VALUES); + } + } + } else { + MultiIndex multiIndex; + if ((*interiorMap)[component].find(dofIt->first, multiIndex) && + (*interiorMap)[component].isRankDof(dofIt->first)) { + if (dofIt->second > 0.5) + cInterior++; + VecSetValue(getVecRhsInterior(), + interiorMap->getMatIndex(component, multiIndex.global), + dofIt->second, INSERT_VALUES); + } + } } } - VecAssemblyBegin(mpiVec); - VecAssemblyEnd(mpiVec); + VecAssemblyBegin(getVecRhsInterior()); + VecAssemblyEnd(getVecRhsInterior()); + + if (hasCoarseSpace()) { + VecAssemblyBegin(getVecRhsCoarse()); + VecAssemblyEnd(getVecRhsCoarse()); + } + + mpi::globalAdd(cInterior); + mpi::globalAdd(cCoarse); + MSG("WORKED ON DIRICHLET DOFS: %d %d\n", cInterior, cCoarse); } diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.h b/AMDiS/src/parallel/PetscSolverGlobalMatrix.h index b3ff065d8b4a7812c570a05739c0cfdf226ae9ec..6ae8a3343eef3101ffd465cdceaca25a7c69782f 100644 --- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.h +++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.h @@ -39,14 +39,7 @@ namespace AMDiS { class PetscSolverGlobalMatrix : public PetscSolver { public: - PetscSolverGlobalMatrix(string name) - : PetscSolver(name), - zeroStartVector(false), - printMatInfo(false) - { - Parameters::get("parallel->use zero start vector", zeroStartVector); - Parameters::get("parallel->print matrix info", printMatInfo); - } + PetscSolverGlobalMatrix(string name); void fillPetscMatrix(Matrix<DOFMatrix*> *mat); @@ -63,13 +56,9 @@ namespace AMDiS { void destroyVectorData(); protected: - void removeDirichletRows(Matrix<DOFMatrix*> *seqMat, - ParallelDofMapping &dofMap, - Mat mpiMat); + void removeDirichletRows(Matrix<DOFMatrix*> *seqMat); - void removeDirichletRows(SystemVector *seqVec, - ParallelDofMapping &dofMap, - Vec mpiVec); + void removeDirichletRows(SystemVector *seqVec); /// Reads field split information and creats a splitting based on /// component numbers.