From 6882b12ca352aa54601aa8082de31ef87f0155fb Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Thu, 16 Apr 2015 19:58:30 +0000 Subject: [PATCH] Make initialization indicator also work for 1d grids. Document some functions and add comments. git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/branches/gridadapt@14585 2fb0f335-1f38-0410-981e-8018bf24f1b0 --- .../gridadaptinitializationindicator.hh | 242 ++++++++++-------- 1 file changed, 140 insertions(+), 102 deletions(-) diff --git a/dumux/implicit/common/gridadaptinitializationindicator.hh b/dumux/implicit/common/gridadaptinitializationindicator.hh index a4e82fdff2..4562336599 100644 --- a/dumux/implicit/common/gridadaptinitializationindicator.hh +++ b/dumux/implicit/common/gridadaptinitializationindicator.hh @@ -25,12 +25,12 @@ /** * @file - * @brief Class defining a start indicator for grid adaption + * @brief Class defining an initialization indicator for grid adaption */ namespace Dumux { -/*!\ingroup IMPES - * @brief Class defining a start indicator for grid adaption +/*!\ingroup ImplicitGridAdaptInitializationIndicator + * @brief Class defining an initialization indicator for grid adaption * * Uses the defined grid adaptation indicator and further accounts for sources and boundaries. * Only for grid initialization! @@ -55,90 +55,130 @@ private: typedef typename GET_PROP_TYPE(TypeTag, BoundaryTypes) BoundaryTypes; enum - { - dim = GridView::dimension, - dimWorld = GridView::dimensionworld, - numEq = GET_PROP_VALUE(TypeTag, NumEq), - }; + { + dim = GridView::dimension, + dimWorld = GridView::dimensionworld, + numEq = GET_PROP_VALUE(TypeTag, NumEq), + }; enum - { - refineCell = 1, - coarsenCell = -1 - }; + { + refineCell = 1, + coarsenCell = -1 + }; typedef Dune::FieldVector<Scalar, dim> LocalPosition; typedef Dune::FieldVector<Scalar, dim-1> LocalPositionFace; typedef Dune::FieldVector<Scalar, dimWorld> GlobalPosition; + /*! \brief Hierarchical search for a source term + * + * For every element we do virtual refinement until maxAllowedLevel + * and check if we have a source term at the element center. This + * is necessary as an element can also be only partly in a source zone. + * + * \param source A primary variables vector that will return the source values + * \param element A grid element + */ void virtualHierarchicSourceSearch_(PrimaryVariables &source, const Element& element) { int level = element.level(); - + const auto geometry = element.geometry(); + if (level == maxAllowedLevel_) { - GlobalPosition globalPos = element.geometry().center(); + GlobalPosition globalPos = geometry.center(); problem_.sourceAtPos(source, globalPos); - return; } + // get the number of check points in each dimension unsigned int numRefine = maxAllowedLevel_ - level; - int numCheckCoords = pow(2, numRefine); + int numCheckCoords = 1 << numRefine; + // the local position of the check point as we do this on the reference element LocalPosition localPos(0.0); GlobalPosition globalPosCheck(0.0); - Scalar halfInterval = (1.0/double(numCheckCoords))/2.; - PrimaryVariables sourceCheck(0.0); + // we check for a source in the midpoint + Scalar halfInterval = (1.0/double(numCheckCoords))/2.0; - for (int i = 1; i <= numCheckCoords; i++) + // TODO this only works correctly for cubes! + + PrimaryVariables sourceCheck(0.0); + // use a switch statement to let the compiler do easy optimization + switch(dim) { - for (int j = 1; j <= numCheckCoords; j++) - { - localPos[0] = double(i)/double(numCheckCoords) - halfInterval; - localPos[1] = double(j)/double(numCheckCoords) - halfInterval; - if (dim == 2) - { - globalPosCheck = element.geometry().global(localPos); - problem_.sourceAtPos(sourceCheck, globalPosCheck); - - for (int eqIdx = 0; eqIdx < numEq; eqIdx++) - { - if (std::abs(sourceCheck[eqIdx]) > std::abs(source[eqIdx])) - { - source[eqIdx] = sourceCheck[eqIdx]; - } - } - } - else if (dim == 3) - { - for (int k = 1; k <= numCheckCoords; k++) + case 3: + for (int i = 1; i <= numCheckCoords; i++) + for (int j = 1; i <= numCheckCoords; i++) + for (int k = 1; i <= numCheckCoords; i++) { + localPos[0] = double(i)/double(numCheckCoords) - halfInterval; + localPos[1] = double(j)/double(numCheckCoords) - halfInterval; localPos[2] = double(k)/double(numCheckCoords) - halfInterval; - globalPosCheck = element.geometry().global(localPos); + globalPosCheck = geometry.global(localPos); problem_.sourceAtPos(sourceCheck, globalPosCheck); for (int eqIdx = 0; eqIdx < numEq; eqIdx++) { if (std::abs(sourceCheck[eqIdx]) > std::abs(source[eqIdx])) - { source[eqIdx] = sourceCheck[eqIdx]; - } } } + break; + case 2: + for (int i = 1; i <= numCheckCoords; i++) + for (int j = 1; i <= numCheckCoords; i++) + { + localPos[0] = double(i)/double(numCheckCoords) - halfInterval; + localPos[1] = double(j)/double(numCheckCoords) - halfInterval; + globalPosCheck = geometry.global(localPos); + problem_.sourceAtPos(sourceCheck, globalPosCheck); + + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + { + if (std::abs(sourceCheck[eqIdx]) > std::abs(source[eqIdx])) + source[eqIdx] = sourceCheck[eqIdx]; + } + } + break; + case 1: + for (int i = 1; i <= numCheckCoords; i++) + { + localPos[0] = double(i)/double(numCheckCoords) - halfInterval; + globalPosCheck = geometry.global(localPos); + problem_.sourceAtPos(sourceCheck, globalPosCheck); + + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + { + if (std::abs(sourceCheck[eqIdx]) > std::abs(source[eqIdx])) + source[eqIdx] = sourceCheck[eqIdx]; } } + break; } } + /*! \brief Hierarchical search for the value of Neumann boundary condition + * + * For every intersection we do virtual refinement until maxAllowedLevel + * and check which boundary condition is defined on the intersection center. This + * is necessary as an element can partly have Neumann boundary conditions. + * + * \param bcTypes The boundary condition types + * \param values The value of the boundary condition. Returns the Neumann flux values + * \param element A grid element + * \param intersection The boundary intersection + */ void virtualHierarchicBCSearch_(BoundaryTypes &bcTypes, PrimaryVariables &values, const Element& element, const Intersection& intersection) { int level = element.level(); + const auto isGeometry = intersection.geometry(); - if (level == maxAllowedLevel_) + if (level == maxAllowedLevel_ || dim==1) { - GlobalPosition globalPos = intersection.geometry().center(); + GlobalPosition globalPos = isGeometry.center(); problem_.boundaryTypesAtPos(bcTypes, globalPos); if (refineAtFluxBC_) @@ -149,55 +189,40 @@ private: { PrimaryVariables fluxes; problem_.neumannAtPos(fluxes, globalPos); - - values += fluxes; + values[i] += std::abs(fluxes[i]); } } } return; } + // get the number of check points in each dimension unsigned int numRefine = maxAllowedLevel_ - level; - int numCheckCoords = pow(2, numRefine); + int numCheckCoords = 1 << numRefine; + // the local position of the check point + // as we do this on the reference codim 1 element LocalPositionFace localPos(0.0); GlobalPosition globalPosCheck(0.0); - Scalar halfInterval = (1.0/double(numCheckCoords))/2.; + + // we check for the boundary condition type in the midpoint + Scalar halfInterval = (1.0/double(numCheckCoords))/2.0; - PrimaryVariables fluxCheck(0.0); + // TODO this only works correctly for cubes! - for (int i = 1; i <= numCheckCoords; i++) + PrimaryVariables fluxCheck(0.0); + // use a switch statement to let the compiler do easy optimization + switch(dim-1) { - localPos[0] = double(i)/double(numCheckCoords) - halfInterval; - if (dim == 2) - { - globalPosCheck = intersection.geometry().global(localPos); - problem_.boundaryTypesAtPos(bcTypes, globalPosCheck); - - for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + case 2: + for (int i = 1; i <= numCheckCoords; i++) + for (int j = 1; i <= numCheckCoords; i++) { - if (refineAtDirichletBC_ && bcTypes.isDirichlet(eqIdx)) - { - return; - } - else if (refineAtFluxBC_ && bcTypes.isNeumann(eqIdx)) - { - problem_.neumannAtPos(fluxCheck, globalPosCheck); - - values += fluxCheck; - } - } - } - else if (dim == 3) - { - for (int k = 1; k <= numCheckCoords; k++) - { - localPos[1] = double(k)/double(numCheckCoords) - halfInterval; - globalPosCheck = intersection.geometry().global(localPos); - + localPos[0] = double(i)/double(numCheckCoords) - halfInterval; + localPos[1] = double(j)/double(numCheckCoords) - halfInterval; + globalPosCheck = isGeometry.global(localPos); problem_.boundaryTypesAtPos(bcTypes, globalPosCheck); - for (int eqIdx = 0; eqIdx < numEq; eqIdx++) { if (refineAtDirichletBC_ && bcTypes.isDirichlet(eqIdx)) @@ -207,13 +232,32 @@ private: else if (refineAtFluxBC_ && bcTypes.isNeumann(eqIdx)) { problem_.neumannAtPos(fluxCheck, globalPosCheck); - - values += fluxCheck; + values[eqIdx] += std::abs(fluxCheck[eqIdx]); } + } + } + break; + case 1: + for (int i = 1; i <= numCheckCoords; i++) + { + localPos[0] = double(i)/double(numCheckCoords) - halfInterval; + globalPosCheck = isGeometry.global(localPos); + problem_.boundaryTypesAtPos(bcTypes, globalPosCheck); + for (int eqIdx = 0; eqIdx < numEq; eqIdx++) + { + if (refineAtDirichletBC_ && bcTypes.isDirichlet(eqIdx)) + { + return; + } + else if (refineAtFluxBC_ && bcTypes.isNeumann(eqIdx)) + { + problem_.neumannAtPos(fluxCheck, globalPosCheck); + values[eqIdx] += std::abs(fluxCheck[eqIdx]); } } } + break; } } @@ -224,23 +268,23 @@ public: */ void calculateIndicator() { - //First Adapt for boundary conditions and sources to get a correct pressure solution + if (!enableInitializationIndicator_) + return; + + //First adapt for boundary conditions and sources to get a good initial solution if (nextMaxLevel_ == maxAllowedLevel_) adaptionIndicator_.calculateIndicator(); // prepare an indicator for refinement indicatorVector_.resize(problem_.model().numDofs()); + // set the default to coarsen indicatorVector_ = coarsenCell; - if (!enableInitializationIndicator_) - return; - - ElementIterator eEndIt = problem_.gridView().template end<0>(); // 1) calculate Indicator -> min, maxvalues - // Schleife über alle Leaf-Elemente - for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eEndIt; - ++eIt) + // loop over all leaf elements + const ElementIterator eEndIt = problem_.gridView().template end<0>(); + for (ElementIterator eIt = problem_.gridView().template begin<0>(); eIt != eEndIt; ++eIt) { #if DUNE_VERSION_NEWER(DUNE_COMMON, 2, 4) @@ -258,13 +302,15 @@ public: continue; } + // Check if we have to refine around a source term if (refineAtSource_) { PrimaryVariables source(0.0); virtualHierarchicSourceSearch_(source, *eIt); for (int i = 0; i < numEq; i++) { - if (std::abs(source[i]) > 1e-10) + // If source term was found mark cell for refinement + if (std::abs(source[i]) > 1e-30) { nextMaxLevel_ = std::min(std::max(level + 1, nextMaxLevel_), maxAllowedLevel_); indicatorVector_[globalIdxI] = refineCell; @@ -273,20 +319,19 @@ public: } } + // Check if we have to refine at the boundary if (indicatorVector_[globalIdxI] != refineCell && (refineAtDirichletBC_ || refineAtFluxBC_)) { - // Berechne Verfeinerungsindikator an allen Zellen - IntersectionIterator isItend = problem_.gridView().iend(*eIt); + // Calculate the boundary indicator for all boundary intersections + const IntersectionIterator isItend = problem_.gridView().iend(*eIt); for (IntersectionIterator isIt = problem_.gridView().ibegin(*eIt); isIt != isItend; ++isIt) { if (isIt->boundary() && indicatorVector_[globalIdxI] != refineCell) { BoundaryTypes bcTypes; PrimaryVariables values(0.0); - virtualHierarchicBCSearch_(bcTypes, values, *eIt, *isIt); - for (int i = 0; i < numEq; i++) { if (bcTypes.isDirichlet(i) && refineAtDirichletBC_) @@ -295,16 +340,12 @@ public: indicatorVector_[globalIdxI] = refineCell; break; } - } - for (int j = 0; j < values.size(); j++) - { - if (std::abs(values[j]) > 1e-10) + if (std::abs(values[i]) > 1e-30) { nextMaxLevel_ = std::min(std::max(level + 1, nextMaxLevel_), maxAllowedLevel_); indicatorVector_[globalIdxI] = refineCell; break; - } - + } } } } @@ -472,10 +513,7 @@ public: * \param adaptionIndicator Indicator whether a be adapted */ ImplicitGridAdaptInitializationIndicatorDefault(Problem& problem, AdaptionIndicator& adaptionIndicator) - { - - } - + {} }; } -- GitLab