Commit c7cbb878 authored by Thomas Witkowski's avatar Thomas Witkowski

* Performance optimization

parent 64b92aed
......@@ -4,6 +4,7 @@
#include "DOFVector.h"
#include "BasisFunction.h"
#include "Lagrange.h"
#include "OpenMP.h"
namespace AMDiS {
......@@ -14,19 +15,34 @@ namespace AMDiS {
/* are those corresponding to these barycentric coordinates. */
/****************************************************************************/
BasisFunction::~BasisFunction()
{
DELETE nDOF;
}
BasisFunction::BasisFunction(const ::std::string& name_, int dim_, int degree_)
: name(name_), degree(degree_), dim(dim_)
: name(name_),
degree(degree_),
dim(dim_)
{
FUNCNAME("BasisFunction::BasisFunction()");
nDOF = NEW DimVec<int>(dim, DEFAULT_VALUE, -1);
dow = Global::getGeo(WORLD);
grdTmpVec1.resize(omp_get_max_threads());
grdTmpVec2.resize(omp_get_max_threads());
for (int i = 0; i < omp_get_max_threads(); i++) {
grdTmpVec1[i] = NEW DimVec<double>(dim, DEFAULT_VALUE, 0.0);
grdTmpVec2[i] = NEW DimVec<double>(dim, DEFAULT_VALUE, 0.0);
}
};
BasisFunction::~BasisFunction()
{
DELETE nDOF;
for (int i = 0; i < grdTmpVec1.size(); i++) {
DELETE grdTmpVec1[i];
DELETE grdTmpVec2[i];
}
}
/****************************************************************************/
/* some routines for evaluation of a finite element function, its gradient */
......@@ -50,9 +66,8 @@ namespace AMDiS {
const WorldVector<double> *uh_loc,
WorldVector<double>* values) const
{
static WorldVector<double> Values(DEFAULT_VALUE, 0.);
static WorldVector<double> Values(DEFAULT_VALUE, 0.0);
WorldVector<double> *val = (NULL != values) ? values : &Values;
int dow = Global::getGeo(WORLD);
for (int n = 0; n < dow; n++)
(*val)[n] = 0;
......@@ -70,32 +85,27 @@ namespace AMDiS {
const WorldVector<double>& BasisFunction::evalGrdUh(const DimVec<double>& lambda,
const DimVec<WorldVector<double> >& grd_lambda,
const double *uh_loc,
WorldVector<double>* grd_uh) const
WorldVector<double>* val) const
{
static WorldVector<double> grd;
TEST_EXIT_DBG(val)("return value is NULL\n");
DimVec<double> *grdTmp1 = grdTmpVec1[omp_get_thread_num()];
DimVec<double> *grdTmp2 = grdTmpVec2[omp_get_thread_num()];
DimVec<double> grd_b(dim, DEFAULT_VALUE, 0.0);
WorldVector<double> *val;
DimVec<double> grd1(dim, DEFAULT_VALUE, 0.);
val = grd_uh ? grd_uh : &grd;
for (int j = 0; j < dim + 1; j++)
grd1[j] = 0.0;
(*grdTmp2)[j] = 0.0;
for (int i = 0; i < nBasFcts; i++) {
(*(*grdPhi)[i])(lambda, grd_b);
(*(*grdPhi)[i])(lambda, *grdTmp1);
for (int j = 0; j < dim + 1; j++)
grd1[j] += uh_loc[i] * grd_b[j];
(*grdTmp2)[j] += uh_loc[i] * (*grdTmp1)[j];
}
int dow = Global::getGeo(WORLD);
for (int i = 0; i < dow; i++) {
(*val)[i] = 0;
(*val)[i] = 0.0;
for (int j = 0; j < dim + 1; j++)
(*val)[i] += grd_lambda[j][i] * grd1[j];
(*val)[i] += grd_lambda[j][i] * (*grdTmp2)[j];
}
return ((*val));
......@@ -105,7 +115,7 @@ namespace AMDiS {
const DimVec<WorldVector<double> >& grd_lambda,
const double *uh_loc, WorldMatrix<double>* D2_uh) const
{
static WorldMatrix<double> D2(DEFAULT_VALUE, 0.);
static WorldMatrix<double> D2(DEFAULT_VALUE, 0.0);
DimMat<double> D2_b(dim, DEFAULT_VALUE, 0.0);
DimMat<double> D2_tmp(dim, DEFAULT_VALUE, 0.0);
WorldMatrix<double> *val = D2_uh ? D2_uh : &D2;
......@@ -117,8 +127,6 @@ namespace AMDiS {
D2_tmp[k][l] += uh_loc[i] * D2_b[k][l];
}
int dow = Global::getGeo(WORLD);
for (int i = 0; i < dow; i++)
for (int j = 0; j < dow; j++) {
(*val)[i][j] = 0.0;
......
......@@ -432,6 +432,11 @@ namespace AMDiS {
*/
int dim;
/** \brief
* Dimension of the world.
*/
int dow;
/** \brief
* Number of DOFs at the different positions
*/
......@@ -450,7 +455,20 @@ namespace AMDiS {
/** \brief
* Vector of second derivatives
*/
::std::vector<D2BasFctType*> *d2Phi;
::std::vector<D2BasFctType*> *d2Phi;
/** \brief
* Is used by function evalGrdUh. To make it thread safe, we need a
* temporary DimVec for every thread.
*/
::std::vector<DimVec<double>* > grdTmpVec1;
/** \brief
* Is used by function evalGrdUh. To make it thread safe, we need a
* temporary DimVec for every thread.
*/
::std::vector<DimVec<double>* > grdTmpVec2;
};
}
......
......@@ -53,7 +53,7 @@ namespace AMDiS {
// define result vector
static DOFVector<WorldVector<double> > *result = NULL;
if(grad) {
if (grad) {
result = grad;
} else {
if(result && result->getFESpace() != feSpace) {
......@@ -62,8 +62,6 @@ namespace AMDiS {
}
}
int i, j;
Mesh *mesh = feSpace->getMesh();
int dim = mesh->getDim();
......@@ -80,11 +78,11 @@ namespace AMDiS {
int numNodes = 0;
int numDOFs = 0;
for(i = 0; i < dim + 1; i++) {
for (int i = 0; i < dim + 1; i++) {
GeoIndex geoIndex = INDEX_OF_DIM(i, dim);
int numPositionNodes = mesh->getGeo(geoIndex);
int numPreDOFs = admin->getNumberOfPreDOFs(i);
for(j = 0; j < numPositionNodes; j++) {
for (int j = 0; j < numPositionNodes; j++) {
int dofs = basFcts->getNumberOfDOFs(geoIndex);
numNodeDOFs.push_back(dofs);
numDOFs += dofs;
......@@ -99,7 +97,7 @@ namespace AMDiS {
TEST_EXIT_DBG(numDOFs == basFcts->getNumber())
("number of dofs != number of basis functions\n");
for(i = 0; i < numDOFs; i++) {
for (int i = 0; i < numDOFs; i++) {
bary.push_back(basFcts->getCoords(i));
}
......@@ -112,22 +110,19 @@ namespace AMDiS {
ElInfo *elInfo = stack.traverseFirst(mesh, -1, fillFlag);
while(elInfo) {
while (elInfo) {
const DegreeOfFreedom **dof = elInfo->getElement()->getDOF();
const double *localUh = getLocalVector(elInfo->getElement(), NULL);
const DimVec<WorldVector<double> > &grdLambda = elInfo->getGrdLambda();
int localDOFNr = 0;
for(i = 0; i < numNodes; i++) { // for all nodes
for(j = 0; j < numNodeDOFs[i]; j++) { // for all dofs at this node
for (int i = 0; i < numNodes; i++) { // for all nodes
for (int j = 0; j < numNodeDOFs[i]; j++) { // for all dofs at this node
DegreeOfFreedom dofIndex = dof[i][numNodePreDOFs[localDOFNr] + j];
if(!visited[dofIndex]) {
result[dofIndex] = basFcts->evalGrdUh(*(bary[localDOFNr]),
grdLambda,
localUh,
NULL);
if (!visited[dofIndex]) {
basFcts->evalGrdUh(*(bary[localDOFNr]), grdLambda,
localUh, &((*result)[dofIndex]));
visited[dofIndex] = true;
}
......@@ -168,8 +163,6 @@ namespace AMDiS {
DOFVector<double> volume(feSpace, "volume");
volume.set(0.0);
int i;
Mesh *mesh = feSpace->getMesh();
int dim = mesh->getDim();
......@@ -190,17 +183,15 @@ namespace AMDiS {
ElInfo *elInfo = stack.traverseFirst(mesh, -1, fillFlag);
while(elInfo) {
while (elInfo) {
double det = elInfo->getDet();
const DegreeOfFreedom **dof = elInfo->getElement()->getDOF();
const double *localUh = getLocalVector(elInfo->getElement(), NULL);
const DimVec<WorldVector<double> > &grdLambda = elInfo->getGrdLambda();
const WorldVector<double> &grd = basFcts->evalGrdUh(bary,
grdLambda,
localUh,
NULL);
WorldVector<double> grd;
basFcts->evalGrdUh(bary, grdLambda, localUh, &grd);
for(i = 0; i < dim + 1; i++) {
for (int i = 0; i < dim + 1; i++) {
DegreeOfFreedom dofIndex = dof[i][numPreDOFs];
(*result)[dofIndex] += grd * det;
volume[dofIndex] += det;
......@@ -212,8 +203,8 @@ namespace AMDiS {
DOFVector<double>::Iterator volIt(&volume, USED_DOFS);
DOFVector<WorldVector<double> >::Iterator grdIt(result, USED_DOFS);
for(volIt.reset(), grdIt.reset(); !volIt.end(); ++volIt, ++grdIt) {
if(*volIt != 0.0) {
for (volIt.reset(), grdIt.reset(); !volIt.end(); ++volIt, ++grdIt) {
if (*volIt != 0.0) {
*grdIt *= 1.0/(*volIt);
}
}
......@@ -248,7 +239,6 @@ namespace AMDiS {
const BasisFunction *basFcts = feSpace->getBasisFcts();
int numPoints = quadrature->getNumPoints();
int nBasFcts = basFcts->getNumber();
static WorldVector<double> *grd = NULL;
......@@ -349,7 +339,6 @@ namespace AMDiS {
const BasisFunction *basFcts = feSpace->getBasisFcts();
int numPoints = quadrature->getNumPoints();
int nBasFcts = basFcts->getNumber();
int i, j, k, l, iq;
static WorldMatrix<double> *vec = NULL;
......@@ -403,7 +392,6 @@ namespace AMDiS {
for (i = 0; i < nBasFcts; i++) {
WARNING("not tested after index correction\n");
//(*(basFcts->getD2Phi(j)))(quad->getLambda(i), D2Phi);
(*(basFcts->getD2Phi(i)))(quad->getLambda(iq), D2Phi);
for (k = 0; k < parts; k++)
......@@ -441,7 +429,7 @@ namespace AMDiS {
this->set(0.0);
DegreeOfFreedom *localIndices = GET_MEMORY(DegreeOfFreedom, nBasisFcts);
DegreeOfFreedom *myLocalIndices = localIndices[omp_get_thread_num()];
double *sourceLocalCoeffs = GET_MEMORY(double, nSourceBasisFcts);
if (feSpace->getMesh() == sourceFeSpace->getMesh()) {
......@@ -454,13 +442,13 @@ namespace AMDiS {
while (elInfo) {
Element *el = elInfo->getElement();
basisFcts->getLocalIndices(el, feSpace->getAdmin(), localIndices);
basisFcts->getLocalIndices(el, feSpace->getAdmin(), myLocalIndices);
source->getLocalVector(el, sourceLocalCoeffs);
for (int i = 0; i < nBasisFcts; i++) {
if (vec[localIndices[i]] == 0.0) {
if (vec[myLocalIndices[i]] == 0.0) {
coords = basisFcts->getCoords(i);
vec[localIndices[i]] = sourceBasisFcts->evalUh(*coords, sourceLocalCoeffs) * factor;
vec[myLocalIndices[i]] = sourceBasisFcts->evalUh(*coords, sourceLocalCoeffs) * factor;
}
}
elInfo = stack.traverseNext(elInfo);
......@@ -483,12 +471,12 @@ namespace AMDiS {
while (nextTraverse) {
basisFcts->getLocalIndices(elInfo1->getElement(),
feSpace->getAdmin(),
localIndices);
myLocalIndices);
source->getLocalVector(elInfo2->getElement(),
sourceLocalCoeffs);
for (int i = 0; i < nBasisFcts; i++) {
if (vec[localIndices[i]] == 0.0) {
if (vec[myLocalIndices[i]] == 0.0) {
coords1 = basisFcts->getCoords(i);
elInfo1->coordToWorld(*coords1, &worldVec);
elInfo2->worldToCoord(worldVec, &coords2);
......@@ -502,7 +490,7 @@ namespace AMDiS {
}
if (isPositive) {
vec[localIndices[i]] = sourceBasisFcts->evalUh(coords2, sourceLocalCoeffs);
vec[myLocalIndices[i]] = sourceBasisFcts->evalUh(coords2, sourceLocalCoeffs);
}
}
}
......@@ -512,7 +500,6 @@ namespace AMDiS {
}
}
FREE_MEMORY(localIndices, DegreeOfFreedom, nBasisFcts);
FREE_MEMORY(sourceLocalCoeffs, double, nSourceBasisFcts);
}
......@@ -539,7 +526,7 @@ namespace AMDiS {
int vNumBasFcts = vBasFcts->getNumber();
if (feSpace->getMesh() == vFESpace->getMesh()) {
DegreeOfFreedom *localIndices = GET_MEMORY(DegreeOfFreedom, numBasFcts);
DegreeOfFreedom *myLocalIndices = localIndices[omp_get_thread_num()];
WorldVector<double> *vLocalCoeffs = NEW WorldVector<double>[vNumBasFcts];
Mesh *mesh = feSpace->getMesh();
TraverseStack stack;
......@@ -550,20 +537,19 @@ namespace AMDiS {
while (elInfo) {
Element *el = elInfo->getElement();
basFcts->getLocalIndices(el, feSpace->getAdmin(), localIndices);
basFcts->getLocalIndices(el, feSpace->getAdmin(), myLocalIndices);
v->getLocalVector(el, vLocalCoeffs);
for (int i = 0; i < numBasFcts; i++) {
if (vec[localIndices[i]] == nul) {
if (vec[myLocalIndices[i]] == nul) {
coords = basFcts->getCoords(i);
vec[localIndices[i]] += vBasFcts->evalUh(*coords, vLocalCoeffs,NULL) * factor;
vec[myLocalIndices[i]] += vBasFcts->evalUh(*coords, vLocalCoeffs,NULL) * factor;
}
}
elInfo = stack.traverseNext(elInfo);
}
FREE_MEMORY(localIndices, DegreeOfFreedom, numBasFcts);
DELETE [] vLocalCoeffs;
} else {
ERROR_EXIT("not yet for dual traverse\n");
......@@ -651,10 +637,8 @@ namespace AMDiS {
DegreeOfFreedom dofIndex = dof[i][numNodePreDOFs[localDOFNr] + j];
if (!visited[dofIndex]) {
grd = basFcts->evalGrdUh(*(bary[localDOFNr]),
grdLambda,
localUh,
NULL);
basFcts->evalGrdUh(*(bary[localDOFNr]), grdLambda,
localUh, &grd);
for (int k = 0; k < dow; k++) {
(*result)[k][dofIndex] = grd[k];
......
......@@ -38,6 +38,7 @@
#include "CreatorInterface.h"
#include "Serializable.h"
#include "DOFMatrix.h"
#include "BasisFunction.h"
#include <vector>
#include <memory>
#include <list>
......@@ -69,18 +70,17 @@ namespace AMDiS {
class DOFVectorBase : public DOFIndexed<T>
{
public:
DOFVectorBase()
: feSpace(NULL),
elementVector(NULL),
boundaryManager(NULL)
boundaryManager(NULL),
nBasFcts(0)
{};
DOFVectorBase(const FiniteElemSpace *f, ::std::string n);
DOFVectorBase(const FiniteElemSpace *f, ::std::string n)
: feSpace(f),
name(n),
elementVector(NULL),
boundaryManager(NULL)
{};
virtual ~DOFVectorBase();
virtual const T *getLocalVector(const Element *el, T* localVec) const;
......@@ -156,9 +156,14 @@ namespace AMDiS {
*/
T evalUh(const DimVec<double>& lambda, DegreeOfFreedom* ind);
inline ::std::vector<Operator*>& getOperators() { return operators; };
inline ::std::vector<Operator*>& getOperators() {
return operators;
};
inline ::std::vector<double*>& getOperatorFactor() {
return operatorFactor;
};
inline ::std::vector<double*>& getOperatorFactor() { return operatorFactor; };
inline ::std::vector<double*>& getOperatorEstFactor() {
return operatorEstFactor;
};
......@@ -166,45 +171,66 @@ namespace AMDiS {
/** \brief
* Returns \ref name
*/
inline const ::std::string& getName() const { return name; };
inline const ::std::string& getName() const {
return name;
};
inline BoundaryManager* getBoundaryManager() const { return boundaryManager; };
inline BoundaryManager* getBoundaryManager() const {
return boundaryManager;
};
inline void setBoundaryManager(BoundaryManager *bm) {
boundaryManager = bm;
};
protected:
/** \brief
*
*/
const FiniteElemSpace *feSpace;
/** \brief
*
*/
::std::string name;
/** \brief
*
*/
ElementVector *elementVector;
/** \brief
*
*/
::std::vector<Operator*> operators;
/** \brief
*
*/
::std::vector<double*> operatorFactor;
/** \brief
*
*/
::std::vector<double*> operatorEstFactor;
/** \brief
*
*/
BoundaryManager *boundaryManager;
};
/** \brief
* Number of basis functions of the used finite element space.
*/
int nBasFcts;
// template<typename T>
// class QPEvaluatable : public DOFVectorBase<T>
// {
// public:
// QPEvaluatable()
// : DOFVectorBase<T>()
// {};
// QPEvaluatable(const FiniteElemSpace *f, ::std::string n)
// : DOFVectorBase<T>(f, n)
// {};
/** \brief
* Are used to store temporary local dofs of an element.
* Thread safe.
*/
::std::vector<DegreeOfFreedom* > localIndices;
};
// protected:
// };
// ===========================================================================
// ===== defs ================================================================
......@@ -280,7 +306,6 @@ namespace AMDiS {
*/
DOFVector()
: DOFVectorBase<T>(),
//elementVector(NULL),
refineInter(false),
feSpace(NULL),
coarsenOperation(NO_OPERATION)
......@@ -289,7 +314,7 @@ namespace AMDiS {
/** \brief
* Constructs a DOFVector with name n belonging to FiniteElemSpace f
*/
DOFVector(const FiniteElemSpace* f,::std::string n);
DOFVector(const FiniteElemSpace* f, ::std::string n);
/** \brief
* Initialization.
......@@ -300,9 +325,9 @@ namespace AMDiS {
* Copy Constructor
*/
DOFVector(const DOFVector& rhs) {
*this=rhs;
name=rhs.name+"copy";
if(feSpace && feSpace->getAdmin()) {
*this = rhs;
name = rhs.name + "copy";
if (feSpace && feSpace->getAdmin()) {
(dynamic_cast<DOFAdmin*>(feSpace->getAdmin()))->addDOFIndexed(this);
}
};
......@@ -374,16 +399,10 @@ namespace AMDiS {
/** \brief
* Returns \ref vec
*/
// ::std::vector<T>& getVector() const {return (::std::vector<T>&) vec;} ;
::std::vector<T>& getVector() {
return vec;
return vec;
};
// /** \brief
// * Returns \ref feSpace
// */
// inline const FiniteElemSpace* getFESpace() const { return feSpace; };
/** \brief
* Returns size of \ref vec
*/
......@@ -439,9 +458,7 @@ namespace AMDiS {
("Illegal vector index %d.\n",i);
return vec[i];
};
// Andreas Ergaenzungen:
/** \brief
* Calculates Integral of this DOFVector
*/
......@@ -451,10 +468,7 @@ namespace AMDiS {
* Calculates L1 norm of this DOFVector
*/
double L1Norm(Quadrature* q = NULL) const;
// Ende Andreas Ergaenzungen (hier) unten geht es weiter
/** \brief
* Calculates L2 norm of this DOFVector
*/
......@@ -507,16 +521,12 @@ namespace AMDiS {
inline double l1norm() const {
return asum();
};
// hier Andreas Ergaenzung
/** \brief
* Calculates the sum of this DOFVector
*/
T sum() const;
// bis hier Andreas E.
/** \brief
* Sets \ref vec[i] = val, i=0 , ... , size
*/
......@@ -535,58 +545,11 @@ namespace AMDiS {
*/
DOFVector<T>& operator=(const DOFVector<T>& );
//virtual DOFVector<T>& operator-=(const DOFVector<T>& rhs) {
// axpy(-1.0, rhs); return *this;
//};
//virtual DOFVector<T>& operator+=(const DOFVector<T>& rhs) {
// axpy(1.0, rhs); return *this;
//};
/** \brief
* Multiplies all entries of \ref vec with s
*/
//virtual void scal(T s);
/** \brief
* Multiplication with a scalar
*/