From 3484b9be9280aee3c4574d80b80d80b0a23b09e5 Mon Sep 17 00:00:00 2001 From: Sebastian Aland <sebastian.aland@yahoo.com> Date: Tue, 12 Feb 2013 12:51:57 +0000 Subject: [PATCH] PetscSolverCahnHilliard2 korrigiert --- .../src/parallel/PetscSolverCahnHilliard2.cc | 209 +++++++++--------- AMDiS/src/parallel/PetscSolverCahnHilliard2.h | 46 +++- 2 files changed, 142 insertions(+), 113 deletions(-) diff --git a/AMDiS/src/parallel/PetscSolverCahnHilliard2.cc b/AMDiS/src/parallel/PetscSolverCahnHilliard2.cc index e7a996f7..ae421783 100644 --- a/AMDiS/src/parallel/PetscSolverCahnHilliard2.cc +++ b/AMDiS/src/parallel/PetscSolverCahnHilliard2.cc @@ -13,14 +13,15 @@ #include "PetscSolverCahnHilliard2.h" #include "parallel/PetscHelper.h" -#include "parallel/PetscSolverGlobalMatrix.h" +#include "TransformDOF.h" namespace AMDiS { + using namespace std; - - /// solve Schurcomplement Pre-Preconditioner - PetscErrorCode pcChShell2b(PC pc, Vec b, Vec x) // solve Px=b + + + PetscErrorCode pcChShell2b(PC pc, Vec b, Vec x) // solve Px=b {FUNCNAME("PCApply()"); void *ctx; PCShellGetContext(pc, &ctx); @@ -31,41 +32,26 @@ namespace AMDiS { VecDuplicate(b, &y2); KSPSolve(data->kspMplusK, b, y1); - MatMult(data->matM, y1, y2); + MatMult(data->matMass, y1, y2); KSPSolve(data->kspMplusK, y2, x); } /// solve Cahn-Hilliard Preconditioner - PetscErrorCode pcChShell2(PC pc, Vec b, Vec x) // solve Px=b + PetscErrorCode pcChSchurShell(PC pc, Vec b, Vec x) // solve Px=b {FUNCNAME("PCApply()"); void *ctx; PCShellGetContext(pc, &ctx); CahnHilliardData2* data = static_cast<CahnHilliardData2*>(ctx); - Vec b1, b2, x1, x2; - VecNestGetSubVec(b, 0, &b1); - VecNestGetSubVec(b, 1, &b2); - - VecNestGetSubVec(x, 0, &x1); - VecNestGetSubVec(x, 1, &x2); - - Vec y1; - VecDuplicate(b1, &y1); - -// VecPointwiseMult(y1, y2, b1); - KSPSolve(data->kspMass, b1, y1); // M*y1 = b1 - /// create S = M + eps^2*delta*K*D^(-1)*K where D=diag(M) Mat K, S; MatDuplicate(data->matMinusDeltaK, MAT_COPY_VALUES, &K); - MatGetDiagonal(data->matM, x1); - VecReciprocal(x1); - MatDiagonalScale(K, x1, PETSC_NULL); // K' := -delta*D^(-1)*K + MatGetDiagonal(data->matMass, x); + VecReciprocal(x); + MatDiagonalScale(K, x, PETSC_NULL); // K' := -delta*D^(-1)*K MatMatMult(data->matMinusDeltaK, K, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &S); // S := -delta*K*K' - MatAYPX(S, sqr(*data->eps)/(*data->delta), data->matM, DIFFERENT_NONZERO_PATTERN); // S = eps^2/delta*S + M - - MatMultAdd(data->matMinusDeltaK, y1, b2, x1); // x1 := b2-delta*K*y1 + MatAYPX(S, sqr(*data->eps)/(*data->delta), data->matMass, DIFFERENT_NONZERO_PATTERN); // S = eps^2/delta*S + M /// create new solver for S KSP kspS; @@ -79,35 +65,46 @@ namespace AMDiS { PCShellSetContext(pc, data); } - KSPSolve(kspS, x1, x2); // S*x2 = x1 - MatMult(data->matM, x2, y1); // y1 := M*x2 - VecAXPY(y1, -1.0, b2); // y1 := y1 - b2 - - // Project out constant null space - { - int vecSize; - VecGetSize(y1, &vecSize); - PetscScalar vecSum; - VecSum(y1, &vecSum); - vecSum = vecSum / static_cast<PetscScalar>(-1.0 * vecSize); - VecShift(y1, vecSum); - } - KSPSolve(data->kspMinusDeltaK, y1, x1); // -delta*K*x1 = y1 - - VecDestroy(&y1); + KSPSolve(kspS, b, x); // S*x2 = x1 + MatDestroy(&S); MatDestroy(&K); KSPDestroy(&kspS); } + - PetscSolverCahnHilliard2::PetscSolverCahnHilliard2(string name, double *epsPtr, double *deltaPtr) - : PetscSolverGlobalBlockMatrix(name), + PetscSolverCahnHilliard2::PetscSolverCahnHilliard2(string name) + : PetscSolverGlobalMatrix(name), + useOldInitialGuess(false), + laplaceSolutionMode(0), massMatrixSolver(NULL), - laplaceMatrixSolver(NULL), + laplaceMatrixSolver(NULL), deltaKMatrixSolver(NULL), - eps(epsPtr), - delta(deltaPtr) { } + phase(NULL) + { + Parameters::get(initFileStr + "->cahnhilliard->use old initial guess", + useOldInitialGuess); + } + + + void PetscSolverCahnHilliard2::solvePetscMatrix(SystemVector &vec, + AdaptInfo *adaptInfo) + { + FUNCNAME("PetscSolverCahnHilliard2::solvePetscMatrix()"); + + if (useOldInitialGuess) { + VecSet(getVecSolInterior(), 0.0); + + for (int i = 0; i < solution->getSize(); i++) + setDofVector(getVecSolInterior(), solution->getDOFVector(i), i, true); + + vecSolAssembly(); + KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE); + } + + PetscSolverGlobalMatrix::solvePetscMatrix(vec, adaptInfo); + } void PetscSolverCahnHilliard2::initSolver(KSP &ksp) @@ -115,27 +112,63 @@ namespace AMDiS { FUNCNAME("PetscSolverCahnHilliard2::initSolver()"); // Create FGMRES based outer solver - KSPCreate(meshDistributor->getMpiComm(0), &ksp); + + MSG("CREATE POS 1: %p\n", &ksp); + KSPCreate(domainComm, &ksp); KSPSetOperators(ksp, getMatInterior(), getMatInterior(), SAME_NONZERO_PATTERN); KSPMonitorSet(ksp, KSPMonitorTrueResidualNorm, PETSC_NULL, PETSC_NULL); - petsc_helper::setSolver(ksp, "ch_", KSPFGMRES, PCNONE, 1e-6, 1e-8, 1000); + petsc_helper::setSolver(ksp, "ch_", KSPFGMRES, PCNONE, 1e-6, 1e-8, 10000); + + } void PetscSolverCahnHilliard2::initPreconditioner(PC pc) { FUNCNAME("PetscSolverCahnHilliard2::initPreconditioner()"); - MSG("PetscSolverCahnHilliard2::initPreconditioner()\n"); -// KSPSetUp(kspInterior); + MPI::COMM_WORLD.Barrier(); + double wtime = MPI::Wtime(); + + int dim = componentSpaces[0]->getMesh()->getDim(); + + vector<int> chPotentialComponent; + chPotentialComponent.push_back(0); + vector<int> chSchurComponent; + chSchurComponent.push_back(1); - PCSetType(pc, PCSHELL); - PCShellSetApply(pc, pcChShell2); - PCShellSetContext(pc, &matShellContext); + PCSetType(pc, PCFIELDSPLIT); + PCFieldSplitSetType(pc, PC_COMPOSITE_SCHUR); + PCFieldSplitSetSchurFactType(pc, PC_FIELDSPLIT_SCHUR_FACT_FULL); - const FiniteElemSpace *feSpace = componentSpaces[0]; - - // === matrix M === + createFieldSplit(pc, "ch_potential", chPotentialComponent); + createFieldSplit(pc, "ch_schur", chSchurComponent); + PCSetFromOptions(pc); + + KSPSetUp(kspInterior); + + KSP *subKspCH; + int nSubKspCH; + PCFieldSplitGetSubKSP(pc, &nSubKspCH, &subKspCH); + + + TEST_EXIT(nSubKspCH == 2) + ("Wrong numer of KSPs inside of the fieldsplit preconditioner!\n"); + + KSP kspChPotential = subKspCH[0]; + KSP kspChSchur = subKspCH[1]; + PetscFree(subKspCH); + + KSPSetType(kspChSchur, KSPPREONLY); + PC pcSub; + KSPGetPC(kspChSchur, &pcSub); + PCSetType(pcSub, PCSHELL); + PCShellSetApply(pcSub, pcChSchurShell); + PCShellSetContext(pcSub, &matShellContext); + + const FiniteElemSpace *feSpace = componentSpaces[0]; + + // === Mass matrix solver === DOFMatrix massMatrix(feSpace, feSpace); Operator massOp(feSpace, feSpace); Simple_ZOT zot; @@ -144,8 +177,7 @@ namespace AMDiS { massMatrixSolver = createSubSolver(0, "mass_"); massMatrixSolver->fillPetscMatrix(&massMatrix); - - // === matrix (M + eps*sqrt(delta)*K) === + // === Laplace matrix solver === DOFMatrix laplaceMatrix(feSpace, feSpace); Operator laplaceOp(feSpace, feSpace); laplaceOp.addTerm(&zot); // M @@ -166,80 +198,47 @@ namespace AMDiS { // === Setup solver === - matShellContext.kspMass = massMatrixSolver->getSolver(); - matShellContext.kspMinusDeltaK = deltaKMatrixSolver->getSolver(); matShellContext.kspMplusK = laplaceMatrixSolver->getSolver(); - matShellContext.matM = massMatrixSolver->getMatInterior(); matShellContext.matMinusDeltaK = deltaKMatrixSolver->getMatInterior(); matShellContext.eps = eps; matShellContext.delta = delta; + matShellContext.kspMass = massMatrixSolver->getSolver(); + matShellContext.matMass = massMatrixSolver->getMatInterior(); matShellContext.mpiCommGlobal = &(meshDistributor->getMpiComm(0)); petsc_helper::setSolver(matShellContext.kspMass, "mass_", KSPCG, PCJACOBI, 0.0, 1e-14, 2); -// petsc_helper::setSolver(matShellContext.kspMass, "mass_", KSPRICHARDSON, PCLU, 0.0, 1e-14, 1); -// { -// PC pc; -// KSPGetPC(matShellContext.kspMass, &pc); -// PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); -// } - - petsc_helper::setSolver(matShellContext.kspMinusDeltaK, "laplace_", KSPRICHARDSON, PCHYPRE, 0.0, 1e-14, 1); petsc_helper::setSolver(matShellContext.kspMplusK, "MpK_", KSPRICHARDSON, PCHYPRE, 0.0, 1e-14, 1); -// petsc_helper::setSolver(matShellContext.kspLaplace, "laplace_", KSPRICHARDSON, PCLU, 0.0, 1e-14, 1); -// { -// PC pc; -// KSPGetPC(matShellContext.kspLaplace, &pc); -// PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); -// } - PCSetFromOptions(pc); + petsc_helper::setSolver(kspChPotential, "chPotential", KSPRICHARDSON, PCHYPRE, 0.0, 1e-14, 1); + + MSG("Setup of Cahn-Hilliard preconditioner needed %.5f seconds\n", + MPI::Wtime() - wtime); } - - PetscSolver* PetscSolverCahnHilliard2::createSubSolver(int component, - string kspPrefix) - { - FUNCNAME("PetscSolverCahnHilliard2::createSubSolver()"); - - vector<const FiniteElemSpace*> fe; - fe.push_back(componentSpaces[component]); - - PetscSolver* subSolver = new PetscSolverGlobalMatrix(""); - subSolver->setKspPrefix(kspPrefix.c_str()); - subSolver->setMeshDistributor(meshDistributor, 0); - subSolver->init(fe, fe); - ParallelDofMapping &subDofMap = subSolver->getDofMap(); - subDofMap[0] = dofMap[component]; - subDofMap.update(); - - return subSolver; - } - - - - void PetscSolverCahnHilliard2::exitPreconditioner(PC pc) { - FUNCNAME("PetscSolverNavierStokes::exitPreconditioner()"); - + FUNCNAME("PetscSolverCahnHilliard2::exitPreconditioner()"); + massMatrixSolver->destroyMatrixData(); + massMatrixSolver->destroyVectorData(); laplaceMatrixSolver->destroyMatrixData(); + laplaceMatrixSolver->destroyVectorData(); deltaKMatrixSolver->destroyMatrixData(); + deltaKMatrixSolver->destroyVectorData(); + massMatrixSolver->destroyVectorData(); laplaceMatrixSolver->destroyVectorData(); deltaKMatrixSolver->destroyVectorData(); - delete massMatrixSolver; massMatrixSolver = NULL; delete laplaceMatrixSolver; laplaceMatrixSolver = NULL; - + delete deltaKMatrixSolver; deltaKMatrixSolver = NULL; - } - + } } diff --git a/AMDiS/src/parallel/PetscSolverCahnHilliard2.h b/AMDiS/src/parallel/PetscSolverCahnHilliard2.h index 31bf7570..1c4b924c 100644 --- a/AMDiS/src/parallel/PetscSolverCahnHilliard2.h +++ b/AMDiS/src/parallel/PetscSolverCahnHilliard2.h @@ -23,7 +23,7 @@ #ifndef AMDIS_PETSC_SOLVER_CAHN_HILLIARD2_H #define AMDIS_PETSC_SOLVER_CAHN_HILLIARD2_H -#include "parallel/PetscSolverGlobalBlockMatrix.h" +#include "parallel/PetscSolverGlobalMatrix.h" namespace AMDiS { @@ -31,12 +31,12 @@ namespace AMDiS { struct CahnHilliardData2 { KSP kspMass, kspMinusDeltaK, kspMplusK; - Mat matM, matMinusDeltaK; + Mat matMass, matMinusDeltaK; double *eps, *delta; MPI::Intracomm *mpiCommGlobal; }; - class PetscSolverCahnHilliard2 : public PetscSolverGlobalBlockMatrix + class PetscSolverCahnHilliard2 : public PetscSolverGlobalMatrix { public: /// Creator class @@ -51,33 +51,63 @@ namespace AMDiS { return new PetscSolverCahnHilliard2(this->name); } }; - - PetscSolverCahnHilliard2(string name, double *epsPtr = NULL, double *deltaPtr = NULL); + PetscSolverCahnHilliard2(string name); + + void solvePetscMatrix(SystemVector &vec, AdaptInfo *adaptInfo); + void setChData(double *epsPtr, double *deltaPtr) { eps = epsPtr; delta = deltaPtr; } + + + void setPhase(DOFVector<double> *d, double eP3=0) + { + phase = d; + epsPhase3 = eP3; + } protected: void initSolver(KSP &ksp); void initPreconditioner(PC pc); + void exitPreconditioner(PC pc); - - PetscSolver* createSubSolver(int component, string kspPrefix); private: int pressureComponent; + bool pressureNullSpace; + + /// If true, old solution is used for initial guess in solver phase. + bool useOldInitialGuess; + + /// 0: approximate solve 1: direct solver + int velocitySolutionMode; + + /// 0: approximate solve 1: direct solver + int massSolutionMode; + + /// 0: approximate solve 1: direct solver + int laplaceSolutionMode; + PetscSolver *massMatrixSolver, *laplaceMatrixSolver, *deltaKMatrixSolver; CahnHilliardData2 matShellContext; double *eps, *delta; + + + double epsPhase3; + + SystemVector* solution; + + DOFVector<double>* phase; + }; } -#endif // AMDIS_PETSC_SOLVER_CAHN_HILLIARD2_H +#endif -- GitLab