Commit 5e000286 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Introduction of optimized dual mesh traverse procedure.

parent a74b2cdb
...@@ -23,15 +23,17 @@ namespace AMDiS { ...@@ -23,15 +23,17 @@ namespace AMDiS {
rememberElVec(false), rememberElVec(false),
elementMatrix(nRow, nCol), elementMatrix(nRow, nCol),
elementVector(nRow), elementVector(nRow),
tmpMat(nRow, nCol),
lastMatEl(NULL), lastMatEl(NULL),
lastVecEl(NULL), lastVecEl(NULL),
lastTraverseId(-1) lastTraverseId(-1)
{} {}
Assembler::~Assembler() Assembler::~Assembler()
{} {}
void Assembler::calculateElementMatrix(const ElInfo *elInfo, void Assembler::calculateElementMatrix(const ElInfo *elInfo,
ElementMatrix& userMat, ElementMatrix& userMat,
double factor) double factor)
...@@ -110,10 +112,9 @@ namespace AMDiS { ...@@ -110,10 +112,9 @@ namespace AMDiS {
ERROR_EXIT("Da muss i noch ma testen!\n"); ERROR_EXIT("Da muss i noch ma testen!\n");
secondOrderAssembler->calculateElementMatrix(smallElInfo, mat); secondOrderAssembler->calculateElementMatrix(smallElInfo, mat);
ElementMatrix m(nRow, nRow); ElementMatrix &m =
smallElInfo->getSubElemCoordsMat_so(m, rowFESpace->getBasisFcts()->getDegree()); smallElInfo->getSubElemCoordsMat_so(rowFESpace->getBasisFcts()->getDegree());
ElementMatrix tmpMat(nRow, nRow);
tmpMat = m * mat; tmpMat = m * mat;
mat = tmpMat; mat = tmpMat;
} }
...@@ -131,10 +132,8 @@ namespace AMDiS { ...@@ -131,10 +132,8 @@ namespace AMDiS {
if (zeroOrderAssembler) { if (zeroOrderAssembler) {
zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat); zeroOrderAssembler->calculateElementMatrix(smallElInfo, mat);
ElementMatrix m(nRow, nRow); ElementMatrix &m =
smallElInfo->getSubElemCoordsMat(m, rowFESpace->getBasisFcts()->getDegree()); smallElInfo->getSubElemCoordsMat(rowFESpace->getBasisFcts()->getDegree());
ElementMatrix tmpMat(nRow, nRow);
if (smallElInfo == colElInfo) if (smallElInfo == colElInfo)
tmpMat = m * mat; tmpMat = m * mat;
...@@ -366,22 +365,24 @@ namespace AMDiS { ...@@ -366,22 +365,24 @@ namespace AMDiS {
} }
} }
void Assembler::finishAssembling() void Assembler::finishAssembling()
{ {
lastVecEl = NULL; lastVecEl = NULL;
lastMatEl = NULL; lastMatEl = NULL;
} }
OptimizedAssembler::OptimizedAssembler(Operator *op, OptimizedAssembler::OptimizedAssembler(Operator *op,
Quadrature *quad2, Quadrature *quad2,
Quadrature *quad1GrdPsi, Quadrature *quad1GrdPsi,
Quadrature *quad1GrdPhi, Quadrature *quad1GrdPhi,
Quadrature *quad0, Quadrature *quad0,
const FiniteElemSpace *row, const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *col) const FiniteElemSpace *colFeSpace)
: Assembler(op, row, col) : Assembler(op, rowFeSpace, colFeSpace)
{ {
bool opt = (row == col); bool opt = (rowFeSpace->getBasisFcts() == colFeSpace->getBasisFcts());
// create sub assemblers // create sub assemblers
secondOrderAssembler = secondOrderAssembler =
...@@ -396,14 +397,15 @@ namespace AMDiS { ...@@ -396,14 +397,15 @@ namespace AMDiS {
checkQuadratures(); checkQuadratures();
} }
StandardAssembler::StandardAssembler(Operator *op, StandardAssembler::StandardAssembler(Operator *op,
Quadrature *quad2, Quadrature *quad2,
Quadrature *quad1GrdPsi, Quadrature *quad1GrdPsi,
Quadrature *quad1GrdPhi, Quadrature *quad1GrdPhi,
Quadrature *quad0, Quadrature *quad0,
const FiniteElemSpace *row, const FiniteElemSpace *rowFeSpace,
const FiniteElemSpace *col) const FiniteElemSpace *colFeSpace)
: Assembler(op, row, col) : Assembler(op, rowFeSpace, colFeSpace)
{ {
remember = false; remember = false;
......
...@@ -247,6 +247,9 @@ namespace AMDiS { ...@@ -247,6 +247,9 @@ namespace AMDiS {
/// Locally stored element vector /// Locally stored element vector
ElementVector elementVector; ElementVector elementVector;
///
ElementMatrix tmpMat;
/** \brief /** \brief
* Used to check whether \ref initElement() must be called, because * Used to check whether \ref initElement() must be called, because
......
...@@ -87,7 +87,7 @@ namespace AMDiS { ...@@ -87,7 +87,7 @@ namespace AMDiS {
return NULL; return NULL;
} }
int getStatus() inline int getStatus() const
{ {
return status; return status;
} }
...@@ -166,16 +166,30 @@ namespace AMDiS { ...@@ -166,16 +166,30 @@ namespace AMDiS {
return vectorComponents[row]; return vectorComponents[row];
} }
int getStatus(int row, int col) inline int getStatus(int row, int col) const
{ {
return matrixComponents[row][col].getStatus(); return matrixComponents[row][col].getStatus();
} }
int getStatus(int row) inline int getStatus(int row) const
{ {
return vectorComponents[row].getStatus(); 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) const FiniteElemSpace* getAuxFeSpace(int row, int col)
{ {
return matrixComponents[row][col].getAuxFeSpace(); return matrixComponents[row][col].getAuxFeSpace();
...@@ -185,6 +199,24 @@ namespace AMDiS { ...@@ -185,6 +199,24 @@ namespace AMDiS {
{ {
return vectorComponents[row].getAuxFeSpace(); 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 /** \brief
* Returns the row FE space for a given row number, i.e., the FE space * Returns the row FE space for a given row number, i.e., the FE space
......
...@@ -221,6 +221,7 @@ namespace AMDiS { ...@@ -221,6 +221,7 @@ namespace AMDiS {
DegreeOfFreedom col = colIndices[j]; DegreeOfFreedom col = colIndices[j];
double entry = elMat[i][j]; double entry = elMat[i][j];
// std::cout << "ADD at " << row << " " << col << std::endl;
ins[row][col] += entry; ins[row][col] += entry;
} }
} }
......
...@@ -337,8 +337,7 @@ namespace AMDiS { ...@@ -337,8 +337,7 @@ namespace AMDiS {
getLocalVector(largeElInfo->getElement(), localVec); getLocalVector(largeElInfo->getElement(), localVec);
const BasisFunction *basFcts = feSpace->getBasisFcts(); const BasisFunction *basFcts = feSpace->getBasisFcts();
mtl::dense2D<double> m(nBasFcts, nBasFcts); mtl::dense2D<double> &m = smallElInfo->getSubElemCoordsMat(basFcts->getDegree());
smallElInfo->getSubElemCoordsMat(m, basFcts->getDegree());
DimVec<double> &grd1 = *grdTmp[myRank]; DimVec<double> &grd1 = *grdTmp[myRank];
int parts = Global::getGeo(PARTS, dim); int parts = Global::getGeo(PARTS, dim);
...@@ -779,8 +778,7 @@ namespace AMDiS { ...@@ -779,8 +778,7 @@ namespace AMDiS {
double *localVec = localVectors[omp_get_thread_num()]; double *localVec = localVectors[omp_get_thread_num()];
getLocalVector(largeElInfo->getElement(), localVec); getLocalVector(largeElInfo->getElement(), localVec);
mtl::dense2D<double> m(nBasFcts, nBasFcts); mtl::dense2D<double> &m = smallElInfo->getSubElemCoordsMat(basFcts->getDegree());
smallElInfo->getSubElemCoordsMat(m, basFcts->getDegree());
for (int i = 0; i < nPoints; i++) { for (int i = 0; i < nPoints; i++) {
result[i] = 0.0; result[i] = 0.0;
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
namespace AMDiS { 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) ElInfo::ElInfo(Mesh *aMesh)
: mesh(aMesh), : mesh(aMesh),
......
...@@ -239,12 +239,15 @@ namespace AMDiS { ...@@ -239,12 +239,15 @@ namespace AMDiS {
return refinementPathLength; return refinementPathLength;
} }
virtual mtl::dense2D<double>& getSubElemCoordsMat(int degree) const
{
return subElemMatrices[degree][refinementPath];
}
virtual void getSubElemCoordsMat(mtl::dense2D<double>& mat, virtual mtl::dense2D<double>& getSubElemCoordsMat_so(int degree) const
int basisFctsDegree) const {} {
return subElemMatrices[degree][refinementPath];
virtual void getSubElemCoordsMat_so(mtl::dense2D<double>& mat, }
int basisFctsDegree) const {}
/** \} */ /** \} */
...@@ -544,7 +547,7 @@ namespace AMDiS { ...@@ -544,7 +547,7 @@ namespace AMDiS {
mtl::dense2D<double> subElemCoordsMat_so; mtl::dense2D<double> subElemCoordsMat_so;
public: public:
static std::map<unsigned long, mtl::dense2D<double> > subElemMatrices; static std::vector<std::map<unsigned long, mtl::dense2D<double> > > subElemMatrices;
/** \brief /** \brief
* child_vertex[el_type][child][i] = father's local vertex index of new * child_vertex[el_type][child][i] = father's local vertex index of new
......
...@@ -295,45 +295,69 @@ namespace AMDiS { ...@@ -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()"); FUNCNAME("ElInfo1d::getSubElemCoordsMat()");
switch (degree) { using namespace mtl;
case 1:
mat = mat_d1; 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++) { subElemMatrices[1][refinementPath] = mat;
if (refinementPath & (1 << i)) }
mat *= mat_d1_left;
else break;
mat *= mat_d1_right; 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; subElemMatrices[2][refinementPath] = mat;
}
case 2: break;
mat = mat_d2; default:
ERROR_EXIT("Not supported for basis function degree: %d\n", degree);
for (int i = 0; i < refinementPathLength; i++) {
if (refinementPath & (1 << i))
mat *= mat_d2_left;
else
mat *= mat_d2_right;
} }
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()"); FUNCNAME("ElInfo1d::getSubElemCoordsMat_so()");
ERROR_EXIT("Reimplement!\n");
return subElemMatrices[degree][refinementPath];
#if 0
switch (degree) { switch (degree) {
case 1: case 1:
mat = test2_val; mat = test2_val;
...@@ -345,6 +369,7 @@ namespace AMDiS { ...@@ -345,6 +369,7 @@ namespace AMDiS {
default: default:
ERROR_EXIT("Not supported for basis function degree: %d\n", degree); ERROR_EXIT("Not supported for basis function degree: %d\n", degree);
} }
#endif
} }
......
...@@ -62,9 +62,9 @@ namespace AMDiS { ...@@ -62,9 +62,9 @@ namespace AMDiS {
return (i + 1) % 2; 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: protected:
static double mat_d1_val[2][2]; static double mat_d1_val[2][2];
......
...@@ -688,46 +688,47 @@ namespace AMDiS { ...@@ -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()"); FUNCNAME("ElInfo2d::getSubElemCoordsMat()");
using namespace mtl; using namespace mtl;
switch (degree) { if (subElemMatrices[degree].count(refinementPath) == 0) {
case 1: switch (degree) {
{ case 1:
if (subElemMatrices.count(refinementPath) > 0) { {
mat = subElemMatrices[refinementPath]; dense2D<double> mat(mat_d1);
return; dense2D<double> tmpMat(num_rows(mat), num_rows(mat));
}
for (int i = 0; i < refinementPathLength; i++) {
mat = mat_d1; if (refinementPath & (1 << i)) {
dense2D<double> tmpMat(num_rows(mat), num_rows(mat)); tmpMat = mat_d1_right * mat;
mat = tmpMat;
for (int i = 0; i < refinementPathLength; i++) { } else {
if (refinementPath & (1 << i)) { tmpMat = mat_d1_left * mat;
tmpMat = mat_d1_right * mat; mat = tmpMat;
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()"); FUNCNAME("ElInfo2d::getSubElemCoordsMat_so()");
ERROR_EXIT("Not yet implemented!\n"); ERROR_EXIT("Not yet implemented!\n");
return subElemMatrices[degree][refinementPath];
} }
} }
...@@ -58,9 +58,9 @@ namespace AMDiS { ...@@ -58,9 +58,9 @@ namespace AMDiS {
/// 2-dimensional realisation of ElInfo's getElementNormal method. /// 2-dimensional realisation of ElInfo's getElementNormal method.
double getElementNormal(WorldVector<double> &normal) const; 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: protected:
/// Temp vectors for function \ref calcGrdLambda. /// Temp vectors for function \ref calcGrdLambda.
......
...@@ -591,19 +591,23 @@ namespace AMDiS { ...@@ -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()"); FUNCNAME("ElInfo3d::getSubElemCoordsMat()");
ERROR_EXIT("Not yet implemented!\n"); 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()"); FUNCNAME("ElInfo3d::getSubElemCoordsMat_so()");
ERROR_EXIT("Not yet implemented!\n"); ERROR_EXIT("Not yet implemented!\n");
return subElemMatrices[degree][refinementPath];
}