From 5ba917be79f90a6922750d36f6ecfdea0145b884 Mon Sep 17 00:00:00 2001
From: Thomas Witkowski <thomas.witkowski@gmx.de>
Date: Thu, 19 Jan 2012 13:14:54 +0000
Subject: [PATCH] Integration of the BDDCML library.

---
 AMDiS/AMDISConfig.cmake.in                    |   9 +
 AMDiS/CMakeLists.txt                          |  33 ++-
 AMDiS/src/Serializer.h                        |   6 +-
 AMDiS/src/parallel/BddcMlSolver.cc            | 242 +++++++++++++++---
 AMDiS/src/parallel/BddcMlSolver.h             |  17 +-
 AMDiS/src/time/RosenbrockAdaptInstationary.cc |   3 +-
 6 files changed, 271 insertions(+), 39 deletions(-)

diff --git a/AMDiS/AMDISConfig.cmake.in b/AMDiS/AMDISConfig.cmake.in
index 34e34e6e..aafcef46 100644
--- a/AMDiS/AMDISConfig.cmake.in
+++ b/AMDiS/AMDISConfig.cmake.in
@@ -61,6 +61,7 @@ endif(Boost_FOUND)
 set(AMDIS_NEED_ZOLTAN @ENABLE_ZOLTAN@)
 set(AMDIS_HAS_PARALLEL_DOMAIN @ENABLE_PARALLEL_DOMAIN@)
 set(AMDIS_NEED_UMFPACK @ENABLE_UMFPACK@)
+set(AMDIS_NEED_BDDCML @ENABLE_BDDCML@)
 set(AMDIS_NEED_MKL @ENABLE_MKL@)
 set(AMDIS_USE_FILE ${AMDIS_DIR}/AMDISUse.cmake)
 set(AMDIS_COMPILEFLAGS "@COMPILEFLAGS@")
@@ -101,6 +102,14 @@ if(AMDIS_NEED_UMFPACK)
 	endif()
 endif(AMDIS_NEED_UMFPACK)
 
+if(AMDIS_NEED_BDDCML)
+	set(AMDIS_BDDCML_PATH @BDDCML_PATH@)
+	list(APPEND AMDIS_INCLUDE_DIRS ${AMDIS_BDDCML_PATH})
+
+	set(AMDIS_BDDCML_LIB @BDDCML_LIB@)
+	list(APPEND AMDIS_LIBRARIES ${AMDIS_BDDCML_LIB})
+endif(AMDIS_NEED_BDDCML)
+
 
 #add directories for reinit
 list(APPEND AMDIS_INCLUDE_DIRS ${AMDIS_INCLUDE_DIR}/reinit)
diff --git a/AMDiS/CMakeLists.txt b/AMDiS/CMakeLists.txt
index 072224bb..bc2fef6c 100644
--- a/AMDiS/CMakeLists.txt
+++ b/AMDiS/CMakeLists.txt
@@ -36,6 +36,7 @@ SET(ENABLE_PARALLEL_DOMAIN "OFF" CACHE STRING "use parallel domain decomposition
 option(USE_PETSC_DEV false)
 option(ENABLE_ZOLTAN false)
 option(ENABLE_UMFPACK "use umfpack solver" false)
+option(ENABLE_BDDCML "Use of BDDCML library" false)
 
 
 if(ENABLE_INTEL)
@@ -239,7 +240,9 @@ if(ENABLE_PARALLEL_DOMAIN)
 		find_package(PETSc REQUIRED)
 		include_directories(${PETSC_DIR}/include ${PETSC_DIR}/${PETSC_ARCH}/include)
 		list(APPEND AMDIS_INCLUDE_DIRS ${PETSC_DIR}/include ${PETSC_DIR}/${PETSC_ARCH}/include)
-		list(APPEND PARALLEL_DOMAIN_AMDIS_SRC ${SOURCE_DIR}/parallel/PetscMultigridPrecon.cc
+		list(APPEND PARALLEL_DOMAIN_AMDIS_SRC 
+			${SOURCE_DIR}/parallel/BddcMlSolver.cc
+		        ${SOURCE_DIR}/parallel/PetscMultigridPrecon.cc
 			${SOURCE_DIR}/parallel/PetscSolver.cc
 			${SOURCE_DIR}/parallel/PetscProblemStat.cc
 			${SOURCE_DIR}/parallel/PetscSolverFeti.cc
@@ -279,6 +282,34 @@ if(ENABLE_UMFPACK)
 	SET(RPM_DEPEND_STR "blas")
 endif(ENABLE_UMFPACK)
 
+
+if(ENABLE_BDDCML)
+	find_file(BDDCML_H bddcml_interface_c.h
+			   HINTS ENV CPATH
+			   DOC "Header bddcml_interface_c.h for the BDDCML library.")
+
+	if(BDDCML_H)
+		get_filename_component(BDDCML_PATH ${BDDCML_H} PATH)
+		include_directories(${BDDCML_PATH})		
+		list(APPEND COMPILEFLAGS "-DHAVE_BDDC_ML=1")
+		list(APPEND COMPILEFLAGS "-DAdd_")
+	else()
+		message(FATAL_ERROR "Could not find BDDCML headers.")
+	endif()
+
+	find_library(BDDCML_LIB bddcml
+				HINTS ENV LIBRARY_PATH
+				DOC "BDDCML library")
+
+	if(BDDCML_LIB)
+		list(APPEND AMDIS_LIBS ${BDDCML_LIB})
+	else()
+		message(FATAL_ERROR "Could not find the BDDCML library")
+	endif()
+endif(ENABLE_BDDCML)
+
+
+
 SET(COMPOSITE_SOURCE_DIR ${SOURCE_DIR}/compositeFEM)
 SET(COMPOSITE_FEM_SRC ${COMPOSITE_SOURCE_DIR}/CFE_Integration.cc 
 		      ${COMPOSITE_SOURCE_DIR}/CFE_NormAndErrorFcts.cc 
diff --git a/AMDiS/src/Serializer.h b/AMDiS/src/Serializer.h
index fdfd0631..4df563aa 100644
--- a/AMDiS/src/Serializer.h
+++ b/AMDiS/src/Serializer.h
@@ -58,7 +58,7 @@ namespace AMDiS {
 		      tsModulo);
       TEST_EXIT(name != "")("No filename!\n");
 
-      Parameters::get(problem->getName() + "->output->append index", appendIndex);
+      Parameters::get(problem->getName() + "->output->append serialization index", appendIndex);
       Parameters::get(problem->getName() + "->output->index length", indexLength);
       Parameters::get(problem->getName() + "->output->index decimals", indexDecimals);
     }
@@ -77,7 +77,7 @@ namespace AMDiS {
 
       TEST_EXIT(name != "")("No filename!\n");
 
-      Parameters::get(problem->getName() + "->output->append index", appendIndex);
+      Parameters::get(problem->getName() + "->output->append serialization index", appendIndex);
       Parameters::get(problem->getName() + "->output->index length", indexLength);
       Parameters::get(problem->getName() + "->output->index decimals", indexDecimals);
     }
@@ -118,8 +118,6 @@ namespace AMDiS {
 	filename += string(timeStr);
       }
 
-      filename += ".ser";
-      
 #if HAVE_PARALLEL_DOMAIN_AMDIS
       filename += ".p" + boost::lexical_cast<std::string>(MPI::COMM_WORLD.Get_rank());
 #endif
diff --git a/AMDiS/src/parallel/BddcMlSolver.cc b/AMDiS/src/parallel/BddcMlSolver.cc
index 7cc9e347..5a3513bb 100644
--- a/AMDiS/src/parallel/BddcMlSolver.cc
+++ b/AMDiS/src/parallel/BddcMlSolver.cc
@@ -14,20 +14,25 @@ extern "C" {
 }
 
 #include "parallel/BddcMlSolver.h"
+#include "parallel/MpiHelper.h"
 
 namespace AMDiS {
 
 #ifdef HAVE_BDDC_ML
 
-  void BddcMlSolver::fillPetscMatrix(Matrix<DOFMatrix*> *mat)
+  void BddcMlSolver::fillPetscMatrix(Matrix<DOFMatrix*> *m)
   {
     FUNCNAME("BddcMlSolver::fillPetscMatrix()");
+
+    mat = m;
   }
 
 
   void BddcMlSolver::fillPetscRhs(SystemVector *vec)
   {
     FUNCNAME("BddcMlSolver::fillPetscRhs()");
+
+    rhsVec = vec;
   }
 
 
@@ -35,8 +40,11 @@ namespace AMDiS {
   {
     FUNCNAME("BddcMlSolver::solvePetscMatrix()");
     
+    TEST_EXIT(rhsVec)("Should not happen!\n");
+    TEST_EXIT(mat)("Should not happen!\n");
+
     int nComponents = vec.getSize();
-    const FiniteElemSüace *feSpace = vec.getFeSpace(0);
+    const FiniteElemSpace *feSpace = vec.getFeSpace(0);
     Mesh *mesh = feSpace->getMesh();
     
 
@@ -51,7 +59,7 @@ namespace AMDiS {
     }
 
     map<int, int> mapElIndex;
-    int c = nLeafEls;
+    int nLeafEls = 0;
     for (std::set<int>::iterator it = leafElIndex.begin();
 	 it != leafElIndex.end(); ++it)
       mapElIndex[*it] = nLeafEls++;
@@ -62,7 +70,7 @@ namespace AMDiS {
     int nSubdomains = meshDistributor->getMpiSize();
     int length = 1;
     int nSubPerProc = 1;
-    MPI_Fint c2f = MPI_Comm_c2f(MPI::COMM_WORLD);
+    MPI_Fint c2f = MPI_Comm_c2f(meshDistributor->getMpiComm());
     int verboseLevel = 2;
     int numbase = 0;
 
@@ -92,7 +100,7 @@ namespace AMDiS {
     int nelems = nLeafEls;
 
     // local number of nodes
-    int nnods = feSpace->getUsedSize();
+    int nnods = feSpace->getAdmin()->getUsedSize();
 
     // local number of dofs
     int ndofs = nnods * nComponents;
@@ -117,40 +125,163 @@ namespace AMDiS {
       nnet[i] = 3;
 
     // local array with number of DOFs per node.
-    int nndf[nnod];
-    for (int i = 0; i < nnod; i++)
+    int nndf[nnods];
+    for (int i = 0; i < nnods; i++)
       nndf[i] = nComponents;
 
     // array of indices of subdomain nodes in global numbering
-    int isngn[nnod];
-    for (int i = 0; i < nnod; i++)
-      nnod[i] = meshDistributor->mapLocalToGlobal(feSpace, i);
+    int isngn[nnods];
+    for (int i = 0; i < nnods; i++)
+      isngn[i] = meshDistributor->mapLocalToGlobal(feSpace, i);
 
     // array of indices of subdomain variables in global numbering
     int isvgvn[ndof];
+    for (int j = 0; j < nnods; j++)
+      for (int i = 0; i < nComponents; i++)
+	isvgvn[j * nComponents + i] = 
+	  meshDistributor->mapLocalToGlobal(feSpace, j) * nComponents + i;
+
+    // array of indices of subdomain elements in global numbering
+    int isegn[nelems];
+    int rStartEl, nOverallEl;
+    mpi::getDofNumbering(meshDistributor->getMpiComm(),
+			 nelems, rStartEl, nOverallEl);
+    for (int i = 0; i < nelems; i++)
+      isegn[i] = rStartEl + i;
+
+
+
+    int lxyz1 = nnods;
+    int lxyz2 = 2;
+    // local array with coordinates of nodes
+    double xyz[lxyz1 * lxyz2];
+    
+    {
+      DOFVector<WorldVector<double> > coordDofs(feSpace, "tmp");
+      mesh->getDofIndexCoords(feSpace, coordDofs);
+
+      for (int i = 0; i < lxyz2; i++)
+	for (int j = 0; j < nnods; j++)
+	  xyz[i * nnods + j] = coordDofs[j][i];
+    }
+
+    // local array of indices denoting dirichlet boundary data
+    int ifix[ndofs];
+    for (int i = 0; i < ndofs; i++)
+      ifix[ndofs] = -1;
+
+    // local array of values for dirichlet boundary data
+    double fixv[ndofs];
+
+    // local rhs data
+    double rhs[ndofs];
+    for (int i = 0; i < nComponents; i++) {
+      DOFVector<double>& dofvec = *(rhsVec->getDOFVector(i));
+      for (int j = 0; j < ndofs; j++)
+	rhs[j * nComponents + i] = dofvec[j];
+    }
+
+    // Completenes of the rhs vector on subdomains
+    int is_rhs_complete = 1;
+
+    // Local array with initial solution guess
+    double sol[ndofs];
+    for (int i = 0; i < ndofs; i++)
+      sol[i] = 0.0;
+
+    // matrix type (set here to unsymmetric)
+    int matrixtype = 0;
 
-    /*
-      bddcml_upload_subdomain_data(
-      &nelem,
-      &nnod,
-      &ndof,
-      &ndim,
-      &meshdim,
-      &isub,
-      &nelems,
-      &nnods,
-      &ndofs,
-      inet,
-      &linet,
-      nnet,
-      &nelems,
-      nndf,
-      &nnods,
-      isngn,
-      &nnods,
-
-      );
-    */
+    // Non zero structure of matrix
+    vector<int> i_sparse;
+    vector<int> j_sparse;
+    vector<double> a_sparse;
+
+    for (int i = 0; i < nComponents; i++)
+      for (int j = 0; j < nComponents; j++)
+	if ((*mat)[i][j])
+	  addDofMatrix((*mat)[i][j], 
+		       i_sparse, j_sparse, a_sparse, nComponents, i, j);
+	
+
+    // Number of non-zero entries in matrix
+    int la = i_sparse.size();
+    
+    // Matrix is assembled
+    int is_assembled_int = 1;
+
+
+    bddcml_upload_subdomain_data(&nelem,
+				 &nnod,
+				 &ndof,
+				 &ndim,
+				 &meshdim,
+				 &isub,
+				 &nelems,
+				 &nnods,
+				 &ndofs,
+				 inet,
+				 &linet,
+				 nnet,
+				 &nelems,
+				 nndf,
+				 &nnods,
+				 isngn,
+				 &nnods,
+				 isvgvn,
+				 &ndof,
+				 isegn,
+				 &nelems,
+				 xyz,
+				 &lxyz1,
+				 &lxyz2,
+				 ifix,
+				 &ndofs,
+				 fixv,
+				 &ndofs,
+				 rhs,
+				 &ndofs,
+				 &is_rhs_complete,
+				 sol,
+				 &ndofs,
+				 &matrixtype,
+				 &(i_sparse[0]),
+				 &(j_sparse[0]),
+				 &(a_sparse[0]),
+				 &la,
+				 &is_assembled_int);
+
+
+    int use_defaults_int = 1;
+    int parallel_division_int = 1;
+    int use_arithmetic_int = 1;
+    int use_adaptive_int = 1;
+    bddcml_setup_preconditioner(&matrixtype, 
+				&use_defaults_int,
+				&parallel_division_int,
+				&use_arithmetic_int,
+				&use_adaptive_int);
+
+
+    int method = 1;
+    double tol = 1.e-6;
+    int maxit = 1000;
+    int ndecrmax = 30;
+    int num_iter = 0;
+    int converged_reason = 0;
+    double condition_number = 0.0;
+
+    bddcml_solve(&c2f, 
+		 &method, 
+		 &tol,
+		 &maxit,
+		 &ndecrmax,
+		 &num_iter,
+		 &converged_reason,
+		 &condition_number);
+
+    MSG("BDDCML converged reason: %d within %d iterations \n", 
+	converged_reason, num_iter);
 
     bddcml_finalize();
   }
@@ -161,6 +292,53 @@ namespace AMDiS {
     FUNCNAME("BddcMlSolver::destroyMatrixData()");
   }
 
+
+  void BddcMlSolver::addDofMatrix(DOFMatrix* dmat, 
+				  vector<int> i_sparse, 
+				  vector<int> j_sparse,
+				  vector<double> a_sparse,
+				  int nComponents,
+				  int ithRowComponent,
+				  int ithColComponent)
+  {
+    FUNCNAME("BddcMlSolver::addDofMatrix()");
+
+    TEST_EXIT(dmat)("Should not happen!\n");
+
+    const FiniteElemSpace *feSpace = dmat->getFeSpace();
+
+    using mtl::tag::row; using mtl::tag::nz; using mtl::begin; using mtl::end;
+    namespace traits = mtl::traits;
+    typedef DOFMatrix::base_matrix_type Matrix;
+
+    traits::col<Matrix>::type col(dmat->getBaseMatrix());
+    traits::const_value<Matrix>::type value(dmat->getBaseMatrix());
+
+    typedef traits::range_generator<row, Matrix>::type cursor_type;
+    typedef traits::range_generator<nz, cursor_type>::type icursor_type;
+
+    for (cursor_type cursor = begin<row>(dmat->getBaseMatrix()), 
+	   cend = end<row>(dmat->getBaseMatrix()); cursor != cend; ++cursor) {
+      int rowIndex = 
+	meshDistributor->mapLocalToGlobal(feSpace, *cursor) * nComponents +
+	ithRowComponent;
+
+      for (icursor_type icursor = begin<nz>(cursor), icend = end<nz>(cursor); 
+	   icursor != icend; ++icursor) {	
+	int colIndex = 
+	  meshDistributor->mapLocalToGlobal(feSpace, col(*icursor)) * nComponents +
+	  ithColComponent;
+
+	double val = value(*icursor);
+	
+	i_sparse.push_back(rowIndex);
+	j_sparse.push_back(colIndex);
+	a_sparse.push_back(val);
+      }
+    }
+
+  }
+
 #endif
 
 }
diff --git a/AMDiS/src/parallel/BddcMlSolver.h b/AMDiS/src/parallel/BddcMlSolver.h
index 227dd777..2c08585f 100644
--- a/AMDiS/src/parallel/BddcMlSolver.h
+++ b/AMDiS/src/parallel/BddcMlSolver.h
@@ -36,7 +36,9 @@ namespace AMDiS {
   {
   public:
     BddcMlSolver()
-      : PetscSolver()
+      : PetscSolver(),
+	rhsVec(NULL),
+	mat(NULL)
     {}
 
     void fillPetscMatrix(Matrix<DOFMatrix*> *mat);
@@ -46,6 +48,19 @@ namespace AMDiS {
     void solvePetscMatrix(SystemVector &vec, AdaptInfo *adaptInfo);    
 
     void destroyMatrixData();
+
+  protected:
+    void addDofMatrix(DOFMatrix* mat, 
+		      vector<int> i_sparse, 
+		      vector<int> j_sparse,
+		      vector<double> a_sparse,
+		      int nComponents,
+		      int ithRowComponent,
+		      int ithColComponent);
+  protected:
+    SystemVector *rhsVec;
+
+    Matrix<DOFMatrix*> *mat;
   };
 
 #endif
diff --git a/AMDiS/src/time/RosenbrockAdaptInstationary.cc b/AMDiS/src/time/RosenbrockAdaptInstationary.cc
index ce447451..c46fd0e1 100644
--- a/AMDiS/src/time/RosenbrockAdaptInstationary.cc
+++ b/AMDiS/src/time/RosenbrockAdaptInstationary.cc
@@ -233,7 +233,8 @@ namespace AMDiS {
       if (firstTimestep)
 	firstTimestep = false;
 
-      
+      if (fixFirstTimesteps > 0)
+	fixFirstTimesteps--;     
     } while (rejected || 
 	     (dbgTimestepStudy && (studyTimestep + 1 < dbgTimesteps.size())));
 
-- 
GitLab