diff --git a/extensions/POperators.cc b/extensions/POperators.cc index 0023fa8bf55d503fee12cab258316f5cd630eaec..91bd2b32f739af40d0fbcc87dc2f1cc9188ef814 100644 --- a/extensions/POperators.cc +++ b/extensions/POperators.cc @@ -827,6 +827,86 @@ void WorldVecPhase_FOT::eval(int nPoints, } }; + +/* ----------------------------------------------------------- */ + +VecAndWorldVec_FOT::VecAndWorldVec_FOT(DOFVector<double>* vec0_, + WorldVector<DOFVector<double>*> vecs_, + AbstractFunction<double, double>* fct_, double fac_) + : FirstOrderTerm(2), vDV(vec0_), fct(fct_), fac(fac_) +{ + numVecs = vecs_.size(); + TEST_EXIT(numVecs == 2 || numVecs == 3) + ("Only Dim=2 or Dim=3 possible\n"); + + for (int i = 0; i < numVecs; i++) { + TEST_EXIT(vecs_[i])("One vector is NULL!\n"); + auxFeSpaces.insert(vecs_[i]->getFeSpace()); + } + + vec0DV = vecs_[0]; + vec1DV = vecs_[1]; + if (numVecs >= 3) + vec2DV = vecs_[2]; +}; +void VecAndWorldVec_FOT::initElement(const ElInfo* elInfo, + SubAssembler* subAssembler, + Quadrature *quad) +{ + getVectorAtQPs(vDV, elInfo, subAssembler, quad, v); + getVectorAtQPs(vec0DV, elInfo, subAssembler, quad, vec0); + getVectorAtQPs(vec1DV, elInfo, subAssembler, quad, vec1); + if (numVecs >= 3) + getVectorAtQPs(vec2DV, elInfo, subAssembler, quad, vec2); +}; +void VecAndWorldVec_FOT::initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler* subAssembler, + Quadrature *quad) +{ + getVectorAtQPs(vDV, smallElInfo, largeElInfo, subAssembler, quad, v); + getVectorAtQPs(vec0DV, smallElInfo, largeElInfo, subAssembler, quad, vec0); + getVectorAtQPs(vec1DV, smallElInfo, largeElInfo, subAssembler, quad, vec1); + if (numVecs >= 3) + getVectorAtQPs(vec2DV, smallElInfo, largeElInfo, subAssembler, quad, vec2); +}; +void VecAndWorldVec_FOT::getLb(const ElInfo *elInfo, + vector<mtl::dense_vector<double> >& result) const +{ + const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda(); + const int nPoints = static_cast<int>(result.size()); + + for (int iq = 0; iq < nPoints; iq++) { + double f = (*fct)(v[iq]); + WorldVector<double> vec; + vec[0] = vec0[iq]; + vec[1] = vec1[iq]; + if (numVecs >= 3) + vec[2] = vec2[iq]; + lb(Lambda, f*vec, result[iq], fac); + } +}; +void VecAndWorldVec_FOT::eval(int nPoints, + const mtl::dense_vector<double>& uhAtQP, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor) +{ + double factor = fac * opFactor; + for (int iq = 0; iq < nPoints; iq++) { + double resultQP = 0.0; + + resultQP += grdUhAtQP[iq][0] * vec0[iq]; + resultQP += grdUhAtQP[iq][1] * vec1[iq]; + if (numVecs >= 3) + resultQP += grdUhAtQP[iq][2] * vec2[iq]; + + result[iq] += factor * resultQP * (*fct)(v[iq]); + } +}; + + + /* ----------------------------------------------------------- */ // vec1*vec2*d/dxi(...) @@ -872,6 +952,164 @@ void VecAndPartialDerivative_FOT::eval(int nPoints, result[iq] += opFactor * vec1[iq] * grdUhAtQP[iq][component] * fac; }; +/* ----------------------------------------------------------- */ + +// vec1*vec2*d/dxi(...) +VecAndPartialDerivativeIJ_FOT::VecAndPartialDerivativeIJ_FOT(DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int i_, + int j_, + double fac_) +: FirstOrderTerm(4), vec1DV(dv1), vec2DV(dv2), fct(NULL), fac(fac_), xi(i_), xj(j_) +{ + auxFeSpaces.insert(vec1DV->getFeSpace()); + auxFeSpaces.insert(vec2DV->getFeSpace()); + + setB(xi); +} + +VecAndPartialDerivativeIJ_FOT::VecAndPartialDerivativeIJ_FOT(DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int i_, + int j_, + BinaryAbstractFunction<double, double, double>* fct_, // = f(v1, d_j(v2)) + double fac_) +: FirstOrderTerm(4), vec1DV(dv1), vec2DV(dv2), fct(fct_), fac(fac_), xi(i_), xj(j_) +{ + auxFeSpaces.insert(vec1DV->getFeSpace()); + auxFeSpaces.insert(vec2DV->getFeSpace()); + + setB(xi); +} + +void VecAndPartialDerivativeIJ_FOT::initElement(const ElInfo* elInfo, + SubAssembler* subAssembler, + Quadrature *quad) +{ + getVectorAtQPs(vec1DV, elInfo, subAssembler, quad, vec1); + getGradientsAtQPs(vec2DV, elInfo, subAssembler, quad, grad); +} + +void VecAndPartialDerivativeIJ_FOT::initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler* subAssembler, + Quadrature *quad) +{ + getVectorAtQPs(vec1DV, smallElInfo, largeElInfo, subAssembler, quad, vec1); + getGradientsAtQPs(vec1DV, smallElInfo, largeElInfo, subAssembler, quad, grad); +} + +void VecAndPartialDerivativeIJ_FOT::getLb(const ElInfo *elInfo, + vector<mtl::dense_vector<double> >& result) const +{ + const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda(); + const int nPoints = static_cast<int>(result.size()); + + if (fct == NULL) { + for(int iq = 0; iq < nPoints; iq++) { + lb_one(Lambda, result[iq], vec1[iq] * grad[iq][xj] * fac); + } + } else { + for(int iq = 0; iq < nPoints; iq++) { + lb_one(Lambda, result[iq], (*fct)(vec1[iq], grad[iq][xj]) * fac); + } + } +} + +void VecAndPartialDerivativeIJ_FOT::eval(int nPoints, + const mtl::dense_vector<double>& uhAtQP, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor) +{ + if (fct == NULL) { + for(int iq = 0; iq < nPoints; iq++) + result[iq] += opFactor * vec1[iq] * grad[iq][xj] * grdUhAtQP[iq][xi] * fac; + } else { + for(int iq = 0; iq < nPoints; iq++) + result[iq] += opFactor * (*fct)(vec1[iq], grad[iq][xj]) * grdUhAtQP[iq][xi] * fac; + } +} + + +/* ----------------------------------------------------------- */ + +// vec1*vec2*d/dxi(...) +Vec2AndPartialDerivative_FOT::Vec2AndPartialDerivative_FOT( + DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int component_, + double fac_) +: FirstOrderTerm(3), vec1DV(dv1), vec2DV(dv2), fct(NULL), fac(fac_), component(component_) +{ + auxFeSpaces.insert(vec1DV->getFeSpace()); + auxFeSpaces.insert(vec2DV->getFeSpace()); + + setB(component); +} + + +Vec2AndPartialDerivative_FOT::Vec2AndPartialDerivative_FOT( + DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int component_, + BinaryAbstractFunction<double, double, double>* fct_, // = f(v1, v2) + double fac_) +: FirstOrderTerm(3), vec1DV(dv1), vec2DV(dv2), fct(fct_), fac(fac_), component(component_) +{ + auxFeSpaces.insert(vec1DV->getFeSpace()); + auxFeSpaces.insert(vec2DV->getFeSpace()); + + setB(component); +} + +void Vec2AndPartialDerivative_FOT::initElement(const ElInfo* elInfo, + SubAssembler* subAssembler, + Quadrature *quad) +{ + getVectorAtQPs(vec1DV, elInfo, subAssembler, quad, vec1); + getVectorAtQPs(vec2DV, elInfo, subAssembler, quad, vec2); +} + +void Vec2AndPartialDerivative_FOT::initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler* subAssembler, + Quadrature *quad) +{ + getVectorAtQPs(vec1DV, smallElInfo, largeElInfo, subAssembler, quad, vec1); + getVectorAtQPs(vec2DV, smallElInfo, largeElInfo, subAssembler, quad, vec2); +} + +void Vec2AndPartialDerivative_FOT::getLb(const ElInfo *elInfo, + vector<mtl::dense_vector<double> >& result) const +{ + const DimVec<WorldVector<double> > &Lambda = elInfo->getGrdLambda(); + const int nPoints = static_cast<int>(result.size()); + + if (fct == NULL) { + for(int iq = 0; iq < nPoints; iq++) + lb_one(Lambda, result[iq], vec1[iq] * vec2[iq] * fac); + } else { + for(int iq = 0; iq < nPoints; iq++) + lb_one(Lambda, result[iq], (*fct)(vec1[iq], vec2[iq]) * fac); + } +}; +void Vec2AndPartialDerivative_FOT::eval(int nPoints, + const mtl::dense_vector<double>& uhAtQP, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor) +{ + if (fct == NULL) { + for(int iq = 0; iq < nPoints; iq++) + result[iq] += opFactor * vec1[iq] * vec2[iq] * grdUhAtQP[iq][component] * fac; + } else { + for(int iq = 0; iq < nPoints; iq++) + result[iq] += opFactor * (*fct)(vec1[iq], vec2[iq]) * grdUhAtQP[iq][component] * fac; + } +}; + + /* ----------------------------------------------------------- */ // vec1*vec2*d/dxi(...) @@ -1161,6 +1399,27 @@ VecAndPartialDerivative_ZOT::VecAndPartialDerivative_ZOT(DOFVectorBase<double> * vecDV(vecDV_), gradDV(gradDV_), component(component_), + fct(NULL), + fac(fac_) +{ + TEST_EXIT(vecDV_)("No value vector!\n"); + TEST_EXIT(gradDV_)("No gradient vector!\n"); + + auxFeSpaces.insert(vecDV_->getFeSpace()); + auxFeSpaces.insert(gradDV_->getFeSpace()); +} + + +VecAndPartialDerivative_ZOT::VecAndPartialDerivative_ZOT(DOFVectorBase<double> *vecDV_, + DOFVectorBase<double> *gradDV_, + int component_, + AbstractFunction<double, double>* fct_, + double fac_) +: ZeroOrderTerm(2), + vecDV(vecDV_), + gradDV(gradDV_), + component(component_), + fct(fct_), fac(fac_) { TEST_EXIT(vecDV_)("No value vector!\n"); @@ -1192,8 +1451,14 @@ void VecAndPartialDerivative_ZOT::initElement(const ElInfo* largeElInfo, void VecAndPartialDerivative_ZOT::getC(const ElInfo *, int nPoints, ElementVector &C) { - for (int iq = 0; iq < nPoints; iq++) - C[iq] += vec[iq] * grad[iq][component] * fac; + if (fct == NULL) { + for (int iq = 0; iq < nPoints; iq++) + C[iq] += vec[iq] * grad[iq][component] * fac; + } else { + for (int iq = 0; iq < nPoints; iq++) + C[iq] += (*fct)(vec[iq]) * grad[iq][component] * fac; + } + } @@ -1205,42 +1470,73 @@ void VecAndPartialDerivative_ZOT::eval(int nPoints, double opFactor) { double fac_ = fac * opFactor; - for (int iq = 0; iq < nPoints; iq++) - result[iq] += vec[iq] * grad[iq][component] * uhAtQP[iq] * fac_; + if (fct == NULL) { + for (int iq = 0; iq < nPoints; iq++) + result[iq] += vec[iq] * grad[iq][component] * uhAtQP[iq] * fac_; + } else { + for (int iq = 0; iq < nPoints; iq++) + result[iq] += (*fct)(vec[iq]) * grad[iq][component] * uhAtQP[iq] * fac_; + } } /* ----------------------------------------------------------- */ -Vec2AndPartialDerivative_ZOT::Vec2AndPartialDerivative_ZOT(DOFVectorBase<double> *vec1DV_, DOFVectorBase<double> *vec2DV_, DOFVectorBase<double> *gradDV_,int component_, double fac_) - : ZeroOrderTerm(3), vec1DV(vec1DV_), vec2DV(vec2DV_), gradDV(gradDV_), fac(fac_), component(component_) +Vec2AndPartialDerivative_ZOT::Vec2AndPartialDerivative_ZOT(DOFVectorBase<double> *vec1DV_, + DOFVectorBase<double> *vec2DV_, + DOFVectorBase<double> *gradDV_, + int component_, + double fac_) + : ZeroOrderTerm(3), vec1DV(vec1DV_), vec2DV(vec2DV_), gradDV(gradDV_), fct(NULL), fac(fac_), component(component_) { - TEST_EXIT(vec1DV_)("No first vector!\n"); - TEST_EXIT(vec2DV_)("No second vector!\n"); - TEST_EXIT(gradDV_)("No gradient vector!\n"); - auxFeSpaces.insert(vec1DV_->getFeSpace()); - auxFeSpaces.insert(vec2DV_->getFeSpace()); - auxFeSpaces.insert(gradDV_->getFeSpace()); + TEST_EXIT(vec1DV_)("No first vector!\n"); + TEST_EXIT(vec2DV_)("No second vector!\n"); + TEST_EXIT(gradDV_)("No gradient vector!\n"); + auxFeSpaces.insert(vec1DV_->getFeSpace()); + auxFeSpaces.insert(vec2DV_->getFeSpace()); + auxFeSpaces.insert(gradDV_->getFeSpace()); +}; + +Vec2AndPartialDerivative_ZOT::Vec2AndPartialDerivative_ZOT(DOFVectorBase<double> *vec1DV_, + DOFVectorBase<double> *vec2DV_, + DOFVectorBase<double> *gradDV_, + int component_, + BinaryAbstractFunction<double, double, double>* fct_, + double fac_) + : ZeroOrderTerm(3), vec1DV(vec1DV_), vec2DV(vec2DV_), gradDV(gradDV_), fct(fct_), fac(fac_), component(component_) +{ + TEST_EXIT(vec1DV_)("No first vector!\n"); + TEST_EXIT(vec2DV_)("No second vector!\n"); + TEST_EXIT(gradDV_)("No gradient vector!\n"); + auxFeSpaces.insert(vec1DV_->getFeSpace()); + auxFeSpaces.insert(vec2DV_->getFeSpace()); + auxFeSpaces.insert(gradDV_->getFeSpace()); }; + void Vec2AndPartialDerivative_ZOT::initElement(const ElInfo* elInfo, SubAssembler* subAssembler, Quadrature *quad) { - getVectorAtQPs(vec1DV, elInfo, subAssembler, quad, vec1); - getVectorAtQPs(vec2DV, elInfo, subAssembler, quad, vec2); - getGradientsAtQPs(gradDV, elInfo, subAssembler, quad, grad); + getVectorAtQPs(vec1DV, elInfo, subAssembler, quad, vec1); + getVectorAtQPs(vec2DV, elInfo, subAssembler, quad, vec2); + getGradientsAtQPs(gradDV, elInfo, subAssembler, quad, grad); }; void Vec2AndPartialDerivative_ZOT::initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, SubAssembler* subAssembler, Quadrature *quad) { - getVectorAtQPs(vec1DV, smallElInfo, largeElInfo, subAssembler, quad, vec1); - getVectorAtQPs(vec2DV, smallElInfo, largeElInfo, subAssembler, quad, vec2); - getGradientsAtQPs(gradDV, smallElInfo, largeElInfo, subAssembler, quad, grad); + getVectorAtQPs(vec1DV, smallElInfo, largeElInfo, subAssembler, quad, vec1); + getVectorAtQPs(vec2DV, smallElInfo, largeElInfo, subAssembler, quad, vec2); + getGradientsAtQPs(gradDV, smallElInfo, largeElInfo, subAssembler, quad, grad); }; void Vec2AndPartialDerivative_ZOT::getC(const ElInfo *, int nPoints, ElementVector &C) { - for (int iq = 0; iq < nPoints; iq++) - C[iq] += vec1[iq]*vec2[iq]*grad[iq][component]*fac; + if (fct == NULL) { + for (int iq = 0; iq < nPoints; iq++) + C[iq] += vec1[iq]*vec2[iq]*grad[iq][component]*fac; + } else { + for (int iq = 0; iq < nPoints; iq++) + C[iq] += (*fct)(vec1[iq],vec2[iq])*grad[iq][component]*fac; + } }; void Vec2AndPartialDerivative_ZOT::eval(int nPoints, const mtl::dense_vector<double>& uhAtQP, @@ -1249,9 +1545,15 @@ void Vec2AndPartialDerivative_ZOT::eval(int nPoints, mtl::dense_vector<double>& result, double opFactor) { - for (int iq = 0; iq < nPoints; iq++) { - result[iq] += (vec1[iq] * vec2[iq]) * grad[iq][component] * uhAtQP[iq] * opFactor * fac; - } + if (fct == NULL) { + for (int iq = 0; iq < nPoints; iq++) { + result[iq] += (vec1[iq] * vec2[iq]) * grad[iq][component] * uhAtQP[iq] * opFactor * fac; + } + } else { + for (int iq = 0; iq < nPoints; iq++) { + result[iq] += (*fct)(vec1[iq], vec2[iq]) * grad[iq][component] * uhAtQP[iq] * opFactor * fac; + } + } }; /* ----------------------------------------------------------- */ diff --git a/extensions/POperators_FOT.h b/extensions/POperators_FOT.h index af232352f38032ed3e175b2fdc75a649eb9a7659..c496b92837f494f28d53821cb9faec4ad0bf3e16 100644 --- a/extensions/POperators_FOT.h +++ b/extensions/POperators_FOT.h @@ -180,6 +180,45 @@ double fac; int numVecs; }; + + +/* -------------------------------------------------------------- */ + +/// < f(vec0)*vecs*grad(u) , psi > or < f(vec0)*vecs*u , grad(psi) > where vecs in R^n +struct VecAndWorldVec_FOT : FirstOrderTerm +{ + VecAndWorldVec_FOT(DOFVector<double>* vec0, + WorldVector<DOFVector<double>*> vecs, + AbstractFunction<double, double>* fct, + double fac = 1.0); + + void initElement(const ElInfo*, + SubAssembler*, + Quadrature *quad= NULL); + + void initElement(const ElInfo* largeElInfo, + const ElInfo* smallElInfo, + SubAssembler*, + Quadrature *quad = NULL); + + void getLb(const ElInfo *elInfo, + vector<mtl::dense_vector<double> >& result) const; + + void eval(int nPoints, + const mtl::dense_vector<double>&, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor); + +private: + DOFVector<double> *vDV, *vec0DV, *vec1DV, *vec2DV; + mtl::dense_vector<double> v, vec0, vec1, vec2; + AbstractFunction<double, double>* fct; + double fac; + int numVecs; +}; + /* -------------------------------------------------------------- */ /// < factor*d_i(u) , psi > or < factor*u , d_i(psi) > @@ -242,6 +281,96 @@ mtl::dense_vector<double> vec1; double fac; int component; }; + +/* -------------------------------------------------------------- */ + +/// < d_i(u) * factor*v1*d_j(v2) , psi > or < u * factor*v1*d_j(v2) , d_i(psi) > +struct VecAndPartialDerivativeIJ_FOT : FirstOrderTerm +{ + VecAndPartialDerivativeIJ_FOT(DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int i_, + int j_, + double fac_ = 1.0); + + VecAndPartialDerivativeIJ_FOT(DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int i_, + int j_, + BinaryAbstractFunction<double, double, double>* fct, // = f(v1, d_j(v2)) + double fac_ = 1.0); + + void initElement(const ElInfo* elInfo, + SubAssembler* subAssembler, + Quadrature *quad = NULL); + + void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler* subAssembler, + Quadrature *quad = NULL); + + void getLb(const ElInfo *elInfo, vector<mtl::dense_vector<double> >& result) const; + + void eval(int nPoints, + const mtl::dense_vector<double>&, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor); + +private: + DOFVectorBase<double>* vec1DV; + DOFVectorBase<double>* vec2DV; + mtl::dense_vector<double> vec1; + mtl::dense_vector<WorldVector<double> > grad; + BinaryAbstractFunction<double, double, double>* fct; + double fac; + int xi, xj; +}; + + +/* -------------------------------------------------------------- */ + +/// < factor*v1*v2*d_i(u) , psi > or < factor*v1*v2*u , d_i(psi) > +struct Vec2AndPartialDerivative_FOT : public FirstOrderTerm +{ + Vec2AndPartialDerivative_FOT(DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int component_, + double fac_=1.0); + + Vec2AndPartialDerivative_FOT(DOFVectorBase<double> *dv1, + DOFVectorBase<double> *dv2, + int component_, + BinaryAbstractFunction<double, double, double>* fct, // = f(v1, v2) + double fac_=1.0); + + void initElement(const ElInfo* elInfo, + SubAssembler* subAssembler, + Quadrature *quad = NULL); + + void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler* subAssembler, + Quadrature *quad = NULL); + + void getLb(const ElInfo *elInfo, vector<mtl::dense_vector<double> >& result) const; + + void eval(int nPoints, + const mtl::dense_vector<double>&, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor); + +private: + DOFVectorBase<double>* vec1DV; + DOFVectorBase<double>* vec2DV; + mtl::dense_vector<double> vec1,vec2; + BinaryAbstractFunction<double, double, double>* fct; + double fac; + int component; +}; + + /* -------------------------------------------------------------- */ diff --git a/extensions/POperators_ZOT.h b/extensions/POperators_ZOT.h index 6671c8133f2004da8d44219755efa33f5e040b2d..8a950b2af8d8eb898b2e1ba1c9000f4cc30e3029 100644 --- a/extensions/POperators_ZOT.h +++ b/extensions/POperators_ZOT.h @@ -336,65 +336,87 @@ int component, component2; /* -------------------------------------------------------------- */ /// < factor*v*d_i(w)*u , psi > -class VecAndPartialDerivative_ZOT : public ZeroOrderTerm +struct VecAndPartialDerivative_ZOT : ZeroOrderTerm { -public: -VecAndPartialDerivative_ZOT(DOFVectorBase<double>* vecDV_, DOFVectorBase<double>* gradDV_, int component_, double fac_=1.0); - -void initElement(const ElInfo*, - SubAssembler*, - Quadrature *quad= NULL); -void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, - SubAssembler*, - Quadrature *quad = NULL); - -void getC(const ElInfo *, int nPoints, ElementVector &C); - -void eval(int nPoints, - const mtl::dense_vector<double>&, - const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, - const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, - mtl::dense_vector<double>& result, - double opFactor); - -protected: -DOFVectorBase<double> *vecDV, *gradDV; -mtl::dense_vector<double> vec; -double fac; -mtl::dense_vector<WorldVector<double> > grad; -int component; + VecAndPartialDerivative_ZOT(DOFVectorBase<double>* vecDV_, + DOFVectorBase<double>* gradDV_, + int component_, + double fac_ = 1.0); + + VecAndPartialDerivative_ZOT(DOFVectorBase<double>* vecDV_, + DOFVectorBase<double>* gradDV_, + int component_, + AbstractFunction<double, double>* fct, // f(v) + double fac_ = 1.0); + + void initElement(const ElInfo*, + SubAssembler*, + Quadrature *quad= NULL); + + void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler*, + Quadrature *quad = NULL); + + void getC(const ElInfo *, int nPoints, ElementVector &C); + + void eval(int nPoints, + const mtl::dense_vector<double>&, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor); + +private: + DOFVectorBase<double> *vecDV, *gradDV; + mtl::dense_vector<double> vec; + AbstractFunction<double, double>* fct; + double fac; + mtl::dense_vector<WorldVector<double> > grad; + int component; }; /* -------------------------------------------------------------- */ /// < factor*v1*v2*d_i(w)*u , psi > -class Vec2AndPartialDerivative_ZOT : public ZeroOrderTerm +struct Vec2AndPartialDerivative_ZOT : ZeroOrderTerm { -public: -Vec2AndPartialDerivative_ZOT(DOFVectorBase<double>* vec1DV_, DOFVectorBase<double>* vec2DV_, DOFVectorBase<double>* gradDV_, int component_, double fac_=1.0); - -void initElement(const ElInfo*, - SubAssembler*, - Quadrature *quad= NULL); -void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, - SubAssembler*, - Quadrature *quad = NULL); - -void getC(const ElInfo *, int nPoints, ElementVector &C); - -void eval(int nPoints, - const mtl::dense_vector<double>&, - const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, - const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, - mtl::dense_vector<double>& result, - double opFactor); - -protected: -DOFVectorBase<double> *vec1DV, *vec2DV, *gradDV; -mtl::dense_vector<double> vec1, vec2; -double fac; -mtl::dense_vector<WorldVector<double> > grad; -int component; + Vec2AndPartialDerivative_ZOT(DOFVectorBase<double>* vec1DV_, + DOFVectorBase<double>* vec2DV_, + DOFVectorBase<double>* gradDV_, + int component_, + double fac_ = 1.0); + + Vec2AndPartialDerivative_ZOT(DOFVectorBase<double>* vec1DV_, + DOFVectorBase<double>* vec2DV_, + DOFVectorBase<double>* gradDV_, + int component_, + BinaryAbstractFunction<double, double, double>* fct, + double fac_ = 1.0); + + void initElement(const ElInfo*, + SubAssembler*, + Quadrature *quad= NULL); + + void initElement(const ElInfo* largeElInfo, const ElInfo* smallElInfo, + SubAssembler*, + Quadrature *quad = NULL); + + void getC(const ElInfo *, int nPoints, ElementVector &C); + + void eval(int nPoints, + const mtl::dense_vector<double>&, + const mtl::dense_vector<WorldVector<double> >& grdUhAtQP, + const mtl::dense_vector<WorldMatrix<double> >& D2UhAtQP, + mtl::dense_vector<double>& result, + double opFactor); + +private: + DOFVectorBase<double> *vec1DV, *vec2DV, *gradDV; + mtl::dense_vector<double> vec1, vec2; + BinaryAbstractFunction<double, double, double>* fct; + double fac; + mtl::dense_vector<WorldVector<double> > grad; + int component; }; /* -------------------------------------------------------------- */ diff --git a/extensions/SignedDistFunctors.h b/extensions/SignedDistFunctors.h index 0d35e9c715adbae345fb8a1b589999685e6720eb..821e83f3571c66a8dee716f58f655a8ded84775d 100644 --- a/extensions/SignedDistFunctors.h +++ b/extensions/SignedDistFunctors.h @@ -247,17 +247,17 @@ class Plane : public AbstractFunction<double, WorldVector<double> > { public: - Plane(double shift_, double factor_=1.0) : - shift(shift_), factor(factor_) {} + Plane(double shift_, double factor_=1.0, int component_=1) : + shift(shift_), factor(factor_), component(component_) {} double operator()(const WorldVector<double>& x) const { - return factor*(shift-x[1]); + return factor*(shift-x[component]); }; private: double shift; - int comp; + int component; double factor; }; diff --git a/extensions/base_problems/BaseProblem_RB.h b/extensions/base_problems/BaseProblem_RB.h index b395524d4cc020c8e7a3dfe6fac47f31379b4dd5..2ab0c40e9441c167ee637297a92cb9043fa62353 100644 --- a/extensions/base_problems/BaseProblem_RB.h +++ b/extensions/base_problems/BaseProblem_RB.h @@ -30,7 +30,7 @@ public: void setRosenbrockMethod(RosenbrockMethod *method) { prob->setRosenbrockMethod(method); } void setTau(double *ptr) { prob->setTau(ptr); } - void setTauGamma(double *ptr0, double *ptr1, double *ptr2, double *ptr3) { prob->setTauGamma(ptr0,ptr1,ptr2,ptr3); } + void setTauGamma(double *ptr0, double *ptr1, double *ptr2, double *ptr3, double *ptr4) { prob->setTauGamma(ptr0,ptr1,ptr2,ptr3,ptr4); } double* getTauGamma() { return prob->getTauGamma(); } double* getMinusTauGamma() { return prob->getMinusTauGamma(); } diff --git a/extensions/base_problems/CahnHilliardNavierStokes.cc b/extensions/base_problems/CahnHilliardNavierStokes.cc index c194ad5abbf7664c03653a67556b894d4e719d84..aabe82027c4aa1663af89794d93fd75861cd659a 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes.cc +++ b/extensions/base_problems/CahnHilliardNavierStokes.cc @@ -59,7 +59,7 @@ CahnHilliardNavierStokes::CahnHilliardNavierStokes(const std::string &name_) : // 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; + surfaceTension = -sigma*3.0/(2.0*sqrt(2.0)) / eps; force.set(0.0); diff --git a/extensions/base_problems/CahnHilliardNavierStokes_RB.cc b/extensions/base_problems/CahnHilliardNavierStokes_RB.cc index 70a1b7be0896a9a7c4076892e003ae72d2535506..9a23aead05689a10c600ed2798ba7d5f7cff45c6 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes_RB.cc +++ b/extensions/base_problems/CahnHilliardNavierStokes_RB.cc @@ -59,7 +59,7 @@ CahnHilliardNavierStokes_RB::CahnHilliardNavierStokes_RB(const std::string &name // 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; + surfaceTension = -sigma*3.0/(2.0*sqrt(2.0)) / eps; force.set(0.0); @@ -148,35 +148,43 @@ void CahnHilliardNavierStokes_RB::fillOperators() opChLM->addTerm(new VecAtQP_SOT( prob->getUnVec(0), new MobilityCH0(gamma))); - opChLM->addTerm(new VecGrad_FOT( + prob->addMatrixOperator(*opChLM, 0, 1); + + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChLM2->addTerm(new VecGrad_FOT( prob->getUnVec(0), prob->getUnVec(1), new MobilityCH0Diff(gamma)), GRD_PSI); - prob->addMatrixOperator(*opChLM, 0, 1); + prob->addMatrixOperator(*opChLM2, 0, 0); + // rhs operators - Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); - opChLM2->addTerm(new VecAtQP_SOT( + Operator *opChLMe = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLMe->addTerm(new VecAtQP_SOT( prob->getStageSolution(0), new MobilityCH0(gamma))); - opChLM2->setUhOld(prob->getStageSolution(1)); - prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); - } else { + opChLMe->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLMe, 0, &minus1, &minus1); + } else if (doubleWell == 1) { // jacobian operators opChLM->addTerm(new VecAtQP_SOT( prob->getUnVec(0), new MobilityCH1(gamma))); - opChLM->addTerm(new VecGrad_FOT( + prob->addMatrixOperator(*opChLM, 0, 1); + + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChLM2->addTerm(new VecGrad_FOT( prob->getUnVec(0), prob->getUnVec(1), new MobilityCH1Diff(gamma)), GRD_PSI); - prob->addMatrixOperator(*opChLM, 0, 1); + prob->addMatrixOperator(*opChLM2, 0, 0); + // rhs operators - Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); - opChLM2->addTerm(new VecAtQP_SOT( + Operator *opChLMe = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLMe->addTerm(new VecAtQP_SOT( prob->getStageSolution(0), new MobilityCH1(gamma))); - opChLM2->setUhOld(prob->getStageSolution(1)); - prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + opChLMe->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLMe, 0, &minus1, &minus1); } } else { opChLM->addTerm(new Simple_SOT(gamma)); @@ -319,7 +327,7 @@ void CahnHilliardNavierStokes_RB::fillOperators() /// < 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(1), prob->getStageSolution(0), i)); prob->addVectorOperator(*opMuGradC, 2+i, &surfaceTension, &surfaceTension); } @@ -347,8 +355,8 @@ void CahnHilliardNavierStokes_RB::addLaplaceTerm(int i) 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); + opLaplaceUi1->setUhOld(prob->getStageSolution(2+j)); + prob->addVectorOperator(*opLaplaceUi1, 2+i, &minus1, &minus1); } } diff --git a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.cc b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.cc new file mode 100644 index 0000000000000000000000000000000000000000..e77b6244f6505337765cdc557e96f13a5b878736 --- /dev/null +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.cc @@ -0,0 +1,436 @@ +#include "CahnHilliardNavierStokes_TwoPhase.h" +#include "Views.h" +#include "SignedDistFunctors.h" +#include "PhaseFieldConvert.h" +#include "POperators.h" + +using namespace AMDiS; + +CahnHilliardNavierStokes_TwoPhase::CahnHilliardNavierStokes_TwoPhase(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); + + // 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; + + MSG("surface tension: %e\n", surfaceTension); + + 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::~CahnHilliardNavierStokes_TwoPhase() +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::~CahnHilliardNavierStokes_TwoPhase()"); + + if (reinit != NULL) { + delete reinit; + reinit = NULL; + } + if (velocity != NULL) { + delete velocity; + velocity = NULL; + } + delete fileWriter; + fileWriter = NULL; +} + + +void CahnHilliardNavierStokes_TwoPhase::initData() +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::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::transferInitialSolution(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::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::fillOperators() +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::fillOperators()"); + MSG("CahnHilliardNavierStokes_TwoPhase::fillOperators()\n"); + + // variable order: + // (c, mu, u0, u1 [, u2], p) + + WorldVector<DOFVector<double>* > vel; + for (size_t i = 0; i < dow; i++) + vel[i] = prob->getSolution()->getDOFVector(2+i); + + + // dt(c) = laplace(mu) - u*grad(c) + // ----------------------------------- + /// < phi*c/tau , psi > + Operator *opChMnew = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChMnew->addZeroOrderTerm(new Simple_ZOT); + prob->addMatrixOperator(*opChMnew, 0, 0, getInvTau()); + + /// < phi*c^old/tau , psi > + Operator *opChMold = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChMold->addZeroOrderTerm(new VecAtQP_ZOT(prob->getSolution()->getDOFVector(0))); + prob->addVectorOperator(*opChMold,0, getInvTau()); + + /// < phi*grad(mu) , grad(psi) > + // 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) + opChLM->addSecondOrderTerm(new VecAtQP_SOT( + prob->getSolution()->getDOFVector(0), + new MobilityCH0(gamma))); + else + opChLM->addSecondOrderTerm(new VecAtQP_SOT( + prob->getSolution()->getDOFVector(0), + new MobilityCH1(gamma))); + } else + opChLM->addSecondOrderTerm(new Simple_SOT(gamma)); + prob->addMatrixOperator(*opChLM, 0, 1); + + /// < u_old * grad(c) - u_old * grad(c_old), psi > + Operator *uGradC = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + 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); + + /// < u * grad(c_old) , psi > + for (size_t i = 0; i < dow; i++) { + Operator *uGradC2 = new Operator(prob->getFeSpace(0), prob->getFeSpace(0)); + if (useConservationForm) + uGradC2->addTerm(new VecAndPartialDerivative_FOT(prob->getSolution()->getDOFVector(0), i, -1.0), GRD_PSI); + else { + uGradC2->addTerm(new PartialDerivative_ZOT(prob->getSolution()->getDOFVector(0), i)); + } + prob->addMatrixOperator(*uGradC2, 0, 2+i); + } + + + // mu + eps^2*laplace(c) + c - 3*(c_old^2)*c = -2*c_old^3 [+ BC] + // ---------------------------------------------------------------------- + /// < -3*phi*c*c_old^2 , psi > + // -3*c_old^2 * c + Operator *opChWImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChWImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getSolution()->getDOFVector(0), + (doubleWell == 0 ? static_cast<AbstractFunction<double, double>*>(new DoubleWell0Diff(-1.0)) + : static_cast<AbstractFunction<double, double>*>(new DoubleWell1Diff(-1.0))))); + prob->addMatrixOperator(*opChWImpl, 1, 0); + + /// < -2*phi*c_old^3 , psi > + // -2*c_old^3 + 3/2*c_old^2 + Operator *opChWExpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChWExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getSolution()->getDOFVector(0), + new Pow3Functor(-2.0))); + if (doubleWell == 0) { + opChWExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getSolution()->getDOFVector(0), + new Pow2Functor(3.0/2.0))); + } + prob->addVectorOperator(*opChWExpl, 1); + + /// < -eps^2*phi*grad(c) , grad(psi) > + Operator *opChL = new Operator(prob->getFeSpace(1),prob->getFeSpace(0)); + opChL->addSecondOrderTerm(new Simple_SOT); + prob->addMatrixOperator(*opChL, 1, 0, &minusEpsSqr); + + /// < phi*mu , psi > + Operator *opChM = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChM->addZeroOrderTerm(new Simple_ZOT); + prob->addMatrixOperator(*opChM, 1, 1); + + // ----------------------------------------------------------------------------------- + for (size_t i = 0; i < dow; ++i) { + if (abs(density1 - density2) > FLT_TOL) + addMaterialDerivativeNonConst(i); + else + addMaterialDerivativeConst(i); + + /// Diffusion-Operator (including Stress-Tensor for space-dependent viscosity) + if (abs(viscosity1 - viscosity2) > FLT_TOL) + addLaplaceTermNonConst(i); + else + addLaplaceTermConst(i); + + /// < p , d_i(psi) > + Operator *opGradP = new Operator(getFeSpace(2+i),getFeSpace(2+dow)); + opGradP->addTerm(new PartialDerivative_FOT(i, -1.0), GRD_PSI); + prob->addMatrixOperator(*opGradP, 2+i, 2+dow); + + /// 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 *opMuGradC = new Operator(getFeSpace(2+i),getFeSpace(0)); + opMuGradC->addTerm(new VecAndPartialDerivative_FOT( + prob->getSolution()->getDOFVector(1), i, -1.0), 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, -1.0)); + 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); + } + + /// 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); + } +} + + +void CahnHilliardNavierStokes_TwoPhase::addMaterialDerivativeConst(int i) +{ + WorldVector<DOFVector<double>* > vel; + for (size_t j = 0; j < dow; j++) + vel[j] = prob->getSolution()->getDOFVector(2+j); + + /// < (1/tau)*u'_i , psi > + Operator *opTime = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opTime->addTerm(new Simple_ZOT(density1)); + 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)); + opTimeOld->addTerm(new Phase_ZOT(prob->getSolution()->getDOFVector(2+i), density1)); + prob->addVectorOperator(*opTimeOld, 2+i, getInvTau(), getInvTau()); + + /// < u^old*grad(u_i^old) , psi > + 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)*density1), + GRD_PHI); + opUGradU0->setUhOld(prob->getSolution()->getDOFVector(2+i)); + prob->addVectorOperator(*opUGradU0, 2+i); + } + 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, density1)); + prob->addMatrixOperator(*opUGradU1, 2+i, 2+j); + } + } + 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( + prob->getSolution()->getDOFVector(2+j), j, density1), GRD_PHI); + prob->addMatrixOperator(*opUGradU2, 2+i, 2+i); + } + } +} + + +void CahnHilliardNavierStokes_TwoPhase::addMaterialDerivativeNonConst(int i) +{ + WorldVector<DOFVector<double>* > vel; + for (size_t j = 0; j < dow; j++) + vel[j] = prob->getSolution()->getDOFVector(2+j); + + /// < (1/tau)*u'_i , psi > + Operator *opTime = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opTime->addTerm(new VecAtQP_ZOT( + prob->getSolution()->getDOFVector(0), + new LinearInterpolation(density1, density2))); + prob->addMatrixOperator(*opTime, 2+i, 2+i, getInvTau(), getInvTau()); + /// < (1/tau)*u_i^old , psi > + opTime->setUhOld(prob->getSolution()->getDOFVector(2+i)); + prob->addVectorOperator(*opTime, 2+i, getInvTau(), getInvTau()); + + /// < (rho(c^old) + c^old*rho'(c^old)) * u^old*grad(u_i^old) , psi > + for(size_t j = 0; j < dow; ++j) { + Operator *opCUGradU = new Operator(getFeSpace(2+i),getFeSpace(2+i)); + opCUGradU->addTerm(new Vec2AndPartialDerivative_FOT( + prob->getSolution()->getDOFVector(0), + prob->getSolution()->getDOFVector(2+j), + j, + new TaylorExpansionFactor(density1, density2)), GRD_PHI); + opCUGradU->setUhOld(prob->getSolution()->getDOFVector(2+i)); + prob->addVectorOperator(*opCUGradU, 2+i); + } + + /// < rho(c^old)*u*grad(u_i^old) , psi > + for (size_t j = 0; j < dow; ++j) { + Operator *opUGradU1 = new Operator(getFeSpace(2+i),getFeSpace(2+j)); + opUGradU1->addTerm(new VecAndPartialDerivative_ZOT( + prob->getSolution()->getDOFVector(0), + prob->getSolution()->getDOFVector(2+i), + j, + new LinearInterpolation(density1, density2))); + prob->addMatrixOperator(*opUGradU1, 2+i, 2+j); + } + + /// < rho(c^old)*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 Vec2AndPartialDerivative_FOT( + prob->getSolution()->getDOFVector(0), + prob->getSolution()->getDOFVector(2+j), + j, + new LinearInterpolationFactor(density1, density2)), GRD_PHI); + prob->addMatrixOperator(*opUGradU2, 2+i, 2+i); + } + + /// < c * rho'(c^old) * u^old*grad(u_i^old) , psi > + for(size_t j = 0; j < dow; ++j) { + Operator *opCUGradU2 = new Operator(getFeSpace(2+i),getFeSpace(0)); + opCUGradU2->addTerm(new Vec2AndPartialDerivative_ZOT( + prob->getSolution()->getDOFVector(0), + prob->getSolution()->getDOFVector(2+j), + prob->getSolution()->getDOFVector(2+i), + j, + new LinearInterpolationDiffFactor(density1, density2))); + prob->addMatrixOperator(*opCUGradU2, 2+i, 0); + } +} + + +void CahnHilliardNavierStokes_TwoPhase::addLaplaceTermConst(int i) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::addLaplaceTerm()"); + + /// < alpha*[grad(u)+grad(u)^t] , grad(psi) > + if (laplaceType == 1) { + for (size_t j = 0; j < dow; ++j) { + Operator *opLaplaceUi1 = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opLaplaceUi1->addTerm(new MatrixIJ_SOT(1-i, 1-j, viscosity1)); + prob->addMatrixOperator(*opLaplaceUi1, 2+i, 2+j); + } + } + + /// < alpha*grad(u'_i) , grad(psi) > + Operator *opLaplaceUi = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opLaplaceUi->addTerm(new Simple_SOT(viscosity1)); + prob->addMatrixOperator(*opLaplaceUi, 2+i, 2+i); +} + + +void CahnHilliardNavierStokes_TwoPhase::addLaplaceTermNonConst(int i) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::addLaplaceTerm()"); + + /// < alpha*[grad(u)+grad(u)^t] , grad(psi) > + if (laplaceType == 1) { + for (size_t j = 0; j < dow; ++j) { + Operator *opLaplaceUi1 = new Operator(getFeSpace(2+i), getFeSpace(2+j)); + opLaplaceUi1->addTerm(new VecAtQP_IJ_SOT( + prob->getSolution()->getDOFVector(0), + new LinearInterpolation(viscosity1, viscosity2), + 1-i, 1-j)); + prob->addMatrixOperator(*opLaplaceUi1, 2+i, 2+j); + } + } + + /// < alpha*grad(u'_i) , grad(psi) > + Operator *opLaplaceUi = new Operator(getFeSpace(2+i), getFeSpace(2+i)); + opLaplaceUi->addTerm(new VecAtQP_SOT( + prob->getSolution()->getDOFVector(0), + new LinearInterpolation(viscosity1, viscosity2))); + prob->addMatrixOperator(*opLaplaceUi, 2+i, 2+i); +} + + +void CahnHilliardNavierStokes_TwoPhase::closeTimestep(AdaptInfo *adaptInfo) +{ FUNCNAME("CahnHilliardNavierStokes_TwoPhase::closeTimestep()"); + + calcVelocity(); + fileWriter->writeFiles(adaptInfo, false); + writeFiles(adaptInfo, false); +} diff --git a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.h b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.h new file mode 100644 index 0000000000000000000000000000000000000000..4fc241c5a717b7391c819504c0cdb3342cde67de --- /dev/null +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase.h @@ -0,0 +1,96 @@ +/** \file CahnHilliardNavierStokes_TwoPhase.h */ + +#ifndef CAHN_HILLIARD_H +#define CAHN_HILLIARD_H + +#include "AMDiS.h" +#include "BaseProblem.h" +#include "ExtendedProblemStat.h" +#include "HL_SignedDistTraverse.h" +#include "chns.h" + +using namespace AMDiS; + +class CahnHilliardNavierStokes_TwoPhase : public BaseProblem<ExtendedProblemStat> +{ +public: // definition of types + + typedef BaseProblem<ExtendedProblemStat> super; + +public: // public methods + + CahnHilliardNavierStokes_TwoPhase(const std::string &name_); + ~CahnHilliardNavierStokes_TwoPhase(); + + 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 addMaterialDerivativeConst(int i); + virtual void addMaterialDerivativeNonConst(int i); + virtual void addLaplaceTermConst(int i); + virtual void addLaplaceTermNonConst(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; +}; + +#endif // CAHN_HILLIARD_H diff --git a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc index 38b0df01dc02b6741e6dd35fdc7549c8e6efe58e..d395c5abcc06b27f33aa63765f4ca737a0268efb 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc @@ -146,35 +146,43 @@ void CahnHilliardNavierStokes_TwoPhase_RB::fillOperators() opChLM->addTerm(new VecAtQP_SOT( prob->getUnVec(0), new MobilityCH0(gamma))); - opChLM->addTerm(new VecGrad_FOT( + prob->addMatrixOperator(*opChLM, 0, 1); + + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChLM2->addTerm(new VecGrad_FOT( prob->getUnVec(0), prob->getUnVec(1), new MobilityCH0Diff(gamma)), GRD_PSI); - prob->addMatrixOperator(*opChLM, 0, 1); + prob->addMatrixOperator(*opChLM2, 0, 0); + // rhs operators - Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); - opChLM2->addTerm(new VecAtQP_SOT( + Operator *opChLMe = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLMe->addTerm(new VecAtQP_SOT( prob->getStageSolution(0), new MobilityCH0(gamma))); - opChLM2->setUhOld(prob->getStageSolution(1)); - prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); - } else { + opChLMe->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLMe, 0, &minus1, &minus1); + } else if (doubleWell == 1) { // jacobian operators opChLM->addTerm(new VecAtQP_SOT( prob->getUnVec(0), new MobilityCH1(gamma))); - opChLM->addTerm(new VecGrad_FOT( + prob->addMatrixOperator(*opChLM, 0, 1); + + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChLM2->addTerm(new VecGrad_FOT( prob->getUnVec(0), prob->getUnVec(1), new MobilityCH1Diff(gamma)), GRD_PSI); - prob->addMatrixOperator(*opChLM, 0, 1); + prob->addMatrixOperator(*opChLM2, 0, 0); + // rhs operators - Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); - opChLM2->addTerm(new VecAtQP_SOT( + Operator *opChLMe = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLMe->addTerm(new VecAtQP_SOT( prob->getStageSolution(0), new MobilityCH1(gamma))); - opChLM2->setUhOld(prob->getStageSolution(1)); - prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + opChLMe->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLMe, 0, &minus1, &minus1); } } else { opChLM->addTerm(new Simple_SOT(gamma)); @@ -260,34 +268,40 @@ void CahnHilliardNavierStokes_TwoPhase_RB::fillOperators() // Navier-Stokes part // ----------------------------------------------------------------------------------- + bool variableDensity = abs(density1 - density2) > DBL_TOL; + int shift = 2; + if (variableDensity) + shift = 3+dow; + 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); - + prob->addTimeOperator(shift+i, 2+i, (variableDensity ? 1.0 : density1)); + + if (variableDensity) { + /// < z , psi > + Operator *opZ = new Operator(getFeSpace(shift+i), getFeSpace(shift+i)); + opZ->addTerm(new Simple_ZOT); + prob->addMatrixOperator(*opZ, shift+i, shift+i, &minus1, &minus1); + opZ->setUhOld(prob->getStageSolution(shift+i)); + prob->addVectorOperator(*opZ, shift+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); + Operator *opUGradU = new Operator(getFeSpace(shift+i), getFeSpace(2+i)); + opUGradU->addTerm(new WorldVec_FOT(stage_velocity, (variableDensity ? -1.0 : -density1)), GRD_PHI); opUGradU->setUhOld(stage_velocity[i]); - prob->addVectorOperator(*opUGradU, 3+dow+i); + prob->addVectorOperator(*opUGradU, shift+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); + Operator *opUGradV = new Operator(getFeSpace(shift+i), getFeSpace(2+i)); + opUGradV->addTerm(new WorldVec_FOT(un_velocity, (variableDensity ? -1.0 : -density1)), GRD_PHI); + prob->addMatrixOperator(*opUGradV, shift+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); + Operator *opVGradU = new Operator(getFeSpace(shift+i), getFeSpace(2+j)); + opVGradU->addTerm(new PartialDerivative_ZOT(un_velocity[i], j, (variableDensity ? -1.0 : -density1))); + prob->addMatrixOperator(*opVGradU, shift+i, 2+j, &minus1, &minus1); } } @@ -305,49 +319,52 @@ void CahnHilliardNavierStokes_TwoPhase_RB::fillOperators() // 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); + if (surfaceTension > DBL_TOL) { + /// < 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_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); + // --------------------------------------- + if (variableDensity) { + /// < rho(c_s)*z_s , psi > + Operator *opDensityExpl = new Operator(prob->getFeSpace(2+i),prob->getFeSpace(shift+1)); + opDensityExpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getStageSolution(0), + new LinearInterpolation(density1, density2, -1.0))); + opDensityExpl->setUhOld(prob->getStageSolution(shift+i)); + prob->addVectorOperator(*opDensityExpl, 2+i); + + /// < rho(c_old)*z , psi > + Operator *opDensityImpl = new Operator(prob->getFeSpace(1),prob->getFeSpace(shift+i)); + opDensityImpl->addZeroOrderTerm(new VecAtQP_ZOT( + prob->getUnVec(0), + new LinearInterpolation(density1, density2, -1.0))); + prob->addMatrixOperator(*opDensityImpl, 2+i, shift+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(shift+i), + new LinearInterpolationDiffFactor(density1, density2, -1.0))); + prob->addMatrixOperator(*opDensityImpl2, 2+i, 0, &minus1, &minus1); + } } // div(u) = 0 @@ -411,53 +428,53 @@ void CahnHilliardNavierStokes_TwoPhase_RB::addStressTerm(int i) /// < 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) > + /// < 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); + 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) > + /// < 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->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) > + /// < 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->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->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))); + 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); + 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) > diff --git a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h index a4ccf45031be5cf4d6a7e4e566c93ff684478705..94030c42c8b9d5e850ba153e5ac4a8369d13399a 100644 --- a/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h +++ b/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.h @@ -6,6 +6,7 @@ #include "AMDiS.h" #include "BaseProblem_RB.h" #include "HL_SignedDistTraverse.h" +#include "chns.h" using namespace AMDiS; @@ -89,238 +90,4 @@ protected: // protected variables }; -/** \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/CahnHilliard_RB.cc b/extensions/base_problems/CahnHilliard_RB.cc index 94cc4798c328fd827562ba340327ee696f99b30c..7b3e839d1443bccc2295c99bcee600c2c1830c01 100644 --- a/extensions/base_problems/CahnHilliard_RB.cc +++ b/extensions/base_problems/CahnHilliard_RB.cc @@ -141,35 +141,43 @@ void CahnHilliard_RB::fillOperators() opChLM->addTerm(new VecAtQP_SOT( prob->getUnVec(0), new MobilityCH0(gamma))); - opChLM->addTerm(new VecGrad_FOT( + prob->addMatrixOperator(*opChLM, 0, 1); + + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChLM2->addTerm(new VecGrad_FOT( prob->getUnVec(0), prob->getUnVec(1), new MobilityCH0Diff(gamma)), GRD_PSI); - prob->addMatrixOperator(*opChLM, 0, 1); + prob->addMatrixOperator(*opChLM2, 0, 0); + // rhs operators - Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); - opChLM2->addTerm(new VecAtQP_SOT( + Operator *opChLMe = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLMe->addTerm(new VecAtQP_SOT( prob->getStageSolution(0), new MobilityCH0(gamma))); - opChLM2->setUhOld(prob->getStageSolution(1)); - prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); - } else { + opChLMe->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLMe, 0, &minus1, &minus1); + } else if (doubleWell == 1) { // jacobian operators opChLM->addTerm(new VecAtQP_SOT( prob->getUnVec(0), new MobilityCH1(gamma))); - opChLM->addTerm(new VecGrad_FOT( + prob->addMatrixOperator(*opChLM, 0, 1); + + Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(0)); + opChLM2->addTerm(new VecGrad_FOT( prob->getUnVec(0), prob->getUnVec(1), new MobilityCH1Diff(gamma)), GRD_PSI); - prob->addMatrixOperator(*opChLM, 0, 1); + prob->addMatrixOperator(*opChLM2, 0, 0); + // rhs operators - Operator *opChLM2 = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); - opChLM2->addTerm(new VecAtQP_SOT( + Operator *opChLMe = new Operator(prob->getFeSpace(0),prob->getFeSpace(1)); + opChLMe->addTerm(new VecAtQP_SOT( prob->getStageSolution(0), new MobilityCH1(gamma))); - opChLM2->setUhOld(prob->getStageSolution(1)); - prob->addVectorOperator(*opChLM2, 0, &minus1, &minus1); + opChLMe->setUhOld(prob->getStageSolution(1)); + prob->addVectorOperator(*opChLMe, 0, &minus1, &minus1); } } else { opChLM->addTerm(new Simple_SOT(gamma)); diff --git a/extensions/base_problems/NavierStokes_TaylorHood_RB.h b/extensions/base_problems/NavierStokes_TaylorHood_RB.h index 56834b4fa24458dcaa8dafd4a226d4f50cabea60..1e471752f8d509af5d2fd8c33074a74fb1188662 100644 --- a/extensions/base_problems/NavierStokes_TaylorHood_RB.h +++ b/extensions/base_problems/NavierStokes_TaylorHood_RB.h @@ -7,7 +7,7 @@ #include "Helpers.h" #include "POperators.h" #include "BoundaryFunctions.h" -#include "BaseProblem.h" +#include "BaseProblem_RB.h" #include "time/ExtendedRosenbrockStationary.h" #include <boost/numeric/mtl/mtl.hpp> #include <boost/numeric/mtl/utility/property_map.hpp> @@ -24,11 +24,11 @@ using namespace AMDiS; * \brief * Navier-Stokes problem, using Taylor Hood elements */ -class NavierStokes_TaylorHood_RB : public BaseProblem<ExtendedRosenbrockStationary> +class NavierStokes_TaylorHood_RB : public BaseProblem_RB { public: // typedefs - typedef BaseProblem<ExtendedRosenbrockStationary> super; + typedef BaseProblem_RB super; public: // methods @@ -58,23 +58,6 @@ public: // methods return velocity; } -// Rosenbrock methods -//_________________________________________________________________________ - -public: - - void acceptTimestep() { prob->acceptTimestep(); } - void reset() { prob->reset(); } - - void setRosenbrockMethod(RosenbrockMethod *method) { prob->setRosenbrockMethod(method); } - void setTau(double *ptr) { prob->setTau(ptr); } - void setTauGamma(double *ptr0, double *ptr1, double *ptr2, double *ptr3) { prob->setTauGamma(ptr0,ptr1,ptr2,ptr3); } - - double* getTauGamma() { return prob->getTauGamma(); } - double* getMinusTauGamma() { return prob->getMinusTauGamma(); } - double* getInvTauGamma() { return prob->getInvTauGamma(); } - double* getMinusInvTauGamma() { return prob->getMinusInvTauGamma(); } - protected: // methods virtual void fillOperators(); diff --git a/extensions/base_problems/chns.h b/extensions/base_problems/chns.h new file mode 100644 index 0000000000000000000000000000000000000000..bc6cf319833f723335bbc4ca7fd88297b39b8a56 --- /dev/null +++ b/extensions/base_problems/chns.h @@ -0,0 +1,276 @@ +/** \file chns.h */ + +#ifndef CHNS_FUNCTORS_H +#define CHNS_FUNCTORS_H + +#include "AMDiS.h" + +/** \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 LinearInterpolationFactor : BinaryAbstractFunction<double, double, double> +{ + LinearInterpolationFactor(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& u) const + { + return factor * u * (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; +}; + +struct TaylorExpansionFactor : BinaryAbstractFunction<double,double,double> +{ + TaylorExpansionFactor(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& u) const + { + return LinearInterpolationFactor(v0, v1, factor)(c, u) + c * LinearInterpolationDiffFactor(v0, v1, factor)(c, u); + } + +private: + double v0; + double v1; + double factor; +}; + +#endif // CHNS_FUNCTORS_H diff --git a/extensions/demo/CMakeLists.txt b/extensions/demo/CMakeLists.txt index 074280e7a7696d784a9efc0acf00ec8b9eda67b1..d6f1a931ee54376bbf758453905beda9a25b9e42 100644 --- a/extensions/demo/CMakeLists.txt +++ b/extensions/demo/CMakeLists.txt @@ -10,47 +10,36 @@ if(AMDIS_FOUND) SET(BASIS_LIBS ${AMDIS_LIBRARIES}) endif(AMDIS_FOUND) - -# set(elliptBase src/elliptBaseProblem.cc) -# add_executable("elliptBase" ${elliptBase}) -# target_link_libraries("elliptBase" ${BASIS_LIBS}) -# -# set(elliptImplicit src/elliptImplicit.cc) -# add_executable("elliptImplicit" ${elliptImplicit}) -# target_link_libraries("elliptImplicit" ${BASIS_LIBS}) -# -# set(cahn_hilliard src/cahn_hilliard.cc) -# add_executable("cahn_hilliard" ${cahn_hilliard}) -# target_link_libraries("cahn_hilliard" ${BASIS_LIBS}) -# -# set(pfc src/pfc.cc) -# add_executable("pfc" ${pfc}) -# target_link_libraries("pfc" ${BASIS_LIBS}) -# -# set(drivenCavity src/chns/drivenCavity.cc) -# add_executable("drivenCavity" ${drivenCavity}) -# target_link_libraries("drivenCavity" ${BASIS_LIBS}) -# -# include_directories(/home/spraetor/projects/src/common) -# set(navierStokes src/navierStokes.cc) -# add_executable("navierStokes" ${navierStokes}) -# target_link_libraries("navierStokes" ${BASIS_LIBS}) -# -# set(navierStokesDd src/navierStokes_diffuseDomain.cc) -# add_executable("navierStokesDd" ${navierStokesDd}) -# target_link_libraries("navierStokesDd" ${BASIS_LIBS}) -# -# set(linearElasticityDd src/linearElasticity.cc) -# add_executable("linearElasticityDd" ${linearElasticityDd}) -# target_link_libraries("linearElasticityDd" ${BASIS_LIBS}) - set(fsi src/fsi_explicit/fluidStructureInteraction.cc) add_executable("fsi" ${fsi}) target_link_libraries("fsi" ${BASIS_LIBS}) + set_target_properties("fsi" PROPERTIES COMPILE_FLAGS "-DUSE_KD_TREE") + + set(drivenCavity src/drivenCavity.cc) + add_executable("drivenCavity" ${drivenCavity}) + target_link_libraries("drivenCavity" ${BASIS_LIBS}) + + include_directories(/opt/amdis/amdis-src/extensions/base_problems/) + set(drivenCavity_rb src/drivenCavity_rb.cc /opt/amdis/amdis-src/extensions/base_problems/CahnHilliardNavierStokes_RB.cc) + add_executable("drivenCavity_rb" ${drivenCavity_rb}) + target_link_libraries("drivenCavity_rb" ${BASIS_LIBS}) -# set(ddFsi src/diffuseDomainFsi.cc) -# add_executable("ddFsi" ${ddFsi}) -# target_link_libraries("ddFsi" ${BASIS_LIBS}) +# include_directories(/opt/amdis/amdis-src/extensions/base_problems/) + set(drivenCavity_twophase src/drivenCavity_twophase_rb.cc /opt/amdis/amdis-src/extensions/base_problems/CahnHilliardNavierStokes_TwoPhase_RB.cc) + add_executable("drivenCavity_twophase" ${drivenCavity_twophase}) + target_link_libraries("drivenCavity_twophase" ${BASIS_LIBS}) + + set(ddFsi src/diffuseDomainFsi.cc) + add_executable("ddFsi" ${ddFsi}) + target_link_libraries("ddFsi" ${BASIS_LIBS}) + + set(movingMesh src/movingMesh.cc) + add_executable("movingMesh" ${movingMesh}) + target_link_libraries("movingMesh" ${BASIS_LIBS}) + + set(rosenbrockTest src/rosenbrock_test.cc) + add_executable("rosenbrockTest" ${rosenbrockTest}) + target_link_libraries("rosenbrockTest" ${BASIS_LIBS}) #create the output dir diff --git a/extensions/demo/init/drivenCavity2.dat.2d b/extensions/demo/init/drivenCavity2.dat.2d index 951831594610d3e1c3b0b5fa7ee05c5239fdee49..d12fd8e428529dc860819c5df36247405c2fe44a 100644 --- a/extensions/demo/init/drivenCavity2.dat.2d +++ b/extensions/demo/init/drivenCavity2.dat.2d @@ -66,12 +66,12 @@ chns->non-linear term: 3 % 0... u^old*grad(u_i^old), 1... u'*grad(u_i^old), 2. % ====================== USER_PARAMETER - COUPLING ============== -chns->sigma: 0.0 % surface tension +chns->sigma: 1 % surface tension chns->use conservation form: 0 % ====================== TIMESTEPS ======================== -adapt->rosenbrock method: rodasp +adapt->rosenbrock method: rosI2Pw adapt->fix first timesteps: 0 adapt->rosenbrock->timestep study: 0 adapt->rosenbrock->timestep study steps: 0 @@ -87,7 +87,7 @@ adapt->timestep: 1.e-2 adapt->max timestep: 1e+10 adapt->min timestep: 1e-6 adapt->start time: 0.0 -adapt->end time: 10 +adapt->end time: 9999999 % =========== OUTPUT ============================================== diff --git a/extensions/doc/doxyfile b/extensions/doc/doxyfile index f4e5b24aeed3455ceeebed365f0204a6a2cbf75e..458fde2f83f63d64296727915205bb69da8b1fa4 100644 --- a/extensions/doc/doxyfile +++ b/extensions/doc/doxyfile @@ -1103,7 +1103,7 @@ EXT_LINKS_IN_WINDOW = NO # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. -FORMULA_FONTSIZE = 10 +FORMULA_FONTSIZE = 11 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are diff --git a/extensions/time/ExtendedRosenbrockAdaptInstationary.h b/extensions/time/ExtendedRosenbrockAdaptInstationary.h index d41c6e5d241f6e778ca32b7e8e4636ebb2e6be65..bb20ab87c6a8d274c98c21581ec114b5a4a053ee 100644 --- a/extensions/time/ExtendedRosenbrockAdaptInstationary.h +++ b/extensions/time/ExtendedRosenbrockAdaptInstationary.h @@ -110,6 +110,8 @@ namespace AMDiS { /// The value tau * gamma, where gamma is a value of the used /// Rosenbrock method. double tauGamma, minusTauGamma, invTauGamma, minusInvTauGamma; + + double oldTime; /// If true, the first timestep is calculated with different timesteps. /// This is usually used to make a study how the time error estimator diff --git a/extensions/time/ExtendedRosenbrockAdaptInstationary.hh b/extensions/time/ExtendedRosenbrockAdaptInstationary.hh index 7a4192fdd84eba96ae1095552193922c600ec603..f338e886f393de6ae1bfa0cd39bb8e0e16c540e9 100644 --- a/extensions/time/ExtendedRosenbrockAdaptInstationary.hh +++ b/extensions/time/ExtendedRosenbrockAdaptInstationary.hh @@ -35,6 +35,7 @@ namespace AMDiS { minusTauGamma(-1.0), invTauGamma(1.0), minusInvTauGamma(-1.0), + oldTime(adaptInfo->getStartTime()), dbgTimestepStudy(false) { FUNCNAME("ExtendedRosenbrockAdaptInstationary::ExtendedRosenbrockAdaptInstationary()"); @@ -87,7 +88,8 @@ namespace AMDiS { adaptInfo->setRosenbrockMode(true); rosenbrockStat->setTauGamma(&tauGamma, &minusTauGamma, - &invTauGamma, &minusInvTauGamma); + &invTauGamma, &minusInvTauGamma, + &oldTime); rosenbrockStat->setTau(&tau); Parameters::get(name + "->rosenbrock->timestep study", dbgTimestepStudy); @@ -125,6 +127,7 @@ namespace AMDiS { minusTauGamma = -1.0; invTauGamma = 1.0; minusInvTauGamma = -1.0; + oldTime = 0.0; } @@ -265,6 +268,8 @@ namespace AMDiS { (dbgTimestepStudy && (studyTimestep + 1 < dbgTimesteps.size()))); rosenbrockStat->acceptTimestep(); + oldTime = adaptInfo->getTime(); + adaptInfo->setLastProcessedTimestep(adaptInfo->getTimestep()); adaptInfo->incTimestepNumber(); diff --git a/extensions/time/ExtendedRosenbrockStationary.cc b/extensions/time/ExtendedRosenbrockStationary.cc index e8c5db1028c6aeebfe93d6aa25b97f88ffd15765..1fb320792197f1313cbe9289a97e3b81159990e8 100644 --- a/extensions/time/ExtendedRosenbrockStationary.cc +++ b/extensions/time/ExtendedRosenbrockStationary.cc @@ -16,6 +16,7 @@ #include "SystemVector.h" #include "OEMSolver.h" #include "Debug.h" +#include "POperators_ZOT.h" #ifdef HAVE_PARALLEL_DOMAIN_AMDIS #include "parallel/MeshDistributor.h" @@ -65,7 +66,11 @@ using namespace AMDiS; *newUn = *unVec; *lowSol = *unVec; - for (int i = 0; i < rm->getStages(); i++) { + for (int i = 0; i < rm->getStages(); i++) { + + stageTime = (*oldTime) + rm->getAlphaI(i) * (*tauPtr); + tauGammaI = rm->getGammaI(i) * (*tauPtr); + *stageSolution = *unVec; for (int j = 0; j < i; j++) { *tmp = *(stageSolutions[j]); @@ -76,6 +81,13 @@ using namespace AMDiS; for (unsigned int j = 0; j < boundaries.size(); j++) { boundaries[j].vec->interpol(boundaries[j].fct); *(boundaries[j].vec) -= *(stageSolution->getDOFVector(boundaries[j].row)); + if (boundaries[j].fctDt != NULL) { + DOFVector<double>* tmpDt = new DOFVector<double>(getFeSpace(boundaries[j].row), "tmp"); + tmpDt->interpol(boundaries[j].fctDt); + *tmpDt *= tauGammaI; + *(boundaries[j].vec) -= *tmpDt; + delete tmpDt; + } } timeRhsVec->set(0.0); @@ -100,6 +112,8 @@ using namespace AMDiS; *lowSol += *tmp; } + stageTime = (*oldTime) + (*tauPtr); + for (int i = 0; i < nComponents; i++) { (*(lowSol->getDOFVector(i))) -= (*(newUn->getDOFVector(i))); adaptInfo->setTimeEstSum(lowSol->getDOFVector(i)->l2norm(), i+componentShift); @@ -135,40 +149,41 @@ using namespace AMDiS; } - void ExtendedRosenbrockStationary::addTimeOperator(int row, int col) + void ExtendedRosenbrockStationary::addTimeOperator(int row, int col, double factor) { FUNCNAME("ExtendedRosenbrockStationary::addTimeOperator()"); TEST_EXIT(invTauGamma)("This should not happen!\n"); Operator *op = new Operator(componentSpaces[row], componentSpaces[col]); - op->addZeroOrderTerm(new Simple_ZOT); + op->addZeroOrderTerm(new Simple_ZOT(factor)); super::addMatrixOperator(op, row, col, invTauGamma, invTauGamma); Operator *opRhs = new Operator(componentSpaces[row]); - opRhs->addZeroOrderTerm(new VecAtQP_ZOT(timeRhsVec->getDOFVector(col))); - super::addVectorOperator(opRhs, row, &minusOne, &minusOne); + opRhs->addZeroOrderTerm(new Phase_ZOT(timeRhsVec->getDOFVector(col), factor)); + super::addVectorOperator(opRhs, row); } void ExtendedRosenbrockStationary::addDirichletBC(BoundaryType type, int row, int col, - AbstractFunction<double, WorldVector<double> > *fct) + AbstractFunction<double, WorldVector<double> > *fct, + AbstractFunction<double, WorldVector<double> > *fctDt) { FUNCNAME("ExtendedRosenbrockStationary::addDirichletBC()"); DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {fct, vec, row, col}; + MyRosenbrockBoundary bound(fct, fctDt, vec, row, col); boundaries.push_back(bound); super::addDirichletBC(type, row, col, vec); } - + void ExtendedRosenbrockStationary::addSingularDirichletBC(WorldVector<double> &pos, int row, int col, AbstractFunction<double, WorldVector<double> > &fct) { DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {&fct, vec, row, col}; + MyRosenbrockBoundary bound(&fct, NULL, vec, row, col); boundaries.push_back(bound); super::addSingularDirichletBC(pos, row, col, *vec); @@ -179,7 +194,7 @@ using namespace AMDiS; AbstractFunction<double, WorldVector<double> > &fct) { DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {&fct, vec, row, col}; + MyRosenbrockBoundary bound(&fct, NULL, vec, row, col); boundaries.push_back(bound); super::addSingularDirichletBC(idx, row, col, *vec); @@ -190,7 +205,7 @@ using namespace AMDiS; AbstractFunction<double, WorldVector<double> > &fct) { DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {&fct, vec, row, col}; + MyRosenbrockBoundary bound(&fct, NULL, vec, row, col); boundaries.push_back(bound); super::addImplicitDirichletBC(signedDist, row, col, *vec); @@ -201,7 +216,7 @@ using namespace AMDiS; AbstractFunction<double, WorldVector<double> > &fct) { DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {&fct, vec, row, col}; + MyRosenbrockBoundary bound(&fct, NULL, vec, row, col); boundaries.push_back(bound); super::addImplicitDirichletBC(signedDist, row, col, *vec); @@ -213,7 +228,7 @@ using namespace AMDiS; AbstractFunction<double, WorldVector<double> > &fct) { DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {&fct, vec, row, col}; + MyRosenbrockBoundary bound(&fct, NULL, vec, row, col); boundaries.push_back(bound); super::addManualDirichletBC(nr, meshIndicator, row, col, *vec); @@ -225,7 +240,7 @@ using namespace AMDiS; AbstractFunction<double, WorldVector<double> > &fct) { DOFVector<double>* vec = new DOFVector<double>(componentSpaces[row], "vec"); - MyRosenbrockBoundary bound = {&fct, vec, row, col}; + MyRosenbrockBoundary bound(&fct, NULL, vec, row, col); boundaries.push_back(bound); super::addManualDirichletBC(meshIndicator, row, col, *vec); diff --git a/extensions/time/ExtendedRosenbrockStationary.h b/extensions/time/ExtendedRosenbrockStationary.h index 181eed911fd2b23bb3b6ad9a3210f49149ec3095..50c1994d689965bf78eec0c38b89f4a44271ddc4 100644 --- a/extensions/time/ExtendedRosenbrockStationary.h +++ b/extensions/time/ExtendedRosenbrockStationary.h @@ -40,7 +40,15 @@ using namespace AMDiS; struct MyRosenbrockBoundary { - AbstractFunction<double, WorldVector<double> > *fct; + MyRosenbrockBoundary(AbstractFunction<double, WorldVector<double> > * fct_, + AbstractFunction<double, WorldVector<double> > * fctDt_, + DOFVector<double> *vec_, + int row_, + int col_ + ) : fct(fct_), fctDt(fctDt_), vec(vec_), row(row_), col(col_) {} + + AbstractFunction<double, WorldVector<double> > *fct; // f(t,x) + AbstractFunction<double, WorldVector<double> > *fctDt; // dt[f](t,x) DOFVector<double> *vec; @@ -65,7 +73,8 @@ using namespace AMDiS; tauGamma(NULL), minusTauGamma(NULL), invTauGamma(NULL), - minusInvTauGamma(NULL) + minusInvTauGamma(NULL), + stageTime(0.0) {} DOFVector<double>* getUnVec(int i) @@ -111,20 +120,21 @@ using namespace AMDiS; void addJacobianOperator(Operator &op, int row, int col, double *factor = NULL, double *estFactor = NULL); - void addTimeOperator(int i, int j); + void addTimeOperator(int i, int j, double factor = 1.0); void setTau(double *ptr) { tauPtr = ptr; } - void setTauGamma(double *ptr0, double *ptr1, double *ptr2, double *ptr3) + void setTauGamma(double *ptr0, double *ptr1, double *ptr2, double *ptr3, double *ptr4) { tauGamma = ptr0; minusTauGamma = ptr1; invTauGamma = ptr2; minusInvTauGamma = ptr3; - } + oldTime = ptr4; + } double* getTauGamma() { @@ -145,11 +155,33 @@ using namespace AMDiS; { return minusInvTauGamma; } + + double getStageTime() + { + return stageTime; + } + + double* getOldTimePtr() + { + return oldTime; + } + + double* getStageTimePtr() + { + return &stageTime; + } + + + double* getTauGammaI() + { + return &tauGammaI; + } /// Adds a Dirichlet boundary condition, where the rhs is given by an /// abstract function. void addDirichletBC(BoundaryType type, int row, int col, - AbstractFunction<double, WorldVector<double> > *b); + AbstractFunction<double, WorldVector<double> > *b, + AbstractFunction<double, WorldVector<double> > *bDt = NULL); /// Adds a Dirichlet boundary condition, where the rhs is given by a DOF /// vector. @@ -163,33 +195,33 @@ using namespace AMDiS; /// Adds a Neumann boundary condition, where the rhs is given by an /// abstract function. - void addNeumannBC(BoundaryType type, int row, int col, - AbstractFunction<double, WorldVector<double> > *n) - { - FUNCNAME("ExtendedRosenbrockStationary::addNeumannBC()"); - - ERROR_EXIT("Not yet supported!\n"); - } +// void addNeumannBC(BoundaryType type, int row, int col, +// AbstractFunction<double, WorldVector<double> > *n) +// { +// FUNCNAME("ExtendedRosenbrockStationary::addNeumannBC()"); +// +// ERROR_EXIT("Not yet supported!\n"); +// } /// Adds a Neumann boundary condition, where the rhs is given by an DOF /// vector. - void addNeumannBC(BoundaryType type, int row, int col, - DOFVector<double> *n) - { - FUNCNAME("ExtendedRosenbrockStationary::addNeumannBC()"); - - ERROR_EXIT("Not yet supported!\n"); - } +// void addNeumannBC(BoundaryType type, int row, int col, +// DOFVector<double> *n) +// { +// FUNCNAME("ExtendedRosenbrockStationary::addNeumannBC()"); +// +// ERROR_EXIT("Not yet supported!\n"); +// } /// Adds Robin boundary condition. - void addRobinBC(BoundaryType type, int row, int col, - AbstractFunction<double, WorldVector<double> > *n, - AbstractFunction<double, WorldVector<double> > *r) - { - FUNCNAME("ExtendedRosenbrockStationary::addRobinBC()"); - - ERROR_EXIT("Not yet supported!\n"); - } +// void addRobinBC(BoundaryType type, int row, int col, +// AbstractFunction<double, WorldVector<double> > *n, +// AbstractFunction<double, WorldVector<double> > *r) +// { +// FUNCNAME("ExtendedRosenbrockStationary::addRobinBC()"); +// +// ERROR_EXIT("Not yet supported!\n"); +// } /// special boundary conditions defined in ExtendedProblemStat @@ -229,7 +261,7 @@ using namespace AMDiS; protected: RosenbrockMethod *rm; - SystemVector *stageSolution, *unVec, *timeRhsVec, *newUn, *tmp, *lowSol; + SystemVector *stageSolution, *unVec, *timeRhsVec, *newUn, *tmp, *lowSol, *timeDrivative; std::vector<SystemVector*> stageSolutions; @@ -242,6 +274,10 @@ using namespace AMDiS; double *tauPtr; double *tauGamma, *minusTauGamma, *invTauGamma, *minusInvTauGamma; + + double stageTime; // t_n + alpha_i*tau + double* oldTime; + double tauGammaI; // tau*gamma_i std::vector<MyRosenbrockBoundary> boundaries; }; diff --git a/extensions/tutorial.hpp b/extensions/tutorial.hpp index 4ee32d5a911d93c277cada13fcce37b2ba226e3e..cb161cb88a09bab0729b514a6ddde6fd295005ff 100644 --- a/extensions/tutorial.hpp +++ b/extensions/tutorial.hpp @@ -28,7 +28,7 @@ But it should give you enough information to get started. - \subpage mesh_refinement - \subpage boundary_conditions - \subpage tools - +- \subpage base_problems */ @@ -940,6 +940,116 @@ int main(int argc, char* argv[]) \image html elliptManual.png "Manual Dirichlet condition at the left boundary of the domain" width=300px +*/ + +//----------------------------------------------------------- + + +/*! \page base_problems Base Problems + +Some common problems are implemented in the directory base_problems: +- \subpage cahn_hilliard +- \subpage phase_field_crystal +- \subpage navier_stokes +- \subpage chns +- \subpage chns2 +- \subpage linear_elasticity +- \subpage fsi + +*/ + +//----------------------------------------------------------- + + +/*! \page fsi Fully coupled fluid structure interaction using diffuse domain approach + +The underliing equations are + +\f{eqnarray*}{ + \partial_t u_j + \mathbf{u}\cdot\nabla u_j - \nabla\cdot(\phi\cdot\sigma_f) - \nabla\cdot((1-\phi)\cdot\sigma_s) &=& 0,\quad j=0\ldots d-1 \\ + \nabla\cdot(\phi\cdot\mathbf{u}) - \nabla\phi \cdot \mathbf{u} + (1-\phi)(p - \alpha\nabla\cdot\eta) &=& 0 \\ + (1-\phi)\cdot(\partial_t\eta_j + \mathbf{u}\cdot\nabla\eta_j) &=& (1-\phi)\cdot u_j,\quad j=0\ldots d-1 +\f} + +with \f$ \alpha = \lambda + \frac{2}{3}\mu,\; \sigma_s = \mu(\nabla\eta+\nabla\eta^\top)+\lambda I\nabla\cdot\eta +\f$ and \f$ \sigma_f = \nu(\nabla \mathbf{u} + \nabla\mathbf{u}^\top)-Ip \f$. + +*/ + +//----------------------------------------------------------- + + +/*! \page chns Cahn-Hilliard-Navier-Stokes equation + +Two phase flow simulations are often implemented using by coupling the Cahn-Hilliard equations and the +Navier-Stokes equations. This coupling can be done explicitely, i.e. solve the equations one after the other, +or implicitely as one system of equations. This is implemented in the CahnHillirdNavierStokes base problem: + +\f{eqnarray*}{ + \partial_t u_j + \mathbf{u}\cdot\nabla u_j - \nabla\cdot\sigma &=& \mu\partial_j c,\quad j=0\ldots d-1 \\ + \nabla\cdot \mathbf{u} &=& 0 \\ + \partial_t c - \Delta\mu + \mathbf{u}\cdot\nabla c &=& 0 \\ + -\epsilon^2\Delta c + W'(c) &=& \mu +\f} + +with \f$ \sigma = Ip - \nu\nabla u \f$ and \f$ W(c) = \frac{1}{4}c^2(1-c)^2 \f$. + +For the time-discretization the nonlinear terms are linearized around the old timestep: + +\f{eqnarray*}{ + \frac{1}{\tau} (u^{k+1}_j - u^{k}_j) + \mathbf{u}^{k+1}\cdot\nabla u^k_j + \mathbf{u}^{k}\cdot\nabla u^{k+1}_j - \mathbf{u}^{k}\cdot\nabla u^{k}_j - \nabla\cdot(\sigma^{k+1}) &=& \mu^{k+1}\partial_j c^k + \mu^{k}\partial_j c^{k+1} - \mu^{k}\partial_j c^k,\quad j=0\ldots d-1 \\ + \nabla\cdot \mathbf{u}^{k+1} &=& 0 \\ + \frac{1}{\tau} (c^{k+1} - c^k) - \Delta\mu^{k+1} &=& - \mathbf{u}^{k+1}\cdot\nabla c^k - \mathbf{u}^{k}\cdot\nabla c^{k+1} + \mathbf{u}^{k}\cdot\nabla c^k \\ + \mu^{k+1} &=& -\epsilon^2\Delta c^{k+1} + W'(c^k) + W''(c^k)(c^{k+1}-c^k) +\f} + +*/ + +//----------------------------------------------------------- + + +/*! \page chns2 Cahn-Hilliard-Navier-Stokes equation (variable density/viscosity) + +Two phase flow simulations are often implemented using by coupling the Cahn-Hilliard equations and the +Navier-Stokes equations. This coupling can be done explicitely, i.e. solve the equations one after the other, +or implicitely as one system of equations. This is implemented in the CahnHillirdNavierStokes base problem: + +\f{eqnarray*}{ + \partial_t c + \mathbf{u}\cdot\nabla c &=& \nabla\cdot \gamma W(c) \nabla \mu \\ + 0 &=& \mu + \epsilon^2\Delta c - W'(c) \\ + \rho(c)\partial_t u_j + \rho(c)\mathbf{u}\cdot\nabla u_j &=& \nabla\cdot\nu(c)\nabla u_j - \nabla p + \alpha\mu\partial_j c + F_j,\quad j=0\ldots d-1 \\ + 0 &=& \nabla\cdot \mathbf{u} +\f} + +with \f$ W(c) = \frac{1}{4}c^2(1-c)^2 \f$ and \f$ \alpha \f$ the surface tension. + +\section chns2_euler Semi-implicit Euler discretization + +For the time-discretization a semi-implicit euler discretization is chosen and the nonlinear terms are linearized around the old timestep: + +\f{eqnarray*}{ + \frac{1}{\tau} (c^{k+1} - c^k) - \Delta\mu^{k+1} &=& - \mathbf{u}^{k+1}\cdot\nabla c^k - \mathbf{u}^{k}\cdot\nabla c^{k+1} + \mathbf{u}^{k}\cdot\nabla c^k \\ + \mu^{k+1} &=& -\epsilon^2\Delta c^{k+1} + W'(c^k) + W''(c^k)(c^{k+1}-c^k) \\ + \rho(c^k)\frac{1}{\tau} (u^{k+1}_j - u^{k}_j) + [\rho(c)\mathbf{u}\cdot\nabla u_j] &=& \nabla\cdot(\nu(c^k)\nabla u_i^{k+1}) - \nabla p^{k+1} + \alpha(\mu^{k+1}\partial_j c^k + \mu^{k}\partial_j c^{k+1} - \mu^{k}\partial_j c^k) + F_i,\quad j=0\ldots d-1 \\ + \nabla\cdot \mathbf{u}^{k+1} &=& 0 +\f} + +with \f[ [\rho(c)\mathbf{u}\cdot\nabla u_j] := \rho(c^k)\cdot\mathbf{u}^{k+1}\cdot\nabla u^k_j + \rho(c^k)\cdot\mathbf{u}^{k}\cdot\nabla u^{k+1}_j + c^{k+1}\cdot\rho'(c^k)\cdot\mathbf{u}^{k}\cdot\nabla u^{k}_j - \big(\rho(c^k) + c^k\cdot\rho'(c^k)\big)\cdot\mathbf{u}^{k}\cdot\nabla u^{k}_j \f]. + +\section chns2_rb Rosenbrock Discretization + +For the time-discretization a Rosenbrock scheme is chosen. +Therefor we have to introduce a new variable \f$ z_j = \partial_t u_j + \mathbf{u}\cdot\nabla u_j \f$. +Stage solutions are depicted with supscripts \f$ \cdot^s \f$ and old solution with \f$ \cdot^{old} \f$: + +\f{eqnarray*}{ + \partial^s_t c - \Delta\mu + \mathbf{u}\cdot\nabla c^{old} + \mathbf{u}^{old}\cdot\nabla c &=& \Delta\mu^s - \mathbf{u}^{s}\cdot\nabla c^s \\ + -\mu - \epsilon^2\Delta c + W''(c^{old})c&=& \mu^s + \epsilon^2\Delta c^{s} - W'(c^s) \\ + \partial^s_t u_j - z_j + u^{old}\cdot\nabla u_j + u\cdot\nabla u^{old}_j &=& z^s - u^s\cdot\nabla u^s_j,\quad j=0\ldots d-1 \\ + \rho(c^{old})z + \rho'(c^{old})z^{old}\cdot c - \nabla\cdot\nu(c^{old})\nabla u_j - \nabla\cdot[c\nu'(c^{old})\nabla u^{old}_j] \\ + + \nabla p - \alpha\mu\partial_j c^{old} - \alpha\mu^{old}\partial_j c &=& \nabla\cdot\nu(c^s)\nabla u^s_j - \nabla p^s + \alpha\mu^{s}\partial_j c^s + F_j,\quad j=0\ldots d-1 \\ + -\nabla\cdot \mathbf{u} &=& \nabla\cdot \mathbf{u}^s +\f} */