// // Software License for AMDiS // // Copyright (c) 2010 Dresden University of Technology // All rights reserved. // Authors: Simon Vey, Thomas Witkowski et al. // // This file is part of AMDiS // // See also license.opensource.txt in the distribution. #include "AMDiS.h" #include "parallel/PetscSolver.h" #include "parallel/StdMpi.h" #include "parallel/MpiHelper.h" namespace AMDiS { using namespace std; PetscSolver::PetscSolver() : meshDistributor(NULL), subdomainLevel(0), interiorMap(NULL), coarseSpaceMap(NULL), mpiRank(-1), kspPrefix(""), removeRhsNullspace(false), hasConstantNullspace(false) { string kspStr = ""; Parameters::get("parallel->solver->petsc->ksp", kspStr); if (kspStr != "") PetscOptionsInsertString(kspStr.c_str()); Parameters::get("parallel->remove rhs null space", removeRhsNullspace); Parameters::get("parallel->has constant null space", hasConstantNullspace); } void PetscSolver::setDofMapping(ParallelDofMapping *interiorDofs, ParallelDofMapping *coarseDofs) { interiorMap = interiorDofs; coarseSpaceMap = coarseDofs; } void PetscSolver::updateSubdomainData() { if (mpiCommLocal.Get_size() == 1) { rStartInterior = 0; nGlobalOverallInterior = interiorMap->getOverallDofs(); } else { int groupRowsInterior = 0; if (mpiCommLocal.Get_rank() == 0) groupRowsInterior = interiorMap->getOverallDofs(); mpi::getDofNumbering(mpiCommGlobal, groupRowsInterior, rStartInterior, nGlobalOverallInterior); int tmp = 0; if (mpiCommLocal.Get_rank() == 0) tmp = rStartInterior; mpiCommLocal.Allreduce(&tmp, &rStartInterior, 1, MPI_INT, MPI_SUM); } } void PetscSolver::solve(Vec &rhs, Vec &sol) { FUNCNAME("PetscSolver::solve()"); PetscErrorCode solverError = KSPSolve(kspInterior, rhs, sol); if (solverError != 0) { AMDiS::finalize(); exit(-1); } } void PetscSolver::solveGlobal(Vec &rhs, Vec &sol) { FUNCNAME("PetscSolver::solveGlobal()"); ERROR_EXIT("Not implemented!\n"); } void PetscSolver::copyVec(Vec& originVec, Vec& destVec, vector& originIndex, vector& destIndex) { FUNCNAME("PetscSolver::copyVec()"); IS originIs, destIs; ISCreateGeneral(mpiCommGlobal, originIndex.size(), &(originIndex[0]), PETSC_USE_POINTER, &originIs); ISCreateGeneral(mpiCommGlobal, destIndex.size(), &(destIndex[0]), PETSC_USE_POINTER, &destIs); VecScatter scatter; VecScatterCreate(originVec, originIs, destVec, destIs, &scatter); VecScatterBegin(scatter, originVec, destVec, INSERT_VALUES, SCATTER_FORWARD); VecScatterEnd(scatter, originVec, destVec, INSERT_VALUES, SCATTER_FORWARD); ISDestroy(&originIs); ISDestroy(&destIs); VecScatterDestroy(&scatter); } vector PetscSolver::getFeSpaces(Matrix *mat) { FUNCNAME("PetscSolver::getFeSpaces()"); int nComponents = mat->getNumRows(); vector result(nComponents); for (int i = 0; i < nComponents; i++) for (int j = 0; j < nComponents; j++) if ((*mat)[i][j]) { result[i] = (*mat)[i][j]->getRowFeSpace(); break; } #if (DEBUG != 0) // === In debug mode, we test if all FE spaces of the matrix are also === // === considered by the mesh distributor. === checkFeSpaces(result); #endif return result; } vector PetscSolver::getFeSpaces(SystemVector *vec) { FUNCNAME("PetscSolver::getFeSpaces()"); int nComponents = vec->getSize(); vector result(nComponents); for (int i = 0; i < nComponents; i++) result[i] = vec->getFeSpace(i); #if (DEBUG != 0) // === In debug mode, we test if all FE spaces of the matrix are also === // === considered by the mesh distributor. === checkFeSpaces(result); #endif return result; } void PetscSolver::checkFeSpaces(vector& feSpaces) { FUNCNAME("PetscSolver::checkFeSpaces()"); for (unsigned int i = 0; i < feSpaces.size(); i++) { bool found = false; for (unsigned int j = 0; j < meshDistributor->getFeSpaces().size(); j++) if (feSpaces[i] == meshDistributor->getFeSpace(j)) { found = true; break; } TEST_EXIT(found)("FE spaces not found in mesh distributor!\n"); } } }