From ced7e4c94c8a6acb68daecf43095e3b5d0cdb642 Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Fri, 14 Feb 2014 09:18:30 +0000 Subject: [PATCH] generic operators updated --- AMDiS/src/GenericOperatorTerm.h | 43 +++-- AMDiS/src/GenericOperatorTerm.hh | 146 ++++++++++++++++ AMDiS/src/expressions/AtomicExpression.h | 147 ++++++++++++---- AMDiS/src/expressions/GradientOf.h | 128 ++++++++++++-- AMDiS/src/expressions/LazyExpression.h | 6 + AMDiS/src/expressions/LazyOperatorTerm.h | 54 +++--- AMDiS/src/expressions/ValueOf.h | 204 +++++++++++++++-------- 7 files changed, 568 insertions(+), 160 deletions(-) create mode 100644 AMDiS/src/GenericOperatorTerm.hh diff --git a/AMDiS/src/GenericOperatorTerm.h b/AMDiS/src/GenericOperatorTerm.h index 198bcda0..e677e8b0 100644 --- a/AMDiS/src/GenericOperatorTerm.h +++ b/AMDiS/src/GenericOperatorTerm.h @@ -111,7 +111,7 @@ struct GenericZeroOrderTerm : public ZeroOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad, NULL); } @@ -120,7 +120,7 @@ struct GenericZeroOrderTerm : public ZeroOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad, NULL); } @@ -160,7 +160,7 @@ struct GenericFirstOrderTerm_1 : public FirstOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad); } @@ -169,7 +169,7 @@ struct GenericFirstOrderTerm_1 : public FirstOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad); } @@ -209,7 +209,7 @@ struct GenericFirstOrderTerm_i : public FirstOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad); } @@ -218,7 +218,7 @@ struct GenericFirstOrderTerm_i : public FirstOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad); } @@ -250,7 +250,7 @@ struct GenericFirstOrderTerm_b : public FirstOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad); } @@ -259,7 +259,7 @@ struct GenericFirstOrderTerm_b : public FirstOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad); } @@ -294,7 +294,7 @@ struct GenericSecondOrderTerm_1 : public SecondOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad); } @@ -303,7 +303,7 @@ struct GenericSecondOrderTerm_1 : public SecondOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad); } /// Implements SecondOrderTerm::getLALt(). @@ -365,7 +365,7 @@ struct GenericSecondOrderTerm_A : public SecondOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad); } @@ -374,7 +374,7 @@ struct GenericSecondOrderTerm_A : public SecondOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad); } void getLALt(const ElInfo *elInfo, @@ -453,7 +453,7 @@ struct GenericSecondOrderTerm_ij : public SecondOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, elInfo, subAssembler, quad); + term.initElement(this, elInfo, subAssembler, quad); } @@ -462,7 +462,7 @@ struct GenericSecondOrderTerm_ij : public SecondOrderTerm SubAssembler* subAssembler, Quadrature *quad) { - term.initElement(*this, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(this, smallElInfo, largeElInfo, subAssembler, quad); } void getLALt(const ElInfo *elInfo, @@ -767,6 +767,21 @@ inline void addSOT(Operator& op, double term, int I, int J) addSOT(op, constant(term), I, J); } +template<typename Term> +inline typename boost::enable_if<typename boost::is_base_of<LazyOperatorTermBase, Term>::type, typename Term::value_type>::type +integrate(Term term); + + +template<typename Term> +inline typename boost::enable_if<typename boost::is_base_of<LazyOperatorTermBase, Term>::type, typename Term::value_type>::type +transformDOF(Term term, DOFVector<typename Term::value_type>* result); + +template<typename Term> +typename boost::enable_if<typename boost::is_base_of<LazyOperatorTermBase, Term>::type, + DOFVector<typename Term::value_type>& >::type +operator<<(DOFVector<typename Term::value_type>& result, const Term& term); } +#include "GenericOperatorTerm.hh" + #endif // AMDIS_GENERIC_OPERATOR_TERM_H diff --git a/AMDiS/src/GenericOperatorTerm.hh b/AMDiS/src/GenericOperatorTerm.hh new file mode 100644 index 00000000..4d33f0b9 --- /dev/null +++ b/AMDiS/src/GenericOperatorTerm.hh @@ -0,0 +1,146 @@ +/****************************************************************************** + * + * AMDiS - Adaptive multidimensional simulations + * + * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. + * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis + * + * Authors: + * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al. + * + * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE + * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * + * This file is part of AMDiS + * + * See also license.opensource.txt in the distribution. + * + ******************************************************************************/ + + + +/** \file GenericOperatorTerm.hh */ + +namespace AMDiS { + + namespace detail { + + template<typename Term, typename T> + struct GenericOperatorTerm { }; + + template<typename Term> + struct GenericOperatorTerm<Term, double> { + typedef GenericZeroOrderTerm<Term> type; + }; + + template<typename Term> + struct GenericOperatorTerm<Term, WorldVector<double> > { + typedef GenericFirstOrderTerm_b<Term> type; + }; + + template<typename Term > + struct GenericOperatorTerm<Term, WorldMatrix<double> > { + typedef GenericSecondOrderTerm_A<Term, true> type; + }; + + } + + template<typename Term> + struct GenericOperatorTerm { + typedef typename detail::GenericOperatorTerm<Term, typename Term::value_type>::type type; + }; + +template<typename Term> +inline typename boost::enable_if<typename boost::is_base_of<LazyOperatorTermBase, Term>::type, typename Term::value_type>::type +integrate(Term term) +{ + typedef typename Term::value_type TOut; + + typename GenericOperatorTerm<Term>::type ot(term); + std::set<const FiniteElemSpace*> feSpaces = ot.getAuxFeSpaces(); + Mesh* mesh = (*feSpaces.begin())->getMesh(); + + int deg = term.getDegree(); + int dim = mesh->getDim(); + Quadrature* quad = Quadrature::provideQuadrature(dim, deg); + + TOut value; nullify(value); + + Flag traverseFlag = Mesh::CALL_LEAF_EL | Mesh::FILL_COORDS | Mesh::FILL_GRD_LAMBDA | Mesh::FILL_DET; + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(mesh, -1, traverseFlag); + while (elInfo) { + term.initElement(&ot, elInfo, NULL, quad); + TOut tmp; nullify(tmp); + for (int iq = 0; iq < quad->getNumPoints(); iq++) { + tmp += quad->getWeight(iq) * term(iq); + } + value += tmp * elInfo->getDet(); + + elInfo = stack.traverseNext(elInfo); + } + +#ifdef HAVE_PARALLEL_DOMAIN_AMDIS + Parallel::mpi::globalAdd(value); +#endif + + return value; +} + + +// works only for nodal basis functions! +template<typename Term> +inline typename boost::enable_if<typename boost::is_base_of<LazyOperatorTermBase, Term>::type, typename Term::value_type>::type +transformDOF(Term term, DOFVector<typename Term::value_type>* result) +{ + typedef typename Term::value_type TOut; + TOut tmp; nullify(tmp); + + typename GenericOperatorTerm<Term>::type ot(term); + std::set<const FiniteElemSpace*> feSpaces = ot.getAuxFeSpaces(); + Mesh* mesh = (*feSpaces.begin())->getMesh(); + + const FiniteElemSpace* resultFeSpace = result->getFeSpace(); + const BasisFunction *basisFcts = resultFeSpace->getBasisFcts(); + int nBasisFcts = basisFcts->getNumber(); + + DOFVector<short int> assigned(resultFeSpace, "assigned"); + assigned.set(0); + result->set(tmp); + + std::vector<DegreeOfFreedom> localIndices(nBasisFcts); + TraverseStack stack; + ElInfo *elInfo = stack.traverseFirst(mesh, -1, + Mesh::CALL_LEAF_EL | + Mesh::FILL_COORDS | Mesh::FILL_GRD_LAMBDA); + + while (elInfo) { + term.initElement(&ot, elInfo, NULL, NULL, basisFcts); + basisFcts->getLocalIndices(elInfo->getElement(), resultFeSpace->getAdmin(), localIndices); + + for (int i = 0; i < nBasisFcts; i++) { + (*result)[localIndices[i]] += term(i); + assigned[localIndices[i]]++; + } + elInfo = stack.traverseNext(elInfo); + } + + DOFIterator<typename Term::value_type> resultIter(result, USED_DOFS); + DOFIterator<short int> assignedIter(&assigned, USED_DOFS); + for (resultIter.reset(), assignedIter.reset(); !resultIter.end(); ++resultIter, ++assignedIter) { + *resultIter *= 1.0/static_cast<double>(*assignedIter); + } +} + +template<typename Term> +typename boost::enable_if<typename boost::is_base_of<LazyOperatorTermBase, Term>::type, + DOFVector<typename Term::value_type>& >::type +operator<<(DOFVector<typename Term::value_type>& result, const Term& term) +{ + transformDOF(term, &result); + return result; +} + + +} \ No newline at end of file diff --git a/AMDiS/src/expressions/AtomicExpression.h b/AMDiS/src/expressions/AtomicExpression.h index dbc7ad1d..93233b82 100644 --- a/AMDiS/src/expressions/AtomicExpression.h +++ b/AMDiS/src/expressions/AtomicExpression.h @@ -55,18 +55,53 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - subAssembler->getCoordsAtQPs(elInfo, quad, x); + if (subAssembler) { + subAssembler->getCoordsAtQPs(elInfo, quad, x); + } + else if (quad) { + const int nPoints = quad->getNumPoints(); + + x.change_dim(nPoints); + for (int i = 0; i < nPoints; i++) + elInfo->coordToWorld(quad->getLambda(i), x[i]); + } + else if (basisFct) { + const int nBasisFct = basisFct->getNumber(); + + x.change_dim(nBasisFct); + for (int i = 0; i < nBasisFct; i++) + elInfo->coordToWorld(*basisFct->getCoords(i), x[i]); + MSG("elInfo->coordToWorld(basisFct)\n"); + } } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - subAssembler->getCoordsAtQPs(smallElInfo, quad, x); + if (subAssembler) { + subAssembler->getCoordsAtQPs(smallElInfo, quad, x); + } + else if (quad) { + const int nPoints = quad->getNumPoints(); + + x.change_dim(nPoints); + for (int i = 0; i < nPoints; i++) + smallElInfo->coordToWorld(quad->getLambda(i), x[i]); + } + else if (basisFct) { + const int nBasisFct = basisFct->getNumber(); + + x.change_dim(nBasisFct); + for (int i = 0; i < nBasisFct; i++) + smallElInfo->coordToWorld(*basisFct->getCoords(i), x[i]); + } } inline value_type operator()(const int& iq) const { return x[iq]; } @@ -91,17 +126,51 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - subAssembler->getCoordsAtQPs(elInfo, quad, x); + if (subAssembler) { + subAssembler->getCoordsAtQPs(elInfo, quad, x); + } + else if (quad) { + const int nPoints = quad->getNumPoints(); + + x.change_dim(nPoints); + for (int i = 0; i < nPoints; i++) + elInfo->coordToWorld(quad->getLambda(i), x[i]); + } + else if (basisFct) { + const int nBasisFct = basisFct->getNumber(); + + x.change_dim(nBasisFct); + for (int i = 0; i < nBasisFct; i++) + elInfo->coordToWorld(*basisFct->getCoords(i), x[i]); + } } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - subAssembler->getCoordsAtQPs(smallElInfo, quad, x); + if (subAssembler) { + subAssembler->getCoordsAtQPs(smallElInfo, quad, x); + } + else if (quad) { + const int nPoints = quad->getNumPoints(); + + x.change_dim(nPoints); + for (int i = 0; i < nPoints; i++) + smallElInfo->coordToWorld(quad->getLambda(i), x[i]); + } + else if (basisFct) { + const int nBasisFct = basisFct->getNumber(); + + x.change_dim(nBasisFct); + for (int i = 0; i < nBasisFct; i++) + smallElInfo->coordToWorld(*basisFct->getCoords(i), x[i]); + } } inline double operator()(const int& iq) const { return x[iq][I]; } @@ -127,16 +196,18 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { elInfo->getNormal(side, normal); } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { smallElInfo->getNormal(side, normal); } @@ -164,22 +235,24 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { elInfo->getNormal(side, normal); } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { smallElInfo->getNormal(side, normal); } inline value_type operator()(const int& iq) const { return normal[I]; } - inline value_type derivative(const int& iq, int identifier) const { 0.0; } + inline value_type derivative(const int& iq, int identifier) const { return 0.0; } }; @@ -201,16 +274,18 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { elInfo->getElementNormal(elementNormal); } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { smallElInfo->getElementNormal(elementNormal); } @@ -237,22 +312,24 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { elInfo->getElementNormal(elementNormal); } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { smallElInfo->getElementNormal(elementNormal); } inline value_type operator()(const int& iq) const { return elementNormal[I]; } - inline value_type derivative(const int& iq, int identifier) const { 0.0; } + inline value_type derivative(const int& iq, int identifier) const { return 0.0; } }; @@ -272,12 +349,14 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) {} + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) {} template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) {} + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) {} inline value_type operator()(const int& iq) const { return value; } inline value_type derivative(const int& iq, int identifier) const { return 0.0; } diff --git a/AMDiS/src/expressions/GradientOf.h b/AMDiS/src/expressions/GradientOf.h index d6aba4ff..29ca53b9 100644 --- a/AMDiS/src/expressions/GradientOf.h +++ b/AMDiS/src/expressions/GradientOf.h @@ -44,6 +44,7 @@ namespace result_of { DOFVector<T>* vecDV; mutable mtl::dense_vector<typename GradientType<T>::type> vec; + mutable mtl::dense_vector<T> coeff; GradientOf(Vector& vector) : vecDV(&vector) {} GradientOf(Vector* vector) : vecDV(vector) {} @@ -60,18 +61,56 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) - { - ot.getGradientsAtQPs(vecDV, elInfo, subAssembler, quad, vec); + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) + { + if (ot && subAssembler) + ot->getGradientsAtQPs(vecDV, elInfo, subAssembler, quad, vec); + else if (quad) + vecDV->getGrdAtQPs(elInfo, quad, NULL, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(elInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + vec.change_dim(nBasisFct); + + const DimVec<WorldVector<double> > &grdLambda = elInfo->getGrdLambda(); + for (size_t i = 0; i < nBasisFct; i++) + localBasisFct->evalGrdUh(*basisFct->getCoords(i), grdLambda, coeff, vec[i]); + } } template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getGradientsAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); + if (ot && subAssembler) + ot->getGradientsAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); + else if (quad) + vecDV->getGrdAtQPs(smallElInfo, largeElInfo, quad, NULL, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(smallElInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + vec.change_dim(nBasisFct); + + const DimVec<WorldVector<double> > &grdLambda = smallElInfo->getGrdLambda(); + for (size_t i = 0; i < nBasisFct; i++) + localBasisFct->evalGrdUh(*basisFct->getCoords(i), grdLambda, coeff, vec[i]); + } } value_type operator()(const int& iq) const { return vec[iq]; } @@ -85,7 +124,9 @@ namespace result_of { typedef T value_type; DOFVector<T>* vecDV; - mutable mtl::dense_vector<typename GradientType<T>::type> vec; +// mutable mtl::dense_vector<typename GradientType<T>::type> vec; + mutable mtl::dense_vector<T> vec; + mutable mtl::dense_vector<T> coeff; int comp; DerivativeOf(Vector& vector) : vecDV(&vector), comp(I) {} @@ -114,21 +155,78 @@ namespace result_of { } template<typename OT> - void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getGradientsAtQPs(vecDV, elInfo, subAssembler, quad, vec); +// if (op && subAssembler) +// ot->getGradientsAtQPs(vecDV, elInfo, subAssembler, quad, vec); +// else +// vecDV->getGrdAtQPs(elInfo, localQuad, NULL, vec); + + if (ot && subAssembler) + subAssembler->getDerivativeAtQPs(vecDV, elInfo, quad, comp, vec); + else if (quad) + vecDV->getDerivativeAtQPs(elInfo, quad, NULL, comp, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(elInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + mtl::dense_vector<typename GradientType<T>::type> helper(nBasisFct); + + const DimVec<WorldVector<double> > &grdLambda = elInfo->getGrdLambda(); + for (size_t i = 0; i < nBasisFct; i++) + localBasisFct->evalGrdUh(*basisFct->getCoords(i), grdLambda, coeff, helper[i]); + + vec.change_dim(nBasisFct); + for (size_t i = 0; i < num_rows(helper); i++) + vec[i] = helper[i][comp]; + } } template<typename OT> - void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getGradientsAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); +// if (op && subAssembler) +// ot->getGradientsAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); +// else +// vecDV->getGrdAtQPs(smallElInfo, largeElInfo, localQuad, NULL, vec); + + if (ot && subAssembler) + subAssembler->getDerivativeAtQPs(vecDV, smallElInfo, largeElInfo, quad, comp, vec); + else if (quad) + vecDV->getDerivativeAtQPs(smallElInfo, largeElInfo, quad, NULL, comp, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(smallElInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + mtl::dense_vector<typename GradientType<T>::type> helper(nBasisFct); + + const DimVec<WorldVector<double> > &grdLambda = smallElInfo->getGrdLambda(); + for (size_t i = 0; i < nBasisFct; i++) + localBasisFct->evalGrdUh(*basisFct->getCoords(i), grdLambda, coeff, helper[i]); + + vec.change_dim(nBasisFct); + for (size_t i = 0; i < num_rows(helper); i++) + vec[i] = helper[i][comp]; + } } - value_type operator()(const int& iq) const { return vec[iq][comp]; } +// value_type operator()(const int& iq) const { return vec[iq][comp]; } + value_type operator()(const int& iq) const { return vec[iq]; } }; } // end namespace result_of diff --git a/AMDiS/src/expressions/LazyExpression.h b/AMDiS/src/expressions/LazyExpression.h index eb7a5b1b..f053bccb 100644 --- a/AMDiS/src/expressions/LazyExpression.h +++ b/AMDiS/src/expressions/LazyExpression.h @@ -40,6 +40,12 @@ struct NoType {}; struct FunctorBase { typedef NoType value_type; + int getDegree() const { return 0; } + int getDegree(int d0) const { return 0; } + int getDegree(int d0, int d1) const { return 0; } + int getDegree(int d0, int d1, int d2) const { return 0; } + int getDegree(int d0, int d1, int d2, int d3) const { return 0; } + protected: virtual void helper() {}; }; diff --git a/AMDiS/src/expressions/LazyOperatorTerm.h b/AMDiS/src/expressions/LazyOperatorTerm.h index 67b15eea..6dd75db8 100644 --- a/AMDiS/src/expressions/LazyOperatorTerm.h +++ b/AMDiS/src/expressions/LazyOperatorTerm.h @@ -49,17 +49,19 @@ struct LazyOperatorTerm1 : public LazyOperatorTermBase } template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - term.initElement(ot, elInfo, subAssembler, quad); + term.initElement(ot, elInfo, subAssembler, quad, basisFct); } template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - term.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad); + term.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct); } inline double operator()(const int& iq) const; @@ -80,19 +82,21 @@ struct LazyOperatorTerm2 : public LazyOperatorTermBase } template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - term1.initElement(ot, elInfo, subAssembler, quad); - term2.initElement(ot, elInfo, subAssembler, quad); + term1.initElement(ot, elInfo, subAssembler, quad, basisFct); + term2.initElement(ot, elInfo, subAssembler, quad, basisFct); } template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - term1.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad); - term2.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad); + term1.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct); + term2.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct); } double operator()(const int& iq) const; @@ -116,21 +120,23 @@ struct LazyOperatorTerm3 : public LazyOperatorTermBase } template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - term1.initElement(ot, elInfo, subAssembler, quad); - term2.initElement(ot, elInfo, subAssembler, quad); - term3.initElement(ot, elInfo, subAssembler, quad); + term1.initElement(ot, elInfo, subAssembler, quad, basisFct); + term2.initElement(ot, elInfo, subAssembler, quad, basisFct); + term3.initElement(ot, elInfo, subAssembler, quad, basisFct); } template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - term1.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad); - term2.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad); - term3.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad); + term1.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct); + term2.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct); + term3.initElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct); } inline double operator()(const int& iq) const; diff --git a/AMDiS/src/expressions/ValueOf.h b/AMDiS/src/expressions/ValueOf.h index a740d9b9..4af2ff3b 100644 --- a/AMDiS/src/expressions/ValueOf.h +++ b/AMDiS/src/expressions/ValueOf.h @@ -47,6 +47,7 @@ namespace result_of { DOFVector<T>* vecDV; mutable mtl::dense_vector<T> vec; + mutable mtl::dense_vector<T> coeff; ValueOf(DOFVector<T>& vector) : vecDV(&vector) {} ValueOf(DOFVector<T>* vector) : vecDV(vector) {} @@ -63,18 +64,52 @@ namespace result_of { } template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getVectorAtQPs(vecDV, elInfo, subAssembler, quad, vec); + if (ot && subAssembler) + ot->getVectorAtQPs(vecDV, elInfo, subAssembler, quad, vec); + else if (quad) + vecDV->getVecAtQPs(elInfo, quad, NULL, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(elInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + vec.change_dim(nBasisFct); + for (size_t i = 0; i < nBasisFct; i++) + vec[i] = localBasisFct->evalUh(*basisFct->getCoords(i), coeff); + } } template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getVectorAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); + if (ot && subAssembler) + ot->getVectorAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); + else if (quad) + vecDV->getVecAtQPs(smallElInfo, largeElInfo, quad, NULL, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(smallElInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + vec.change_dim(nBasisFct); + for (size_t i = 0; i < nBasisFct; i++) + vec[i] = localBasisFct->evalUh(*basisFct->getCoords(i), coeff); + } } inline value_type operator()(const int& iq) const { return vec[iq]; } @@ -89,8 +124,12 @@ namespace result_of { Vector<DOFVector<T>*> vecDV; mutable mtl::dense_vector<value_type> vec; + mutable Vector<mtl::dense_vector<T> > coeff; - ValueOf(Vector<DOFVector<T>*>& vector) : vecDV(vector) {} + ValueOf(Vector<DOFVector<T>*>& vector) : vecDV(vector) + { + resize(coeff, num_rows(vecDV)); + } template<typename List> inline void insertFeSpaces(List& feSpaces) const @@ -105,12 +144,30 @@ namespace result_of { } template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { Vector<mtl::dense_vector<T> > helper; resize(helper, num_rows(vecDV)); - for (size_t i = 0; i < num_rows(vecDV); i++) - ot.getVectorAtQPs(vecDV[i], elInfo, subAssembler, quad, helper[i]); + for (size_t i = 0; i < num_rows(vecDV); i++) { + if (ot && subAssembler) + ot->getVectorAtQPs(vecDV[i], elInfo, subAssembler, quad, helper[i]); + else if (quad) + vecDV[i]->getVecAtQPs(elInfo, quad, NULL, helper[i]); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV[i]->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff[i].change_dim(localBasisFct->getNumber()); + vecDV[i]->getLocalVector(elInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + helper[i].change_dim(nBasisFct); + for (size_t j = 0; j < nBasisFct; j++) + helper[i][j] = localBasisFct->evalUh(*basisFct->getCoords(j), coeff[i]); + } + } vec.change_dim(num_rows(helper[0])); for (size_t iq = 0; iq < num_rows(helper[0]); iq++) { value_type tmp; resize(tmp, num_rows(vecDV)); @@ -122,12 +179,30 @@ namespace result_of { template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { Vector<mtl::dense_vector<T> > helper; resize(helper, num_rows(vecDV)); - for (size_t i = 0; i < num_rows(vecDV); i++) - ot.getVectorAtQPs(vecDV[i], smallElInfo, largeElInfo, subAssembler, quad, helper[i]); + for (size_t i = 0; i < num_rows(vecDV); i++) { + if (ot && subAssembler) + ot->getVectorAtQPs(vecDV[i], smallElInfo, subAssembler, quad, helper[i]); + else if (quad) + vecDV[i]->getVecAtQPs(smallElInfo, quad, NULL, helper[i]); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV[i]->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff[i].change_dim(localBasisFct->getNumber()); + vecDV[i]->getLocalVector(smallElInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + helper[i].change_dim(nBasisFct); + for (size_t j = 0; j < nBasisFct; j++) + helper[i][j] = localBasisFct->evalUh(*basisFct->getCoords(j), coeff[i]); + } + } vec.change_dim(num_rows(helper[0])); for (size_t iq = 0; iq < num_rows(helper[0]); iq++) { value_type tmp; resize(tmp, num_rows(vecDV)); @@ -142,58 +217,6 @@ namespace result_of { }; - struct ValueOf2 : public LazyOperatorTermBase - { - typedef double value_type; - - DOFVector<value_type>* vecDV; - - mutable mtl::dense_vector<value_type> vec; - - const int I; // component of problem - - ValueOf2(ProblemStat& prob, int I_) : vecDV(prob.getSolution(I_)), I(I_) {} - ValueOf2(ProblemStat* prob, int I_) : vecDV(prob->getSolution(I_)), I(I_) {} - - // for Rosenbrock problems - ValueOf2(RosenbrockStationary& prob, int I_) - : vecDV(prob.getStageSolution(I_)), I(I_) {} - ValueOf2(RosenbrockStationary* prob, int I_) - : vecDV(prob->getStageSolution(I_)), I(I_) {} - - template<typename List> - inline void insertFeSpaces(List& feSpaces) const - { - feSpaces.insert(vecDV->getFeSpace()); - } - - inline int getDegree() const - { - return vecDV->getFeSpace()->getBasisFcts()->getDegree(); - } - - template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) - { - ot.getVectorAtQPs(vecDV, elInfo, subAssembler, quad, vec); - } - - - template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) - { - ot.getVectorAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); - } - - inline value_type operator()(const int& iq) const { return vec[iq]; } - inline value_type derivative(const int& iq, int identifier) const - { - return static_cast<value_type>(identifier == I); - } - }; - template<typename Vector> struct ComponentOf : public LazyOperatorTermBase {}; @@ -204,6 +227,7 @@ namespace result_of { DOFVector<Vector<T> >* vecDV; mutable mtl::dense_vector<Vector<T> > vec; + mutable mtl::dense_vector<Vector<T> > coeff; int I; ComponentOf(DOFVector<Vector<T> >& vector, int I_) : vecDV(&vector), I(I_) {} @@ -221,18 +245,52 @@ namespace result_of { } template<typename OT> - inline void initElement(OT& ot, const ElInfo* elInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* elInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getVectorAtQPs(vecDV, elInfo, subAssembler, quad, vec); + if (ot && subAssembler) + ot->getVectorAtQPs(vecDV, elInfo, subAssembler, quad, vec); + else if (quad) + vecDV->getVecAtQPs(elInfo, quad, NULL, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(elInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + vec.change_dim(nBasisFct); + for (size_t i = 0; i < nBasisFct; i++) + vec[i] = localBasisFct->evalUh(*basisFct->getCoords(i), coeff); + } } template<typename OT> - inline void initElement(OT& ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, - SubAssembler* subAssembler, Quadrature *quad) + inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, + SubAssembler* subAssembler, Quadrature *quad, + const BasisFunction *basisFct = NULL) { - ot.getVectorAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); + if (ot && subAssembler) + ot->getVectorAtQPs(vecDV, smallElInfo, largeElInfo, subAssembler, quad, vec); + else if (quad) + vecDV->getVecAtQPs(smallElInfo, largeElInfo, quad, NULL, vec); + else if (basisFct) { + const BasisFunction *localBasisFct = vecDV->getFeSpace()->getBasisFcts(); + + // get coefficients of DOFVector + coeff.change_dim(localBasisFct->getNumber()); + vecDV->getLocalVector(smallElInfo->getElement(), coeff); + + // eval basisfunctions of DOFVector at coords of given basisFct + size_t nBasisFct = basisFct->getNumber(); + vec.change_dim(nBasisFct); + for (size_t i = 0; i < nBasisFct; i++) + vec[i] = localBasisFct->evalUh(*basisFct->getCoords(i), coeff); + } } inline value_type operator()(const int& iq) const { return vec[iq][I]; } -- GitLab