From 8881aea28f3af77d82e7a8a65b7b49a190145ef0 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Thu, 7 Apr 2011 09:26:59 +0000
Subject: [PATCH] PetscSchur solver makes use of MatNest for simpler definition
 of preconditioners.

---
 AMDiS/src/parallel/PetscSolver.cc | 178 +++++++++++++++++++-----------
 AMDiS/src/parallel/PetscSolver.h  |  36 +++---
 2 files changed, 134 insertions(+), 80 deletions(-)

diff --git a/AMDiS/src/parallel/PetscSolver.cc b/AMDiS/src/parallel/PetscSolver.cc
index 1b8672d0..f56b300b 100644
--- a/AMDiS/src/parallel/PetscSolver.cc
+++ b/AMDiS/src/parallel/PetscSolver.cc
@@ -27,6 +27,29 @@ namespace AMDiS {
   }
 
 
+  void PetscSolver::printSolutionInfo(AdaptInfo *adaptInfo,
+				      bool iterationCounter, 
+				      bool residual)
+  {
+    FUNCNAME("PetscSolver::printSolutionInfo()");
+
+    if (iterationCounter) {
+      int iterations = 0;
+      KSPGetIterationNumber(solver, &iterations);
+      MSG("  Number of iterations: %d\n", iterations);
+      adaptInfo->setSolverIterations(iterations);
+    }
+
+    if (residual) {
+      double norm = 0.0;
+      MatMult(petscMatrix, petscSolVec, petscTmpVec);
+      VecAXPY(petscTmpVec, -1.0, petscRhsVec);
+      VecNorm(petscTmpVec, NORM_2, &norm);
+      MSG("  Residual norm: %e\n", norm);
+    }
+  }
+
+
   void PetscSolverGlobalMatrix::fillPetscMatrix(Matrix<DOFMatrix*> *mat, SystemVector *vec)
   {
     FUNCNAME("PetscSolverGlobalMatrix::fillPetscMatrix()");
@@ -139,10 +162,6 @@ namespace AMDiS {
     }
 
     // === Init PETSc solver. ===
-
-    KSP solver;
-    PC pc;
-
     KSPCreate(PETSC_COMM_WORLD, &solver);
     KSPGetPC(solver, &pc);
     KSPSetOperators(solver, petscMatrix, petscMatrix, SAME_NONZERO_PATTERN); 
@@ -157,17 +176,14 @@ namespace AMDiS {
       KSPSetInitialGuessNonzero(solver, PETSC_TRUE);
 
    
-    // === Run PETSc. ===
-
+    // PETSc.
     KSPSolve(solver, petscRhsVec, petscSolVec);
 
-
-    // === Transfere values from PETSc's solution vectors to the dof vectors.
-
+    // === Transfere values from PETSc's solution vectors to the DOF vectors. ===
+    int nRankDofs = meshDistributor->getNumberRankDofs();
     PetscScalar *vecPointer;
     VecGetArray(petscSolVec, &vecPointer);
 
-    int nRankDofs = meshDistributor->getNumberRankDofs();
     for (int i = 0; i < nComponents; i++) {
       DOFVector<double> &dofvec = *(vec.getDOFVector(i));
       for (int j = 0; j < nRankDofs; j++)
@@ -178,26 +194,16 @@ namespace AMDiS {
     VecRestoreArray(petscSolVec, &vecPointer);
 
 
-    // === Synchronize DOFs at common DOFs, i.e., DOFs that correspond to more ===
-    // === than one partition.                                                 ===
+    // === Synchronize DOFs at common DOFs, i.e., DOFs that correspond to ===
+    // === more than one partition.                                       ===
     meshDistributor->synchVector(vec);
 
 
-    // === Print information about solution process. ===
-
-    int iterations = 0;
-    KSPGetIterationNumber(solver, &iterations);
-    MSG("  Number of iterations: %d\n", iterations);
-    adaptInfo->setSolverIterations(iterations);
+    // Print iteration counter and residual norm of the solution.
+    printSolutionInfo(adaptInfo);
 
-    double norm = 0.0;
-    MatMult(petscMatrix, petscSolVec, petscTmpVec);
-    VecAXPY(petscTmpVec, -1.0, petscRhsVec);
-    VecNorm(petscTmpVec, NORM_2, &norm);
-    MSG("  Residual norm: %e\n", norm);
 
-
-    // === Destroy Petsc's variables. ===
+    // === Destroy PETSc's variables. ===
 
     MatDestroy(petscMatrix);
     VecDestroy(petscRhsVec);
@@ -811,7 +817,6 @@ namespace AMDiS {
     MatAssemblyBegin(matA22, MAT_FINAL_ASSEMBLY);
     MatAssemblyEnd(matA22, MAT_FINAL_ASSEMBLY);
 
-
     Mat tmpMat[2][2];
     tmpMat[0][0] = matA11;
     tmpMat[0][1] = matA12;
@@ -825,26 +830,24 @@ namespace AMDiS {
     MatAssemblyEnd(petscMatrix, MAT_FINAL_ASSEMBLY);
 
 
-    MatGetVecs(matA12, &petscRhsVec2, &petscRhsVec1);
-    MatGetVecs(matA12, &petscSolVec2, &petscSolVec1);
+    int nRankRows = meshDistributor->getNumberRankDofs() * nComponents;
+    int nOverallRows = meshDistributor->getNumberOverallDofs() * nComponents;
 
-    for (int i = 0; i < nComponents; i++)
-      setDofVector(petscRhsVec, vec->getDOFVector(i), nComponents, i);
+    VecCreate(PETSC_COMM_WORLD, &petscRhsVec);
+    VecSetSizes(petscRhsVec, nRankRows, nOverallRows);
+    VecSetType(petscRhsVec, VECMPI);
 
-    Vec tmpVec[2];
-    tmpVec[0] = petscRhsVec1;
-    tmpVec[1] = petscRhsVec2;
-    VecCreateNest(PETSC_COMM_WORLD, 2, PETSC_NULL, tmpVec, &petscRhsVec);
+    VecCreate(PETSC_COMM_WORLD, &petscSolVec);
+    VecSetSizes(petscSolVec, nRankRows, nOverallRows);
+    VecSetType(petscSolVec, VECMPI);
+
+    VecCreate(PETSC_COMM_WORLD, &petscTmpVec);
+    VecSetSizes(petscTmpVec, nRankRows, nOverallRows);
+    VecSetType(petscTmpVec, VECMPI);
 
-    tmpVec[0] = petscSolVec1;
-    tmpVec[1] = petscSolVec2;
-    VecCreateNest(PETSC_COMM_WORLD, 2, PETSC_NULL, tmpVec, &petscSolVec);
 
-    VecAssemblyBegin(petscRhsVec1);
-    VecAssemblyEnd(petscRhsVec1);
-      
-    VecAssemblyBegin(petscRhsVec2);
-    VecAssemblyEnd(petscRhsVec2);
+    for (int i = 0; i < nComponents; i++)
+      setDofVector(petscRhsVec, vec->getDOFVector(i), nComponents, i);
 
     VecAssemblyBegin(petscRhsVec);
     VecAssemblyEnd(petscRhsVec);
@@ -855,33 +858,78 @@ namespace AMDiS {
   {
     FUNCNAME("PetscSolverSchur::solvePetscMatrix()");
 
-    KSP solver;
-    PC pc;
-    KSPCreate(PETSC_COMM_WORLD, &solver);
-    KSPGetPC(solver, &pc);
-    //    PCSetType(pc, PCFIELDSPLIT);
-    const PetscInt interiorField[1] = {0};
-    const PetscInt boundaryField[1] = {1};
-    PCFieldSplitSetFields(pc, "interior", 1, interiorField);
-    PCFieldSplitSetFields(pc, "boundary", 1, boundaryField);
+    int nComponents = vec.getSize();
 
+    KSPCreate(PETSC_COMM_WORLD, &solver);
 
     KSPSetOperators(solver, petscMatrix, petscMatrix, SAME_NONZERO_PATTERN); 
     KSPSetTolerances(solver, 0.0, 1e-8, PETSC_DEFAULT, PETSC_DEFAULT);
+    KSPMonitorSet(solver, myKSPMonitor, PETSC_NULL, 0);
     KSPSetFromOptions(solver);
+
+    KSPGetPC(solver, &pc);
+    PCSetType(pc, PCFIELDSPLIT);
+
+    IS interiorIs;
+    ISCreateStride(PETSC_COMM_WORLD, 
+		   nInteriorDofs * nComponents,
+		   (rStartInteriorDofs + rStartBoundaryDofs) * nComponents, 
+		   1, &interiorIs);
+    PCFieldSplitSetIS(pc, "interior", interiorIs);
+
+
+    IS boundaryIs;
+    ISCreateStride(PETSC_COMM_WORLD,
+		   nBoundaryDofs * nComponents,
+		   (rStartInteriorDofs + rStartBoundaryDofs + nInteriorDofs) * nComponents, 
+		   1, &boundaryIs);
+    PCFieldSplitSetIS(pc, "boundary", boundaryIs);
+
     PCSetFromOptions(pc);
 
+
     KSPSolve(solver, petscRhsVec, petscSolVec);
 
-    KSPDestroy(solver);
+    // === Transfere values from PETSc's solution vectors to AMDiS vectors. ===
 
-    VecDestroy(petscRhsVec1);
-    VecDestroy(petscRhsVec2);    
-    VecDestroy(petscRhsVec);
+    PetscScalar *vecPointer;
+    VecGetArray(petscSolVec, &vecPointer);
 
-    VecDestroy(petscSolVec1);
-    VecDestroy(petscSolVec2);    
+    for (int i = 0; i < nComponents; i++) {
+      DOFVector<double>::Iterator dofIt(vec.getDOFVector(i), USED_DOFS);
+      for (dofIt.reset(); !dofIt.end(); ++dofIt) {
+	DegreeOfFreedom globalRowDof = 
+	  meshDistributor->mapLocalToGlobal(dofIt.getDOFIndex());
+	if (boundaryDofs.count(globalRowDof)) {
+	  int index =
+	    (mapGlobalBoundaryDof[globalRowDof] - rStartBoundaryDofs + nInteriorDofs) * (i + 1);
+	  *dofIt = vecPointer[index];
+	} else {
+	  int index = 
+	    (mapGlobalInteriorDof[globalRowDof] - rStartInteriorDofs) * (i + 1);
+	  *dofIt = vecPointer[index];
+	}
+      }
+    }
+
+    VecRestoreArray(petscSolVec, &vecPointer);
+
+
+    // === Synchronize DOFs at common DOFs, i.e., DOFs that correspond to ===
+    // === more than one partition.                                       ===
+    meshDistributor->synchVector(vec);
+
+
+
+    // === Print iteration counter and residual norm of the solution. ===
+    printSolutionInfo(adaptInfo);
+
+
+    // === Destroy PETSC's variables. ===
+
+    VecDestroy(petscRhsVec);
     VecDestroy(petscSolVec);
+    VecDestroy(petscTmpVec);
 
     MatDestroy(matA11);
     MatDestroy(matA12);
@@ -889,8 +937,7 @@ namespace AMDiS {
     MatDestroy(matA22);
     MatDestroy(petscMatrix);
 
-    MSG("SOLVED IT!\n");
-    exit(0);
+    KSPDestroy(solver);
   }
   
 
@@ -984,11 +1031,16 @@ namespace AMDiS {
       double value = *dofIt;
 
       if (boundaryDofs.count(globalRowDof)) {
-	int index = mapGlobalBoundaryDof[globalRowDof] * dispMult + dispAdd;
-	VecSetValues(petscRhsVec2, 1, &index, &value, ADD_VALUES);
+	int index = 
+	  (rStartInteriorDofs + 
+	   nInteriorDofs +
+	   mapGlobalBoundaryDof[globalRowDof]) * dispMult + dispAdd;
+	VecSetValues(petscRhsVec, 1, &index, &value, ADD_VALUES);
       } else {
-	int index = mapGlobalInteriorDof[globalRowDof] * dispMult + dispAdd;
-	VecSetValues(petscRhsVec1, 1, &index, &value, ADD_VALUES);
+	int index = 
+	  (rStartBoundaryDofs + 
+	   mapGlobalInteriorDof[globalRowDof]) * dispMult + dispAdd;
+	VecSetValues(petscRhsVec, 1, &index, &value, ADD_VALUES);
       }
     }
   }
diff --git a/AMDiS/src/parallel/PetscSolver.h b/AMDiS/src/parallel/PetscSolver.h
index ca0cdec5..25a7e3c8 100644
--- a/AMDiS/src/parallel/PetscSolver.h
+++ b/AMDiS/src/parallel/PetscSolver.h
@@ -41,6 +41,7 @@ namespace AMDiS {
 
   using namespace std;
 
+
   class PetscSolver
   {
   public:
@@ -68,8 +69,26 @@ namespace AMDiS {
     /// Use PETSc to solve the linear system of equations
     virtual void solvePetscMatrix(SystemVector &vec, AdaptInfo *adaptInfo) = 0;
 
+  protected:
+    void printSolutionInfo(AdaptInfo* adaptInfo,
+			   bool iterationCounter = true,
+			   bool residual = true);
+
   protected:
     MeshDistributor *meshDistributor;
+
+    /// Petsc's matrix structure.
+    Mat petscMatrix;
+
+    /** \brief
+     * PETSc's vector structures for the rhs vector, the solution vector and a
+     * temporary vector for calculating the final residuum.
+     */
+    Vec petscRhsVec, petscSolVec, petscTmpVec;
+
+    KSP solver;
+
+    PC pc;
   };
 
 
@@ -103,15 +122,6 @@ namespace AMDiS {
 		      int disMult = 1, int dispAdd = 0, bool rankOnly = false);
 
   protected:
-    /// Petsc's matrix structure.
-    Mat petscMatrix;
-
-    /** \brief
-     * PETSc's vector structures for the rhs vector, the solution vector and a
-     * temporary vector for calculating the final residuum.
-     */
-    Vec petscRhsVec, petscSolVec, petscTmpVec;
-
     /// Arrays definig the non zero pattern of Petsc's matrix.
     int *d_nnz, *o_nnz;
 
@@ -172,14 +182,6 @@ namespace AMDiS {
     map<DegreeOfFreedom, DegreeOfFreedom> mapGlobalInteriorDof;
 
     Mat matA11, matA12, matA21, matA22;
-
-    Mat petscMatrix;
-
-    Vec petscRhsVec1, petscRhsVec2;
-
-    Vec petscSolVec1, petscSolVec2;
-
-    Vec petscRhsVec, petscSolVec;
   };
 #endif
 
-- 
GitLab