From 3b97cf2bb9d8acf118a548eb8d072d5deef5f6a2 Mon Sep 17 00:00:00 2001 From: Thomas Witkowski <thomas.witkowski@gmx.de> Date: Tue, 23 Sep 2008 15:10:22 +0000 Subject: [PATCH] * Parallel assemblage * BoundaryManager.hh deleted, was not included in any file --- AMDiS/src/BasisFunction.h | 23 +++--- AMDiS/src/BoundaryManager.cc | 38 +++++++-- AMDiS/src/BoundaryManager.h | 22 +++-- AMDiS/src/BoundaryManager.hh | 130 ------------------------------ AMDiS/src/DOFMatrix.cc | 60 ++++++++++++-- AMDiS/src/DOFMatrix.h | 17 ++++ AMDiS/src/DOFVector.hh | 2 +- AMDiS/src/Global.h | 7 -- AMDiS/src/Lagrange.cc | 27 +------ AMDiS/src/Lagrange.h | 2 +- AMDiS/src/MultiGridSolver.cc | 14 ++-- AMDiS/src/NonLinUpdater.cc | 45 +++++++---- AMDiS/src/ProblemScal.cc | 9 ++- AMDiS/src/ProblemVec.cc | 113 +++++++++++++++++++------- AMDiS/src/SecondOrderAssembler.cc | 2 +- AMDiS/src/Traverse.h | 5 +- 16 files changed, 268 insertions(+), 248 deletions(-) delete mode 100644 AMDiS/src/BoundaryManager.hh diff --git a/AMDiS/src/BasisFunction.h b/AMDiS/src/BasisFunction.h index b40ee744..e11450a3 100644 --- a/AMDiS/src/BasisFunction.h +++ b/AMDiS/src/BasisFunction.h @@ -177,18 +177,17 @@ namespace AMDiS { DegreeOfFreedom*) const = 0; /** \brief - * Pointer to a function which fills a vector with the boundary types of the - * basis functions; - * getBound(el info, bound) returns a pointer to this vector of length - * \ref nBasFcts where the i-th entry is the boundary type of the i-th basis - * function; bound may be a pointer to a vector which has to be filled - * (compare the dof argument of \ref getDOFIindices); - * such a function needs boundary information; thus, all routines using this - * function on the elements need the FILL_BOUND flag during mesh traversal; - */ - virtual const BoundaryType* getBound(const ElInfo*, BoundaryType *) const { - return NULL; - }; + * The second argument 'bound' has to be a pointer to a vector which has + * to be filled. Its length is \ref nBasFcts (the number of basis functions + * in the used finite element space). After calling this function, the i-th + * entry of the array is the boundary type of the i-th basis function of this + * element. + * + * This function needs boundary information within the ElInfo object; thus, + * all routines using this function on the elements need the FILL_BOUND + * flag during mesh traversal; + */ + virtual void getBound(const ElInfo*, BoundaryType *) const {}; /** \brief * Returns \ref degree of BasisFunction diff --git a/AMDiS/src/BoundaryManager.cc b/AMDiS/src/BoundaryManager.cc index 85fa9016..8ae905e8 100644 --- a/AMDiS/src/BoundaryManager.cc +++ b/AMDiS/src/BoundaryManager.cc @@ -1,19 +1,45 @@ #include "FiniteElemSpace.h" -//#include "BoundaryCondition.h" #include "BoundaryManager.h" #include "DOFIndexed.h" #include "DOFVector.h" #include "Traverse.h" #include "BasisFunction.h" #include "ElInfo.h" +#include "OpenMP.h" namespace AMDiS { + BoundaryManager::BoundaryManager(const FiniteElemSpace *feSpace) + { + localBounds.resize(omp_get_max_threads()); + allocatedMemoryLocalBounds = feSpace->getBasisFcts()->getNumber(); + for (int i = 0; i < static_cast<int>(localBounds.size()); i++) { + localBounds[i] = GET_MEMORY(BoundaryType, allocatedMemoryLocalBounds); + } + } + + BoundaryManager::BoundaryManager(BoundaryManager &bm) + { + localBCs = bm.localBCs; + allocatedMemoryLocalBounds = bm.allocatedMemoryLocalBounds; + localBounds.resize(bm.localBounds.size()); + for (int i = 0; i < static_cast<int>(localBounds.size()); i++) { + localBounds[i] = GET_MEMORY(BoundaryType, allocatedMemoryLocalBounds); + } + } + + BoundaryManager::~BoundaryManager() + { + for (int i = 0; i < static_cast<int>(localBounds.size()); i++) { + FREE_MEMORY(localBounds[i], BoundaryType, allocatedMemoryLocalBounds); + } + } + double BoundaryManager::boundResidual(ElInfo *elInfo, DOFMatrix *matrix, const DOFVectorBase<double> *dv) { - double result = 0; + double result = 0.0; std::map<BoundaryType, BoundaryCondition*>::iterator it; for (it = localBCs.begin(); it != localBCs.end(); ++it) { if ((*it).second) @@ -37,7 +63,7 @@ namespace AMDiS { if (localBCs.size() > 0) { // get boundaries of all DOFs - BoundaryType *localBound = GET_MEMORY(BoundaryType, nBasFcts); + BoundaryType *localBound = localBounds[omp_get_thread_num()]; basisFcts->getBound(elInfo, localBound); // get dof indices @@ -60,8 +86,6 @@ namespace AMDiS { } } } - - FREE_MEMORY(localBound, BoundaryType, nBasFcts); } } @@ -79,7 +103,9 @@ namespace AMDiS { if (localBCs.size() > 0) { // get boundaries of all DOFs - const BoundaryType *localBound = basisFcts->getBound(elInfo, NULL); + BoundaryType *localBound = localBounds[omp_get_thread_num()]; + basisFcts->getBound(elInfo, localBound); + // get dof indices basisFcts->getLocalIndicesVec(elInfo->getElement(), admin, &dofIndices); diff --git a/AMDiS/src/BoundaryManager.h b/AMDiS/src/BoundaryManager.h index a593b89b..f90ac30d 100644 --- a/AMDiS/src/BoundaryManager.h +++ b/AMDiS/src/BoundaryManager.h @@ -50,6 +50,12 @@ namespace AMDiS { public: MEMORY_MANAGED(BoundaryManager); + BoundaryManager(const FiniteElemSpace *feSpace); + + BoundaryManager(BoundaryManager &bm); + + ~BoundaryManager(); + /** \brief * Adds a local boundary condition to the list of managed conditions. */ @@ -92,11 +98,6 @@ namespace AMDiS { return localBCs[type]; }; - // /** \brief - // * Fills boundary types in DOFVectorBase bound. - // */ - // void fillGlobalBoundVector(DOFVectorBase<BoundaryType> *bound); - const std::map<BoundaryType, BoundaryCondition*>& getBoundaryConditionMap() { return localBCs; }; @@ -110,6 +111,17 @@ namespace AMDiS { * Map of managed local boundary conditions. */ std::map<BoundaryType, BoundaryCondition*> localBCs; + + /** \brief + * Temporary thread-safe variable for functions fillBoundaryconditions. + */ + std::vector<BoundaryType*> localBounds; + + /** \brief + * Stores the number of byte that were allocated in the constructor for + * each localBounds value. Is used to free the memory in the destructor. + */ + int allocatedMemoryLocalBounds; }; } diff --git a/AMDiS/src/BoundaryManager.hh b/AMDiS/src/BoundaryManager.hh deleted file mode 100644 index 51333d35..00000000 --- a/AMDiS/src/BoundaryManager.hh +++ /dev/null @@ -1,130 +0,0 @@ -#include "FiniteElemSpace.h" -#include "DOFIndexed.h" -#include "DOFVector.h" -#include "Traverse.h" -#include "BasisFunction.h" -#include "ElInfo.h" -#include "BoundaryCondition.h" -#include <list> - -namespace AMDiS { - - template<typename T> - double BoundaryManager<T>::boundResidual(ElInfo *elInfo, Estimator<T> *estimator) - { - double result = 0; - typename std::list<LocalBC<T>*>::iterator it; - for(it = localBCs.begin(); it != localBCs.end(); ++it) { - result += (*it)->boundResidual(elInfo, estimator); - } - return result; - } - - template<typename T> - void BoundaryManager<T>::fillGlobalBoundVector(DOFVector<BoundaryType> *globalBound) - { - int i; - TraverseStack stack; - const FiniteElemSpace *feSpace = globalBound->getFESpace(); - - const BasisFunction *basisFcts = feSpace->getBasisFcts(); - int nBasFcts = basisFcts->getNumber(); - Mesh *mesh = feSpace->getMesh(); - DOFAdmin *admin = feSpace->getAdmin(); - - const BoundaryType *localBound = NULL; - const DegreeOfFreedom *dofIndices = NULL; - - ElInfo *elInfo = - stack.traverseFirst(mesh, -1, - Mesh::CALL_LEAF_EL | - Mesh::FILL_BOUND | - Mesh::FILL_COORDS); - - // for all elements ... - while(elInfo) { - // get boundaries of all DOFs - localBound = basisFcts->getBound(elInfo, NULL); - - // get dof indices - dofIndices = basisFcts->getLocalIndices(elInfo->getElement(), - admin, NULL); - - // for all DOFs - for(i=0; i < nBasFcts; i++) { - (*globalBound)[dofIndices[i]] = localBound[i]; - } - - elInfo = stack.traverseNext(elInfo); - } - } - - template<typename T> - void BoundaryManager<T>::fillLocalBCs(ElInfo *elInfo, - DOFVector<T> *vec) - { - int i; - - // ===== fill local conditions ============================================== - const FiniteElemSpace *feSpace = vec->getFESpace(); - const BoundaryType *localBound = NULL; - const DegreeOfFreedom *dofIndices = NULL; - Mesh *mesh = feSpace->getMesh(); - const BasisFunction *basisFcts = feSpace->getBasisFcts(); - int nBasFcts = basisFcts->getNumber(); - LocalBC<T> *localBC; - DOFAdmin *admin = feSpace->getAdmin(); - - typename std::list<LocalBC<T>*>::iterator it; - - if(localBCs.size() > 0) { - - // get boundaries of all DOFs - localBound = basisFcts->getBound(elInfo, NULL); - - // get dof indices - dofIndices = basisFcts->getLocalIndices(elInfo->getElement(), - admin, NULL); - - // apply boundary conditions - for(it = localBCs.begin(); it != localBCs.end(); ++it) { - (*it)->fillLocalBC(vec, elInfo, dofIndices, localBound, nBasFcts); - } - } - } - - template<typename T> - void BoundaryManager<T>::fillLocalBCs(ElInfo *elInfo, - DOFMatrix *mat) - { - int i; - - // ===== fill local conditions ============================================== - const FiniteElemSpace *feSpace = mat->getRowFESpace(); - const BoundaryType *localBound = NULL; - const DegreeOfFreedom *dofIndices = NULL; - Mesh *mesh = feSpace->getMesh(); - const BasisFunction *basisFcts = feSpace->getBasisFcts(); - int nBasFcts = basisFcts->getNumber(); - LocalBC<T> *localBC; - DOFAdmin *admin = feSpace->getAdmin(); - - typename std::list<LocalBC<T>*>::iterator it; - - if(localBCs.size() > 0) { - - // get boundaries of all DOFs - localBound = basisFcts->getBound(elInfo, NULL); - - // get dof indices - dofIndices = basisFcts->getLocalIndices(elInfo->getElement(), - admin, NULL); - - // apply boundary conditions - for(it = localBCs.begin(); it != localBCs.end(); ++it) { - (*it)->fillLocalBC(mat, elInfo, dofIndices, localBound, nBasFcts); - } - } - } - -} diff --git a/AMDiS/src/DOFMatrix.cc b/AMDiS/src/DOFMatrix.cc index d1358583..2398e57f 100644 --- a/AMDiS/src/DOFMatrix.cc +++ b/AMDiS/src/DOFMatrix.cc @@ -42,9 +42,11 @@ namespace AMDiS { if (rowFESpace && rowFESpace->getAdmin()) (const_cast<DOFAdmin*>(rowFESpace->getAdmin()))->addDOFIndexed(this); - boundaryManager = NEW BoundaryManager; + boundaryManager = NEW BoundaryManager(rowFESpace_); elementMatrix = NEW ElementMatrix(rowFESpace->getBasisFcts()->getNumber(), colFESpace->getBasisFcts()->getNumber()); + + applyDBCs.clear(); } DOFMatrix::DOFMatrix(const DOFMatrix& rhs) @@ -215,7 +217,7 @@ namespace AMDiS { operatorFactor = rhs.operatorFactor; matrix = rhs.matrix; if (rhs.boundaryManager) { - boundaryManager = new BoundaryManager(*rhs.boundaryManager); + boundaryManager = NEW BoundaryManager(*rhs.boundaryManager); } else { boundaryManager = NULL; } @@ -248,14 +250,15 @@ namespace AMDiS { bound ? boundaryManager->getBoundaryCondition(bound[i]) : NULL; if (condition && condition->isDirichlet()) { - MatrixRow *matrixRow = &(matrix[row]); + /* MatrixRow *matrixRow = &(matrix[row]); if (coupleMatrix) { matrixRow->resize(0); } else { matrixRow->resize(1); ((*matrixRow)[0]).col = row; - ((*matrixRow)[0]).entry = 1.0; - } + ((*matrixRow)[0]).entry = 1.0; + } */ + applyDBCs.insert(static_cast<int>(row)); } else { for (int j = 0; j < nCol; j++) { // for all columns addSparseDOFEntry(sign, row, elMat.colIndices[j], @@ -653,6 +656,21 @@ namespace AMDiS { } } + void DOFMatrix::removeRowsWithDBC(std::set<int> *rows) + { + for (std::set<int>::iterator it = rows->begin(); + it != rows->end(); + ++it) { + if (coupleMatrix) { + matrix[*it].resize(0); + } else { + matrix[*it].resize(1); + matrix[*it][0].col = *it; + matrix[*it][0].entry = 1.0; + } + } + } + void DOFMatrix::createPictureFile(const char* filename, int dim) { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); @@ -814,4 +832,36 @@ namespace AMDiS { } } + void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a) + { + DOFMatrix::Iterator resultIterator(result, USED_DOFS); + DOFMatrix::Iterator aIterator(const_cast<DOFMatrix*>(a), USED_DOFS); + + for (resultIterator.reset(), aIterator.reset(); + !aIterator.end(); + ++resultIterator, ++aIterator) { + std::vector<MatEntry>::iterator resultRowIt; + std::vector<MatEntry>::const_iterator aRowIt; + + for (aRowIt = aIterator->begin(); + aRowIt != aIterator->end(); + ++aRowIt) { + bool added = false; + for (resultRowIt = resultIterator->begin(); + resultRowIt != resultIterator->end(); + ++resultRowIt) { + if (aRowIt->col == resultRowIt->col) { + resultRowIt->entry += aRowIt->entry; + + added = true; + break; + } + } + + if (!added) { + resultIterator->push_back(*aRowIt); + } + } + } + } } diff --git a/AMDiS/src/DOFMatrix.h b/AMDiS/src/DOFMatrix.h index 77b51fe2..61386b3f 100644 --- a/AMDiS/src/DOFMatrix.h +++ b/AMDiS/src/DOFMatrix.h @@ -27,6 +27,7 @@ // ============================================================================ #include <vector> +#include <set> #include <memory> #include <list> #include "Global.h" @@ -581,6 +582,8 @@ namespace AMDiS { void addRow(std::vector<MatEntry> row); + void removeRowsWithDBC(std::set<int> *rows); + /** \brief * Prints \ref matrix to stdout */ @@ -619,6 +622,10 @@ namespace AMDiS { return boundaryManager; }; + std::set<int>* getApplyDBCs() { + return &applyDBCs; + } + inline void setBoundaryManager(BoundaryManager *bm) { boundaryManager = bm; }; @@ -720,6 +727,8 @@ namespace AMDiS { */ ElementMatrix *elementMatrix; + std::set<int> applyDBCs; + friend class DOFAdmin; friend class DOFVector<double>; friend class DOFVector<unsigned char>; @@ -739,8 +748,16 @@ namespace AMDiS { double max(std::vector<MatEntry> *row); + /** \brief + * Addes two matrices. The result matrix is overwritten. + */ void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a, const DOFMatrix *b); + /** \brief + * Addes matrix a to matrix result. + */ + void addDOFMatrix(DOFMatrix *result, const DOFMatrix *a); + } #endif // AMDIS_DOFMATRIX_H diff --git a/AMDiS/src/DOFVector.hh b/AMDiS/src/DOFVector.hh index 3fe022e4..e58c6449 100644 --- a/AMDiS/src/DOFVector.hh +++ b/AMDiS/src/DOFVector.hh @@ -70,7 +70,7 @@ namespace AMDiS { (feSpace->getAdmin())->addDOFIndexed(this); } - this->boundaryManager = NEW BoundaryManager; + this->boundaryManager = NEW BoundaryManager(f); } template<typename T> diff --git a/AMDiS/src/Global.h b/AMDiS/src/Global.h index b9aacee3..589bf359 100644 --- a/AMDiS/src/Global.h +++ b/AMDiS/src/Global.h @@ -88,13 +88,6 @@ namespace AMDiS { */ #define DIM_OF_INDEX(ind, dim) ((static_cast<int>(ind) == 0) ? dim : static_cast<int>(ind) - 1) - - /** \brief - * Returns boundary->getBound() if boundary is not NULL. Returns INTERIOR - * otherwise. - */ - //#define GET_BOUND(boundary) ((boundary) ? (boundary)->getBound() : INTERIOR) - /** \brief * Calculates factorial of i */ diff --git a/AMDiS/src/Lagrange.cc b/AMDiS/src/Lagrange.cc index 81fdbd01..a86aa0da 100644 --- a/AMDiS/src/Lagrange.cc +++ b/AMDiS/src/Lagrange.cc @@ -765,27 +765,8 @@ namespace AMDiS { return NULL; } - const BoundaryType* Lagrange::getBound(const ElInfo* el_info, - BoundaryType* bound) const + void Lagrange::getBound(const ElInfo* el_info, BoundaryType* bound) const { - static BoundaryType *bound_vec = NULL; - static int bound_vec_size = 0; - BoundaryType *result; - - if (bound) { - result = bound; - } else { - // realloc memory if neccessary - if (bound_vec_size < nBasFcts) { - if (bound_vec) - FREE_MEMORY(bound_vec, BoundaryType, bound_vec_size); - bound_vec = GET_MEMORY(BoundaryType, nBasFcts); - bound_vec_size = nBasFcts; - } - - result = bound_vec; - } - el_info->testFlag(Mesh::FILL_BOUND); // boundaries @@ -801,7 +782,7 @@ namespace AMDiS { boundaryType = el_info->getBoundary(j); int kto = (*nDOF)[INDEX_OF_DIM(i, dim)]; for (int k = 0; k < kto; k++) { - result[index++] = boundaryType; + bound[index++] = boundaryType; } } offset -= Global::getGeo(INDEX_OF_DIM(i + 1, dim), dim); @@ -809,12 +790,10 @@ namespace AMDiS { // interior nodes in the center for (int i = 0; i < (*nDOF)[CENTER]; i++) { - result[index++] = INTERIOR; + bound[index++] = INTERIOR; } TEST_EXIT_DBG(index == nBasFcts)("found not enough boundarys\n"); - - return result; } diff --git a/AMDiS/src/Lagrange.h b/AMDiS/src/Lagrange.h index 5b6061e7..36a0165e 100644 --- a/AMDiS/src/Lagrange.h +++ b/AMDiS/src/Lagrange.h @@ -100,7 +100,7 @@ namespace AMDiS { /** \brief * Implements BasisFunction::getBound */ - const BoundaryType* getBound(const ElInfo*, BoundaryType *) const; + void getBound(const ElInfo*, BoundaryType *) const; /** \brief * Calculates the local vertex indices which are involved in evaluating diff --git a/AMDiS/src/MultiGridSolver.cc b/AMDiS/src/MultiGridSolver.cc index b9a69e33..689f67c2 100644 --- a/AMDiS/src/MultiGridSolver.cc +++ b/AMDiS/src/MultiGridSolver.cc @@ -157,7 +157,7 @@ namespace AMDiS { std::vector<double*>::iterator factorIt; std::vector<double*>::iterator factorBegin = systemMatrix_->getOperatorFactorBegin(); ElementMatrix *elementMatrix = NULL; - const BoundaryType *bound; + BoundaryType *bound = GET_MEMORY(BoundaryType, numDOFs); TraverseStack stack; @@ -190,7 +190,7 @@ namespace AMDiS { element = elInfo->getElement(); level = elInfo->getLevel(); basFcts->getLocalIndices(element, admin, dofs); - bound = basFcts->getBound(elInfo, NULL); + basFcts->getBound(elInfo, bound); elementMatrix = (*opBegin)->getAssembler(omp_get_thread_num())->initElementMatrix(elementMatrix, elInfo); bool levelUsed = isMGLevel_[level]; @@ -274,6 +274,8 @@ namespace AMDiS { } // if-else element is leaf elInfo = stack.traverseNext(elInfo); } // while elInfo + + FREE_MEMORY(bound, BoundaryType, numDOFs); if (!galerkin_) { // Fill boundary conditions @@ -1048,16 +1050,17 @@ namespace AMDiS { elInfo = stack.traverseNext(elInfo); } + BoundaryType *bound = GET_MEMORY(BoundaryType, numDOFs); + for (int col = 0; col < numComponents_; col++) { DOFMatrix *dofMatrix = (*systemMatrix_)[row][col]; - if(dofMatrix) { + if (dofMatrix) { std::vector<Operator*>::iterator it; std::vector<Operator*>::iterator opBegin = dofMatrix->getOperatorsBegin(); std::vector<Operator*>::iterator opEnd = dofMatrix->getOperatorsEnd(); std::vector<double*>::iterator factorIt; std::vector<double*>::iterator factorBegin = dofMatrix->getOperatorFactorBegin(); ElementMatrix *elementMatrix = NULL; - const BoundaryType *bound; // assemble level matrices and create dof sets elInfo = stack.traverseFirst(mesh, -1, @@ -1071,7 +1074,7 @@ namespace AMDiS { element = elInfo->getElement(); level = elInfo->getLevel(); basFcts->getLocalIndices(element, admin, dofs); - bound = basFcts->getBound(elInfo, NULL); + basFcts->getBound(elInfo, bound); elementMatrix = (*opBegin)->getAssembler(omp_get_thread_num())->initElementMatrix(elementMatrix, elInfo); bool levelUsed = isMGLevel_[level]; @@ -1163,6 +1166,7 @@ namespace AMDiS { } } + FREE_MEMORY(bound, BoundaryType, numDOFs); FREE_MEMORY(dofs, DegreeOfFreedom, numDOFs); } diff --git a/AMDiS/src/NonLinUpdater.cc b/AMDiS/src/NonLinUpdater.cc index e83a2fbb..9f866f11 100644 --- a/AMDiS/src/NonLinUpdater.cc +++ b/AMDiS/src/NonLinUpdater.cc @@ -18,8 +18,8 @@ namespace AMDiS { FUNCNAME("NonLinUpdaterScal::update()"); TraverseStack stack; - ElInfo *el_info; - Flag fill_flag; + ElInfo *el_info; + Flag fill_flag; TEST_EXIT(F || df)("neither F nor df are set\n"); @@ -43,9 +43,12 @@ namespace AMDiS { Mesh::FILL_DET| Mesh::FILL_GRD_LAMBDA; + BoundaryType *bound = GET_MEMORY(BoundaryType, feSpace->getBasisFcts()->getNumber()); + el_info = stack.traverseFirst(feSpace->getMesh(), -1, fill_flag); while (el_info) { - const BoundaryType *bound = basFcts->getBound(el_info, NULL); + basFcts->getBound(el_info, bound); + if (updateDF) { df->assemble(1.0, el_info, bound); } @@ -56,6 +59,8 @@ namespace AMDiS { el_info = stack.traverseNext(el_info); } + + FREE_MEMORY(bound, BoundaryType, feSpace->getBasisFcts()->getNumber()); } void NonLinUpdaterVec::update(bool updateDF, @@ -63,19 +68,19 @@ namespace AMDiS { { FUNCNAME("NonLinUpdaterVec::update()"); - int i, j, size = df->getNumRows(); - TraverseStack stack; - ElInfo *el_info; - Flag fill_flag; + ElInfo *el_info; + Flag fill_flag; TEST_EXIT(F || df)("neither F nor df are set\n"); - if ((!updateDF) && (F==NULL)) { + if (!updateDF && (F == NULL)) { WARNING("No RHS vector and no update for system matrix! Updater does nothing!\n"); return; } + int size = df->getNumRows(); + const FiniteElemSpace *feSpace = F ? F->getDOFVector(0)->getFESpace() : @@ -83,9 +88,10 @@ namespace AMDiS { if (updateDF) { TEST_EXIT(df)("df not set but update tried!\n"); - for(i = 0; i < size; i++) { - for(j = 0; j < size; j++) { - if((*df)[i][j]) { + + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + if ((*df)[i][j]) { (*df)[i][j]->clear(); } } @@ -95,7 +101,7 @@ namespace AMDiS { BasisFunction *basFcts = const_cast<BasisFunction*>(feSpace->getBasisFcts()); if (F) { - for(i = 0; i < size; i++) { + for (int i = 0; i < size; i++) { F->getDOFVector(i)->set(0.0); } } @@ -107,13 +113,16 @@ namespace AMDiS { Mesh::FILL_DET| Mesh::FILL_GRD_LAMBDA; + BoundaryType *bound = GET_MEMORY(BoundaryType, basFcts->getNumber()); + el_info = stack.traverseFirst(feSpace->getMesh(), -1, fill_flag); while (el_info) { - const BoundaryType *bound = basFcts->getBound(el_info, NULL); + basFcts->getBound(el_info, bound); + if (updateDF) { - for(i = 0; i < size; i++) { - for(j = 0; j < size; j++) { - if((*df)[i][j]) { + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + if ((*df)[i][j]) { (*df)[i][j]->assemble(1.0, el_info, bound); } } @@ -121,13 +130,15 @@ namespace AMDiS { } if (F) { - for(i = 0; i < size; i++) { + for(int i = 0; i < size; i++) { F->getDOFVector(i)->assemble(1.0, el_info, bound); } } el_info = stack.traverseNext(el_info); } + + FREE_MEMORY(bound, BoundaryType, basFcts->getNumber()); }; } diff --git a/AMDiS/src/ProblemScal.cc b/AMDiS/src/ProblemScal.cc index 8a46a287..3d65398e 100644 --- a/AMDiS/src/ProblemScal.cc +++ b/AMDiS/src/ProblemScal.cc @@ -629,10 +629,11 @@ namespace AMDiS { int ProblemScal::buildAfterCoarsenFct(ElInfo *elInfo) { - const BoundaryType *bound; + BoundaryType *bound; if (traversePtr_->getBoundUsed()) { - bound = traversePtr_->getFESpace()->getBasisFcts()->getBound(elInfo, NULL); + bound = GET_MEMORY(BoundaryType, traversePtr_->getFESpace()->getBasisFcts()->getNumber()); + traversePtr_->getFESpace()->getBasisFcts()->getBound(elInfo, bound); } else { bound = NULL; } @@ -640,6 +641,10 @@ namespace AMDiS { traversePtr_->getSystemMatrix()->assemble(1.0, elInfo, bound); traversePtr_->getRHS()->assemble(1.0, elInfo, bound); + if (traversePtr_->getBoundUsed()) { + FREE_MEMORY(bound, BoundaryTyppe, traversePtr_->getFESpace()->getBasisFcts()->getNumber()); + } + return 0; } diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc index f11a7f1c..6a32fc54 100644 --- a/AMDiS/src/ProblemVec.cc +++ b/AMDiS/src/ProblemVec.cc @@ -22,6 +22,7 @@ #include "PeriodicBC.h" #include "Lagrange.h" #include "Flag.h" +#include "TraverseParallel.h" namespace AMDiS { @@ -694,11 +695,7 @@ namespace AMDiS { } } - int i; -#ifdef _OPENMP -#pragma omp parallel for -#endif - for (i = 0; i < nComponents; i++) { + for (int i = 0; i < nComponents; i++) { for (int j = 0; j < nComponents; j++) { // Only if this variable is true, the current matrix will be assembled. bool assembleMatrix = true; @@ -942,39 +939,95 @@ namespace AMDiS { { Mesh *mesh = feSpace->getMesh(); const BasisFunction *basisFcts = feSpace->getBasisFcts(); + TraverseParallelStack stack; - BoundaryType *bound = NULL; - if (useGetBound_) { - bound = GET_MEMORY(BoundaryType, basisFcts->getNumber()); - } +#pragma omp parallel + { + BoundaryType *bound = useGetBound_ ? GET_MEMORY(BoundaryType, basisFcts->getNumber()) : NULL; + + // Create for every thread its private matrix and vector, on that + // the thread will assemble its part of the mesh. + DOFMatrix *tmpMatrix = NULL; + DOFVector<double> *tmpVector = NULL; - TraverseStack stack; - ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag); - - while (elInfo) { - if (useGetBound_) { - basisFcts->getBound(elInfo, bound); - } - if (matrix) { - matrix->assemble(1.0, elInfo, bound); + tmpMatrix = NEW DOFMatrix(matrix->getRowFESpace(), + matrix->getColFESpace(), + "tmp"); + + // Copy the global matrix to the private matrix, because we need the + // operators defined on the global matrix in the private one. Only the + // values have to be set to zero. + *tmpMatrix = *matrix; + tmpMatrix->clear(); + } + + if (vector) { + tmpVector = NEW DOFVector<double>(vector->getFESpace(), "tmp"); + + // Copy the global vector to the private vector, because we need the + // operatirs defined on the global vector in the private one. But set + // the values to zero of the private vector after copying. + *tmpVector = *vector; + tmpVector->set(0.0); + } + + // Because we are using the parallel traverse stack, each thread will + // traverse only a part of the mesh. + ElInfo *elInfo = stack.traverseFirst(mesh, -1, assembleFlag); + while (elInfo) { + if (useGetBound_) { + basisFcts->getBound(elInfo, bound); + } - if (matrix->getBoundaryManager()) { - matrix->getBoundaryManager()-> - fillBoundaryConditions(elInfo, matrix); - } + if (matrix) { + tmpMatrix->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, tmpMatrix); + } + } + + if (vector) { + tmpVector->assemble(1.0, elInfo, bound); + } + + elInfo = stack.traverseNext(elInfo); } - + + // After mesh traverse, all thread have to added their private matrices and + // vectors to the global public matrix and public vector. Therefore, this is + // a critical section, which is allowed to be executed by on thread only at + // the same time. + + if (matrix) { +#pragma omp critical + { + addDOFMatrix(matrix, tmpMatrix); + + // Remove rows corresponding to DOFs on a Dirichlet boundary. + matrix->removeRowsWithDBC(tmpMatrix->getApplyDBCs()); + } + + DELETE tmpMatrix; + } + if (vector) { - vector->assemble(1.0, elInfo, bound); +#pragma omp critical + *vector += *tmpVector; + + DELETE tmpVector; } - - elInfo = stack.traverseNext(elInfo); - } - if (useGetBound_) { - FREE_MEMORY(bound, BoundaryType, basisFcts->getNumber()); - } + if (useGetBound_) { + FREE_MEMORY(bound, BoundaryType, basisFcts->getNumber()); + } + + } // pragma omp parallel + } void ProblemVec::assembleOnDifMeshes(FiniteElemSpace *rowFeSpace, FiniteElemSpace *colFeSpace, diff --git a/AMDiS/src/SecondOrderAssembler.cc b/AMDiS/src/SecondOrderAssembler.cc index 538ef7ce..bd1dc76e 100644 --- a/AMDiS/src/SecondOrderAssembler.cc +++ b/AMDiS/src/SecondOrderAssembler.cc @@ -110,7 +110,7 @@ namespace AMDiS { const double *values; int myRank = omp_get_thread_num(); - DimMat<double> **LALt = tmpLALt[myRank]; + DimMat<double> **LALt = tmpLALt[0]; DimMat<double> &tmpMat = *LALt[0]; tmpMat.set(0.0); diff --git a/AMDiS/src/Traverse.h b/AMDiS/src/Traverse.h index 32a2fc26..01090252 100644 --- a/AMDiS/src/Traverse.h +++ b/AMDiS/src/Traverse.h @@ -147,18 +147,19 @@ namespace AMDiS { VectorOfFixVecs<DimVec<double> > *coords); /** \brief - * + * Is used for parallel mesh traverse. */ inline void setMyThreadId(int myThreadId) { myThreadId_ = myThreadId; } /** \brief - * + * Is used for parallel mesh traverse. */ inline void setMaxThreads(int maxThreads) { maxThreads_ = maxThreads; } + private: /** \brief * Enlargement of the stack -- GitLab