Liebe Gitlab-Nutzer, lieber Gitlab-Nutzer, es ist nun möglich sich mittels des ZIH-Logins/LDAP an unserem Dienst anzumelden. Ein Anmelden über dieses erzeugt ein neues Konto. Das alte Konto ist über den Reiter "Standard" erreichbar. Die Administratoren

Dear Gitlab user, it is now possible to log in to our service using the ZIH login/LDAP. Logging in via this will create a new account. The old account can be accessed via the "Standard" tab. The administrators

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 {
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;
......
......@@ -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
......
......@@ -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
......
......@@ -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;
}
}
......
......@@ -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;
......
......@@ -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),
......
......@@ -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
......
......@@ -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
}
......
......@@ -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];
......
......@@ -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];
}
}
......@@ -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.
......
......@@ -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];
}
}
......@@ -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
......
......@@ -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;
......
......@@ -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 {