Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
D
dune-gdt
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
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
ag-ohlberger
dune-community
dune-gdt
Commits
5715a621
Commit
5715a621
authored
2 years ago
by
Dr. Felix Tobias Schindler
Browse files
Options
Downloads
Patches
Plain Diff
[test.stokes] modernize and use new bilinear forms and matrix operators
parent
124734bb
No related branches found
No related tags found
1 merge request
!10
Draft: consolidate refactoring work
Pipeline
#134915
failed
2 years ago
Stage: images
Stage: cpp
Stage: headercheck
Stage: python
Changes
1
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
dune/gdt/test/stokes/stokes-taylorhood.hh
+72
-86
72 additions, 86 deletions
dune/gdt/test/stokes/stokes-taylorhood.hh
with
72 additions
and
86 deletions
dune/gdt/test/stokes/stokes-taylorhood.hh
+
72
−
86
View file @
5715a621
...
...
@@ -20,6 +20,7 @@
#include
<dune/xt/grid/boundaryinfo/alldirichlet.hh>
#include
<dune/xt/grid/gridprovider/cube.hh>
#include
<dune/xt/grid/walker.hh>
#include
<dune/xt/functions/base/function-as-grid-function.hh>
#include
<dune/xt/functions/constant.hh>
...
...
@@ -102,44 +103,44 @@ struct StokesDirichletProblem
const
GV
&
grid_view
()
{
return
grid_view_
;
}
// ... make_initial_grid(...)
}
const
XT
::
Functions
::
GridFunctionInterface
<
E
,
d
,
d
>&
diffusion
()
{
return
*
diffusion_
;
}
// ... make_initial_grid(...)
}
const
VectorGridFunction
&
rhs_f
()
{
return
*
rhs_f_
;
}
// ... make_initial_grid(...)
}
const
VectorGridFunction
&
rhs_g
()
{
return
*
rhs_g_
;
}
// ... make_initial_grid(...)
}
const
VectorGridFunction
&
dirichlet
()
{
return
*
dirichlet_
;
}
// ... make_initial_grid(...)
}
const
VectorGridFunction
&
reference_solution_u
()
{
DUNE_THROW_IF
(
!
reference_sol_u_
,
Dune
::
InvalidStateException
,
"No reference solution provided!"
);
return
*
reference_sol_u_
;
}
// ... make_initial_grid(...)
}
const
ScalarGridFunction
&
reference_solution_p
()
{
DUNE_THROW_IF
(
!
reference_sol_p_
,
Dune
::
InvalidStateException
,
"No reference solution provided!"
);
return
*
reference_sol_p_
;
}
// ... make_initial_grid(...)
}
const
XT
::
Grid
::
BoundaryInfo
<
I
>&
boundary_info
()
{
return
boundary_info_
;
}
// ... make_initial_grid(...)
}
std
::
shared_ptr
<
const
DiffusionTensor
>
diffusion_
;
std
::
shared_ptr
<
const
VectorGridFunction
>
rhs_f_
;
...
...
@@ -208,118 +209,102 @@ public:
// \int (div u) q = \int gg q
// System is [A B; B^T C] [u; p] = [f; g]
// Dimensions are: A: n x n, B: n x m, C: m x m, u: n, f: n, p: m, g: m
// With n = velocity_space.mapper.size(), m = pressure_space.mapper().size()
const
VelocitySpace
velocity_space
(
grid_view
,
velocity_order
);
const
PressureSpace
pressure_space
(
grid_view
,
velocity_order
-
1
);
const
size_t
m
=
velocity_space
.
mapper
().
size
();
const
size_t
n
=
pressure_space
.
mapper
().
size
();
auto
pattern_A
=
make_element_sparsity_pattern
(
velocity_space
,
velocity_space
,
grid_view
);
auto
pattern_B
=
make_element_sparsity_pattern
(
velocity_space
,
pressure_space
,
grid_view
);
auto
pattern_C
=
make_element_sparsity_pattern
(
pressure_space
,
pressure_space
,
grid_view
);
Matrix
A
(
m
,
m
,
pattern_A
);
Matrix
B
(
m
,
n
,
pattern_B
);
MatrixOperator
<
GV
,
d
>
A_operator
(
grid_view
,
velocity_space
,
velocity_space
,
A
);
MatrixOperator
<
GV
,
1
,
1
,
d
>
B_operator
(
grid_view
,
pressure_space
,
velocity_space
,
B
);
// calculate A_{ij} as \int \nabla v_i \nabla v_j
A_operator
.
append
(
LocalElementIntegralBilinearForm
<
E
,
d
>
(
LocalLaplaceIntegrand
<
E
,
d
>
(
problem_
.
diffusion
())));
// calculate B_{ij} as \int -\nabla p_i div(v_j)
B_operator
.
append
(
LocalElementIntegralBilinearForm
<
E
,
d
,
1
,
RangeField
,
RangeField
,
1
>
(
LocalElementAnsatzValueTestDivProductIntegrand
<
E
>
(
-
1.
)));
// calculate rhs f as \int ff v and the integrated pressure space basis \int q_i
Vector
f_vector
(
m
),
p_basis_integrated_vector
(
n
);
auto
f_functional
=
make_vector_functional
(
velocity_space
,
f_vector
);
// Define bilinear forms associated with A and B
// - calculate A_{ij} as \int \nabla v_i \nabla v_j, using associated bilinear form a
BilinearForm
<
GV
,
d
>
a
(
grid_view
);
a
+=
LocalElementIntegralBilinearForm
<
E
,
d
>
(
LocalLaplaceIntegrand
<
E
,
d
>
(
problem_
.
diffusion
()));
// - calculate B_{ij} as \int -\nabla p_i div(v_j), using associated bilinear form b
BilinearForm
<
GV
,
1
,
1
,
d
,
1
>
b
(
grid_view
);
b
+=
LocalElementIntegralBilinearForm
<
E
,
d
,
1
,
RangeField
,
RangeField
,
1
>
(
LocalElementAnsatzValueTestDivProductIntegrand
<
E
>
(
-
1.
));
// Turn these into (discrete) matrix operators (by providing discrete function spaces) which can be assembled
auto
A
=
a
.
template
with
<
Matrix
>(
velocity_space
,
velocity_space
);
auto
B
=
b
.
template
with
<
Matrix
>(
pressure_space
,
velocity_space
);
// calculate rhs f as \int ff v
auto
f_functional
=
make_vector_functional
<
Vector
>
(
velocity_space
);
f_functional
.
append
(
LocalElementIntegralFunctional
<
E
,
d
>
(
LocalProductIntegrand
<
E
,
d
>
().
with_ansatz
(
problem_
.
rhs_f
())));
A_operator
.
append
(
f_functional
);
auto
p_basis_integrated_functional
=
make_vector_functional
(
pressure_space
,
p_basis_integrated_vector
);
XT
::
Functions
::
ConstantGridFunction
<
E
>
one_function
(
1
);
p_basis_integrated_functional
.
append
(
LocalElementIntegralFunctional
<
E
,
1
>
(
LocalProductIntegrand
<
E
,
1
>
().
with_ansatz
(
one_function
)));
B_operator
.
append
(
p_basis_integrated_functional
);
// calculate integrated pressure space basis \int q_i
auto
p_basis_integrated_functional
=
make_vector_functional
<
Vector
>
(
pressure_space
);
p_basis_integrated_functional
.
append
(
LocalElementIntegralFunctional
<
E
,
1
>
(
LocalProductIntegrand
<
E
,
1
>
().
with_ansatz
(
XT
::
Functions
::
ConstantGridFunction
<
E
>
(
1
))));
// Dirichlet constrainst for u
DirichletConstraints
<
I
,
VelocitySpace
>
dirichlet_constraints
(
problem_
.
boundary_info
(),
velocity_space
);
A_operator
.
append
(
dirichlet_constraints
);
// assemble everything
A_operator
.
assemble
(
DXTC_TEST_CONFIG_GET
(
"setup.use_tbb"
,
true
)
);
EXPECT_TRUE
(
is_symmetric
(
A
)
)
;
B_operator
.
assemble
(
DXTC_TEST_CONFIG_GET
(
"setup.use_tbb"
,
true
)
);
Vector
dirichlet_vector
(
m
,
0.
),
reference_solution_u_vector
(
m
,
0.
),
reference_solution_p_vector
(
n
,
0.
);
auto
discrete_dirichlet_values
=
make_discre
te_function
(
velocity_space
,
dirichlet_vector
);
auto
reference_solution_u
=
make_discrete_function
(
velocity_space
,
reference_solution_u_vector
);
auto
reference_solution_p
=
make_discrete_function
(
pressure_space
,
reference_solution_p_vector
);
boundary_interpolation
(
problem_
.
dirichlet
(),
discrete_dirichlet_values
,
problem_
.
boundary_info
(),
XT
::
Grid
::
DirichletBoundary
());
default_interpolation
(
problem_
.
reference_solution_u
(),
reference_solution_u
);
default_interpolation
(
problem_
.
reference_solution_
p
(),
reference_solution_p
);
Vector
rhs_vector_u
(
m
),
rhs_vector_p
(
n
);
auto
walker
=
XT
::
Grid
::
make_walker
(
grid_view
);
walker
.
append
(
A
);
walker
.
append
(
B
);
walker
.
append
(
f_functional
);
walker
.
append
(
p_basis_integra
te
d
_function
al
);
walker
.
append
(
dirichlet_constraints
);
walker
.
walk
(
DXTC_TEST_CONFIG_GET
(
"setup.use_tbb"
,
true
)
);
EXPECT_TRUE
(
is_symmetric
(
A
.
matrix
()));
const
auto
discrete_dirichlet_values
=
boundary_interpolation
<
Vector
>
(
problem_
.
dirichlet
(),
velocity_space
,
problem_
.
boundary_info
(),
XT
::
Grid
::
DirichletBoundary
()
);
auto
reference_solution_u
=
default_interpolation
<
Vector
>
(
problem_
.
reference_solution_
u
(),
velocity_space
);
auto
reference_solution_p
=
default_interpolation
<
Vector
>
(
problem_
.
reference_solution_p
(),
pressure_space
);
// create rhs vector f - A g_D for u
A
.
mv
(
dirichlet_vector
,
rhs_
vector
_u
);
auto
rhs_vector_u
=
A
.
apply
(
discrete_dirichlet_values
.
dofs
().
vector
()
);
rhs_vector_u
*=
-
1.
;
rhs_vector_u
+=
f_vector
;
rhs_vector_u
+=
f_
functional
.
vector
()
;
// create rhs vector -B^T g_D for p
B
.
mtv
(
dirichlet_vector
,
rhs_vector_p
);
rhs_vector_p
*=
-
1
;
auto
rhs_vector_p
=
B
.
matrix
().
mtv
(
discrete_dirichlet_values
.
dofs
().
vector
());
// TODO: use B.apply_adjoint ...
rhs_vector_p
*=
-
1
;
// ... see https://zivgitlab.uni-muenster.de/ag-ohlberger/dune-community/dune-gdt/-/issues/32
// apply dirichlet constraints for u. We need to set the whole row of (A B; B^T 0) to the unit row for each
// Dirichlet DoF, so we also need to clear the row of B.
dirichlet_constraints
.
apply
(
A
,
rhs_vector_u
);
EXPECT_TRUE
(
is_symmetric
(
A
));
dirichlet_constraints
.
apply
(
A
.
matrix
()
,
rhs_vector_u
);
EXPECT_TRUE
(
is_symmetric
(
A
.
matrix
()
));
for
(
const
auto
&
DoF
:
dirichlet_constraints
.
dirichlet_DoFs
())
B
.
clear_row
(
DoF
);
B
.
matrix
().
clear_row
(
DoF
);
#if defined(NDEBUG) || HAVE_MKL || HAVE_LAPACKE
// This check is very slow if compiled in debug mode without LAPACKE,
// so we disable it in that case to avoid a test timeout.
EXPECT_TRUE
(
is_positive_definite
(
A
));
EXPECT_TRUE
(
is_positive_definite
(
A
.
matrix
()
));
#endif
// Fix value of p at first DoF to 0 to ensure the uniqueness of the solution, i.e, we have set the m-th row of
// [A B; B^T 0] to the unit vector.
Matrix
C
(
n
,
n
,
pattern_C
);
size_t
dof_index
=
0
;
B
.
clear_col
(
dof_index
);
auto
C
=
make_matrix_operator
<
Matrix
>
(
pressure_space
);
const
size_t
dof_index
=
0
;
B
.
matrix
().
clear_col
(
dof_index
);
rhs_vector_p
.
set_entry
(
dof_index
,
0.
);
C
.
set_entry
(
dof_index
,
dof_index
,
1.
);
C
.
matrix
().
set_entry
(
dof_index
,
dof_index
,
1.
);
// now solve the system
XT
::
LA
::
SaddlePointSolver
<
Vector
,
Matrix
>
solver
(
A
,
B
,
B
,
C
);
Vector
solution_u
(
m
),
solution_p
(
n
);
XT
::
LA
::
SaddlePointSolver
<
Vector
,
Matrix
>
solver
(
A
.
matrix
(),
B
.
matrix
(),
B
.
matrix
(),
C
.
matrix
());
auto
solution_u
=
make_discrete_function
<
Vector
>
(
velocity_space
);
auto
solution_p
=
make_discrete_function
<
Vector
>
(
pressure_space
);
// solve both by direct solver and by schurcomplement (where the schur complement is inverted by CG and the inner
// solves with A are using a direct method)
for
(
std
::
string
type
:
{
"direct"
,
"cg_direct_schurcomplement"
})
{
solver
.
apply
(
rhs_vector_u
,
rhs_vector_p
,
solution_u
,
solution_p
,
type
);
solver
.
apply
(
rhs_vector_u
,
rhs_vector_p
,
solution_u
.
dofs
().
vector
(),
solution_p
.
dofs
().
vector
()
,
type
);
// add dirichlet values to u
const
auto
actual_u_vector
=
solution_u
+
dirichlet_
vector
;
solution_u
.
dofs
().
vector
()
+=
discrete_dirichlet_values
.
dofs
().
vector
()
;
// ensure int_\Omega p = 0
auto
p_integral
=
p_basis_integrated_vector
*
solution_p
;
auto
p_ref_integral
=
p_basis_integrated_vector
*
reference_solution_p_vector
;
auto
p_correction
=
p_basis_integrated_vector
;
auto
p_correction_func
=
make_discrete_function
(
pressure_space
,
p_correction
);
auto
p_ref_correction
=
reference_solution_p_vector
;
auto
p_ref_correction_func
=
make_discrete_function
(
pressure_space
,
p_ref_correction
);
const
auto
p_integral
=
p_basis_integrated_functional
.
apply
(
solution_p
);
const
auto
p_ref_integral
=
p_basis_integrated_functional
.
apply
(
reference_solution_p
);
const
auto
vol_domain
=
4.
;
XT
::
Functions
::
ConstantGridFunction
<
E
>
const_p_integral_func
(
p_integral
/
vol_domain
);
XT
::
Functions
::
ConstantGridFunction
<
E
>
const_p_ref_integral_func
(
p_ref_integral
/
vol_domain
);
default_interpolation
(
const_p_integral_func
,
p
_correction_func
);
default_interpolation
(
const_p_ref_integral_func
,
p
_
re
f_correction_func
);
const
auto
actual_p_vector
=
solution_p
-
p_correction
;
const
auto
actual_p_ref_vector
=
reference_solution_p
_
vector
-
p_ref_correction
;
const
auto
p_correction_func
=
default_interpolation
<
Vector
>
(
const_p_integral_func
,
p
ressure_space
);
const
auto
p_ref_correction_func
=
default_interpolation
<
Vector
>
(
const_p_ref_integral_func
,
pre
ssure_space
);
solution_p
.
dofs
().
vector
()
-=
p_correction_func
.
dofs
().
vector
()
;
reference_solution_p
.
dofs
().
vector
()
-
=
p_ref_correction
_func
.
dofs
().
vector
()
;
// calculate difference to reference solution
const
auto
u_diff_vector
=
actual_u_vector
-
reference_solution_u_vector
;
const
auto
p_diff_vector
=
actual_p_vector
-
actual_p_ref_vector
;
auto
sol_u_func
=
make_discrete_function
(
velocity_space
,
actual_u_vector
);
auto
sol_p_func
=
make_discrete_function
(
pressure_space
,
actual_p_vector
);
auto
p_diff
=
make_discrete_function
(
pressure_space
,
p_diff_vector
);
auto
u_diff
=
make_discrete_function
(
velocity_space
,
u_diff_vector
);
auto
actual_p_ref
=
make_discrete_function
(
pressure_space
,
actual_p_ref_vector
);
bool
visualize
=
true
;
const
auto
p_diff
=
solution_p
-
reference_solution_p
;
const
auto
u_diff
=
solution_u
-
reference_solution_u
;
std
::
string
grid_name
=
XT
::
Common
::
Typename
<
G
>::
value
();
if
(
visualize
)
{
GDT
::
visualize
(
sol
_u_func
,
"solution_u_"
+
type
+
"_"
+
grid_name
);
GDT
::
visualize
(
sol
_p_func
,
"solution_p_"
+
type
+
"_"
+
grid_name
);
GDT
::
visualize
(
reference_solution_u
,
"u_ref_"
+
grid_name
);
GDT
::
visualize
(
actual_p_ref
,
"p_ref_"
+
grid_name
);
GDT
::
visualize
(
u_diff
,
"u_error_"
+
type
+
"_"
+
grid_name
);
GDT
::
visualize
(
p_diff
,
"p_error_"
+
type
+
"_"
+
grid_name
);
if
(
DXTC_TEST_CONFIG_GET
(
"
visualize
"
,
true
)
)
{
visualize
(
sol
ution_u
,
"solution_u_"
+
type
+
"_"
+
grid_name
);
visualize
(
sol
ution_p
,
"solution_p_"
+
type
+
"_"
+
grid_name
);
visualize
(
reference_solution_u
,
"u_ref_"
+
grid_name
);
visualize
(
reference_solution_p
,
"p_ref_"
+
grid_name
);
visualize
(
u_diff
,
grid_view
,
"u_error_"
+
type
+
"_"
+
grid_name
);
visualize
(
p_diff
,
grid_view
,
"p_error_"
+
type
+
"_"
+
grid_name
);
}
DXTC_EXPECT_FLOAT_LE
(
l2_norm
(
problem_
.
grid_view
(),
u_diff
),
expected_error_u
);
DXTC_EXPECT_FLOAT_LE
(
l2_norm
(
problem_
.
grid_view
(),
p_diff
),
expected_error_p
);
...
...
@@ -329,6 +314,7 @@ public:
StokesDirichletProblem
<
GV
>
problem_
;
};
// class StrokesDirichletTest
template
<
class
G
>
class
StokesTestcase1
:
public
StokesDirichletTest
<
G
>
{
...
...
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