Commit 8817dab1 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

* Several optimizations

parent d8b47d8f
...@@ -205,13 +205,17 @@ namespace AMDiS { ...@@ -205,13 +205,17 @@ namespace AMDiS {
problemTime_->initTimestep(adaptInfo_); problemTime_->initTimestep(adaptInfo_);
#ifdef _OPENMP #ifdef _OPENMP
#pragma omp parallel sections if (problemTime_->existsDelayedCalculation()) {
{ #pragma omp parallel sections num_threads(2)
{
#pragma omp section #pragma omp section
problemTime_->startDelayedTimestepCalculation(); problemTime_->startDelayedTimestepCalculation();
#pragma omp section #pragma omp section
oneTimestep();
}
} else {
oneTimestep(); oneTimestep();
} }
#else #else
......
...@@ -30,6 +30,7 @@ namespace AMDiS { ...@@ -30,6 +30,7 @@ namespace AMDiS {
: nRow(0), : nRow(0),
nCol(0), nCol(0),
coordsAtQPs(NULL), coordsAtQPs(NULL),
coordsNumAllocated(0),
quadrature(quadrat), quadrature(quadrat),
psiFast(NULL), psiFast(NULL),
phiFast(NULL), phiFast(NULL),
...@@ -128,16 +129,20 @@ namespace AMDiS { ...@@ -128,16 +129,20 @@ namespace AMDiS {
return coordsAtQPs; return coordsAtQPs;
} }
// not yet calcualted ! if (coordsAtQPs) {
if (coordsAtQPs) if (coordsNumAllocated != numPoints) {
DELETE [] coordsAtQPs; DELETE [] coordsAtQPs;
// allocate memory coordsAtQPs = NEW WorldVector<double>[numPoints];
coordsAtQPs = NEW WorldVector<double>[numPoints]; coordsNumAllocated = numPoints;
}
} else {
coordsAtQPs = NEW WorldVector<double>[numPoints];
coordsNumAllocated = numPoints;
}
// set new values // set new values
WorldVector<double>* k = NULL; WorldVector<double>* k = &(coordsAtQPs[0]);
int l; for (int l = 0; k < &(coordsAtQPs[numPoints]); ++k, ++l) {
for (k = &(coordsAtQPs[0]), l = 0; k < &(coordsAtQPs[numPoints]); ++k, ++l) {
elInfo->coordToWorld(localQuad->getLambda(l), k); elInfo->coordToWorld(localQuad->getLambda(l), k);
} }
......
...@@ -245,6 +245,11 @@ namespace AMDiS { ...@@ -245,6 +245,11 @@ namespace AMDiS {
*/ */
bool coordsValid; bool coordsValid;
/** \brief
* Used for \ref getCoordsAtQP(). Stores the number of allocated WorldVectors.
*/
int coordsNumAllocated;
/** \brief /** \brief
* Needed Quadrature. Constructed in the constructor of SubAssembler * Needed Quadrature. Constructed in the constructor of SubAssembler
*/ */
......
...@@ -414,7 +414,7 @@ namespace AMDiS { ...@@ -414,7 +414,7 @@ namespace AMDiS {
* value of the determinant of the affine linear paraetrization's Jacobian. * value of the determinant of the affine linear paraetrization's Jacobian.
* pure virtual => must be overriden in sub-class. * pure virtual => must be overriden in sub-class.
*/ */
virtual double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const = 0; virtual double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) = 0;
/** \brief /** \brief
* calculates a normal of the given side (1d,2d: edge, 3d: face) of \ref element. * calculates a normal of the given side (1d,2d: edge, 3d: face) of \ref element.
...@@ -422,7 +422,7 @@ namespace AMDiS { ...@@ -422,7 +422,7 @@ namespace AMDiS {
* transformation to the reference element. * transformation to the reference element.
* pure virtual => must be overriden in sub-class. * pure virtual => must be overriden in sub-class.
*/ */
virtual double getNormal(int side, WorldVector<double> &normal) const = 0; virtual double getNormal(int side, WorldVector<double> &normal) = 0;
/** \brief /** \brief
......
...@@ -83,7 +83,7 @@ namespace AMDiS { ...@@ -83,7 +83,7 @@ namespace AMDiS {
/* value of the determinante from the transformation to the reference */ /* value of the determinante from the transformation to the reference */
/* element */ /* element */
/****************************************************************************/ /****************************************************************************/
double ElInfo1d::calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const double ElInfo1d::calcGrdLambda(DimVec<WorldVector<double> >& grd_lam)
{ {
FUNCNAME("ElInfo1d::calcGrdLambda()"); FUNCNAME("ElInfo1d::calcGrdLambda()");
...@@ -149,7 +149,7 @@ namespace AMDiS { ...@@ -149,7 +149,7 @@ namespace AMDiS {
/* coord; return the absulute value of the determinant from the */ /* coord; return the absulute value of the determinant from the */
/* transformation to the reference element */ /* transformation to the reference element */
/****************************************************************************/ /****************************************************************************/
double ElInfo1d::getNormal(int side, WorldVector<double> &normal) const double ElInfo1d::getNormal(int side, WorldVector<double> &normal)
{ {
normal = coord_[side] - coord_[(side + 1) % 2]; normal = coord_[side] - coord_[(side + 1) % 2];
double det = norm(&normal); double det = norm(&normal);
......
...@@ -63,12 +63,12 @@ namespace AMDiS { ...@@ -63,12 +63,12 @@ namespace AMDiS {
/** \brief /** \brief
* 1-dimensional realisation of ElInfo's calcGrdLambda method. * 1-dimensional realisation of ElInfo's calcGrdLambda method.
*/ */
double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const; double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam);
/** \brief /** \brief
* 1-dimensional realisation of ElInfo's getNormal method. * 1-dimensional realisation of ElInfo's getNormal method.
*/ */
double getNormal(int side, WorldVector<double> &normal) const; double getNormal(int side, WorldVector<double> &normal);
/** \brief /** \brief
* 1-dimensional realisation of ElInfo's getElementNormal method. * 1-dimensional realisation of ElInfo's getElementNormal method.
......
...@@ -391,7 +391,7 @@ namespace AMDiS { ...@@ -391,7 +391,7 @@ namespace AMDiS {
} }
} }
double ElInfo2d::calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const double ElInfo2d::calcGrdLambda(DimVec<WorldVector<double> >& grd_lam)
{ {
FUNCNAME("ElInfo2d::calcGrdLambda()"); FUNCNAME("ElInfo2d::calcGrdLambda()");
...@@ -512,7 +512,7 @@ namespace AMDiS { ...@@ -512,7 +512,7 @@ namespace AMDiS {
} }
double ElInfo2d::getNormal(int side, WorldVector<double> &normal) const double ElInfo2d::getNormal(int side, WorldVector<double> &normal)
{ {
FUNCNAME("ElInfo::getNormal()"); FUNCNAME("ElInfo::getNormal()");
......
...@@ -63,12 +63,12 @@ namespace AMDiS { ...@@ -63,12 +63,12 @@ namespace AMDiS {
/** \brief /** \brief
* 2-dimensional realisation of ElInfo's calcGrdLambda method. * 2-dimensional realisation of ElInfo's calcGrdLambda method.
*/ */
double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const; double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam);
/** \brief /** \brief
* 2-dimensional realisation of ElInfo's getNormal method. * 2-dimensional realisation of ElInfo's getNormal method.
*/ */
double getNormal(int side, WorldVector<double> &normal) const; double getNormal(int side, WorldVector<double> &normal);
/** \brief /** \brief
* 2-dimensional realisation of ElInfo's getElementNormal method. * 2-dimensional realisation of ElInfo's getElementNormal method.
......
...@@ -107,30 +107,35 @@ namespace AMDiS { ...@@ -107,30 +107,35 @@ namespace AMDiS {
} }
} }
double ElInfo3d::calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const double ElInfo3d::calcGrdLambda(DimVec<WorldVector<double> >& grd_lam)
{ {
FUNCNAME("ElInfo3d::calcGrdLambda()"); FUNCNAME("ElInfo3d::calcGrdLambda()");
TEST_EXIT_DBG(dimOfWorld == 3) TEST_EXIT_DBG(dimOfWorld == 3)
("dim != dim_of_world ! use parametric elements!\n"); ("dim != dim_of_world ! use parametric elements!\n");
WorldVector<double> e1, e2, e3; int myRank = omp_get_thread_num();
WorldVector<double> v0;
WorldVector<double> *e1 = &tmpWorldVecs[myRank][0];
WorldVector<double> *e2 = &tmpWorldVecs[myRank][1];
WorldVector<double> *e3 = &tmpWorldVecs[myRank][2];
WorldVector<double> *v0 = &tmpWorldVecs[myRank][3];
double det, adet; double det, adet;
double a11, a12, a13, a21, a22, a23, a31, a32, a33; double a11, a12, a13, a21, a22, a23, a31, a32, a33;
testFlag(Mesh::FILL_COORDS); testFlag(Mesh::FILL_COORDS);
v0 = coord_[0]; *v0 = coord_[0];
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
e1[i] = coord_[1][i] - v0[i]; (*e1)[i] = coord_[1][i] - (*v0)[i];
e2[i] = coord_[2][i] - v0[i]; (*e2)[i] = coord_[2][i] - (*v0)[i];
e3[i] = coord_[3][i] - v0[i]; (*e3)[i] = coord_[3][i] - (*v0)[i];
} }
det = e1[0] * (e2[1] * e3[2] - e2[2] * e3[1]) det = (*e1)[0] * ((*e2)[1] * (*e3)[2] - (*e2)[2] * (*e3)[1])
- e1[1] * (e2[0] * e3[2] - e2[2] * e3[0]) - (*e1)[1] * ((*e2)[0] * (*e3)[2] - (*e2)[2] * (*e3)[0])
+ e1[2] * (e2[0] * e3[1] - e2[1] * e3[0]); + (*e1)[2] * ((*e2)[0] * (*e3)[1] - (*e2)[1] * (*e3)[0]);
adet = abs(det); adet = abs(det);
...@@ -141,15 +146,15 @@ namespace AMDiS { ...@@ -141,15 +146,15 @@ namespace AMDiS {
grd_lam[i][j] = 0.0; grd_lam[i][j] = 0.0;
} else { } else {
det = 1.0 / det; det = 1.0 / det;
a11 = (e2[1] * e3[2] - e2[2] * e3[1]) * det; /* (a_ij) = A^{-T} */ a11 = ((*e2)[1] * (*e3)[2] - (*e2)[2] * (*e3)[1]) * det; /* (a_ij) = A^{-T} */
a12 = (e2[2] * e3[0] - e2[0] * e3[2]) * det; a12 = ((*e2)[2] * (*e3)[0] - (*e2)[0] * (*e3)[2]) * det;
a13 = (e2[0] * e3[1] - e2[1] * e3[0]) * det; a13 = ((*e2)[0] * (*e3)[1] - (*e2)[1] * (*e3)[0]) * det;
a21 = (e1[2] * e3[1] - e1[1] * e3[2]) * det; a21 = ((*e1)[2] * (*e3)[1] - (*e1)[1] * (*e3)[2]) * det;
a22 = (e1[0] * e3[2] - e1[2] * e3[0]) * det; a22 = ((*e1)[0] * (*e3)[2] - (*e1)[2] * (*e3)[0]) * det;
a23 = (e1[1] * e3[0] - e1[0] * e3[1]) * det; a23 = ((*e1)[1] * (*e3)[0] - (*e1)[0] * (*e3)[1]) * det;
a31 = (e1[1] * e2[2] - e1[2] * e2[1]) * det; a31 = ((*e1)[1] * (*e2)[2] - (*e1)[2] * (*e2)[1]) * det;
a32 = (e1[2] * e2[0] - e1[0] * e2[2]) * det; a32 = ((*e1)[2] * (*e2)[0] - (*e1)[0] * (*e2)[2]) * det;
a33 = (e1[0] * e2[1] - e1[1] * e2[0]) * det; a33 = ((*e1)[0] * (*e2)[1] - (*e1)[1] * (*e2)[0]) * det;
grd_lam[1][0] = a11; grd_lam[1][0] = a11;
grd_lam[1][1] = a12; grd_lam[1][1] = a12;
...@@ -161,9 +166,9 @@ namespace AMDiS { ...@@ -161,9 +166,9 @@ namespace AMDiS {
grd_lam[3][1] = a32; grd_lam[3][1] = a32;
grd_lam[3][2] = a33; grd_lam[3][2] = a33;
grd_lam[0][0] = -grd_lam[1][0] -grd_lam[2][0] -grd_lam[3][0]; grd_lam[0][0] = -grd_lam[1][0] - grd_lam[2][0] - grd_lam[3][0];
grd_lam[0][1] = -grd_lam[1][1] -grd_lam[2][1] -grd_lam[3][1]; grd_lam[0][1] = -grd_lam[1][1] - grd_lam[2][1] - grd_lam[3][1];
grd_lam[0][2] = -grd_lam[1][2] -grd_lam[2][2] -grd_lam[3][2]; grd_lam[0][2] = -grd_lam[1][2] - grd_lam[2][2] - grd_lam[3][2];
} }
return adet; return adet;
...@@ -305,11 +310,17 @@ namespace AMDiS { ...@@ -305,11 +310,17 @@ namespace AMDiS {
} }
double ElInfo3d::getNormal(int face, WorldVector<double> &normal) const double ElInfo3d::getNormal(int face, WorldVector<double> &normal)
{ {
FUNCNAME("ElInfo3d::getNormal"); FUNCNAME("ElInfo3d::getNormal()");
double det = 0.0; double det = 0.0;
WorldVector<double> e0, e1, e2;
int myRank = omp_get_thread_num();
WorldVector<double> *e0 = &tmpWorldVecs[myRank][0];
WorldVector<double> *e1 = &tmpWorldVecs[myRank][1];
WorldVector<double> *e2 = &tmpWorldVecs[myRank][2];
if (dimOfWorld == 3) { if (dimOfWorld == 3) {
int i0 = (face + 1) % 4; int i0 = (face + 1) % 4;
...@@ -317,14 +328,14 @@ namespace AMDiS { ...@@ -317,14 +328,14 @@ namespace AMDiS {
int i2 = (face + 3) % 4; int i2 = (face + 3) % 4;
for (int i = 0; i < dimOfWorld; i++) { for (int i = 0; i < dimOfWorld; i++) {
e0[i] = coord_[i1][i] - coord_[i0][i]; (*e0)[i] = coord_[i1][i] - coord_[i0][i];
e1[i] = coord_[i2][i] - coord_[i0][i]; (*e1)[i] = coord_[i2][i] - coord_[i0][i];
e2[i] = coord_[face][i] - coord_[i0][i]; (*e2)[i] = coord_[face][i] - coord_[i0][i];
} }
vectorProduct(e0, e1, normal); vectorProduct(*e0, *e1, normal);
if ((e2*normal) < 0.0) if ((*e2 * normal) < 0.0)
for (int i = 0; i < dimOfWorld; i++) for (int i = 0; i < dimOfWorld; i++)
normal[i] = -normal[i]; normal[i] = -normal[i];
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "ElInfo.h" #include "ElInfo.h"
#include "MemoryManager.h" #include "MemoryManager.h"
#include "OpenMP.h"
namespace AMDiS { namespace AMDiS {
...@@ -44,7 +45,15 @@ namespace AMDiS { ...@@ -44,7 +45,15 @@ namespace AMDiS {
/** \brief /** \brief
* Constructor. Calls ElInfo's protected Constructor. * Constructor. Calls ElInfo's protected Constructor.
*/ */
ElInfo3d(Mesh* aMesh) : ElInfo(aMesh) {}; ElInfo3d(Mesh* aMesh)
: ElInfo(aMesh)
{
tmpWorldVecs.resize(omp_get_max_threads());
for (int i = 0; i < static_cast<int>(tmpWorldVecs.size()); i++) {
tmpWorldVecs[i].resize(4);
}
};
/** \brief /** \brief
* Assignment operator * Assignment operator
...@@ -74,12 +83,12 @@ namespace AMDiS { ...@@ -74,12 +83,12 @@ namespace AMDiS {
/** \brief /** \brief
* 3-dimensional realisation of ElInfo's calcGrdLambda method. * 3-dimensional realisation of ElInfo's calcGrdLambda method.
*/ */
double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam) const; double calcGrdLambda(DimVec<WorldVector<double> >& grd_lam);
/** \brief /** \brief
* 3-dimensional realisation of ElInfo's getNormal method. * 3-dimensional realisation of ElInfo's getNormal method.
*/ */
double getNormal(int side, WorldVector<double> &normal) const; double getNormal(int side, WorldVector<double> &normal);
/** \brief /** \brief
* update ElInfo after refinement (of some neighbours). Only in 3d! * update ElInfo after refinement (of some neighbours). Only in 3d!
...@@ -126,6 +135,12 @@ namespace AMDiS { ...@@ -126,6 +135,12 @@ namespace AMDiS {
* element with vertices (0,0,0), (1,1,1), (1,1,0), (1,0,0). * element with vertices (0,0,0), (1,1,1), (1,1,0), (1,0,0).
*/ */
signed char orientation; signed char orientation;
/** \brief
* Tmp vectors used for calculations in calcGrdLambda and getNormal().
* Thread safe!
*/
::std::vector< ::std::vector< WorldVector<double> > > tmpWorldVecs;
}; };
} }
......
...@@ -32,6 +32,10 @@ namespace AMDiS { ...@@ -32,6 +32,10 @@ namespace AMDiS {
void writeDelayedFiles() {}; void writeDelayedFiles() {};
bool isWritingDelayed() {
return false;
};
protected: protected:
/** /**
* Writes element data in tecplot format. * Writes element data in tecplot format.
......
...@@ -72,6 +72,8 @@ namespace AMDiS { ...@@ -72,6 +72,8 @@ namespace AMDiS {
virtual void writeDelayedFiles() = 0; virtual void writeDelayedFiles() = 0;
virtual bool isWritingDelayed() = 0;
void setTraverseProperties(int level, void setTraverseProperties(int level,
Flag flag, Flag flag,
bool (*writeElem)(ElInfo*)) bool (*writeElem)(ElInfo*))
...@@ -153,8 +155,18 @@ namespace AMDiS { ...@@ -153,8 +155,18 @@ namespace AMDiS {
Flag traverseFlag = Mesh::CALL_LEAF_EL, Flag traverseFlag = Mesh::CALL_LEAF_EL,
bool (*writeElem)(ElInfo*) = NULL); bool (*writeElem)(ElInfo*) = NULL);
/** \brief
* Starts the delayed writing.
*/
virtual void writeDelayedFiles(); virtual void writeDelayedFiles();
/** \brief
* Returns true, if the file writer is waiting to start writing.
*/
bool isWritingDelayed() {
return writingIsDelayed_;
}
protected: protected:
/** \brief /** \brief
* Initialization of the filewriter. * Initialization of the filewriter.
......
...@@ -947,13 +947,14 @@ namespace AMDiS { ...@@ -947,13 +947,14 @@ namespace AMDiS {
for (int pos = 0, j = 0; pos <= dim; pos++) { for (int pos = 0, j = 0; pos <= dim; pos++) {
posIndex = INDEX_OF_DIM(pos, dim); posIndex = INDEX_OF_DIM(pos, dim);
n0 = admin->getNumberOfPreDOFs(posIndex);
node0 = admin->getMesh()->getNode(posIndex);
num = Global::getGeo(posIndex, dim);
nrDOFs = admin->getNumberOfDOFs(posIndex); nrDOFs = admin->getNumberOfDOFs(posIndex);
for (int i = 0; i < num; node0++, i++) { if (nrDOFs) {
if (nrDOFs) { n0 = admin->getNumberOfPreDOFs(posIndex);
node0 = admin->getMesh()->getNode(posIndex);
num = Global::getGeo(posIndex, dim);
for (int i = 0; i < num; node0++, i++) {
indi = orderOfPositionIndices(el, posIndex, i); indi = orderOfPositionIndices(el, posIndex, i);
for (int k = 0; k < nrDOFs; k++) for (int k = 0; k < nrDOFs; k++)
......
...@@ -96,7 +96,7 @@ namespace AMDiS { ...@@ -96,7 +96,7 @@ namespace AMDiS {
} }
if (res <= tolerance) { if (res <= tolerance) {
INFO(info,6)("finished successfully with %d iterations\n"); INFO(info,6)("finished successfully with %d iterations\n", iter);
return(1); return(1);
} }
......
...@@ -194,4 +194,13 @@ namespace AMDiS { ...@@ -194,4 +194,13 @@ namespace AMDiS {
problemStat->writeDelayedFiles(); problemStat->writeDelayedFiles();
} }
bool ProblemInstatScal::existsDelayedCalculation()
{
return problemStat->existsDelayedCalculation();
}
bool ProblemInstatVec::existsDelayedCalculation()
{
return problemStat->existsDelayedCalculation();
}
} }
...@@ -206,6 +206,8 @@ namespace AMDiS { ...@@ -206,6 +206,8 @@ namespace AMDiS {
virtual void startDelayedTimestepCalculation(); virtual void startDelayedTimestepCalculation();
virtual bool existsDelayedCalculation();
virtual void serialize(::std::ostream &out) {}; virtual void serialize(::std::ostream &out) {};
...@@ -295,6 +297,8 @@ namespace AMDiS { ...@@ -295,6 +297,8 @@ namespace AMDiS {
virtual void startDelayedTimestepCalculation(); virtual void startDelayedTimestepCalculation();
virtual bool existsDelayedCalculation();
virtual void serialize(::std::ostream &out) {}; virtual void serialize(::std::ostream &out) {};
virtual void deserialize(::std::istream &in) {}; virtual void deserialize(::std::istream &in) {};
...