Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dune-gfe
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
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
Sander, Oliver
dune-gfe
Commits
badc23be
Commit
badc23be
authored
3 years ago
by
Müller, Alexander
Browse files
Options
Downloads
Patches
Plain Diff
added ProductManifold class
parent
a2647f48
No related branches found
No related tags found
1 merge request
!70
added ProductManifold<...>
Pipeline
#6331
passed
3 years ago
Stage: test
Changes
1
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
dune/gfe/productmanifold.hh
+503
-0
503 additions, 0 deletions
dune/gfe/productmanifold.hh
with
503 additions
and
0 deletions
dune/gfe/productmanifold.hh
0 → 100644
+
503
−
0
View file @
badc23be
#ifndef DUNE_GFE_PRODUCTMANIFOLD_HH
#define DUNE_GFE_PRODUCTMANIFOLD_HH
#include
<iostream>
#include
<tuple>
#include
<dune/common/fvector.hh>
#include
<dune/common/math.hh>
#include
<dune/common/hybridutilities.hh>
#include
<dune/common/tuplevector.hh>
#include
<dune/common/power.hh>
#include
<dune/gfe/linearalgebra.hh>
namespace
Dune
::
GFE
{
namespace
Impl
{
template
<
typename
T
,
typename
...
Ts
>
constexpr
auto
sumDim
()
{
return
(
T
::
dim
+
...
+
sumDim
<
Ts
>
());
}
template
<
typename
T
,
typename
...
Ts
>
constexpr
auto
sumEmbeddedDim
()
{
return
(
T
::
embeddedDim
+
...
+
sumEmbeddedDim
<
Ts
>
());
}
template
<
typename
T
,
typename
...
Ts
>
constexpr
auto
variadicConvexityRadiusMin
()
{
if
constexpr
(
sizeof
...(
Ts
)
!=
0
)
return
std
::
min
(
T
::
convexityRadius
,
variadicConvexityRadiusMin
<
Ts
...
>
());
else
return
T
::
convexityRadius
;
}
template
<
typename
TS
,
typename
...
TargetSpaces
>
class
ProductManifold
;
template
<
class
U
,
typename
Tfirst
,
typename
...
TargetSpaces2
>
struct
rebindHelper
{
typedef
ProductManifold
<
typename
Tfirst
::
template
rebind
<
U
>
::
other
,
typename
rebindHelper
<
U
,
TargetSpaces2
...
>::
other
>
other
;
};
template
<
class
U
,
typename
Tlast
>
struct
rebindHelper
<
U
,
Tlast
>
{
typedef
typename
Tlast
::
template
rebind
<
U
>
::
other
other
;
};
}
/** \brief A Product manifold */
template
<
typename
TS
,
typename
...
TargetSpaces
>
class
ProductManifold
{
public:
template
<
std
::
size_t
I
>
using
IC
=
Dune
::
index_constant
<
I
>
;
/** \brief The type used for coordinates. */
using
ctype
=
typename
std
::
common_type
<
typename
TS
::
ctype
,
typename
TargetSpaces
::
ctype
...
>::
type
;
using
field_type
=
typename
std
::
common_type
<
typename
TS
::
ctype
,
typename
TargetSpaces
::
ctype
...
>::
type
;
/** \brief Number of factors */
static
constexpr
int
numTS
=
1
+
sizeof
...(
TargetSpaces
);
/** \brief Dimension of manifold */
static
constexpr
int
dim
=
TS
::
dim
+
Impl
::
sumDim
<
TargetSpaces
...
>
();
/** \brief Dimension of the embedding space */
static
constexpr
int
embeddedDim
=
TS
::
embeddedDim
+
Impl
::
sumEmbeddedDim
<
TargetSpaces
...
>
();
/** \brief Type of a tangent of the ProductManifold with inner dimensions*/
typedef
Dune
::
FieldVector
<
field_type
,
dim
>
TangentVector
;
/** \brief Type of a tangent of the ProductManifold represented in the embedding space*/
typedef
Dune
::
FieldVector
<
field_type
,
embeddedDim
>
EmbeddedTangentVector
;
/** \brief The global convexity radius of the Product space */
static
constexpr
double
convexityRadius
=
Impl
::
variadicConvexityRadiusMin
<
TS
,
TargetSpaces
...
>
();
/** \brief The type used for global coordinates */
typedef
Dune
::
FieldVector
<
field_type
,
embeddedDim
>
CoordinateType
;
/** \brief Default constructor */
ProductManifold
()
=
default
;
/** \brief Constructor from another ProductManifold */
ProductManifold
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
productManifold
)
:
data_
(
productManifold
.
data_
)
{}
/** \brief Constructor from a coordinates vector of the embedding space */
explicit
ProductManifold
(
const
CoordinateType
&
globalCoordinates
)
{
DUNE_ASSERT_BOUNDS
(
globalCoordinates
.
size
()
==
sumEmbeddedDim
)
auto
constructorFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
globalCoords
=
std
::
get
<
1
>
(
argsTuple
);
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
res
)
>
>
;
res
=
Manifold
(
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
globalCoords
,
posHelper
[
0
]));
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
constructorFunctor
,
*
this
,
globalCoordinates
);
}
/** \brief Assignment from a coordinates vector of the embedding space */
ProductManifold
<
TS
,
TargetSpaces
...
>&
operator
=
(
const
CoordinateType
&
globalCoordinates
)
{
ProductManifold
<
TS
,
TargetSpaces
...
>
res
(
globalCoordinates
);
data_
=
res
.
data_
;
return
*
this
;
}
/** \brief Assignment from ProductManifold with different type -- used for automatic differentiation with ADOL-C */
template
<
typename
TS2
,
typename
...
TargetSpaces2
>
ProductManifold
<
TS
,
TargetSpaces
...
>&
operator
<<=
(
const
ProductManifold
<
TS2
,
TargetSpaces2
...
>&
other
)
{
forEach
(
integralRange
(
IC
<
numTS
>
()),
[
&
](
auto
&&
i
)
{
(
*
this
)[
i
]
<<=
other
[
i
];
});
return
*
this
;
}
/** \brief Rebind the ProductManifold to another coordinate type using an embedded tangent vector*/
template
<
class
U
,
typename
...
TargetSpaces2
>
struct
rebind
{
typedef
typename
Impl
::
rebindHelper
<
U
,
TS
,
TargetSpaces
...
>::
other
other
;
};
/** \brief The exponential map from a given point. */
static
ProductManifold
<
TS
,
TargetSpaces
...
>
exp
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
p
,
const
EmbeddedTangentVector
&
v
)
{
ProductManifold
<
TS
,
TargetSpaces
...
>
res
;
auto
expFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
p
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
tang
=
std
::
get
<
2
>
(
argsTuple
);
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
res
)
>
>
;
auto
currentEmbeddedTangentVector
=
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
tang
,
posHelper
[
0
]);
res
=
Manifold
::
exp
(
p
,
currentEmbeddedTangentVector
);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
expFunctor
,
res
,
p
,
v
);
return
res
;
}
/** \brief The exponential map from a given point using an intrinsic tangent vector*/
static
ProductManifold
<
TS
,
TargetSpaces
...
>
exp
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
p
,
const
TangentVector
&
v
)
{
auto
basis
=
p
.
orthonormalFrame
();
EmbeddedTangentVector
embeddedTangent
;
basis
.
mtv
(
v
,
embeddedTangent
);
return
exp
(
p
,
embeddedTangent
);
}
/** \brief Compute difference vector from a to b on the tangent space of a */
static
TangentVector
log
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
TangentVector
diff
;
auto
logFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
diffLoc
=
Manifold
::
log
(
a
,
b
);
std
::
copy
(
diffLoc
.
begin
(),
diffLoc
.
end
(),
res
.
begin
()
+
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
dim
;
};
foreachManifold
(
logFunctor
,
diff
,
a
,
b
);
return
diff
;
}
/** \brief Compute geodesic distance from a to b */
static
field_type
distance
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
field_type
dist
=
0.0
;
auto
distanceFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
res
+=
Dune
::
Power
<
2
>
().
eval
(
Manifold
::
distance
(
a
,
b
));
};
foreachManifold
(
distanceFunctor
,
dist
,
a
,
b
);
return
sqrt
(
dist
);
}
/** \brief Compute the gradient of the squared distance function keeping the first argument fixed */
static
EmbeddedTangentVector
derivativeOfDistanceSquaredWRTSecondArgument
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
EmbeddedTangentVector
derivative
;
derivative
=
0.0
;
auto
derivOfDistSqdWRTSecArgFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
derivative
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
diffLoc
=
Manifold
::
derivativeOfDistanceSquaredWRTSecondArgument
(
a
,
b
);
std
::
copy
(
diffLoc
.
begin
(),
diffLoc
.
end
(),
derivative
.
begin
()
+
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
derivOfDistSqdWRTSecArgFunctor
,
derivative
,
a
,
b
);
return
derivative
;
}
/** \brief Compute the Hessian of the squared distance function keeping the first argument fixed */
static
auto
secondDerivativeOfDistanceSquaredWRTSecondArgument
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
Dune
::
SymmetricMatrix
<
field_type
,
embeddedDim
>
result
;
auto
secDerivOfDistSqWRTSecArgFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
deriv
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
diffLoc
=
Manifold
::
secondDerivativeOfDistanceSquaredWRTSecondArgument
(
a
,
b
);
for
(
size_t
i
=
posHelper
[
0
];
i
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
i
)
for
(
size_t
j
=
posHelper
[
0
];
j
<=
i
;
++
j
)
deriv
(
i
,
j
)
=
diffLoc
(
i
-
posHelper
[
0
],
j
-
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
secDerivOfDistSqWRTSecArgFunctor
,
result
,
a
,
b
);
return
result
;
}
/** \brief Compute the mixed second derivate \partial d^2 / \partial da db */
static
Dune
::
FieldMatrix
<
field_type
,
embeddedDim
,
embeddedDim
>
secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
Dune
::
FieldMatrix
<
field_type
,
embeddedDim
,
embeddedDim
>
result
(
0
);
auto
secDerivOfDistSqWRTFirstAndSecArgFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
deriv
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
diffLoc
=
Manifold
::
secondDerivativeOfDistanceSquaredWRTFirstAndSecondArgument
(
a
,
b
);
for
(
size_t
i
=
posHelper
[
0
];
i
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
i
)
for
(
size_t
j
=
posHelper
[
0
];
j
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
j
)
deriv
[
i
][
j
]
=
diffLoc
[
i
-
posHelper
[
0
]][
j
-
posHelper
[
0
]];
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
secDerivOfDistSqWRTFirstAndSecArgFunctor
,
result
,
a
,
b
);
return
result
;
}
/** \brief Compute the third derivative \partial d^3 / \partial dq^3 */
static
Tensor3
<
field_type
,
embeddedDim
,
embeddedDim
,
embeddedDim
>
thirdDerivativeOfDistanceSquaredWRTSecondArgument
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
Tensor3
<
field_type
,
embeddedDim
,
embeddedDim
,
embeddedDim
>
result
(
0
);
auto
thirdDerivOfDistSqWRTSecArgFunctor
=
[](
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
deriv
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>>
;
const
auto
diffLoc
=
Manifold
::
thirdDerivativeOfDistanceSquaredWRTSecondArgument
(
a
,
b
);
for
(
size_t
i
=
posHelper
[
0
];
i
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
i
)
for
(
size_t
j
=
posHelper
[
0
];
j
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
j
)
for
(
size_t
k
=
posHelper
[
0
];
k
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
k
)
deriv
[
i
][
j
][
k
]
=
diffLoc
[
i
-
posHelper
[
0
]][
j
-
posHelper
[
0
]][
k
-
posHelper
[
0
]];
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
thirdDerivOfDistSqWRTSecArgFunctor
,
result
,
a
,
b
);
return
result
;
}
/** \brief Compute the mixed third derivative \partial d^3 / \partial da db^2 */
static
Tensor3
<
field_type
,
embeddedDim
,
embeddedDim
,
embeddedDim
>
thirdDerivativeOfDistanceSquaredWRTFirst1AndSecond2Argument
(
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
a
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
b
)
{
Tensor3
<
field_type
,
embeddedDim
,
embeddedDim
,
embeddedDim
>
result
(
0
);
auto
thirdDerivOfDistSqWRT1And2ArgFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
deriv
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
b
=
std
::
get
<
2
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>>
;
const
auto
diffLoc
=
Manifold
::
thirdDerivativeOfDistanceSquaredWRTFirst1AndSecond2Argument
(
a
,
b
);
for
(
size_t
i
=
posHelper
[
0
];
i
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
i
)
for
(
size_t
j
=
posHelper
[
0
];
j
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
j
)
for
(
size_t
k
=
posHelper
[
0
];
k
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
k
)
deriv
[
i
][
j
][
k
]
=
diffLoc
[
i
-
posHelper
[
0
]][
j
-
posHelper
[
0
]][
k
-
posHelper
[
0
]];
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
thirdDerivOfDistSqWRT1And2ArgFunctor
,
result
,
a
,
b
);
return
result
;
}
/** \brief Project tangent vector of R^n onto the tangent space */
EmbeddedTangentVector
projectOntoTangentSpace
(
const
EmbeddedTangentVector
&
v
)
const
{
EmbeddedTangentVector
result
{
v
};
auto
projectOntoTangentSpaceFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
v
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
vLoc
=
a
.
projectOntoTangentSpace
(
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
v
,
posHelper
[
0
]));
std
::
copy
(
vLoc
.
begin
(),
vLoc
.
end
(),
v
.
begin
()
+
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
projectOntoTangentSpaceFunctor
,
result
,
*
this
);
return
result
;
}
/** \brief Project tangent vector of R^n onto the normal space space */
EmbeddedTangentVector
projectOntoNormalSpace
(
const
EmbeddedTangentVector
&
v
)
const
{
EmbeddedTangentVector
result
{
v
};
auto
projectOntoNormalSpaceFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
v
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
vLoc
=
a
.
projectOntoNormalSpace
(
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
v
,
posHelper
[
0
]));
std
::
copy
(
vLoc
.
begin
(),
vLoc
.
end
(),
v
.
begin
()
+
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
projectOntoNormalSpaceFunctor
,
result
,
*
this
);
return
result
;
}
/** \brief Project tangent vector of R^n onto the normal space space */
static
ProductManifold
<
TS
,
TargetSpaces
...
>
projectOnto
(
const
CoordinateType
&
v
)
{
ProductManifold
<
TS
,
TargetSpaces
...
>
result
{
v
};
auto
projectOntoFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
)[
manifoldInt
];
auto
&
v
=
std
::
get
<
1
>
(
argsTuple
);
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
res
)
>
>
;
res
=
Manifold
::
projectOnto
(
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
v
,
posHelper
[
0
]));
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
projectOntoFunctor
,
result
,
v
);
return
result
;
}
/** \brief Project tangent vector of R^n onto the normal space space */
static
auto
derivativeOfProjection
(
const
CoordinateType
&
v
)
{
Dune
::
FieldMatrix
<
typename
CoordinateType
::
value_type
,
embeddedDim
,
embeddedDim
>
result
;
auto
derivativeOfProjectionFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
v
=
std
::
get
<
1
>
(
argsTuple
);
const
Dune
::
TupleVector
<
TS
,
TargetSpaces
...
>
ManifoldTuple
;
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
ManifoldTuple
[
manifoldInt
])
>
>
;
const
auto
vLoc
=
Manifold
::
derivativeOfProjection
(
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
v
,
posHelper
[
0
]));
for
(
size_t
k
=
posHelper
[
0
];
k
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
k
)
for
(
size_t
j
=
posHelper
[
0
];
j
<
posHelper
[
0
]
+
Manifold
::
embeddedDim
;
++
j
)
res
[
k
][
j
]
=
vLoc
[
k
-
posHelper
[
0
]][
j
-
posHelper
[
0
]];
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
derivativeOfProjectionFunctor
,
result
,
v
);
return
result
;
}
/** \brief The Weingarten map */
EmbeddedTangentVector
weingarten
(
const
EmbeddedTangentVector
&
z
,
const
EmbeddedTangentVector
&
v
)
const
{
EmbeddedTangentVector
result
;
auto
weingartenFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
const
auto
&
z
=
std
::
get
<
2
>
(
argsTuple
);
const
auto
&
v
=
std
::
get
<
3
>
(
argsTuple
);
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
resLoc
=
a
.
weingarten
(
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
z
,
posHelper
[
0
]),
Dune
::
GFE
::
segmentAt
<
Manifold
::
embeddedDim
>
(
v
,
posHelper
[
0
]));
std
::
copy
(
resLoc
.
begin
(),
resLoc
.
end
(),
res
.
begin
()
+
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
weingartenFunctor
,
result
,
*
this
,
z
,
v
);
return
result
;
}
/** \brief Compute an orthonormal basis of the tangent space of the ProductManifold
This basis may not be globally continuous. */
Dune
::
FieldMatrix
<
field_type
,
dim
,
embeddedDim
>
orthonormalFrame
()
const
{
Dune
::
FieldMatrix
<
field_type
,
dim
,
embeddedDim
>
result
(
0
);
auto
orthonormalFrameFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
manifoldInt
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
a
=
std
::
get
<
1
>
(
argsTuple
)[
manifoldInt
];
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
a
)
>
>
;
const
auto
resLoc
=
a
.
orthonormalFrame
();
for
(
size_t
i
=
posHelper
[
0
];
i
<
posHelper
[
0
]
+
Manifold
::
dim
;
++
i
)
for
(
size_t
j
=
posHelper
[
1
];
j
<
posHelper
[
1
]
+
Manifold
::
embeddedDim
;
++
j
)
res
[
i
][
j
]
=
resLoc
[
i
-
posHelper
[
0
]][
j
-
posHelper
[
1
]];
posHelper
[
0
]
+=
Manifold
::
dim
;
posHelper
[
1
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
orthonormalFrameFunctor
,
result
,
*
this
);
return
result
;
}
/** \brief The global coordinates */
CoordinateType
globalCoordinates
()
const
{
CoordinateType
returnValue
;
auto
globalCoordinatesFunctor
=
[]
(
auto
&
argsTuple
,
std
::
array
<
std
::
size_t
,
2
>&
posHelper
,
const
auto
&
i
)
{
auto
&
res
=
std
::
get
<
0
>
(
argsTuple
);
const
auto
&
p
=
std
::
get
<
1
>
(
argsTuple
)[
i
];
const
auto
vLoc
=
p
.
globalCoordinates
();
using
Manifold
=
std
::
remove_const_t
<
typename
std
::
remove_reference_t
<
decltype
(
p
)
>
>
;
std
::
copy
(
vLoc
.
begin
(),
vLoc
.
end
(),
res
.
begin
()
+
posHelper
[
0
]);
posHelper
[
0
]
+=
Manifold
::
embeddedDim
;
};
foreachManifold
(
globalCoordinatesFunctor
,
returnValue
,
*
this
);
return
returnValue
;
}
/** \brief Const access to the tuple elements */
template
<
std
::
size_t
i
>
constexpr
decltype
(
auto
)
operator
[]
(
const
Dune
::
index_constant
<
i
>&
)
const
{
return
std
::
get
<
i
>
(
data_
);
}
/** \brief Non-const access to the tuple elements */
template
<
std
::
size_t
i
>
decltype
(
auto
)
operator
[]
(
const
Dune
::
index_constant
<
i
>&
)
{
return
std
::
get
<
i
>
(
data_
);
}
/** \brief Number of elements of the tuple */
static
constexpr
std
::
size_t
size
()
{
return
numTS
;
}
template
<
class
TS2
,
class
...
TargetSpaces2
>
friend
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
ProductManifold
<
TS2
,
TargetSpaces2
...
>&
c
);
private
:
/**
* \brief Range based for loop over all Manifolds in ProductManifold
*
* \tparam FunctorType the functor which should be applied for all manifolds
* \tparam Args... The arguments which are passed to the functor
*
* The functor has to extract the current manifold from its arguments.
* Therefore, the current index i is passed to the functor.
*
* Furthermore, the functor gets two integers to deal with FieldVectors
* or FieldMatrices which span the whole (embedding) coordinate range of the ProductManifold.
*
* Example:
* If a argument of the functor is
* ProductManifold<Realtuple<double,3>,UnitVector<double,3>>::EmbeddedTangentVector,
* the embedded coordinate vector has 6 entries. The functor needs to know where
* to insert the next subvector of the submanifold. Therefore, posHelper[0] should be 0 at the first
* iteration and 3 at the second one. Then first indices [0..2] stores the result of
* Realtuple<double,3> and [3..5] stores
* the result of UnitVector<double,3>.
* See e.g. the globalCoordinates() function
*/
template
<
typename
FunctorType
,
typename
...
Args
>
static
void
foreachManifold
(
FunctorType
&&
functor
,
Args
&&
...
args
)
{
auto
argsTuple
=
std
::
forward_as_tuple
(
args
...);
std
::
array
<
std
::
size_t
,
2
>
posHelper
({
0
,
0
});
Dune
::
Hybrid
::
forEach
(
Dune
::
Hybrid
::
integralRange
(
IC
<
numTS
>
()),[
&
](
auto
&&
i
)
{
functor
(
argsTuple
,
posHelper
,
i
);
});
}
std
::
tuple
<
TS
,
TargetSpaces
...
>
data_
;
};
template
<
typename
TS
,
typename
...
TargetSpaces
>
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
ProductManifold
<
TS
,
TargetSpaces
...
>&
c
)
{
Dune
::
Hybrid
::
forEach
(
Dune
::
Hybrid
::
integralRange
(
Dune
::
index_constant
<
ProductManifold
<
TS
,
TargetSpaces
...
>::
numTS
>
()),
[
&
](
auto
&&
i
)
{
s
<<
Dune
::
className
<
decltype
(
c
[
i
])
>
()
<<
" "
<<
c
[
i
]
<<
"
\n
"
;
});
return
s
;
}
}
#endif
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