Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Praetorius, Simon
dune-amdis
Commits
0689eaae
Commit
0689eaae
authored
Mar 13, 2019
by
Praetorius, Simon
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reduce errors and compiletime in tree traversal
parent
efebae43
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
319 additions
and
287 deletions
+319
-287
cmake/modules/AmdisCXXFeatures.cmake
cmake/modules/AmdisCXXFeatures.cmake
+12
-2
config.h.cmake
config.h.cmake
+1
-0
examples/CMakeLists.txt
examples/CMakeLists.txt
+1
-1
src/amdis/BoundaryManager.hpp
src/amdis/BoundaryManager.hpp
+4
-3
src/amdis/DataTransfer.inc.hpp
src/amdis/DataTransfer.inc.hpp
+7
-7
src/amdis/DirichletBC.hpp
src/amdis/DirichletBC.hpp
+1
-1
src/amdis/PeriodicBC.inc.hpp
src/amdis/PeriodicBC.inc.hpp
+1
-1
src/amdis/ProblemStat.inc.hpp
src/amdis/ProblemStat.inc.hpp
+7
-7
src/amdis/common/ForEach.hpp
src/amdis/common/ForEach.hpp
+28
-11
src/amdis/common/TypeTraits.hpp
src/amdis/common/TypeTraits.hpp
+6
-0
src/amdis/gridfunctions/DiscreteFunction.inc.hpp
src/amdis/gridfunctions/DiscreteFunction.inc.hpp
+2
-2
src/amdis/linearalgebra/DOFMatrixBase.inc.hpp
src/amdis/linearalgebra/DOFMatrixBase.inc.hpp
+3
-3
src/amdis/linearalgebra/DOFVectorBase.inc.hpp
src/amdis/linearalgebra/DOFVectorBase.inc.hpp
+2
-2
src/amdis/typetree/CMakeLists.txt
src/amdis/typetree/CMakeLists.txt
+0
-1
src/amdis/typetree/Traversal.hpp
src/amdis/typetree/Traversal.hpp
+234
-116
src/amdis/typetree/TreeData.hpp
src/amdis/typetree/TreeData.hpp
+4
-4
src/amdis/typetree/Visitor.hpp
src/amdis/typetree/Visitor.hpp
+0
-120
test/DataTransferTest.hpp
test/DataTransferTest.hpp
+2
-2
test/TreeDataTest.cpp
test/TreeDataTest.cpp
+4
-4
No files found.
cmake/modules/AmdisCXXFeatures.cmake
View file @
0689eaae
#include(CheckIncludeFileCXX)
include
(
CheckCXXSourceCompiles
)
#include(CheckCXXSymbolExists)
# fold expressions (a + ...)
check_cxx_source_compiles
(
"
...
...
@@ -30,4 +28,16 @@ check_cxx_source_compiles("
return f<1>();
}
"
AMDIS_HAS_CXX_CONSTEXPR_IF
)
check_cxx_source_compiles
(
"
#include <iostream>
#include <tuple>
int main()
{
auto tup = std::make_tuple(0, 'a', 3.14);
for... (auto elem : tup)
std::cout << elem << std::endl;
}
"
AMDIS_HAS_EXPANSION_STATEMENTS
)
\ No newline at end of file
config.h.cmake
View file @
0689eaae
...
...
@@ -49,6 +49,7 @@
/* some detected compiler features may be used in AMDiS */
#cmakedefine AMDIS_HAS_CXX_FOLD_EXPRESSIONS 1
#cmakedefine AMDIS_HAS_CXX_CONSTEXPR_IF 1
#cmakedefine AMDIS_HAS_EXPANSION_STATEMENTS 1
/* end amdis
Everything below here will be overwritten
...
...
examples/CMakeLists.txt
View file @
0689eaae
...
...
@@ -24,4 +24,4 @@ add_dependencies(examples
stokes1.2d
stokes3.2d
navier_stokes.2d
convection_diffusion.2d
)
\ No newline at end of file
convection_diffusion.2d
)
src/amdis/BoundaryManager.hpp
View file @
0689eaae
...
...
@@ -146,9 +146,10 @@ namespace AMDiS
if
(
!
segment
.
boundary
())
continue
;
auto
index
=
segment
.
boundarySegmentIndex
();
Dune
::
Hybrid
::
ifElse
(
Dune
::
Std
::
is_detected
<
HasBoundaryId
,
Segment
>
{},
[
&
](
auto
id
)
{
boundaryIds_
[
index
]
=
id
(
segment
).
boundaryId
();
});
Dune
::
Hybrid
::
ifElse
(
Dune
::
Std
::
is_detected
<
HasBoundaryId
,
Segment
>
{},
[
&
](
auto
id
)
{
auto
index
=
segment
.
boundarySegmentIndex
();
boundaryIds_
[
index
]
=
id
(
segment
).
boundaryId
();
});
}
}
}
...
...
src/amdis/DataTransfer.inc.hpp
View file @
0689eaae
...
...
@@ -22,8 +22,8 @@
#include <amdis/Output.hpp>
#include <amdis/common/ConcurrentCache.hpp>
#include <amdis/typetree/Traversal.hpp>
#include <amdis/typetree/TreeContainer.hpp>
#include <amdis/typetree/Visitor.hpp>
namespace
AMDiS
{
...
...
@@ -135,7 +135,7 @@ namespace AMDiS
auto
lv
=
basis_
->
localView
();
auto
const
&
idSet
=
gv
.
grid
().
localIdSet
();
for
E
ach
L
eaf
N
ode
_
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
for
_e
ach
_l
eaf
_n
ode
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
nodeDataTransfer_
[
tp
].
preAdaptInit
(
lv
,
coeff
,
node
);
});
...
...
@@ -148,7 +148,7 @@ namespace AMDiS
lv
.
bind
(
e
);
auto
&
treeContainer
=
it
.
first
->
second
;
for
E
ach
L
eaf
N
ode
_
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
for
_e
ach
_l
eaf
_n
ode
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
nodeDataTransfer_
[
tp
].
cacheLocal
(
treeContainer
[
tp
]);
});
}
...
...
@@ -201,7 +201,7 @@ namespace AMDiS
};
restrictLocalCompleted
=
true
;
for
E
ach
L
eaf
N
ode
_
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
for
_e
ach
_l
eaf
_n
ode
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
restrictLocalCompleted
&=
nodeDataTransfer_
[
tp
].
restrictLocal
(
father
,
treeContainer
[
tp
],
xInChildCached
,
childContainer
[
tp
],
init
);
...
...
@@ -224,7 +224,7 @@ namespace AMDiS
auto
gv
=
basis_
->
gridView
();
auto
lv
=
basis_
->
localView
();
auto
const
&
idSet
=
gv
.
grid
().
localIdSet
();
for
E
ach
L
eaf
N
ode
_
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
for
_e
ach
_l
eaf
_n
ode
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
nodeDataTransfer_
[
tp
].
postAdaptInit
(
lv
,
coeff
,
node
);
});
...
...
@@ -243,7 +243,7 @@ namespace AMDiS
if
(
it
!=
persistentContainer_
.
end
())
{
lv
.
bind
(
e
);
auto
const
&
treeContainer
=
it
->
second
;
for
E
ach
L
eaf
N
ode
_
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
for
_e
ach
_l
eaf
_n
ode
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
nodeDataTransfer_
[
tp
].
copyLocal
(
treeContainer
[
tp
]);
});
finished_
[
index
]
=
true
;
...
...
@@ -275,7 +275,7 @@ namespace AMDiS
return
fatherGeo
.
local
(
childGeo
.
global
(
x
));
};
for
E
ach
L
eaf
N
ode
_
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
for
_e
ach
_l
eaf
_n
ode
(
lv
.
tree
(),
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
nodeDataTransfer_
[
tp
].
prolongLocal
(
father
,
treeContainer
[
tp
],
xInFather
,
init
);
});
...
...
src/amdis/DirichletBC.hpp
View file @
0689eaae
...
...
@@ -11,8 +11,8 @@
#include <amdis/BoundaryCondition.hpp>
#include <amdis/common/Concepts.hpp>
#include <amdis/typetree/RangeType.hpp>
#include <amdis/typetree/Traversal.hpp>
#include <amdis/typetree/TreeData.hpp>
#include <amdis/typetree/Visitor.hpp>
namespace
AMDiS
{
...
...
src/amdis/PeriodicBC.inc.hpp
View file @
0689eaae
...
...
@@ -196,7 +196,7 @@ std::vector<D> PeriodicBC<D,MI>::
coords
(
Node
const
&
tree
,
std
::
vector
<
std
::
size_t
>
const
&
localIndices
)
const
{
std
::
vector
<
D
>
dofCoords
(
localIndices
.
size
());
AMDiS
::
for
E
ach
L
eaf
N
ode
_
(
tree
,
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
for
_e
ach
_l
eaf
_n
ode
(
tree
,
[
&
](
auto
const
&
node
,
auto
const
&
tp
)
{
std
::
size_t
size
=
node
.
finiteElement
().
size
();
auto
geometry
=
node
.
element
().
geometry
();
...
...
src/amdis/ProblemStat.inc.hpp
View file @
0689eaae
...
...
@@ -177,7 +177,7 @@ void ProblemStat<Traits>::createMatricesAndVectors()
rhs_
=
std
::
make_shared
<
SystemVector
>
(
*
globalBasis_
,
NO_OPERATION
);
auto
localView
=
globalBasis_
->
localView
();
AMDiS
::
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
{
std
::
string
i
=
to_string
(
treePath
);
estimates_
[
i
].
resize
(
globalBasis_
->
gridView
().
indexSet
().
size
(
0
));
...
...
@@ -205,7 +205,7 @@ void ProblemStat<Traits>::createMarker()
{
marker_
.
clear
();
auto
localView
=
globalBasis_
->
localView
();
AMDiS
::
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
{
std
::
string
componentName
=
name_
+
"->marker["
+
to_string
(
treePath
)
+
"]"
;
...
...
@@ -232,7 +232,7 @@ void ProblemStat<Traits>::createFileWriter()
{
filewriter_
.
clear
();
auto
localView
=
globalBasis_
->
localView
();
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
node
,
auto
treePath
)
{
std
::
string
componentName
=
name_
+
"->output["
+
to_string
(
treePath
)
+
"]"
;
...
...
@@ -428,9 +428,9 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
rhs_
->
init
(
asmVector
);
auto
localView
=
globalBasis_
->
localView
();
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
rowNode
,
auto
rowTp
)
{
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
rowNode
,
auto
rowTp
)
{
auto
rowBasis
=
Dune
::
Functions
::
subspaceBasis
(
*
globalBasis_
,
rowTp
);
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
colNode
,
auto
colTp
)
{
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
colNode
,
auto
colTp
)
{
auto
colBasis
=
Dune
::
Functions
::
subspaceBasis
(
*
globalBasis_
,
colTp
);
for
(
auto
bc
:
dirichletBCs_
[
rowNode
][
colNode
])
bc
->
init
(
rowBasis
,
colBasis
);
...
...
@@ -456,8 +456,8 @@ buildAfterAdapt(AdaptInfo& /*adaptInfo*/, Flag /*flag*/, bool asmMatrix, bool as
systemMatrix_
->
finish
(
asmMatrix
);
rhs_
->
finish
(
asmVector
);
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
rowNode
,
auto
)
{
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
colNode
,
auto
)
{
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
rowNode
,
auto
)
{
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
,
this
](
auto
const
&
colNode
,
auto
)
{
// finish boundary condition
for
(
auto
bc
:
dirichletBCs_
[
rowNode
][
colNode
])
bc
->
fillBoundaryCondition
(
*
systemMatrix_
,
*
solution_
,
*
rhs_
,
rowNode
,
colNode
);
...
...
src/amdis/common/ForEach.hpp
View file @
0689eaae
...
...
@@ -2,7 +2,6 @@
#include <initializer_list>
#include <amdis/common/Apply.hpp>
#include <amdis/common/Index.hpp>
#include <amdis/common/Range.hpp>
...
...
@@ -16,34 +15,52 @@ namespace AMDiS
void
ignored_evaluation
(
std
::
initializer_list
<
T
>&&
)
{
/* do nothing */
}
}
template
<
std
::
size_t
...
I
,
class
Tuple
,
class
Functor
>
constexpr
void
for_each
(
std
::
index_sequence
<
I
...
>
,
Tuple
&&
tuple
,
Functor
&&
f
)
{
using
std
::
get
;
#if AMDIS_HAS_EXPANSION_STATEMENTS
for
...
(
auto
&&
t
:
tuple
)
{
f
(
FWD
(
t
));
}
#elif AMDIS_HAS_CXX_FOLD_EXPRESSIONS
(
f
(
get
<
I
>
(
tuple
)),...);
#else
Impl_
::
ignored_evaluation
<
int
>
({
0
,
(
f
(
get
<
I
>
(
tuple
)),
0
)...});
#endif
}
template
<
class
Tuple
,
class
Functor
>
constexpr
void
for_each
(
Tuple
&&
tuple
,
Functor
&&
f
)
{
#if AMDIS_HAS_CXX_FOLD_EXPRESSIONS
Tools
::
apply
([
f
=
std
::
move
(
f
)](
auto
&&
...
t
)
{
(
f
(
FWD
(
t
)),...);
},
tuple
);
#else
Tools
::
apply
([
f
=
std
::
move
(
f
)](
auto
&&
...
t
)
{
Impl_
::
ignored_evaluation
<
int
>
({
0
,
(
f
(
FWD
(
t
)),
0
)...});
},
tuple
);
#endif
Tools
::
for_each
(
std
::
make_index_sequence
<
Size_v
<
std
::
remove_reference_t
<
Tuple
>>>
{},
FWD
(
tuple
),
FWD
(
f
));
}
template
<
std
::
size_t
I0
=
0
,
std
::
size_t
...
I
,
class
Functor
>
constexpr
void
for_range
(
std
::
index_sequence
<
I
...
>
,
Functor
&&
f
)
{
#if AMDIS_HAS_CXX_FOLD_EXPRESSIONS
(
f
(
index_t
<
I0
+
I
>
{}),...);
#else
Impl_
::
ignored_evaluation
<
int
>
({
0
,
(
f
(
index_t
<
I0
+
I
>
{}),
0
)...});
#endif
}
template
<
std
::
size_t
I0
,
std
::
size_t
I1
,
class
Functor
>
constexpr
void
for_range
(
index_t
<
I0
>
i0
,
index_t
<
I1
>
i1
,
Functor
&&
f
)
{
Tools
::
for_
each
(
range
_t
<
I0
,
I1
>
{},
FWD
(
f
));
Tools
::
for_range
<
I0
>
(
std
::
make_index_sequence
<
std
::
size_t
(
I1
-
I0
)
>
{},
FWD
(
f
));
}
template
<
std
::
size_t
N
,
class
Functor
>
constexpr
void
for_range
(
index_t
<
N
>
,
Functor
&&
f
)
{
Tools
::
for_
each
(
range_t
<
0
,
N
>
{},
FWD
(
f
));
Tools
::
for_
range
(
std
::
make_index_sequence
<
N
>
{},
FWD
(
f
));
}
template
<
std
::
size_t
I0
,
std
::
size_t
I1
,
class
Functor
>
constexpr
void
for_range
(
Functor
&&
f
)
{
Tools
::
for_
each
(
range
_t
<
I0
,
I1
>
{},
FWD
(
f
));
Tools
::
for_range
<
I0
>
(
std
::
make_index_sequence
<
std
::
size_t
(
I1
-
I0
)
>
{},
FWD
(
f
));
}
}
// end namespace Tools
...
...
src/amdis/common/TypeTraits.hpp
View file @
0689eaae
...
...
@@ -65,6 +65,12 @@ namespace AMDiS
template
<
class
T
>
using
owner
=
T
;
/// A functor with no operation
struct
NoOp
{
template
<
class
...
T
>
constexpr
void
operator
()(
T
&&
...)
const
{
/* no nothing */
}
};
/// Create a unique_ptr by copy/move construction
template
<
class
Obj
>
...
...
src/amdis/gridfunctions/DiscreteFunction.inc.hpp
View file @
0689eaae
...
...
@@ -147,7 +147,7 @@ LocalFunction::operator()(Domain const& x) const
auto
&&
coefficients
=
*
globalFunction_
.
dofVector_
;
auto
&&
nodeToRangeEntry
=
globalFunction_
.
nodeToRangeEntry_
;
for
E
ach
L
eaf
N
ode
_
(
*
subTree_
,
[
&
,
this
](
auto
const
&
node
,
auto
const
&
tp
)
for
_e
ach
_l
eaf
_n
ode
(
*
subTree_
,
[
&
,
this
](
auto
const
&
node
,
auto
const
&
tp
)
{
auto
&&
fe
=
node
.
finiteElement
();
auto
&&
localBasis
=
fe
.
localBasis
();
...
...
@@ -193,7 +193,7 @@ GradientLocalFunction::operator()(Domain const& x) const
auto
&&
coefficients
=
*
globalFunction_
.
dofVector_
;
auto
&&
nodeToRangeEntry
=
globalFunction_
.
nodeToRangeEntry_
;
for
E
ach
L
eaf
N
ode
_
(
*
subTree_
,
[
&
,
this
](
auto
const
&
node
,
auto
const
&
tp
)
for
_e
ach
_l
eaf
_n
ode
(
*
subTree_
,
[
&
,
this
](
auto
const
&
node
,
auto
const
&
tp
)
{
// TODO: may DOFVectorView::Range to FieldVector type if necessary
using
LocalDerivativeTraits
...
...
src/amdis/linearalgebra/DOFMatrixBase.inc.hpp
View file @
0689eaae
...
...
@@ -2,7 +2,7 @@
#include <amdis/Assembler.hpp>
#include <amdis/LocalOperator.hpp>
#include <amdis/typetree/
Visitor
.hpp>
#include <amdis/typetree/
Traversal
.hpp>
#include <amdis/utility/AssembleOperators.hpp>
namespace
AMDiS
{
...
...
@@ -75,8 +75,8 @@ assemble(RowLocalView const& rowLocalView, ColLocalView const& colLocalView)
auto
const
&
element
=
rowLocalView
.
element
();
auto
geometry
=
element
.
geometry
();
for
E
ach
N
ode
_
(
rowLocalView
.
tree
(),
[
&
](
auto
const
&
rowNode
,
auto
)
{
for
E
ach
N
ode
_
(
colLocalView
.
tree
(),
[
&
](
auto
const
&
colNode
,
auto
)
{
for
_e
ach
_n
ode
(
rowLocalView
.
tree
(),
[
&
](
auto
const
&
rowNode
,
auto
)
{
for
_e
ach
_n
ode
(
colLocalView
.
tree
(),
[
&
](
auto
const
&
colNode
,
auto
)
{
auto
&
matOp
=
operators_
[
rowNode
][
colNode
];
if
(
matOp
)
{
matOp
.
bind
(
element
,
geometry
);
...
...
src/amdis/linearalgebra/DOFVectorBase.inc.hpp
View file @
0689eaae
...
...
@@ -2,7 +2,7 @@
#include <amdis/Assembler.hpp>
#include <amdis/LocalOperator.hpp>
#include <amdis/typetree/
Visitor
.hpp>
#include <amdis/typetree/
Traversal
.hpp>
#include <amdis/utility/AssembleOperators.hpp>
namespace
AMDiS
{
...
...
@@ -66,7 +66,7 @@ assemble(LocalView const& localView)
auto
const
&
element
=
localView
.
element
();
auto
geometry
=
element
.
geometry
();
for
E
ach
N
ode
_
(
localView
.
tree
(),
[
&
](
auto
const
&
node
,
auto
)
{
for
_e
ach
_n
ode
(
localView
.
tree
(),
[
&
](
auto
const
&
node
,
auto
)
{
auto
&
rhsOp
=
operators_
[
node
];
if
(
rhsOp
)
{
rhsOp
.
bind
(
element
,
geometry
);
...
...
src/amdis/typetree/CMakeLists.txt
View file @
0689eaae
...
...
@@ -7,5 +7,4 @@ install(FILES
TreeContainer.hpp
TreeData.hpp
TreePath.hpp
Visitor.hpp
DESTINATION
${
CMAKE_INSTALL_INCLUDEDIR
}
/amdis/typetree
)
src/amdis/typetree/Traversal.hpp
View file @
0689eaae
...
...
@@ -3,139 +3,257 @@
#include <dune/common/hybridutilities.hh>
#include <dune/common/rangeutilities.hh>
#include <dune/typetree/childextraction.hh>
#include <dune/typetree/nodetags.hh>
#include <dune/typetree/treepath.hh>
#include <dune/typetree/visitor.hh>
#include <amdis/common/ForEach.hpp>
#include <amdis/common/Logical.hpp>
#include <amdis/common/Range.hpp>
#include <amdis/common/TypeTraits.hpp>
namespace
AMDiS
{
// forward declaration of main engine struct
template
<
typename
NodeTag
,
bool
visit
=
true
>
struct
TraverseTree
;
// Do not visit nodes the visitor is not interested in
template
<
typename
NodeTag
>
struct
TraverseTree
<
NodeTag
,
false
>
{
template
<
typename
Node
,
typename
Visitor
,
typename
TreePath
>
static
void
apply
(
const
Node
&
node
,
const
Visitor
&
visitor
,
TreePath
const
&
tp
)
{}
};
#ifndef DOXYGEN
// some implementation details
template
<
class
Node
,
class
Index
>
struct
HybridChildType
:
HybridChildType
<
std
::
remove_const_t
<
Node
>
,
std
::
remove_const_t
<
Index
>>
{};
template
<
class
Node
>
struct
HybridChildType
<
Node
,
std
::
size_t
>
{
using
type
=
typename
Node
::
template
Child
<
0
>
::
Type
;
};
template
<
class
Node
,
std
::
size_t
K
>
struct
HybridChildType
<
Node
,
Dune
::
index_constant
<
K
>>
{
using
type
=
typename
Node
::
template
Child
<
K
>
::
Type
;
};
template
<
class
NodeTag
,
class
Node
>
constexpr
std
::
size_t
hybridDegree
(
NodeTag
,
Node
const
&
node
)
{
return
Dune
::
TypeTree
::
degree
(
node
);
}
template
<
class
Node
>
constexpr
auto
hybridDegree
(
Dune
::
TypeTree
::
CompositeNodeTag
,
Node
const
&
node
)
{
return
Dune
::
index_constant
<
Node
::
CHILDREN
>
{};
}
template
<
std
::
size_t
k
,
std
::
size_t
n
>
constexpr
bool
notLastChild
(
Dune
::
index_constant
<
k
>
const
&
,
Dune
::
index_constant
<
n
>
const
&
)
{
return
k
<
n
-
1
;
}
constexpr
bool
notLastChild
(
std
::
size_t
k
,
std
::
size_t
n
)
{
return
k
<
n
-
1
;
}
#endif
template
<
class
NodeTag
>
struct
TraverseTree
<
NodeTag
,
true
>
{
template
<
typename
N
,
typename
V
,
typename
TreePath
>
static
void
apply
(
N
&&
n
,
V
&&
v
,
TreePath
const
&
tp
)
// NOTE: backport of dune/typetree/traversal.hpp from Dune 2.7
namespace
AMDiS
{
enum
class
TreePathType
{
using
Node
=
std
::
remove_reference_t
<
N
>
;
using
Visitor
=
std
::
remove_reference_t
<
V
>
;
DYNAMIC
,
STATIC
};
namespace
Impl
{
// This is a constexpr version of the ternery operator c?t1:t1.
// In contrast to the latter the type of t1 and t2 can be different.
// Notice that std::conditional would not do the trick, because
// it only selects between types.
template
<
bool
c
,
class
T1
,
class
T2
,
std
::
enable_if_t
<
c
,
int
>
=
0
>
constexpr
auto
conditionalValue
(
T1
&&
t1
,
T2
&&
t2
)
{
return
std
::
forward
<
T1
>
(
t1
);
}
template
<
bool
c
,
class
T1
,
class
T2
,
std
::
enable_if_t
<
not
c
,
int
>
=
0
>
constexpr
auto
conditionalValue
(
T1
&&
t1
,
T2
&&
t2
)
{
return
std
::
forward
<
T2
>
(
t2
);
}
/* The signature is the same as for the public applyToTree
* function in Dune::Typetree, despite the additionally passed
* treePath argument. The path passed here is associated to
* the tree and the relative paths of the children (wrt. to tree)
* are appended to this. Hence the behavior of the public function
* is resembled by passing an empty treePath.
*/
/*
* This is the overload for leaf traversal
*/
template
<
class
T
,
class
TP
,
class
V
,
std
::
enable_if_t
<
remove_cvref_t
<
T
>
::
isLeaf
,
int
>
=
0
>
void
apply_to_tree
(
T
&&
tree
,
TP
treePath
,
V
&&
visitor
)
{
visitor
.
leaf
(
tree
,
treePath
);
}
/*
* This is the general overload doing child traversal.
*/
template
<
class
T
,
class
TP
,
class
V
,
std
::
enable_if_t
<
not
remove_cvref_t
<
T
>
::
isLeaf
,
int
>
=
0
>
void
apply_to_tree
(
T
&&
tree
,
TP
treePath
,
V
&&
visitor
)
{
// Do we really want to take care for const-ness of the Tree
// when instantiating VisitChild below? I'd rather expect this:
// using Tree = remove_cvref_t<T>;
// using Visitor = remove_cvref_t<V>;
using
Tree
=
std
::
remove_reference_t
<
T
>
;
using
Visitor
=
std
::
remove_reference_t
<
V
>
;
visitor
.
pre
(
tree
,
treePath
);
// Use statically encoded degree unless tree
// is a power node and dynamic traversal is requested.
constexpr
auto
useDynamicTraversal
=
(
Tree
::
isPower
and
Visitor
::
treePathType
==
TreePathType
::
DYNAMIC
);
auto
degree
=
conditionalValue
<
useDynamicTraversal
>
(
Tree
::
degree
(),
Dune
::
index_constant
<
Tree
::
degree
()
>
{});
auto
indices
=
Dune
::
range
(
degree
);
Dune
::
Hybrid
::
forEach
(
indices
,
[
&
](
auto
i
)
{
auto
childTP
=
Dune
::
TypeTree
::
push_back
(
treePath
,
i
);
auto
&&
child
=
tree
.
child
(
i
);
using
Child
=
TYPEOF
(
child
);
visitor
.
beforeChild
(
tree
,
child
,
treePath
,
i
);
// This requires that visiotor.in(...) can always be instantiated,
// even if there's a single child only.
if
(
i
>
0
)
visitor
.
in
(
tree
,
treePath
);
static
constexpr
auto
visitChild
=
Visitor
::
template
VisitChild
<
Tree
,
Child
,
TP
>
::
value
;
#if AMDIS_HAS_CXX_CONSTEXPR_IF
if
constexpr
(
visitChild
)
applyToTree
(
child
,
childTP
,
visitor
);
#else // AMDIS_HAS_CXX_CONSTEXPR_IF
Dune
::
Hybrid
::
ifElse
(
bool_t
<
visitChild
>
{},
[
&
]
(
auto
/*id*/
)
{
applyToTree
(
child
,
childTP
,
visitor
);
});
#endif // AMDIS_HAS_CXX_CONSTEXPR_IF
visitor
.
afterChild
(
tree
,
child
,
treePath
,
i
);
});
visitor
.
post
(
tree
,
treePath
);
}
// Overload for leaf nodes
template
<
class
Tree
,
class
TP
,
class
Pre
,
class
Leaf
,
class
Post
,
std
::
enable_if_t
<
remove_cvref_t
<
Tree
>
::
isLeaf
,
int
>
=
0
>
void
for_each_node
(
Tree
&&
tree
,
TP
treePath
,
Pre
&&
/*preFunc*/
,
Leaf
&&
leafFunc
,
Post
&&
/*postFunc*/
)
{
leafFunc
(
tree
,
treePath
);
}
// Overload for non-leaf nodes
// Forward declaration needed for recursion
template
<
class
Tree
,
class
TP
,
class
Pre
,
class
Leaf
,
class
Post
,
std
::
enable_if_t
<
not
remove_cvref_t
<
Tree
>
::
isLeaf
,
int
>
=
0
>
void
for_each_node
(
Tree
&&
tree
,
TP
treePath
,
Pre
&&
preFunc
,
Leaf
&&
leafFunc
,
Post
&&
postFunc
);
// Helper for power nodes
template
<
class
Tree
,
class
TP
,
class
Pre
,
class
Leaf
,
class
Post
,
std
::
size_t
...
I
,
std
::
enable_if_t
<
remove_cvref_t
<
Tree
>
::
isPower
,
int
>
=
0
>
void
for_each_node_unfold
(
Tree
&&
tree
,
TP
treePath
,
Pre
&&
preFunc
,
Leaf
&&
leafFunc
,
Post
&&
postFunc
,
std
::
index_sequence
<
I
...
>
)
{
for
(
std
::
size_t
i
=
0
;
i
<
sizeof
...(
I
);
++
i
)
Impl
::
for_each_node
(
tree
.
child
(
i
),
Dune
::
TypeTree
::
push_back
(
treePath
,
i
),
preFunc
,
leafFunc
,
postFunc
);
}
v
.
pre
(
FWD
(
n
),
tp
);
// Helper for composite nodes
template
<
class
Tree
,
class
TP
,
class
Pre
,
class
Leaf
,
class
Post
,
std
::
size_t
...
I
,
std
::
enable_if_t
<
not
remove_cvref_t
<
Tree
>
::
isPower
,
int
>
=
0
>
void
for_each_node_unfold
(
Tree
&&
tree
,
TP
treePath
,
Pre
&&
preFunc
,
Leaf
&&
leafFunc
,
Post
&&
postFunc
,
std
::
index_sequence
<
I
...
>
)
{
(
void
)
std
::
initializer_list
<
int
>
{(
Impl
::
for_each_node
(
tree
.
child
(
Dune
::
index_constant
<
I
>
{}),
Dune
::
TypeTree
::
push_back
(
treePath
,
Dune
::
index_constant
<
I
>
{}),
preFunc
,
leafFunc
,
postFunc
),
0
)...
};
}
auto
const
deg
=
hybridDegree
(
NodeTag
{},
n
);
Dune
::
Hybrid
::
forEach
(
Dune
::
range
(
deg
),
[
&
](
auto
const
_k
)
/*
* Traverse tree and visit each node. The signature is the same
* as for the public for_each_node function in Dune::Typtree,
* despite the additionally passed treePath argument. The path
* passed here is associated to the tree and the relative
* paths of the children (wrt. to tree) are appended to this.
* Hence the behavior of the public function is resembled
* by passing an empty treePath.
*
* See also the specialization for leaf-nodes.
*/
template
<
class
Tree
,
class
TP
,
class
Pre
,
class
Leaf
,
class
Post
,
std
::
enable_if_t
<
not
remove_cvref_t
<
Tree
>
::
isLeaf
,
int
>>
void
for_each_node
(
Tree
&&
tree
,
TP
treePath
,
Pre
&&
preFunc
,
Leaf
&&
leafFunc
,
Post
&&
postFunc
)
{
// always call beforeChild(), regardless of the value of visit
v
.
beforeChild
(
FWD
(
n
),
n
.
child
(
_k
),
tp
,
_k
);
auto
indices
=
std
::
make_index_sequence
<
TYPEOF
(
tree
)
::
degree
()
>
{};
preFunc
(
tree
,
treePath
);
Impl
::
for_each_node_unfold
(
tree
,
treePath
,
preFunc
,
leafFunc
,
postFunc
,
indices
);
postFunc
(
tree
,
treePath
);
}
}
// namespace Impl
// ********************************************************************************
// Public Interface
// ********************************************************************************
// descend to child
using
C
=
typename
HybridChildType
<
Node
,
decltype
(
_k
)
>::
type
;
const
bool
visit
=
Visitor
::
template
VisitChild
<
Node
,
C
,
TreePath
>
::
value
;
TraverseTree
<
Dune
::
TypeTree
::
NodeTag
<
C
>
,
visit
>::
apply
(
n
.
child
(
_k
),
FWD
(
v
),
push_back
(
tp
,
_k
));
//! Apply visitor to TypeTree.
/**
* \code
* #include <amdis/typetree/Traversal.hpp>
* \endcode
* This function applies the given visitor to the given tree. Both visitor and tree may be const
* or non-const (if the compiler supports rvalue references, they may even be a non-const temporary).
*
* \note The visitor must implement the interface laid out by DefaultVisitor (most easily achieved by
* inheriting from it) and specify the required type of tree traversal (static or dynamic) by