diff --git a/AMDiS/src/parallel/FeSpaceMapping.cc b/AMDiS/src/parallel/FeSpaceMapping.cc index 36d1d7f4810072600ab5dc0655ed2d1f56145d70..4167cc168c1297949be852556ddf74661a2e7c10 100644 --- a/AMDiS/src/parallel/FeSpaceMapping.cc +++ b/AMDiS/src/parallel/FeSpaceMapping.cc @@ -37,20 +37,20 @@ namespace AMDiS { mpi::getDofNumbering(*mpiComm, nRankDofs, rStartDofs, nOverallDofs); if (needGlobalMapping) - addOffset(rStartDofs); + computeGlobalMapping(rStartDofs); - if (overlap) + if (hasNonLocalDofs) computeNonLocalIndices(); } - void GlobalDofMap::addOffset(int offset) + void GlobalDofMap::computeGlobalMapping(int offset) { for (map<DegreeOfFreedom, MultiIndex>::iterator it = dofMap.begin(); it != dofMap.end(); ++it) it->second.global = it->second.local + offset; - // it->second.local += offset; } + void GlobalDofMap::computeNonLocalIndices() { FUNCNAME("GlobalDofMap::computeNonLocalIndices()"); diff --git a/AMDiS/src/parallel/FeSpaceMapping.h b/AMDiS/src/parallel/FeSpaceMapping.h index b283252794e0765535d5d693e88cc465701e96f9..88e8762e6e6551b9b0765ed7b5934be87fc1cd50 100644 --- a/AMDiS/src/parallel/FeSpaceMapping.h +++ b/AMDiS/src/parallel/FeSpaceMapping.h @@ -106,7 +106,7 @@ namespace AMDiS { nLocalDofs(0), nOverallDofs(0), rStartDofs(0), - overlap(false) + hasNonLocalDofs(false) {} void clear(); @@ -163,7 +163,7 @@ namespace AMDiS { void update(); - void addOffset(int offset); + void computeGlobalMapping(int offset); void computeNonLocalIndices(); @@ -174,9 +174,9 @@ namespace AMDiS { feSpace = fe; } - void setOverlap(bool b) + void setNonLocalDofs(bool b) { - overlap = b; + hasNonLocalDofs = b; } void setNeedGlobalMapping(bool b) @@ -209,7 +209,10 @@ namespace AMDiS { /// int nRankDofs, nLocalDofs, nOverallDofs, rStartDofs; - bool overlap; + /// Is true if there are DOFs in at least one subdomain that are not owned + /// by the rank. If the value is false, each rank contains only DOFs that + /// are also owned by this rank. + bool hasNonLocalDofs; }; @@ -221,7 +224,7 @@ namespace AMDiS { : mpiComm(NULL), sendDofs(NULL), recvDofs(NULL), - overlap(false), + hasNonLocalDofs(false), feSpaces(0), nRankDofs(-1), nOverallDofs(-1), @@ -328,17 +331,17 @@ namespace AMDiS { void init(MPI::Intracomm *m, vector<const FiniteElemSpace*> &fe, bool needGlobalMapping, - bool ol) + bool bNonLocalDofs) { mpiComm = m; feSpaces = fe; - overlap = ol; + hasNonLocalDofs = bNonLocalDofs; for (unsigned int i = 0; i < feSpaces.size(); i++) { feSpacesUnique.insert(feSpaces[i]); addFeSpace(feSpaces[i]); data[feSpaces[i]].setNeedGlobalMapping(needGlobalMapping); - data[feSpaces[i]].setOverlap(overlap); + data[feSpaces[i]].setNonLocalDofs(hasNonLocalDofs); } } @@ -370,14 +373,13 @@ namespace AMDiS { for (ItType it = dofMap.begin(); it != dofMap.end(); ++it) { if (data[feSpaces[i]].isRankDof(it->first)) { int globalMatIndex = it->second.local + offset; - -// int globalMatIndex = -// it->second.local - data[feSpaces[i]].rStartDofs + offset; dofToMatIndex.add(i, it->first, globalMatIndex); } } + + offset += data[feSpaces[i]].nRankDofs; - if (!overlap) + if (!hasNonLocalDofs) continue; TEST_EXIT_DBG(sendDofs != NULL && recvDofs != NULL) @@ -413,50 +415,9 @@ namespace AMDiS { } } } - - offset += data[feSpaces[i]].nRankDofs; } } - - inline int mapLocal(int index, int ithFeSpace) - { - int result = 0; - for (int i = 0; i < ithFeSpace; i++) - result += data[feSpaces[i]].nRankDofs; - result += data[feSpaces[ithFeSpace]][index].local; - - return result; - } - - inline int mapLocal(int index, const FiniteElemSpace *feSpace) - { - for (unsigned int i = 0; i < feSpaces.size(); i++) - if (feSpaces[i] == feSpace) - return mapLocal(index, feSpace, i); - - return -1; - } - - inline int mapGlobal(int index, int ithFeSpace) - { - int result = rStartDofs; - for (int i = 0; i < ithFeSpace; i++) - result += data[feSpaces[i]].nRankDofs; - result += data[feSpaces[ithFeSpace]][index].local; - - return result; - } - - inline int mapGlobal(int index, const FiniteElemSpace *feSpace) - { - for (unsigned int i = 0; i < feSpaces.size(); i++) - if (feSpaces[i] == feSpace) - return mapGlobal(index, feSpace, i); - - return -1; - } - void setDofComm(DofComm &pSend, DofComm &pRecv) { sendDofs = &pSend; @@ -469,11 +430,19 @@ namespace AMDiS { inline int getMatIndex(int ithComponent, DegreeOfFreedom d) { - FUNCNAME("FeSpaceData::getMatIndex()"); - return dofToMatIndex.get(ithComponent, d); } + inline int getLocalMatIndex(int ithComponent, DegreeOfFreedom d) + { + FUNCNAME("FeSpaceData::getLocalMatIndex()"); + + TEST_EXIT_DBG(data[feSpaces[ithComponent]].isRankDof(d)) + ("Should not happen!\n"); + + return dofToMatIndex.get(ithComponent, d) - rStartDofs; + } + private: MPI::Intracomm* mpiComm; @@ -481,7 +450,10 @@ namespace AMDiS { DofComm *recvDofs; - bool overlap; + /// Is true if there are DOFs in at least one subdomain that are not owned + /// by the rank. If the value is false, each rank contains only DOFs that + /// are also owned by this rank. + bool hasNonLocalDofs; map<const FiniteElemSpace*, T> data; diff --git a/AMDiS/src/parallel/PetscSolverFeti.cc b/AMDiS/src/parallel/PetscSolverFeti.cc index 6201c4f9a7247304fdcbfb71474dc19abbb2cd61..802034e7d8bc3bc9c56bcf38fa589ae0dd88258f 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.cc +++ b/AMDiS/src/parallel/PetscSolverFeti.cc @@ -232,6 +232,8 @@ namespace AMDiS { dualDofMap.update(); lagrangeMap.update(); localDofMap.update(); + if (fetiPreconditioner == FETI_DIRICHLET) + interiorDofMap.update(); for (unsigned int i = 0; i < meshDistributor->getFeSpaces().size(); i++) { const FiniteElemSpace *feSpace = meshDistributor->getFeSpace(i); @@ -240,12 +242,10 @@ namespace AMDiS { primalDofMap[feSpace].nRankDofs, primalDofMap[feSpace].nOverallDofs); MSG("nRankDuals = %d nOverallDuals = %d\n", - dualDofMap[feSpace].nRankDofs, - dualDofMap[feSpace].nOverallDofs); + dualDofMap[feSpace].nRankDofs, dualDofMap[feSpace].nOverallDofs); MSG("nRankLagrange = %d nOverallLagrange = %d\n", - lagrangeMap[feSpace].nRankDofs, - lagrangeMap[feSpace].nOverallDofs); + lagrangeMap[feSpace].nRankDofs, lagrangeMap[feSpace].nOverallDofs); TEST_EXIT_DBG(localDofMap[feSpace].size() + primalDofMap[feSpace].size() == static_cast<unsigned int>(feSpace->getAdmin()->getUsedDofs())) @@ -306,14 +306,14 @@ namespace AMDiS { // === Create for each dual node that is owned by the rank, the set === // === of ranks that contain this node (denoted by W(x_j)). === - boundaryDofRanks.clear(); + boundaryDofRanks[feSpace].clear(); for (DofComm::Iterator it(meshDistributor->getSendDofs(), feSpace); !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) { if (!isPrimal(feSpace, it.getDofIndex())) { - boundaryDofRanks[it.getDofIndex()].insert(mpiRank); - boundaryDofRanks[it.getDofIndex()].insert(it.getRank()); + boundaryDofRanks[feSpace][it.getDofIndex()].insert(mpiRank); + boundaryDofRanks[feSpace][it.getDofIndex()].insert(it.getRank()); } } @@ -327,7 +327,7 @@ namespace AMDiS { !it.end(); it.nextRank()) for (; !it.endDofIter(); it.nextDof()) if (!isPrimal(feSpace, it.getDofIndex())) - stdMpi.getSendData(it.getRank()).push_back(boundaryDofRanks[it.getDofIndex()]); + stdMpi.getSendData(it.getRank()).push_back(boundaryDofRanks[feSpace][it.getDofIndex()]); stdMpi.updateSendDataSize(); @@ -352,7 +352,7 @@ namespace AMDiS { int i = 0; for (; !it.endDofIter(); it.nextDof()) if (!isPrimal(feSpace, it.getDofIndex())) - boundaryDofRanks[it.getDofIndex()] = + boundaryDofRanks[feSpace][it.getDofIndex()] = stdMpi.getRecvData(it.getRank())[i++]; } @@ -365,7 +365,7 @@ namespace AMDiS { for (map<DegreeOfFreedom, MultiIndex>::iterator it = dualMap.begin(); it != dualMap.end(); ++it) { if (meshDistributor->getIsRankDof(feSpace, it->first)) { lagrangeMap[feSpace].insertRankDof(it->first, nRankLagrange); - int degree = boundaryDofRanks[it->first].size(); + int degree = boundaryDofRanks[feSpace][it->first].size(); nRankLagrange += (degree * (degree - 1)) / 2; } else { lagrangeMap[feSpace].insert(it->first); @@ -385,13 +385,17 @@ namespace AMDiS { // === the global index of all B nodes, insert all interior nodes first, === // === without defining a correct index. === - nLocalInterior[feSpace] = 0; + int nLocalInterior = 0; for (int i = 0; i < admin->getUsedSize(); i++) { if (admin->isDofFree(i) == false && isPrimal(feSpace, i) == false && dualDofMap[feSpace].isSet(i) == false) { - localDofMap[feSpace].insertRankDof(i, nLocalInterior[feSpace]); - nLocalInterior[feSpace]++; + localDofMap[feSpace].insertRankDof(i, nLocalInterior); + + if (fetiPreconditioner == FETI_DIRICHLET) + interiorDofMap[feSpace].insertRankDof(i, nLocalInterior); + + nLocalInterior++; } } @@ -428,25 +432,24 @@ namespace AMDiS { for (map<DegreeOfFreedom, MultiIndex>::iterator it = dualMap.begin(); it != dualMap.end(); ++it) { - TEST_EXIT_DBG(boundaryDofRanks.count(it->first)) + TEST_EXIT_DBG(boundaryDofRanks[feSpaces[k]].count(it->first)) ("Should not happen!\n"); // Global index of the first Lagrange constriant for this node. int index = lagrangeMap.getMatIndex(k, it->first); // Copy set of all ranks that contain this dual node. - vector<int> W(boundaryDofRanks[it->first].begin(), - boundaryDofRanks[it->first].end()); + vector<int> W(boundaryDofRanks[feSpaces[k]][it->first].begin(), + boundaryDofRanks[feSpaces[k]][it->first].end()); // Number of ranks that contain this dual node. int degree = W.size(); for (int i = 0; i < degree; i++) { for (int j = i + 1; j < degree; j++) { if (W[i] == mpiRank || W[j] == mpiRank) { - int colIndex = localDofMap.mapGlobal(it->first, k); + int colIndex = localDofMap.getMatIndex(k, it->first); double value = (W[i] == mpiRank ? 1.0 : -1.0); - MatSetValue(mat_lagrange, index, colIndex, value, - INSERT_VALUES); + MatSetValue(mat_lagrange, index, colIndex, value, INSERT_VALUES); } index++; } @@ -831,7 +834,7 @@ namespace AMDiS { for (map<DegreeOfFreedom, MultiIndex>::iterator it = localDofMap[feSpaces[i]].getMap().begin(); it != localDofMap[feSpaces[i]].getMap().end(); ++it) { - int petscIndex = localDofMap.mapLocal(it->first, i); + int petscIndex = localDofMap.getLocalMatIndex(i, it->first); dofVec[it->first] = localSolB[petscIndex]; } @@ -849,65 +852,70 @@ namespace AMDiS { void PetscSolverFeti::fillPetscMatrix(Matrix<DOFMatrix*> *mat) { FUNCNAME("PetscSolverFeti::fillPetscMatrix()"); - + // === Create all sets and indices. === - + vector<const FiniteElemSpace*> feSpaces = getFeSpaces(mat); - + primalDofMap.init(mpiComm, feSpaces, true, true); dualDofMap.init(mpiComm, feSpaces, false, false); lagrangeMap.init(mpiComm, feSpaces, true, true); localDofMap.init(mpiComm, feSpaces, false, false); + if (fetiPreconditioner == FETI_DIRICHLET) + interiorDofMap.init(mpiComm, feSpaces, false, false); updateDofData(); - + // === Create matrices for the FETI-DP method. === - + int nRowsRankB = localDofMap.getRankDofs(); int nRowsOverallB = localDofMap.getOverallDofs(); int nRowsRankPrimal = primalDofMap.getRankDofs(); int nRowsOverallPrimal = primalDofMap.getOverallDofs(); - int nRowsDual = dualDofMap.getRankDofs(); - int nRowsInterior = nRowsRankB - nRowsDual; - + MatCreateSeqAIJ(PETSC_COMM_SELF, nRowsRankB, nRowsRankB, 30, PETSC_NULL, &mat_b_b); - + MatCreateMPIAIJ(PETSC_COMM_WORLD, nRowsRankPrimal, nRowsRankPrimal, nRowsOverallPrimal, nRowsOverallPrimal, 30, PETSC_NULL, 30, PETSC_NULL, &mat_primal_primal); - + MatCreateMPIAIJ(PETSC_COMM_WORLD, nRowsRankB, nRowsRankPrimal, nRowsOverallB, nRowsOverallPrimal, 30, PETSC_NULL, 30, PETSC_NULL, &mat_b_primal); - + MatCreateMPIAIJ(PETSC_COMM_WORLD, nRowsRankPrimal, nRowsRankB, nRowsOverallPrimal, nRowsOverallB, 15, PETSC_NULL, 15, PETSC_NULL, &mat_primal_b); - - + + // === Create matrices for FETI-DP preconditioner. === + + if (fetiPreconditioner != FETI_NONE) { + int nRowsDual = dualDofMap.getRankDofs(); - if (fetiPreconditioner != FETI_NONE) MatCreateSeqAIJ(PETSC_COMM_SELF, nRowsDual, nRowsDual, 30, PETSC_NULL, &mat_duals_duals); - if (fetiPreconditioner == FETI_DIRICHLET) { - MatCreateSeqAIJ(PETSC_COMM_SELF, - nRowsInterior, nRowsInterior, 30, PETSC_NULL, - &mat_interior_interior); - - MatCreateSeqAIJ(PETSC_COMM_SELF, - nRowsInterior, nRowsDual, 30, PETSC_NULL, - &mat_interior_duals); - - MatCreateSeqAIJ(PETSC_COMM_SELF, - nRowsDual, nRowsInterior, 30, PETSC_NULL, - &mat_duals_interior); + if (fetiPreconditioner == FETI_DIRICHLET) { + int nRowsInterior = interiorDofMap.getRankDofs(); + + MatCreateSeqAIJ(PETSC_COMM_SELF, + nRowsInterior, nRowsInterior, 30, PETSC_NULL, + &mat_interior_interior); + + MatCreateSeqAIJ(PETSC_COMM_SELF, + nRowsInterior, nRowsDual, 30, PETSC_NULL, + &mat_interior_duals); + + MatCreateSeqAIJ(PETSC_COMM_SELF, + nRowsDual, nRowsInterior, 30, PETSC_NULL, + &mat_duals_interior); + } } @@ -992,32 +1000,24 @@ namespace AMDiS { // === For preconditioner === if (!rowPrimal && !colPrimal) { - int rowIndex = localDofMap[feSpaces[i]][*cursor].local; - int colIndex = localDofMap[feSpaces[j]][col(*icursor)].local; - - if (rowIndex < nLocalInterior[feSpaces[i]]) { - if (colIndex < nLocalInterior[feSpaces[j]]) { - int colIndex2 = localDofMap.mapLocal(col(*icursor), j); - colsLocal.push_back(colIndex2); + if (!isDual(feSpaces[i], *cursor)) { + if (!isDual(feSpaces[j], col(*icursor))) { + int colIndex = interiorDofMap.getLocalMatIndex(j, col(*icursor)); + colsLocal.push_back(colIndex); valuesLocal.push_back(value(*icursor)); } else { - int colIndex2 = - (localDofMap[feSpaces[j]][col(*icursor)].local - nLocalInterior[feSpaces[j]]) * - nComponents + j; - - colsLocalOther.push_back(colIndex2); + int colIndex = dualDofMap.getLocalMatIndex(j, col(*icursor)); + colsLocalOther.push_back(colIndex); valuesLocalOther.push_back(value(*icursor)); } } else { - if (colIndex < nLocalInterior[feSpaces[j]]) { - int colIndex2 = localDofMap.mapLocal(col(*icursor), j); - colsLocalOther.push_back(colIndex2); + if (!isDual(feSpaces[j], col(*icursor))) { + int colIndex = interiorDofMap.getLocalMatIndex(j, col(*icursor)); + colsLocalOther.push_back(colIndex); valuesLocalOther.push_back(value(*icursor)); } else { - int colIndex2 = (localDofMap[feSpaces[j]][col(*icursor)].local - nLocalInterior[feSpaces[j]]) * - nComponents + j; - - colsLocal.push_back(colIndex2); + int colIndex = dualDofMap.getLocalMatIndex(j, col(*icursor)); + colsLocal.push_back(colIndex); valuesLocal.push_back(value(*icursor)); } } @@ -1039,22 +1039,22 @@ namespace AMDiS { if (colsOther.size()) { for (unsigned int k = 0; k < colsOther.size(); k++) - colsOther[k] = localDofMap.mapGlobal(colsOther[k], j); + colsOther[k] = localDofMap.getMatIndex(j, colsOther[k]); MatSetValues(mat_primal_b, 1, &rowIndex, colsOther.size(), &(colsOther[0]), &(valuesOther[0]), ADD_VALUES); } } else { - int localRowIndex = localDofMap.mapLocal(*cursor, i); + int localRowIndex = localDofMap.getLocalMatIndex(i, *cursor); for (unsigned int k = 0; k < cols.size(); k++) - cols[k] = localDofMap.mapLocal(cols[k], j); + cols[k] = localDofMap.getLocalMatIndex(j, cols[k]); MatSetValues(mat_b_b, 1, &localRowIndex, cols.size(), &(cols[0]), &(values[0]), ADD_VALUES); if (colsOther.size()) { - int globalRowIndex = localDofMap.mapGlobal(*cursor, i); + int globalRowIndex = localDofMap.getMatIndex(i, *cursor); for (unsigned int k = 0; k < colsOther.size(); k++) colsOther[k] = primalDofMap.getMatIndex(j, colsOther[k]); @@ -1068,44 +1068,28 @@ namespace AMDiS { if (!rowPrimal) { switch (fetiPreconditioner) { case FETI_DIRICHLET: - { - int rowIndex = localDofMap[feSpaces[i]][*cursor].local; - - if (rowIndex < nLocalInterior[feSpaces[i]]) { - int rowIndex2 = localDofMap[feSpaces[i]][*cursor].local * nComponents + i; - - MatSetValues(mat_interior_interior, 1, &rowIndex2, colsLocal.size(), - &(colsLocal[0]), &(valuesLocal[0]), INSERT_VALUES); - - if (colsLocalOther.size()) - MatSetValues(mat_interior_duals, 1, &rowIndex2, colsLocalOther.size(), - &(colsLocalOther[0]), &(valuesLocalOther[0]), INSERT_VALUES); - } else { - int rowIndex2 = - (localDofMap[feSpaces[i]][*cursor].local - nLocalInterior[feSpaces[i]]) * nComponents + i; - - MatSetValues(mat_duals_duals, 1, &rowIndex2, colsLocal.size(), - &(colsLocal[0]), &(valuesLocal[0]), INSERT_VALUES); - - if (colsLocalOther.size()) - MatSetValues(mat_duals_interior, 1, &rowIndex2, colsLocalOther.size(), - &(colsLocalOther[0]), &(valuesLocalOther[0]), INSERT_VALUES); - - } + if (!isDual(feSpaces[i], *cursor)) { + int rowIndex = interiorDofMap.getLocalMatIndex(i, *cursor); + MatSetValues(mat_interior_interior, 1, &rowIndex, colsLocal.size(), + &(colsLocal[0]), &(valuesLocal[0]), INSERT_VALUES); + if (colsLocalOther.size()) + MatSetValues(mat_interior_duals, 1, &rowIndex, colsLocalOther.size(), + &(colsLocalOther[0]), &(valuesLocalOther[0]), INSERT_VALUES); + } else { + int rowIndex = dualDofMap.getLocalMatIndex(i, *cursor); + MatSetValues(mat_duals_duals, 1, &rowIndex, colsLocal.size(), + &(colsLocal[0]), &(valuesLocal[0]), INSERT_VALUES); + if (colsLocalOther.size()) + MatSetValues(mat_duals_interior, 1, &rowIndex, colsLocalOther.size(), + &(colsLocalOther[0]), &(valuesLocalOther[0]), INSERT_VALUES); } break; case FETI_LUMPED: - { - int rowIndex = localDofMap[feSpaces[i]][*cursor].local; - - if (rowIndex >= nLocalInterior[feSpaces[i]]) { - int rowIndex2 = - (localDofMap[feSpaces[i]][*cursor].local - nLocalInterior[feSpaces[i]]) * nComponents + i; - - MatSetValues(mat_duals_duals, 1, &rowIndex2, colsLocal.size(), - &(colsLocal[0]), &(valuesLocal[0]), INSERT_VALUES); - } + if (isDual(feSpaces[i], *cursor)) { + int rowIndex = dualDofMap.getLocalMatIndex(i, *cursor); + MatSetValues(mat_duals_duals, 1, &rowIndex, colsLocal.size(), + &(colsLocal[0]), &(valuesLocal[0]), INSERT_VALUES); } break; default: @@ -1194,7 +1178,7 @@ namespace AMDiS { index = primalDofMap.getMatIndex(i, index); VecSetValue(f_primal, index, *dofIt, ADD_VALUES); } else { - index = localDofMap.mapGlobal(index, i); + index = localDofMap.getMatIndex(i, index); VecSetValue(f_b, index, *dofIt, INSERT_VALUES); } } diff --git a/AMDiS/src/parallel/PetscSolverFeti.h b/AMDiS/src/parallel/PetscSolverFeti.h index a2dcadd2486dcdb07d5981899704a9490ad17fea..3d02e9e563bdaf43c7d34df4121bd4843ac396b5 100644 --- a/AMDiS/src/parallel/PetscSolverFeti.h +++ b/AMDiS/src/parallel/PetscSolverFeti.h @@ -144,12 +144,18 @@ namespace AMDiS { void printStatistics(); - /// Checks whether a given DOF in a gifen FE space is a primal DOF. + /// Checks whether a given DOF in a given FE space is a primal DOF. inline bool isPrimal(const FiniteElemSpace *feSpace, DegreeOfFreedom dof) { return primalDofMap[feSpace].isSet(dof); } + /// Checks whether a given DOF in a give FE space is a dual DOF. + inline bool isDual(const FiniteElemSpace *feSpace, DegreeOfFreedom dof) + { + return dualDofMap[feSpace].isSet(dof); + } + protected: /// Mapping from primal DOF indices to a global index of primals. FeSpaceData<GlobalDofMap> primalDofMap; @@ -161,13 +167,16 @@ namespace AMDiS { /// constraint that is assigned to this DOF. FeSpaceData<GlobalDofMap> lagrangeMap; - /// Index for each non primal DOF to the global index of - /// B variables. + /// Index for each non primal DOF to the global index of B variables. FeSpaceData<GlobalDofMap> localDofMap; - /// Stores to each dual boundary DOF the set of ranks in which the DOF - /// is contained in. - DofIndexToPartitions boundaryDofRanks; + /// Mapping of pure local DOF indices, thus no primal and no dual DOFs are + /// in this map. Is used for the Dirichlet preconditioner only. + FeSpaceData<GlobalDofMap> interiorDofMap; + + /// Stores to each dual boundary DOF in each finite elment space the set of + /// ranks in which the DOF is contained in. + map<const FiniteElemSpace*, DofIndexToPartitions> boundaryDofRanks; /// Global PETSc matrix of non primal variables. Mat mat_b_b; @@ -231,8 +240,6 @@ namespace AMDiS { Mat mat_interior_interior, mat_duals_duals, mat_interior_duals, mat_duals_interior; KSP ksp_interior; - - map<const FiniteElemSpace*, int> nLocalInterior; }; }