// ============================================================================ // == == // == AMDiS - Adaptive multidimensional simulations == // == == // == http://www.amdis-fem.org == // == == // ============================================================================ // // Software License for AMDiS // // Copyright (c) 2010 Dresden University of Technology // All rights reserved. // Authors: Simon Vey, Thomas Witkowski et al. // // This file is part of AMDiS // // See also license.opensource.txt in the distribution. /** \file Operator.h */ #ifndef AMDIS_OPERATOR_H #define AMDIS_OPERATOR_H #include #include "AMDiS_fwd.h" #include "FixVec.h" #include "Flag.h" #include "MatrixVector.h" #include "ElInfo.h" #include "AbstractFunction.h" #include "SubAssembler.h" #include "OperatorTerm.h" #include "ZeroOrderTerm.h" #include "FirstOrderTerm.h" #include "SecondOrderTerm.h" namespace AMDiS { using namespace std; /** \brief * An Operator holds all information needed to assemble the system matrix * and the right hand side. It consists of four OperatorTerm lists each storing * Terms of a specific order and type. You can define your own Operator by * creating an empty Operator and than adding OperatorTerms to it. * By calling \ref getElementMatrix() or \ref getElementVector() one can * initiate the assembling procedure. Therefor each Operator has its own * Assembler, especially created for this Operator, by the first call of * \ref getElementMatrix() or \ref getElementVector(). */ class Operator { public: /// Obsolete consructor. Calling this constructor yields an error. Will be removed /// in on of the next revisions. Operator(Flag operatorType, const FiniteElemSpace *rowFeSpace, const FiniteElemSpace *colFeSpace = NULL); /// Constructs an empty Operator of type operatorType for the given FiniteElemSpace. Operator(const FiniteElemSpace *rowFeSpace, const FiniteElemSpace *colFeSpace = NULL); /// Destructor. virtual ~Operator() {} /// Sets \ref optimized. inline void useOptimizedAssembler(bool opt) { optimized = opt; } /// Returns \ref optimized. inline bool isOptimized() { return optimized; } /// Adds a SecondOrderTerm to the Operator template void addSecondOrderTerm(T *term); /// Adds a FirstOrderTerm to the Operator template void addFirstOrderTerm(T *term, FirstOrderType type = GRD_PHI); /// Adds a ZeroOrderTerm to the Operator template void addZeroOrderTerm(T *term); void addTerm(ZeroOrderTerm *term); void addTerm(FirstOrderTerm *term, FirstOrderType type); void addTerm(SecondOrderTerm *term); /** \brief * Calculates the element matrix for this ElInfo and adds it multiplied by * factor to userMat. */ virtual void getElementMatrix(const ElInfo *elInfo, ElementMatrix& userMat, double factor = 1.0); virtual void getElementMatrix(const ElInfo *rowElInfo, const ElInfo *colElInfo, const ElInfo *smallElInfo, const ElInfo *largeElInfo, bool rowColFeSpaceEqual, ElementMatrix& userMat, double factor = 1.0); /** \brief * Calculates the element vector for this ElInfo and adds it multiplied by * factor to userVec. */ virtual void getElementVector(const ElInfo *elInfo, ElementVector& userVec, double factor = 1.0); virtual void getElementVector(const ElInfo *mainElInfo, const ElInfo *auxElInfo, const ElInfo *smallElInfo, const ElInfo *largeElInfo, ElementVector& userVec, double factor = 1.0); /// That function must be called after one assembling cycle has been finished. void finishAssembling(); /// Returns \ref rowFeSpace. inline const FiniteElemSpace *getRowFeSpace() { return rowFeSpace; } /// Returns \ref colFeSpace. inline const FiniteElemSpace *getColFeSpace() { return colFeSpace; } /// Returns \ref auxFeSpaces. inline std::set& getAuxFeSpaces() { return auxFeSpaces; } /// Sets \ref uhOld. void setUhOld(const DOFVectorBase *uhOld); /// Returns \ref uhOld. inline const DOFVectorBase *getUhOld() { return uhOld; } /// Returns \ref assembler Assembler *getAssembler(); /// Sets \ref assembler void setAssembler(Assembler *ass); /// Sets \ref fillFlag, the flag used for this Operator while mesh traversal. inline void setFillFlag(Flag f) { fillFlag = f; } /// Sets \ref needDualTraverse. void setNeedDualTraverse(bool b) { needDualTraverse = b; } /// Returns \ref fillFlag inline Flag getFillFlag() { return fillFlag; } /// Returns \ref needDualTraverse bool getNeedDualTraverse() { return needDualTraverse; } /// Initialization of the needed SubAssemblers using the given quadratures. void initAssembler(Quadrature *quad2, Quadrature *quad1GrdPsi, Quadrature *quad1GrdPhi, Quadrature *quad0); /// Calculates the needed quadrature degree for the given order. int getQuadratureDegree(int order, FirstOrderType firstOrderType = GRD_PHI); /// Evaluation of all terms in \ref zeroOrder. void evalZeroOrder(int nPoints, const ElementVector& uhAtQP, const WorldVector *grdUhAtQP, const WorldMatrix *D2UhAtQP, ElementVector& result, double factor) const { for (vector::const_iterator termIt = zeroOrder.begin(); termIt != zeroOrder.end(); ++termIt) (*termIt)->eval(nPoints, uhAtQP, grdUhAtQP, D2UhAtQP, result, factor); } /// Evaluation of all terms in \ref firstOrderGrdPsi. void evalFirstOrderGrdPsi(int nPoints, const ElementVector& uhAtQP, const WorldVector *grdUhAtQP, const WorldMatrix *D2UhAtQP, ElementVector& result, double factor) const { for (vector::const_iterator termIt = firstOrderGrdPsi.begin(); termIt != firstOrderGrdPsi.end(); ++termIt) (*termIt)->eval(nPoints, uhAtQP, grdUhAtQP, D2UhAtQP, result, factor); } /// Evaluation of all terms in \ref firstOrderGrdPhi. void evalFirstOrderGrdPhi(int nPoints, const ElementVector& uhAtQP, const WorldVector *grdUhAtQP, const WorldMatrix *D2UhAtQP, ElementVector& result, double factor) const { for (vector::const_iterator termIt = firstOrderGrdPhi.begin(); termIt != firstOrderGrdPhi.end(); ++termIt) (*termIt)->eval(nPoints, uhAtQP, grdUhAtQP, D2UhAtQP, result, factor); } /// Evaluation of all terms in \ref secondOrder. void evalSecondOrder(int nPoints, const ElementVector& uhAtQP, const WorldVector *grdUhAtQP, const WorldMatrix *D2UhAtQP, ElementVector& result, double factor) const { for (vector::const_iterator termIt = secondOrder.begin(); termIt != secondOrder.end(); ++termIt) (*termIt)->eval(nPoints, uhAtQP, grdUhAtQP, D2UhAtQP, result, factor); } /// Weak evaluation of all terms in \ref secondOrder. void weakEvalSecondOrder(const vector > &grdUhAtQP, vector > &result) const; /// Calls getLALt() for each term in \ref secondOrder and adds the results to LALt. void getLALt(const ElInfo *elInfo, std::vector > &LALt) const { for (vector::const_iterator termIt = secondOrder.begin(); termIt != secondOrder.end(); ++termIt) static_cast(*termIt)->getLALt(elInfo, LALt); } /// Calls getLb() for each term in \ref firstOrderGrdPsi and adds the results to Lb. void getLbGrdPsi(const ElInfo *elInfo, vector >& Lb) const { for (vector::const_iterator termIt = firstOrderGrdPsi.begin(); termIt != firstOrderGrdPsi.end(); ++termIt) static_cast(*termIt)->getLb(elInfo, Lb); } /// Calls getLb() for each term in \ref firstOrderGrdPhi and adds the results to Lb. void getLbGrdPhi(const ElInfo *elInfo, vector >& Lb) const { for (vector::const_iterator termIt = firstOrderGrdPhi.begin(); termIt != firstOrderGrdPhi.end(); ++termIt) static_cast(*termIt)->getLb(elInfo, Lb); } /// Calls getC() for each term in \ref zeroOrder and adds the results to c. void getC(const ElInfo *elInfo, int nPoints, ElementVector& c) { for (vector::const_iterator termIt = zeroOrder.begin(); termIt != zeroOrder.end(); ++termIt) static_cast(*termIt)->getC(elInfo, nPoints, c); } /// Returns true, if there are second order terms. Returns false otherwise. inline bool secondOrderTerms() { return secondOrder.size() != 0; } /// Returns true, if there are first order terms (grdPsi). Returns false otherwise. inline bool firstOrderTermsGrdPsi() { return firstOrderGrdPsi.size() != 0; } /// Returns true, if there are first order terms (grdPhi). Returns false otherwise. inline bool firstOrderTermsGrdPhi() { return firstOrderGrdPhi.size() != 0; } /// Returns true, if there are zero order terms. Returns false otherwise. inline bool zeroOrderTerms() { return zeroOrder.size() != 0; } public: /// Constant type flag for matrix operators. Obsolete, will be removed! static const Flag MATRIX_OPERATOR; /// Constant type flag for vector operators. Obsolete, will be removed! static const Flag VECTOR_OPERATOR; protected: /// FiniteElemSpace for matrix rows and element vector const FiniteElemSpace *rowFeSpace; /// FiniteElemSpace for matrix columns. Can be equal to \rowFeSpace. const FiniteElemSpace *colFeSpace; /// List of aux fe spaces, e.g., if a term is multiplied with a DOF vector std::set auxFeSpaces; /// Number of rows in the element matrix int nRow; /// Number of columns in the element matrix int nCol; /// Flag for mesh traversal Flag fillFlag; /// If true, the operator needs a dual traverse over two meshes for assembling. bool needDualTraverse; /** \brief * Calculates the element matrix and/or the element vector. It is * created especially for this Operator, when \ref getElementMatrix() * or \ref getElementVector is called for the first time. */ Assembler* assembler; /// List of all second order terms vector secondOrder; /// List of all first order terms derived to psi vector firstOrderGrdPsi; /// List of all first order terms derived to phi vector firstOrderGrdPhi; /// List of all zero order terms vector zeroOrder; /** \brief * Pointer to the solution of the last timestep. Can be used for a more efficient * assemblage of the element vector when the element matrix was already computed. */ const DOFVectorBase *uhOld; /// Spezifies whether optimized assemblers are used or not. bool optimized; friend class Assembler; friend class SubAssembler; friend class ZeroOrderAssembler; friend class FirstOrderAssembler; friend class SecondOrderAssembler; }; } #include "Operator.hh" #endif // AMDIS_OPERATOR_H