Liebe Gitlab-Nutzerin, lieber Gitlab-Nutzer,
es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Die Konten der externen Nutzer:innen sind über den Reiter "Standard" erreichbar.
Die Administratoren


Dear Gitlab user,
it is now possible to log in to our service using the ZIH login/LDAP. The accounts of external users can be accessed via the "Standard" tab.
The administrators

Commit 430cb57b authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Add more support for mixed finite element FETI-DP. Does not work yet.

parent 3f9bb6b2
...@@ -34,6 +34,13 @@ namespace AMDiS { ...@@ -34,6 +34,13 @@ namespace AMDiS {
class GlobalDofMap class GlobalDofMap
{ {
public: public:
/// This constructor exists only to create std::map of this class and make
/// use of the operator [] for read access. Should never be called.
GlobalDofMap()
{
ERROR_EXIT("Should not be called!\n");
}
GlobalDofMap(MPI::Intracomm* m) GlobalDofMap(MPI::Intracomm* m)
: mpiComm(m), : mpiComm(m),
nRankDofs(0), nRankDofs(0),
...@@ -103,7 +110,13 @@ namespace AMDiS { ...@@ -103,7 +110,13 @@ namespace AMDiS {
class FeSpaceData class FeSpaceData
{ {
public: public:
FeSpaceData() {} FeSpaceData()
: mpiComm(NULL),
feSpaces(0),
nRankDofs(-1),
nOverallDofs(-1),
rStartDofs(-1)
{}
void setMpiComm(MPI::Intracomm *m) void setMpiComm(MPI::Intracomm *m)
{ {
...@@ -129,17 +142,26 @@ namespace AMDiS { ...@@ -129,17 +142,26 @@ namespace AMDiS {
data.insert(make_pair(feSpace, T(mpiComm))); data.insert(make_pair(feSpace, T(mpiComm)));
} }
int getRankDofs(vector<const FiniteElemSpace*> &feSpaces) int getRankDofs(vector<const FiniteElemSpace*> &fe)
{ {
FUNCNAME("FeSpaceData::getRankDofs()");
int result = 0; int result = 0;
for (unsigned int i = 0; i < feSpaces.size(); i++) { for (unsigned int i = 0; i < fe.size(); i++) {
TEST_EXIT_DBG(data.count(feSpaces[i]))("Should not happen!\n"); TEST_EXIT_DBG(data.count(fe[i]))("Cannot find FE space: %p\n", fe[i]);
result += data.find(feSpaces[i])->second.nRankDofs; result += data[fe[i]].nRankDofs;
} }
return result; return result;
} }
inline int getRankDofs()
{
TEST_EXIT_DBG(nRankDofs >= 0)("Should not happen!\n");
return nRankDofs;
}
int getOverallDofs(vector<const FiniteElemSpace*> &feSpaces) int getOverallDofs(vector<const FiniteElemSpace*> &feSpaces)
{ {
int result = 0; int result = 0;
...@@ -151,6 +173,13 @@ namespace AMDiS { ...@@ -151,6 +173,13 @@ namespace AMDiS {
return result; return result;
} }
inline int getOverallDofs()
{
TEST_EXIT_DBG(nOverallDofs >= 0)("Should not happen!\n");
return nOverallDofs;
}
int getStartDofs(vector<const FiniteElemSpace*> &feSpaces) int getStartDofs(vector<const FiniteElemSpace*> &feSpaces)
{ {
int result = 0; int result = 0;
...@@ -162,10 +191,74 @@ namespace AMDiS { ...@@ -162,10 +191,74 @@ namespace AMDiS {
return result; return result;
} }
int getStartDofs()
{
TEST_EXIT_DBG(rStartDofs >= 0)("Should not happen!\n");
return rStartDofs;
}
void setFeSpaces(vector<const FiniteElemSpace*> &fe)
{
feSpaces = fe;
for (unsigned int i = 0; i < feSpaces.size(); i++)
addFeSpace(feSpaces[i]);
}
void update()
{
nRankDofs = getRankDofs(feSpaces);
nOverallDofs = getOverallDofs(feSpaces);
rStartDofs = getStartDofs(feSpaces);
}
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];
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];
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;
}
private: private:
MPI::Intracomm* mpiComm; MPI::Intracomm* mpiComm;
map<const FiniteElemSpace*, T> data; map<const FiniteElemSpace*, T> data;
vector<const FiniteElemSpace*> feSpaces;
int nRankDofs, nOverallDofs, rStartDofs;
}; };
} }
......
...@@ -248,7 +248,6 @@ namespace AMDiS { ...@@ -248,7 +248,6 @@ namespace AMDiS {
// === Calculate the number of primals that are owned by the rank and === // === Calculate the number of primals that are owned by the rank and ===
// === create local indices of the primals starting at zero. === // === create local indices of the primals starting at zero. ===
primalDofMap.addFeSpace(feSpace);
for (DofIndexSet::iterator it = primals.begin(); it != primals.end(); ++it) for (DofIndexSet::iterator it = primals.begin(); it != primals.end(); ++it)
if (meshDistributor->getIsRankDof(feSpace, *it)) if (meshDistributor->getIsRankDof(feSpace, *it))
primalDofMap[feSpace].insertRankDof(*it); primalDofMap[feSpace].insertRankDof(*it);
...@@ -372,8 +371,6 @@ namespace AMDiS { ...@@ -372,8 +371,6 @@ namespace AMDiS {
// === Create global index of the dual nodes on each rank. === // === Create global index of the dual nodes on each rank. ===
dualDofMap.addFeSpace(feSpace);
DofContainer allBoundaryDofs; DofContainer allBoundaryDofs;
meshDistributor->getAllBoundaryDofs(feSpace, allBoundaryDofs); meshDistributor->getAllBoundaryDofs(feSpace, allBoundaryDofs);
...@@ -397,8 +394,6 @@ namespace AMDiS { ...@@ -397,8 +394,6 @@ namespace AMDiS {
// === Reserve for each dual node, on the rank that owns this node, the === // === Reserve for each dual node, on the rank that owns this node, the ===
// === appropriate number of Lagrange constraints. === // === appropriate number of Lagrange constraints. ===
lagrangeMap.addFeSpace(feSpace);
int nRankLagrange = 0; int nRankLagrange = 0;
DofMapping& dualMap = dualDofMap[feSpace].getMap(); DofMapping& dualMap = dualDofMap[feSpace].getMap();
for (DofMapping::iterator it = dualMap.begin(); it != dualMap.end(); ++it) { for (DofMapping::iterator it = dualMap.begin(); it != dualMap.end(); ++it) {
...@@ -463,7 +458,6 @@ namespace AMDiS { ...@@ -463,7 +458,6 @@ namespace AMDiS {
{ {
FUNCNAME("PetscSolverFeti::createIndexB()"); FUNCNAME("PetscSolverFeti::createIndexB()");
localDofMap.addFeSpace(feSpace);
DOFAdmin* admin = feSpace->getAdmin(); DOFAdmin* admin = feSpace->getAdmin();
// === To ensure that all interior node on each rank are listen first in === // === To ensure that all interior node on each rank are listen first in ===
...@@ -511,9 +505,9 @@ namespace AMDiS { ...@@ -511,9 +505,9 @@ namespace AMDiS {
MatCreateMPIAIJ(PETSC_COMM_WORLD, MatCreateMPIAIJ(PETSC_COMM_WORLD,
lagrangeMap.getRankDofs(feSpaces), lagrangeMap.getRankDofs(feSpaces),
localDofMap.getRankDofs(feSpaces), localDofMap.getRankDofs(),
lagrangeMap.getOverallDofs(feSpaces), lagrangeMap.getOverallDofs(feSpaces),
localDofMap.getOverallDofs(feSpaces), localDofMap.getOverallDofs(),
2, PETSC_NULL, 2, PETSC_NULL, 2, PETSC_NULL, 2, PETSC_NULL,
&mat_lagrange); &mat_lagrange);
...@@ -560,7 +554,7 @@ namespace AMDiS { ...@@ -560,7 +554,7 @@ namespace AMDiS {
} }
void PetscSolverFeti::createSchurPrimalKsp() void PetscSolverFeti::createSchurPrimalKsp(vector<const FiniteElemSpace*> &feSpaces)
{ {
FUNCNAME("PetscSolverFeti::createSchurPrimal()"); FUNCNAME("PetscSolverFeti::createSchurPrimal()");
...@@ -575,7 +569,7 @@ namespace AMDiS { ...@@ -575,7 +569,7 @@ namespace AMDiS {
schurPrimalData.fetiSolver = this; schurPrimalData.fetiSolver = this;
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
localDofMap[feSpace].nRankDofs * nComponents, localDofMap[feSpace].nOverallDofs * nComponents, localDofMap.getRankDofs(), localDofMap.getOverallDofs(),
&(schurPrimalData.tmp_vec_b)); &(schurPrimalData.tmp_vec_b));
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
primalDofMap[feSpace].nRankDofs * nComponents, primalDofMap[feSpace].nOverallDofs * nComponents, primalDofMap[feSpace].nRankDofs * nComponents, primalDofMap[feSpace].nOverallDofs * nComponents,
...@@ -602,8 +596,8 @@ namespace AMDiS { ...@@ -602,8 +596,8 @@ namespace AMDiS {
int nRowsRankPrimal = primalDofMap[feSpace].nRankDofs * nComponents; int nRowsRankPrimal = primalDofMap[feSpace].nRankDofs * nComponents;
int nRowsOverallPrimal = primalDofMap[feSpace].nOverallDofs * nComponents; int nRowsOverallPrimal = primalDofMap[feSpace].nOverallDofs * nComponents;
int nRowsRankB = localDofMap[feSpace].nRankDofs * nComponents; int nRowsRankB = localDofMap.getRankDofs();
int nRowsOverallB = localDofMap[feSpace].nOverallDofs * nComponents; int nRowsOverallB = localDofMap.getOverallDofs();
Mat matBPi; Mat matBPi;
MatCreateMPIAIJ(PETSC_COMM_WORLD, MatCreateMPIAIJ(PETSC_COMM_WORLD,
...@@ -618,8 +612,8 @@ namespace AMDiS { ...@@ -618,8 +612,8 @@ namespace AMDiS {
map<int, vector<pair<int, double> > > mat_b_primal_cols; map<int, vector<pair<int, double> > > mat_b_primal_cols;
for (int i = 0; i < localDofMap[feSpace].nRankDofs * nComponents; i++) { for (int i = 0; i < nRowsRankB; i++) {
PetscInt row = localDofMap[feSpace].rStartDofs * nComponents + i; PetscInt row = localDofMap.getStartDofs() + i;
MatGetRow(mat_b_primal, row, &nCols, &cols, &values); MatGetRow(mat_b_primal, row, &nCols, &cols, &values);
for (int j = 0; j < nCols; j++) for (int j = 0; j < nCols; j++)
...@@ -637,7 +631,7 @@ namespace AMDiS { ...@@ -637,7 +631,7 @@ namespace AMDiS {
for (map<int, vector<pair<int, double> > >::iterator it = mat_b_primal_cols.begin(); for (map<int, vector<pair<int, double> > >::iterator it = mat_b_primal_cols.begin();
it != mat_b_primal_cols.end(); ++it) { it != mat_b_primal_cols.end(); ++it) {
Vec tmpVec; Vec tmpVec;
VecCreateSeq(PETSC_COMM_SELF, localDofMap[feSpace].nRankDofs * nComponents, &tmpVec); VecCreateSeq(PETSC_COMM_SELF, nRowsRankB, &tmpVec);
for (unsigned int i = 0; i < it->second.size(); i++) for (unsigned int i = 0; i < it->second.size(); i++)
VecSetValue(tmpVec, VecSetValue(tmpVec,
...@@ -650,9 +644,9 @@ namespace AMDiS { ...@@ -650,9 +644,9 @@ namespace AMDiS {
PetscScalar *tmpValues; PetscScalar *tmpValues;
VecGetArray(tmpVec, &tmpValues); VecGetArray(tmpVec, &tmpValues);
for (int i = 0; i < localDofMap[feSpace].nRankDofs * nComponents; i++) for (int i = 0; i < nRowsRankB; i++)
MatSetValue(matBPi, MatSetValue(matBPi,
localDofMap[feSpace].rStartDofs * nComponents + i, localDofMap.getStartDofs() + i,
it->first, it->first,
tmpValues[i], tmpValues[i],
ADD_VALUES); ADD_VALUES);
...@@ -706,7 +700,7 @@ namespace AMDiS { ...@@ -706,7 +700,7 @@ namespace AMDiS {
} }
void PetscSolverFeti::createFetiKsp() void PetscSolverFeti::createFetiKsp(vector<const FiniteElemSpace*> &feSpaces)
{ {
FUNCNAME("PetscSolverFeti::createFetiKsp()"); FUNCNAME("PetscSolverFeti::createFetiKsp()");
...@@ -721,14 +715,15 @@ namespace AMDiS { ...@@ -721,14 +715,15 @@ namespace AMDiS {
fetiData.ksp_schur_primal = &ksp_schur_primal; fetiData.ksp_schur_primal = &ksp_schur_primal;
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
localDofMap[feSpace].nRankDofs * nComponents, localDofMap[feSpace].nOverallDofs * nComponents, localDofMap.getRankDofs(), localDofMap.getOverallDofs(),
&(fetiData.tmp_vec_b)); &(fetiData.tmp_vec_b));
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
lagrangeMap[feSpace].nRankDofs * nComponents, lagrangeMap[feSpace].nRankDofs * nComponents,
lagrangeMap[feSpace].nOverallDofs * nComponents, lagrangeMap[feSpace].nOverallDofs * nComponents,
&(fetiData.tmp_vec_lagrange)); &(fetiData.tmp_vec_lagrange));
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
primalDofMap[feSpace].nRankDofs * nComponents, primalDofMap[feSpace].nOverallDofs * nComponents, primalDofMap[feSpace].nRankDofs * nComponents,
primalDofMap[feSpace].nOverallDofs * nComponents,
&(fetiData.tmp_vec_primal)); &(fetiData.tmp_vec_primal));
MatCreateShell(PETSC_COMM_WORLD, MatCreateShell(PETSC_COMM_WORLD,
...@@ -769,11 +764,14 @@ namespace AMDiS { ...@@ -769,11 +764,14 @@ namespace AMDiS {
fetiDirichletPreconData.ksp_interior = &ksp_interior; fetiDirichletPreconData.ksp_interior = &ksp_interior;
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
localDofMap[feSpace].nRankDofs * nComponents, localDofMap[feSpace].nOverallDofs * nComponents, localDofMap.getRankDofs(),localDofMap.getOverallDofs(),
&(fetiDirichletPreconData.tmp_vec_b)); &(fetiDirichletPreconData.tmp_vec_b));
MatGetVecs(mat_duals_duals, PETSC_NULL, &(fetiDirichletPreconData.tmp_vec_duals0)); MatGetVecs(mat_duals_duals, PETSC_NULL,
MatGetVecs(mat_duals_duals, PETSC_NULL, &(fetiDirichletPreconData.tmp_vec_duals1)); &(fetiDirichletPreconData.tmp_vec_duals0));
MatGetVecs(mat_interior_interior, PETSC_NULL, &(fetiDirichletPreconData.tmp_vec_interior)); MatGetVecs(mat_duals_duals, PETSC_NULL,
&(fetiDirichletPreconData.tmp_vec_duals1));
MatGetVecs(mat_interior_interior, PETSC_NULL,
&(fetiDirichletPreconData.tmp_vec_interior));
KSPGetPC(ksp_feti, &precon_feti); KSPGetPC(ksp_feti, &precon_feti);
PCSetType(precon_feti, PCSHELL); PCSetType(precon_feti, PCSHELL);
...@@ -787,10 +785,13 @@ namespace AMDiS { ...@@ -787,10 +785,13 @@ namespace AMDiS {
fetiLumpedPreconData.mat_duals_duals = &mat_duals_duals; fetiLumpedPreconData.mat_duals_duals = &mat_duals_duals;
VecCreateMPI(PETSC_COMM_WORLD, VecCreateMPI(PETSC_COMM_WORLD,
localDofMap[feSpace].nRankDofs * nComponents, localDofMap[feSpace].nOverallDofs * nComponents, localDofMap.getRankDofs(),
localDofMap.getOverallDofs(),
&(fetiLumpedPreconData.tmp_vec_b)); &(fetiLumpedPreconData.tmp_vec_b));
MatGetVecs(mat_duals_duals, PETSC_NULL, &(fetiLumpedPreconData.tmp_vec_duals0)); MatGetVecs(mat_duals_duals, PETSC_NULL,
MatGetVecs(mat_duals_duals, PETSC_NULL, &(fetiLumpedPreconData.tmp_vec_duals1)); &(fetiLumpedPreconData.tmp_vec_duals0));
MatGetVecs(mat_duals_duals, PETSC_NULL,
&(fetiLumpedPreconData.tmp_vec_duals1));
KSPGetPC(ksp_feti, &precon_feti); KSPGetPC(ksp_feti, &precon_feti);
PCSetType(precon_feti, PCSHELL); PCSetType(precon_feti, PCSHELL);
...@@ -926,7 +927,13 @@ namespace AMDiS { ...@@ -926,7 +927,13 @@ namespace AMDiS {
for (DofMapping::iterator it = localDofMap[feSpace].getMap().begin(); for (DofMapping::iterator it = localDofMap[feSpace].getMap().begin();
it != localDofMap[feSpace].getMap().end(); ++it) { it != localDofMap[feSpace].getMap().end(); ++it) {
#if 1
int petscIndex = localDofMap.mapLocal(it->first, i);
#else
int petscIndex = it->second * nComponents + i; int petscIndex = it->second * nComponents + i;
#endif
dofVec[it->first] = localSolB[petscIndex]; dofVec[it->first] = localSolB[petscIndex];
} }
...@@ -959,18 +966,28 @@ namespace AMDiS { ...@@ -959,18 +966,28 @@ namespace AMDiS {
dualDofMap.setMpiComm(mpiComm); dualDofMap.setMpiComm(mpiComm);
lagrangeMap.setMpiComm(mpiComm); lagrangeMap.setMpiComm(mpiComm);
localDofMap.setMpiComm(mpiComm); localDofMap.setMpiComm(mpiComm);
primalDofMap.setFeSpaces(feSpaces);
dualDofMap.setFeSpaces(feSpaces);
lagrangeMap.setFeSpaces(feSpaces);
localDofMap.setFeSpaces(feSpaces);
updateDofData(); updateDofData();
primalDofMap.update();
dualDofMap.update();
lagrangeMap.update();
localDofMap.update();
// === Create matrices for the FETI-DP method. === // === Create matrices for the FETI-DP method. ===
int nRowsRankB = localDofMap.getRankDofs(feSpaces); int nRowsRankB = localDofMap.getRankDofs();
int nRowsOverallB = localDofMap.getOverallDofs(feSpaces); int nRowsOverallB = localDofMap.getOverallDofs();
int nRowsRankPrimal = primalDofMap.getRankDofs(feSpaces); int nRowsRankPrimal = primalDofMap.getRankDofs(feSpaces);
int nRowsOverallPrimal = primalDofMap.getOverallDofs(feSpaces); int nRowsOverallPrimal = primalDofMap.getOverallDofs(feSpaces);
int nRowsDual = dualDofMap.getRankDofs(feSpaces); int nRowsDual = dualDofMap.getRankDofs(feSpaces);
int nRowsInterior = nRowsRankB - nRowsDual; int nRowsInterior = nRowsRankB - nRowsDual;
MatCreateSeqAIJ(PETSC_COMM_SELF, nRowsRankB, nRowsRankB, 30, PETSC_NULL, MatCreateSeqAIJ(PETSC_COMM_SELF, nRowsRankB, nRowsRankB, 30, PETSC_NULL,
&mat_b_b); &mat_b_b);
...@@ -1071,36 +1088,24 @@ namespace AMDiS { ...@@ -1071,36 +1088,24 @@ namespace AMDiS {
bool colPrimal = primalDofMap[feSpace].isSet(col(*icursor)); bool colPrimal = primalDofMap[feSpace].isSet(col(*icursor));
if (colPrimal) { if (colPrimal) {
// Column is a primal variable.
int colIndex =
primalDofMap[feSpace][col(*icursor)] * nComponents + j;
if (rowPrimal) { if (rowPrimal) {
cols.push_back(colIndex); cols.push_back(col(*icursor));
values.push_back(value(*icursor)); values.push_back(value(*icursor));
} else { } else {
colsOther.push_back(colIndex); colsOther.push_back(col(*icursor));
valuesOther.push_back(value(*icursor)); valuesOther.push_back(value(*icursor));
} }
} else { } else {
// Column is not a primal variable.
int colIndex =
(localDofMap[feSpace][col(*icursor)] +
localDofMap[feSpace].rStartDofs) * nComponents + j;
if (rowPrimal) { if (rowPrimal) {
colsOther.push_back(colIndex); colsOther.push_back(col(*icursor));
valuesOther.push_back(value(*icursor)); valuesOther.push_back(value(*icursor));
} else { } else {
cols.push_back(colIndex); cols.push_back(col(*icursor));
values.push_back(value(*icursor)); values.push_back(value(*icursor));
} }
} }
// === For preconditioner === // === For preconditioner ===
if (!rowPrimal && !colPrimal) { if (!rowPrimal && !colPrimal) {
...@@ -1109,7 +1114,11 @@ namespace AMDiS { ...@@ -1109,7 +1114,11 @@ namespace AMDiS {
if (rowIndex < nLocalInterior) { if (rowIndex < nLocalInterior) {
if (colIndex < nLocalInterior) { if (colIndex < nLocalInterior) {
#if 1
int colIndex2 = localDofMap.mapLocal(col(*icursor), j);
#else
int colIndex2 = localDofMap[feSpace][col(*icursor)] * nComponents + j; int colIndex2 = localDofMap[feSpace][col(*icursor)] * nComponents + j;
#endif
colsLocal.push_back(colIndex2); colsLocal.push_back(colIndex2);
valuesLocal.push_back(value(*icursor)); valuesLocal.push_back(value(*icursor));
...@@ -1122,7 +1131,11 @@ namespace AMDiS { ...@@ -1122,7 +1131,11 @@ namespace AMDiS {
} }
} else { } else {
if (colIndex < nLocalInterior) { if (colIndex < nLocalInterior) {
#if 1
int colIndex2 = localDofMap.mapLocal(col(*icursor), j);
#else
int colIndex2 = localDofMap[feSpace][col(*icursor)] * nComponents + j; int colIndex2 = localDofMap[feSpace][col(*icursor)] * nComponents + j;
#endif
colsLocalOther.push_back(colIndex2); colsLocalOther.push_back(colIndex2);
valuesLocalOther.push_back(value(*icursor)); valuesLocalOther.push_back(value(*icursor));
...@@ -1139,31 +1152,67 @@ namespace AMDiS { ...@@ -1139,31 +1152,67 @@ namespace AMDiS {
} // for each nnz in row } // for each nnz in row
// === Set matrix values. ===
if (rowPrimal) { if (rowPrimal) {
int rowIndex = int rowIndex =
primalDofMap[feSpace][*cursor] * nComponents + i; primalDofMap[feSpace][*cursor] * nComponents + i;
for (unsigned int k = 0; k < cols.size(); k++)
cols[k] = primalDofMap[feSpace][cols[k]] * nComponents + j;
MatSetValues(mat_primal_primal, 1, &rowIndex, cols.size(), MatSetValues(mat_primal_primal, 1, &rowIndex, cols.size(),
&(cols[0]), &(values[0]), ADD_VALUES); &(cols[0]), &(values[0]), ADD_VALUES);
if (colsOther.size()) if (colsOther.size()) {
MatSetValues(mat_primal_b, 1, &rowIndex, colsOther.size(), for (unsigned int k = 0; k < colsOther.size(); k++)
&(colsOther[0]), &(valuesOther[0]), ADD_VALUES); #if 1