// ============================================================================ // == == // == 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 Assembler.h */ /** * \defgroup Assembler Assembler module * * \brief * Contains the operator and assembler classes: * @{ <img src="assembler.png"> @} */ #ifndef AMDIS_ASSEMBLER_H #define AMDIS_ASSEMBLER_H #include <vector> #include "AMDiS_fwd.h" #include "FixVec.h" #include "ZeroOrderAssembler.h" #include "FirstOrderAssembler.h" #include "SecondOrderAssembler.h" #include "ElInfo.h" namespace AMDiS { /** * \ingroup Assembler * * \brief * Assembles element matrices and vectors for a given Operator. Uses * one SubAssembler for all second order terms of the Operator, one for all * first order terms, and one for all zero order terms. */ class Assembler { public: /// Constructor Assembler(Operator *op, const FiniteElemSpace *rowFeSpace, const FiniteElemSpace *colFeSpace = NULL); /// Destructor ~Assembler(); /// Assembles the element matrix for the given ElInfo void calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& userMat, double factor = 1.0); void calculateElementMatrix(const ElInfo *rowElInfo, const ElInfo *colElInfo, const ElInfo *smallElInfo, const ElInfo *largeElInfo, bool rowColFeSpaceEqual, ElementMatrix& userMat, double factor = 1.0); /// Assembles the element vector for the given ElInfo void calculateElementVector(const ElInfo *elInfo, ElementVector& userVec, double factor = 1.0); void calculateElementVector(const ElInfo *mainElInfo, const ElInfo *auxElInfo, const ElInfo *smallElInfo, const ElInfo *largeElInfo, ElementVector& userVec, double factor = 1.0); /// Returns \ref rowFeSpace. inline const FiniteElemSpace* getRowFeSpace() { return rowFeSpace; } /// Returns \ref colFeSpace. inline const FiniteElemSpace* getColFeSpace() { return colFeSpace; } /// Returns \ref nRow. inline int getNRow() { return nRow; } /// Returns \ref nCol. inline int getNCol() { return nCol; } /// Sets \ref rememberElMat. inline void rememberElementMatrix(bool rem) { rememberElMat = rem; } /// Sets \ref rememberElVec. inline void rememberElementVector(bool rem) { rememberElVec = rem; } /// Returns \ref zeroOrderAssembler. inline ZeroOrderAssembler* getZeroOrderAssembler() { return zeroOrderAssembler; } /** \brief * Returns \ref firstOrderAssemblerGrdPsi or \ref firstOrderAssemblerGrdPhi * depending on type. */ inline FirstOrderAssembler* getFirstOrderAssembler(FirstOrderType type = GRD_PSI) { return (type == GRD_PSI) ? firstOrderAssemblerGrdPsi : firstOrderAssemblerGrdPhi; } /// Returns \ref secondOrderAssembler. inline SecondOrderAssembler* getSecondOrderAssembler() { return secondOrderAssembler; } /// Returns \ref operat; inline Operator* getOperator() { return operat; } /// Initialisation for the given ElInfo. The call is deligated to the sub assemblers. void initElement(const ElInfo *smallElInfo, const ElInfo *largeElInfo = NULL, Quadrature *quad = NULL); /// Sets quadratures of all sub assemblers. void setQuadratures(Quadrature *quad2, Quadrature *quad1GrdPsi, Quadrature *quad1GrdPhi, Quadrature *quad0) { if (secondOrderAssembler) { TEST_EXIT(!secondOrderAssembler->getQuadrature()) ("quadrature already existing\n"); secondOrderAssembler->setQuadrature(quad2); } if (firstOrderAssemblerGrdPsi) { TEST_EXIT(!firstOrderAssemblerGrdPsi->getQuadrature()) ("quadrature already existing\n"); firstOrderAssemblerGrdPsi->setQuadrature(quad1GrdPsi); } if (firstOrderAssemblerGrdPhi) { TEST_EXIT(!firstOrderAssemblerGrdPhi->getQuadrature()) ("quadrature already existing\n"); firstOrderAssemblerGrdPhi->setQuadrature(quad1GrdPhi); } if (zeroOrderAssembler) { TEST_EXIT(!zeroOrderAssembler->getQuadrature()) ("quadrature already existing\n"); zeroOrderAssembler->setQuadrature(quad0); } } /// That function must be called after one assembling cycle has been finished. void finishAssembling(); protected: /** \brief * Vector assembling by element matrix-vector multiplication. * Usefull if an element matrix was already calculated. */ void matVecAssemble(const ElInfo *elInfo, ElementVector& vec); /// void matVecAssemble(const ElInfo *mainElInfo, const ElInfo *auxElInfo, const ElInfo *smallElInfo, const ElInfo *largeElInfo, ElementVector& vec); /** \brief * Checks whether quadratures for subassemblers are already set. * If not they will be created. */ void checkQuadratures(); protected: /// Operator this Assembler belongs to. Operator *operat; /// Row FiniteElemSpace. const FiniteElemSpace *rowFeSpace; /// Column FiniteElemSpace. const FiniteElemSpace *colFeSpace; /// Number of rows. int nRow; /// Number of columns. int nCol; /// SubAssembler for the second order terms SecondOrderAssembler *secondOrderAssembler; /// SubAssembler for the first order terms (grdPsi) FirstOrderAssembler *firstOrderAssemblerGrdPsi; /// SubAssembler for the first order terms (grdPhi) FirstOrderAssembler *firstOrderAssemblerGrdPhi; /// SubAssembler for the zero order terms ZeroOrderAssembler *zeroOrderAssembler; /// bool remember; /// Determines whether the element matrix should be stored locally. bool rememberElMat; /// Determines whether the element vector should be stored locally. bool rememberElVec; /// Locally stored element matrix ElementMatrix elementMatrix; /// Locally stored element vector ElementVector elementVector; /// ElementMatrix tmpMat; /** \brief * Used to check whether \ref initElement() must be called, because * a new Element is visited. */ Element* lastMatEl; /** \brief * Used to check whether \ref initElement() must be called, because * a new Element is visited. */ Element* lastVecEl; /// Used to check for new traverse. int lastTraverseId; friend class SubAssembler; friend class ZeroOrderAssembler; friend class FirstOrderAssembler; friend class SecondOrderAssembler; }; /** * \ingroup Assembler * * \brief * Assembler using non optimized sub assemblers. */ class StandardAssembler : public Assembler { public: /// Constructor StandardAssembler(Operator *op, Quadrature *quad2, Quadrature *quad1GrdPsi, Quadrature *quad1GrdPhi, Quadrature *quad0, const FiniteElemSpace *rowFeSpace, const FiniteElemSpace *colFeSpace = NULL); }; /** * \ingroup Assembler * * \brief * Assembler using optimized sub assemblers. */ class OptimizedAssembler : public Assembler { public: /// Constructor OptimizedAssembler(Operator *op, Quadrature *quad2, Quadrature *quad1GrdPsi, Quadrature *quad1GrdPhi, Quadrature *quad0, const FiniteElemSpace *rowFeSpace, const FiniteElemSpace *colFeSpace = NULL); }; } #endif // AMDIS_ASSEMBLER_H