Commit 2f5be996 authored by Sebastian Aland's avatar Sebastian Aland
Browse files

PetscSolverCahnHilliard geht jetzt auch mit diffuse domain

parent 6ee1c6b6
...@@ -16,139 +16,189 @@ ...@@ -16,139 +16,189 @@
#include "parallel/PetscSolverGlobalMatrix.h" #include "parallel/PetscSolverGlobalMatrix.h"
namespace AMDiS { 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; using namespace std;
/// solve Cahn-Hilliard Preconditioner /// solve Cahn-Hilliard Preconditioner
PetscErrorCode pcChShell(PC pc, Vec b, Vec x) // solve Px=b PetscErrorCode pcChShell(PC pc, Vec b, Vec x) // solve Px=b
{FUNCNAME("PCApply()"); {FUNCNAME("PCApply()");
void *ctx; void *ctx;
PCShellGetContext(pc, &ctx); PCShellGetContext(pc, &ctx);
CahnHilliardData* data = static_cast<CahnHilliardData*>(ctx); CahnHilliardData* data = static_cast<CahnHilliardData*>(ctx);
Vec b1, b2, x1, x2; Vec b1, b2, x1, x2;
VecNestGetSubVec(b, 0, &b1); VecNestGetSubVec(b, 0, &b1);
VecNestGetSubVec(b, 1, &b2); VecNestGetSubVec(b, 1, &b2);
VecNestGetSubVec(x, 0, &x1); VecNestGetSubVec(x, 0, &x1);
VecNestGetSubVec(x, 1, &x2); VecNestGetSubVec(x, 1, &x2);
Vec y1, y2; Vec y1, y2;
VecDuplicate(b1, &y1); VecDuplicate(b1, &y1);
VecDuplicate(b2, &y2); VecDuplicate(b2, &y2);
// MatGetDiagonal(data->matM, y2); // MatGetDiagonal(data->matM, y2);
// VecReciprocal(y2); // VecReciprocal(y2);
// VecPointwiseMult(y1, y2, b1); // VecPointwiseMult(y1, y2, b1);
KSPSolve(data->kspMass, b1, y1); // M*y1 = b1 KSPSolve(data->kspMass, b1, y1); // M*y1 = b1
MatMultAdd(data->matMinusDeltaK, y1, b2, x1); // -> x1 := b2-delta*K*y1 MatMultAdd(data->matMinusDeltaK, y1, b2, x1); // -> x1 := b2-delta*K*y1
KSPSolve(data->kspLaplace, x1, y2); // (M+eps*sqrt(delta))*y2 = x1 KSPSolve(data->kspLaplace, x1, y2); // (M+eps*sqrt(delta))*y2 = x1
MatMult(data->matM, y2, x1); // x1 := M*y2 MatMult(data->matM, y2, x1); // x1 := M*y2
KSPSolve(data->kspLaplace, x1, x2); // (M+eps*sqrt(delta))*x2 = x1 KSPSolve(data->kspLaplace, x1, x2); // (M+eps*sqrt(delta))*x2 = x1
double factor = (*data->eps)/sqrt(*data->delta); double factor = (*data->eps)/sqrt(*data->delta);
VecCopy(x2, x1); // x1 := x2 VecCopy(x2, x1); // x1 := x2
VecAXPBYPCZ(x1, 1.0, factor, -factor, y1, y2); // x1 = 1*y1 + factor*y2 - factor*x1 VecAXPBYPCZ(x1, 1.0, factor, -factor, y1, y2); // x1 = 1*y1 + factor*y2 - factor*x1
VecDestroy(&y1); VecDestroy(&y1);
VecDestroy(&y2); VecDestroy(&y2);
} }
PetscSolverCahnHilliard::PetscSolverCahnHilliard(string name, double *epsPtr, double *deltaPtr) PetscSolverCahnHilliard::PetscSolverCahnHilliard(string name, double *epsPtr, double *deltaPtr)
: PetscSolverGlobalBlockMatrix(name), : PetscSolverGlobalBlockMatrix(name),
massMatrixSolver(NULL), massMatrixSolver(NULL),
laplaceMatrixSolver(NULL), laplaceMatrixSolver(NULL),
deltaKMatrixSolver(NULL), deltaKMatrixSolver(NULL),
useOldInitialGuess(false), useOldInitialGuess(false),
eps(epsPtr), eps(epsPtr),
delta(deltaPtr) { delta(deltaPtr) {
Parameters::get(initFileStr + "->use old initial guess", useOldInitialGuess); Parameters::get(initFileStr + "->use old initial guess", useOldInitialGuess);
} }
void PetscSolverCahnHilliard::solvePetscMatrix(SystemVector &vec, void PetscSolverCahnHilliard::solvePetscMatrix(SystemVector &vec,
AdaptInfo *adaptInfo) AdaptInfo *adaptInfo)
{ {
FUNCNAME("PetscSolverCahnHilliard::solvePetscMatrix()"); FUNCNAME("PetscSolverCahnHilliard::solvePetscMatrix()");
/* if (useOldInitialGuess) { /* if (useOldInitialGuess) {
VecSet(getVecSolInterior(), 0.0); if (getVecSolInterior())
{VecSet(getVecSolInterior(), 0.0);
for (int i = 0; i < solution->getSize(); i++) for (int i = 0; i < solution->getSize(); i++)
{ {
Vec tmp; Vec tmp;
VecNestGetSubVec(getVecSolInterior(), i, &tmp); VecNestGetSubVec(getVecSolInterior(), i, &tmp);
setDofVector(tmp, solution->getDOFVector(i)); setDofVector(tmp, solution->getDOFVector(i));
} }
vecSolAssembly(); vecSolAssembly();
KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE); KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE);
} }
*/ KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE); KSPSetInitialGuessNonzero(kspInterior, PETSC_TRUE);
}*/
PetscSolverGlobalBlockMatrix::solvePetscMatrix(vec, adaptInfo); PetscSolverGlobalBlockMatrix::solvePetscMatrix(vec, adaptInfo);
} }
void PetscSolverCahnHilliard::initSolver(KSP &ksp) void PetscSolverCahnHilliard::initSolver(KSP &ksp)
{ {
FUNCNAME("PetscSolverCahnHilliard::initSolver()"); FUNCNAME("PetscSolverCahnHilliard::initSolver()");
// Create FGMRES based outer solver // Create FGMRES based outer solver
KSPCreate(meshDistributor->getMpiComm(0), &ksp); KSPCreate(meshDistributor->getMpiComm(0), &ksp);
KSPSetOperators(ksp, getMatInterior(), getMatInterior(), SAME_NONZERO_PATTERN); KSPSetOperators(ksp, getMatInterior(), getMatInterior(), SAME_NONZERO_PATTERN);
KSPMonitorSet(ksp, KSPMonitorTrueResidualNorm, PETSC_NULL, PETSC_NULL); 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, 1000);
KSPSetFromOptions(ksp); KSPSetFromOptions(ksp);
} }
void PetscSolverCahnHilliard::initPreconditioner(PC pc) void PetscSolverCahnHilliard::initPreconditioner(PC pc)
{ {
FUNCNAME("PetscSolverCahnHilliard::initPreconditioner()"); FUNCNAME("PetscSolverCahnHilliard::initPreconditioner()");
MSG("PetscSolverCahnHilliard::initPreconditioner()\n"); MSG("PetscSolverCahnHilliard::initPreconditioner()\n");
// KSPSetUp(kspInterior); // KSPSetUp(kspInterior);
PCSetType(pc, PCSHELL); PCSetType(pc, PCSHELL);
PCShellSetApply(pc, pcChShell); PCShellSetApply(pc, pcChShell);
PCShellSetContext(pc, &matShellContext); PCShellSetContext(pc, &matShellContext);
const FiniteElemSpace *feSpace = componentSpaces[0]; const FiniteElemSpace *feSpace = componentSpaces[0];
// === matrix M === // === 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); DOFMatrix laplaceMatrix(feSpace, feSpace);
Operator laplaceOp(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); DOFMatrix deltaKMatrix(feSpace, feSpace);
Operator laplaceOp2(feSpace, feSpace); Operator laplaceOp2(feSpace, feSpace);
Simple_SOT sot(-(*delta));
laplaceOp2.addTerm(&sot); // -delta*K if (phase)
deltaKMatrix.assembleOperator(laplaceOp2); {
deltaKMatrixSolver = createSubSolver(0, "laplace2_"); VecAtQP_ZOT zot(phase, NULL);
deltaKMatrixSolver->fillPetscMatrix(&deltaKMatrix); 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 === // === Setup solver ===
matShellContext.kspMass = massMatrixSolver->getSolver(); matShellContext.kspMass = massMatrixSolver->getSolver();
...@@ -159,43 +209,43 @@ namespace AMDiS { ...@@ -159,43 +209,43 @@ namespace AMDiS {
matShellContext.delta = delta; matShellContext.delta = delta;
matShellContext.mpiCommGlobal= &(meshDistributor->getMpiComm(0)); matShellContext.mpiCommGlobal= &(meshDistributor->getMpiComm(0));
petsc_helper::setSolver(matShellContext.kspMass, "", KSPCG, PCJACOBI, 0.0, 1e-14, 2); 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); // petsc_helper::setSolver(matShellContext.kspMass, "mass_", KSPRICHARDSON, PCLU, 0.0, 1e-14, 1);
// { // {
// PC pc; // PC pc;
// KSPGetPC(matShellContext.kspMass, &pc); // KSPGetPC(matShellContext.kspMass, &pc);
// PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); // PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS);
// } // }
petsc_helper::setSolver(matShellContext.kspLaplace, "laplace_", KSPRICHARDSON, PCHYPRE, 0.0, 1e-14, 1); 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); // petsc_helper::setSolver(matShellContext.kspLaplace, "laplace_", KSPRICHARDSON, PCLU, 0.0, 1e-14, 1);
// { // {
// PC pc; // PC pc;
// KSPGetPC(matShellContext.kspLaplace, &pc); // KSPGetPC(matShellContext.kspLaplace, &pc);
// PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS); // PCFactorSetMatSolverPackage(pc, MATSOLVERMUMPS);
// } // }
PCSetFromOptions(pc); PCSetFromOptions(pc);
} }
PetscSolver* PetscSolverCahnHilliard::createSubSolver(int component, PetscSolver* PetscSolverCahnHilliard::createSubSolver(int component,
string kspPrefix) string kspPrefix)
{ {
FUNCNAME("PetscSolverCahnHilliard::createSubSolver()"); FUNCNAME("PetscSolverCahnHilliard::createSubSolver()");
vector<const FiniteElemSpace*> fe; vector<const FiniteElemSpace*> fe;
fe.push_back(componentSpaces[component]); fe.push_back(componentSpaces[component]);
PetscSolver* subSolver = new PetscSolverGlobalMatrix(""); PetscSolver* subSolver = new PetscSolverGlobalMatrix("");
subSolver->setKspPrefix(kspPrefix.c_str()); subSolver->setKspPrefix(kspPrefix.c_str());
subSolver->setMeshDistributor(meshDistributor, 0); subSolver->setMeshDistributor(meshDistributor, 0);
subSolver->init(fe, fe); subSolver->init(fe, fe);
ParallelDofMapping &subDofMap = subSolver->getDofMap(); ParallelDofMapping &subDofMap = subSolver->getDofMap();
subDofMap[0] = dofMap[component]; subDofMap[0] = dofMap[component];
subDofMap.update(); subDofMap.update();
return subSolver; return subSolver;
} }
...@@ -206,21 +256,21 @@ namespace AMDiS { ...@@ -206,21 +256,21 @@ namespace AMDiS {
massMatrixSolver->destroyMatrixData(); massMatrixSolver->destroyMatrixData();
laplaceMatrixSolver->destroyMatrixData(); laplaceMatrixSolver->destroyMatrixData();
deltaKMatrixSolver->destroyMatrixData(); deltaKMatrixSolver->destroyMatrixData();
massMatrixSolver->destroyVectorData(); massMatrixSolver->destroyVectorData();
laplaceMatrixSolver->destroyVectorData(); laplaceMatrixSolver->destroyVectorData();
deltaKMatrixSolver->destroyVectorData(); deltaKMatrixSolver->destroyVectorData();
delete massMatrixSolver; delete massMatrixSolver;
massMatrixSolver = NULL; massMatrixSolver = NULL;
delete laplaceMatrixSolver; delete laplaceMatrixSolver;
laplaceMatrixSolver = NULL; laplaceMatrixSolver = NULL;
delete deltaKMatrixSolver; delete deltaKMatrixSolver;
deltaKMatrixSolver = NULL; deltaKMatrixSolver = NULL;
} }
} }
...@@ -58,11 +58,12 @@ namespace AMDiS { ...@@ -58,11 +58,12 @@ namespace AMDiS {
PetscSolverCahnHilliard(string name, double *epsPtr = NULL, double *deltaPtr = NULL); 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; eps = epsPtr;
delta = deltaPtr; delta = deltaPtr;
solution = vec; solution = vec;
phase = p;
} }
protected: protected:
...@@ -83,6 +84,8 @@ namespace AMDiS { ...@@ -83,6 +84,8 @@ namespace AMDiS {
bool useOldInitialGuess; bool useOldInitialGuess;
SystemVector* solution; SystemVector* solution;
DOFVector<double> *phase;
double *eps, *delta; double *eps, *delta;
}; };
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment