diff --git a/AMDiS/src/DOFMatrix.cc b/AMDiS/src/DOFMatrix.cc index 7f6d9754336db6bd0a4901f2069cd532227d17f4..6104d8ee28a9fe9ca219d8b8c9c9e38dec0ef5d1 100644 --- a/AMDiS/src/DOFMatrix.cc +++ b/AMDiS/src/DOFMatrix.cc @@ -238,18 +238,18 @@ namespace AMDiS { if (condition->applyBoundaryCondition()) { #ifdef HAVE_PARALLEL_DOMAIN_AMDIS - if (dofMap->isRankDof(rowIndices[i])) - applyDBCs.insert(static_cast<int>(row)); + // if (dofMap->isRankDof(rowIndices[i])) { + applyDBCs.insert(row); + // dirichletDofs.push_back(row); + // } #else - applyDBCs.insert(static_cast<int>(row)); + applyDBCs.insert(row); #endif } } else { for (int j = 0; j < nCol; j++) { DegreeOfFreedom col = colIndices[j]; - if (fabs(elMat[i][j]) > 1e-10) { - ins[row][col] += elMat[i][j]; - } + ins[row][col] += elMat[i][j]; } } } @@ -493,11 +493,16 @@ namespace AMDiS { { FUNCNAME("DOFMatrix::removeRowsWithDBC()"); + // Do the following only in sequential code. In parallel mode, the specific + // solver method must care about dirichlet boundary conditions. + +#ifndef HAVE_PARALLEL_DOMAIN_AMDIS inserter_type &ins = *inserter; for (std::set<int>::iterator it = rows->begin(); it != rows->end(); ++it) ins[*it][*it] = 1.0; rows->clear(); +#endif } diff --git a/AMDiS/src/DOFMatrix.h b/AMDiS/src/DOFMatrix.h index 5105828e941cfe9c67adec713fb4fe00925ebb22..84410b014e334742cb75e8936ba98dc78b8e047f 100644 --- a/AMDiS/src/DOFMatrix.h +++ b/AMDiS/src/DOFMatrix.h @@ -455,27 +455,25 @@ namespace AMDiS { /// Maps local col indices of an element to global matrix indices. vector<DegreeOfFreedom> colIndices; - /* \brief - * A set of row indices. When assembling the DOF matrix, all rows, that - * correspond to a dof at a dirichlet boundary, are ignored and the row is - * left blank. After assembling, the diagonal element of the matrix must be - * set to 1. The indices of all rows, where this should be done, are stored - * in this set. - */ + /// A set of row indices. When assembling the DOF matrix, all rows, that + /// correspond to a dof at a dirichlet boundary, are ignored and the row is + /// left blank. After assembling, the diagonal element of the matrix must be + /// set to 1. The indices of all rows, where this should be done, are stored + /// in this set. std::set<int> applyDBCs; - /* \brief - * Number of non zero entries per row (average). For instationary problems this - * information may be used in the next timestep to accelerate insertion of - * elemnts during assembling. - */ - int nnzPerRow; + /// Number of non zero entries per row (average). For instationary problems this + /// information may be used in the next timestep to accelerate insertion of + /// elemnts during assembling. + int nnzPerRow; #ifdef HAVE_PARALLEL_DOMAIN_AMDIS /// Is used in parallel computations to check whether specific DOFs in the /// row FE spaces are owned by the rank or not. This is used to ensure that /// Dirichlet BC is handled correctly in parallel computations. FeSpaceDofMap *dofMap; + + // std::set<DegreeOfFreedom> dirichletDofs; #endif /// Inserter object: implemented as pointer, allocated and deallocated as needed diff --git a/AMDiS/src/DOFVector.cc b/AMDiS/src/DOFVector.cc index 36ac7118450e2caff0f6fe525265fccc09080b12..e05c35a45c5eca0519368ae1a97164cbdba7ded8 100644 --- a/AMDiS/src/DOFVector.cc +++ b/AMDiS/src/DOFVector.cc @@ -219,10 +219,10 @@ namespace AMDiS { elInfo = stack.traverseNext(elInfo); } - #ifdef HAVE_PARALLEL_DOMAIN_AMDIS +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS double localResult = result; MPI::COMM_WORLD.Allreduce(&localResult, &result, 1, MPI_DOUBLE, MPI_SUM); - #endif +#endif return result; } diff --git a/AMDiS/src/DOFVector.h b/AMDiS/src/DOFVector.h index 41afc730400dd5447dff825fc3b5a2d7aeccbfc0..d334ab56116745e8bfe735d28d6b2e49166a61bb 100644 --- a/AMDiS/src/DOFVector.h +++ b/AMDiS/src/DOFVector.h @@ -250,6 +250,17 @@ namespace AMDiS { return dofMap->isRankDof(dof); } + + inline void setDirichletDofValue(DegreeOfFreedom dof, + T value) + { + dirichletDofValues[dof] = value; + } + + map<DegreeOfFreedom, T>& getDirichletValues() + { + return dirichletDofValues; + } #endif protected: @@ -282,10 +293,12 @@ namespace AMDiS { #ifdef HAVE_PARALLEL_DOMAIN_AMDIS FeSpaceDofMap *dofMap; -#endif + map<DegreeOfFreedom, T> dirichletDofValues; +#endif }; + /// Specifies which operation should be done after coarsening typedef enum{ NO_OPERATION = 0, diff --git a/AMDiS/src/DirichletBC.cc b/AMDiS/src/DirichletBC.cc index a739647d71268304ad26490c7ac3ebdb016efb67..a5f5ec79e2fe4d5d572d067317e4e341f0b7bb22 100644 --- a/AMDiS/src/DirichletBC.cc +++ b/AMDiS/src/DirichletBC.cc @@ -65,15 +65,22 @@ namespace AMDiS { for (int i = 0; i < nBasFcts; i++) { #ifdef HAVE_PARALLEL_DOMAIN_AMDIS - if (vector->isRankDof(dofIndices[i])) + // if (vector->isRankDof(dofIndices[i])) #endif if (localBound[i] == boundaryType) { + double value = 0.0; if (f) { elInfo->coordToWorld(*(basFcts->getCoords(i)), worldCoords); - (*vector)[dofIndices[i]] = (*f)(worldCoords); + value = (*f)(worldCoords); } if (dofVec) - (*vector)[dofIndices[i]] = (*dofVec)[dofIndices[i]]; + value = (*dofVec)[dofIndices[i]]; + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + vector->setDirichletDofValue(dofIndices[i], value); +#else + (*vector)[dofIndices[i]] = value; +#endif } } } diff --git a/AMDiS/src/Element.cc b/AMDiS/src/Element.cc index 07633a87c61a2fa880d83590c57f91245c7afeaa..f212abf6e18d54b7b80db9e04e34d4b705325418 100644 --- a/AMDiS/src/Element.cc +++ b/AMDiS/src/Element.cc @@ -76,13 +76,30 @@ namespace AMDiS { } - void Element::createNewDofPtrs() + void Element::createNewDofPtrs(bool setDofs) { FUNCNAME("Element::setDofPtrs()"); TEST_EXIT_DBG(mesh)("no mesh!\n"); dof = mesh->createDofPtrs(); + + if (setDofs) { + for (int i = 0; i < mesh->getGeo(VERTEX); i++) + dof[i] = mesh->getDof(VERTEX); + + if (mesh->getNumberOfDofs(EDGE)) + for (int i = 0; i < mesh->getGeo(EDGE); i++) + dof[mesh->getNode(EDGE) + i] = mesh->getDof(EDGE); + + if (mesh->getNumberOfDofs(FACE)) + for (int i = 0; i < mesh->getGeo(FACE); i++) + dof[mesh->getNode(FACE) + i] = mesh->getDof(FACE); + + if (mesh->getNumberOfDofs(CENTER)) + for (int i = 0; i < mesh->getGeo(CENTER); i++) + dof[mesh->getNode(CENTER) + i] = mesh->getDof(CENTER); + } } diff --git a/AMDiS/src/Element.h b/AMDiS/src/Element.h index a13d3c95f8df720337391eb342caac3cc6de0ecf..607eff4cf82684a5e1c4cff1ce002bac158df516 100644 --- a/AMDiS/src/Element.h +++ b/AMDiS/src/Element.h @@ -538,7 +538,7 @@ namespace AMDiS { void deserialize(std::istream &in); /// Sets Element's \ref dof pointer. - void createNewDofPtrs(); + void createNewDofPtrs(bool setDofs = false); protected: /// Sets Element's \ref index. Used by friend class Mesh. diff --git a/AMDiS/src/Mesh.h b/AMDiS/src/Mesh.h index 1bf6e97404efc6bdb9e13f9315fd22c5611dacc8..fa9d755d8b73108c70a99d54d184d0527de8aa96 100644 --- a/AMDiS/src/Mesh.h +++ b/AMDiS/src/Mesh.h @@ -803,7 +803,7 @@ namespace AMDiS { DimVec<int> nDof; /// Number of nodes on a single element where DOFs are located. Needed for - /// the (de-) allocation of the dof-vector on the element (\ref Element::dof). + /// the (de-) allocation of the DOF-vector on the element (\ref Element::dof). /// Here "node" is equivalent to the number of basis functions on the element. int nNodeEl; diff --git a/AMDiS/src/parallel/InteriorBoundary.cc b/AMDiS/src/parallel/InteriorBoundary.cc index 5451e74aafede2c0e849eca1b1fd0c7fd430e467..f907b32cc437db8502169e101126cb3e620e5880 100644 --- a/AMDiS/src/parallel/InteriorBoundary.cc +++ b/AMDiS/src/parallel/InteriorBoundary.cc @@ -12,6 +12,7 @@ #include "parallel/InteriorBoundary.h" #include "parallel/ElementObjectDatabase.h" +#include "parallel/MeshDistributor.h" #include "FiniteElemSpace.h" #include "BasisFunction.h" #include "Serializer.h" @@ -177,8 +178,18 @@ namespace AMDiS { bound.type = it->second; - AtomicBoundary& b = getNewPeriodic(otherElementRank); - b = bound; + if (MeshDistributor::sebastianMode) { + if (bound.rankObj.elIndex == 3 && + bound.rankObj.ithObj == 1 || + bound.rankObj.elIndex == 78 && + bound.rankObj.ithObj == 2) { + AtomicBoundary& b = getNewPeriodic(otherElementRank); + b = bound; + } + } else { + AtomicBoundary& b = getNewPeriodic(otherElementRank); + b = bound; + } } } diff --git a/AMDiS/src/parallel/MeshDistributor.cc b/AMDiS/src/parallel/MeshDistributor.cc index 644c52ed4d8429eb76cf2ab410fde711224c824a..aae499703c286b5ccc0f045a121f08226027aa67 100644 --- a/AMDiS/src/parallel/MeshDistributor.cc +++ b/AMDiS/src/parallel/MeshDistributor.cc @@ -68,6 +68,7 @@ namespace AMDiS { return (*dof1 < *dof2); } + bool MeshDistributor::sebastianMode = false; MeshDistributor::MeshDistributor() : problemStat(0), @@ -1322,10 +1323,6 @@ namespace AMDiS { // === Add new macro elements to mesh. === - TEST_EXIT_DBG(feSpaces.size() == 1)("Not yet implemented!\n"); - TEST_EXIT_DBG(feSpaces[0]->getBasisFcts()->getDegree() == 1) - ("Not yet implemented!\n"); - for (std::set<MacroElement*>::iterator it = newMacroEl.begin(); it != newMacroEl.end(); ++it) { MacroElement *mel = *it; @@ -1336,10 +1333,7 @@ namespace AMDiS { mel->setNeighbour(i, NULL); // Create new DOFs for the macro element. - mel->getElement()->createNewDofPtrs(); - - for (int i = 0; i < mesh->getGeo(VERTEX); i++) - mel->getElement()->setDof(i, mesh->getDof(VERTEX)); + mel->getElement()->createNewDofPtrs(true); // Push the macro element to all macro elements in mesh. mesh->getMacroElements().push_back(mel); diff --git a/AMDiS/src/parallel/MeshDistributor.h b/AMDiS/src/parallel/MeshDistributor.h index dff4bfb2bea2bfab44914fa1ba154092db922513..75c412dd9f5b476dbcf058dfcedf0c667e4f13b8 100644 --- a/AMDiS/src/parallel/MeshDistributor.h +++ b/AMDiS/src/parallel/MeshDistributor.h @@ -550,6 +550,8 @@ namespace AMDiS { MeshLevelData levelData; public: + static bool sebastianMode; + /// The boundary DOFs are sorted by subobject entities, i.e., first all /// face DOFs, edge DOFs and to the last vertex DOFs will be set to /// communication structure vectors, \ref sendDofs and \ref recvDofs. diff --git a/AMDiS/src/parallel/ParallelDofMapping.cc b/AMDiS/src/parallel/ParallelDofMapping.cc index bc306d6ccdd9a49347791e294dc337dad4a432ea..21d16e390a17527d36d8eed370ff47b1ad862df1 100644 --- a/AMDiS/src/parallel/ParallelDofMapping.cc +++ b/AMDiS/src/parallel/ParallelDofMapping.cc @@ -382,25 +382,74 @@ namespace AMDiS { stdMpi.startCommunication(); - { - for (DofComm::Iterator it(dofComm->getRecvDofs(), 0, feSpaces[i]); - !it.end(); it.nextRank()) { - int rank = it.getRank(); - if (meshLevel > 0) - rank = levelData->mapRank(rank, 0, meshLevel); - - int counter = 0; - for (; !it.endDofIter(); it.nextDof()) { - if (dofMap.count(it.getDofIndex())) { - DegreeOfFreedom d = stdMpi.getRecvData(rank)[counter++]; - if (globalIndex) - dofToMatIndex.add(i, dofMap[it.getDofIndex()].global, d); - else - dofToMatIndex.add(i, it.getDofIndex(), d); - } + for (DofComm::Iterator it(dofComm->getRecvDofs(), 0, feSpaces[i]); + !it.end(); it.nextRank()) { + int rank = it.getRank(); + if (meshLevel > 0) + rank = levelData->mapRank(rank, 0, meshLevel); + + int counter = 0; + for (; !it.endDofIter(); it.nextDof()) { + if (dofMap.count(it.getDofIndex())) { + DegreeOfFreedom d = stdMpi.getRecvData(rank)[counter++]; + if (globalIndex) + dofToMatIndex.add(i, dofMap[it.getDofIndex()].global, d); + else + dofToMatIndex.add(i, it.getDofIndex(), d); } } } + + + // === Communicate DOFs on periodic boundaries. === + + stdMpi.clear(); + + for (DofComm::Iterator it(dofComm->getPeriodicDofs(), 0, feSpaces[i]); + !it.end(); it.nextRank()) { + vector<DegreeOfFreedom> sendGlobalDofs; + + for (; !it.endDofIter(); it.nextDof()) + if (dofMap.count(it.getDofIndex())) { + if (globalIndex) { + sendGlobalDofs.push_back(dofMap[it.getDofIndex()].global); + sendGlobalDofs.push_back(dofToMatIndex.get(i, dofMap[it.getDofIndex()].global)); + } else { + sendGlobalDofs.push_back(dofToMatIndex.get(i, it.getDofIndex())); + } + } + + int rank = it.getRank(); + if (meshLevel > 0) + rank = levelData->mapRank(rank, 0, meshLevel); + + stdMpi.send(rank, sendGlobalDofs); + stdMpi.recv(rank); + } + + stdMpi.startCommunication(); + + for (DofComm::Iterator it(dofComm->getPeriodicDofs(), 0, feSpaces[i]); + !it.end(); it.nextRank()) { + + int rank = it.getRank(); + if (meshLevel > 0) + rank = levelData->mapRank(rank, 0, meshLevel); + + int counter = 0; + + for (; !it.endDofIter(); it.nextDof()) + if (dofMap.count(it.getDofIndex())) { + if (globalIndex) { + dofToMatIndex.add(i, + stdMpi.getRecvData(it.getRank())[counter++], + stdMpi.getRecvData(it.getRank())[counter++]); + } else { + dofToMatIndex.add(i, it.getDofIndex(), + stdMpi.getRecvData(it.getRank())[counter++]); + } + } + } } } diff --git a/AMDiS/src/parallel/PetscSolver.h b/AMDiS/src/parallel/PetscSolver.h index 022a50b39fc77fd765ce4dd9a2e21ec91d29d2fc..231a9203046edd6e2191ce0e80950cbaaa1aa540 100644 --- a/AMDiS/src/parallel/PetscSolver.h +++ b/AMDiS/src/parallel/PetscSolver.h @@ -125,8 +125,9 @@ namespace AMDiS { DegreeOfFreedom dof) { FUNCNAME("PetscSolver::isCoarseSpace()"); - TEST_EXIT_DBG(coarseSpaceMap) - ("Subdomain solver does not contain a coarse space!\n"); + + if (coarseSpaceMap == NULL) + return false; return (*coarseSpaceMap)[feSpace].isSet(dof); } diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index 9d4b86ec332d669e487fb05a97491783ed8bd273..c7de58a86fd0e3281bb60b05036c2860b696cdd6 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -22,6 +22,12 @@ namespace AMDiS { using namespace std; + double FetiTimings::fetiSolve = 0.0; + double FetiTimings::fetiSolve01 = 0.0; + double FetiTimings::fetiSolve02 = 0.0; + double FetiTimings::fetiPreconditioner = 0.0; + + // y = mat * x int petscMultMatSchurPrimal(Mat mat, Vec x, Vec y) { @@ -44,25 +50,44 @@ namespace AMDiS { // y = mat * x int petscMultMatFeti(Mat mat, Vec x, Vec y) { + FUNCNAME("petscMultMatFeti()"); + // F = L inv(K_BB) trans(L) + L inv(K_BB) K_BPi inv(S_PiPi) K_PiB inv(K_BB) trans(L) // => F = L [I + inv(K_BB) K_BPi inv(S_PiPi) K_PiB] inv(K_BB) trans(L) + double wtime = MPI::Wtime(); + void *ctx; MatShellGetContext(mat, &ctx); FetiData* data = static_cast<FetiData*>(ctx); MatMultTranspose(*(data->mat_lagrange), x, data->tmp_vec_b); + + double wtime01 = MPI::Wtime(); data->subSolver->solveGlobal(data->tmp_vec_b, data->tmp_vec_b); + + FetiTimings::fetiSolve01 += (MPI::Wtime() - wtime01); + MatMult(*(data->mat_lagrange), data->tmp_vec_b, data->tmp_vec_lagrange); MatMult(data->subSolver->getMatCoarseInt(), data->tmp_vec_b, data->tmp_vec_primal); + + wtime01 = MPI::Wtime(); KSPSolve(*(data->ksp_schur_primal), data->tmp_vec_primal, data->tmp_vec_primal); + FetiTimings::fetiSolve02 += (MPI::Wtime() - wtime01); + MatMult(data->subSolver->getMatIntCoarse(), data->tmp_vec_primal, data->tmp_vec_b); + + wtime01 = MPI::Wtime(); data->subSolver->solveGlobal(data->tmp_vec_b, data->tmp_vec_b); + FetiTimings::fetiSolve01 += (MPI::Wtime() - wtime01); + MatMult(*(data->mat_lagrange), data->tmp_vec_b, y); VecAXPBY(y, 1.0, 1.0, data->tmp_vec_lagrange); + FetiTimings::fetiSolve += (MPI::Wtime() - wtime); + return 0; } @@ -70,6 +95,8 @@ namespace AMDiS { // y = PC * x PetscErrorCode petscApplyFetiDirichletPrecon(PC pc, Vec x, Vec y) { + double wtime = MPI::Wtime(); + // Get data for the preconditioner void *ctx; PCShellGetContext(pc, &ctx); @@ -125,6 +152,8 @@ namespace AMDiS { // Multiply with scaled Lagrange constraint matrix. MatMult(*(data->mat_lagrange_scaled), data->tmp_vec_b, y); + FetiTimings::fetiPreconditioner += (MPI::Wtime() - wtime); + return 0; } @@ -1452,6 +1481,7 @@ namespace AMDiS { MSG("FETI-DP timing 09: %.5f seconds (create rhs vector)\n", MPI::Wtime() - wtime); wtime = MPI::Wtime(); + FetiTimings::reset(); } @@ -1463,6 +1493,11 @@ namespace AMDiS { MSG("FETI-DP timing 10: %.5f seconds (application of FETI-DP operator)\n", MPI::Wtime() - wtime); wtime = MPI::Wtime(); + + MSG("FETI-DP timing 10a: %.5f [ %.5f %.5f ] seconds (FETI-DP KSP Solve)\n", + FetiTimings::fetiSolve, FetiTimings::fetiSolve01, FetiTimings::fetiSolve02); + MSG("FETI-DP timing 10b: %.5f seconds (FETI-DP KSP Solve)\n", + FetiTimings::fetiPreconditioner); } // === Solve for u_primals. === diff --git a/AMDiS/src/parallel/PetscSolverFeti.h b/AMDiS/src/parallel/PetscSolverFeti.h index 0a3cf2771876b14582ee641425306b37f8ee5551..cbe71f8713cfd5f2b24c4e38d5e05fce938b060b 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.h +++ b/AMDiS/src/parallel/PetscSolverFeti.h @@ -269,6 +269,27 @@ namespace AMDiS { bool printTimings; }; + + class FetiTimings { + private: + FetiTimings() {} + + public: + static void reset() + { + fetiSolve = 0.0; + fetiSolve01 = 0.0; + fetiSolve02 = 0.0; + fetiPreconditioner = 0.0; + } + + public: + static double fetiSolve; + static double fetiSolve01; + static double fetiSolve02; + + static double fetiPreconditioner; + }; } #endif diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc index 78146dc3aac96ad5fc38fabd951584c1a1825a81..d7b3d3ac81603e6d190afc8a7ecd9564e6cfe893 100644 --- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc +++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc @@ -102,7 +102,14 @@ namespace AMDiS { MatAssemblyBegin(matIntInt, MAT_FINAL_ASSEMBLY); MatAssemblyEnd(matIntInt, MAT_FINAL_ASSEMBLY); + + // === Remove Dirichlet BC DOFs. === + + removeDirichletBcDofs(mat); + + // === Init PETSc solver. === + KSPCreate(mpiCommGlobal, &kspInterior); KSPGetPC(kspInterior, &pcInterior); KSPSetOperators(kspInterior, matIntInt, matIntInt, SAME_NONZERO_PATTERN); @@ -296,6 +303,10 @@ namespace AMDiS { } + // === Remove Dirichlet BC DOFs. === + + removeDirichletBcDofs(mat); + // === Create solver for the non primal (thus local) variables. === KSPCreate(mpiCommLocal, &kspInterior); @@ -342,6 +353,10 @@ namespace AMDiS { } + // === Remove Dirichlet BC DOFs. === + removeDirichletBcDofs(vec); + + VecAssemblyBegin(rhsInterior); VecAssemblyEnd(rhsInterior); @@ -350,6 +365,9 @@ namespace AMDiS { VecAssemblyEnd(rhsCoarseSpace); } + + // === Remove null space, if requested. === + if (removeRhsNullSpace) { TEST_EXIT_DBG(coarseSpaceMap == NULL)("Not supported!\n"); @@ -409,6 +427,9 @@ namespace AMDiS { { FUNCNAME("PetscSolverGlobalMatrix::solveGlobal()"); + double wtime = MPI::Wtime(); + double t0 = 0.0, t1 = 0.0; + Vec tmp; if (mpiCommLocal.Get_size() == 1) VecCreateSeq(mpiCommLocal, interiorMap->getRankDofs(), &tmp); @@ -428,7 +449,13 @@ namespace AMDiS { VecRestoreArray(rhs, &rhsValues); VecRestoreArray(tmp, &tmpValues); + t0 = MPI::Wtime() - wtime; + + wtime = MPI::Wtime(); KSPSolve(kspInterior, tmp, tmp); + t1 = MPI::Wtime() - wtime; + + wtime = MPI::Wtime(); VecGetArray(tmp, &tmpValues); VecGetArray(sol, &rhsValues); @@ -440,6 +467,9 @@ namespace AMDiS { VecRestoreArray(tmp, &tmpValues); VecDestroy(&tmp); + t0 += MPI::Wtime() - wtime; + + MSG("TIMEING: %.5f %.5f\n", t0, t1); } @@ -712,7 +742,7 @@ namespace AMDiS { if (rankOnly && !(*interiorMap)[feSpace].isRankDof(dofIt.getDOFIndex())) continue; - if (coarseSpaceMap && isCoarseSpace(feSpace, dofIt.getDOFIndex())) { + if (isCoarseSpace(feSpace, dofIt.getDOFIndex())) { TEST_EXIT_DBG(vecCoarse != PETSC_NULL)("Should not happen!\n"); int index = coarseSpaceMap->getMatIndex(nRowVec, dofIt.getDOFIndex()); @@ -752,6 +782,85 @@ namespace AMDiS { } + void PetscSolverGlobalMatrix::removeDirichletBcDofs(Matrix<DOFMatrix*> *mat) + { + FUNCNAME("PetscSolverGlobalMatrix::removeDirichletBcDofs()"); + + vector<int> dofsInterior, dofsCoarse; + + int nComponents = mat->getNumRows(); + for (int i = 0; i < nComponents; i++) { + if ((*mat)[i][i]) { + const FiniteElemSpace *feSpace = (*mat)[i][i]->getRowFeSpace(); + + std::set<DegreeOfFreedom> &dirichletDofs = *((*mat)[i][i]->getApplyDBCs()); + + MSG("DIRICHLET DOFS: %d %d -> %d\n", i, i, dirichletDofs.size()); + + for (std::set<DegreeOfFreedom>::iterator it = dirichletDofs.begin(); + it != dirichletDofs.end(); ++it) { + if (isCoarseSpace(feSpace, *it)) { + if ((*coarseSpaceMap)[feSpace].isRankDof(*it)) + dofsCoarse.push_back(coarseSpaceMap->getMatIndex(i, *it)); + } else { + if ((*interiorMap)[feSpace].isRankDof(*it)) + dofsInterior.push_back(interiorMap->getMatIndex(i, *it)); + } + } + } else { + MSG("NO MAT DIAG in %d\n", i); + } + } + + MatZeroRows(matIntInt, dofsInterior.size(), &(dofsInterior[0]), 1.0, + PETSC_NULL, PETSC_NULL); + + if (coarseSpaceMap != NULL) + MatZeroRows(matCoarseCoarse, dofsCoarse.size(), &(dofsCoarse[0]), 1.0, + PETSC_NULL, PETSC_NULL); + } + + + void PetscSolverGlobalMatrix::removeDirichletBcDofs(SystemVector *vec) + { + FUNCNAME("PetscSolverGlobalMatrix::removeDirichletBcDofs()"); + + int nComponents = vec->getSize(); + for (int i = 0; i < nComponents; i++) { + const FiniteElemSpace *feSpace = vec->getDOFVector(i)->getFeSpace(); + + map<DegreeOfFreedom, double> &dirichletValues = + vec->getDOFVector(i)->getDirichletValues(); + + MSG("DIRICHLET DOFS: %d -> %d\n", i, dirichletValues.size()); + + MSG("MAT IS GLOBAL: %d\n", interiorMap->isMatIndexFromGlobal()); +// if (interiorMap->isMatIndexFromGlobal()) +// index = +// interiorMap->getMatIndex(nRowVec, globalRowDof) + rStartInterior; +// else +// index = +// interiorMap->getMatIndex(nRowVec, dofIt.getDOFIndex()) + rStartInterior; + + + for (map<DegreeOfFreedom, double>::iterator it = dirichletValues.begin(); + it != dirichletValues.end(); ++it) { + if (isCoarseSpace(feSpace, it->first)) { + if ((*coarseSpaceMap)[feSpace].isRankDof(it->first)) + VecSetValue(rhsCoarseSpace, coarseSpaceMap->getMatIndex(i, it->first), + it->second, INSERT_VALUES); + } else { + if ((*interiorMap)[feSpace].isRankDof(it->first)) { + MSG("REMOVE: %d %d %d\n", i, it->first, interiorMap->getMatIndex(i, it->first)); + VecSetValue(rhsInterior, interiorMap->getMatIndex(i, it->first), + it->second, INSERT_VALUES); + } + } + } + } + } + + void PetscSolverGlobalMatrix::createPetscNnzStructure(Matrix<DOFMatrix*> *mat) { FUNCNAME("PetscSolverGlobalMatrix::createPetscNnzStructure()"); diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.h b/AMDiS/src/parallel/PetscSolverGlobalMatrix.h index 94d2117b46bb9026a775ae2256275be80a3a9edf..ac2631300c9e61b104431099f53ed6448d8b2048 100644 --- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.h +++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.h @@ -75,6 +75,10 @@ namespace AMDiS { DOFVector<double>* vec, int nRowVec, bool rankOnly = false); + void removeDirichletBcDofs(Matrix<DOFMatrix*> *mat); + + void removeDirichletBcDofs(SystemVector *vec); + inline void setDofVector(Vec vecInterior, DOFVector<double>* vec, int nRowVec, bool rankOnly = false) @@ -89,12 +93,10 @@ namespace AMDiS { Vec petscSolVec; - /** \brief - * Stores the mesh change index of the mesh the nnz structure was created for. - * Therefore, if the mesh change index is higher than this value, we have to create - * a new nnz structure for PETSc matrices, because the mesh has been changed and - * therefore also the assembled matrix structure. - */ + /// Stores the mesh change index of the mesh the nnz structure was created for. + /// Therefore, if the mesh change index is higher than this value, we have to create + /// a new nnz structure for PETSc matrices, because the mesh has been changed and + /// therefore also the assembled matrix structure. int lastMeshNnz; bool zeroStartVector;