Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
amdis
amdis-core
Commits
98d84228
Commit
98d84228
authored
Jul 27, 2020
by
Praetorius, Simon
Browse files
Merge branch 'feature/tree_container' into 'master'
add extended TreeContainer implementation and replace TreeData See merge request
!193
parents
1f3895e9
a7a4301c
Changes
16
Hide whitespace changes
Inline
Side-by-side
amdis/BiLinearForm.hpp
View file @
98d84228
...
...
@@ -57,8 +57,6 @@ namespace AMDiS
,
colBasis_
(
colBasis
)
,
updatePattern_
(
true
)
{
operators_
.
init
(
*
rowBasis_
,
*
colBasis_
);
auto
const
rowSize
=
rowBasis_
->
localView
().
maxSize
();
auto
const
colSize
=
colBasis_
->
localView
().
maxSize
();
elementMatrix_
.
resize
(
rowSize
,
colSize
);
...
...
amdis/BiLinearForm.inc.hpp
View file @
98d84228
...
...
@@ -20,13 +20,15 @@ addOperator(ContextTag contextTag, Expr const& expr,
static_assert
(
Concepts
::
PreTreePath
<
ColTreePath
>
,
"col must be a valid treepath, or an integer/index-constant"
);
auto
i
=
child
(
this
->
rowBasis
()
->
localView
().
tree
(),
makeTreePath
(
row
));
auto
j
=
child
(
this
->
colBasis
()
->
localView
().
tree
(),
makeTreePath
(
col
));
auto
i
=
makeTreePath
(
row
);
auto
node_i
=
child
(
this
->
rowBasis
()
->
localView
().
tree
(),
i
);
auto
j
=
makeTreePath
(
col
);
auto
node_j
=
child
(
this
->
colBasis
()
->
localView
().
tree
(),
j
);
using
LocalContext
=
typename
ContextTag
::
type
;
using
Tr
=
DefaultAssemblerTraits
<
LocalContext
,
ElementMatrix
>
;
auto
op
=
makeLocalOperator
<
LocalContext
>
(
expr
,
this
->
rowBasis
()
->
gridView
());
auto
localAssembler
=
makeUniquePtr
(
makeAssembler
<
Tr
>
(
std
::
move
(
op
),
i
,
j
));
auto
localAssembler
=
makeUniquePtr
(
makeAssembler
<
Tr
>
(
std
::
move
(
op
),
node_i
,
node_
j
));
operators_
[
i
][
j
].
push
(
contextTag
,
std
::
move
(
localAssembler
));
updatePattern_
=
true
;
...
...
@@ -47,9 +49,9 @@ assemble(RowLocalView const& rowLocalView, ColLocalView const& colLocalView)
auto
const
&
element
=
rowLocalView
.
element
();
auto
geometry
=
element
.
geometry
();
for_each_node
(
rowLocalView
.
tree
(),
[
&
](
auto
const
&
rowNode
,
auto
)
{
for_each_node
(
colLocalView
.
tree
(),
[
&
](
auto
const
&
colNode
,
auto
)
{
auto
&
matOp
=
operators_
[
row
Node
][
col
Node
];
for_each_node
(
rowLocalView
.
tree
(),
[
&
](
auto
const
&
rowNode
,
auto
rowTp
)
{
for_each_node
(
colLocalView
.
tree
(),
[
&
](
auto
const
&
colNode
,
auto
colTp
)
{
auto
&
matOp
=
operators_
[
row
Tp
][
col
Tp
];
if
(
matOp
)
{
matOp
.
bind
(
element
,
geometry
);
assembleOperators
(
gv
,
element
,
matOp
,
makeMatrixAssembler
(
rowNode
,
colNode
,
elementMatrix_
));
...
...
amdis/BoundaryCondition.hpp
View file @
98d84228
...
...
@@ -3,7 +3,7 @@
#include
<list>
#include
<memory>
#include
<amdis/typetree/Tree
Data
.hpp>
#include
<amdis/typetree/Tree
Container
.hpp>
namespace
AMDiS
{
...
...
@@ -48,6 +48,8 @@ namespace AMDiS
/// Container for storing shared pointers to boundary conditions indexed by their position in
/// the basis tree, see \ref MatrixData.
template
<
class
Mat
,
class
Sol
,
class
Rhs
,
class
RB
,
class
CB
>
using
BoundaryConditions
=
MatrixData
<
RB
,
CB
,
BCData
<
Mat
,
Sol
,
Rhs
>::
template
type
>;
using
BoundaryConditions
=
TreeMatrix
<
BCData
<
Mat
,
Sol
,
Rhs
>::
template
type
,
typename
RB
::
LocalView
::
Tree
,
typename
CB
::
LocalView
::
Tree
>;
}
// end namespace AMDiS
amdis/DataTransfer.hpp
View file @
98d84228
...
...
@@ -94,7 +94,7 @@ namespace AMDiS
template
<
class
Node
>
using
NodeElementData
=
typename
NodeDataTransfer
<
Node
,
Container
,
Basis
>::
NodeElementData
;
using
ElementData
=
TYPEOF
(
make
TreeContainer
<
NodeElementData
>
(
std
::
declval
<
const
Tree
&>
()))
;
using
ElementData
=
TreeContainer
<
NodeElementData
,
Tree
,
true
>
;
using
Interface
=
DataTransferInterface
<
Container
>
;
...
...
@@ -138,7 +138,7 @@ namespace AMDiS
/// Data transfer on a single basis node
template
<
class
Node
>
using
NDT
=
NodeDataTransfer
<
Node
,
Container
,
Basis
>
;
using
NodeDataTransferContainer
=
TYPEOF
(
make
TreeContainer
<
NDT
>
(
std
::
declval
<
const
Tree
&>
()))
;
using
NodeDataTransferContainer
=
TreeContainer
<
NDT
,
Tree
,
true
>
;
NodeDataTransferContainer
nodeDataTransfer_
;
};
...
...
amdis/DataTransfer.inc.hpp
View file @
98d84228
...
...
@@ -46,7 +46,7 @@ template <class C, class B>
DataTransfer
<
C
,
B
>::
DataTransfer
(
std
::
shared_ptr
<
B
const
>
basis
)
:
basis_
(
std
::
move
(
basis
))
,
mapper_
(
basis_
->
gridView
().
grid
(),
Dune
::
mcmgElementLayout
())
,
nodeDataTransfer_
(
makeTreeContainer
<
NDT
>
(
basis_
->
localView
().
tree
())
)
,
nodeDataTransfer_
()
{}
...
...
@@ -66,7 +66,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
persistentContainer_
.
clear
();
// Redundant if postAdapt was correctly called last cycle
for
(
const
auto
&
e
:
elements
(
gv
))
{
auto
it
=
persistentContainer_
.
emplace
(
idSet
.
id
(
e
),
makeTreeContainer
<
NodeElementData
>
(
lv
.
tree
()));
auto
it
=
persistentContainer_
.
emplace
(
idSet
.
id
(
e
),
makeTreeContainer
<
NodeElementData
,
true
>
(
lv
.
tree
()));
lv
.
bind
(
e
);
auto
&
treeContainer
=
it
.
first
->
second
;
...
...
@@ -88,7 +88,7 @@ preAdapt(C const& coeff, bool mightCoarsen)
while
(
father
.
mightVanish
()
&&
father
.
hasFather
())
{
father
=
father
.
father
();
auto
it
=
persistentContainer_
.
emplace
(
idSet
.
id
(
father
),
makeTreeContainer
<
NodeElementData
>
(
lv
.
tree
()));
auto
it
=
persistentContainer_
.
emplace
(
idSet
.
id
(
father
),
makeTreeContainer
<
NodeElementData
,
true
>
(
lv
.
tree
()));
if
(
!
it
.
second
)
continue
;
...
...
amdis/LinearForm.hpp
View file @
98d84228
...
...
@@ -44,8 +44,6 @@ namespace AMDiS
:
Super
(
*
basis
)
,
basis_
(
basis
)
{
operators_
.
init
(
*
basis
);
auto
const
localSize
=
basis
->
localView
().
maxSize
();
elementVector_
.
resize
(
localSize
);
}
...
...
amdis/LinearForm.inc.hpp
View file @
98d84228
...
...
@@ -18,12 +18,13 @@ addOperator(ContextTag contextTag, Expr const& expr, TreePath path)
static_assert
(
Concepts
::
PreTreePath
<
TreePath
>
,
"path must be a valid treepath, or an integer/index-constant"
);
auto
i
=
child
(
this
->
basis
()
->
localView
().
tree
(),
makeTreePath
(
path
));
auto
i
=
makeTreePath
(
path
);
auto
node
=
child
(
this
->
basis
()
->
localView
().
tree
(),
i
);
using
LocalContext
=
typename
ContextTag
::
type
;
using
Tr
=
DefaultAssemblerTraits
<
LocalContext
,
ElementVector
>
;
auto
op
=
makeLocalOperator
<
LocalContext
>
(
expr
,
this
->
basis
()
->
gridView
());
auto
localAssembler
=
makeUniquePtr
(
makeAssembler
<
Tr
>
(
std
::
move
(
op
),
i
));
auto
localAssembler
=
makeUniquePtr
(
makeAssembler
<
Tr
>
(
std
::
move
(
op
),
node
));
operators_
[
i
].
push
(
contextTag
,
std
::
move
(
localAssembler
));
}
...
...
@@ -41,8 +42,8 @@ assemble(LocalView const& localView)
auto
const
&
element
=
localView
.
element
();
auto
geometry
=
element
.
geometry
();
for_each_node
(
localView
.
tree
(),
[
&
](
auto
const
&
node
,
auto
)
{
auto
&
rhsOp
=
operators_
[
node
];
for_each_node
(
localView
.
tree
(),
[
&
](
auto
const
&
node
,
auto
tp
)
{
auto
&
rhsOp
=
operators_
[
tp
];
if
(
rhsOp
)
{
rhsOp
.
bind
(
element
,
geometry
);
assembleOperators
(
gv
,
element
,
rhsOp
,
makeVectorAssembler
(
node
,
elementVector_
));
...
...
amdis/OperatorList.hpp
View file @
98d84228
...
...
@@ -5,7 +5,7 @@
#include
<amdis/BoundarySubset.hpp>
#include
<amdis/AssemblerInterface.hpp>
#include
<amdis/typetree/Tree
Data
.hpp>
#include
<amdis/typetree/Tree
Container
.hpp>
namespace
AMDiS
{
...
...
@@ -141,10 +141,15 @@ namespace AMDiS
template
<
class
RowBasis
,
class
ColBasis
,
class
ElementMatrix
>
using
MatrixOperators
=
MatrixData
<
RowBasis
,
ColBasis
,
OperatorLists
<
typename
RowBasis
::
GridView
,
ElementMatrix
>::
template
MatData
>;
=
TreeMatrix
<
OperatorLists
<
typename
RowBasis
::
GridView
,
ElementMatrix
>::
template
MatData
,
typename
RowBasis
::
LocalView
::
Tree
,
typename
ColBasis
::
LocalView
::
Tree
>;
template
<
class
Global
Basis
,
class
ElementVector
>
template
<
class
Basis
,
class
ElementVector
>
using
VectorOperators
=
VectorData
<
GlobalBasis
,
OperatorLists
<
typename
GlobalBasis
::
GridView
,
ElementVector
>::
template
VecData
>;
=
TreeContainer
<
OperatorLists
<
typename
Basis
::
GridView
,
ElementVector
>::
template
VecData
,
typename
Basis
::
LocalView
::
Tree
>;
}
// end namespace AMDiS
amdis/PeriodicBC.inc.hpp
View file @
98d84228
...
...
@@ -197,7 +197,7 @@ auto PeriodicBC<Mat, Sol, Rhs, Basis, TP>::
coords
(
Node
const
&
tree
,
std
::
vector
<
std
::
size_t
>
const
&
localIndices
)
const
{
std
::
vector
<
Domain
>
dofCoords
(
localIndices
.
size
());
for_each_leaf_node
(
tree
,
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
for_each_leaf_node
(
tree
,
[
&
](
auto
const
&
node
,
auto
&&
)
{
std
::
size_t
size
=
node
.
finiteElement
().
size
();
auto
geometry
=
node
.
element
().
geometry
();
...
...
amdis/ProblemStat.hpp
View file @
98d84228
...
...
@@ -33,17 +33,12 @@
#include
<amdis/ProblemStatBase.hpp>
#include
<amdis/ProblemStatTraits.hpp>
#include
<amdis/StandardProblemIteration.hpp>
#include
<amdis/common/SharedPtr.hpp>
#include
<amdis/common/TupleUtility.hpp>
#include
<amdis/common/TypeTraits.hpp>
#include
<amdis/GridFunctions.hpp>
#include
<amdis/gridfunctions/DiscreteFunction.hpp>
#include
<amdis/io/FileWriterBase.hpp>
#include
<amdis/typetree/TreeData.hpp>
#include
<amdis/typetree/TreePath.hpp>
namespace
AMDiS
...
...
@@ -305,7 +300,7 @@ namespace AMDiS
bool
storeMatrixData
=
false
)
override
;
/// Implementation of \ref ProblemStatBase::estimate.
void
estimate
(
AdaptInfo
&
adaptInfo
)
override
{
/* do nothing. */
}
void
estimate
(
AdaptInfo
&
/*
adaptInfo
*/
)
override
{
/* do nothing. */
}
/// Implementation of \ref ProblemStatBase::refineMesh.
Flag
adaptGrid
(
AdaptInfo
&
adaptInfo
)
override
;
...
...
amdis/ProblemStat.inc.hpp
View file @
98d84228
...
...
@@ -209,10 +209,7 @@ void ProblemStat<Traits>::createGlobalBasisImpl(std::false_type)
template
<
class
Traits
>
void
ProblemStat
<
Traits
>::
initGlobalBasis
()
{
boundaryConditions_
.
init
(
*
globalBasis_
,
*
globalBasis_
);
}
void
ProblemStat
<
Traits
>::
initGlobalBasis
()
{}
template
<
class
Traits
>
...
...
@@ -227,7 +224,7 @@ void ProblemStat<Traits>::createMatricesAndVectors()
rhs_
=
std
::
make_shared
<
SystemVector
>
(
globalBasis_
);
auto
localView
=
globalBasis_
->
localView
();
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
->
void
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
&&
,
auto
treePath
)
->
void
{
std
::
string
i
=
to_string
(
treePath
);
estimates_
[
i
].
resize
(
globalBasis_
->
gridView
().
indexSet
().
size
(
0
));
...
...
@@ -255,7 +252,7 @@ void ProblemStat<Traits>::createMarker()
{
marker_
.
clear
();
auto
localView
=
globalBasis_
->
localView
();
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
->
void
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
&&
,
auto
treePath
)
->
void
{
std
::
string
componentName
=
name_
+
"->marker["
+
to_string
(
treePath
)
+
"]"
;
...
...
@@ -358,7 +355,7 @@ addPeriodicBC(BoundaryType id, WorldMatrix const& matrix, WorldVector const& vec
template
<
class
Traits
>
void
ProblemStat
<
Traits
>::
solve
(
AdaptInfo
&
adaptInfo
,
bool
createMatrixData
,
bool
storeMatrixData
)
solve
(
AdaptInfo
&
/*
adaptInfo
*/
,
bool
createMatrixData
,
bool
storeMatrixData
)
{
Dune
::
Timer
t
;
...
...
@@ -449,7 +446,7 @@ globalRefine(int n)
template
<
class
Traits
>
Flag
ProblemStat
<
Traits
>::
adaptGrid
(
AdaptInfo
&
adaptInfo
)
adaptGrid
(
AdaptInfo
&
/*
adaptInfo
*/
)
{
Dune
::
Timer
t
;
...
...
@@ -470,9 +467,9 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
Dune
::
Timer
t2
;
auto
localView
=
globalBasis_
->
localView
();
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
rowNode
,
auto
rowTp
)
->
void
{
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
colNode
,
auto
colTp
)
->
void
{
for
(
auto
bc
:
boundaryConditions_
[
row
Node
][
col
Node
])
for_each_node
(
localView
.
tree
(),
[
&
](
auto
&&
,
auto
rowTp
)
->
void
{
for_each_node
(
localView
.
tree
(),
[
&
](
auto
&&
,
auto
colTp
)
->
void
{
for
(
auto
bc
:
boundaryConditions_
[
row
Tp
][
col
Tp
])
bc
->
init
();
});
});
...
...
@@ -509,10 +506,10 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
t2
.
reset
();
solution_
->
resize
(
sizeInfo
(
*
globalBasis_
));
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
rowNode
,
auto
row
_t
p
)
->
void
{
for_each_node
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
colNode
,
auto
col
_t
p
)
->
void
{
for_each_node
(
localView
.
tree
(),
[
&
](
auto
&&
,
auto
row
T
p
)
->
void
{
for_each_node
(
localView
.
tree
(),
[
&
](
auto
&&
,
auto
col
T
p
)
->
void
{
// finish boundary condition
for
(
auto
bc
:
boundaryConditions_
[
row
Node
][
col
Node
])
for
(
auto
bc
:
boundaryConditions_
[
row
Tp
][
col
Tp
])
bc
->
apply
(
*
systemMatrix_
,
*
solution_
,
*
rhs_
);
});
});
...
...
amdis/typetree/CMakeLists.txt
View file @
98d84228
...
...
@@ -5,6 +5,5 @@ install(FILES
RangeType.hpp
Traversal.hpp
TreeContainer.hpp
TreeData.hpp
TreePath.hpp
DESTINATION
${
CMAKE_INSTALL_INCLUDEDIR
}
/amdis/typetree
)
amdis/typetree/TreeContainer.hpp
View file @
98d84228
...
...
@@ -18,20 +18,217 @@
namespace
AMDiS
{
/// \brief Vector data-structure with tree-path index access and hierarchic structure
/// given by the `Container` template type
/**
* This Vector container is parametrized with the actual container type that is stored
* internally. Access to the elements of the container is possible by using a tree-path
* index.
*
* The internal container is constructed by the \ref ContainerFactory, storing for each
* tree node a corresponding array or tuple plus a value. The data-structure to hold
* both, the value and the container is defined in \ref ValueAndContainer.
**/
template
<
class
Container
>
class
TreeContainerStorage
{
using
Self
=
TreeContainerStorage
;
template
<
class
C
>
static
constexpr
decltype
(
auto
)
accessByTreePath
(
C
&&
container
,
Dune
::
TypeTree
::
HybridTreePath
<>
const
&
)
{
return
container
.
value
();
}
template
<
class
C
,
class
...
T
>
static
constexpr
decltype
(
auto
)
accessByTreePath
(
C
&&
container
,
Dune
::
TypeTree
::
HybridTreePath
<
T
...
>
const
&
path
)
{
auto
head
=
Dune
::
TypeTree
::
treePathEntry
(
path
,
Dune
::
Indices
::
_0
);
return
accessByTreePath
(
container
[
head
],
pop_front
(
path
));
}
public:
/// \brief Default-construct the tree-container
TreeContainerStorage
()
:
container_
()
{}
TreeContainerStorage
(
Container
const
&
container
)
:
container_
(
container
)
{}
/// \brief Construct the tree-container from a given container storage
TreeContainerStorage
(
Container
&&
container
)
:
container_
(
std
::
move
(
container
))
{}
/// \brief Access a (const) element of the container by treepath
template
<
class
...
T
>
decltype
(
auto
)
operator
[](
Dune
::
TypeTree
::
HybridTreePath
<
T
...
>
const
&
path
)
const
{
return
accessByTreePath
(
container_
,
path
);
}
/// \brief Access a (mutable) element of the container by treepath
template
<
class
...
T
>
decltype
(
auto
)
operator
[](
Dune
::
TypeTree
::
HybridTreePath
<
T
...
>
const
&
path
)
{
return
accessByTreePath
(
container_
,
path
);
}
/// \brief Obtain the container (const)
Container
const
&
data
()
const
{
return
container_
;
}
/// \brief Obtain the container (mutable)
Container
&
data
()
{
return
container_
;
}
/// \brief Compare two containers for equality
bool
operator
==
(
TreeContainerStorage
const
&
other
)
const
{
return
container_
==
other
.
container_
;
}
/// \brief Compare two containers for inequality
bool
operator
!=
(
TreeContainerStorage
const
&
other
)
const
{
return
container_
!=
other
.
container_
;
}
private:
Container
container_
;
};
namespace
Impl
{
template
<
class
Value
,
class
Container
>
class
ValueAndContainer
{
public:
template
<
class
V
,
class
C
>
ValueAndContainer
(
V
&&
value
,
C
&&
container
)
:
value_
(
FWD
(
value
))
,
container_
(
FWD
(
container
))
{}
ValueAndContainer
()
:
value_
()
,
container_
()
{}
template
<
class
I
>
auto
&
operator
[](
I
const
&
i
)
{
return
container_
[
i
];
}
template
<
class
I
>
auto
const
&
operator
[](
I
const
&
i
)
const
{
return
container_
[
i
];
}
Value
&
value
()
{
return
value_
;
}
Value
const
&
value
()
const
{
return
value_
;
}
Container
&
container
()
{
return
container_
;
}
Container
const
&
container
()
const
{
return
container_
;
}
bool
operator
==
(
ValueAndContainer
const
&
other
)
const
{
return
value_
==
other
.
value_
&&
container_
==
other
.
container_
;
}
private:
Value
value_
;
Container
container_
;
};
template
<
class
Value
>
class
ValueAndContainer
<
Value
,
void
>
{
public:
template
<
class
V
,
Dune
::
disableCopyMove
<
ValueAndContainer
,
V
>
=
0
>
ValueAndContainer
(
V
&&
value
)
:
value_
(
FWD
(
value
))
{}
ValueAndContainer
()
:
value_
()
{}
Value
&
value
()
{
return
value_
;
}
Value
const
&
value
()
const
{
return
value_
;
}
bool
operator
==
(
ValueAndContainer
const
&
other
)
const
{
return
value_
==
other
.
value_
;
}
private:
Value
value_
;
};
struct
Ignore
{};
template
<
class
Container
>
class
ValueAndContainer
<
Ignore
,
Container
>
{
public:
template
<
class
C
>
ValueAndContainer
(
Ignore
,
C
&&
container
)
:
container_
(
FWD
(
container
))
{}
ValueAndContainer
()
:
container_
()
{}
template
<
class
I
>
auto
&
operator
[](
I
const
&
i
)
{
return
container_
[
i
];
}
template
<
class
I
>
auto
const
&
operator
[](
I
const
&
i
)
const
{
return
container_
[
i
];
}
Ignore
value
()
{
return
{};
}
Ignore
value
()
const
{
return
{};
}
Container
&
container
()
{
return
container_
;
}
Container
const
&
container
()
const
{
return
container_
;
}
bool
operator
==
(
ValueAndContainer
const
&
other
)
const
{
return
container_
==
other
.
container_
;
}
private:
Container
container_
;
};
template
<
class
Value
,
class
Container
>
ValueAndContainer
(
Value
const
&
,
Container
const
&
)
->
ValueAndContainer
<
Value
,
Container
>
;
template
<
class
Value
>
ValueAndContainer
(
Value
const
&
)
->
ValueAndContainer
<
Value
,
void
>
;
/// \brief A factory class creating a hybrid container compatible with a type tree
/**
*
*
This class allows to create a nested hybrid container having the same structur
e
*
as a given type tree. Power nodes are represented as std::array's while composite
*
nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
*
are creating using a given predicate. Once created, the factory provides an
* operator() creating the container for the tree given as argument.
*
*
\tparam LeafToValue Type of a predicate that determines the stored values at the
leafs
*/
template
<
class
Leaf
ToValue
>
*
This class allows to create a nested hybrid container having the same structure
*
as a given type tree. Power nodes are represented as std::array's while composit
e
*
nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
*
are creating using a given predicate. Once created, the factory provides an
*
operator() creating the container for the tree given as argument.
*
*
\tparam NodeToValue Type of a predicate that determines the stored values at the
*
leafs
*
*/
template
<
class
Node
ToValue
,
bool
leafOnly
=
false
>
class
ContainerFactory
{
public:
...
...
@@ -41,25 +238,29 @@ namespace AMDiS
*
* \param A predicate used to generate the stored values for the leaves
*/
ContainerFactory
(
Leaf
ToValue
leaf
ToValue
)
:
leaf
ToValue_
(
std
::
move
(
leaf
ToValue
))
ContainerFactory
(
Node
ToValue
node
ToValue
)
:
node
ToValue_
(
std
::
move
(
node
ToValue
))
{}
/// \brief Return a container for storing the node content
template
<
class
Node
>
auto
operator
()
(
Node
const
&
node
)
const
auto
operator
()(
Node
const
&
node
)
const
{
if
constexpr
(
Node
::
isLeaf
)
return
leafToV
alue
_
(
node
);
return
ValueAndContainer
{
v
alue
(
node
)
}
;
else
if
constexpr
(
Node
::
isPower
)
{
using
TransformedChild
=
decltype
((
*
this
)(
node
.
child
(
0
)));
return
std
::
array
<
TransformedChild
,
Node
::
degree
()
>
();
return
ValueAndContainer
{
value
(
node
),
std
::
array
<
TransformedChild
,
Node
::
degree
()
>
()};
}
else
if
constexpr
(
Node
::
isComposite
)
{
return
Tools
::
apply_indices
<
Node
::
degree
()
>
(
[
&
](
auto
...
i
)
{
return
Dune
::
makeTupleVector
((
*
this
)(
node
.
child
(
i
))...);
});
return
ValueAndContainer
{
value
(
node
),
Tools
::
apply_indices
<
Node
::
degree
()
>
(
[
&
](
auto
...
i
)
{
return
Dune
::
makeTupleVector
((
*
this
)(
node
.
child
(
i
))...);
})};
}
else
{
static_assert
(
Node
::
isLeaf
||
Node
::
isPower
||
Node
::
isComposite
,
...
...
@@ -68,93 +269,23 @@ namespace AMDiS
}
}
private:
LeafToValue
leafToValue_
;
};
/// \brief Wrap nested container to provide a VectorBackend
template
<
class
Container
>
class
TreeContainerVectorBackend
{
using
Self
=
TreeContainerVectorBackend
;
template
<
class
C
>
static
constexpr
decltype
(
auto
)
accessByTreePath
(
C
&&
container
,
Dune
::
TypeTree
::
HybridTreePath
<>
const
&
path
)
{
return
container
;
}
template
<
class
C
,
class
...
T
>
static
constexpr
decltype
(
auto
)
accessByTreePath
(
C
&&
container
,
Dune
::
TypeTree
::
HybridTreePath
<
T
...
>
const
&
path
)
{
auto
head
=
Dune
::
TypeTree
::
treePathEntry
(
path
,
Dune
::
Indices
::
_0
);
return
accessByTreePath
(
container
[
head
],
pop_front
(
path
));
}
public:
/// \brief Default-construct the tree-container
TreeContainerVectorBackend
()
:
container_
()
{}
/// \brief Construct the tree-container from a given container storage
TreeContainerVectorBackend
(
Container
&&
container
)
:
container_
(
std
::
move
(
container
))
{}
/// \brief Access a (const) element of the container by treepath
template
<
class
...
T
>
decltype
(
auto
)
operator
[](
Dune
::
TypeTree
::
HybridTreePath
<
T
...
>
const
&
path
)
const
{
return
accessByTreePath
(
container_
,
path
);
}
/// \brief Access a (mutable) element of the container by treepath
template
<
class
...
T
>
decltype
(
auto
)
operator
[](
Dune
::
TypeTree
::
HybridTreePath
<
T
...
>
const
&
path
)
{