version 3.8
facet/box/couplingmapper.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightInfo: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
12#ifndef DUMUX_BOX_FACETCOUPLING_MAPPER_HH
13#define DUMUX_BOX_FACETCOUPLING_MAPPER_HH
14
15#include <dune/common/indices.hh>
16
22
23namespace Dumux {
24
36template<class BulkFVG, class LowDimFVG, std::size_t bulkId, std::size_t lowDimId>
37class FacetCouplingMapper<BulkFVG, LowDimFVG, bulkId, lowDimId, DiscretizationMethods::Box>
38: public virtual FacetCouplingMapperBase<BulkFVG, LowDimFVG, bulkId, lowDimId>
39{
41 using LowDimElement = typename LowDimFVG::GridView::template Codim<0>::Entity;
42
43 // dimensions of the two grids
44 using BulkGridView = typename BulkFVG::GridView;
45 using LowDimGridView = typename LowDimFVG::GridView;
46 static constexpr int bulkDim = BulkGridView::dimension;
47 static constexpr int lowDimDim = LowDimGridView::dimension;
48
49public:
51 using ParentType::bulkGridId;
52 using ParentType::facetGridId;
53
62 template< class Embeddings >
63 void update(const BulkFVG& bulkFvGridGeometry,
64 const LowDimFVG& lowDimFvGridGeometry,
65 std::shared_ptr<const Embeddings> embeddings)
66 {
67 // forward to update function with instantiated vertex adapter
69 update(bulkFvGridGeometry, lowDimFvGridGeometry, embeddings, GridAdapter(embeddings));
70 }
71
80 template< class Embeddings, class CodimOneGridAdapter >
81 void update(const BulkFVG& bulkFvGridGeometry,
82 const LowDimFVG& lowDimFvGridGeometry,
83 std::shared_ptr<const Embeddings> embeddings,
84 const CodimOneGridAdapter& codimOneGridAdapter)
85 {
86 // define the policy how to add map entries for given lowdim element and adjoined entity indices
87 auto addCouplingEntryPolicy = [&] (auto&& adjoinedEntityIndices,
88 const LowDimElement& lowDimElement,
89 const LowDimFVG& lowDimFvGridGeometry,
90 const BulkFVG& bulkFvGridGeometry)
91 {
92 using LowDimIndexType = typename IndexTraits<LowDimGridView>::GridIndex;
93 using BulkIndexType = typename IndexTraits<BulkGridView>::GridIndex;
94
95 const auto lowDimElemIdx = lowDimFvGridGeometry.elementMapper().index(lowDimElement);
96 auto& lowDimData = this->couplingMap_(facetGridId, bulkGridId)[lowDimElemIdx];
97
98 // determine corner indices (in bulk grid indices)
99 const auto& eg = lowDimElement.geometry();
100 const auto numElementCorners = eg.corners();
101 std::vector<BulkIndexType> elementCorners(numElementCorners);
102 for (int i = 0; i < numElementCorners; ++i)
103 elementCorners[i] = codimOneGridAdapter.bulkGridVertexIndex(lowDimElement.template subEntity<lowDimDim>(i));
104
105 // save unsorted set of corner indices and search scvfs in adjoined entities
106 const auto unsortedElemCorners = elementCorners;
107 std::sort(elementCorners.begin(), elementCorners.end());
108
109 auto fvGeometry = localView(bulkFvGridGeometry);
110 for (auto bulkElemIdx : adjoinedEntityIndices)
111 {
112 const auto bulkElement = bulkFvGridGeometry.element(bulkElemIdx);
113 const auto bulkRefElem = referenceElement(bulkElement);
114
115 // find the bulk element facet that lies on this low dim element (assumes conformity!)
116 const auto coupledFacetIndex = [&]
117 {
118 bool found = false;
119 unsigned int coupledFacetIndex = 0;
120 std::vector<unsigned int> handledFacets;
121 for (const auto& is : intersections(bulkFvGridGeometry.gridView(), bulkElement))
122 {
123 // skip already handled facets (necessary for e.g. Dune::FoamGrid)
124 if (std::count(handledFacets.begin(), handledFacets.end(), is.indexInInside()))
125 continue;
126
127 handledFacets.push_back(is.indexInInside());
128
129 // determine if it lies on low dim element by comparing corner indices
130 const auto numCorners = is.geometry().corners();
131 std::vector<BulkIndexType> facetIndices(numCorners);
132 for (int i = 0; i < numCorners; ++i)
133 {
134 const auto vIdxLocal = bulkRefElem.subEntity(is.indexInInside(), 1, i, bulkDim);
135 facetIndices[i] = bulkFvGridGeometry.vertexMapper().vertexIndex(bulkElement.template subEntity<bulkDim>(vIdxLocal));
136 }
137
138 std::sort(facetIndices.begin(), facetIndices.end());
139 if ( std::equal(facetIndices.begin(), facetIndices.end(), elementCorners.begin(), elementCorners.end()) )
140 {
141 coupledFacetIndex = is.indexInInside();
142 found = true; break;
143 }
144 }
145
146 // ensure that we found the facet!
147 if (!found)
148 DUNE_THROW(Dune::InvalidStateException, "Could not find the bulk element coupling facet!");
149
150 return coupledFacetIndex;
151 }();
152
153 // we should always find numElementCorners coupling scvfs
154 fvGeometry.bindElement(bulkElement);
155
156 unsigned int foundCounter = 0;
157 std::vector<BulkIndexType> embeddedScvfIndices(numElementCorners);
158 for (const auto& scvf : scvfs(fvGeometry))
159 {
160 if (scvf.interiorBoundary() && scvf.facetIndexInElement() == coupledFacetIndex)
161 {
162 // we want to order the set of scvfs lying on the lower-dimensional element such that the i-th scvf
163 // coincides with the i-th low dim element corner. This will help later to identify which scvf fluxes
164 // enter which scv of the low dim element if the lower-dimensional domain uses the box scheme
165 const auto vIdxLocal = bulkRefElem.subEntity(coupledFacetIndex, 1, scvf.indexInElementFacet(), bulkDim);
166 const auto vIdxGlobal = bulkFvGridGeometry.vertexMapper().vertexIndex(bulkElement, vIdxLocal, bulkDim);
167 const auto it = std::find(unsortedElemCorners.begin(), unsortedElemCorners.end(), vIdxGlobal);
168 assert(it != unsortedElemCorners.end());
169 const auto lowDimElemLocalCornerIdx = std::distance(unsortedElemCorners.begin(), it);
170 embeddedScvfIndices[lowDimElemLocalCornerIdx] = scvf.index();
171 foundCounter++;
172 }
173 }
174
175 // ensure we found all scvfs
176 if (foundCounter != numElementCorners)
177 DUNE_THROW(Dune::InvalidStateException, "Found " << foundCounter << " instead of " << numElementCorners << " coupling scvfs in the bulk element");
178
179 // add each dof in the low dim element to coupling stencil of the bulk element
180 auto& bulkData = this->couplingMap_(bulkGridId, facetGridId)[bulkElemIdx];
181 const auto lowDimElementDofs = LowDimFVG::discMethod == DiscretizationMethods::box
182 ? this->extractNodalDofs_(lowDimElement, lowDimFvGridGeometry)
183 : std::vector<LowDimIndexType>({lowDimElemIdx});
184
185 for (auto lowDimDofIdx : lowDimElementDofs)
186 {
187 bulkData.couplingStencil.push_back(lowDimDofIdx);
188 auto& couplingScvfs = bulkData.dofToCouplingScvfMap[lowDimDofIdx];
189 couplingScvfs.insert(couplingScvfs.end(), embeddedScvfIndices.begin(), embeddedScvfIndices.end());
190 }
191
192 // add info on which scvfs coincide with which low dim element
193 bulkData.couplingElementStencil.push_back(lowDimElemIdx);
194 auto& elemToScvfMap = bulkData.elementToScvfMap[lowDimElemIdx];
195 elemToScvfMap.insert(elemToScvfMap.end(), embeddedScvfIndices.begin(), embeddedScvfIndices.end());
196
197 // add embedment and the bulk cell dofs to coupling stencil of low dim element
198 lowDimData.embedments.emplace_back(bulkElemIdx, std::move(embeddedScvfIndices));
199
200 const auto bulkElementDofs = this->extractNodalDofs_(bulkElement, bulkFvGridGeometry);
201 for (auto bulkDofIdx : bulkElementDofs)
202 lowDimData.couplingStencil.push_back(bulkDofIdx);
203 }
204 };
205
206 // let the parent do the update subject to the execution policy defined above
207 ParentType::update_(bulkFvGridGeometry, lowDimFvGridGeometry, embeddings, addCouplingEntryPolicy);
208
209 // coupling stencils might not be unique with the policy above
210 auto makeStencilUnique = [] (auto& data)
211 {
212 auto& cs = data.second.couplingStencil;
213 std::sort(cs.begin(), cs.end());
214 cs.erase( std::unique(cs.begin(), cs.end()), cs.end() );
215 };
216
217 auto& lowDimCouplingData = this->couplingMap_(facetGridId, bulkGridId);
218 std::for_each(lowDimCouplingData.begin(), lowDimCouplingData.end(), makeStencilUnique);
219
220 // bulk coupling stencil is only non-unique if box is used
221 if (LowDimFVG::discMethod == DiscretizationMethods::box)
222 {
223 auto& bulkCouplingData = this->couplingMap_(bulkGridId, facetGridId);
224 std::for_each(bulkCouplingData.begin(), bulkCouplingData.end(), makeStencilUnique);
225 }
226 }
227};
228
229} // end namespace Dumux
230
231#endif
Adapter that allows retrieving information on a d-dimensional grid for entities of a (d-1)-dimensiona...
Definition: codimonegridadapter.hh:40
BulkIndexType bulkGridVertexIndex(const FacetGridVertex &v) const
Returns the index within the d-dimensional grid of a vertex of the (d-1)-dimensional grid.
Definition: codimonegridadapter.hh:133
void update(const BulkFVG &bulkFvGridGeometry, const LowDimFVG &lowDimFvGridGeometry, std::shared_ptr< const Embeddings > embeddings, const CodimOneGridAdapter &codimOneGridAdapter)
Update coupling maps with a given grid adapter.
Definition: facet/box/couplingmapper.hh:81
void update(const BulkFVG &bulkFvGridGeometry, const LowDimFVG &lowDimFvGridGeometry, std::shared_ptr< const Embeddings > embeddings)
Update coupling maps. This is the standard interface required by any mapper implementation.
Definition: facet/box/couplingmapper.hh:63
Base class for the coupling mapper that sets up and stores the coupling maps between two domains of d...
Definition: couplingmapperbase.hh:41
Implementation for the coupling mapper that sets up and stores the coupling maps between two domains ...
Definition: facet/couplingmapper.hh:42
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
static ctype distance(const Dune::FieldVector< ctype, dimWorld > &a, const Dune::FieldVector< ctype, dimWorld > &b)
Compute the shortest distance between two points.
Definition: distance.hh:282
Defines the index types used for grid and local indices.
The available discretization methods in Dumux.
constexpr Box box
Definition: method.hh:147
CVFE< CVFEMethods::PQ1 > Box
Definition: method.hh:94
std::size_t numCorners(Shape shape)
Returns the number of corners of a given geometry.
Definition: throatproperties.hh:220
Definition: adapt.hh:17
typename GridView::IndexSet::IndexType GridIndex
Definition: indextraits.hh:27