Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
dumux
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
dumux-repositories
dumux
Commits
7ed44503
Commit
7ed44503
authored
5 years ago
by
Timo Koch
Browse files
Options
Downloads
Patches
Plain Diff
[md] Use intersectionentityset for implementing MultiDomainGlue
parent
ea170d36
No related branches found
No related tags found
1 merge request
!1771
[geometry] Implement intersection entity set, a set of intersections of two entity sets
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
dumux/multidomain/glue.hh
+12
-255
12 additions, 255 deletions
dumux/multidomain/glue.hh
with
12 additions
and
255 deletions
dumux/multidomain/glue.hh
+
12
−
255
View file @
7ed44503
...
...
@@ -26,274 +26,28 @@
#ifndef DUMUX_MULTIDOMAIN_GLUE_HH
#define DUMUX_MULTIDOMAIN_GLUE_HH
#include
<iostream>
#include
<fstream>
#include
<string>
#include
<utility>
#include
<type_traits>
#include
<tuple>
#include
<dune/common/indices.hh>
#include
<dune/common/timer.hh>
#include
<dune/common/iteratorrange.hh>
#include
<dune/common/promotiontraits.hh>
#include
<dune/common/reservedvector.hh>
#include
<dune/geometry/affinegeometry.hh>
#include
<dune/geometry/type.hh>
#include
<dune/grid/common/mcmgmapper.hh>
#include
<dumux/common/geometry/geometricentityset.hh>
#include
<dumux/common/geometry/boundingboxtree.hh>
#include
<dumux/common/geometry/intersectin
g
entit
ies
.hh>
#include
<dumux/common/geometry/intersecti
o
nentit
yset
.hh>
namespace
Dumux
{
// forward declaration
template
<
class
DomainGridView
,
class
TargetGridView
,
class
DomainMapper
,
class
TargetMapper
>
class
MultiDomainGlue
;
/*!
* \ingroup MultiDomain
* \brief Range generator to iterate with range-based for loops over all intersections
* as follows: for (const auto& is : intersections(glue)) { ... }
*/
template
<
class
DomainGridView
,
class
TargetGridView
,
class
DomainMapper
,
class
TargetMapper
>
Dune
::
IteratorRange
<
typename
MultiDomainGlue
<
DomainGridView
,
TargetGridView
,
DomainMapper
,
TargetMapper
>::
Intersections
::
const_iterator
>
intersections
(
const
MultiDomainGlue
<
DomainGridView
,
TargetGridView
,
DomainMapper
,
TargetMapper
>&
glue
)
{
return
{
glue
.
ibegin
(),
glue
.
iend
()};
}
namespace
Glue
{
/*!
* \ingroup MultiDomain
* \brief An intersection object representing the intersection
* between two grid entites of different grids
*/
template
<
class
DomainGridView
,
class
TargetGridView
,
class
DomainMapper
,
class
TargetMapper
>
class
Intersection
class
MultiDomainGlue
:
public
IntersectionEntitySet
<
GridViewGeometricEntitySet
<
DomainGridView
,
0
,
DomainMapper
>
,
GridViewGeometricEntitySet
<
TargetGridView
,
0
,
TargetMapper
>>
{
using
DomainElement
=
typename
DomainGridView
::
template
Codim
<
0
>
::
Entity
;
using
TargetElement
=
typename
TargetGridView
::
template
Codim
<
0
>
::
Entity
;
using
DomainEntitySet
=
GridViewGeometricEntitySet
<
DomainGridView
,
0
,
DomainMapper
>
;
using
DomainTree
=
BoundingBoxTree
<
DomainEntitySet
>
;
using
TargetEntitySet
=
GridViewGeometricEntitySet
<
TargetGridView
,
0
,
TargetMapper
>
;
using
TargetTree
=
BoundingBoxTree
<
TargetEntitySet
>
;
static
constexpr
int
dimWorld
=
DomainGridView
::
dimensionworld
;
static_assert
(
dimWorld
==
int
(
TargetGridView
::
dimensionworld
),
"Grids must have the same world dimension"
);
static
constexpr
int
dimDomain
=
DomainGridView
::
dimension
;
static
constexpr
int
dimTarget
=
TargetGridView
::
dimension
;
static
constexpr
int
dimIs
=
std
::
min
(
dimDomain
,
dimTarget
);
using
ctypeDomain
=
typename
DomainGridView
::
ctype
;
using
ctypeTarget
=
typename
TargetGridView
::
ctype
;
using
ctype
=
typename
Dune
::
PromotionTraits
<
ctypeDomain
,
ctypeTarget
>::
PromotedType
;
using
Geometry
=
Dune
::
AffineGeometry
<
ctype
,
dimIs
,
dimWorld
>
;
using
GlobalPosition
=
Dune
::
FieldVector
<
ctype
,
dimWorld
>
;
// we can only have multiple neighbors in the mixeddimensional case and then only for the side with the largest dimension
using
IndexStorage
=
std
::
pair
<
std
::
conditional_t
<
dimDomain
<=
dimTarget
,
Dune
::
ReservedVector
<
std
::
size_t
,
1
>
,
std
::
vector
<
std
::
size_t
>>
,
std
::
conditional_t
<
dimTarget
<=
dimDomain
,
Dune
::
ReservedVector
<
std
::
size_t
,
1
>
,
std
::
vector
<
std
::
size_t
>>>
;
static
constexpr
auto
domainIdx
=
Dune
::
index_constant
<
0
>
{};
static
constexpr
auto
targetIdx
=
Dune
::
index_constant
<
1
>
{};
public
:
Intersection
(
const
DomainTree
&
domainTree
,
const
TargetTree
&
targetTree
)
:
domainTree_
(
domainTree
)
,
targetTree_
(
targetTree
)
{}
//! set the intersection geometry corners
void
setCorners
(
const
std
::
vector
<
GlobalPosition
>&
corners
)
{
corners_
=
corners
;
assert
(
corners
.
size
()
==
dimIs
+
1
);
// Only simplex intersections are allowed
}
//! add a pair of neighbor elements
void
addNeighbors
(
std
::
size_t
domain
,
std
::
size_t
target
)
{
if
(
numDomainNeighbors
()
==
0
&&
numTargetNeighbors
()
==
0
)
{
std
::
get
<
domainIdx
>
(
neighbors_
).
push_back
(
domain
);
std
::
get
<
targetIdx
>
(
neighbors_
).
push_back
(
target
);
}
else
if
(
dimDomain
>
dimTarget
)
std
::
get
<
domainIdx
>
(
neighbors_
).
push_back
(
domain
);
else
if
(
dimTarget
>
dimDomain
)
std
::
get
<
targetIdx
>
(
neighbors_
).
push_back
(
target
);
else
DUNE_THROW
(
Dune
::
InvalidStateException
,
"Cannot add more than one neighbor per side for equidimensional intersection!"
);
}
//! get the intersection geometry
Geometry
geometry
()
const
{
return
Geometry
(
Dune
::
GeometryTypes
::
simplex
(
dimIs
),
corners_
);
}
//! get the number of domain neighbors of this intersection
std
::
size_t
numDomainNeighbors
()
const
{
return
std
::
get
<
domainIdx
>
(
neighbors_
).
size
();
}
//! get the number of target neighbors of this intersection
std
::
size_t
numTargetNeighbors
()
const
{
return
std
::
get
<
targetIdx
>
(
neighbors_
).
size
();
}
//! get the nth domain neighbor entity
DomainElement
domainEntity
(
unsigned
int
n
=
0
)
const
{
return
domainTree_
.
entitySet
().
entity
(
std
::
get
<
domainIdx
>
(
neighbors_
)[
n
]);
}
//! get the nth target neighbor entity
TargetElement
targetEntity
(
unsigned
int
n
=
0
)
const
{
return
targetTree_
.
entitySet
().
entity
(
std
::
get
<
targetIdx
>
(
neighbors_
)[
n
]);
}
private
:
IndexStorage
neighbors_
;
std
::
vector
<
GlobalPosition
>
corners_
;
const
DomainTree
&
domainTree_
;
const
TargetTree
&
targetTree_
;
};
}
// end namespace Glue
/*!
* \ingroup MultiDomain
* \brief Manages the coupling between domain elements and lower dimensional elements
* Point sources on each integration point are computed by an AABB tree.
* Both domain are assumed to be discretized using a cc finite volume scheme.
*/
template
<
class
DomainGridView
,
class
TargetGridView
,
class
DomainMapper
=
Dune
::
MultipleCodimMultipleGeomTypeMapper
<
DomainGridView
>,
class
TargetMapper
=
Dune
::
MultipleCodimMultipleGeomTypeMapper
<
TargetGridView
>>
class
MultiDomainGlue
{
using
DomainEntitySet
=
GridViewGeometricEntitySet
<
DomainGridView
,
0
,
DomainMapper
>
;
using
ParentType
=
IntersectionEntitySet
<
DomainEntitySet
,
TargetEntitySet
>
;
using
DomainTree
=
BoundingBoxTree
<
DomainEntitySet
>
;
using
TargetEntitySet
=
GridViewGeometricEntitySet
<
TargetGridView
,
0
,
TargetMapper
>
;
using
TargetTree
=
BoundingBoxTree
<
TargetEntitySet
>
;
using
ctypeDomain
=
typename
DomainGridView
::
ctype
;
using
ctypeTarget
=
typename
TargetGridView
::
ctype
;
using
ctype
=
typename
Dune
::
PromotionTraits
<
ctypeDomain
,
ctypeTarget
>::
PromotedType
;
enum
{
dimWorld
=
DomainGridView
::
dimensionworld
};
using
GlobalPosition
=
Dune
::
FieldVector
<
ctype
,
dimWorld
>
;
static
constexpr
int
dimDomain
=
DomainGridView
::
dimension
;
static
constexpr
int
dimTarget
=
TargetGridView
::
dimension
;
static
constexpr
bool
isMixedDimensional
=
dimDomain
!=
dimTarget
;
public:
// export intersection container type
using
Intersections
=
std
::
vector
<
Glue
::
Intersection
<
DomainGridView
,
TargetGridView
,
DomainMapper
,
TargetMapper
>>
;
using
ParentType
::
ParentType
;
/*!
* \brief Default constructor
*/
MultiDomainGlue
()
=
default
;
/*!
* \brief Constructor
*/
// TODO: After the deprecation period (after release 3.2) this class can be replaced by an alias template
[[
deprecated
(
"Will be removed after 3.2. Use default constructor and call build(domainTree, targetTree)!"
)]]
MultiDomainGlue
(
const
DomainTree
&
domainTree
,
const
TargetTree
&
targetTree
)
{
build
(
domainTree
,
targetTree
);
}
void
build
(
const
DomainTree
&
domainTree
,
const
TargetTree
&
targetTree
)
{
Dune
::
Timer
timer
;
// compute raw intersections
auto
rawIntersections
=
intersectingEntities
(
domainTree
,
targetTree
);
// create a map to check whether intersection geometries were already inserted
// Note that this can only occur if the grids have different dimensionality.
// If this is the case, we keep track of the intersections using the indices of the lower-
// dimensional entities which is identical for all geometrically identical intersections.
std
::
vector
<
std
::
vector
<
std
::
vector
<
GlobalPosition
>>>
intersectionMap
;
std
::
vector
<
std
::
vector
<
std
::
size_t
>>
intersectionIndex
;
if
(
isMixedDimensional
)
{
const
auto
numLowDimEntities
=
dimTarget
<
dimDomain
?
targetTree
.
entitySet
().
size
()
:
domainTree
.
entitySet
().
size
();
intersectionMap
.
resize
(
numLowDimEntities
);
intersectionIndex
.
resize
(
numLowDimEntities
);
}
// lambda to obtain the index of the lower-dimensional neighbor of a raw intersection
auto
getLowDimNeighborIdx
=
[]
(
const
auto
&
rawIS
)
{
return
dimTarget
<
dimDomain
?
rawIS
.
second
()
:
rawIS
.
first
();
};
// reserve memory for storing the intersections. In case of grids of
// different dimensionality this might be an overestimate. We get rid
// of the overhead memory at the end of this function though.
intersections_
.
clear
();
intersections_
.
reserve
(
rawIntersections
.
size
());
for
(
const
auto
&
rawIntersection
:
rawIntersections
)
{
bool
add
=
true
;
// Check if intersection was already inserted.
// In this case we only add new neighbor information as the geometry is identical.
if
(
isMixedDimensional
)
{
const
auto
lowDimNeighborIdx
=
getLowDimNeighborIdx
(
rawIntersection
);
for
(
int
i
=
0
;
i
<
intersectionMap
[
lowDimNeighborIdx
].
size
();
++
i
)
{
if
(
rawIntersection
.
cornersMatch
(
intersectionMap
[
lowDimNeighborIdx
][
i
]))
{
add
=
false
;
// only add the pair of neighbors using the insertionIndex
auto
idx
=
intersectionIndex
[
lowDimNeighborIdx
][
i
];
intersections_
[
idx
].
addNeighbors
(
rawIntersection
.
first
(),
rawIntersection
.
second
());
break
;
}
}
}
if
(
add
)
{
// maybe add to the map
if
(
isMixedDimensional
)
{
intersectionMap
[
getLowDimNeighborIdx
(
rawIntersection
)].
push_back
(
rawIntersection
.
corners
());
intersectionIndex
[
getLowDimNeighborIdx
(
rawIntersection
)].
push_back
(
intersections_
.
size
());
}
// add new intersection and add the neighbors
intersections_
.
emplace_back
(
domainTree
,
targetTree
);
intersections_
.
back
().
setCorners
(
rawIntersection
.
corners
());
intersections_
.
back
().
addNeighbors
(
rawIntersection
.
first
(),
rawIntersection
.
second
());
}
}
intersections_
.
shrink_to_fit
();
std
::
cout
<<
"Computed tree intersections in "
<<
timer
.
elapsed
()
<<
std
::
endl
;
}
//! Return begin iterator to intersection container
typename
Intersections
::
const_iterator
ibegin
()
const
{
return
intersections_
.
begin
();
}
//! Return end iterator to intersection container
typename
Intersections
::
const_iterator
iend
()
const
{
return
intersections_
.
end
();
}
//! the number of intersections
std
::
size_t
size
()
const
{
return
intersections_
.
size
();
}
private
:
Intersections
intersections_
;
{
this
->
build
(
domainTree
,
targetTree
);
}
};
/*!
...
...
@@ -309,7 +63,10 @@ MultiDomainGlue< typename DomainGG::GridView, typename TargetGG::GridView,
typename
DomainGG
::
ElementMapper
,
typename
TargetGG
::
ElementMapper
>
makeGlue
(
const
DomainGG
&
domainGridGeometry
,
const
TargetGG
&
targetGridGeometry
)
{
return
{
domainGridGeometry
.
boundingBoxTree
(),
targetGridGeometry
.
boundingBoxTree
()};
MultiDomainGlue
<
typename
DomainGG
::
GridView
,
typename
TargetGG
::
GridView
,
typename
DomainGG
::
ElementMapper
,
typename
TargetGG
::
ElementMapper
>
glue
;
glue
.
build
(
domainGridGeometry
.
boundingBoxTree
(),
targetGridGeometry
.
boundingBoxTree
());
return
glue
;
}
}
// end namespace Dumux
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment