From 5cede7ac9053a4b6ea2f5511d36636a010e8fa88 Mon Sep 17 00:00:00 2001 From: Thomas Witkowski <thomas.witkowski@gmx.de> Date: Mon, 25 May 2009 09:15:53 +0000 Subject: [PATCH] Dirichlet boundary conditions fixed. --- AMDiS/src/BoundaryCondition.h | 30 +++++++++--- AMDiS/src/BoundaryManager.h | 15 +++--- AMDiS/src/DOFMatrix.cc | 91 +++++------------------------------ AMDiS/src/DOFMatrix.h | 2 - AMDiS/src/DirichletBC.cc | 18 +++---- AMDiS/src/DirichletBC.h | 26 ++++++++-- AMDiS/src/ProblemVec.cc | 42 ++++++++-------- AMDiS/src/ProblemVec.h | 2 +- 8 files changed, 98 insertions(+), 128 deletions(-) diff --git a/AMDiS/src/BoundaryCondition.h b/AMDiS/src/BoundaryCondition.h index 33d62b1a..94a8371a 100644 --- a/AMDiS/src/BoundaryCondition.h +++ b/AMDiS/src/BoundaryCondition.h @@ -46,21 +46,25 @@ namespace AMDiS { rowFESpace(rowFESpace_), colFESpace(colFESpace_) { - if(!colFESpace) colFESpace = rowFESpace; + if (!colFESpace) + colFESpace = rowFESpace; } /// Returns \ref boundaryType. - inline BoundaryType getBoundaryType() { + inline BoundaryType getBoundaryType() + { return boundaryType; } /// Returns \ref rowFESpace. - inline const FiniteElemSpace *getRowFESpace() { + inline const FiniteElemSpace *getRowFESpace() + { return rowFESpace; } /// Returns \ref rowFESpace. - inline const FiniteElemSpace *getColFESpace() { + inline const FiniteElemSpace *getColFESpace() + { return colFESpace; } @@ -106,13 +110,27 @@ namespace AMDiS { } /** \brief - * Returns whether the condition must be treated as dirichlet condition + * Returns whether the condition must be treated as Dirichlet condition * while assemblage. */ - virtual bool isDirichlet() { + virtual bool isDirichlet() + { return false; } + /** \brief + * In some situations it may be required to set Dirichlet boundary conditions, + * but not to apply them to the matrix. This is for example the case, if the + * boundary condition is set to a couple matrix. Then, the boundary conditions + * must be applied to the couple matrix, but they are set to all matrices in this + * row (to ensure that there are no other element entries in the Dirichlet boundary + * condition rows). + */ + virtual bool applyBoundaryCondition() + { + return true; + } + protected: /** \brief * Speciefies for which parts of the boundary the condition holds. diff --git a/AMDiS/src/BoundaryManager.h b/AMDiS/src/BoundaryManager.h index 6aa72c70..13bfd66d 100644 --- a/AMDiS/src/BoundaryManager.h +++ b/AMDiS/src/BoundaryManager.h @@ -48,10 +48,10 @@ namespace AMDiS { ~BoundaryManager(); /// Adds a local boundary condition to the list of managed conditions. - void addBoundaryCondition(BoundaryCondition *localBC) { + void addBoundaryCondition(BoundaryCondition *localBC) + { BoundaryType type = localBC->getBoundaryType(); - TEST_EXIT(localBCs[type] == NULL) - ("there is already a condition for this type\n"); + TEST_EXIT(localBCs[type] == NULL)("there is already a condition for this type\n"); localBCs[type] = localBC; } @@ -83,15 +83,18 @@ namespace AMDiS { DOFMatrix *matrix, const DOFVectorBase<double> *dv); - inline BoundaryCondition *getBoundaryCondition(BoundaryType type) { + inline BoundaryCondition *getBoundaryCondition(BoundaryType type) + { return localBCs[type]; } - const std::map<BoundaryType, BoundaryCondition*>& getBoundaryConditionMap() { + const std::map<BoundaryType, BoundaryCondition*>& getBoundaryConditionMap() + { return localBCs; } - void setBoundaryConditionMap(const std::map<BoundaryType, BoundaryCondition*>& bcs) { + void setBoundaryConditionMap(const std::map<BoundaryType, BoundaryCondition*>& bcs) + { localBCs = bcs; } diff --git a/AMDiS/src/DOFMatrix.cc b/AMDiS/src/DOFMatrix.cc index c1f3116b..04716a56 100644 --- a/AMDiS/src/DOFMatrix.cc +++ b/AMDiS/src/DOFMatrix.cc @@ -100,9 +100,11 @@ namespace AMDiS { typedef traits::range_generator<nz, cursor_type>::type icursor_type; std::cout.precision(10); - for (cursor_type cursor = begin<major>(matrix), cend = end<major>(matrix); cursor != cend; ++cursor) - for (icursor_type icursor = begin<nz>(cursor), icend = end<nz>(cursor); icursor != icend; ++icursor) - std::cout << row(*icursor) << " " << col(*icursor) << " " << value(*icursor) << "\n"; + for (cursor_type cursor = begin<major>(matrix), cend = end<major>(matrix); cursor != cend; ++cursor) { + for (icursor_type icursor = begin<nz>(cursor), icend = end<nz>(cursor); icursor != icend; ++icursor) + std::cout << "(" << row(*icursor) << "," << col(*icursor) << "," << value(*icursor) << ") "; + std::cout << "\n"; + } } bool DOFMatrix::symmetric() @@ -202,21 +204,19 @@ namespace AMDiS { // === Add element matrix to the global matrix using the indices mapping. === - DegreeOfFreedom row, col; - double entry; for (int i = 0; i < nRow; i++) { // for all rows of element matrix - row = rowIndices[i]; + DegreeOfFreedom row = rowIndices[i]; BoundaryCondition *condition = bound ? boundaryManager->getBoundaryCondition(bound[i]) : NULL; if (condition && condition->isDirichlet()) { - if (!coupleMatrix) + if (condition->applyBoundaryCondition()) applyDBCs.insert(static_cast<int>(row)); } else for (int j = 0; j < nCol; j++) { // for all columns - col = colIndices[j]; - entry = elMat[i][j]; + DegreeOfFreedom col = colIndices[j]; + double entry = elMat[i][j]; if (add) ins[row][col]+= sign * entry; @@ -331,19 +331,17 @@ namespace AMDiS { // call the operatos cleanup procedures for (std::vector<Operator*>::iterator it = operators.begin(); it != operators.end(); - ++it) { + ++it) (*it)->finishAssembling(); - } } // Should work as before Flag DOFMatrix::getAssembleFlag() { Flag fillFlag(0); - std::vector<Operator*>::iterator op; - for(op = operators.begin(); op != operators.end(); ++op) { + for (std::vector<Operator*>::iterator op = operators.begin(); + op != operators.end(); ++op) fillFlag |= (*op)->getFillFlag(); - } return fillFlag; } @@ -381,71 +379,6 @@ namespace AMDiS { rows->clear(); } - void DOFMatrix::createPictureFile(const char* filename, int dim) - { - TEST_EXIT(0)("Not yet re-implemented."); - -#if 0 - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - NULL, NULL, NULL); - - if (!png_ptr) - return; - - png_bytep rowPointers[dim]; - for (int i = 0; i < dim; i++) { - rowPointers[i] = (png_byte*)png_malloc(png_ptr, dim); - - for (int j = 0; j < dim; j++) - rowPointers[i][j] = 255; - } - - double scalFactor = static_cast<double>(dim) / static_cast<double>(matrix.size()); - - for (int i = 0; i < static_cast<int>(matrix.size()); i++) { - int pi = static_cast<int>(static_cast<double>(i) * scalFactor); - - TEST_EXIT_DBG((pi >= 0) && (pi < dim))("PI"); - - for (int j = 0; j < static_cast<int>(matrix[i].size()); j++) { - - int pj = static_cast<int>(static_cast<double>(matrix[i][j].col) * scalFactor); - - TEST_EXIT_DBG((pj >= 0) && (pj < dim))("PJ"); - - rowPointers[pi][pj] = 0; - } - } - - FILE *fp = fopen(filename, "wb"); - TEST_EXIT(fp)("Cannot open file for writing matrix picture file!\n"); - - png_infop info_ptr = png_create_info_struct(png_ptr); - - if (!info_ptr) { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return; - } - - png_init_io(png_ptr, fp); - - png_set_IHDR(png_ptr, info_ptr, dim, dim, 8, - PNG_COLOR_TYPE_GRAY, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - - png_set_rows(png_ptr, info_ptr, rowPointers); - - png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - png_destroy_write_struct(&png_ptr, &info_ptr); - - fclose(fp); -#endif - } - - int DOFMatrix::memsize() { return (num_rows(matrix) + matrix.nnz()) * sizeof(base_matrix_type::size_type) diff --git a/AMDiS/src/DOFMatrix.h b/AMDiS/src/DOFMatrix.h index a72f9ebd..5771b2c1 100644 --- a/AMDiS/src/DOFMatrix.h +++ b/AMDiS/src/DOFMatrix.h @@ -347,8 +347,6 @@ namespace AMDiS { boundaryManager = bm; } - void createPictureFile(const char* filename, int dim); - private: template <typename T> void s_write(::std::ostream &out, const T& value) diff --git a/AMDiS/src/DirichletBC.cc b/AMDiS/src/DirichletBC.cc index 15652327..1c623dfd 100644 --- a/AMDiS/src/DirichletBC.cc +++ b/AMDiS/src/DirichletBC.cc @@ -9,10 +9,12 @@ namespace AMDiS { DirichletBC::DirichletBC(BoundaryType type, AbstractFunction<double, WorldVector<double> > *fct, FiniteElemSpace *rowFESpace, - FiniteElemSpace *colFESpace) + FiniteElemSpace *colFESpace, + bool apply) : BoundaryCondition(type, rowFESpace, colFESpace), f(fct), - dofVec(NULL) + dofVec(NULL), + applyBC(apply) { worldCoords.resize(omp_get_overall_max_threads()); } @@ -21,7 +23,8 @@ namespace AMDiS { DOFVectorBase<double> *vec) : BoundaryCondition(type, vec->getFESpace()), f(NULL), - dofVec(vec) + dofVec(vec), + applyBC(true) { worldCoords.resize(omp_get_overall_max_threads()); } @@ -34,8 +37,7 @@ namespace AMDiS { { FUNCNAME("DirichletBC::fillBoundaryCondition()"); - TEST_EXIT_DBG(matrix->getRowFESpace() == rowFESpace) - ("invalid row fe space\n"); + TEST_EXIT_DBG(matrix->getRowFESpace() == rowFESpace)("invalid row fe space\n"); } void DirichletBC::fillBoundaryCondition(DOFVectorBase<double>* vector, @@ -46,8 +48,7 @@ namespace AMDiS { { FUNCNAME("DirichletBC::fillBoundaryCondition()"); - TEST_EXIT_DBG(vector->getFESpace() == rowFESpace) - ("invalid row fe space\n"); + TEST_EXIT_DBG(vector->getFESpace() == rowFESpace)("invalid row fe space\n"); const BasisFunction *basFcts = rowFESpace->getBasisFcts(); int myRank = omp_get_thread_num(); @@ -59,9 +60,8 @@ namespace AMDiS { double fAtCoords = (*f)(worldCoords[myRank]); (*vector)[dofIndices[i]] = fAtCoords; } - if (dofVec) { + if (dofVec) (*vector)[dofIndices[i]] = (*dofVec)[dofIndices[i]]; - } } } } diff --git a/AMDiS/src/DirichletBC.h b/AMDiS/src/DirichletBC.h index 082a8fc1..fc59f594 100644 --- a/AMDiS/src/DirichletBC.h +++ b/AMDiS/src/DirichletBC.h @@ -44,7 +44,8 @@ namespace AMDiS { DirichletBC(BoundaryType type, AbstractFunction<double, WorldVector<double> > *fct, FiniteElemSpace *rowFESpace, - FiniteElemSpace *colFESpace = NULL); + FiniteElemSpace *colFESpace = NULL, + bool apply = true); /// Constructor. DirichletBC(BoundaryType type, @@ -72,15 +73,25 @@ namespace AMDiS { return 0.0; } - bool isDirichlet() { + /// Because this is a Dirichlet boundary condition, always return true. + bool isDirichlet() + { return true; } - inline AbstractFunction<double, WorldVector<double> > *getF() { + /// Returns \ref applyBC. + bool applyBoundaryCondition() + { + return applyBC; + } + + inline AbstractFunction<double, WorldVector<double> > *getF() + { return f; } - inline DOFVectorBase<double> *getDOFVector() { + inline DOFVectorBase<double> *getDOFVector() + { return dofVec; } @@ -88,10 +99,17 @@ namespace AMDiS { /// Function which is evaluated at world coords of Dirichlet dofs. AbstractFunction<double, WorldVector<double> > *f; + /// std::vector<WorldVector<double> > worldCoords; /// DOFVector containing the boundary values DOFVectorBase<double> *dofVec; + + /** \brief + * Defines, if the boundary condition must be applied to the matrix. See + * comment of \ref BoundaryCondition::applyBoundaryCondition. + */ + bool applyBC; }; } diff --git a/AMDiS/src/ProblemVec.cc b/AMDiS/src/ProblemVec.cc index 1159d6cd..6b7bf79b 100644 --- a/AMDiS/src/ProblemVec.cc +++ b/AMDiS/src/ProblemVec.cc @@ -916,23 +916,27 @@ namespace AMDiS { } } - void ProblemVec::addDirichletBC(BoundaryType type, int system, + void ProblemVec::addDirichletBC(BoundaryType type, int row, int col, AbstractFunction<double, WorldVector<double> >* b) { FUNCNAME("ProblemVec::addDirichletBC()"); - DirichletBC *dirichlet = new DirichletBC(type, - b, - componentSpaces[system]); - for (int i = 0; i < nComponents; i++) { - if (systemMatrix && (*systemMatrix)[system][i]) { - (*systemMatrix)[system][i]->getBoundaryManager()->addBoundaryCondition(dirichlet); - } - } + DirichletBC *dirichletApply = + new DirichletBC(type, b, componentSpaces[row], componentSpaces[col], true); + DirichletBC *dirichletNotApply = + new DirichletBC(type, b, componentSpaces[row], componentSpaces[col], false); + + for (int i = 0; i < nComponents; i++) + if (systemMatrix && (*systemMatrix)[row][i]) + if (i == col) + (*systemMatrix)[row][i]->getBoundaryManager()->addBoundaryCondition(dirichletApply); + else + (*systemMatrix)[row][i]->getBoundaryManager()->addBoundaryCondition(dirichletNotApply); + if (rhs) - rhs->getDOFVector(system)->getBoundaryManager()->addBoundaryCondition(dirichlet); + rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(dirichletApply); if (solution) - solution->getDOFVector(system)->getBoundaryManager()->addBoundaryCondition(dirichlet); + solution->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(dirichletApply); } void ProblemVec::addNeumannBC(BoundaryType type, int row, int col, @@ -941,9 +945,8 @@ namespace AMDiS { FUNCNAME("ProblemVec::addNeumannBC()"); NeumannBC *neumann = - new NeumannBC(type, n, - componentSpaces[row], - componentSpaces[col]); + new NeumannBC(type, n, componentSpaces[row], componentSpaces[col]); + if (rhs) rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(neumann); } @@ -955,15 +958,12 @@ namespace AMDiS { FUNCNAME("ProblemVec::addRobinBC()"); RobinBC *robin = - new RobinBC(type, n, r, - componentSpaces[row], - componentSpaces[col]); - if (rhs) - rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(robin); + new RobinBC(type, n, r, componentSpaces[row], componentSpaces[col]); - if (systemMatrix && (*systemMatrix)[row][col]) { + if (systemMatrix && (*systemMatrix)[row][col]) (*systemMatrix)[row][col]->getBoundaryManager()->addBoundaryCondition(robin); - } + if (rhs) + rhs->getDOFVector(row)->getBoundaryManager()->addBoundaryCondition(robin); } void ProblemVec::addPeriodicBC(BoundaryType type, int row, int col) diff --git a/AMDiS/src/ProblemVec.h b/AMDiS/src/ProblemVec.h index da66a0dd..3300fce3 100644 --- a/AMDiS/src/ProblemVec.h +++ b/AMDiS/src/ProblemVec.h @@ -208,7 +208,7 @@ namespace AMDiS { bool fake = false); /// Adds dirichlet boundary conditions. - virtual void addDirichletBC(BoundaryType type, int system, + virtual void addDirichletBC(BoundaryType type, int row, int col, AbstractFunction<double, WorldVector<double> > *b); /// Adds neumann boundary conditions. -- GitLab