3.1-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
glue.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 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
26#ifndef DUMUX_MULTIDOMAIN_GLUE_HH
27#define DUMUX_MULTIDOMAIN_GLUE_HH
28
29#include <iostream>
30#include <fstream>
31#include <string>
32#include <utility>
33#include <type_traits>
34#include <tuple>
35
36#include <dune/common/indices.hh>
37#include <dune/common/timer.hh>
38#include <dune/common/iteratorrange.hh>
39#include <dune/common/promotiontraits.hh>
40#include <dune/common/reservedvector.hh>
41#include <dune/geometry/affinegeometry.hh>
42#include <dune/geometry/type.hh>
43#include <dune/grid/common/mcmgmapper.hh>
44
48
49namespace Dumux {
50
51// forward declaration
52template<class DomainGridView, class TargetGridView, class DomainMapper, class TargetMapper>
53class MultiDomainGlue;
54
60template<class DomainGridView, class TargetGridView, class DomainMapper, class TargetMapper>
61Dune::IteratorRange<typename MultiDomainGlue<DomainGridView, TargetGridView, DomainMapper, TargetMapper>::Intersections::const_iterator>
63{ return {glue.ibegin(), glue.iend()}; }
64
65namespace Glue {
66
72template<class DomainGridView, class TargetGridView, class DomainMapper, class TargetMapper>
74{
75 using DomainElement = typename DomainGridView::template Codim<0>::Entity;
76 using TargetElement = typename TargetGridView::template Codim<0>::Entity;
77
80
83
84 static constexpr int dimWorld = DomainGridView::dimensionworld;
85 static_assert(dimWorld == int(TargetGridView::dimensionworld), "Grids must have the same world dimension");
86
87 static constexpr int dimDomain = DomainGridView::dimension;
88 static constexpr int dimTarget = TargetGridView::dimension;
89 static constexpr int dimIs = std::min(dimDomain, dimTarget);
90
91 using ctypeDomain = typename DomainGridView::ctype;
92 using ctypeTarget = typename TargetGridView::ctype;
93 using ctype = typename Dune::PromotionTraits<ctypeDomain, ctypeTarget>::PromotedType;
94
95 using Geometry = Dune::AffineGeometry<ctype, dimIs, dimWorld>;
96 using GlobalPosition = Dune::FieldVector<ctype, dimWorld>;
97
98 // we can only have multiple neighbors in the mixeddimensional case and then only for the side with the largest dimension
99 using IndexStorage = std::pair<std::conditional_t<dimDomain <= dimTarget, Dune::ReservedVector<std::size_t, 1>, std::vector<std::size_t>>,
100 std::conditional_t<dimTarget <= dimDomain, Dune::ReservedVector<std::size_t, 1>, std::vector<std::size_t>>>;
101
102 static constexpr auto domainIdx = Dune::index_constant<0>{};
103 static constexpr auto targetIdx = Dune::index_constant<1>{};
104
105public:
106 Intersection(const DomainTree& domainTree, const TargetTree& targetTree)
107 : domainTree_(domainTree)
108 , targetTree_(targetTree)
109 {}
110
112 void setCorners(const std::vector<GlobalPosition>& corners)
113 {
114 corners_ = corners;
115 assert(corners.size() == dimIs + 1); // Only simplex intersections are allowed
116 }
117
119 void addNeighbors(std::size_t domain, std::size_t target)
120 {
121 if (numDomainNeighbors() == 0 && numTargetNeighbors() == 0)
122 {
123 std::get<domainIdx>(neighbors_).push_back(domain);
124 std::get<targetIdx>(neighbors_).push_back(target);
125 }
126 else if (dimDomain > dimTarget)
127 std::get<domainIdx>(neighbors_).push_back(domain);
128
129 else if (dimTarget > dimDomain)
130 std::get<targetIdx>(neighbors_).push_back(target);
131
132 else
133 DUNE_THROW(Dune::InvalidStateException, "Cannot add more than one neighbor per side for equidimensional intersection!");
134 }
135
137 Geometry geometry() const
138 { return Geometry(Dune::GeometryTypes::simplex(dimIs), corners_); }
139
141 std::size_t numDomainNeighbors() const
142 { return std::get<domainIdx>(neighbors_).size(); }
143
145 std::size_t numTargetNeighbors() const
146 { return std::get<targetIdx>(neighbors_).size(); }
147
149 DomainElement domainEntity(unsigned int n = 0) const
150 { return domainTree_.entitySet().entity(std::get<domainIdx>(neighbors_)[n]); }
151
153 TargetElement targetEntity(unsigned int n = 0) const
154 { return targetTree_.entitySet().entity(std::get<targetIdx>(neighbors_)[n]); }
155
157 [[deprecated("neighbor is deprecated and will be removed after release 3.1. Use numDomainNeighbors() / numTargetNeighbors()")]]
158 std::size_t neighbor(unsigned int side) const
159 { return std::max(std::get<domainIdx>(neighbors_).size(), std::get<targetIdx>(neighbors_).size()); }
160
162 [[deprecated("outside is deprecated and will be removed after release 3.1. Use domainIdx(uint)")]]
163 DomainElement outside(unsigned int n) const
164 { return domainTree_.entitySet().entity(std::get<domainIdx>(neighbors_)[n]); }
165
167 [[deprecated("inside is deprecated and will be removed after release 3.1. Use targetIdx(uint)")]]
168 TargetElement inside(unsigned int n) const
169 { return targetTree_.entitySet().entity(std::get<targetIdx>(neighbors_)[n]); }
170
171private:
172 IndexStorage neighbors_;
173 std::vector<GlobalPosition> corners_;
174
175 const DomainTree& domainTree_;
176 const TargetTree& targetTree_;
177};
178
179} // end namespace Glue
180
187template<class DomainGridView, class TargetGridView,
188 class DomainMapper = Dune::MultipleCodimMultipleGeomTypeMapper<DomainGridView>,
189 class TargetMapper = Dune::MultipleCodimMultipleGeomTypeMapper<TargetGridView>>
191{
194
197
198 using ctypeDomain = typename DomainGridView::ctype;
199 using ctypeTarget = typename TargetGridView::ctype;
200 using ctype = typename Dune::PromotionTraits<ctypeDomain, ctypeTarget>::PromotedType;
201
202 enum { dimWorld = DomainGridView::dimensionworld };
203 using GlobalPosition = Dune::FieldVector<ctype, dimWorld>;
204
205 static constexpr int dimDomain = DomainGridView::dimension;
206 static constexpr int dimTarget = TargetGridView::dimension;
207 static constexpr bool isMixedDimensional = dimDomain != dimTarget;
208
209public:
210 // export intersection container type
211 using Intersections = std::vector<Glue::Intersection<DomainGridView, TargetGridView, DomainMapper, TargetMapper>>;
212
213
217 MultiDomainGlue() = default;
218
222 MultiDomainGlue(const DomainTree& domainTree, const TargetTree& targetTree)
223 { build(domainTree, targetTree); }
224
225 void build(const DomainTree& domainTree, const TargetTree& targetTree)
226 {
227 Dune::Timer timer;
228
229 // compute raw intersections
230 auto rawIntersections = intersectingEntities(domainTree, targetTree);
231
232 // create a map to check whether intersection geometries were already inserted
233 // Note that this can only occur if the grids have different dimensionality.
234 // If this is the case, we keep track of the intersections using the indices of the lower-
235 // dimensional entities which is identical for all geometrically identical intersections.
236 std::vector<std::vector<std::vector<GlobalPosition>>> intersectionMap;
237 std::vector<std::vector<std::size_t>> intersectionIndex;
238 if ( isMixedDimensional )
239 {
240 const auto numLowDimEntities = dimTarget < dimDomain ? targetTree.entitySet().size()
241 : domainTree.entitySet().size();
242 intersectionMap.resize(numLowDimEntities);
243 intersectionIndex.resize(numLowDimEntities);
244 }
245
246 // lambda to obtain the index of the lower-dimensional neighbor of a raw intersection
247 auto getLowDimNeighborIdx = [] (const auto& rawIS)
248 { return dimTarget < dimDomain ? rawIS.second() : rawIS.first(); };
249
250 // reserve memory for storing the intersections. In case of grids of
251 // different dimensionality this might be an overestimate. We get rid
252 // of the overhead memory at the end of this function though.
253 intersections_.clear();
254 intersections_.reserve(rawIntersections.size());
255
256 for (const auto& rawIntersection : rawIntersections)
257 {
258 bool add = true;
259
260 // Check if intersection was already inserted.
261 // In this case we only add new neighbor information as the geometry is identical.
262 if ( isMixedDimensional )
263 {
264 const auto lowDimNeighborIdx = getLowDimNeighborIdx(rawIntersection);
265 for (int i = 0; i < intersectionMap[lowDimNeighborIdx].size(); ++i)
266 {
267 if (rawIntersection.cornersMatch(intersectionMap[lowDimNeighborIdx][i]))
268 {
269 add = false;
270 // only add the pair of neighbors using the insertionIndex
271 auto idx = intersectionIndex[lowDimNeighborIdx][i];
272 intersections_[idx].addNeighbors(rawIntersection.first(), rawIntersection.second());
273 break;
274 }
275 }
276 }
277
278 if(add)
279 {
280 // maybe add to the map
281 if ( isMixedDimensional )
282 {
283 intersectionMap[getLowDimNeighborIdx(rawIntersection)].push_back(rawIntersection.corners());
284 intersectionIndex[getLowDimNeighborIdx(rawIntersection)].push_back(intersections_.size());
285 }
286
287 // add new intersection and add the neighbors
288 intersections_.emplace_back(domainTree, targetTree);
289 intersections_.back().setCorners(rawIntersection.corners());
290 intersections_.back().addNeighbors(rawIntersection.first(), rawIntersection.second());
291 }
292 }
293
294 intersections_.shrink_to_fit();
295 std::cout << "Computed tree intersections in " << timer.elapsed() << std::endl;
296 }
297
299 typename Intersections::const_iterator ibegin() const
300 { return intersections_.begin(); }
301
303 typename Intersections::const_iterator iend() const
304 { return intersections_.end(); }
305
307 std::size_t size() const
308 { return intersections_.size(); }
309
310private:
311 Intersections intersections_;
312};
313
322template<class DomainGG, class TargetGG>
323MultiDomainGlue< typename DomainGG::GridView, typename TargetGG::GridView,
324 typename DomainGG::ElementMapper, typename TargetGG::ElementMapper >
325makeGlue(const DomainGG& domainGridGeometry, const TargetGG& targetGridGeometry)
326{
327 return {domainGridGeometry.boundingBoxTree(), targetGridGeometry.boundingBoxTree()};
328}
329
330} // end namespace Dumux
331
332#endif
An interface for a set of geometric entities.
Algorithms that finds which geometric entites intersect.
std::vector< std::size_t > intersectingEntities(const Dune::FieldVector< ctype, dimworld > &point, const BoundingBoxTree< EntitySet > &tree, bool isCartesianGrid=false)
Compute all intersections between entities and a point.
Definition: intersectingentities.hh:45
MultiDomainGlue< typename DomainGG::GridView, typename TargetGG::GridView, typename DomainGG::ElementMapper, typename TargetGG::ElementMapper > makeGlue(const DomainGG &domainGridGeometry, const TargetGG &targetGridGeometry)
Creates the glue object containing the intersections between two grids obtained from given grid geome...
Definition: glue.hh:325
Dune::IteratorRange< typename MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper >::Intersections::const_iterator > intersections(const MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper > &glue)
Range generator to iterate with range-based for loops over all intersections as follows: for (const a...
Definition: glue.hh:62
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
An axis-aligned bounding box volume tree implementation.
Definition: geometry/boundingboxtree.hh:66
const EntitySet & entitySet() const
the entity set this tree was built with
Definition: geometry/boundingboxtree.hh:133
An interface for a set of geometric entities.
Definition: geometricentityset.hh:41
Manages the coupling between domain elements and lower dimensional elements Point sources on each int...
Definition: glue.hh:191
std::vector< Glue::Intersection< DomainGridView, TargetGridView, DomainMapper, TargetMapper > > Intersections
Definition: glue.hh:211
MultiDomainGlue(const DomainTree &domainTree, const TargetTree &targetTree)
Constructor.
Definition: glue.hh:222
std::size_t size() const
the number of intersections
Definition: glue.hh:307
Intersections::const_iterator ibegin() const
Return begin iterator to intersection container.
Definition: glue.hh:299
Intersections::const_iterator iend() const
Return end iterator to intersection container.
Definition: glue.hh:303
void build(const DomainTree &domainTree, const TargetTree &targetTree)
Definition: glue.hh:225
MultiDomainGlue()=default
Default constructor.
An intersection object representing the intersection between two grid entites of different grids.
Definition: glue.hh:74
DomainElement outside(unsigned int n) const
get the inside (domain) neighbor
Definition: glue.hh:163
void setCorners(const std::vector< GlobalPosition > &corners)
set the intersection geometry corners
Definition: glue.hh:112
TargetElement targetEntity(unsigned int n=0) const
get the nth target neighbor entity
Definition: glue.hh:153
std::size_t neighbor(unsigned int side) const
get the number of neigbors
Definition: glue.hh:158
Geometry geometry() const
get the intersection geometry
Definition: glue.hh:137
std::size_t numTargetNeighbors() const
get the number of target neighbors of this intersection
Definition: glue.hh:145
Intersection(const DomainTree &domainTree, const TargetTree &targetTree)
Definition: glue.hh:106
DomainElement domainEntity(unsigned int n=0) const
get the nth domain neighbor entity
Definition: glue.hh:149
void addNeighbors(std::size_t domain, std::size_t target)
add a pair of neighbor elements
Definition: glue.hh:119
std::size_t numDomainNeighbors() const
get the number of domain neighbors of this intersection
Definition: glue.hh:141
TargetElement inside(unsigned int n) const
get the outside (target) neighbor
Definition: glue.hh:168
An axis-aligned bounding box volume hierarchy for dune grids.