From 2f5be996fced70b0fa8d2e41f67e45c0204ce617 Mon Sep 17 00:00:00 2001 From: Sebastian Aland <sebastian.aland@yahoo.com> Date: Tue, 5 Feb 2013 12:32:40 +0000 Subject: [PATCH] PetscSolverCahnHilliard geht jetzt auch mit diffuse domain --- AMDiS/src/parallel/PetscSolverCahnHilliard.cc | 272 +++++++++++------- AMDiS/src/parallel/PetscSolverCahnHilliard.h | 5 +- 2 files changed, 165 insertions(+), 112 deletions(-) diff --git a/AMDiS/src/parallel/PetscSolverCahnHilliard.cc b/AMDiS/src/parallel/PetscSolverCahnHilliard.cc index 1ee3f22c..3b3e0c80 100644 --- a/AMDiS/src/parallel/PetscSolverCahnHilliard.cc +++ b/AMDiS/src/parallel/PetscSolverCahnHilliard.cc @@ -16,139 +16,189 @@ #include "parallel/PetscSolverGlobalMatrix.h" namespace AMDiS { - + + class Multiplier: public AbstractFunction<double, double> + { + public: + Multiplier(double d_) : AbstractFunction<double, double>(2),d(d_) {}; + + double operator()(const double& x) const { + return d*x; + } + protected: + double d; + }; + + + using namespace std; - + /// solve Cahn-Hilliard Preconditioner PetscErrorCode pcChShell(PC pc, Vec b, Vec x) // solve Px=b {FUNCNAME("PCApply()"); - void *ctx; - PCShellGetContext(pc, &ctx); - CahnHilliardData* data = static_cast<CahnHilliardData*>(ctx); - - Vec b1, b2, x1, x2; - VecNestGetSubVec(b, 0, &b1); - VecNestGetSubVec(b, 1, &b2); - - VecNestGetSubVec(x, 0, &x1); - VecNestGetSubVec(x, 1, &x2); - - Vec y1, y2; - VecDuplicate(b1, &y1); - VecDuplicate(b2, &y2); - -// MatGetDiagonal(data->matM, y2); -// VecReciprocal(y2); -// VecPointwiseMult(y1, y2, b1); - KSPSolve(data->kspMass, b1, y1); // M*y1 = b1 - MatMultAdd(data->matMinusDeltaK, y1, b2, x1); // -> x1 := b2-delta*K*y1 - - KSPSolve(data->kspLaplace, x1, y2); // (M+eps*sqrt(delta))*y2 = x1 - MatMult(data->matM, y2, x1); // x1 := M*y2 - - KSPSolve(data->kspLaplace, x1, x2); // (M+eps*sqrt(delta))*x2 = x1 - double factor = (*data->eps)/sqrt(*data->delta); - VecCopy(x2, x1); // x1 := x2 - VecAXPBYPCZ(x1, 1.0, factor, -factor, y1, y2); // x1 = 1*y1 + factor*y2 - factor*x1 - - VecDestroy(&y1); - VecDestroy(&y2); - + void *ctx; + PCShellGetContext(pc, &ctx); + CahnHilliardData* data = static_cast<CahnHilliardData*>(ctx); + + Vec b1, b2, x1, x2; + VecNestGetSubVec(b, 0, &b1); + VecNestGetSubVec(b, 1, &b2); + + VecNestGetSubVec(x, 0, &x1); + VecNestGetSubVec(x, 1, &x2); + + Vec y1, y2; + VecDuplicate(b1, &y1); + VecDuplicate(b2, &y2); + + // MatGetDiagonal(data->matM, y2); + // VecReciprocal(y2); + // VecPointwiseMult(y1, y2, b1); + KSPSolve(data->kspMass, b1, y1); // M*y1 = b1 + MatMultAdd(data->matMinusDeltaK, y1, b2, x1); // -> x1 := b2-delta*K*y1 + + KSPSolve(data->kspLaplace, x1, y2); // (M+eps*sqrt(delta))*y2 = x1 + MatMult(data->matM, y2, x1); // x1 := M*y2 + + KSPSolve(data->kspLaplace, x1, x2); // (M+eps*sqrt(delta))*x2 = x1 + double factor = (*data->eps)/sqrt(*data->delta); + VecCopy(x2, x1); // x1 := x2 + VecAXPBYPCZ(x1, 1.0, factor, -factor, y1, y2); // x1 = 1*y1 + factor*y2 - factor*x1 + + VecDestroy(&y1); + VecDestroy(&y2); + } - + PetscSolverCahnHilliard::PetscSolverCahnHilliard(string name, double *epsPtr, double *deltaPtr) - : PetscSolverGlobalBlockMatrix(name), - massMatrixSolver(NULL), - laplaceMatrixSolver(NULL), - deltaKMatrixSolver(NULL), - useOldInitialGuess(false), - eps(epsPtr), - delta(deltaPtr) { - Parameters::get(initFileStr + "->use old initial guess", useOldInitialGuess); - } - - + : PetscSolverGlobalBlockMatrix(name), + massMatrixSolver(NULL), + laplaceMatrixSolver(NULL), + deltaKMatrixSolver(NULL), + useOldInitialGuess(false), + eps(epsPtr), + delta(deltaPtr) { + Parameters::get(initFileStr + "->use old initial guess", useOldInitialGuess); + } + + void PetscSolverCahnHilliard::solvePetscMatrix(SystemVector &vec, AdaptInfo *adaptInfo) { FUNCNAME("PetscSolverCahnHilliard::solvePetscMatrix()"); - -/* if (useOldInitialGuess) { - VecSet(getVecSolInterior(), 0.0); + + /* if (useOldInitialGuess) { + if (getVecSolInterior()) + {VecSet(getVecSolInterior(), 0.0); for (int i = 0; i < solution->getSize(); i++) { Vec tmp; - VecNestGetSubVec(getVecSolInterior(), i, &tmp); + VecNestGetSubVec(getVecSolInterior(), i, &tmp); setDofVector(tmp, solution->getDOFVector(i)); } vecSolAssembly(); KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE); } -*/ KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE); + KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE); + }*/ PetscSolverGlobalBlockMatrix::solvePetscMatrix(vec, adaptInfo); } - + void PetscSolverCahnHilliard::initSolver(KSP &ksp) { FUNCNAME("PetscSolverCahnHilliard::initSolver()"); - + // Create FGMRES based outer solver KSPCreate(meshDistributor->getMpiComm(0), &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); - KSPSetFromOptions(ksp); - + KSPSetFromOptions(ksp); + } - - + + void PetscSolverCahnHilliard::initPreconditioner(PC pc) { FUNCNAME("PetscSolverCahnHilliard::initPreconditioner()"); MSG("PetscSolverCahnHilliard::initPreconditioner()\n"); - -// KSPSetUp(kspInterior); - + + // KSPSetUp(kspInterior); + PCSetType(pc, PCSHELL); PCShellSetApply(pc, pcChShell); PCShellSetContext(pc, &matShellContext); - + const FiniteElemSpace *feSpace = componentSpaces[0]; // === matrix M === - DOFMatrix massMatrix(feSpace, feSpace); - Operator massOp(feSpace, feSpace); - Simple_ZOT zot; - massOp.addTerm(&zot); - massMatrix.assembleOperator(massOp); - massMatrixSolver = createSubSolver(0, "mass_"); - massMatrixSolver->fillPetscMatrix(&massMatrix); - - - // === matrix (M + eps*sqrt(delta)*K) === DOFMatrix laplaceMatrix(feSpace, feSpace); Operator laplaceOp(feSpace, feSpace); - laplaceOp.addTerm(&zot); // M - Simple_SOT sot2((*eps)*sqrt(*delta)); - laplaceOp.addTerm(&sot2); // eps*sqrt(delta)*K - laplaceMatrix.assembleOperator(laplaceOp); - laplaceMatrixSolver = createSubSolver(0, "laplace_"); - laplaceMatrixSolver->fillPetscMatrix(&laplaceMatrix); - - // === matrix (-delta*K) === + DOFMatrix massMatrix(feSpace, feSpace); + Operator massOp(feSpace, feSpace); + DOFMatrix deltaKMatrix(feSpace, feSpace); Operator laplaceOp2(feSpace, feSpace); - Simple_SOT sot(-(*delta)); - laplaceOp2.addTerm(&sot); // -delta*K - deltaKMatrix.assembleOperator(laplaceOp2); - deltaKMatrixSolver = createSubSolver(0, "laplace2_"); - deltaKMatrixSolver->fillPetscMatrix(&deltaKMatrix); - + + if (phase) + { + VecAtQP_ZOT zot(phase, NULL); + massOp.addTerm(&zot); + laplaceOp.addTerm(&zot); // M + VecAtQP_SOT sot2(phase, new Multiplier((*eps)*sqrt(*delta))); + laplaceOp.addTerm(&sot2); // eps*sqrt(delta)*K + VecAtQP_SOT sot(phase, new Multiplier(-(*delta))); + laplaceOp2.addTerm(&sot); // -delta*K + massMatrix.assembleOperator(massOp); + massMatrixSolver = createSubSolver(0, "mass_"); + massMatrixSolver->fillPetscMatrix(&massMatrix); + + // === matrix (M + eps*sqrt(delta)*K) === + laplaceMatrix.assembleOperator(laplaceOp); + laplaceMatrixSolver = createSubSolver(0, "laplace_"); + laplaceMatrixSolver->fillPetscMatrix(&laplaceMatrix); + + + // === matrix (-delta*K) === + deltaKMatrix.assembleOperator(laplaceOp2); + deltaKMatrixSolver = createSubSolver(0, "laplace2_"); + deltaKMatrixSolver->fillPetscMatrix(&deltaKMatrix); + + + } + else + { + Simple_ZOT zot; + massOp.addTerm(&zot); + laplaceOp.addTerm(&zot); // M + Simple_SOT sot2((*eps)*sqrt(*delta)); + laplaceOp.addTerm(&sot2); // eps*sqrt(delta)*K + Simple_SOT sot(-(*delta)); + laplaceOp2.addTerm(&sot); // -delta*K + + massMatrix.assembleOperator(massOp); + massMatrixSolver = createSubSolver(0, "mass_"); + massMatrixSolver->fillPetscMatrix(&massMatrix); + + // === matrix (M + eps*sqrt(delta)*K) === + laplaceMatrix.assembleOperator(laplaceOp); + laplaceMatrixSolver = createSubSolver(0, "laplace_"); + laplaceMatrixSolver->fillPetscMatrix(&laplaceMatrix); + + + // === matrix (-delta*K) === + deltaKMatrix.assembleOperator(laplaceOp2); + deltaKMatrixSolver = createSubSolver(0, "laplace2_"); + deltaKMatrixSolver->fillPetscMatrix(&deltaKMatrix); + } + + + // === Setup solver === matShellContext.kspMass = massMatrixSolver->getSolver(); @@ -159,43 +209,43 @@ namespace AMDiS { matShellContext.delta = delta; matShellContext.mpiCommGlobal= &(meshDistributor->getMpiComm(0)); - + petsc_helper::setSolver(matShellContext.kspMass, "", 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.kspMass, "mass_", KSPRICHARDSON, PCLU, 0.0, 1e-14, 1); + // { + // PC pc; + // KSPGetPC(matShellContext.kspMass, &pc); + // PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); + // } + petsc_helper::setSolver(matShellContext.kspLaplace, "laplace_", 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(matShellContext.kspLaplace, "laplace_", KSPRICHARDSON, PCLU, 0.0, 1e-14, 1); + // { + // PC pc; + // KSPGetPC(matShellContext.kspLaplace, &pc); + // PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); + // } + PCSetFromOptions(pc); } - + PetscSolver* PetscSolverCahnHilliard::createSubSolver(int component, string kspPrefix) { FUNCNAME("PetscSolverCahnHilliard::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; } @@ -206,21 +256,21 @@ namespace AMDiS { massMatrixSolver->destroyMatrixData(); laplaceMatrixSolver->destroyMatrixData(); deltaKMatrixSolver->destroyMatrixData(); - + massMatrixSolver->destroyVectorData(); laplaceMatrixSolver->destroyVectorData(); deltaKMatrixSolver->destroyVectorData(); - + delete massMatrixSolver; massMatrixSolver = NULL; - + delete laplaceMatrixSolver; laplaceMatrixSolver = NULL; - + delete deltaKMatrixSolver; deltaKMatrixSolver = NULL; } - - + + } diff --git a/AMDiS/src/parallel/PetscSolverCahnHilliard.h b/AMDiS/src/parallel/PetscSolverCahnHilliard.h index 9ff119c7..2ebcf8be 100644 --- a/AMDiS/src/parallel/PetscSolverCahnHilliard.h +++ b/AMDiS/src/parallel/PetscSolverCahnHilliard.h @@ -58,11 +58,12 @@ namespace AMDiS { PetscSolverCahnHilliard(string name, double *epsPtr = NULL, double *deltaPtr = NULL); - void setChData(double *epsPtr, double *deltaPtr, SystemVector* vec) + void setChData(double *epsPtr, double *deltaPtr, SystemVector* vec, DOFVector<double> *p=NULL) { eps = epsPtr; delta = deltaPtr; solution = vec; + phase = p; } protected: @@ -83,6 +84,8 @@ namespace AMDiS { bool useOldInitialGuess; SystemVector* solution; + + DOFVector<double> *phase; double *eps, *delta; }; -- GitLab