From f4a387b2eaada16a70c5383f869b5d208c9784d2 Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Mon, 15 Jun 2020 19:54:12 +0200 Subject: [PATCH] [embedded] Improve integration point source * Add box point source lumping or distribution by ansatz functions * Optimize storage: we only need one element index to interpolate --- .../embedded/integrationpointsource.hh | 120 +++++++++++++----- 1 file changed, 85 insertions(+), 35 deletions(-) diff --git a/dumux/multidomain/embedded/integrationpointsource.hh b/dumux/multidomain/embedded/integrationpointsource.hh index 74ac494c9f..e842481517 100644 --- a/dumux/multidomain/embedded/integrationpointsource.hh +++ b/dumux/multidomain/embedded/integrationpointsource.hh @@ -30,6 +30,7 @@ #include <type_traits> #include <dune/common/reservedvector.hh> #include <dumux/common/pointsource.hh> +#include <dumux/common/parameters.hh> #include <dumux/discretization/method.hh> namespace Dumux { @@ -47,37 +48,64 @@ class IntegrationPointSource : public IdPointSource<GlobalPosition, SourceValues public: //! Constructor for integration point sources + [[deprecated("Call constructor with a single element index instead! Will be removed after 3.3")]] IntegrationPointSource(GlobalPosition pos, SourceValues values, IdType id, Scalar qpweight, Scalar integrationElement, const std::vector<std::size_t>& elementIndices) : ParentType(pos, values, id), qpweight_(qpweight), integrationElement_(integrationElement), - elementIndices_(elementIndices) {} + elementIndex_(elementIndices[0]) {} //! Constructor for integration point sources, when there is no // value known at the time of initialization + [[deprecated("Call constructor with a single element index instead! Will be removed after 3.3")]] IntegrationPointSource(GlobalPosition pos, IdType id, Scalar qpweight, Scalar integrationElement, const std::vector<std::size_t>& elementIndices) : ParentType(pos, id), qpweight_(qpweight), integrationElement_(integrationElement), - elementIndices_(elementIndices) {} + elementIndex_(elementIndices[0]) {} + //! Constructor for integration point sources + IntegrationPointSource(GlobalPosition pos, SourceValues values, IdType id, + Scalar qpweight, Scalar integrationElement, + std::size_t elementIndex) + : ParentType(pos, values, id) + , qpweight_(qpweight) + , integrationElement_(integrationElement) + , elementIndex_(elementIndex) + {} + + //! Constructor for integration point sources, when there is no + //! value known at the time of initialization + IntegrationPointSource(GlobalPosition pos, IdType id, + Scalar qpweight, Scalar integrationElement, + std::size_t elementIndex) + : ParentType(pos, id) + , qpweight_(qpweight) + , integrationElement_(integrationElement) + , elementIndex_(elementIndex) + {} Scalar quadratureWeight() const - { - return qpweight_; - } + { return qpweight_; } Scalar integrationElement() const - { - return integrationElement_; - } + { return integrationElement_; } - const std::vector<std::size_t>& elementIndices() const - { - return elementIndices_; - } + void setQuadratureWeight(const Scalar qpWeight) + { return qpweight_ = qpWeight; } + + void setIntegrationElement(const Scalar ie) + { integrationElement_ = ie; } + + [[deprecated("Use elementIndex() instead. Will be removed after 3.3")]] + std::vector<std::size_t> elementIndices() const + { return std::vector<std::size_t>({elementIndex_}); } + + //! The index of the element this intergration point source is associated with + std::size_t elementIndex() const + { return elementIndex_; } //! Convenience = operator overload modifying only the values IntegrationPointSource& operator= (const SourceValues& values) @@ -96,7 +124,7 @@ public: private: Scalar qpweight_; Scalar integrationElement_; - std::vector<std::size_t> elementIndices_; + std::size_t elementIndex_; }; /*! @@ -110,29 +138,29 @@ public: //! calculate a DOF index to point source map from given vector of point sources template<class GridGeometry, class PointSource, class PointSourceMap> static void computePointSourceMap(const GridGeometry& gridGeometry, - std::vector<PointSource>& sources, - PointSourceMap& pointSourceMap) + const std::vector<PointSource>& sources, + PointSourceMap& pointSourceMap, + const std::string& paramGroup = "") { - for (auto&& source : sources) + for (const auto& source : sources) { - // compute in which elements the point source falls - const auto& entities = source.elementIndices(); - // split the source values equally among all concerned entities - source.setEmbeddings(source.embeddings()*entities.size()); - // loop over all intersected elements - for (unsigned int eIdx : entities) + // get the index of the element in which the point source falls + const auto eIdx = source.elementIndex(); + if constexpr (GridGeometry::discMethod == DiscretizationMethod::box) { - if (GridGeometry::discMethod == DiscretizationMethod::box) + // check in which subcontrolvolume(s) we are + const auto element = gridGeometry.boundingBoxTree().entitySet().entity(eIdx); + auto fvGeometry = localView(gridGeometry); + fvGeometry.bindElement(element); + const auto globalPos = source.position(); + + static const bool boxPointSourceLumping = getParamFromGroup<bool>(paramGroup, "PointSource.EnableBoxLumping", true); + if (boxPointSourceLumping) { - // check in which subcontrolvolume(s) we are - const auto element = gridGeometry.boundingBoxTree().entitySet().entity(eIdx); - auto fvGeometry = localView(gridGeometry); - fvGeometry.bindElement(element); - const auto globalPos = source.position(); // loop over all sub control volumes and check if the point source is inside constexpr int dim = GridGeometry::GridView::dimension; Dune::ReservedVector<std::size_t, 1<<dim> scvIndices; - for (auto&& scv : scvs(fvGeometry)) + for (const auto& scv : scvs(fvGeometry)) if (intersectsPointGeometry(globalPos, scv.geometry())) scvIndices.push_back(scv.indexInElement()); @@ -150,16 +178,38 @@ public: s.setEmbeddings(scvIndices.size()*s.embeddings()); } } + + // distribute the sources using the basis function weights else { - // add the pointsource to the DOF map - const auto key = std::make_pair(eIdx, /*scvIdx=*/ 0); - if (pointSourceMap.count(key)) - pointSourceMap.at(key).push_back(source); - else - pointSourceMap.insert({key, {source}}); + const auto& localBasis = fvGeometry.feLocalBasis(); + const auto ipLocal = element.geometry().local(globalPos); + using Scalar = std::decay_t<decltype(source.values()[0])>; + std::vector<typename Dune::FieldVector<Scalar, 1>> shapeValues; + localBasis.evaluateFunction(ipLocal, shapeValues); + for (const auto& scv : scvs(fvGeometry)) + { + const auto key = std::make_pair(eIdx, scv.indexInElement()); + if (pointSourceMap.count(key)) + pointSourceMap.at(key).push_back(source); + else + pointSourceMap.insert({key, {source}}); + + // adjust the integration element + auto& s = pointSourceMap.at(key).back(); + s.setIntegrationElement(shapeValues[scv.indexInElement()]*s.integrationElement()); + } } } + else + { + // add the pointsource to the DOF map + const auto key = std::make_pair(eIdx, /*scvIdx=*/ 0); + if (pointSourceMap.count(key)) + pointSourceMap.at(key).push_back(source); + else + pointSourceMap.insert({key, {source}}); + } } } }; -- GitLab