From 2bbf10f76aec8b98ce655056ee4a22d7de296059 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Tue, 26 Jun 2012 20:11:48 +0000
Subject: [PATCH] Fixed some problems with nnz computation with coarse grid,
 still not finished.

---
 AMDiS/src/parallel/PetscSolverGlobalMatrix.cc | 261 +++++++++---------
 AMDiS/src/parallel/PetscSolverGlobalMatrix.h  |  62 ++++-
 2 files changed, 184 insertions(+), 139 deletions(-)

diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc
index 06552c19..68033d96 100644
--- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc
+++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.cc
@@ -51,7 +51,9 @@ namespace AMDiS {
 
     MatCreateAIJ(mpiCommGlobal, nRankRows, nRankRows, 
 		 nOverallRows, nOverallRows,
-		 0, matInteriorDiagNnz, 0, matInteriorOffdiagNnz, &matIntInt);
+		 0, nnzInterior.dnnz, 
+		 0, nnzInterior.onnz, 
+		 &matIntInt);
 
     MatSetOption(matIntInt, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
 
@@ -132,28 +134,40 @@ namespace AMDiS {
 
     bool localMatrix = (subdomainLevel == 0);
     if (checkMeshChange(mat, localMatrix)) {
-      createPetscNnzStructureWithCoarseSpace(mat, 
-					     *interiorMap, 
-					     matInteriorDiagNnz,
-					     matInteriorOffdiagNnz,
-					     localMatrix);
-
-      if (coarseSpaceMap)
+       createPetscNnzStructureWithCoarseSpace(mat, 
+					      *interiorMap,
+					      *interiorMap,
+					      nnzInterior,
+					      localMatrix);
+
+      if (coarseSpaceMap) {
+ 	createPetscNnzStructureWithCoarseSpace(mat, 
+ 					       *coarseSpaceMap,
+ 					       *coarseSpaceMap,
+ 					       nnzCoarse);
 	createPetscNnzStructureWithCoarseSpace(mat, 
-					       *coarseSpaceMap, 
-					       matCoarseDiagNnz,
-					       matCoarseOffdiagNnz);	
+					       *coarseSpaceMap,
+					       *interiorMap,
+					       nnzCoarseInt);
+ 	createPetscNnzStructureWithCoarseSpace(mat, 
+ 					       *interiorMap,
+ 					       *coarseSpaceMap,
+ 					       nnzIntCoarse);
+      }
     }
 
     if (localMatrix) {
       MatCreateSeqAIJ(mpiCommLocal, nRowsRankInterior, nRowsRankInterior,
-		      0, matInteriorDiagNnz, &matIntInt);
+		      0, nnzInterior.dnnz, 
+		      &matIntInt);
+      //      MatSetOption(matIntInt, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
     } else {
       MatCreateAIJ(mpiCommLocal, 
 		   nRowsRankInterior, nRowsRankInterior,
 		   nRowsOverallInterior, nRowsOverallInterior,
-		   0, matInteriorDiagNnz, 0, matInteriorOffdiagNnz, 
+		   0, nnzInterior.dnnz, 0, nnzInterior.onnz, 
 		   &matIntInt);
+      //      MatSetOption(matIntInt, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
     }
     
     if (coarseSpaceMap) {
@@ -163,13 +177,16 @@ namespace AMDiS {
       MatCreateAIJ(mpiCommGlobal,
 		   nRowsRankCoarse, nRowsRankCoarse,
 		   nRowsOverallCoarse, nRowsOverallCoarse,
-		   0, matCoarseDiagNnz, 0, matCoarseOffdiagNnz, 
+		   0, nnzCoarse.dnnz, 0, nnzCoarse.onnz, 
+		   //	   100, PETSC_NULL, 100, PETSC_NULL,
 		   &matCoarseCoarse);
+      //      MatSetOption(matCoarseCoarse, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
 
       MatCreateAIJ(mpiCommGlobal,
 		   nRowsRankCoarse, nRowsRankInterior,
 		   nRowsOverallCoarse, nGlobalOverallInterior,
 		   100, PETSC_NULL, 100, PETSC_NULL,
+		   //	   0, nnzCoarseInt.dnnz, 0, nnzCoarseInt.onnz,
 		   &matCoarseInt);
       MatSetOption(matCoarseInt, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
 
@@ -177,7 +194,7 @@ namespace AMDiS {
 		   nRowsRankInterior, nRowsRankCoarse,
 		   nGlobalOverallInterior, nRowsOverallCoarse,
 		   100, PETSC_NULL, 100, PETSC_NULL,
-		   //	   0, matInteriorDiagNnz, 0, matCoarseOffdiagNnz,
+		   //	   0, nnzIntCoarse.dnnz, 0, nnzIntCoarse.onnz,
 		   &matIntCoarse);
       MatSetOption(matIntCoarse, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
     }
@@ -259,14 +276,19 @@ namespace AMDiS {
 
 	    if (colsOther.size()) {
 	      if (subdomainLevel == 0) {
-		for (unsigned int k = 0; k < colsOther.size(); k++)
+		for (unsigned int k = 0; k < colsOther.size(); k++) {
+		  int local = interiorMap->getMatIndex(j, colsOther[k]) - interiorMap->getStartDofs();
+		  if (rowIndex == 0 && local == 9297)
+		    MSG("FOUND: %d %d %d\n", colsOther[k], j, interiorMap->getMatIndex(j, colsOther[k]));
+
 		  colsOther[k] = interiorMap->getMatIndex(j, colsOther[k]);
+		}
 	      } else {
 		for (unsigned int k = 0; k < colsOther.size(); k++)
 		  colsOther[k] = 
 		    interiorMap->getMatIndex(j, colsOther[k]) + rStartInterior;
 	      }
- 	      
+
 	      MatSetValues(matCoarseInt, 1, &rowIndex, colsOther.size(),
  			   &(colsOther[0]), &(valuesOther[0]), ADD_VALUES);
 	    }
@@ -318,6 +340,8 @@ namespace AMDiS {
       MatAssemblyEnd(matCoarseInt, MAT_FINAL_ASSEMBLY);
     }
 
+    AMDiS::finalize();
+    exit(0);
 
     // === Remove Dirichlet BC DOFs. ===
 
@@ -577,30 +601,18 @@ namespace AMDiS {
       static_cast<int>(meshDistributor->getLastMeshChangeIndex() != lastMeshNnz);
     mpiCommGlobal.Allreduce(&sendValue, &recvAllValues, 1, MPI_INT, MPI_SUM);
 
-    if (!matInteriorDiagNnz || recvAllValues != 0 || alwaysCreateNnzStructure) {
+    if (!nnzInterior.dnnz || recvAllValues != 0 || alwaysCreateNnzStructure) {
       vector<const FiniteElemSpace*> feSpaces = getFeSpaces(mat);
       
       interiorMap->setComputeMatIndex(true, !localMatrix);
       interiorMap->update(feSpaces);
 
-      if (matInteriorDiagNnz) {
-	delete [] matInteriorDiagNnz;
-	matInteriorDiagNnz = NULL;
-      }
-      
-      if (matInteriorOffdiagNnz) {
-	delete [] matInteriorOffdiagNnz;
-	matInteriorOffdiagNnz = NULL;
-      }
+      nnzInterior.clear();
 
-      if (matCoarseDiagNnz) {
-	delete [] matCoarseDiagNnz;
-	matCoarseDiagNnz = NULL;
-      }
-      
-      if (matCoarseOffdiagNnz) {
-	delete [] matCoarseOffdiagNnz;
-	matCoarseOffdiagNnz = NULL;
+      if (coarseSpaceMap) {
+	nnzCoarse.clear();
+	nnzCoarseInt.clear();
+	nnzIntCoarse.clear();
       }
 
       updateSubdomainData();
@@ -1034,18 +1046,11 @@ namespace AMDiS {
   {
     FUNCNAME("PetscSolverGlobalMatrix::createPetscNnzStructure()");
 
-    TEST_EXIT_DBG(!matInteriorDiagNnz)("There is something wrong!\n");
-
     vector<const FiniteElemSpace*> feSpaces = getFeSpaces(mat);
     int nRankRows = interiorMap->getRankDofs();
     int rankStartIndex = interiorMap->getStartDofs();
 
-    matInteriorDiagNnz = new int[nRankRows];
-    matInteriorOffdiagNnz = new int[nRankRows];
-    for (int i = 0; i < nRankRows; i++) {
-      matInteriorDiagNnz[i] = 0;
-      matInteriorOffdiagNnz[i] = 0;
-    }
+    nnzInterior.create(nRankRows, nRankRows);
 
     using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
     namespace traits = mtl::traits;
@@ -1143,9 +1148,9 @@ namespace AMDiS {
 		// otherwise the matInteriorDiagNnz value.
 		if (petscColIdx >= rankStartIndex && 
 		    petscColIdx < rankStartIndex + nRankRows)
-		  matInteriorDiagNnz[localPetscRowIdx]++;
+		  nnzInterior.dnnz[localPetscRowIdx]++;
 		else
-		  matInteriorOffdiagNnz[localPetscRowIdx]++;
+		  nnzInterior.onnz[localPetscRowIdx]++;
 	      }    
 	    }
 	  } else {
@@ -1202,9 +1207,9 @@ namespace AMDiS {
 	     r, localRowIdx, nRankRows, it->first);
 	  
 	  if (c < rankStartIndex || c >= rankStartIndex + nRankRows)
-	    matInteriorOffdiagNnz[localRowIdx]++;
+	    nnzInterior.onnz[localRowIdx]++;
 	  else
-	    matInteriorDiagNnz[localRowIdx]++;
+	    nnzInterior.dnnz[localRowIdx]++;
 	}
       }
     }
@@ -1217,33 +1222,26 @@ namespace AMDiS {
 
     if (nRankRows < 100) 
       for (int i = 0; i < nRankRows; i++)
-	matInteriorDiagNnz[i] = std::min(matInteriorDiagNnz[i], nRankRows);
+	nnzInterior.dnnz[i] = std::min(nnzInterior.dnnz[i], nRankRows);
   }
 
 
   void PetscSolverGlobalMatrix::createPetscNnzStructureWithCoarseSpace(Matrix<DOFMatrix*> *mat,
-								       ParallelDofMapping &dofMap,
-								       int*& diagNnz, 
-								       int*& offdiagNnz,
+								       ParallelDofMapping &rowDofMap,
+								       ParallelDofMapping &colDofMap,
+								       NnzStructure &nnz,
 								       bool localMatrix)
   {
     FUNCNAME("PetscSolverGlobalMatrix::createPetscNnzStructure()");
 
-    TEST_EXIT_DBG(!diagNnz)("There is something wrong!\n");
-
     vector<const FiniteElemSpace*> feSpaces = getFeSpaces(mat);
-    int nRankRows = dofMap.getRankDofs();
-    int rankStartIndex = dofMap.getStartDofs();
+    int nRankRows = rowDofMap.getRankDofs();
+    int rankStartRowIndex = rowDofMap.getStartDofs();
 
-    diagNnz = new int[nRankRows];
-    for (int i = 0; i < nRankRows; i++)
-      diagNnz[i] = 0;
+    int nRankCols = colDofMap.getRankDofs();
+    int rankStartColIndex = colDofMap.getStartDofs();
 
-    if (localMatrix == false) {
-      offdiagNnz = new int[nRankRows];
-      for (int i = 0; i < nRankRows; i++)
-	offdiagNnz[i] = 0;
-    }
+    nnz.create(nRankRows, (!localMatrix ? nRankRows : -1));
 
     using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
     namespace traits = mtl::traits;
@@ -1308,21 +1306,21 @@ namespace AMDiS {
 	for (cursor_type cursor = begin<row>(bmat), 
 	       cend = end<row>(bmat); cursor != cend; ++cursor) {
 
-	  if (dofMap[feSpaces[i]].find(*cursor, rowDofIndex) == false)
+	  if (rowDofMap[feSpaces[i]].find(*cursor, rowDofIndex) == false)
 	    continue;
 
 	  // The corresponding global matrix row index of the current row DOF.
 	  int petscRowIdx = 0;
 	  if (localMatrix) {
-	    petscRowIdx = dofMap.getLocalMatIndex(i, *cursor);
+	    petscRowIdx = rowDofMap.getLocalMatIndex(i, *cursor);
 	  } else {
-	    if (dofMap.isMatIndexFromGlobal())
-	      petscRowIdx = dofMap.getMatIndex(i, rowDofIndex.global);
+	    if (rowDofMap.isMatIndexFromGlobal())
+	      petscRowIdx = rowDofMap.getMatIndex(i, rowDofIndex.global);
 	    else
-	      petscRowIdx = dofMap.getMatIndex(i, *cursor);
+	      petscRowIdx = rowDofMap.getMatIndex(i, *cursor);
 	  }
 
-	  if (localMatrix || dofMap[feSpaces[i]].isRankDof(*cursor)) {
+	  if (localMatrix || rowDofMap[feSpaces[i]].isRankDof(*cursor)) {
     	    
 	    // === The current row DOF is a rank DOF, so create the       ===
 	    // === corresponding nnz values directly on rank's nnz data.  ===
@@ -1330,50 +1328,47 @@ namespace AMDiS {
 	    // This is the local row index of the local PETSc matrix.
 	    int localPetscRowIdx = petscRowIdx;
 
-	    if (localMatrix == false) {
-	      localPetscRowIdx -= rankStartIndex;
+	    if (localMatrix == false)
+	      localPetscRowIdx -= rankStartRowIndex;
 	    
-	      TEST_EXIT_DBG(localPetscRowIdx >= 0 && localPetscRowIdx < nRankRows)
-		("Should not happen! \n Debug info: DOF = %d   globalRowIndx = %d   petscRowIdx = %d   localPetscRowIdx = %d   rStart = %d   compontens = %d from %d   nRankRows = %d\n",
-		 *cursor,
-		 dofMap[feSpaces[i]][*cursor].global,
-		 petscRowIdx, 
-		 localPetscRowIdx, 
-		 rankStartIndex,
-		 i,
-		 nComponents, 
-		 nRankRows);
-	    }
+	    TEST_EXIT_DBG(localPetscRowIdx >= 0 && localPetscRowIdx < nRankRows)
+	      ("Should not happen! \n Debug info: DOF = %d   globalRowIndx = %d   petscRowIdx = %d   localPetscRowIdx = %d   rStart = %d   compontens = %d from %d   nRankRows = %d\n",
+	       *cursor,
+	       rowDofMap[feSpaces[i]][*cursor].global,
+	       petscRowIdx, 
+	       localPetscRowIdx, 
+	       rankStartRowIndex,
+	       i,
+	       nComponents, 
+	       nRankRows);
 	    
 
 	    if (localMatrix) {
 	      for (icursor_type icursor = begin<nz>(cursor), 
 		     icend = end<nz>(cursor); icursor != icend; ++icursor)
-		if (dofMap[feSpaces[j]].isSet(col(*icursor)))
-		  diagNnz[localPetscRowIdx]++;	      
+		if (colDofMap[feSpaces[j]].isSet(col(*icursor)))
+		  nnz.dnnz[localPetscRowIdx]++;	      
 	    } else {
 	      MultiIndex colDofIndex;
 
 	      // Traverse all non zero entries in this row.
 	      for (icursor_type icursor = begin<nz>(cursor), 
 		     icend = end<nz>(cursor); icursor != icend; ++icursor) {
-		if (dofMap[feSpaces[j]].find(col(*icursor), colDofIndex) == false)
+		if (colDofMap[feSpaces[j]].find(col(*icursor), colDofIndex) == false)
 		  continue;
 		
-		int petscColIdx = (dofMap.isMatIndexFromGlobal() ? 
-				   dofMap.getMatIndex(j, colDofIndex.global) :
-				   dofMap.getMatIndex(j, col(*icursor)));
-		
-		if (value(*icursor) != 0.0 || petscRowIdx == petscColIdx) {
-		  // The row DOF is a rank DOF, if also the column is a rank DOF, 
-		  // increment the diagNnz values for this row, 
-		  // otherwise the offdiagNnz value.
-		  if (petscColIdx >= rankStartIndex && 
-		      petscColIdx < rankStartIndex + nRankRows)
-		    diagNnz[localPetscRowIdx]++;
-		  else
-		    offdiagNnz[localPetscRowIdx]++;
-		}    
+		int petscColIdx = (colDofMap.isMatIndexFromGlobal() ? 
+				   colDofMap.getMatIndex(j, colDofIndex.global) :
+				   colDofMap.getMatIndex(j, col(*icursor)));
+	
+		// The row DOF is a rank DOF, if also the column is a rank DOF, 
+		// increment the diagNnz values for this row, 
+		// otherwise the offdiagNnz value.
+		if (petscColIdx >= rankStartColIndex && 
+		    petscColIdx < rankStartColIndex + nRankCols)
+		  nnz.dnnz[localPetscRowIdx]++;
+		else
+		  nnz.onnz[localPetscRowIdx]++;
 	      }
 	    }
 	  } else {
@@ -1389,17 +1384,15 @@ namespace AMDiS {
 
 	    for (icursor_type icursor = begin<nz>(cursor), 
 		   icend = end<nz>(cursor); icursor != icend; ++icursor) {
-	      if (dofMap[feSpaces[j]].find(col(*icursor), colDofIndex) == false)
+	      if (colDofMap[feSpaces[j]].find(col(*icursor), colDofIndex) == false)
 		continue;
 
-	      if (value(*icursor) != 0.0) {
-		int petscColIdx = (dofMap.isMatIndexFromGlobal() ? 
-				   dofMap.getMatIndex(j, colDofIndex.global) :
-				   dofMap.getMatIndex(j, col(*icursor)));
-		
-		sendMatrixEntry[sendToRank].
-		  push_back(make_pair(petscRowIdx, petscColIdx));
-	      }
+	      int petscColIdx = (colDofMap.isMatIndexFromGlobal() ? 
+				 colDofMap.getMatIndex(j, colDofIndex.global) :
+				 colDofMap.getMatIndex(j, col(*icursor)));
+	      
+	      sendMatrixEntry[sendToRank].
+		push_back(make_pair(petscRowIdx, petscColIdx));
 	    }
 	    
 	  } // if (isRankDof[*cursor]) ... else ...
@@ -1407,6 +1400,7 @@ namespace AMDiS {
       } 
     }
 
+
     if (localMatrix == false) {
       // === Send and recv the nnz row structure to/from other ranks. ===
       
@@ -1428,43 +1422,54 @@ namespace AMDiS {
 	    int r = it->second[i].first;
 	    int c = it->second[i].second;
 	    
-	    int localRowIdx = r - rankStartIndex;
+	    int localRowIdx = r - rankStartRowIndex;
 	    
 	    TEST_EXIT_DBG(localRowIdx >= 0 && localRowIdx < nRankRows)
 	      ("Got row index %d/%d (nRankRows = %d) from rank %d. Should not happen!\n",
 	       r, localRowIdx, nRankRows, it->first);
 	    
-	    if (c < rankStartIndex || c >= rankStartIndex + nRankRows)
-	      offdiagNnz[localRowIdx]++;
+	    if (c < rankStartColIndex || c >= rankStartColIndex + nRankCols)
+	      nnz.onnz[localRowIdx]++;
 	    else
-	      diagNnz[localRowIdx]++;
+	      nnz.dnnz[localRowIdx]++;
 	  }
 	}
       }
-
-      // The above algorithm for calculating the number of nnz per row over-
-      // approximates the value, i.e., the number is always equal or larger to 
-      // the real number of nnz values in the global parallel matrix. For small
-      // matrices, the problem may arise, that the result is larger than the
-      // number of elements in a row. This is fixed in the following.
-      
-      if (nRankRows < 100) 
-	for (int i = 0; i < nRankRows; i++)
-	  diagNnz[i] = std::min(diagNnz[i], nRankRows);
     }
 
+    // The above algorithm for calculating the number of nnz per row over-
+    // approximates the value, i.e., the number is always equal or larger to 
+    // the real number of nnz values in the global parallel matrix. For small
+    // matrices, the problem may arise, that the result is larger than the
+    // number of elements in a row. This is fixed in the following.
+
+//     if (nRankRows < 100) 
+//       for (int i = 0; i < nRankRows; i++)
+// 	nnzInterior.dnnz[i] = std::min(nnzInterior.dnnz[i], nRankCols);
 
-#if (DEBUG != 0)    
+#if (DEBUG != 0)
     int nMax = 0; 
     int nSum = 0;
     for (int i = 0; i < nRankRows; i++) {
-      nMax = std::max(nMax, diagNnz[i]);
-      nSum += diagNnz[i];
+      nMax = std::max(nMax, nnz.dnnz[i]);
+      nSum += nnz.dnnz[i];
     }
 
-    MSG("NNZ in matrix: max = %d, avrg = %.0f\n",
-	nMax, static_cast<double>(nSum) / nRankRows);
-#endif
+    MSG("NNZ in diag block: max = %d, avrg = %.0f\n",
+	nMax, (nSum > 0 ? (static_cast<double>(nSum) / nRankRows) : 0));
+
+    if (!localMatrix) {
+      nMax = 0;
+      nSum = 0;
+
+      for (int i = 0; i < nRankRows; i++) {
+	nMax = std::max(nMax, nnz.onnz[i]);
+	nSum += nnz.onnz[i];
+      }
 
+      MSG("NNZ in offdiag block: max = %d, avrg = %.0f\n",
+	  nMax, (nSum > 0 ? (static_cast<double>(nSum) / nRankRows) : 0));     
+    }
   }
+#endif
 }
diff --git a/AMDiS/src/parallel/PetscSolverGlobalMatrix.h b/AMDiS/src/parallel/PetscSolverGlobalMatrix.h
index 63b2fc47..728b1a2e 100644
--- a/AMDiS/src/parallel/PetscSolverGlobalMatrix.h
+++ b/AMDiS/src/parallel/PetscSolverGlobalMatrix.h
@@ -31,16 +31,56 @@ namespace AMDiS {
 
   using namespace std;
 
+  struct NnzStructure {
+    NnzStructure()
+      : dnnz(NULL),
+	onnz(NULL)
+    {}
+	
+    void clear()
+    {
+      if (dnnz) {
+	delete [] dnnz;
+	dnnz = NULL;
+      }
+
+      if (onnz) {
+	delete [] onnz;
+	onnz = NULL;
+      }
+    }
+
+    void create(int nRows0, int nRows1 = -1)
+    {
+      if (nRows0 == 0)
+	return;
+
+      TEST_EXIT_DBG(nRows0 > 0)("Should not happen!\n");
+
+      dnnz = new int[nRows0];
+      for (int i = 0; i < nRows0; i++)
+	dnnz[i] = 0;
+
+      if (nRows1 > 0) {
+	onnz = new int[nRows1];
+	for (int i = 0; i < nRows1; i++)
+	  onnz[i] = 0;	
+      }
+    }
+
+    int *dnnz;
+
+    int *onnz;
+  };
+
+
+
   class PetscSolverGlobalMatrix : public PetscSolver
   {
   public:
     PetscSolverGlobalMatrix()
       : PetscSolver(),
 	petscSolVec(PETSC_NULL),
-	matInteriorDiagNnz(NULL),
-	matInteriorOffdiagNnz(NULL),
-	matCoarseDiagNnz(NULL),
-	matCoarseOffdiagNnz(NULL),
 	lastMeshNnz(0),
 	zeroStartVector(false),
 	alwaysCreateNnzStructure(false)
@@ -81,9 +121,9 @@ namespace AMDiS {
     void createPetscNnzStructure(Matrix<DOFMatrix*> *mat);
 
     void createPetscNnzStructureWithCoarseSpace(Matrix<DOFMatrix*> *mat,
-						ParallelDofMapping &dofMap,
-						int*& diagNnz, 
-						int*& offdiagNnz,
+						ParallelDofMapping &rowDofMap,
+						ParallelDofMapping &colDofMap,
+						NnzStructure &nnz,
 						bool localMatrix = false);
     
     /// Takes a DOF matrix and sends the values to the global PETSc matrix.
@@ -108,11 +148,11 @@ namespace AMDiS {
 
 
   protected:
-    /// Arrays definig the non zero pattern of Petsc's interior matrix.
-    int *matInteriorDiagNnz, *matInteriorOffdiagNnz;
+    NnzStructure nnzInterior;
+
+    NnzStructure nnzCoarse;
 
-    /// Arrays definig the non zero pattern of Petsc's coarse space matrix.
-    int *matCoarseDiagNnz, *matCoarseOffdiagNnz;
+    NnzStructure nnzIntCoarse, nnzCoarseInt;
 
     Vec petscSolVec;
 
-- 
GitLab