diff --git a/AMDiS/src/Assembler.cc b/AMDiS/src/Assembler.cc index 0216b10e78a4a3deb68f0662d6c797d0e7460da1..a9a1078e99c6db24f7a03aad9b443d5c31c77c13 100644 --- a/AMDiS/src/Assembler.cc +++ b/AMDiS/src/Assembler.cc @@ -23,15 +23,17 @@ namespace AMDiS { rememberElVec(false), elementMatrix(nRow, nCol), elementVector(nRow), + tmpMat(nRow, nCol), lastMatEl(NULL), lastVecEl(NULL), lastTraverseId(-1) - {} + Assembler::~Assembler() {} + void Assembler::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& userMat, double factor) @@ -110,10 +112,9 @@ namespace AMDiS { ERROR_EXIT("Da muss i noch ma testen!\n"); secondOrderAssembler->calculateElementMatrix(smallElInfo, mat); - ElementMatrix m(nRow, nRow); - smallElInfo->getSubElemCoordsMat_so(m, rowFESpace->getBasisFcts()->getDegree()); + ElementMatrix &m = + smallElInfo->getSubElemCoordsMat_so(rowFESpace->getBasisFcts()->getDegree()); - ElementMatrix tmpMat(nRow, nRow); tmpMat = m * mat; mat = tmpMat; } @@ -131,10 +132,8 @@ namespace AMDiS { if (zeroOrderAssembler) { zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat); - ElementMatrix m(nRow, nRow); - smallElInfo->getSubElemCoordsMat(m, rowFESpace->getBasisFcts()->getDegree()); - - ElementMatrix tmpMat(nRow, nRow); + ElementMatrix &m = + smallElInfo->getSubElemCoordsMat(rowFESpace->getBasisFcts()->getDegree()); if (smallElInfo == colElInfo) tmpMat = m * mat; @@ -366,22 +365,24 @@ namespace AMDiS { } } + void Assembler::finishAssembling() { lastVecEl = NULL; lastMatEl = NULL; } + OptimizedAssembler::OptimizedAssembler(Operator *op, Quadrature *quad2, Quadrature *quad1GrdPsi, Quadrature *quad1GrdPhi, Quadrature *quad0, - const FiniteElemSpace *row, - const FiniteElemSpace *col) - : Assembler(op, row, col) + const FiniteElemSpace *rowFeSpace, + const FiniteElemSpace *colFeSpace) + : Assembler(op, rowFeSpace, colFeSpace) { - bool opt = (row == col); + bool opt = (rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts()); // create sub assemblers secondOrderAssembler = @@ -396,14 +397,15 @@ namespace AMDiS { checkQuadratures(); } + StandardAssembler::StandardAssembler(Operator *op, Quadrature *quad2, Quadrature *quad1GrdPsi, Quadrature *quad1GrdPhi, Quadrature *quad0, - const FiniteElemSpace *row, - const FiniteElemSpace *col) - : Assembler(op, row, col) + const FiniteElemSpace *rowFeSpace, + const FiniteElemSpace *colFeSpace) + : Assembler(op, rowFeSpace, colFeSpace) { remember = false; diff --git a/AMDiS/src/Assembler.h b/AMDiS/src/Assembler.h index 37a84e27e67f91a10edb6d3c07e9bdae3e5fe12c..1328cc219b45aad292e2278acd6e98050ef806da 100644 --- a/AMDiS/src/Assembler.h +++ b/AMDiS/src/Assembler.h @@ -247,6 +247,9 @@ namespace AMDiS { /// Locally stored element vector ElementVector elementVector; + + /// + ElementMatrix tmpMat; /** \brief * Used to check whether \ref initElement() must be called, because diff --git a/AMDiS/src/ComponentTraverseInfo.h b/AMDiS/src/ComponentTraverseInfo.h index d029e3587f874f79451881892a6731b3a265c710..b7123c935900a7e6ee8c89fa7ac4b6b49c3dbe98 100644 --- a/AMDiS/src/ComponentTraverseInfo.h +++ b/AMDiS/src/ComponentTraverseInfo.h @@ -87,7 +87,7 @@ namespace AMDiS { return NULL; } - int getStatus() + inline int getStatus() const { return status; } @@ -166,16 +166,30 @@ namespace AMDiS { return vectorComponents[row]; } - int getStatus(int row, int col) + inline int getStatus(int row, int col) const { return matrixComponents[row][col].getStatus(); } - int getStatus(int row) + inline int getStatus(int row) const { return vectorComponents[row].getStatus(); } + /** \brief + * Returns true, if for the given matrix component the row and the col FE spaces + * are equal. Note that this is also the case, if there is another aux FE space, + * that may be different from both, the row and the col FE spaces. + */ + inline bool eqSpaces(int row, int col) const + { + int status = matrixComponents[row][col].getStatus(); + + return (status == SingleComponentInfo::EQ_SPACES_NO_AUX || + status == SingleComponentInfo::EQ_SPACES_WITH_AUX || + status == SingleComponentInfo::EQ_SPACES_WITH_DIF_AUX); + } + const FiniteElemSpace* getAuxFeSpace(int row, int col) { return matrixComponents[row][col].getAuxFeSpace(); @@ -185,6 +199,24 @@ namespace AMDiS { { return vectorComponents[row].getAuxFeSpace(); } + + /// Returns true if there is an aux FE that is different from row and col FE spaces. + inline bool difAuxSpace(int row, int col) const + { + int status = matrixComponents[row][col].getStatus(); + + return (status == SingleComponentInfo::EQ_SPACES_WITH_DIF_AUX || + status == SingleComponentInfo::DIF_SPACES_WITH_DIF_AUX); + } + + /// Returns true if there is an aux FE that is different from row and col FE spaces. + inline bool difAuxSpace(int row) const + { + int status = vectorComponents[row].getStatus(); + + return (status == SingleComponentInfo::EQ_SPACES_WITH_DIF_AUX || + status == SingleComponentInfo::DIF_SPACES_WITH_DIF_AUX); + } /** \brief * Returns the row FE space for a given row number, i.e., the FE space diff --git a/AMDiS/src/DOFMatrix.cc b/AMDiS/src/DOFMatrix.cc index 0ee1b5a45a0be2e6d81c0f8e41b82ed221a56f87..a8d6589e64f49fce08de7d50c282847c9af2c2a2 100644 --- a/AMDiS/src/DOFMatrix.cc +++ b/AMDiS/src/DOFMatrix.cc @@ -221,6 +221,7 @@ namespace AMDiS { DegreeOfFreedom col = colIndices[j]; double entry = elMat[i][j]; + // std::cout << "ADD at " << row << " " << col << std::endl; ins[row][col] += entry; } } diff --git a/AMDiS/src/DOFVector.cc b/AMDiS/src/DOFVector.cc index b90a5d152a7ad47a41199569a307772ab100e9b9..04ae730c246561c245317174612301ffa6b6a81f 100644 --- a/AMDiS/src/DOFVector.cc +++ b/AMDiS/src/DOFVector.cc @@ -337,8 +337,7 @@ namespace AMDiS { getLocalVector(largeElInfo->getElement(), localVec); const BasisFunction *basFcts = feSpace->getBasisFcts(); - mtl::dense2D<double> m(nBasFcts, nBasFcts); - smallElInfo->getSubElemCoordsMat(m, basFcts->getDegree()); + mtl::dense2D<double> &m = smallElInfo->getSubElemCoordsMat(basFcts->getDegree()); DimVec<double> &grd1 = *grdTmp[myRank]; int parts = Global::getGeo(PARTS, dim); @@ -779,8 +778,7 @@ namespace AMDiS { double *localVec = localVectors[omp_get_thread_num()]; getLocalVector(largeElInfo->getElement(), localVec); - mtl::dense2D<double> m(nBasFcts, nBasFcts); - smallElInfo->getSubElemCoordsMat(m, basFcts->getDegree()); + mtl::dense2D<double> &m = smallElInfo->getSubElemCoordsMat(basFcts->getDegree()); for (int i = 0; i < nPoints; i++) { result[i] = 0.0; diff --git a/AMDiS/src/ElInfo.cc b/AMDiS/src/ElInfo.cc index fe12e9df36a0633aa5cb0b2d9a326cad663b41b7..6ed47f8feba5295f5c95a7036070d8355152f096 100644 --- a/AMDiS/src/ElInfo.cc +++ b/AMDiS/src/ElInfo.cc @@ -14,7 +14,7 @@ namespace AMDiS { - std::map<unsigned long, mtl::dense2D<double> > ElInfo::subElemMatrices; + std::vector<std::map<unsigned long, mtl::dense2D<double> > > ElInfo::subElemMatrices(4); ElInfo::ElInfo(Mesh *aMesh) : mesh(aMesh), diff --git a/AMDiS/src/ElInfo.h b/AMDiS/src/ElInfo.h index a60d70b194657b6f101ffe3e6edf4fecc1baecb1..bd0f395530d0fc945357db966860a02568d4afc3 100644 --- a/AMDiS/src/ElInfo.h +++ b/AMDiS/src/ElInfo.h @@ -239,12 +239,15 @@ namespace AMDiS { return refinementPathLength; } + virtual mtl::dense2D<double>& getSubElemCoordsMat(int degree) const + { + return subElemMatrices[degree][refinementPath]; + } - virtual void getSubElemCoordsMat(mtl::dense2D<double>& mat, - int basisFctsDegree) const {} - - virtual void getSubElemCoordsMat_so(mtl::dense2D<double>& mat, - int basisFctsDegree) const {} + virtual mtl::dense2D<double>& getSubElemCoordsMat_so(int degree) const + { + return subElemMatrices[degree][refinementPath]; + } /** \} */ @@ -544,7 +547,7 @@ namespace AMDiS { mtl::dense2D<double> subElemCoordsMat_so; public: - static std::map<unsigned long, mtl::dense2D<double> > subElemMatrices; + static std::vector<std::map<unsigned long, mtl::dense2D<double> > > subElemMatrices; /** \brief * child_vertex[el_type][child][i] = father's local vertex index of new diff --git a/AMDiS/src/ElInfo1d.cc b/AMDiS/src/ElInfo1d.cc index 4038ff857016df73c087325b39d5c649b299d4b0..0bf6f774d40057ee3b33a5f99c3d272d493334ad 100644 --- a/AMDiS/src/ElInfo1d.cc +++ b/AMDiS/src/ElInfo1d.cc @@ -295,45 +295,69 @@ namespace AMDiS { } - void ElInfo1d::getSubElemCoordsMat(mtl::dense2D<double>& mat, int degree) const + mtl::dense2D<double>& ElInfo1d::getSubElemCoordsMat(int degree) const { FUNCNAME("ElInfo1d::getSubElemCoordsMat()"); - switch (degree) { - case 1: - mat = mat_d1; + using namespace mtl; + + if (subElemMatrices[degree].count(refinementPath) == 0) { + switch (degree) { + case 1: + { + dense2D<double> mat(mat_d1); + dense2D<double> tmpMat(num_rows(mat), num_rows(mat)); + + for (int i = 0; i < refinementPathLength; i++) { + if (refinementPath & (1 << i)) { + tmpMat = mat_d1_right * mat; + mat = tmpMat; + } else { + tmpMat = mat_d1_left * mat; + mat = tmpMat; + } + } - for (int i = 0; i < refinementPathLength; i++) { - if (refinementPath & (1 << i)) - mat *= mat_d1_left; - else - mat *= mat_d1_right; - } + subElemMatrices[1][refinementPath] = mat; + } + + break; + case 2: + { + dense2D<double> mat(mat_d2); + dense2D<double> tmpMat(num_rows(mat), num_rows(mat)); + + for (int i = 0; i < refinementPathLength; i++) { + if (refinementPath & (1 << i)) { + tmpMat = mat_d2_right * mat; + mat = tmpMat; + } else { + tmpMat = mat_d2_left * mat; + mat = tmpMat; + } + } - break; - - case 2: - mat = mat_d2; - - for (int i = 0; i < refinementPathLength; i++) { - if (refinementPath & (1 << i)) - mat *= mat_d2_left; - else - mat *= mat_d2_right; + subElemMatrices[2][refinementPath] = mat; + } + break; + default: + ERROR_EXIT("Not supported for basis function degree: %d\n", degree); } - - break; - - default: - ERROR_EXIT("Not supported for basis function degree: %d\n", degree); } + + return subElemMatrices[degree][refinementPath]; } - void ElInfo1d::getSubElemCoordsMat_so(mtl::dense2D<double>& mat, int degree) const + mtl::dense2D<double>& ElInfo1d::getSubElemCoordsMat_so(int degree) const { FUNCNAME("ElInfo1d::getSubElemCoordsMat_so()"); + ERROR_EXIT("Reimplement!\n"); + + return subElemMatrices[degree][refinementPath]; + +#if 0 switch (degree) { case 1: mat = test2_val; @@ -345,6 +369,7 @@ namespace AMDiS { default: ERROR_EXIT("Not supported for basis function degree: %d\n", degree); } +#endif } diff --git a/AMDiS/src/ElInfo1d.h b/AMDiS/src/ElInfo1d.h index 35c9ff28420d466549e54a289a7392a2a262a712..e2636f12ed99fbc68f49251005b4e491d7ad0934 100644 --- a/AMDiS/src/ElInfo1d.h +++ b/AMDiS/src/ElInfo1d.h @@ -62,9 +62,9 @@ namespace AMDiS { return (i + 1) % 2; } - void getSubElemCoordsMat(mtl::dense2D<double>& mat, int degree) const; + mtl::dense2D<double>& getSubElemCoordsMat(int degree) const; - void getSubElemCoordsMat_so(mtl::dense2D<double>& mat, int degree) const; + mtl::dense2D<double>& getSubElemCoordsMat_so(int degree) const; protected: static double mat_d1_val[2][2]; diff --git a/AMDiS/src/ElInfo2d.cc b/AMDiS/src/ElInfo2d.cc index 9fc6000d7bee21654f0c276673846f9012dcf4b7..2b0ffbee2209872e7c6aac8a3f8a4e36fbb9b561 100644 --- a/AMDiS/src/ElInfo2d.cc +++ b/AMDiS/src/ElInfo2d.cc @@ -688,46 +688,47 @@ namespace AMDiS { } - void ElInfo2d::getSubElemCoordsMat(mtl::dense2D<double>& mat, int degree) const + mtl::dense2D<double>& ElInfo2d::getSubElemCoordsMat(int degree) const { FUNCNAME("ElInfo2d::getSubElemCoordsMat()"); using namespace mtl; - switch (degree) { - case 1: - { - if (subElemMatrices.count(refinementPath) > 0) { - mat = subElemMatrices[refinementPath]; - return; - } - - mat = mat_d1; - dense2D<double> tmpMat(num_rows(mat), num_rows(mat)); - - for (int i = 0; i < refinementPathLength; i++) { - if (refinementPath & (1 << i)) { - tmpMat = mat_d1_right * mat; - mat = tmpMat; - } else { - tmpMat = mat_d1_left * mat; - mat = tmpMat; + if (subElemMatrices[degree].count(refinementPath) == 0) { + switch (degree) { + case 1: + { + dense2D<double> mat(mat_d1); + dense2D<double> tmpMat(num_rows(mat), num_rows(mat)); + + for (int i = 0; i < refinementPathLength; i++) { + if (refinementPath & (1 << i)) { + tmpMat = mat_d1_right * mat; + mat = tmpMat; + } else { + tmpMat = mat_d1_left * mat; + mat = tmpMat; + } } - } - subElemMatrices[refinementPath] = mat; + subElemMatrices[1][refinementPath] = mat; + } + break; + default: + ERROR_EXIT("Not supported for basis function degree: %d\n", degree); } - break; - default: - ERROR_EXIT("Not supported for basis function degree: %d\n", degree); } + + return subElemMatrices[degree][refinementPath]; } - void ElInfo2d::getSubElemCoordsMat_so(mtl::dense2D<double>& mat, int degree) const + mtl::dense2D<double>& ElInfo2d::getSubElemCoordsMat_so(int degree) const { FUNCNAME("ElInfo2d::getSubElemCoordsMat_so()"); ERROR_EXIT("Not yet implemented!\n"); + + return subElemMatrices[degree][refinementPath]; } } diff --git a/AMDiS/src/ElInfo2d.h b/AMDiS/src/ElInfo2d.h index 4d530ab4b5e5e25617424000624212a439bdf955..155221a3479a85631c24c941cc791bfa8540b347 100644 --- a/AMDiS/src/ElInfo2d.h +++ b/AMDiS/src/ElInfo2d.h @@ -58,9 +58,9 @@ namespace AMDiS { /// 2-dimensional realisation of ElInfo's getElementNormal method. double getElementNormal(WorldVector<double> &normal) const; - void getSubElemCoordsMat(mtl::dense2D<double>& mat, int degree) const; + mtl::dense2D<double>& getSubElemCoordsMat(int degree) const; - void getSubElemCoordsMat_so(mtl::dense2D<double>& mat, int degree) const; + mtl::dense2D<double>& getSubElemCoordsMat_so(int degree) const; protected: /// Temp vectors for function \ref calcGrdLambda. diff --git a/AMDiS/src/ElInfo3d.cc b/AMDiS/src/ElInfo3d.cc index 9d72a1056a2c7177a317d21452809e38b7a8d3f4..3e8ace91d9330bdd2c5587121d0acc63631384d4 100644 --- a/AMDiS/src/ElInfo3d.cc +++ b/AMDiS/src/ElInfo3d.cc @@ -591,19 +591,23 @@ namespace AMDiS { } - void ElInfo3d::getSubElemCoordsMat(mtl::dense2D<double>& mat, int degree) const + mtl::dense2D<double>& ElInfo3d::getSubElemCoordsMat(int degree) const { FUNCNAME("ElInfo3d::getSubElemCoordsMat()"); ERROR_EXIT("Not yet implemented!\n"); + + return subElemMatrices[degree][refinementPath]; } - void ElInfo3d::getSubElemCoordsMat_so(mtl::dense2D<double>& mat, int degree) const + mtl::dense2D<double>& ElInfo3d::getSubElemCoordsMat_so(int degree) const { FUNCNAME("ElInfo3d::getSubElemCoordsMat_so()"); ERROR_EXIT("Not yet implemented!\n"); + + return subElemMatrices[degree][refinementPath]; } } diff --git a/AMDiS/src/ElInfo3d.h b/AMDiS/src/ElInfo3d.h index f7364b39c27983f679d7f6e1a0e4a6896a578fa5..d08866f37b46368deeee4f7ba4c53f11adcf03ce 100644 --- a/AMDiS/src/ElInfo3d.h +++ b/AMDiS/src/ElInfo3d.h @@ -80,9 +80,9 @@ namespace AMDiS { orientation = o; } - void getSubElemCoordsMat(mtl::dense2D<double>& mat, int degree) const; + mtl::dense2D<double>& getSubElemCoordsMat(int degree) const; - void getSubElemCoordsMat_so(mtl::dense2D<double>& mat, int degree) const; + mtl::dense2D<double>& getSubElemCoordsMat_so(int degree) const; protected: /** \brief diff --git a/AMDiS/src/FirstOrderAssembler.cc b/AMDiS/src/FirstOrderAssembler.cc index ce304f0af370e0782c328922741b23ce3b9ff1c2..f07620c2b986b560d2b70081f7dea2fbd096520d 100644 --- a/AMDiS/src/FirstOrderAssembler.cc +++ b/AMDiS/src/FirstOrderAssembler.cc @@ -30,12 +30,12 @@ namespace AMDiS { tmpLb.resize(omp_get_overall_max_threads(), Lb); } - FirstOrderAssembler* - FirstOrderAssembler::getSubAssembler(Operator* op, - Assembler *assembler, - Quadrature *quad, - FirstOrderType type, - bool optimized) + + FirstOrderAssembler* FirstOrderAssembler::getSubAssembler(Operator* op, + Assembler *assembler, + Quadrature *quad, + FirstOrderType type, + bool optimized) { std::vector<SubAssembler*> *subAssemblers = optimized ? @@ -101,13 +101,17 @@ namespace AMDiS { return newAssembler; } + Stand10::Stand10(Operator *op, Assembler *assembler, Quadrature *quad) : FirstOrderAssembler(op, assembler, quad, false, GRD_PSI) { + name = "standard first order assembler"; + psi = owner->getRowFESpace()->getBasisFcts(); phi = owner->getColFESpace()->getBasisFcts(); } + void Stand10::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { DimVec<double> grdPsi(dim, DEFAULT_VALUE, 0.0); @@ -137,6 +141,7 @@ namespace AMDiS { } } + void Stand10::calculateElementVector(const ElInfo *elInfo, ElementVector& vec) { DimVec<double> grdPsi(dim, DEFAULT_VALUE, 0.0); @@ -163,7 +168,9 @@ namespace AMDiS { Quad10::Quad10(Operator *op, Assembler *assembler, Quadrature *quad) : FirstOrderAssembler(op, assembler, quad, true, GRD_PSI) - {} + { + name = "fast quadrature first order assembler"; + } void Quad10::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) @@ -208,6 +215,7 @@ namespace AMDiS { } } + void Quad10::calculateElementVector(const ElInfo *elInfo, ElementVector& vec) { VectorOfFixVecs<DimVec<double> > *grdPsi; @@ -244,9 +252,11 @@ namespace AMDiS { } } + Pre10::Pre10(Operator *op, Assembler *assembler, Quadrature *quad) : FirstOrderAssembler(op, assembler, quad, true, GRD_PSI) { + name = "precalculated first order assembler"; } @@ -331,9 +341,13 @@ namespace AMDiS { } } + Quad01::Quad01(Operator *op, Assembler *assembler, Quadrature *quad) : FirstOrderAssembler(op, assembler, quad, true, GRD_PHI) - {} + { + name = "fast quadrature first order assembler"; + } + void Quad01::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { @@ -374,9 +388,13 @@ namespace AMDiS { } } + Pre01::Pre01(Operator *op, Assembler *assembler, Quadrature *quad) : FirstOrderAssembler(op, assembler, quad, true, GRD_PHI) - {} + { + name = "precalculated first order assembler"; + } + void Pre01::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { @@ -422,6 +440,7 @@ namespace AMDiS { } } + void Pre10::calculateElementVector(const ElInfo *elInfo, ElementVector& vec) { const int *k; diff --git a/AMDiS/src/Operator.cc b/AMDiS/src/Operator.cc index ea95dfbd80e7b7b938a58ccb469c836055cf30a5..354b97ff7155c098906d8391deb29f9095e493be 100644 --- a/AMDiS/src/Operator.cc +++ b/AMDiS/src/Operator.cc @@ -1173,7 +1173,7 @@ namespace AMDiS { } void MatrixVec2_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) @@ -1953,7 +1953,7 @@ namespace AMDiS { } void MatrixFct_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); WorldMatrix<double> A; @@ -1986,7 +1986,7 @@ namespace AMDiS { } void Matrix_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) @@ -2021,7 +2021,7 @@ namespace AMDiS { void MatrixGradient_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { FUNCNAME("MatrixGradient_SOT::weakEval()"); @@ -2029,10 +2029,9 @@ namespace AMDiS { TEST_EXIT_DBG(gradAtQPs)("Operator was not initialized correctly!\n"); int nPoints = grdUhAtQP.size(); - WorldMatrix<double> A; for (int iq = 0; iq < nPoints; iq++) { - A = (*f)(gradAtQPs[iq]); - result[iq] += A * grdUhAtQP[iq]; + tmpMat = (*f)(gradAtQPs[iq]); + result[iq] += tmpMat * grdUhAtQP[iq]; } } @@ -2058,7 +2057,7 @@ namespace AMDiS { } void VecAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2088,7 +2087,7 @@ namespace AMDiS { } void Vec2AtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2118,7 +2117,7 @@ namespace AMDiS { } void CoordsAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2148,7 +2147,7 @@ namespace AMDiS { } void FctGradient_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2178,7 +2177,7 @@ namespace AMDiS { } void VecAndGradientAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2214,7 +2213,7 @@ namespace AMDiS { } void VecMatrixGradientAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); WorldMatrix<double> A; @@ -2245,7 +2244,7 @@ namespace AMDiS { } void VecAndCoordsAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2281,7 +2280,7 @@ namespace AMDiS { } void MatrixGradientAndCoords_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); WorldMatrix<double> A; @@ -2312,7 +2311,7 @@ namespace AMDiS { } void VecGradCoordsAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2482,7 +2481,7 @@ namespace AMDiS { } void CoordsAtQP_IJ_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2524,7 +2523,7 @@ namespace AMDiS { } void VecAtQP_IJ_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2674,7 +2673,7 @@ namespace AMDiS { } void VecAndGradAtQP_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { @@ -2775,7 +2774,7 @@ namespace AMDiS { } void General_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); int nVecs = static_cast<int>(vecs_.size()); @@ -2992,7 +2991,7 @@ namespace AMDiS { } void GeneralParametric_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); int nVecs = static_cast<int>(vecs_.size()); @@ -3242,7 +3241,7 @@ namespace AMDiS { } void VecGrad_SOT::weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) { diff --git a/AMDiS/src/Operator.h b/AMDiS/src/Operator.h index 2989692821b1a7c97128dbd5b16f0b2e22abceee..54fb1667896338da9d1c333be4c24831018b17aa 100644 --- a/AMDiS/src/Operator.h +++ b/AMDiS/src/Operator.h @@ -300,7 +300,7 @@ namespace AMDiS { /// Evaluation of \f$ A \nabla u(\vec{x}) \f$ at all quadrature points. virtual void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const = 0; + std::vector<WorldVector<double> > &result) = 0; }; @@ -351,7 +351,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) @@ -418,7 +418,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) @@ -464,7 +464,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -518,7 +518,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// Matrix stroring A. @@ -579,7 +579,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const + std::vector<WorldVector<double> > &result) { int nPoints = grdUhAtQP.size(); for (int iq = 0; iq < nPoints; iq++) @@ -630,7 +630,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -674,7 +674,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -722,7 +722,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: @@ -773,7 +773,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: DOFVectorBase<double>* vec; @@ -791,6 +791,10 @@ namespace AMDiS { /// True, if \ref f provides always a symmetric WorldMatrix<double>. bool symmetric; + + private: + /// Temporary matrix used in \ref MatrixGradient_SOT::weakEval. + WorldMatrix<double> tmpMat; }; /** @@ -825,7 +829,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: DOFVectorBase<double>* vec; @@ -873,7 +877,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: DOFVectorBase<double>* vec; @@ -923,7 +927,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: DOFVectorBase<double>* vec; @@ -977,7 +981,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: DOFVectorBase<double>* vec; @@ -1026,7 +1030,7 @@ namespace AMDiS { double factor); void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -1078,7 +1082,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: DOFVectorBase<double>* vec; @@ -1127,7 +1131,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -1179,7 +1183,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: std::vector<DOFVectorBase<double>*> vecs_; @@ -1236,7 +1240,7 @@ namespace AMDiS { /// Implenetation of SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: std::vector<DOFVectorBase<double>*> vecs_; @@ -2529,7 +2533,7 @@ namespace AMDiS { /// Implements SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -2579,7 +2583,7 @@ namespace AMDiS { /// Implements SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVectors to be evaluated at quadrature points. @@ -2671,7 +2675,7 @@ namespace AMDiS { /// Implements SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); private: /// Stores coordinates at quadrature points. Set in \ref initElement(). @@ -2717,7 +2721,7 @@ namespace AMDiS { /// Implements SecondOrderTerm::weakEval(). void weakEval(const std::vector<WorldVector<double> > &grdUhAtQP, - std::vector<WorldVector<double> > &result) const; + std::vector<WorldVector<double> > &result); protected: /// DOFVector to be evaluated at quadrature points. @@ -3240,7 +3244,7 @@ namespace AMDiS { } /// Returns \ref assembler - Assembler *getAssembler(int rank); + Assembler *getAssembler(int rank = 0); /// Sets \ref assembler void setAssembler(int rank, Assembler *ass); diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc index db21cd06e7254450d2b70ee39eb9cdf8fc1dab3f..822cd79bad16c18a0f08387b77541b2a6ea2be01 100644 --- a/AMDiS/src/ProblemVec.cc +++ b/AMDiS/src/ProblemVec.cc @@ -625,8 +625,12 @@ namespace AMDiS { { FUNCNAME("ProblemVec::buildAfterCoarsen()"); - // printOpenmpTraverseInfo(this, true); + if (dualMeshTraverseRequired()) { + dualAssemble(adaptInfo, flag); + return; + } + // printOpenmpTraverseInfo(this, true); // std::cout << "ElInfo = " << ElInfo::subElemMatrices.size() << std::endl; clock_t first = clock(); @@ -674,6 +678,21 @@ namespace AMDiS { // will be set to false). DOFMatrix *matrix = (*systemMatrix)[i][j]; + if (writeAsmInfo && matrix) { + for (std::vector<Operator*>::iterator it = matrix->getOperatorsBegin(); + it != matrix->getOperatorsEnd(); ++it) { + Assembler *assembler = (*it)->getAssembler(); + if (assembler->getZeroOrderAssembler()) + std::cout << "ZOA: " << assembler->getZeroOrderAssembler()->getName() << std::endl; + if (assembler->getFirstOrderAssembler(GRD_PSI)) + std::cout << "FOA GRD_PSI: " << assembler->getFirstOrderAssembler(GRD_PSI)->getName() << std::endl; + if (assembler->getFirstOrderAssembler(GRD_PHI)) + std::cout << "FOA GRD_PHI: " << assembler->getFirstOrderAssembler(GRD_PHI)->getName() << std::endl; + if (assembler->getSecondOrderAssembler()) + std::cout << "SOA: " << assembler->getSecondOrderAssembler()->getName() << std::endl; + } + } + if (matrix) matrix->calculateNnz(); @@ -706,93 +725,290 @@ namespace AMDiS { if (assembleMatrix && matrix->getBoundaryManager()) matrix->getBoundaryManager()->initMatrix(matrix); - if (traverseInfo.getStatus(i, j) == SingleComponentInfo::EQ_SPACES_NO_AUX || - traverseInfo.getStatus(i, j) == SingleComponentInfo::EQ_SPACES_WITH_AUX) { + // The simplest case: either the right hand side has no operaters, no aux + // fe spaces, or all aux fe spaces are equal to the row and col fe space. + assembleOnOneMesh(componentSpaces[i], + assembleFlag, + assembleMatrix ? matrix : NULL, + ((i == j) && asmVector) ? rhs->getDOFVector(i) : NULL); + + assembledMatrix[i][j] = true; - // Row fe space and col fe space are both equal + if (assembleMatrix) + matrix->finishInsertion(); - if (traverseInfo.getStatus(i) == SingleComponentInfo::EQ_SPACES_NO_AUX || - traverseInfo.getStatus(i) == SingleComponentInfo::EQ_SPACES_WITH_AUX) { + if (assembleMatrix && matrix->getBoundaryManager()) + matrix->getBoundaryManager()->exitMatrix(matrix); + + if (matrix) + nnz += matrix->getBaseMatrix().nnz(); + } - if (writeAsmInfo) - std::cout << "ASM on one mesh!" << std::endl; + // And now assemble boundary conditions on the vectors + assembleBoundaryConditions(rhs->getDOFVector(i), + solution->getDOFVector(i), + componentMeshes[i], + assembleFlag); + } - // The simplest case: either the right hand side has no operaters, no aux - // fe spaces, or all aux fe spaces are equal to the row and col fe space. - assembleOnOneMesh(componentSpaces[i], - assembleFlag, - assembleMatrix ? matrix : NULL, - ((i == j) && asmVector) ? rhs->getDOFVector(i) : NULL); + solverMatrix.setMatrix(*systemMatrix); - } else if (traverseInfo.getStatus(i) == SingleComponentInfo::EQ_SPACES_WITH_DIF_AUX) { + createPrecon(); - // Row fe space and col fe space are both equal, but right hand side has at - // least one another aux fe space. + INFO(info, 8)("fillin of assembled matrix: %d\n", nnz); - if (writeAsmInfo) - std::cout << "ASM on one mesh!" << std::endl; +#ifdef _OPENMP + INFO(info, 8)("buildAfterCoarsen needed %.5f seconds system time / %.5f seconds wallclock time\n", + TIME_USED(first, clock()), omp_get_wtime() - wtime); +#else + INFO(info, 8)("buildAfterCoarsen needed %.5f seconds\n", + TIME_USED(first, clock())); +#endif + } - assembleOnOneMesh(componentSpaces[i], - assembleFlag, - assembleMatrix ? matrix : NULL, - ((i == j) && asmVector) ? rhs->getDOFVector(i) : NULL); - - if (i == j && asmVector) { - if (writeAsmInfo) - std::cout << "ASM vector on two meshes!" << std::endl; - - assembleOnDifMeshes2(componentSpaces[i], - traverseInfo.getAuxFeSpace(i), - assembleFlag, - NULL, - rhs->getDOFVector(i)); - } - } else { - ERROR_EXIT("Possible? If yes, not yet implemented!\n"); + + bool ProblemVec::dualMeshTraverseRequired() + { + FUNCNAME("ProblemVec::dualMeshTraverseRequired()"); + + TEST_EXIT(meshes.size() <= 2)("More than two mneshes are not supported yet!\n"); + + return (meshes.size() == 2); + } + + + void ProblemVec::dualAssemble(AdaptInfo *adaptInfo, Flag flag) + { + FUNCNAME("ProblemVec::dualAssemble()"); + + clock_t first = clock(); +#ifdef _OPENMP + double wtime = omp_get_wtime(); +#endif + + for (int i = 0; i < static_cast<int>(meshes.size()); i++) + meshes[i]->dofCompress(); + + Flag assembleFlag = + flag | + (*systemMatrix)[0][0]->getAssembleFlag() | + rhs->getDOFVector(0)->getAssembleFlag() | + Mesh::CALL_LEAF_EL | + Mesh::FILL_COORDS | + Mesh::FILL_DET | + Mesh::FILL_GRD_LAMBDA | + Mesh::FILL_NEIGH; + + if (useGetBound) + assembleFlag |= Mesh::FILL_BOUND; + + traverseInfo.updateStatus(); + + // Used to calculate the overall number of non zero entries. + int nnz = 0; + + for (int i = 0; i < nComponents; i++) { + + MSG("%d DOFs for %s\n", + componentSpaces[i]->getAdmin()->getUsedSize(), + componentSpaces[i]->getName().c_str()); + + rhs->getDOFVector(i)->set(0.0); + + for (int j = 0; j < nComponents; j++) { + + if (writeAsmInfo) + std::cout << "-------" << i << " " << j << "----------------" << std::endl; + + // Only if this variable is true, the current matrix will be assembled. + bool assembleMatrix = true; + // The DOFMatrix which should be assembled (or not, if assembleMatrix + // will be set to false). + DOFMatrix *matrix = (*systemMatrix)[i][j]; + + if (writeAsmInfo && matrix) { + for (std::vector<Operator*>::iterator it = matrix->getOperatorsBegin(); + it != matrix->getOperatorsEnd(); ++it) { + Assembler *assembler = (*it)->getAssembler(); + if (assembler->getZeroOrderAssembler()) + std::cout << "ZOA: " << assembler->getZeroOrderAssembler()->getName() << std::endl; + if (assembler->getFirstOrderAssembler(GRD_PSI)) + std::cout << "FOA GRD_PSI: " << assembler->getFirstOrderAssembler(GRD_PSI)->getName() << std::endl; + if (assembler->getFirstOrderAssembler(GRD_PHI)) + std::cout << "FOA GRD_PHI: " << assembler->getFirstOrderAssembler(GRD_PHI)->getName() << std::endl; + if (assembler->getSecondOrderAssembler()) + std::cout << "SOA: " << assembler->getSecondOrderAssembler()->getName() << std::endl; } + } - } else if (traverseInfo.getStatus(i, j) == SingleComponentInfo::EQ_SPACES_WITH_DIF_AUX) { - if (writeAsmInfo) - std::cout << "ASM on one mesh!" << std::endl; + if (matrix) + matrix->calculateNnz(); + + // If the matrix was assembled before and it is marked to be assembled + // only once, it will not be assembled. + if (assembleMatrixOnlyOnce[i][j] && assembledMatrix[i][j]) { + assembleMatrix = false; + } else if (matrix) { + matrix->getBaseMatrix(). + change_dim(componentSpaces[i]->getAdmin()->getUsedSize(), + componentSpaces[j]->getAdmin()->getUsedSize()); - assembleOnOneMesh(componentSpaces[i], - assembleFlag, - assembleMatrix ? matrix : NULL, - ((i == j) && asmVector) ? rhs->getDOFVector(i) : NULL); + set_to_zero(matrix->getBaseMatrix()); + matrix->startInsertion(matrix->getNnz()); - if (writeAsmInfo) - std::cout << "ASM on two meshes!" << std::endl; + if (matrix->getBoundaryManager()) + matrix->getBoundaryManager()->initMatrix(matrix); + } - assembleOnDifMeshes2(componentSpaces[i], - traverseInfo.getAuxFeSpace(i, j), - assembleFlag, - assembleMatrix ? matrix : NULL, - ((i == j) && asmVector) ? rhs->getDOFVector(i) : NULL); + // If there is no DOFMatrix, e.g., if it is completly 0, do not assemble. + if (!matrix || !assembleMatrix) + assembleMatrix = false; - } else if (traverseInfo.getStatus(i, j) == SingleComponentInfo::DIF_SPACES_NO_AUX || - traverseInfo.getStatus(i, j) == SingleComponentInfo::DIF_SPACES_WITH_AUX) { + // If the matrix should not be assembled, the rhs vector has to be considered. + // This will be only done, if i == j. So, if both is not true, we can jump + // to the next matrix. + if (!assembleMatrix && i != j) + if (matrix) + nnz += matrix->getBaseMatrix().nnz(); + } + } - if (writeAsmInfo) - std::cout << "ASM on two meshes!" << std::endl; + TEST_EXIT(meshes.size() == 2)("There is something wrong!\n"); - assembleOnDifMeshes(componentSpaces[i], componentSpaces[j], - assembleFlag, - assembleMatrix ? matrix : NULL, - ((i == j) && asmVector) ? rhs->getDOFVector(i) : NULL); - } else { - ERROR_EXIT("Not yet implemented!\n"); + const BasisFunction *basisFcts = componentSpaces[0]->getBasisFcts(); + BoundaryType *bound = + useGetBound ? new BoundaryType[basisFcts->getNumber()] : NULL; + + DualTraverse dualTraverse; + DualElInfo dualElInfo; + int oldElIndex0 = -1; + int oldElIndex1 = -1; + dualTraverse.setFillSubElemMat(true, basisFcts); + bool cont = dualTraverse.traverseFirst(meshes[0], meshes[1], -1, -1, + assembleFlag, assembleFlag, dualElInfo); + + while (cont) { + bool newEl0 = (dualElInfo.rowElInfo->getElement()->getIndex() != oldElIndex0); + bool newEl1 = (dualElInfo.colElInfo->getElement()->getIndex() != oldElIndex1); + oldElIndex0 = dualElInfo.rowElInfo->getElement()->getIndex(); + oldElIndex1 = dualElInfo.colElInfo->getElement()->getIndex(); + + for (int i = 0; i < nComponents; i++) { + for (int j = 0; j < nComponents; j++) { + DOFMatrix *matrix = (*systemMatrix)[i][j]; + + if (!matrix) + continue; + + if (traverseInfo.eqSpaces(i, j)) { + ElInfo *elInfo = NULL; + if (componentMeshes[i] == meshes[0] && newEl0) + elInfo = dualElInfo.rowElInfo; + if (componentMeshes[i] == meshes[1] && newEl1) + elInfo = dualElInfo.colElInfo; + + if (elInfo != NULL) { + if (useGetBound) + basisFcts->getBound(elInfo, bound); + + if (matrix) { + matrix->assemble(1.0, elInfo, bound); + // Take the matrix boundary manager from the public matrix, + // but assemble the boundary conditions on the thread private matrix. + if (matrix->getBoundaryManager()) + matrix->getBoundaryManager()->fillBoundaryConditions(elInfo, matrix); + } + + if (i == j) + rhs->getDOFVector(i)->assemble(1.0, elInfo, bound); + } + + if (traverseInfo.difAuxSpace(i) && i == j) { + ElInfo *mainElInfo, *auxElInfo; + if (traverseInfo.getRowFeSpace(i)->getMesh() == meshes[0]) { + mainElInfo = dualElInfo.rowElInfo; + auxElInfo = dualElInfo.colElInfo; + } else { + mainElInfo = dualElInfo.colElInfo; + auxElInfo = dualElInfo.rowElInfo; + } + + if (useGetBound) + basisFcts->getBound(mainElInfo, bound); + + rhs->getDOFVector(i)->assemble2(1.0, mainElInfo, auxElInfo, + dualElInfo.smallElInfo, dualElInfo.largeElInfo, bound); + } + + if (traverseInfo.difAuxSpace(i, j) && matrix) { + ElInfo *mainElInfo, *auxElInfo; + if (traverseInfo.getRowFeSpace(i)->getMesh() == meshes[0]) { + mainElInfo = dualElInfo.rowElInfo; + auxElInfo = dualElInfo.colElInfo; + } else { + mainElInfo = dualElInfo.colElInfo; + auxElInfo = dualElInfo.rowElInfo; + } + + if (useGetBound) + basisFcts->getBound(mainElInfo, bound); + + matrix->assemble2(1.0, mainElInfo, auxElInfo, + dualElInfo.smallElInfo, dualElInfo.largeElInfo, bound); + + if (matrix->getBoundaryManager()) + matrix->getBoundaryManager()->fillBoundaryConditions(mainElInfo, matrix); + } + } else { + TEST_EXIT_DBG(traverseInfo.getStatus(i, j) != SingleComponentInfo::DIF_SPACES_WITH_DIF_AUX) + ("Not yet supported!\n"); + + ElInfo *rowElInfo, *colElInfo; + if (componentMeshes[i] == meshes[0]) { + rowElInfo = dualElInfo.rowElInfo; + colElInfo = dualElInfo.colElInfo; + } else { + rowElInfo = dualElInfo.colElInfo; + colElInfo = dualElInfo.rowElInfo; + } + + if (useGetBound) + basisFcts->getBound(rowElInfo, bound); + + if (matrix) { + matrix->assemble(1.0, rowElInfo, colElInfo, + dualElInfo.smallElInfo, dualElInfo.largeElInfo, bound); + + if (matrix->getBoundaryManager()) + matrix->getBoundaryManager()->fillBoundaryConditions(rowElInfo, matrix); + } + + if (i == j) + rhs->getDOFVector(i)->assemble(1.0, rowElInfo, bound); + + } } + } - assembledMatrix[i][j] = true; + cont = dualTraverse.traverseNext(dualElInfo); + } - if (assembleMatrix) + + for (int i = 0; i < nComponents; i++) { + for (int j = 0; j < nComponents; j++) { + DOFMatrix *matrix = (*systemMatrix)[i][j]; + + if (matrix) + matrix->removeRowsWithDBC(matrix->getApplyDBCs()); + + if (matrix) matrix->finishInsertion(); - if (assembleMatrix && matrix->getBoundaryManager()) + if (matrix && matrix->getBoundaryManager()) matrix->getBoundaryManager()->exitMatrix(matrix); - + if (matrix) - nnz += matrix->getBaseMatrix().nnz(); + nnz += matrix->getBaseMatrix().nnz(); } // And now assemble boundary conditions on the vectors @@ -1191,112 +1407,6 @@ namespace AMDiS { } - void ProblemVec::assembleOnDifMeshes(FiniteElemSpace *rowFeSpace, - FiniteElemSpace *colFeSpace, - Flag assembleFlag, - DOFMatrix *matrix, - DOFVector<double> *vector) - { - FUNCNAME("ProblemVec::assembleOnDifMeshes()"); - - const BasisFunction *basisFcts = rowFeSpace->getBasisFcts(); - BoundaryType *bound = NULL; - if (useGetBound) - bound = new BoundaryType[basisFcts->getNumber()]; - - if (matrix) - matrix->startInsertion(); - - DualTraverse dualTraverse; - ElInfo *rowElInfo, *colElInfo; - ElInfo *largeElInfo, *smallElInfo; - - dualTraverse.setFillSubElemMat(true, basisFcts); - bool cont = dualTraverse.traverseFirst(rowFeSpace->getMesh(), - colFeSpace->getMesh(), - -1, -1, - assembleFlag, assembleFlag, - &rowElInfo, &colElInfo, - &smallElInfo, &largeElInfo); - while (cont) { - if (useGetBound) - basisFcts->getBound(rowElInfo, bound); - - if (matrix) { - matrix->assemble(1.0, rowElInfo, colElInfo, smallElInfo, largeElInfo, bound); - - if (matrix->getBoundaryManager()) - matrix->getBoundaryManager()->fillBoundaryConditions(rowElInfo, matrix); - } - - if (vector) - vector->assemble(1.0, rowElInfo, bound); - - cont = dualTraverse.traverseNext(&rowElInfo, &colElInfo, - &smallElInfo, &largeElInfo); - } - - if (matrix) - matrix->removeRowsWithDBC(matrix->getApplyDBCs()); - - if (useGetBound) - delete [] bound; - } - - - void ProblemVec::assembleOnDifMeshes2(const FiniteElemSpace *mainFeSpace, - const FiniteElemSpace *auxFeSpace, - Flag assembleFlag, - DOFMatrix *matrix, - DOFVector<double> *vector) - { - FUNCNAME("ProblemVec::assembleOnDifMeshes2()"); - - TEST_EXIT(mainFeSpace)("No main FE space!\n"); - TEST_EXIT(auxFeSpace)("No aux FE space!\n"); - - Mesh *mainMesh = mainFeSpace->getMesh(); - Mesh *auxMesh = auxFeSpace->getMesh(); - - const BasisFunction *basisFcts = mainFeSpace->getBasisFcts(); - BoundaryType *bound = NULL; - if (useGetBound) - bound = new BoundaryType[basisFcts->getNumber()]; - - if (matrix) - matrix->startInsertion(); - - DualTraverse dualTraverse; - ElInfo *mainElInfo, *auxElInfo; - ElInfo *largeElInfo, *smallElInfo; - - dualTraverse.setFillSubElemMat(true, basisFcts); - bool cont = dualTraverse.traverseFirst(mainMesh, auxMesh, -1, -1, - assembleFlag, assembleFlag, - &mainElInfo, &auxElInfo, - &smallElInfo, &largeElInfo); - while (cont) { - if (useGetBound) - basisFcts->getBound(mainElInfo, bound); - - if (matrix) - matrix->assemble2(1.0, mainElInfo, auxElInfo, smallElInfo, largeElInfo, bound); - - if (vector) - vector->assemble2(1.0, mainElInfo, auxElInfo, smallElInfo, largeElInfo, bound); - - cont = dualTraverse.traverseNext(&mainElInfo, &auxElInfo, - &smallElInfo, &largeElInfo); - } - - if (matrix) - matrix->removeRowsWithDBC(matrix->getApplyDBCs()); - - if (useGetBound) - delete [] bound; - } - - void ProblemVec::assembleBoundaryConditions(DOFVector<double> *rhs, DOFVector<double> *solution, Mesh *mesh, @@ -1364,7 +1474,7 @@ namespace AMDiS { ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag); while (elInfo) { if (rhs->getBoundaryManager()) - rhs->getBoundaryManager()-> fillBoundaryConditions(elInfo, rhs); + rhs->getBoundaryManager()->fillBoundaryConditions(elInfo, rhs); if (solution->getBoundaryManager()) solution->getBoundaryManager()->fillBoundaryConditions(elInfo, solution); diff --git a/AMDiS/src/ProblemVec.h b/AMDiS/src/ProblemVec.h index 3017c89d47e71cb42f3b63bfebfcb70db60201d1..9aac3317410c068c354b57915198dde8c1255de8 100644 --- a/AMDiS/src/ProblemVec.h +++ b/AMDiS/src/ProblemVec.h @@ -180,6 +180,10 @@ namespace AMDiS { bool assembleMatrix = true, bool assembleVector = true); + bool dualMeshTraverseRequired(); + + void dualAssemble(AdaptInfo *adaptInfo, Flag flag); + void createPrecon(); @@ -266,19 +270,6 @@ namespace AMDiS { Flag assembleFlag, DOFMatrix *matrix, DOFVector<double> *vector); - /// - void assembleOnDifMeshes(FiniteElemSpace *rowFeSpace, - FiniteElemSpace *colFeSpace, - Flag assembleFlag, - DOFMatrix *matrix, - DOFVector<double> *vector); - - /// - void assembleOnDifMeshes2(const FiniteElemSpace *mainFeSpace, - const FiniteElemSpace *auxFeSpace, - Flag assembleFlag, - DOFMatrix *matrix, - DOFVector<double> *vector); /// void assembleBoundaryConditions(DOFVector<double> *rhs, diff --git a/AMDiS/src/SecondOrderAssembler.cc b/AMDiS/src/SecondOrderAssembler.cc index 0d6fd931da0e0732abb9e54722cbd039cb6b0718..2bd7858f14170760ff7b843c59984f43f33d2096 100644 --- a/AMDiS/src/SecondOrderAssembler.cc +++ b/AMDiS/src/SecondOrderAssembler.cc @@ -21,11 +21,11 @@ namespace AMDiS { : SubAssembler(op, assembler, quad, 2, optimized) {} - SecondOrderAssembler* - SecondOrderAssembler::getSubAssembler(Operator* op, - Assembler *assembler, - Quadrature *quad, - bool optimized) + + SecondOrderAssembler* SecondOrderAssembler::getSubAssembler(Operator* op, + Assembler *assembler, + Quadrature *quad, + bool optimized) { int myRank = omp_get_thread_num(); @@ -78,9 +78,12 @@ namespace AMDiS { return newAssembler; } + Pre2::Pre2(Operator *op, Assembler *assembler, Quadrature *quad) : SecondOrderAssembler(op, assembler, quad, true) { + name = "precalculated second order assembler"; + q11 = Q11PsiPhi::provideQ11PsiPhi(owner->getRowFESpace()->getBasisFcts(), owner->getColFESpace()->getBasisFcts(), quadrature); @@ -91,6 +94,7 @@ namespace AMDiS { } } + Pre2::~Pre2() { for (int i = 0; i < static_cast<int>(tmpLALt.size()); i++) { @@ -99,6 +103,7 @@ namespace AMDiS { } } + void Pre2::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { const int **nEntries; @@ -158,13 +163,17 @@ namespace AMDiS { } } + Quad2::Quad2(Operator *op, Assembler *assembler, Quadrature *quad) : SecondOrderAssembler(op, assembler, quad, true) { + name = "fast quadrature second order assembler"; + tmpVec.resize(omp_get_overall_max_threads()); tmpLALt.resize(omp_get_overall_max_threads()); } + Quad2::~Quad2() { if (!firstCall) { @@ -178,6 +187,7 @@ namespace AMDiS { } } + void Quad2::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { int nPoints = quadrature->getNumPoints(); @@ -247,9 +257,13 @@ namespace AMDiS { } } + Stand2::Stand2(Operator *op, Assembler *assembler, Quadrature *quad) : SecondOrderAssembler(op, assembler, quad, false) - {} + { + name = "standard second order assembler"; + } + void Stand2::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { diff --git a/AMDiS/src/SubAssembler.cc b/AMDiS/src/SubAssembler.cc index e780d6e2a6f404f943a09c72b47443f9b2b33341..2e41ca904073685a397688e2e27561497854f83f 100644 --- a/AMDiS/src/SubAssembler.cc +++ b/AMDiS/src/SubAssembler.cc @@ -26,7 +26,8 @@ namespace AMDiS { owner(assembler), symmetric(true), opt(optimized), - firstCall(true) + firstCall(true), + name("") { const BasisFunction *psi = assembler->rowFESpace->getBasisFcts(); const BasisFunction *phi = assembler->colFESpace->getBasisFcts(); diff --git a/AMDiS/src/SubAssembler.h b/AMDiS/src/SubAssembler.h index 4f5ae9bedf832350b821858d2e403d4a876f7f63..8e66d1ab1b433f8f84304c58ddf5e53ff919a8af 100644 --- a/AMDiS/src/SubAssembler.h +++ b/AMDiS/src/SubAssembler.h @@ -131,6 +131,12 @@ namespace AMDiS { return phiFast; } + /// Returns \ref name. + std::string getName() const + { + return name; + } + protected: /// Updates \ref psiFast and \ref phiFast. FastQuadrature *updateFastQuadrature(FastQuadrature *quadFast, @@ -209,6 +215,9 @@ namespace AMDiS { /// bool firstCall; + /// Name of the assembler. Is used to print information about used assembler. + std::string name; + friend class Assembler; }; diff --git a/AMDiS/src/ZeroOrderAssembler.cc b/AMDiS/src/ZeroOrderAssembler.cc index 736b07b80d151de2b5220fd90c3bec440f702e53..270b15a4fe91a6fab2d0425474eb99bea0ed493b 100644 --- a/AMDiS/src/ZeroOrderAssembler.cc +++ b/AMDiS/src/ZeroOrderAssembler.cc @@ -21,6 +21,7 @@ namespace AMDiS { : SubAssembler(op, assembler, quad, 0, optimized) {} + ZeroOrderAssembler* ZeroOrderAssembler::getSubAssembler(Operator* op, Assembler *assembler, Quadrature *quad, @@ -28,10 +29,9 @@ namespace AMDiS { { int myRank = omp_get_thread_num(); - // check if a assembler is needed at all - if (op->zeroOrder[myRank].size() == 0) { + // check if an assembler is needed at all + if (op->zeroOrder[myRank].size() == 0) return NULL; - } ZeroOrderAssembler *newAssembler; @@ -77,9 +77,13 @@ namespace AMDiS { return newAssembler; } + StandardZOA::StandardZOA(Operator *op, Assembler *assembler, Quadrature *quad) - : ZeroOrderAssembler(op, assembler, quad, false) - {} + : ZeroOrderAssembler(op, assembler, quad, false) + { + name = "standard zero order assembler"; + } + void StandardZOA::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { @@ -132,6 +136,7 @@ namespace AMDiS { } } + void StandardZOA::calculateElementVector(const ElInfo *elInfo, ElementVector& vec) { int nPoints = quadrature->getNumPoints(); @@ -153,12 +158,15 @@ namespace AMDiS { } } + FastQuadZOA::FastQuadZOA(Operator *op, Assembler *assembler, Quadrature *quad) : ZeroOrderAssembler(op, assembler, quad, true) { + name = "fast quadrature zero order assembler"; tmpC.resize(omp_get_overall_max_threads()); } + void FastQuadZOA::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { int nPoints = quadrature->getNumPoints(); @@ -217,6 +225,7 @@ namespace AMDiS { } } + void FastQuadZOA::calculateElementVector(const ElInfo *elInfo, ElementVector& vec) { int myRank = omp_get_thread_num(); @@ -251,11 +260,14 @@ namespace AMDiS { } } + PrecalcZOA::PrecalcZOA(Operator *op, Assembler *assembler, Quadrature *quad) : ZeroOrderAssembler(op, assembler, quad, true) { + name = "precalculated zero order assembler"; } + void PrecalcZOA::calculateElementMatrix(const ElInfo *elInfo, ElementMatrix& mat) { if (firstCall) { @@ -300,6 +312,7 @@ namespace AMDiS { } } + void PrecalcZOA::calculateElementVector(const ElInfo *elInfo, ElementVector& vec) { if (firstCall) {