From 4baf4abeb8143d82f47cdbf65b16b4e75e595af7 Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Wed, 15 Aug 2012 10:18:44 +0000 Subject: [PATCH] base problems --- .../base_problems/CahnHilliardNavierStokes.cc | 74 ++- .../base_problems/CahnHilliardNavierStokes.h | 5 +- .../CahnHilliardNavierStokes_RB.cc | 369 ++++++++++++++ .../CahnHilliardNavierStokes_RB.h | 272 ++++++++++ .../CahnHilliardNavierStokes_TwoPhase_RB.cc | 477 ++++++++++++++++++ .../CahnHilliardNavierStokes_TwoPhase_RB.h | 326 ++++++++++++ extensions/base_problems/DiffuseDomainFsi.cc | 184 ++++--- extensions/base_problems/DiffuseDomainFsi.h | 9 +- extensions/base_problems/LinearElasticity.cc | 44 +- extensions/base_problems/LinearElasticity.h | 2 + .../base_problems/NavierStokes_TaylorHood.cc | 10 +- 11 files changed, 1666 insertions(+), 106 deletions(-) create mode 100644 extensions/base_problems/CahnHilliardNavierStokes_RB.cc create mode 100644 extensions/base_problems/CahnHilliardNavierStokes_RB.h create mode 100644 extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc create mode 100644 extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h diff --git a/extensions/base_problems/CahnHilliardNavierStokes.cc b/extensions/base_problems/CahnHilliardNavierStokes.cc index 6ef2b8ce..c194ad5a 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes.cc +++ b/extensions/base_problems/CahnHilliardNavierStokes.cc @@ -10,7 +10,7 @@ CahnHilliardNavierStokes::CahnHilliardNavierStokes(const std::string &name_) : super(name_), useMobility(false), useConservationForm(false), - doubleWell(0), + doubleWell(1), gamma(1.0), eps(0.1), minusEps(-0.1), @@ -19,7 +19,7 @@ CahnHilliardNavierStokes::CahnHilliardNavierStokes(const std::string &name_) : epsSqr(0.01), minusEpsSqr(-0.01), laplaceType(0), - nonLinTerm(2), + nonLinTerm(3), oldTimestep(0.0), viscosity(1.0), density(1.0), @@ -31,8 +31,8 @@ CahnHilliardNavierStokes::CahnHilliardNavierStokes(const std::string &name_) : fileWriter(NULL) { // parameters for CH - Parameters::get(name + "->use mobility", useMobility); // mobility - Parameters::get(name + "->gamma", gamma); // mobility + Parameters::get(name + "->use mobility", useMobility); // dt(c) = div(M(c)*grad(c)) + ... + Parameters::get(name + "->gamma", gamma); // M(c) = gamma * Double-Well Parameters::get(name + "->epsilon", eps); // interface width // type of double well: 0= [0,1], 1= [-1,1] @@ -41,15 +41,23 @@ CahnHilliardNavierStokes::CahnHilliardNavierStokes(const std::string &name_) : // parameters for navier-stokes Initfile::get(name + "->viscosity", viscosity); Initfile::get(name + "->density", density); - // type of laplace operator: 0... div(nu*grad(u)), 1... div(0.5*nu*(grad(u)+grad(u)^T)) + + // type of laplace operator: 0... div(nu*grad(u)), + // 1... div(0.5*nu*(grad(u)+grad(u)^T)) Initfile::get(name + "->laplace operator", laplaceType); - // type of non-linear term: 0... u^old*grad(u_i^old), 1... u'*grad(u_i^old), 2... u^old*grad(u'_i) + + // type of non-linear term: 0... u^old*grad(u_i^old), + // 1... u*grad(u_i^old), + // 2... u^old*grad(u_i) + // 3... u*grad(u_i^old) + u^old*grad(u_i) - u^old*grad(u_i^old) Initfile::get(name + "->non-linear term", nonLinTerm); // Parameters for CH-Coupling + // 0... u*grad(c), 1... -div(u*c) Initfile::get(name + "->use conservation form", useConservationForm); // Parameters for NS-Coupling + // cahn-hiliard-force: sigma*mu*grad(c) Initfile::get(name + "->sigma", sigma); // surface tension surfaceTension = sigma*3.0/(2.0*sqrt(2.0)) / eps; @@ -97,6 +105,22 @@ void CahnHilliardNavierStokes::initData() } +void CahnHilliardNavierStokes::transferInitialSolution(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes::transferInitialSolution()"); + + calcVelocity(); + + for (int i = 0; i < 2+dow; i++) + prob->setExactSolution(prob->getSolution()->getDOFVector(i), i); + + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); + + // initial parameters for detecting mesh changes + oldMeshChangeIdx= getMesh()->getChangeIndex(); +} + + void CahnHilliardNavierStokes::fillOperators() { FUNCNAME("CahnHilliardNavierStokes::fillOperators()"); MSG("CahnHilliardNavierStokes::fillOperators()\n"); @@ -143,9 +167,9 @@ void CahnHilliardNavierStokes::fillOperators() uGradC->addTerm(new WorldVec_FOT(vel, -1.0), GRD_PSI); else uGradC->addTerm(new WorldVec_FOT(vel), GRD_PHI); + prob->addMatrixOperator(*uGradC, 0, 0); uGradC->setUhOld(prob->getSolution()->getDOFVector(0)); prob->addVectorOperator(*uGradC, 0); - prob->addMatrixOperator(*uGradC, 0, 0); /// < u * grad(c_old) , psi > for (size_t i = 0; i < dow; i++) { @@ -208,27 +232,28 @@ void CahnHilliardNavierStokes::fillOperators() prob->addMatrixOperator(*opTime, 2+i, 2+i, getInvTau(), getInvTau()); /// < (1/tau)*u_i^old , psi > Operator *opTimeOld = new Operator(getFeSpace(2+i), getFeSpace(2+i)); - opTime->addTerm(new Phase_ZOT(prob->getSolution()->getDOFVector(2+i), density)); + opTimeOld->addTerm(new Phase_ZOT(prob->getSolution()->getDOFVector(2+i), density)); prob->addVectorOperator(*opTimeOld, 2+i, getInvTau(), getInvTau()); /// < u^old*grad(u_i^old) , psi > - Operator *opUGradU0 = new Operator(getFeSpace(2+i), getFeSpace(2+i)); - opUGradU0->addTerm(new WorldVector_FOT(velocity, -density), GRD_PHI); - opUGradU0->setUhOld(prob->getSolution()->getDOFVector(2+i)); - if (nonLinTerm == 0) { + if (nonLinTerm == 0 || nonLinTerm == 3) { + Operator *opUGradU0 = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opUGradU0->addTerm(new WorldVec_FOT(vel, (nonLinTerm == 0 ? -1.0 : 1.0)*density), + GRD_PHI); + opUGradU0->setUhOld(prob->getSolution()->getDOFVector(2+i)); prob->addVectorOperator(*opUGradU0, 2+i); } - - if (nonLinTerm == 1) { - /// < u'*grad(u_i^old) , psi > + if (nonLinTerm == 1 || nonLinTerm == 3) { + /// < u*grad(u_i^old) , psi > for (size_t j = 0; j < dow; ++j) { Operator *opUGradU1 = new Operator(getFeSpace(2+i),getFeSpace(2+i)); opUGradU1->addTerm(new PartialDerivative_ZOT( prob->getSolution()->getDOFVector(2+i), j, density)); prob->addMatrixOperator(*opUGradU1, 2+i, 2+j); } - } else if (nonLinTerm == 2) { - /// < u^old*grad(u'_i) , psi > + } + if (nonLinTerm == 2 || nonLinTerm == 3) { + /// < u^old*grad(u_i) , psi > for(size_t j = 0; j < dow; ++j) { Operator *opUGradU2 = new Operator(getFeSpace(2+i),getFeSpace(2+i)); opUGradU2->addTerm(new VecAndPartialDerivative_FOT( @@ -258,16 +283,21 @@ void CahnHilliardNavierStokes::fillOperators() prob->addVectorOperator(*opForce, 2+i); } - /// forces by Cahn-Hilliard terms + // forces by Cahn-Hilliard terms + // ----------------------------- + /// < mu_old * grad(c) , psi > Operator *opMuGradC = new Operator(getFeSpace(2+i),getFeSpace(0)); opMuGradC->addTerm(new VecAndPartialDerivative_FOT( prob->getSolution()->getDOFVector(1), i), GRD_PHI); prob->addMatrixOperator(*opMuGradC, 2+i, 0, &surfaceTension, &surfaceTension); + /// < mu * grad(c_old) , psi > Operator *opMuGradC2 = new Operator(getFeSpace(2+i),getFeSpace(1)); opMuGradC2->addTerm(new PartialDerivative_ZOT( prob->getSolution()->getDOFVector(0), i)); prob->addMatrixOperator(*opMuGradC2, 2+i, 1, &surfaceTension, &surfaceTension); + + /// < mu_old * grad(c_old) , psi > opMuGradC2->setUhOld(prob->getSolution()->getDOFVector(1)); prob->addVectorOperator(*opMuGradC2, 2+i, &surfaceTension, &surfaceTension); @@ -300,3 +330,11 @@ void CahnHilliardNavierStokes::addLaplaceTerm(int i) opLaplaceUi->addTerm(new Simple_SOT(viscosity)); prob->addMatrixOperator(*opLaplaceUi, 2+i, 2+i); } + +void CahnHilliardNavierStokes::closeTimestep(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes::closeTimestep()"); + + calcVelocity(); + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); +} diff --git a/extensions/base_problems/CahnHilliardNavierStokes.h b/extensions/base_problems/CahnHilliardNavierStokes.h index 56686fdd..54d746e1 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes.h +++ b/extensions/base_problems/CahnHilliardNavierStokes.h @@ -23,6 +23,9 @@ public: // public methods virtual void initData(); + virtual void transferInitialSolution(AdaptInfo *adaptInfo); + virtual void closeTimestep(AdaptInfo *adaptInfo); + double getEpsilon() { return eps; } int getDoubleWellType() { return doubleWell; } @@ -31,8 +34,6 @@ public: // public methods return velocity; } -protected: // protected methods - virtual void fillOperators(); virtual void fillBoundaryConditions() {} virtual void addLaplaceTerm(int i); diff --git a/extensions/base_problems/CahnHilliardNavierStokes_RB.cc b/extensions/base_problems/CahnHilliardNavierStokes_RB.cc new file mode 100644 index 00000000..70a1b7be --- /dev/null +++ b/extensions/base_problems/CahnHilliardNavierStokes_RB.cc @@ -0,0 +1,369 @@ +#include "CahnHilliardNavierStokes_RB.h" +#include "Views.h" +#include "SignedDistFunctors.h" +#include "PhaseFieldConvert.h" +#include "POperators.h" + +using namespace AMDiS; + +CahnHilliardNavierStokes_RB::CahnHilliardNavierStokes_RB(const std::string &name_) : + super(name_), + useMobility(false), + useConservationForm(false), + doubleWell(1), + gamma(1.0), + eps(0.1), + minusEps(-0.1), + epsInv(10.0), + minusEpsInv(-10.0), + epsSqr(0.01), + minusEpsSqr(-0.01), + laplaceType(0), + nonLinTerm(3), + oldTimestep(0.0), + viscosity(1.0), + density(1.0), + c(0.0), + sigma(1.0), + surfaceTension(1.0), + reinit(NULL), + velocity(NULL), + fileWriter(NULL) +{ + // parameters for CH + Parameters::get(name + "->use mobility", useMobility); // dt(c) = div(M(c)*grad(c)) + ... + Parameters::get(name + "->gamma", gamma); // M(c) = gamma * Double-Well + Parameters::get(name + "->epsilon", eps); // interface width + + // type of double well: 0= [0,1], 1= [-1,1] + Parameters::get(name + "->double-well type", doubleWell); + + // parameters for navier-stokes + Initfile::get(name + "->viscosity", viscosity); + Initfile::get(name + "->density", density); + + // type of laplace operator: 0... div(nu*grad(u)), + // 1... div(0.5*nu*(grad(u)+grad(u)^T)) + Initfile::get(name + "->laplace operator", laplaceType); + + // type of non-linear term: 0... u^old*grad(u_i^old), + // 1... u*grad(u_i^old), + // 2... u^old*grad(u_i) + // 3... u*grad(u_i^old) + u^old*grad(u_i) - u^old*grad(u_i^old) + Initfile::get(name + "->non-linear term", nonLinTerm); + + // Parameters for CH-Coupling + // 0... u*grad(c), 1... -div(u*c) + Initfile::get(name + "->use conservation form", useConservationForm); + + // Parameters for NS-Coupling + // cahn-hiliard-force: sigma*mu*grad(c) + Initfile::get(name + "->sigma", sigma); // surface tension + surfaceTension = sigma*3.0/(2.0*sqrt(2.0)) / eps; + + + force.set(0.0); + Initfile::get(name + "->force", force); + + // transformation of the parameters + minusEps = -eps; + epsInv = 1.0/eps; + minusEpsInv = -epsInv; + epsSqr = sqr(eps); + minusEpsSqr = -epsSqr; +} + + +CahnHilliardNavierStokes_RB::~CahnHilliardNavierStokes_RB() +{ FUNCNAME("CahnHilliardNavierStokes_RB::~CahnHilliardNavierStokes_RB()"); + + if (reinit != NULL) { + delete reinit; + reinit = NULL; + } + if (velocity != NULL) { + delete velocity; + velocity = NULL; + } + delete fileWriter; + fileWriter = NULL; +} + + +void CahnHilliardNavierStokes_RB::initData() +{ FUNCNAME("CahnHilliardNavierStokes_RB::initData()"); + + dim = getMesh()->getDim(); + // create instance redistancing class + reinit = new HL_SignedDistTraverse("reinit", dim); + + if (velocity == NULL) + velocity = new DOFVector<WorldVector<double> >(getFeSpace(2), "velocity"); + fileWriter = new FileVectorWriter(name + "->velocity->output", getFeSpace(2)->getMesh(), velocity); + + super::initData(); +} + + +void CahnHilliardNavierStokes_RB::transferInitialSolution(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes_RB::transferInitialSolution()"); + + calcVelocity(); + + for (int i = 0; i < 2+dow; i++) + prob->setExactSolution(prob->getSolution()->getDOFVector(i), i); + + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); + + // initial parameters for detecting mesh changes + oldMeshChangeIdx= getMesh()->getChangeIndex(); +} + + +void CahnHilliardNavierStokes_RB::fillOperators() +{ FUNCNAME("CahnHilliardNavierStokes_RB::fillOperators()"); + MSG("CahnHilliardNavierStokes_RB::fillOperators()\n"); + + // variable order: + // (c, mu, u0, u1 [, u2], p) + + WorldVector<DOFVector<double>*> stage_velocity; + WorldVector<DOFVector<double>*> un_velocity; + for (size_t i = 0; i < dow; ++i) { + stage_velocity[i] = prob->getStageSolution(2+i); + un_velocity[i] = prob->getUnVec(2+i); + } + + // dt(c) = laplace(mu) - u*grad(c) + // ----------------------------------- + /// < dt(c) , psi > + prob->addTimeOperator(0, 0); + + // div(M(c)grad(mu)), with M(c)=gamma/4*(c^2-1)^2 + Operator *opChLM = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + if (useMobility) { + if (doubleWell == 0) { + // jacobian operators + opChLM->addTerm(new VecAtQP_SOT( + prob->getUnVec(0), + new MobilityCH0(gamma))); + opChLM->addTerm(new VecGrad_FOT( + prob->getUnVec(0), + prob->getUnVec(1), + new MobilityCH0Diff(gamma)), GRD_PSI); + prob->addMatrixOperator(*opChLM, 0, 1); + // rhs operators + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLM2->addTerm(new VecAtQP_SOT( + prob->getStageSolution(0), + new MobilityCH0(gamma))); + opChLM2->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + } else { + // jacobian operators + opChLM->addTerm(new VecAtQP_SOT( + prob->getUnVec(0), + new MobilityCH1(gamma))); + opChLM->addTerm(new VecGrad_FOT( + prob->getUnVec(0), + prob->getUnVec(1), + new MobilityCH1Diff(gamma)), GRD_PSI); + prob->addMatrixOperator(*opChLM, 0, 1); + // rhs operators + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLM2->addTerm(new VecAtQP_SOT( + prob->getStageSolution(0), + new MobilityCH1(gamma))); + opChLM2->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + } + } else { + opChLM->addTerm(new Simple_SOT(gamma)); + opChLM->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLM, 0, &minus1, &minus1); + prob->addMatrixOperator(*opChLM, 0, 1); /// < phi*grad(mu) , grad(psi) > + } + + /// < u_s * grad(c_s), psi > + Operator *uGradC = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + uGradC->addTerm(new WorldVec_FOT(stage_velocity, -1.0), GRD_PSI); + else + uGradC->addTerm(new WorldVec_FOT(stage_velocity), GRD_PHI); + uGradC->setUhOld(prob->getStageSolution(0)); + prob->addVectorOperator(*uGradC, 0, &minus1, &minus1); + + /// < u_old * grad(c), psi > + Operator *JuGradC1 = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + JuGradC1->addTerm(new WorldVec_FOT(un_velocity, -1.0), GRD_PSI); + else + JuGradC1->addTerm(new WorldVec_FOT(un_velocity), GRD_PHI); + prob->addMatrixOperator(*JuGradC1, 0, 0); + + /// < u * grad(c_old), psi > + for (size_t i = 0; i < dow; i++) { + Operator *JuGradC2 = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + JuGradC2->addTerm(new VecAndPartialDerivative_FOT(prob->getUnVec(0), i, -1.0), GRD_PSI); + else { + JuGradC2->addTerm(new PartialDerivative_ZOT(prob->getUnVec(0), i)); + } + prob->addMatrixOperator(*JuGradC2, 0, 2+i); + } + + + // mu + eps^2*laplace(c) - M'(c) + // ---------------------------------------------------------------------- + /// < mu , psi > + Operator *opChMu = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChMu->addZeroOrderTerm(new Simple_ZOT); + opChMu->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChMu, 1); + prob->addMatrixOperator(*opChMu, 1, 1, &minus1, &minus1); + + /// < -eps^2*grad(c) , grad(psi) > + Operator *opChLC = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChLC->addSecondOrderTerm(new Simple_SOT(minusEpsSqr)); + opChLC->setUhOld(prob->getStageSolution(0)); + prob->addVectorOperator(*opChLC, 1); + prob->addMatrixOperator(*opChLC, 1, 0, &minus1, &minus1); + + /// < -M'(c) , psi > + if (doubleWell == 0) { + // jacobian operators + Operator *opChMImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getUnVec(0), + new DoubleWell0Diff(-1.0))); // < (3c^2-3c+0.5)*c' , psi > + prob->addMatrixOperator(*opChMImpl, 1, 0, &minus1, &minus1); + // rhs operators + Operator *opChMExpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getStageSolution(0), + new DoubleWell0(-1.0))); // < (c^3-3/2*c^2+0.5) , psi > + prob->addVectorOperator(*opChMExpl, 1); + } + else if (doubleWell == 1) { + // jacobian operators + Operator *opChMImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getUnVec(0), + new DoubleWell1Diff(-1.0))); // < (3c^2-1)*c' , psi > + prob->addMatrixOperator(*opChMImpl, 1, 0, &minus1, &minus1); + // rhs operators + Operator *opChMExpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getStageSolution(0), + new DoubleWell1(-1.0))); // < (c^3-c) , psi > + prob->addVectorOperator(*opChMExpl, 1); + } + + // Navier-Stokes part + // ----------------------------------------------------------------------------------- + for (size_t i = 0; i < dow; ++i) { + /// < d_t(u_i) , psi > + prob->addTimeOperator(2+i, 2+i); + + /// < u_s*grad(u_s_i) , psi > + Operator *opUGradU = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opUGradU->addTerm(new WorldVec_FOT(stage_velocity, -1.0), GRD_PHI); + opUGradU->setUhOld(stage_velocity[i]); + prob->addVectorOperator(*opUGradU, 2+i); + + /// < u_old*grad(u_i) , psi > + Operator *opUGradV = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opUGradV->addTerm(new WorldVec_FOT(un_velocity, -1.0), GRD_PHI); + prob->addMatrixOperator(*opUGradV, 2+i, 2+i, &minus1, &minus1); + + /// < u*grad(u_old_i) , psi > + for (size_t j = 0; j < dow; ++j) { + Operator *opVGradU = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opVGradU->addTerm(new PartialDerivative_ZOT(un_velocity[i], j, -1.0)); + prob->addMatrixOperator(*opVGradU, 2+i, 2+j, &minus1, &minus1); + } + + /// Diffusion-Operator (including Stress-Tensor for space-dependent viscosity) + addLaplaceTerm(i); + + /// < p , d_i(psi) > + Operator *opGradP = new Operator(getFeSpace(2+i),getFeSpace(2+dow)); + opGradP->addTerm(new PartialDerivative_FOT(i), GRD_PSI); + opGradP->setUhOld(prob->getStageSolution(2+dow)); + prob->addVectorOperator(*opGradP, 2+i); + prob->addMatrixOperator(*opGradP, 2+i, 2+dow, &minus1, &minus1); + + /// external force, i.e. gravitational force + if (norm(force) > DBL_TOL) { + Operator *opForce = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opForce->addTerm(new Simple_ZOT(force[i])); + prob->addVectorOperator(*opForce, 2+i); + } + + + // forces by Cahn-Hilliard terms + // ----------------------------- + /// < mu_old * grad(c) , psi > + Operator *JmuGradC = new Operator(getFeSpace(2+i),getFeSpace(0)); + JmuGradC->addTerm(new VecAndPartialDerivative_FOT( + prob->getUnVec(1), i, -1.0), GRD_PHI); + prob->addMatrixOperator(*JmuGradC, 2+i, 0, &surfaceTension, &surfaceTension); + + /// < mu * grad(c_old) , psi > + Operator *JmuGradC2 = new Operator(getFeSpace(2+i),getFeSpace(1)); + JmuGradC2->addTerm(new PartialDerivative_ZOT( + prob->getUnVec(0), i, -1.0)); + prob->addMatrixOperator(*JmuGradC2, 2+i, 1, &surfaceTension, &surfaceTension); + + /// < mu_s * grad(c_s) , psi > + Operator *opMuGradC = new Operator(getFeSpace(2+i),getFeSpace(1)); + opMuGradC->addTerm(new VecAndPartialDerivative_ZOT( + prob->getStageSolution(1), + prob->getStageSolution(0), i)); + prob->addVectorOperator(*opMuGradC, 2+i, &surfaceTension, &surfaceTension); + } + + // div(u) = 0 + // ---------- + for (size_t i = 0; i < dow; ++i) { + /// < d_i(u_i) , psi > + Operator *opDivU = new Operator(getFeSpace(2+dow),getFeSpace(2+i)); + opDivU->addTerm(new PartialDerivative_FOT(i), GRD_PHI); + prob->addMatrixOperator(*opDivU, 2+dow, 2+i, &minus1, &minus1); + /// < d_i(u_s_i) , psi > + opDivU->setUhOld(stage_velocity[i]); + prob->addVectorOperator(*opDivU, 2+dow); + } +} + + +void CahnHilliardNavierStokes_RB::addLaplaceTerm(int i) +{ FUNCNAME("CahnHilliardNavierStokes_RB::addLaplaceTerm()"); + + /// < nu*[grad(u)+grad(u)^t] , grad(psi) > + if (laplaceType == 1) { + for (unsigned j = 0; j < dow; ++j) { + Operator *opLaplaceUi1 = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opLaplaceUi1->addTerm(new MatrixIJ_SOT(1-i, 1-j, viscosity)); + prob->addMatrixOperator(*opLaplaceUi1, 2+i, 2+j); + opLaplaceUi1->setUhOld(prob->getStageSolution(2+j)); + prob->addVectorOperator(*opLaplaceUi1, 2+i, &minus1, &minus1); + } + } + + /// < nu*grad(u'_i) , grad(psi) > + Operator *opLaplaceUi = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opLaplaceUi->addTerm(new Simple_SOT(viscosity)); + prob->addMatrixOperator(*opLaplaceUi, 2+i, 2+i); + opLaplaceUi->setUhOld(prob->getStageSolution(2+i)); + prob->addVectorOperator(*opLaplaceUi, 2+i, &minus1, &minus1); +} + +void CahnHilliardNavierStokes_RB::closeTimestep(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes_RB::closeTimestep()"); + + calcVelocity(); + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); +} diff --git a/extensions/base_problems/CahnHilliardNavierStokes_RB.h b/extensions/base_problems/CahnHilliardNavierStokes_RB.h new file mode 100644 index 00000000..bcab1017 --- /dev/null +++ b/extensions/base_problems/CahnHilliardNavierStokes_RB.h @@ -0,0 +1,272 @@ +/** \file CahnHilliardNavierStokes_RB.h */ + +#ifndef CAHN_HILLIARD_H +#define CAHN_HILLIARD_H + +#include "AMDiS.h" +#include "BaseProblem_RB.h" +#include "HL_SignedDistTraverse.h" + +using namespace AMDiS; + +class CahnHilliardNavierStokes_RB : public BaseProblem_RB +{ +public: // definition of types + + typedef BaseProblem_RB super; + +public: // public methods + + CahnHilliardNavierStokes_RB(const std::string &name_); + ~CahnHilliardNavierStokes_RB(); + + virtual void initData(); + + virtual void transferInitialSolution(AdaptInfo *adaptInfo); + virtual void closeTimestep(AdaptInfo *adaptInfo); + + double getEpsilon() { return eps; } + int getDoubleWellType() { return doubleWell; } + + DOFVector<WorldVector<double> >* getVelocity() + { + return velocity; + } + + virtual void fillOperators(); + virtual void fillBoundaryConditions() {} + virtual void addLaplaceTerm(int i); + +protected: // protected variables + + HL_SignedDistTraverse *reinit; + + DOFVector<WorldVector<double> >* velocity; + + void calcVelocity() + { + if (dow == 1) + transformDOF(prob->getSolution()->getDOFVector(2), velocity, new AMDiS::Vec1WorldVec<double>); + else if (dow == 2) + transformDOF(prob->getSolution()->getDOFVector(2), prob->getSolution()->getDOFVector(3), velocity, new AMDiS::Vec2WorldVec<double>); + else if (dow == 3) + transformDOF(prob->getSolution()->getDOFVector(2), prob->getSolution()->getDOFVector(3), prob->getSolution()->getDOFVector(4), velocity, new AMDiS::Vec3WorldVec<double>); + } + + bool useMobility; + bool useConservationForm; + + unsigned dim; + + int laplaceType; + int nonLinTerm; + int doubleWell; + + // navierStokes parameters + double oldTimestep; + double viscosity; + double density; + double c; + + // Cahn-Hilliard parameters + double gamma; + double eps; + double minusEps; + double epsInv; + double minusEpsInv; + double epsSqr; + double minusEpsSqr; + + double sigma; // coupling parameter to calculate the surface tension + double surfaceTension;// := sigma/epsilon + + WorldVector<double> force; + + FileVectorWriter *fileWriter; +}; + + +/** \brief + * Abstract function for Cahn-Hilliard mobility + */ +class MobilityCH0 : public AbstractFunction<double,double> +{ + public: + MobilityCH0(double gamma_=1.0) : + AbstractFunction<double,double>(4), + gamma(gamma_), + delta(1.e-6) { } + double operator()(const double &ch) const + { + double phase = std::max(0.0, std::min(1.0, ch)); + double mobility = 0.25*sqr(phase)*sqr(phase-1.0); + return gamma * std::max(mobility, delta); + } + + protected: + double gamma; + double delta; +}; + +class MobilityCH1 : public AbstractFunction<double,double> +{ + public: + MobilityCH1(double gamma_=1.0) : + AbstractFunction<double,double>(4), + gamma(gamma_), + delta(1.e-6) { } + double operator()(const double &ch) const + { + double phase = std::max(-1.0, std::min(1.0, ch)); + double mobility = 0.25*sqr(sqr(phase)-1.0); + return gamma * std::max(mobility, delta); + } + + protected: + double gamma; + double delta; +}; + +class ScaleFunctor : public AbstractFunction<double,double> +{ + public: + ScaleFunctor(double factor_=1.0) : + AbstractFunction<double,double>(1), + factor(factor_) { } + double operator()(const double &ch) const + { + return factor * ch; + } + + protected: + double factor; +}; + +class Pow2Functor : public AbstractFunction<double,double> +{ + public: + Pow2Functor(double factor_=1.0) : + AbstractFunction<double,double>(2), + factor(factor_) { } + double operator()(const double &ch) const + { + return factor * sqr(ch); + } + + protected: + double factor; +}; + +class Pow3Functor : public AbstractFunction<double,double> +{ + public: + Pow3Functor(double factor_=1.0) : + AbstractFunction<double,double>(3), + factor(factor_) { } + double operator()(const double &ch) const + { + return factor * sqr(ch) * ch; + } + + protected: + double factor; +}; + + +class MobilityCH0Diff : public BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> > +{ + public: + MobilityCH0Diff(double factor_=1.0) : + BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> >(4), + factor(factor_) { } + WorldVector<double> operator()(const double &c, const WorldVector<double>& grdMu) const + { + double phase = std::max(0.0, std::min(1.0, c)); + return (factor * (sqr(phase)*phase - 1.5*sqr(phase) + 0.5*phase)) * grdMu; + } + + protected: + double factor; +}; + +class MobilityCH1Diff : public BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> > +{ + public: + MobilityCH1Diff(double factor_=1.0) : + BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> >(4), + factor(factor_) { } + WorldVector<double> operator()(const double &c, const WorldVector<double>& grdMu) const + { + double phase = std::max(-1.0, std::min(1.0, c)); + return (factor * (sqr(phase)*phase - phase)) * grdMu; + } + + protected: + double factor; +}; + +class DoubleWell0 : public AbstractFunction<double,double> +{ + public: + DoubleWell0(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (sqr(c)*c - 1.5*sqr(c) + 0.5*c); + } + + protected: + double factor; +}; + +class DoubleWell1 : public AbstractFunction<double,double> +{ + public: + DoubleWell1(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (sqr(c)*c - c); + } + + protected: + double factor; +}; + +class DoubleWell0Diff : public AbstractFunction<double,double> +{ + public: + DoubleWell0Diff(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (3.0*sqr(c) - 3.0*c + 0.5); + } + + protected: + double factor; +}; + +class DoubleWell1Diff : public AbstractFunction<double,double> +{ + public: + DoubleWell1Diff(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (3.0*sqr(c) - 1.0); + } + + protected: + double factor; +}; + +#endif // CAHN_HILLIARD_H diff --git a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc new file mode 100644 index 00000000..38b0df01 --- /dev/null +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc @@ -0,0 +1,477 @@ +#include "CahnHilliardNavierStokes_TwoPhase_RB.h" +#include "Views.h" +#include "SignedDistFunctors.h" +#include "PhaseFieldConvert.h" +#include "POperators.h" + +using namespace AMDiS; + +CahnHilliardNavierStokes_TwoPhase_RB::CahnHilliardNavierStokes_TwoPhase_RB(const std::string &name_) : + super(name_), + useMobility(false), + useConservationForm(false), + doubleWell(1), + gamma(1.0), + eps(0.1), + minusEps(-0.1), + epsInv(10.0), + minusEpsInv(-10.0), + epsSqr(0.01), + minusEpsSqr(-0.01), + laplaceType(0), + nonLinTerm(3), + oldTimestep(0.0), + viscosity1(1.0), + viscosity2(1.0), + density1(1.0), + density2(1.0), + c(0.0), + sigma(1.0), + surfaceTension(1.0), + reinit(NULL), + velocity(NULL), + fileWriter(NULL) +{ + // parameters for CH + Parameters::get(name + "->use mobility", useMobility); // dt(c) = div(M(c)*grad(c)) + ... + Parameters::get(name + "->gamma", gamma); // M(c) = gamma * Double-Well + Parameters::get(name + "->epsilon", eps); // interface width + + // type of double well: 0= [0,1], 1= [-1,1] + Parameters::get(name + "->double-well type", doubleWell); + + // parameters for navier-stokes + Initfile::get(name + "->viscosity1", viscosity1); + Initfile::get(name + "->viscosity2", viscosity2); + Initfile::get(name + "->density1", density1); + Initfile::get(name + "->density2", density2); + + // type of laplace operator: 0... div(nu*grad(u)), + // 1... div(0.5*nu*(grad(u)+grad(u)^T)) + Initfile::get(name + "->laplace operator", laplaceType); + + // Parameters for CH-Coupling + // 0... u*grad(c), 1... -div(u*c) + Initfile::get(name + "->use conservation form", useConservationForm); + + // Parameters for NS-Coupling + // cahn-hiliard-force: sigma*mu*grad(c) + Initfile::get(name + "->sigma", sigma); // surface tension + surfaceTension = sigma*3.0/(2.0*sqrt(2.0)) / eps; + + + force.set(0.0); + Initfile::get(name + "->force", force); + + // transformation of the parameters + minusEps = -eps; + epsInv = 1.0/eps; + minusEpsInv = -epsInv; + epsSqr = sqr(eps); + minusEpsSqr = -epsSqr; +} + + +CahnHilliardNavierStokes_TwoPhase_RB::~CahnHilliardNavierStokes_TwoPhase_RB() +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::~CahnHilliardNavierStokes_TwoPhase_RB()"); + + if (reinit != NULL) { + delete reinit; + reinit = NULL; + } + if (velocity != NULL) { + delete velocity; + velocity = NULL; + } + delete fileWriter; + fileWriter = NULL; +} + + +void CahnHilliardNavierStokes_TwoPhase_RB::initData() +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::initData()"); + + dim = getMesh()->getDim(); + // create instance redistancing class + reinit = new HL_SignedDistTraverse("reinit", dim); + + if (velocity == NULL) + velocity = new DOFVector<WorldVector<double> >(getFeSpace(2), "velocity"); + fileWriter = new FileVectorWriter(name + "->velocity->output", getFeSpace(2)->getMesh(), velocity); + + super::initData(); +} + + +void CahnHilliardNavierStokes_TwoPhase_RB::transferInitialSolution(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::transferInitialSolution()"); + + calcVelocity(); + + for (int i = 0; i < 2+dow; i++) + prob->setExactSolution(prob->getSolution()->getDOFVector(i), i); + + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); + + // initial parameters for detecting mesh changes + oldMeshChangeIdx= getMesh()->getChangeIndex(); +} + + +void CahnHilliardNavierStokes_TwoPhase_RB::fillOperators() +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::fillOperators()"); + MSG("CahnHilliardNavierStokes_TwoPhase_RB::fillOperators()\n"); + + // variable order: + // (c, mu, u0, u1 [, u2], p) + + WorldVector<DOFVector<double>*> stage_velocity; + WorldVector<DOFVector<double>*> un_velocity; + for (size_t i = 0; i < dow; ++i) { + stage_velocity[i] = prob->getStageSolution(2+i); + un_velocity[i] = prob->getUnVec(2+i); + } + + // dt(c) = laplace(mu) - u*grad(c) + // ----------------------------------- + /// < dt(c) , psi > + prob->addTimeOperator(0, 0); + + // div(M(c)grad(mu)), with M(c)=gamma/4*(c^2-1)^2 + Operator *opChLM = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + if (useMobility) { + if (doubleWell == 0) { + // jacobian operators + opChLM->addTerm(new VecAtQP_SOT( + prob->getUnVec(0), + new MobilityCH0(gamma))); + opChLM->addTerm(new VecGrad_FOT( + prob->getUnVec(0), + prob->getUnVec(1), + new MobilityCH0Diff(gamma)), GRD_PSI); + prob->addMatrixOperator(*opChLM, 0, 1); + // rhs operators + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLM2->addTerm(new VecAtQP_SOT( + prob->getStageSolution(0), + new MobilityCH0(gamma))); + opChLM2->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + } else { + // jacobian operators + opChLM->addTerm(new VecAtQP_SOT( + prob->getUnVec(0), + new MobilityCH1(gamma))); + opChLM->addTerm(new VecGrad_FOT( + prob->getUnVec(0), + prob->getUnVec(1), + new MobilityCH1Diff(gamma)), GRD_PSI); + prob->addMatrixOperator(*opChLM, 0, 1); + // rhs operators + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLM2->addTerm(new VecAtQP_SOT( + prob->getStageSolution(0), + new MobilityCH1(gamma))); + opChLM2->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + } + } else { + opChLM->addTerm(new Simple_SOT(gamma)); + opChLM->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLM, 0, &minus1, &minus1); + prob->addMatrixOperator(*opChLM, 0, 1); /// < phi*grad(mu) , grad(psi) > + } + + /// < u_s * grad(c_s), psi > + Operator *uGradC = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + uGradC->addTerm(new WorldVec_FOT(stage_velocity, -1.0), GRD_PSI); + else + uGradC->addTerm(new WorldVec_FOT(stage_velocity), GRD_PHI); + uGradC->setUhOld(prob->getStageSolution(0)); + prob->addVectorOperator(*uGradC, 0, &minus1, &minus1); + + /// < u_old * grad(c), psi > + Operator *JuGradC1 = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + JuGradC1->addTerm(new WorldVec_FOT(un_velocity, -1.0), GRD_PSI); + else + JuGradC1->addTerm(new WorldVec_FOT(un_velocity), GRD_PHI); + prob->addMatrixOperator(*JuGradC1, 0, 0); + + /// < u * grad(c_old), psi > + for (size_t i = 0; i < dow; i++) { + Operator *JuGradC2 = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + JuGradC2->addTerm(new VecAndPartialDerivative_FOT(prob->getUnVec(0), i, -1.0), GRD_PSI); + else { + JuGradC2->addTerm(new PartialDerivative_ZOT(prob->getUnVec(0), i)); + } + prob->addMatrixOperator(*JuGradC2, 0, 2+i); + } + + + // mu + eps^2*laplace(c) - M'(c) + // ---------------------------------------------------------------------- + /// < mu , psi > + Operator *opChMu = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChMu->addZeroOrderTerm(new Simple_ZOT); + opChMu->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChMu, 1); + prob->addMatrixOperator(*opChMu, 1, 1, &minus1, &minus1); + + /// < -eps^2*grad(c) , grad(psi) > + Operator *opChLC = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChLC->addSecondOrderTerm(new Simple_SOT(minusEpsSqr)); + opChLC->setUhOld(prob->getStageSolution(0)); + prob->addVectorOperator(*opChLC, 1); + prob->addMatrixOperator(*opChLC, 1, 0, &minus1, &minus1); + + /// < -M'(c) , psi > + if (doubleWell == 0) { + // jacobian operators + Operator *opChMImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getUnVec(0), + new DoubleWell0Diff(-1.0))); // < (3c^2-3c+0.5)*c' , psi > + prob->addMatrixOperator(*opChMImpl, 1, 0, &minus1, &minus1); + // rhs operators + Operator *opChMExpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getStageSolution(0), + new DoubleWell0(-1.0))); // < (c^3-3/2*c^2+0.5) , psi > + prob->addVectorOperator(*opChMExpl, 1); + } + else if (doubleWell == 1) { + // jacobian operators + Operator *opChMImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getUnVec(0), + new DoubleWell1Diff(-1.0))); // < (3c^2-1)*c' , psi > + prob->addMatrixOperator(*opChMImpl, 1, 0, &minus1, &minus1); + // rhs operators + Operator *opChMExpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChMExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getStageSolution(0), + new DoubleWell1(-1.0))); // < (c^3-c) , psi > + prob->addVectorOperator(*opChMExpl, 1); + } + + // Navier-Stokes part + // ----------------------------------------------------------------------------------- + for (size_t i = 0; i < dow; ++i) { + /// < d_t(u_i) , psi > + prob->addTimeOperator(3+dow+i, 2+i); + + /// < z , psi > + Operator *opZ = new Operator(getFeSpace(3+dow+i), getFeSpace(3+dow+i)); + opZ->addTerm(new Simple_ZOT); + prob->addMatrixOperator(*opZ, 3+dow+i, 3+dow+i, &minus1, &minus1); + opZ->setUhOld(prob->getStageSolution(3+dow+i)); + prob->addVectorOperator(*opZ, 3+dow+i); + + + /// < u_s*grad(u_s_i) , psi > + Operator *opUGradU = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opUGradU->addTerm(new WorldVec_FOT(stage_velocity, -1.0), GRD_PHI); + opUGradU->setUhOld(stage_velocity[i]); + prob->addVectorOperator(*opUGradU, 3+dow+i); + + /// < u_old*grad(u_i) , psi > + Operator *opUGradV = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opUGradV->addTerm(new WorldVec_FOT(un_velocity, -1.0), GRD_PHI); + prob->addMatrixOperator(*opUGradV, 3+dow+i, 2+i, &minus1, &minus1); + + /// < u*grad(u_old_i) , psi > + for (size_t j = 0; j < dow; ++j) { + Operator *opVGradU = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opVGradU->addTerm(new PartialDerivative_ZOT(un_velocity[i], j, -1.0)); + prob->addMatrixOperator(*opVGradU, 3+dow+i, 2+j, &minus1, &minus1); + } + } + + for (size_t i = 0; i < dow; ++i) { + + /// Diffusion-Operator (including Stress-Tensor for space-dependent viscosity) + addStressTerm(i); + + /// external force, i.e. gravitational force + if (norm(force) > DBL_TOL) { + Operator *opForce = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opForce->addTerm(new Simple_ZOT(force[i])); + prob->addVectorOperator(*opForce, 2+i); + } + + // forces by Cahn-Hilliard terms + // ----------------------------- + /// < mu_old * grad(c) , psi > + Operator *JmuGradC = new Operator(getFeSpace(2+i),getFeSpace(0)); + JmuGradC->addTerm(new VecAndPartialDerivative_FOT( + prob->getUnVec(1), i, -1.0), GRD_PHI); + prob->addMatrixOperator(*JmuGradC, 2+i, 0, &surfaceTension, &surfaceTension); + + /// < mu * grad(c_old) , psi > + Operator *JmuGradC2 = new Operator(getFeSpace(2+i),getFeSpace(1)); + JmuGradC2->addTerm(new PartialDerivative_ZOT( + prob->getUnVec(0), i, -1.0)); + prob->addMatrixOperator(*JmuGradC2, 2+i, 1, &surfaceTension, &surfaceTension); + + /// < mu_s * grad(c_s) , psi > + Operator *opMuGradC = new Operator(getFeSpace(2+i),getFeSpace(1)); + opMuGradC->addTerm(new VecAndPartialDerivative_ZOT( + prob->getStageSolution(1), + prob->getStageSolution(0), i)); + prob->addVectorOperator(*opMuGradC, 2+i, &surfaceTension, &surfaceTension); + + // --------------------------------------- + + /// < rho(c_s)*z_s , psi > + Operator *opDensityExpl = new Operator(prob->getFeSpace(2+i),prob->getFeSpace(3+dow+1)); + opDensityExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getStageSolution(0), + new LinearInterpolation(density1, density2, -1.0))); + opDensityExpl->setUhOld(prob->getStageSolution(3+dow+i)); + prob->addVectorOperator(*opDensityExpl, 2+i); + + /// < rho(c_old)*z , psi > + Operator *opDensityImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opDensityImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getUnVec(0), + new LinearInterpolation(density1, density2, -1.0))); + prob->addMatrixOperator(*opDensityImpl, 2+i, 3+dow+i, &minus1, &minus1); + + /// < rho'(c_old)*z_old * c , psi > + Operator *opDensityImpl2 = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opDensityImpl2->addZeroOrderTerm(new Vec2AtQP_ZOT( + prob->getUnVec(0), + prob->getUnVec(3+dow+i), + new LinearInterpolationDiffFactor(density1, density2, -1.0))); + prob->addMatrixOperator(*opDensityImpl2, 2+i, 0, &minus1, &minus1); + } + + // div(u) = 0 + // ---------- + for (size_t i = 0; i < dow; ++i) { + /// < d_i(u_i) , psi > + Operator *opDivU = new Operator(getFeSpace(2+dow),getFeSpace(2+i)); + opDivU->addTerm(new PartialDerivative_FOT(i), GRD_PHI); + prob->addMatrixOperator(*opDivU, 2+dow, 2+i, &minus1, &minus1); + /// < d_i(u_s_i) , psi > + opDivU->setUhOld(stage_velocity[i]); + prob->addVectorOperator(*opDivU, 2+dow); + } +} + + +// void CahnHilliardNavierStokes_TwoPhase_RB::addNonlinearTerm(int i) +// { FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::addNonlinearTerm()"); +// +// WorldVector<DOFVector<double>*> stage_velocity; +// WorldVector<DOFVector<double>*> un_velocity; +// for (size_t j = 0; j < dow; ++j) { +// stage_velocity[j] = prob->getStageSolution(2+j); +// un_velocity[j] = prob->getUnVec(2+j); +// } +// +// /// < rho(c_s)*u_s*grad(u_s_i) , psi > +// Operator *opUGradU = new Operator(getFeSpace(2+i), getFeSpace(2+i)); +// opUGradU->addTerm(new VecAndWorldVec_FOT( +// prob->getStageSolution(0), +// stage_velocity, +// new LinearInterpolation(density1, density2, -1.0)), GRD_PHI); +// opUGradU->setUhOld(stage_velocity[i]); +// prob->addVectorOperator(*opUGradU, 2+i); +// +// /// < rho(c_old)*u_old*grad(u_i) , psi > +// Operator *opUGradV = new Operator(getFeSpace(2+i), getFeSpace(2+i)); +// opUGradV->addTerm(new VecAndWorldVec_FOT( +// prob->getUnVec(0), +// un_velocity, +// new LinearInterpolation(density1, density2, -1.0)), GRD_PHI); +// prob->addMatrixOperator(*opUGradV, 2+i, 2+i, &minus1, &minus1); +// +// /// < c * rho'(c_old)*u_old*grad(u_old_i) , psi > +// for (size_t j = 0; j < dow; ++j) { +// Operator *opVGradU = new Operator(getFeSpace(2+i), getFeSpace(2+j)); +// opVGradU->addTerm(new Vec2AndPartialDerivative_ZOT( +// prob->getUnVec(0), +// un_velocity[i], +// un_velocity[j], +// j, +// new LinearInterpolationDiffFactor(density1, density2, -1.0))); +// prob->addMatrixOperator(*opVGradU, 2+i, 0, &minus1, &minus1); +// } +// } + + +void CahnHilliardNavierStokes_TwoPhase_RB::addStressTerm(int i) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::addStressTerm()"); + + /// < nu*[grad(u)+grad(u)^t] , grad(psi) > + if (laplaceType == 1) { + for (unsigned j = 0; j < dow; ++j) { + /// < nu(c_s)*d_j(u_s_i) , d_i(psi) > + Operator *opLaplaceUijExpl = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opLaplaceUijExpl->addTerm(new VecAtQP_IJ_SOT( + prob->getStageSolution(0), + new LinearInterpolation(viscosity1, viscosity2), + 1-i, 1-j)); + opLaplaceUijExpl->setUhOld(prob->getStageSolution(2+j)); + prob->addVectorOperator(*opLaplaceUijExpl, 2+i, &minus1, &minus1); + + /// < nu(c_old)*d_j(u_i) , d_i(psi) > + Operator *opLaplaceUijImpl = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opLaplaceUijImpl->addTerm(new VecAtQP_IJ_SOT( + prob->getUnVec(0), + new LinearInterpolation(viscosity1, viscosity2), + 1-i, 1-j)); + prob->addMatrixOperator(*opLaplaceUijImpl, 2+i, 2+j); + + /// < c * nu'(c_old)*d_j(u_old_i) , d_i(psi) > + Operator *opLaplaceUijImpl2 = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opLaplaceUijImpl2->addTerm(new VecAndPartialDerivativeIJ_FOT( + prob->getUnVec(0), + prob->getUnVec(2+j), + 1-i, 1-j, + new LinearInterpolationDiffFactor(viscosity1, viscosity2)), GRD_PSI); + prob->addMatrixOperator(*opLaplaceUijImpl2, 2+i, 0); + } + } + + /// < nu*grad(u'_i) , grad(psi) > + Operator *opLaplaceUExpl = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opLaplaceUExpl->addTerm(new VecAtQP_SOT( + prob->getStageSolution(0), + new LinearInterpolation(viscosity1, viscosity2))); + opLaplaceUExpl->setUhOld(prob->getStageSolution(2+i)); + prob->addVectorOperator(*opLaplaceUExpl, 2+i, &minus1, &minus1); + + Operator *opLaplaceUImpl = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opLaplaceUImpl->addTerm(new VecAtQP_SOT( + prob->getUnVec(0), + new LinearInterpolation(viscosity1, viscosity2))); + prob->addMatrixOperator(*opLaplaceUImpl, 2+i, 2+i); + + Operator *opLaplaceUImpl2 = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opLaplaceUImpl2->addTerm(new VecGrad_FOT( + prob->getUnVec(0), + prob->getUnVec(2+i), + new LinearInterpolationDiffVector(viscosity1, viscosity2)), GRD_PSI); + prob->addMatrixOperator(*opLaplaceUImpl2, 2+i, 0); + + /// < p , d_i(psi) > + Operator *opGradP = new Operator(getFeSpace(2+i),getFeSpace(2+dow)); + opGradP->addTerm(new PartialDerivative_FOT(i), GRD_PSI); + opGradP->setUhOld(prob->getStageSolution(2+dow)); + prob->addVectorOperator(*opGradP, 2+i); + prob->addMatrixOperator(*opGradP, 2+i, 2+dow, &minus1, &minus1); +} + +void CahnHilliardNavierStokes_TwoPhase_RB::closeTimestep(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase_RB::closeTimestep()"); + + calcVelocity(); + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); +} diff --git a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h new file mode 100644 index 00000000..a4ccf450 --- /dev/null +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h @@ -0,0 +1,326 @@ +/** \file CahnHilliardNavierStokes_TwoPhase_RB.h */ + +#ifndef CAHN_HILLIARD_H +#define CAHN_HILLIARD_H + +#include "AMDiS.h" +#include "BaseProblem_RB.h" +#include "HL_SignedDistTraverse.h" + +using namespace AMDiS; + +class CahnHilliardNavierStokes_TwoPhase_RB : public BaseProblem_RB +{ +public: // definition of types + + typedef BaseProblem_RB super; + +public: // public methods + + CahnHilliardNavierStokes_TwoPhase_RB(const std::string &name_); + ~CahnHilliardNavierStokes_TwoPhase_RB(); + + virtual void initData(); + + virtual void transferInitialSolution(AdaptInfo *adaptInfo); + virtual void closeTimestep(AdaptInfo *adaptInfo); + + double getEpsilon() { return eps; } + int getDoubleWellType() { return doubleWell; } + + DOFVector<WorldVector<double> >* getVelocity() + { + return velocity; + } + + virtual void fillOperators(); + virtual void fillBoundaryConditions() {} +// virtual void addNonlinearTerm(int i); + virtual void addStressTerm(int i); + +protected: // protected variables + + HL_SignedDistTraverse *reinit; + + DOFVector<WorldVector<double> >* velocity; + + void calcVelocity() + { + if (dow == 1) + transformDOF(prob->getSolution()->getDOFVector(2), velocity, new AMDiS::Vec1WorldVec<double>); + else if (dow == 2) + transformDOF(prob->getSolution()->getDOFVector(2), prob->getSolution()->getDOFVector(3), velocity, new AMDiS::Vec2WorldVec<double>); + else if (dow == 3) + transformDOF(prob->getSolution()->getDOFVector(2), prob->getSolution()->getDOFVector(3), prob->getSolution()->getDOFVector(4), velocity, new AMDiS::Vec3WorldVec<double>); + } + + bool useMobility; + bool useConservationForm; + + unsigned dim; + + int laplaceType; + int nonLinTerm; + int doubleWell; + + // navierStokes parameters + double oldTimestep; + double viscosity1; + double viscosity2; + double density1; + double density2; + double c; + + // Cahn-Hilliard parameters + double gamma; + double eps; + double minusEps; + double epsInv; + double minusEpsInv; + double epsSqr; + double minusEpsSqr; + + double sigma; // coupling parameter to calculate the surface tension + double surfaceTension;// := sigma/epsilon + + WorldVector<double> force; + + FileVectorWriter *fileWriter; +}; + + +/** \brief + * Abstract function for Cahn-Hilliard mobility + */ +class MobilityCH0 : public AbstractFunction<double,double> +{ + public: + MobilityCH0(double gamma_=1.0) : + AbstractFunction<double,double>(4), + gamma(gamma_), + delta(1.e-6) { } + double operator()(const double &ch) const + { + double phase = std::max(0.0, std::min(1.0, ch)); + double mobility = 0.25*sqr(phase)*sqr(phase-1.0); + return gamma * std::max(mobility, delta); + } + + protected: + double gamma; + double delta; +}; + +class MobilityCH1 : public AbstractFunction<double,double> +{ + public: + MobilityCH1(double gamma_=1.0) : + AbstractFunction<double,double>(4), + gamma(gamma_), + delta(1.e-6) { } + double operator()(const double &ch) const + { + double phase = std::max(-1.0, std::min(1.0, ch)); + double mobility = 0.25*sqr(sqr(phase)-1.0); + return gamma * std::max(mobility, delta); + } + + protected: + double gamma; + double delta; +}; + +class ScaleFunctor : public AbstractFunction<double,double> +{ + public: + ScaleFunctor(double factor_=1.0) : + AbstractFunction<double,double>(1), + factor(factor_) { } + double operator()(const double &ch) const + { + return factor * ch; + } + + protected: + double factor; +}; + +class Pow2Functor : public AbstractFunction<double,double> +{ + public: + Pow2Functor(double factor_=1.0) : + AbstractFunction<double,double>(2), + factor(factor_) { } + double operator()(const double &ch) const + { + return factor * sqr(ch); + } + + protected: + double factor; +}; + +class Pow3Functor : public AbstractFunction<double,double> +{ + public: + Pow3Functor(double factor_=1.0) : + AbstractFunction<double,double>(3), + factor(factor_) { } + double operator()(const double &ch) const + { + return factor * sqr(ch) * ch; + } + + protected: + double factor; +}; + + +class MobilityCH0Diff : public BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> > +{ + public: + MobilityCH0Diff(double factor_=1.0) : + BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> >(4), + factor(factor_) { } + WorldVector<double> operator()(const double &c, const WorldVector<double>& grdMu) const + { + double phase = std::max(0.0, std::min(1.0, c)); + return (factor * (sqr(phase)*phase - 1.5*sqr(phase) + 0.5*phase)) * grdMu; + } + + protected: + double factor; +}; + +class MobilityCH1Diff : public BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> > +{ + public: + MobilityCH1Diff(double factor_=1.0) : + BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> >(4), + factor(factor_) { } + WorldVector<double> operator()(const double &c, const WorldVector<double>& grdMu) const + { + double phase = std::max(-1.0, std::min(1.0, c)); + return (factor * (sqr(phase)*phase - phase)) * grdMu; + } + + protected: + double factor; +}; + +class DoubleWell0 : public AbstractFunction<double,double> +{ + public: + DoubleWell0(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (sqr(c)*c - 1.5*sqr(c) + 0.5*c); + } + + protected: + double factor; +}; + +class DoubleWell1 : public AbstractFunction<double,double> +{ + public: + DoubleWell1(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (sqr(c)*c - c); + } + + protected: + double factor; +}; + +class DoubleWell0Diff : public AbstractFunction<double,double> +{ + public: + DoubleWell0Diff(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (3.0*sqr(c) - 3.0*c + 0.5); + } + + protected: + double factor; +}; + +class DoubleWell1Diff : public AbstractFunction<double,double> +{ + public: + DoubleWell1Diff(double factor_=1.0) : + AbstractFunction<double,double>(4), + factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (3.0*sqr(c) - 1.0); + } + + protected: + double factor; +}; + +struct LinearInterpolation : AbstractFunction<double,double> +{ + LinearInterpolation(double v0_, double v1_, double factor_ = 1.0) : + AbstractFunction<double,double>(4), + v0(v0_), v1(v1_), factor(factor_) { } + + double operator()(const double &c) const + { + return factor * (v0*(c+1.0) - v1*(c-1.0))/2.0; + } + +private: + double v0; + double v1; + double factor; +}; + +struct LinearInterpolationDiffFactor : BinaryAbstractFunction<double,double,double> +{ + LinearInterpolationDiffFactor(double v0_, double v1_, double factor_ = 1.0) : + BinaryAbstractFunction<double,double,double>(4), + v0(v0_), v1(v1_), factor(factor_) { } + + double operator()(const double &c, const double& z) const + { + return factor * z * (v0 - v1)/2.0; + } + +private: + double v0; + double v1; + double factor; +}; + +struct LinearInterpolationDiffVector : BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> > +{ + LinearInterpolationDiffVector(double v0_, double v1_, double factor_ = 1.0) : + BinaryAbstractFunction<WorldVector<double>,double,WorldVector<double> >(4), + v0(v0_), v1(v1_), factor(factor_) { } + + WorldVector<double> operator()(const double &c, const WorldVector<double>& grdU) const + { + return (factor * (v0 - v1)/2.0) * grdU; + } + +private: + double v0; + double v1; + double factor; +}; + +#endif // CAHN_HILLIARD_H diff --git a/extensions/base_problems/DiffuseDomainFsi.cc b/extensions/base_problems/DiffuseDomainFsi.cc index 0b034703..247c8508 100644 --- a/extensions/base_problems/DiffuseDomainFsi.cc +++ b/extensions/base_problems/DiffuseDomainFsi.cc @@ -6,6 +6,7 @@ using namespace AMDiS; DiffuseDomainFsi::DiffuseDomainFsi(const std::string &name_) : super(name_), phase(NULL), + bcPhase(NULL), phaseInv(NULL), velocity(NULL), displacement(NULL), @@ -17,22 +18,31 @@ DiffuseDomainFsi::DiffuseDomainFsi(const std::string &name_) : density(1.0), lambda(1.0), rho(1.0), + nonLinTerm(3), fileWriterPhase(NULL), fileWriterVelocity(NULL), fileWriterDisplacement(NULL) { - Parameters::get(name + "->beta", beta); Parameters::get(name + "->epsilon", epsilon); - Parameters::get(name + "->alpha", alpha); // parameters for navier-stokes Initfile::get(name + "->viscosity", viscosity); Initfile::get(name + "->density", density); + + Parameters::get(name + "->beta", beta); + Parameters::get(name + "->alpha", alpha); + // parameters for linear elasticity Parameters::get(name + "->mu", mu); Parameters::get(name + "->lambda", lambda); Parameters::get(name + "->rho", rho); + + // type of non-linear term: 0... u^old*grad(u_i^old), + // 1... u*grad(u_i^old), + // 2... u^old*grad(u_i) + // 3... u*grad(u_i^old) + u^old*grad(u_i) - u^old*grad(u_i^old) + Parameters::get(name + "->non-linear term", nonLinTerm); }; DiffuseDomainFsi::~DiffuseDomainFsi() @@ -43,20 +53,26 @@ DiffuseDomainFsi::~DiffuseDomainFsi() delete fileWriterVelocity; if (fileWriterDisplacement != NULL) delete fileWriterDisplacement; + + delete phaseInv; + delete phaseInvDisturbed; + delete velocity; + delete displacement; } void DiffuseDomainFsi::initData() { super::initData(); - phaseInv = new DOFVector<double>(getFeSpace(dow+1), "phaseInv"); + phaseInv = new DOFVector<double>(getFeSpace(0), "phaseInv"); + phaseInvDisturbed = new DOFVector<double>(getFeSpace(0), "phaseInvDisturbed"); velocity = new DOFVector<WorldVector<double> >(getFeSpace(0), "velocity"); displacement = new DOFVector<WorldVector<double> >(getFeSpace(dow+1), "displacement"); dbc_factor = beta/pow(epsilon, alpha); MSG_DBG("dbc_factor = %f\n", dbc_factor); pressure_factor = -(lambda+(2.0/3.0)*mu); - MSG_DBG("pressure_factor = %f\n", pressure_factor); + MSG("pressure_factor = %f\n", pressure_factor); } @@ -68,7 +84,6 @@ void DiffuseDomainFsi::transferInitialSolution(AdaptInfo *adaptInfo) fileWriterDisplacement = new FileVectorWriter(name + "->displacement->output", getFeSpace()->getMesh(), displacement); super::transferInitialSolution(adaptInfo); - transformDOF(1.0, phase, phaseInv, new Subtract<double>); calcVelocity(); calcDisplacement(); @@ -83,6 +98,15 @@ void DiffuseDomainFsi::transferInitialSolution(AdaptInfo *adaptInfo) } +void DiffuseDomainFsi::initTimestep(AdaptInfo *adaptInfo) +{ + super::initTimestep(adaptInfo); + transformDOF(1.0, phase, phaseInv, new Subtract<double>); + transformDOF(phaseInv, 1.e-7, phaseInvDisturbed, new Max<double>); + VtkWriter::writeFile(phaseInv, "phaseInv.vtu"); +} + + void DiffuseDomainFsi::closeTimestep(AdaptInfo *adaptInfo) { calcVelocity(); @@ -108,47 +132,48 @@ void DiffuseDomainFsi::fillOperators() /// < (1/tau)*u'_i , psi > Operator *opTime = new Operator(prob->getFeSpace(i), prob->getFeSpace(i)); opTime->addTerm(new Simple_ZOT(density)); - prob->addMatrixOperator(*opTime, i, i, getInvTau()); + prob->addMatrixOperator(*opTime, i, i, getInvTau(), getInvTau()); /// < (1/tau)*u_i^old , psi > Operator *opTimeOld = new Operator(prob->getFeSpace(i), prob->getFeSpace(i)); - opTimeOld->addTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(i), new Factor<double>(density))); - prob->addVectorOperator(*opTimeOld, i, getInvTau()); + opTimeOld->addTerm(new Phase_ZOT(prob->getSolution()->getDOFVector(i), density)); + prob->addVectorOperator(*opTimeOld, i, getInvTau(), getInvTau()); /// < (1/tau)*(1-phase)*eta_i , psi > Operator *opTimeE = new Operator(getFeSpace(dow+1+i), getFeSpace(dow+1+i)); - opTimeE->addTerm(new VecAtQP_ZOT(phaseInv)); + opTimeE->addTerm(new VecAtQP_ZOT(phaseInvDisturbed)); prob->addMatrixOperator(*opTimeE, dow+1+i, dow+1+i, getInvTau(), getInvTau()); /// < (1/tau)*(1-phase)*eta_i^old , psi > Operator *opTimeEOld = new Operator(getFeSpace(i+dow)); - opTimeEOld->addTerm(new Vec2AtQP_ZOT(phaseInv, prob->getSolution()->getDOFVector(dow+1+i))); + opTimeEOld->addTerm(new Vec2AtQP_ZOT(phaseInvDisturbed, prob->getSolution()->getDOFVector(dow+1+i))); prob->addVectorOperator(*opTimeEOld, dow+1+i, getInvTau(), getInvTau()); /// < (1-phase)*u , psi > Operator *opU = new Operator(getFeSpace(dow+1+i), getFeSpace(i)); - opU->addTerm(new Phase_ZOT(phaseInv, -1.0)); - prob->addMatrixOperator(*opU, dow+1+i, dow+1+i); + opU->addTerm(new Phase_ZOT(phaseInvDisturbed, -1.0)); + prob->addMatrixOperator(*opU, dow+1+i, i); // nonlinear terms // =============== /// < u^old*grad(u_i^old) , psi > - Operator *opUGradU0 = new Operator(getFeSpace(i), getFeSpace(i)); - opUGradU0->addTerm(new WorldVector_FOT(velocity, -density), GRD_PHI); - opUGradU0->setUhOld(prob->getSolution()->getDOFVector(i)); - if (nonLinTerm == 0) + if (nonLinTerm == 0 || nonLinTerm == 3) { + Operator *opUGradU0 = new Operator(getFeSpace(i), getFeSpace(i)); + opUGradU0->addTerm(new WorldVec_FOT(vel, (nonLinTerm == 0 ? -1.0 : 1.0)*density), GRD_PHI); + opUGradU0->setUhOld(prob->getSolution()->getDOFVector(i)); prob->addVectorOperator(*opUGradU0, i); - - if (nonLinTerm == 1) { + } + if (nonLinTerm == 1 || nonLinTerm == 3) { /// < u'*grad(u_i^old) , psi > - for (unsigned j = 0; j < dow; ++j) { - Operator *opUGradU1 = new Operator(getFeSpace(i),getFeSpace(i)); + for (size_t j = 0; j < dow; ++j) { + Operator *opUGradU1 = new Operator(getFeSpace(i),getFeSpace(j)); opUGradU1->addTerm(new PartialDerivative_ZOT( prob->getSolution()->getDOFVector(i), j, density)); prob->addMatrixOperator(*opUGradU1, i, j); } - } else if (nonLinTerm == 2) { + } + if (nonLinTerm == 2 || nonLinTerm == 3) { /// < u^old*grad(u'_i) , psi > - for(unsigned j = 0; j < dow; ++j) { + for(size_t j = 0; j < dow; ++j) { Operator *opUGradU2 = new Operator(getFeSpace(i),getFeSpace(i)); opUGradU2->addTerm(new VecAndPartialDerivative_FOT( prob->getSolution()->getDOFVector(j), j, density), GRD_PHI); @@ -158,32 +183,30 @@ void DiffuseDomainFsi::fillOperators() // ==================== - /// < u^old*grad(u_i^old) , psi > - Operator *opUGradE0 = new Operator(prob->getFeSpace(i),prob->getFeSpace(dow+1+i)); - opUGradE0->addTerm(new WorldVecPhase_FOT(phaseInv, vel), GRD_PHI); - opUGradE0->setUhOld(prob->getSolution()->getDOFVector(dow+1+i)); - if (nonLinTerm == 0) - prob->addVectorOperator(*opUGradE0, dow+1+i); - - if (nonLinTerm == 1) { - /// < u'*grad(u_i^old) , psi > - for (size_t j = 0; j < dow; ++j) { - Operator *opUGradE1 = new Operator(prob->getFeSpace(i),prob->getFeSpace(dow+1+i)); - opUGradE1->addTerm(new VecAndPartialDerivative_ZOT( - phaseInv, - prob->getSolution()->getDOFVector(dow+1+i), j)); - prob->addMatrixOperator(*opUGradE1, dow+1+i, j); - } - } else if (nonLinTerm == 2) { - /// < u^old*grad(u'_i) , psi > - for(size_t j = 0; j < dow; ++j) { - Operator *opUGradE2 = new Operator(prob->getFeSpace(i),prob->getFeSpace(i)); - opUGradE2->addTerm(new Vec2ProductPartial_FOT( - phaseInv, - prob->getSolution()->getDOFVector(j), j, density), GRD_PHI); - prob->addMatrixOperator(*opUGradE2, dow+1+i, dow+1+i); - } - } + /// < (1-phase) * u^old*grad(eta_i^old) , psi > + Operator *opUGradE0 = new Operator(prob->getFeSpace(dow+1+i),prob->getFeSpace(dow+1+i)); + opUGradE0->addTerm(new WorldVecPhase_FOT(phaseInvDisturbed, vel), GRD_PHI); + opUGradE0->setUhOld(prob->getSolution()->getDOFVector(dow+1+i)); + prob->addVectorOperator(*opUGradE0, dow+1+i); + + /// < (1-phase) * u*grad(eta_i^old) , psi > + for (size_t j = 0; j < dow; ++j) { + Operator *opUGradE1 = new Operator(prob->getFeSpace(dow+1+i),prob->getFeSpace(j)); + opUGradE1->addTerm(new VecAndPartialDerivative_ZOT( + phaseInvDisturbed, + prob->getSolution()->getDOFVector(dow+1+i), j)); + prob->addMatrixOperator(*opUGradE1, dow+1+i, j); + } + + /// < (1-phase) * u^old*grad(eta_i) , psi > + for(size_t j = 0; j < dow; ++j) { + Operator *opUGradE2 = new Operator(prob->getFeSpace(dow+1+i),prob->getFeSpace(dow+1+i)); + opUGradE2->addTerm(new Vec2ProductPartial_FOT( + phaseInvDisturbed, + prob->getSolution()->getDOFVector(j), j), GRD_PHI); + prob->addMatrixOperator(*opUGradE2, dow+1+i, dow+1+i); + } + /// Diffusion-Operator (including Stress-Tensor for space-dependent viscosity) addLaplaceTerm(i); @@ -207,39 +230,46 @@ void DiffuseDomainFsi::fillOperators() opP->addTerm(new VecAtQP_ZOT(phaseInv)); prob->addMatrixOperator(*opP, dow, dow); + for (size_t i = 0; i < dow; ++i) { + /// dirichlet boundary condition + /// beta/eps^alpha (bcPhase)*(eta_i - 0) + Operator *opDbcPhaseInvU = new Operator(prob->getFeSpace(dow+1+i), prob->getFeSpace(dow+1+i)); + opDbcPhaseInvU->addTerm(new Phase_ZOT(bcPhase, dbc_factor)); + prob->addMatrixOperator(*opDbcPhaseInvU, dow+1+i, dow+1+i); + } } void DiffuseDomainFsi::addLaplaceTerm(int i) { FUNCNAME("DiffuseDomainFsi::addLaplaceTerm()"); - for (size_t j = 0; j < dow; ++j) { - /// < nu*[grad(u)+grad(u)^t] , grad(psi) > - Operator *opLaplaceUi1 = new Operator(prob->getFeSpace(i), prob->getFeSpace(j)); - opLaplaceUi1->addTerm(new MatrixIJPhase_SOT(phase, 1-i, 1-j, viscosity)); - prob->addMatrixOperator(*opLaplaceUi1, i, j); - - /// < (mu+lambda)*[grad(u)+grad(u)^t] , grad(psi) > - Operator *opLaplaceEi1 = new Operator(prob->getFeSpace(dow+1+i), prob->getFeSpace(dow+1+j)); - opLaplaceEi1->addTerm(new MatrixIJPhase_SOT(phaseInv, 1-i, 1-j, mu+lambda)); - prob->addMatrixOperator(*opLaplaceEi1, dow+1+i, dow+1+j); - } - - /// < nu*grad(u_i) , grad(psi) > - Operator *opLaplaceUi = new Operator(prob->getFeSpace(i), prob->getFeSpace(i)); - opLaplaceUi->addTerm(new Phase_SOT(phase, viscosity)); - prob->addMatrixOperator(*opLaplaceUi, i, i); - - /// < mu*grad(eta_i) , grad(psi) > - Operator *opLaplaceEi = new Operator(prob->getFeSpace(dow+1+i), prob->getFeSpace(dow+1+i)); - opLaplaceEi->addTerm(new Phase_SOT(phaseInv, mu)); - prob->addMatrixOperator(*opLaplaceEi, dow+1+i, dow+1+i); - - /// < p , d_i(psi) > - Operator *opGradP = new Operator(prob->getFeSpace(i),prob->getFeSpace(dow)); - opGradP->addTerm(new VecAndPartialDerivative_FOT(phase,i, -1.0), GRD_PSI); - prob->addMatrixOperator(*opGradP, i, dow); - Operator *opGradP2 = new Operator(prob->getFeSpace(i),prob->getFeSpace(dow)); - opGradP2->addTerm(new PartialDerivative_ZOT(phase,i, -1.0)); - prob->addMatrixOperator(*opGradP2, i, dow); + for (size_t j = 0; j < dow; ++j) { + /// < nu*[grad(u)+grad(u)^t] , grad(psi) > + Operator *opLaplaceUi1 = new Operator(prob->getFeSpace(i), prob->getFeSpace(j)); + opLaplaceUi1->addTerm(new MatrixIJPhase_SOT(phase, 1-i, 1-j, viscosity)); + prob->addMatrixOperator(*opLaplaceUi1, i, j); + + /// < (mu+lambda)*[grad(u)+grad(u)^t] , grad(psi) > + Operator *opLaplaceEi1 = new Operator(prob->getFeSpace(i), prob->getFeSpace(dow+1+j)); + opLaplaceEi1->addTerm(new MatrixIJPhase_SOT(phaseInv, 1-i, 1-j, mu+lambda)); + prob->addMatrixOperator(*opLaplaceEi1, i, dow+1+j); + } + + /// < nu*grad(u_i) , grad(psi) > + Operator *opLaplaceUi = new Operator(prob->getFeSpace(i), prob->getFeSpace(i)); + opLaplaceUi->addTerm(new Phase_SOT(phase, viscosity)); + prob->addMatrixOperator(*opLaplaceUi, i, i); + + /// < mu*grad(eta_i) , grad(psi) > + Operator *opLaplaceEi = new Operator(prob->getFeSpace(i), prob->getFeSpace(dow+1+i)); + opLaplaceEi->addTerm(new Phase_SOT(phaseInv, mu)); + prob->addMatrixOperator(*opLaplaceEi, i, dow+1+i); + + /// < p , d_i(psi) > + Operator *opGradP = new Operator(prob->getFeSpace(i),prob->getFeSpace(dow)); + opGradP->addTerm(new VecAndPartialDerivative_FOT(phase,i, -1.0), GRD_PSI); + prob->addMatrixOperator(*opGradP, i, dow); + Operator *opGradP2 = new Operator(prob->getFeSpace(i),prob->getFeSpace(dow)); + opGradP2->addTerm(new PartialDerivative_ZOT(phase,i, -1.0)); + prob->addMatrixOperator(*opGradP2, i, dow); } diff --git a/extensions/base_problems/DiffuseDomainFsi.h b/extensions/base_problems/DiffuseDomainFsi.h index f54cb1a2..bcfdeb3a 100644 --- a/extensions/base_problems/DiffuseDomainFsi.h +++ b/extensions/base_problems/DiffuseDomainFsi.h @@ -32,6 +32,7 @@ public: // methods virtual void initData(); virtual void transferInitialSolution(AdaptInfo *adaptInfo); + virtual void initTimestep(AdaptInfo *adaptInfo); virtual void closeTimestep(AdaptInfo *adaptInfo); // === getting/setting methods === @@ -61,6 +62,11 @@ public: // methods phase = phase_; } + void setBcPhase(DOFVector<double>* phase_) + { + bcPhase = phase_; + } + void setEpsilon(double epsilon_) { epsilon = epsilon_; @@ -88,7 +94,6 @@ protected: // variables double epsilon; double alpha; - int laplaceType; int nonLinTerm; double oldTimestep; @@ -103,6 +108,8 @@ protected: // variables DOFVector<double> *phase; DOFVector<double> *phaseInv; + DOFVector<double> *phaseInvDisturbed; + DOFVector<double> *bcPhase; DOFVector<WorldVector<double> >* velocity; diff --git a/extensions/base_problems/LinearElasticity.cc b/extensions/base_problems/LinearElasticity.cc index 05755a5b..2b3e8f3c 100644 --- a/extensions/base_problems/LinearElasticity.cc +++ b/extensions/base_problems/LinearElasticity.cc @@ -1,4 +1,5 @@ #include "LinearElasticity.h" +#include "POperators.h" using namespace std; using namespace AMDiS; @@ -8,6 +9,7 @@ LinearElasticity::LinearElasticity(const std::string &name_) : mu(1.0), lambda(1.0), rho(1.0), + nonLinTerm(2), displacement(NULL) { Parameters::get(name + "->mu", mu); @@ -16,6 +18,9 @@ LinearElasticity::LinearElasticity(const std::string &name_) : force.set(0.0); Parameters::get(name + "->force", force); + + // type of non-linear term: 0... u^old*grad(u_i^old), 1... u'*grad(u_i^old), 2... u^old*grad(u'_i) + Parameters::get(name + "->non-linear term", nonLinTerm); } @@ -69,6 +74,10 @@ void LinearElasticity::fillOperators() { FUNCNAME("LinearElasticity::fillOperators()"); MSG("LinearElasticity::fillOperators()\n"); + WorldVector<DOFVector<double>* > velocity; + for (size_t i = 0; i < dow; i++) + velocity[i] = prob->getSolution()->getDOFVector(i+dow); + // fill operators for prob for (size_t i = 0; i < dow; ++i) { /// dt(u) - v = 0 @@ -86,7 +95,7 @@ void LinearElasticity::fillOperators() } // < v , psi > Operator *opV = new Operator(getFeSpace(i+dow), getFeSpace(i+dow)); - opV->addTerm(new Simple_ZOT(abs(rho) > DBL_TOL ? -1.0/rho : -1.0)); + opV->addTerm(new Simple_ZOT(-1.0)); prob->addMatrixOperator(*opV, i+dow, i+dow); /// dt(v) - mu*div(grad(u)) - (mu+lambda)*grad(div(u)) = F @@ -96,14 +105,43 @@ void LinearElasticity::fillOperators() if (abs(rho) > DBL_TOL) { // < (1/tau)*v_i , psi > Operator *opTimeV = new Operator(getFeSpace(i), getFeSpace(i+dow)); - opTimeV->addTerm(new Simple_ZOT); + opTimeV->addTerm(new Simple_ZOT(rho)); prob->addMatrixOperator(*opTimeV, i, i+dow, getInvTau(), getInvTau()); // < (1/tau)*v_i^old , psi > Operator *opTimeVOld = new Operator(getFeSpace(i)); - opTimeVOld->addTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(i+dow))); + opTimeVOld->addTerm(new Phase_ZOT(prob->getSolution()->getDOFVector(i+dow), rho)); prob->addVectorOperator(*opTimeVOld, i, getInvTau(), getInvTau()); } + + + /// < v^old*grad(v_i^old) , psi > + if (nonLinTerm == 0) { + Operator *opUGradU0 = new Operator(getFeSpace(i), getFeSpace(i+dow)); + opUGradU0->addTerm(new WorldVec_FOT(velocity, -rho), GRD_PHI); + opUGradU0->setUhOld(prob->getSolution()->getDOFVector(i+dow)); + prob->addVectorOperator(*opUGradU0, i); + } + + if (nonLinTerm == 1) { + /// < v*grad(v_i^old) , psi > + for (size_t j = 0; j < dow; ++j) { + Operator *opUGradU1 = new Operator(getFeSpace(i),getFeSpace(j+dow)); + opUGradU1->addTerm(new PartialDerivative_ZOT( + velocity[i], j, rho)); + prob->addMatrixOperator(*opUGradU1, i, j); + } + } else if (nonLinTerm == 2) { + /// < v^old*grad(v_i) , psi > + for(size_t j = 0; j < dow; ++j) { + Operator *opUGradU2 = new Operator(getFeSpace(i),getFeSpace(i+dow)); + opUGradU2->addTerm(new VecAndPartialDerivative_FOT( + velocity[j], j, rho), GRD_PHI); + prob->addMatrixOperator(*opUGradU2, i, i); + } + } + + // < grad(u_i) , grad(psi) > Operator *opDivGradU = new Operator(getFeSpace(i), getFeSpace(i)); opDivGradU->addTerm(new Simple_SOT(mu)); diff --git a/extensions/base_problems/LinearElasticity.h b/extensions/base_problems/LinearElasticity.h index 7db74f0f..b387507c 100644 --- a/extensions/base_problems/LinearElasticity.h +++ b/extensions/base_problems/LinearElasticity.h @@ -45,6 +45,8 @@ protected: // variables double mu; double lambda; double rho; + + int nonLinTerm; WorldVector<double> force; DOFVector<WorldVector<double> >* displacement; diff --git a/extensions/base_problems/NavierStokes_TaylorHood.cc b/extensions/base_problems/NavierStokes_TaylorHood.cc index b8d676bf..fd5db021 100644 --- a/extensions/base_problems/NavierStokes_TaylorHood.cc +++ b/extensions/base_problems/NavierStokes_TaylorHood.cc @@ -172,11 +172,11 @@ void NavierStokes_TaylorHood::fillOperators() } } - for (int j = 0; j < dow; ++j) { - Operator *opNull = new Operator(getFeSpace(i), getFeSpace(j)); - opNull->addTerm(new Simple_ZOT(0.0)); - prob->addMatrixOperator(*opNull, i, j); - } +// for (int j = 0; j < dow; ++j) { +// Operator *opNull = new Operator(getFeSpace(i), getFeSpace(j)); +// opNull->addTerm(new Simple_ZOT(0.0)); +// prob->addMatrixOperator(*opNull, i, j); +// } /// Diffusion-Operator (including Stress-Tensor for space-dependent viscosity addLaplaceTerm(i); -- GitLab