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
a10a415b
Commit
a10a415b
authored
5 years ago
by
Timo Koch
Browse files
Options
Downloads
Patches
Plain Diff
[common] Add function to integrate FV-style solutions
parent
92fc1411
No related branches found
No related tags found
1 merge request
!1636
Feature/l2 norm
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
dumux/common/integrate.hh
+115
-5
115 additions, 5 deletions
dumux/common/integrate.hh
test/common/functions/test_function_l2norm.cc
+37
-16
37 additions, 16 deletions
test/common/functions/test_function_l2norm.cc
with
152 additions
and
21 deletions
dumux/common/integrate.hh
+
115
−
5
View file @
a10a415b
...
@@ -28,17 +28,117 @@
...
@@ -28,17 +28,117 @@
#include
<type_traits>
#include
<type_traits>
#include
<dune/geometry/quadraturerules.hh>
#include
<dune/geometry/quadraturerules.hh>
#include
<dune/common/concept.hh>
#if HAVE_DUNE_FUNCTIONS
#include
<dune/functions/gridfunctions/gridfunction.hh>
#endif
#include
<dumux/discretization/evalsolution.hh>
#include
<dumux/discretization/elementsolution.hh>
namespace
Dumux
{
namespace
Dumux
{
namespace
Impl
{
struct
HasLocalFunction
{
template
<
class
F
>
auto
require
(
F
&&
f
)
->
decltype
(
localFunction
(
f
),
localFunction
(
f
).
unbind
()
);
};
template
<
class
F
>
static
constexpr
bool
hasLocalFunction
()
{
return
Dune
::
models
<
HasLocalFunction
,
F
>
();
}
}
// end namespace Impl
/*!
* \brief Integrate a grid function over a grid view
* \param gv the grid view
* \param f the grid function
* \param order the order of the quadrature rule
*/
template
<
class
GridGeometry
,
class
SolutionVector
,
typename
std
::
enable_if_t
<!
Impl
::
hasLocalFunction
<
SolutionVector
>(),
int
>
=
0
>
auto
integrateGridFunction
(
const
GridGeometry
&
gg
,
SolutionVector
&&
sol
,
std
::
size_t
order
)
{
using
Scalar
=
std
::
decay_t
<
decltype
(
sol
[
0
][
0
])
>
;
using
GridView
=
typename
GridGeometry
::
GridView
;
Scalar
integral
=
0.0
;
for
(
const
auto
&
element
:
elements
(
gg
.
gridView
()))
{
const
auto
elemSol
=
elementSolution
(
element
,
sol
,
gg
);
const
auto
geometry
=
element
.
geometry
();
const
auto
&
quad
=
Dune
::
QuadratureRules
<
Scalar
,
GridView
::
dimension
>::
rule
(
geometry
.
type
(),
order
);
for
(
auto
&&
qp
:
quad
)
{
auto
value
=
evalSolution
(
element
,
geometry
,
gg
,
elemSol
,
geometry
.
global
(
qp
.
position
()));
value
*=
qp
.
weight
()
*
geometry
.
integrationElement
(
qp
.
position
());
integral
+=
value
;
}
}
return
integral
;
}
/*!
* \brief Integrate a function over a grid view
* \param gv the grid view
* \param f the first function
* \param g the second function
* \param order the order of the quadrature rule
* \note dune functions currently doesn't support composing two functions
*/
template
<
class
GridGeometry
,
class
Sol1
,
class
Sol2
,
typename
std
::
enable_if_t
<!
Impl
::
hasLocalFunction
<
Sol1
>(),
int
>
=
0
>
auto
integrateL2Error
(
const
GridGeometry
&
gg
,
const
Sol1
&
sol1
,
const
Sol2
&
sol2
,
std
::
size_t
order
)
{
using
Scalar
=
std
::
decay_t
<
decltype
(
sol1
[
0
][
0
])
>
;
using
GridView
=
typename
GridGeometry
::
GridView
;
Scalar
l2norm
=
0.0
;
for
(
const
auto
&
element
:
elements
(
gg
.
gridView
()))
{
const
auto
elemSol1
=
elementSolution
(
element
,
sol1
,
gg
);
const
auto
elemSol2
=
elementSolution
(
element
,
sol2
,
gg
);
const
auto
geometry
=
element
.
geometry
();
const
auto
&
quad
=
Dune
::
QuadratureRules
<
Scalar
,
GridView
::
dimension
>::
rule
(
geometry
.
type
(),
order
);
for
(
auto
&&
qp
:
quad
)
{
const
auto
&
globalPos
=
geometry
.
global
(
qp
.
position
());
const
auto
value1
=
evalSolution
(
element
,
geometry
,
gg
,
elemSol1
,
globalPos
);
const
auto
value2
=
evalSolution
(
element
,
geometry
,
gg
,
elemSol2
,
globalPos
);
const
auto
error
=
(
value1
-
value2
);
l2norm
+=
error
*
error
*
qp
.
weight
()
*
geometry
.
integrationElement
(
qp
.
position
());
}
}
using
std
::
sqrt
;
return
sqrt
(
l2norm
);
}
#if HAVE_DUNE_FUNCTIONS
/*!
/*!
* \brief Integrate a grid function over a grid view
* \brief Integrate a grid function over a grid view
* \param gv the grid view
* \param gv the grid view
* \param f the grid function
* \param f the grid function
* \param order the order of the quadrature rule
* \param order the order of the quadrature rule
* \note overload for a Dune::Funtions::GridFunction
*/
*/
template
<
class
GridView
,
class
F
>
template
<
class
GridView
,
class
F
,
auto
integrateGridFunction
(
const
GridView
&
gv
,
F
&&
f
,
std
::
size_t
order
)
typename
std
::
enable_if_t
<
Impl
::
hasLocalFunction
<
F
>(),
int
>
=
0
>
auto
integrateGridFunction
(
const
GridView
&
gv
,
F
&&
f
,
std
::
size_t
order
)
{
{
auto
fLocal
=
localFunction
(
f
);
auto
fLocal
=
localFunction
(
f
);
...
@@ -54,7 +154,11 @@ auto integrateGridFunction(const GridView& gv, F&& f, std::size_t order)
...
@@ -54,7 +154,11 @@ auto integrateGridFunction(const GridView& gv, F&& f, std::size_t order)
const
auto
geometry
=
element
.
geometry
();
const
auto
geometry
=
element
.
geometry
();
const
auto
&
quad
=
Dune
::
QuadratureRules
<
Scalar
,
GridView
::
dimension
>::
rule
(
geometry
.
type
(),
order
);
const
auto
&
quad
=
Dune
::
QuadratureRules
<
Scalar
,
GridView
::
dimension
>::
rule
(
geometry
.
type
(),
order
);
for
(
auto
&&
qp
:
quad
)
for
(
auto
&&
qp
:
quad
)
integral
+=
fLocal
(
qp
.
position
())
*
qp
.
weight
()
*
geometry
.
integrationElement
(
qp
.
position
());
{
auto
value
=
fLocal
(
qp
.
position
());
value
*=
qp
.
weight
()
*
geometry
.
integrationElement
(
qp
.
position
());
integral
+=
value
;
}
fLocal
.
unbind
();
fLocal
.
unbind
();
}
}
...
@@ -67,10 +171,15 @@ auto integrateGridFunction(const GridView& gv, F&& f, std::size_t order)
...
@@ -67,10 +171,15 @@ auto integrateGridFunction(const GridView& gv, F&& f, std::size_t order)
* \param f the first function
* \param f the first function
* \param g the second function
* \param g the second function
* \param order the order of the quadrature rule
* \param order the order of the quadrature rule
* \note overload for a Dune::Funtions::GridFunction
* \note dune functions currently doesn't support composing two functions
* \note dune functions currently doesn't support composing two functions
*/
*/
template
<
class
GridView
,
class
F
,
class
G
>
template
<
class
GridView
,
class
F
,
class
G
,
auto
integrateL2Error
(
const
GridView
&
gv
,
F
&&
f
,
G
&&
g
,
std
::
size_t
order
)
typename
std
::
enable_if_t
<
Impl
::
hasLocalFunction
<
F
>(),
int
>
=
0
>
auto
integrateL2Error
(
const
GridView
&
gv
,
F
&&
f
,
G
&&
g
,
std
::
size_t
order
)
{
{
auto
fLocal
=
localFunction
(
f
);
auto
fLocal
=
localFunction
(
f
);
auto
gLocal
=
localFunction
(
g
);
auto
gLocal
=
localFunction
(
g
);
...
@@ -102,6 +211,7 @@ auto integrateL2Error(const GridView& gv, F&& f, G&& g, std::size_t order)
...
@@ -102,6 +211,7 @@ auto integrateL2Error(const GridView& gv, F&& f, G&& g, std::size_t order)
using
std
::
sqrt
;
using
std
::
sqrt
;
return
sqrt
(
l2norm
);
return
sqrt
(
l2norm
);
}
}
#endif
}
// end namespace Dumux
}
// end namespace Dumux
...
...
This diff is collapsed.
Click to expand it.
test/common/functions/test_function_l2norm.cc
+
37
−
16
View file @
a10a415b
...
@@ -12,7 +12,8 @@
...
@@ -12,7 +12,8 @@
#include
<dumux/common/integrate.hh>
#include
<dumux/common/integrate.hh>
#include
<dumux/multidomain/glue.hh>
#include
<dumux/multidomain/glue.hh>
#include
<dumux/discretization/projection/projector.hh>
#include
<dumux/discretization/projection/projector.hh>
#include
<dumux/discretization/fem/fegridgeometry.hh>
#include
<dumux/discretization/basegridgeometry.hh>
#include
<dumux/discretization/box/fvgridgeometry.hh>
#include
<dumux/io/grid/gridmanager_yasp.hh>
#include
<dumux/io/grid/gridmanager_yasp.hh>
int
main
(
int
argc
,
char
*
argv
[])
try
int
main
(
int
argc
,
char
*
argv
[])
try
...
@@ -35,38 +36,58 @@ int main (int argc, char *argv[]) try
...
@@ -35,38 +36,58 @@ int main (int argc, char *argv[]) try
const
auto
gvFine
=
gridManagerFine
.
grid
().
leafGridView
();
const
auto
gvFine
=
gridManagerFine
.
grid
().
leafGridView
();
const
auto
gvCoarse
=
gridManagerCoarse
.
grid
().
leafGridView
();
const
auto
gvCoarse
=
gridManagerCoarse
.
grid
().
leafGridView
();
// a quadratic function on the grid
// get some types
auto
f
=
[](
const
auto
&
pos
){
return
pos
.
two_norm2
();
};
// make discrete functions
using
R
=
Dune
::
FieldVector
<
double
,
1
>
;
using
R
=
Dune
::
FieldVector
<
double
,
1
>
;
using
SolutionVector
=
Dune
::
BlockVector
<
R
>
;
using
SolutionVector
=
Dune
::
BlockVector
<
R
>
;
using
GridView
=
Grid
::
LeafGridView
;
using
GridView
=
Grid
::
LeafGridView
;
using
namespace
Dune
::
Functions
;
using
namespace
Dune
::
Functions
;
using
P2
=
LagrangeBasis
<
GridView
,
2
>
;
using
P2
=
LagrangeBasis
<
GridView
,
2
>
;
auto
basisCoarse
=
std
::
make_shared
<
P2
>
(
gvCoarse
),
basisFine
=
std
::
make_shared
<
P2
>
(
gvFine
);
// construct glue, any grid geometry should be fine here
Dumux
::
BaseGridGeometry
<
GridView
,
Dumux
::
DefaultMapperTraits
<
GridView
>>
ggCoarse
(
gvCoarse
),
ggFine
(
gvFine
);
auto
glue
=
makeGlue
(
ggFine
,
ggCoarse
);
// a quadratic function on the grid
auto
f
=
[](
const
auto
&
pos
){
return
pos
.
two_norm2
();
};
// make bases
P2
basisCoarse
(
gvCoarse
),
basisFine
(
gvFine
);
SolutionVector
solCoarse
,
solFine
;
SolutionVector
solCoarse
,
solFine
;
interpolate
(
*
basisCoarse
,
solCoarse
,
f
);
interpolate
(
basisCoarse
,
solCoarse
,
f
);
interpolate
(
*
basisFine
,
solFine
,
f
);
interpolate
(
basisFine
,
solFine
,
f
);
auto
gfCoarse
=
makeDiscreteGlobalBasisFunction
<
R
>
(
*
basisCoarse
,
solCoarse
);
auto
gfCoarse
=
makeDiscreteGlobalBasisFunction
<
R
>
(
basisCoarse
,
solCoarse
);
auto
gfFine
=
makeDiscreteGlobalBasisFunction
<
R
>
(
*
basisFine
,
solFine
);
auto
gfFine
=
makeDiscreteGlobalBasisFunction
<
R
>
(
basisFine
,
solFine
);
// project fine discrete function onto coarse grid
// project fine discrete function onto coarse grid and convert back to grid function
Dumux
::
FEGridGeometry
<
P2
>
ggCoarse
(
basisCoarse
),
ggFine
(
basisFine
);
const
auto
projector
=
Dumux
::
makeProjector
(
basisFine
,
basisCoarse
,
glue
);
const
auto
projector
=
Dumux
::
makeProjector
(
*
basisFine
,
*
basisCoarse
,
makeGlue
(
ggFine
,
ggCoarse
));
SolutionVector
solCoarse2
;
SolutionVector
solCoarse2
;
projector
.
project
(
solFine
,
solCoarse2
);
projector
.
project
(
solFine
,
solCoarse2
);
auto
gfCoarse2
=
makeDiscreteGlobalBasisFunction
<
R
>
(
*
basisCoarse
,
solCoarse
);
auto
gfCoarse2
=
makeDiscreteGlobalBasisFunction
<
R
>
(
basisCoarse
,
solCoarse
);
// check that these functions are identical and that they exactly represent the analytical function
// check that these functions are identical and that they exactly represent the analytical function
auto
l2norm
=
Dumux
::
integrateL2Error
(
gvCoarse
,
gfCoarse
,
gfCoarse2
,
3
);
auto
l2norm
=
Dumux
::
integrateL2Error
(
gvCoarse
,
gfCoarse
,
gfCoarse2
,
3
);
if
(
l2norm
>
1e-14
)
if
(
l2norm
>
1e-14
)
DUNE_THROW
(
Dune
::
MathError
,
"L2 norm of projection and interpolation is non-zero
!
"
);
DUNE_THROW
(
Dune
::
MathError
,
"L2 norm of projection and interpolation is non-zero
("
<<
l2norm
<<
")
"
);
l2norm
=
Dumux
::
integrateL2Error
(
gvCoarse
,
makeAnalyticGridViewFunction
(
f
,
gvCoarse
),
gfCoarse2
,
3
);
l2norm
=
Dumux
::
integrateL2Error
(
gvCoarse
,
makeAnalyticGridViewFunction
(
f
,
gvCoarse
),
gfCoarse2
,
3
);
if
(
l2norm
>
1e-14
)
if
(
l2norm
>
1e-14
)
DUNE_THROW
(
Dune
::
MathError
,
"L2 norm of analytical solution and interpolation is non-zero!"
);
DUNE_THROW
(
Dune
::
MathError
,
"L2 norm of analytical solution and interpolation is non-zero ("
<<
l2norm
<<
")"
);
// check the FV-style interface of integrateL2Error
Dumux
::
BoxFVGridGeometry
<
double
,
GridView
>
ggBoxCoarse
(
gvCoarse
),
ggBoxFine
(
gvFine
);
auto
p1BasisCoarse
=
Dumux
::
getFunctionSpaceBasis
(
ggBoxCoarse
);
auto
p1BasisFine
=
Dumux
::
getFunctionSpaceBasis
(
ggBoxFine
);
auto
f2
=
[](
const
auto
&
pos
){
return
pos
[
0
];
};
interpolate
(
p1BasisFine
,
solFine
,
f2
);
interpolate
(
p1BasisCoarse
,
solCoarse
,
f2
);
// project fine discrete function onto coarse grid
const
auto
projector2
=
Dumux
::
makeProjector
(
p1BasisFine
,
p1BasisCoarse
,
glue
);
projector2
.
project
(
solFine
,
solCoarse2
);
l2norm
=
Dumux
::
integrateL2Error
(
ggBoxCoarse
,
solCoarse
,
solCoarse2
,
3
);
if
(
l2norm
>
1e-14
)
DUNE_THROW
(
Dune
::
MathError
,
"L2 norm of FV-style projected solutions is non-zero ("
<<
l2norm
<<
")"
);
std
::
cout
<<
"All tests passed!"
<<
std
::
endl
;
std
::
cout
<<
"All tests passed!"
<<
std
::
endl
;
return
0
;
return
0
;
...
...
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