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
hyteg
hyteg
Commits
cf20ad5f
Commit
cf20ad5f
authored
Dec 02, 2021
by
Marcel Koch
Browse files
[wip] add ginkgo blocked solver
parent
c3c9b7c9
Pipeline
#36095
failed with stages
in 10 minutes and 18 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/hyteg/ginkgo/GinkgoBlockSolver.hpp
0 → 100644
View file @
cf20ad5f
#pragma once
#include
<ginkgo/core/log/convergence.hpp>
#include
<ginkgo/core/log/convergence_stream.hpp>
#include
<ginkgo/core/matrix/block_matrix.hpp>
#include
<ginkgo/core/solver/bicgstab.hpp>
#include
<ginkgo/core/solver/gmres.hpp>
#include
<ginkgo/core/stop/iteration.hpp>
#include
<ginkgo/core/stop/residual_norm.hpp>
#include
<hyteg/composites/petsc/P2P1TaylorHoodPetsc.hpp>
#include
"hyteg/ginkgo/GinkgoCommunication.hpp"
#include
"hyteg/ginkgo/GinkgoDirichletHandling.hpp"
#include
"hyteg/ginkgo/GinkgoSparseMatrixProxy.hpp"
#include
"hyteg/ginkgo/GinkgoVectorProxy.hpp"
#include
"hyteg/solvers/Solver.hpp"
namespace
hyteg
{
void
gatherIndices
(
std
::
vector
<
int32_t
>&
velocityIndices
,
std
::
vector
<
int32_t
>&
pressureIndices
,
const
PrimitiveStorage
&
storage
,
uint_t
level
,
const
P1StokesFunction
<
int32_t
>&
numerator
)
{
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
0
],
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
1
],
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
if
(
storage
.
hasGlobalCells
()
)
{
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
2
],
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
}
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
p
,
level
)
)
{
pressureIndices
.
push_back
(
dof
.
value
()
);
}
}
void
gatherIndices
(
std
::
vector
<
int32_t
>&
velocityIndices
,
std
::
vector
<
int32_t
>&
pressureIndices
,
const
PrimitiveStorage
&
storage
,
uint_t
level
,
const
P2P1TaylorHoodFunction
<
int32_t
>&
numerator
)
{
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
0
].
getVertexDoFFunction
(),
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
for
(
auto
dof
:
FunctionIterator
<
EdgeDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
0
].
getEdgeDoFFunction
(),
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
1
].
getVertexDoFFunction
(),
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
for
(
auto
dof
:
FunctionIterator
<
EdgeDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
1
].
getEdgeDoFFunction
(),
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
if
(
storage
.
hasGlobalCells
()
)
{
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
2
].
getVertexDoFFunction
(),
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
for
(
auto
dof
:
FunctionIterator
<
EdgeDoFFunction
<
int32_t
>
>
(
numerator
.
uvw
[
2
].
getEdgeDoFFunction
(),
level
)
)
{
velocityIndices
.
push_back
(
dof
.
value
()
);
}
}
for
(
auto
dof
:
FunctionIterator
<
vertexdof
::
VertexDoFFunction
<
int32_t
>
>
(
numerator
.
p
,
level
)
)
{
pressureIndices
.
push_back
(
dof
.
value
()
);
}
}
template
<
typename
OperatorType
>
class
GinkgoBlockSolver
:
public
Solver
<
OperatorType
>
{
using
BlockPreconditioner_T
=
typename
OperatorType
::
BlockPreconditioner_T
;
public:
using
FunctionType
=
typename
OperatorType
::
srcType
;
using
valueType
=
typename
FunctionType
::
valueType
;
using
mtx
=
gko
::
distributed
::
Matrix
<
valueType
,
int32_t
>
;
using
csr
=
gko
::
matrix
::
Csr
<
valueType
,
int32_t
>
;
using
vec
=
gko
::
distributed
::
Vector
<
valueType
,
int32_t
>
;
using
dense
=
gko
::
matrix
::
Dense
<
valueType
>
;
explicit
GinkgoBlockSolver
(
const
std
::
shared_ptr
<
PrimitiveStorage
>&
storage
,
const
uint_t
&
level
,
std
::
shared_ptr
<
const
gko
::
Executor
>
exec
)
:
storage_
(
storage
)
,
exec_
(
exec
)
,
comm_
(
gko
::
mpi
::
communicator
::
create
(
storage
->
getSplitCommunicatorByPrimitiveDistribution
()
)
)
,
num_
(
"numerator"
,
storage
,
level
,
level
)
{}
void
solve
(
const
OperatorType
&
A
,
const
typename
OperatorType
::
srcType
&
x
,
const
typename
OperatorType
::
dstType
&
b
,
const
walberla
::
uint_t
level
)
override
{
const
auto
num_local_dofs
=
numberOfLocalDoFs
<
typename
FunctionType
::
Tag
>
(
*
storage_
,
level
);
const
auto
num_global_dofs
=
numberOfGlobalDoFs
<
typename
FunctionType
::
Tag
>
(
*
storage_
,
level
,
comm_
->
get
()
);
auto
[
start
,
end
]
=
local_range
(
num_local_dofs
,
comm_
);
auto
part
=
gko
::
share
(
gko
::
distributed
::
Partition
<>::
build_from_local_range
(
exec_
,
start
,
end
,
comm_
)
);
// maybe called in parallel, thus need to keep it for empty processes
num_
.
copyBoundaryConditionFromFunction
(
x
);
num_
.
enumerate
(
level
);
std
::
vector
<
int32_t
>
bcIndices
;
hyteg
::
petsc
::
applyDirichletBC
(
num_
,
bcIndices
,
level
);
std
::
sort
(
std
::
begin
(
bcIndices
),
std
::
end
(
bcIndices
)
);
auto
x_gko
=
vec
::
create
(
exec_
,
comm_
,
part
,
gko
::
dim
<
2
>
{
num_global_dofs
,
1
},
gko
::
dim
<
2
>
{
num_local_dofs
,
1
}
);
auto
b_gko
=
vec
::
create
(
exec_
,
comm_
,
part
,
gko
::
dim
<
2
>
{
num_global_dofs
,
1
},
gko
::
dim
<
2
>
{
num_local_dofs
,
1
}
);
hyteg
::
petsc
::
createVectorFromFunction
(
x
,
num_
,
std
::
make_shared
<
GinkgoVectorProxy
>
(
x_gko
.
get
(),
gko
::
dim
<
2
>
{
num_global_dofs
,
1
},
part
),
level
,
All
);
hyteg
::
petsc
::
createVectorFromFunction
(
b
,
num_
,
std
::
make_shared
<
GinkgoVectorProxy
>
(
b_gko
.
get
(),
gko
::
dim
<
2
>
{
num_global_dofs
,
1
},
part
),
level
,
All
);
monolithic_matrix_
=
gko
::
share
(
mtx
::
create
(
exec_
,
comm_
)
);
auto
proxy
=
std
::
make_shared
<
GinkgoSparseMatrixProxy
<
mtx
>
>
(
monolithic_matrix_
.
get
(),
gko
::
dim
<
2
>
{
num_global_dofs
,
num_global_dofs
},
part
);
hyteg
::
petsc
::
createMatrix
(
A
,
num_
,
num_
,
proxy
,
level
,
All
);
proxy
->
finalize
();
auto
dir_handler
=
std
::
make_unique
<
ZeroRowsDirichletHandler
>
(
bcIndices
,
b_gko
.
get
(),
monolithic_matrix_
,
true
);
dir_handler
->
update_matrix
();
std
::
vector
<
int32_t
>
vIndices
;
std
::
vector
<
int32_t
>
pIndices
;
gatherIndices
(
vIndices
,
pIndices
,
*
storage_
,
level
,
num_
);
auto
[
p_v_min
,
p_v_max
]
=
std
::
minmax_element
(
std
::
begin
(
vIndices
),
std
::
end
(
vIndices
)
);
auto
[
p_p_min
,
p_p_max
]
=
std
::
minmax_element
(
std
::
begin
(
pIndices
),
std
::
end
(
pIndices
)
);
gko
::
span
v_span
(
*
p_v_min
,
*
p_v_max
+
1
);
gko
::
span
p_span
(
*
p_p_min
,
*
p_p_max
+
1
);
if
(
p_span
.
begin
!=
v_span
.
end
)
{
WALBERLA_ABORT
(
"Indices are NOT blocked: v"
<<
v_span
<<
", p"
<<
p_span
)
}
auto
b_mtx_v
=
gko
::
share
(
monolithic_matrix_
->
get_local_diag
()
->
create_submatrix
(
v_span
,
v_span
)
);
auto
b_mtx_vp
=
gko
::
share
(
monolithic_matrix_
->
get_local_diag
()
->
create_submatrix
(
v_span
,
p_span
)
);
auto
b_mtx_pv
=
gko
::
share
(
monolithic_matrix_
->
get_local_diag
()
->
create_submatrix
(
p_span
,
v_span
)
);
auto
b_mtx_p
=
gko
::
share
(
monolithic_matrix_
->
get_local_diag
()
->
create_submatrix
(
p_span
,
p_span
)
);
matrix_
=
gko
::
share
(
gko
::
matrix
::
BlockMatrix
::
create
(
exec_
,
{
num_global_dofs
,
num_global_dofs
},
{{
b_mtx_v
,
b_mtx_vp
},
{
b_mtx_pv
,
b_mtx_p
}}));
// auto b_vec_b0 = gko::share( b_gko->get_local()->create_submatrix( v_span, 0 ) );
// auto b_vec_b1 = gko::share( b_gko->get_local()->create_submatrix( p_span, 0 ) );
// auto b_vec_x0 = gko::share( x_gko->get_local()->create_submatrix( v_span, 0 ) );
// auto b_vec_x1 = gko::share( x_gko->get_local()->create_submatrix( p_span, 0 ) );
//
// auto b_b_gko = gko::matrix::BlockMatrix::create(exec_, {num_global_dofs, num_global_dofs}, {{b_vec_b0}, {b_vec_b1}});
// auto b_x_gko = gko::matrix::BlockMatrix::create(exec_, {num_global_dofs, num_global_dofs}, {{b_vec_x0}, {b_vec_x1}});
solver_
=
gko
::
solver
::
Bicgstab
<
valueType
>::
build
()
.
with_criteria
(
gko
::
share
(
gko
::
stop
::
ResidualNorm
<>::
build
()
.
with_baseline
(
gko
::
stop
::
mode
::
initial_resnorm
)
.
with_reduction_factor
(
1e-30
)
.
on
(
exec_
)
),
gko
::
share
(
gko
::
stop
::
ResidualNorm
<>::
build
()
.
with_baseline
(
gko
::
stop
::
mode
::
absolute
)
.
with_reduction_factor
(
1e-12
)
.
on
(
exec_
)
),
gko
::
share
(
gko
::
stop
::
Iteration
::
build
().
with_max_iters
(
15000
).
on
(
exec_
)
)
)
.
on
(
exec_
)
->
generate
(
matrix_
);
auto
log
=
gko
::
share
(
gko
::
log
::
Convergence
<
valueType
>::
create
(
exec_
)
);
auto
factory
=
gko
::
clone
(
solver_
->
get_stop_criterion_factory
()
);
factory
->
add_logger
(
log
);
solver_
->
set_stop_criterion_factory
(
gko
::
share
(
factory
)
);
auto
rhs
=
dir_handler
->
get_rhs
(
b_gko
.
get
(),
x_gko
.
get
()
);
auto
x0
=
dir_handler
->
get_initial_guess
(
x_gko
.
get
()
);
solver_
->
apply
(
rhs
,
x0
);
dir_handler
->
update_solution
(
x0
);
hyteg
::
petsc
::
createFunctionFromVector
(
x
,
num_
,
std
::
make_shared
<
GinkgoVectorProxy
>
(
x0
,
gko
::
dim
<
2
>
{
num_global_dofs
,
1
},
part
),
level
,
All
);
{
WALBERLA_LOG_INFO_ON_ROOT
(
"[Ginkgo CG]"
<<
(
!
log
->
has_converged
()
?
" NOT "
:
" "
)
<<
"converged after "
<<
log
->
get_num_iterations
()
<<
" iterations, residual norm: "
<<
exec_
->
copy_val_to_host
(
gko
::
as
<
gko
::
matrix
::
Dense
<
valueType
>
>
(
log
->
get_residual_norm
()
)
->
get_const_values
()
)
);
}
}
private:
std
::
shared_ptr
<
PrimitiveStorage
>
storage_
;
std
::
shared_ptr
<
const
gko
::
Executor
>
exec_
;
std
::
shared_ptr
<
gko
::
mpi
::
communicator
>
comm_
;
std
::
unique_ptr
<
gko
::
solver
::
Bicgstab
<
valueType
>
>
solver_
;
typename
OperatorType
::
srcType
::
template
FunctionType
<
int
>
num_
;
std
::
shared_ptr
<
gko
::
matrix
::
BlockMatrix
>
matrix_
;
std
::
shared_ptr
<
mtx
>
monolithic_matrix_
;
};
}
// namespace hyteg
tests/hyteg/CMakeLists.txt
View file @
cf20ad5f
...
...
@@ -352,11 +352,18 @@ if( HYTEG_BUILD_WITH_PETSC )
endif
()
if
(
HYTEG_BUILD_WITH_GINKGO
)
add_library
(
precompiled composites/p2p1stokes.cpp
)
target_link_modules
(
precompiled hyteg core
)
target_link_libraries
(
precompiled
${
SERVICE_LIBS
}
)
waLBerla_compile_test
(
FILES P1/P1GinkgoSolveTest.cpp DEPENDS hyteg core
)
waLBerla_execute_test
(
NAME P1GinkgoSolveTest1 COMMAND $<TARGET_FILE:P1GinkgoSolveTest> PROCESSES 1
)
waLBerla_compile_test
(
FILES composites/P2P1StokesGinkgoApplyTest.cpp DEPENDS hyteg core
)
waLBerla_execute_test
(
NAME P2P1StokesGinkgoApplyTest1 COMMAND $<TARGET_FILE:P2P1StokesGinkgoApplyTest> PROCESSES 1
)
waLBerla_compile_test
(
FILES composites/P2P1Stokes3DGinkgoSolveTest.cpp DEPENDS hyteg core
)
waLBerla_execute_test
(
NAME P2P1Stokes3DGinkgoSolveTest1 COMMAND $<TARGET_FILE:P2P1Stokes3DGinkgoSolveTest> PROCESSES 1
)
endif
()
...
...
tests/hyteg/composites/P2P1Stokes3DGinkgoSolveTest.cpp
0 → 100644
View file @
cf20ad5f
/*
* Copyright (c) 2017-2019 Dominik Thoennes.
*
* This file is part of HyTeG
* (see https://i10git.cs.fau.de/hyteg/hyteg).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
"core/Environment.h"
#include
"core/logging/Logging.h"
#include
"core/math/Random.h"
#include
"core/timing/Timer.h"
#include
"hyteg/dataexport/VTKOutput.hpp"
#include
"hyteg/mesh/MeshInfo.hpp"
#include
"hyteg/misc/ExactStencilWeights.hpp"
#include
"hyteg/p1functionspace/P1ConstantOperator.hpp"
#include
"hyteg/p1functionspace/P1Function.hpp"
#include
"hyteg/ginkgo/GinkgoBlockSolver.hpp"
#include
"hyteg/petsc/PETScLUSolver.hpp"
#include
"hyteg/petsc/PETScMinResSolver.hpp"
#include
"hyteg/petsc/PETScBlockPreconditionedStokesSolver.hpp"
#include
"hyteg/petsc/PETScManager.hpp"
#include
"hyteg/petsc/PETScVersion.hpp"
#include
"hyteg/petsc/PETScExportLinearSystem.hpp"
#include
"hyteg/ginkgo/GinkgoSparseMatrixProxy.hpp"
#include
"hyteg/ginkgo/GinkgoUtilities.hpp"
#include
"hyteg/ginkgo/GinkgoVectorProxy.hpp"
#include
"hyteg/primitivestorage/SetupPrimitiveStorage.hpp"
#include
"hyteg/primitivestorage/Visualization.hpp"
#include
"hyteg/primitivestorage/loadbalancing/SimpleBalancer.hpp"
#include
"hyteg/composites/P2P1TaylorHoodFunction.hpp"
#include
"hyteg/composites/P2P1TaylorHoodStokesOperator.hpp"
#ifndef HYTEG_BUILD_WITH_GINKGO
WALBERLA_ABORT
(
"This test only works with Ginkgo enabled. Please enable it via -DHYTEG_BUILD_WITH_GINKGO=ON"
)
#endif
using
walberla
::
real_t
;
using
walberla
::
uint_c
;
using
walberla
::
uint_t
;
namespace
hyteg
{
void
petscSolveTest
(
const
uint_t
&
level
,
const
MeshInfo
&
meshInfo
,
const
real_t
&
resEps
,
const
real_t
&
errEpsUSum
,
const
real_t
&
errEpsP
)
{
SetupPrimitiveStorage
setupStorage
(
meshInfo
,
uint_c
(
walberla
::
mpi
::
MPIManager
::
instance
()
->
numProcesses
()
)
);
setupStorage
.
setMeshBoundaryFlagsOnBoundary
(
1
,
0
,
true
);
hyteg
::
loadbalancing
::
roundRobin
(
setupStorage
);
std
::
shared_ptr
<
PrimitiveStorage
>
storage
=
std
::
make_shared
<
PrimitiveStorage
>
(
setupStorage
);
writeDomainPartitioningVTK
(
storage
,
"../../output"
,
"P2P1Stokes3DPetscSolve_Domain"
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
x
(
"x"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
x_exact
(
"x_exact"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
b
(
"b"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
btmp
(
"btmp"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
err
(
"err"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
residuum
(
"res"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
real_t
>
nullspace
(
"nullspace"
,
storage
,
level
,
level
);
hyteg
::
P2P1TaylorHoodFunction
<
PetscInt
>
numerator
(
"numerator"
,
storage
,
level
,
level
);
numerator
.
enumerate
(
level
);
hyteg
::
P2P1TaylorHoodStokesOperator
A
(
storage
,
level
,
level
);
std
::
function
<
real_t
(
const
hyteg
::
Point3D
&
)
>
exactU
=
[](
const
hyteg
::
Point3D
&
xx
)
{
return
real_c
(
20
)
*
xx
[
0
]
*
xx
[
1
]
*
xx
[
1
]
*
xx
[
1
];
};
std
::
function
<
real_t
(
const
hyteg
::
Point3D
&
)
>
exactV
=
[](
const
hyteg
::
Point3D
&
xx
)
{
return
real_c
(
5
)
*
xx
[
0
]
*
xx
[
0
]
*
xx
[
0
]
*
xx
[
0
]
-
real_c
(
5
)
*
xx
[
1
]
*
xx
[
1
]
*
xx
[
1
]
*
xx
[
1
];
};
std
::
function
<
real_t
(
const
hyteg
::
Point3D
&
)
>
exactW
=
[](
const
hyteg
::
Point3D
&
)
{
return
real_c
(
0
);
};
std
::
function
<
real_t
(
const
hyteg
::
Point3D
&
)
>
exactP
=
[](
const
hyteg
::
Point3D
&
xx
)
{
return
real_c
(
60
)
*
std
::
pow
(
xx
[
0
],
2.0
)
*
xx
[
1
]
-
real_c
(
20
)
*
std
::
pow
(
xx
[
1
],
3.0
);
};
std
::
function
<
real_t
(
const
hyteg
::
Point3D
&
)
>
zero
=
[](
const
hyteg
::
Point3D
&
)
{
return
real_c
(
0
);
};
std
::
function
<
real_t
(
const
hyteg
::
Point3D
&
)
>
ones
=
[](
const
hyteg
::
Point3D
&
)
{
return
real_c
(
1
);
};
b
.
uvw
.
interpolate
(
{
exactU
,
exactV
,
exactW
},
level
,
DirichletBoundary
);
b
.
p
.
interpolate
(
zero
,
level
,
All
);
x
.
uvw
.
interpolate
(
{
exactU
,
exactV
,
exactW
},
level
,
DirichletBoundary
);
x_exact
.
uvw
.
interpolate
(
{
exactU
,
exactV
,
exactW
},
level
);
x_exact
.
p
.
interpolate
(
exactP
,
level
);
hyteg
::
vertexdof
::
projectMean
(
x_exact
.
p
,
level
);
nullspace
.
p
.
interpolate
(
ones
,
level
,
All
);
uint_t
localDoFs1
=
hyteg
::
numberOfLocalDoFs
<
P2P1TaylorHoodFunctionTag
>
(
*
storage
,
level
);
uint_t
globalDoFs1
=
hyteg
::
numberOfGlobalDoFs
<
P2P1TaylorHoodFunctionTag
>
(
*
storage
,
level
);
uint_t
globalDoFsvelocity
=
3
*
hyteg
::
numberOfGlobalDoFs
<
P2FunctionTag
>
(
*
storage
,
level
);
WALBERLA_LOG_INFO
(
"localDoFs: "
<<
localDoFs1
<<
" globalDoFs: "
<<
globalDoFs1
<<
", global velocity dofs: "
<<
globalDoFsvelocity
);
GinkgoBlockSolver
<
P2P1TaylorHoodStokesOperator
>
solver
(
storage
,
level
,
gko
::
ReferenceExecutor
::
create
());
walberla
::
WcTimer
timer
;
solver
.
solve
(
A
,
x
,
b
,
level
);
timer
.
end
();
hyteg
::
vertexdof
::
projectMean
(
x
.
p
,
level
);
WALBERLA_LOG_INFO_ON_ROOT
(
"time was: "
<<
timer
.
last
()
);
A
.
apply
(
x
,
residuum
,
level
,
hyteg
::
Inner
);
err
.
assign
(
{
1.0
,
-
1.0
},
{
x
,
x_exact
},
level
);
real_t
discr_l2_err
=
std
::
sqrt
(
err
.
dotGlobal
(
err
,
level
)
/
(
real_t
)
globalDoFs1
);
real_t
discr_l2_err_1_u
=
std
::
sqrt
(
err
.
uvw
[
0
].
dotGlobal
(
err
.
uvw
[
0
],
level
)
/
(
real_t
)
globalDoFs1
);
real_t
discr_l2_err_1_v
=
std
::
sqrt
(
err
.
uvw
[
1
].
dotGlobal
(
err
.
uvw
[
1
],
level
)
/
(
real_t
)
globalDoFs1
);
real_t
discr_l2_err_1_w
=
std
::
sqrt
(
err
.
uvw
[
2
].
dotGlobal
(
err
.
uvw
[
2
],
level
)
/
(
real_t
)
globalDoFs1
);
real_t
discr_l2_err_1_p
=
std
::
sqrt
(
err
.
p
.
dotGlobal
(
err
.
p
,
level
)
/
(
real_t
)
globalDoFs1
);
real_t
residuum_l2_1
=
std
::
sqrt
(
residuum
.
dotGlobal
(
residuum
,
level
)
/
(
real_t
)
globalDoFs1
);
WALBERLA_LOG_INFO_ON_ROOT
(
"discrete L2 error = "
<<
discr_l2_err
);
WALBERLA_LOG_INFO_ON_ROOT
(
"discrete L2 error u = "
<<
discr_l2_err_1_u
);
WALBERLA_LOG_INFO_ON_ROOT
(
"discrete L2 error v = "
<<
discr_l2_err_1_v
);
WALBERLA_LOG_INFO_ON_ROOT
(
"discrete L2 error w = "
<<
discr_l2_err_1_w
);
WALBERLA_LOG_INFO_ON_ROOT
(
"discrete L2 error p = "
<<
discr_l2_err_1_p
);
WALBERLA_LOG_INFO_ON_ROOT
(
"residuum 1 = "
<<
residuum_l2_1
);
WALBERLA_CHECK_LESS
(
residuum_l2_1
,
resEps
);
WALBERLA_CHECK_LESS
(
discr_l2_err_1_u
+
discr_l2_err_1_v
+
discr_l2_err_1_w
,
errEpsUSum
);
WALBERLA_CHECK_LESS
(
discr_l2_err_1_p
,
errEpsP
);
auto
tt
=
storage
->
getTimingTree
()
->
getReduced
().
getCopyWithRemainder
();
}
}
using
namespace
hyteg
;
int
main
(
int
argc
,
char
*
argv
[]
)
{
walberla
::
Environment
walberlaEnv
(
argc
,
argv
);
walberla
::
MPIManager
::
instance
()
->
useWorldComm
();
PETScManager
petscManager
(
&
argc
,
&
argv
);
printPETScVersionNumberString
();
auto
level
=
argc
>
2
?
std
::
stoi
(
argv
[
2
])
:
0
;
petscSolveTest
(
level
,
hyteg
::
MeshInfo
::
fromGmshFile
(
"../../data/meshes/3D/cube_center_at_origin_24el.msh"
),
2.9e-12
,
0.021
,
0.33
);
return
EXIT_SUCCESS
;
}
tests/hyteg/composites/P2P1StokesGinkgoApplyTest.cpp
View file @
cf20ad5f
...
...
@@ -114,6 +114,35 @@ void gatherIndices( std::vector< int32_t >& velocityIndices,
}
}
bool
check_error
(
std
::
shared_ptr
<
PrimitiveStorage
>
storage
,
const
P2P1TaylorHoodFunction
<
real_t
>&
a
,
const
P2P1TaylorHoodFunction
<
real_t
>&
b
,
const
uint
level
,
const
real_t
&
eps
)
{
// compare
P2P1TaylorHoodFunction
<
real_t
>
err
(
"error"
,
storage
,
level
,
level
);
err
.
assign
(
{
1.0
,
-
1.0
},
{
a
,
b
},
level
,
hyteg
::
All
);
auto
maxError
=
err
.
uvw
[
0
].
getMaxMagnitude
(
level
);
maxError
=
std
::
max
(
maxError
,
err
.
uvw
[
1
].
getMaxMagnitude
(
level
)
);
if
(
err
.
uvw
.
getDimension
()
==
3
)
{
maxError
=
std
::
max
(
maxError
,
err
.
uvw
[
2
].
getMaxMagnitude
(
level
)
);
}
maxError
=
std
::
max
(
maxError
,
err
.
p
.
getMaxMagnitude
(
level
)
);
WALBERLA_LOG_INFO_ON_ROOT
(
"Error max Magnitude = "
<<
maxError
<<
" eps: "
<<
eps
);
if
(
maxError
>
eps
)
{
WALBERLA_LOG_INFO_ON_ROOT
(
"TEST FAILED!"
);
return
false
;
}
else
{
return
true
;
}
}
bool
p2p1StokesGinkgoApplyTest
(
std
::
shared_ptr
<
const
gko
::
Executor
>
exec
,
const
uint_t
&
level
,
const
std
::
string
&
meshFile
,
...
...
@@ -194,6 +223,18 @@ bool p2p1StokesGinkgoApplyTest( std::shared_ptr< const gko::Executor > exec,
hyteg
::
petsc
::
createMatrix
(
L
,
numerator
,
numerator
,
proxy
,
level
,
All
);
proxy
->
finalize
();
gkoMtx
->
apply
(
srcGkoVec
.
get
(),
dstGkoVec
.
get
());
hyteg
::
petsc
::
createFunctionFromVector
(
ginkgoDst
,
numerator
,
std
::
make_shared
<
GinkgoVectorProxy
>
(
gko
::
lend
(
dstGkoVec
),
gko
::
dim
<
2
>
{
localDoFs
,
1
},
part
),
level
,
All
);
auto
success
=
check_error
(
storage
,
hhgDst
,
ginkgoDst
,
level
,
eps
);
std
::
vector
<
int32_t
>
vIndices
;
std
::
vector
<
int32_t
>
pIndices
;
...
...
@@ -222,6 +263,13 @@ bool p2p1StokesGinkgoApplyTest( std::shared_ptr< const gko::Executor > exec,
auto
b_srcGkoVec
=
gko
::
matrix
::
BlockMatrix
::
create
(
exec
,
{
localDoFs
,
localDoFs
},
{{
b_vec_s0
},
{
b_vec_s1
}});
auto
b_dstGkoVec
=
gko
::
matrix
::
BlockMatrix
::
create
(
exec
,
{
localDoFs
,
localDoFs
},
{{
b_vec_d0
},
{
b_vec_d1
}});
hyteg
::
petsc
::
createVectorFromFunction
(
ginkgoDst
,
numerator
,
std
::
make_shared
<
GinkgoVectorProxy
>
(
gko
::
lend
(
dstGkoVec
),
gko
::
dim
<
2
>
{
localDoFs
,
1
},
part
),
level
,
All
);
b_gkoMtx
->
apply
(
b_srcGkoVec
.
get
(),
b_dstGkoVec
.
get
());
hyteg
::
petsc
::
createFunctionFromVector
(
...
...
@@ -232,36 +280,9 @@ bool p2p1StokesGinkgoApplyTest( std::shared_ptr< const gko::Executor > exec,
All
);
// compare
err
.
assign
(
{
1.0
,
-
1.0
},
{
hhgDst
,
ginkgoDst
},
level
,
location
);
auto
maxError
=
err
.
uvw
[
0
].
getMaxMagnitude
(
level
);
maxError
=
std
::
max
(
maxError
,
err
.
uvw
[
1
].
getMaxMagnitude
(
level
)
);
if
(
err
.
uvw
.
getDimension
()
==
3
)
{
maxError
=
std
::
max
(
maxError
,
err
.
uvw
[
2
].
getMaxMagnitude
(
level
)
);
}
maxError
=
std
::
max
(
maxError
,
err
.
p
.
getMaxMagnitude
(
level
)
);
success
&=
check_error
(
storage
,
hhgDst
,
ginkgoDst
,
level
,
eps
);
WALBERLA_LOG_INFO_ON_ROOT
(
"Error max Magnitude = "
<<
maxError
<<
" eps: "
<<
eps
);
if
(
writeVTK
)
{
VTKOutput
vtkOutput
(
"../../output"
,
"P2P1StokesGinkgoApplyTest"
,
storage
);
vtkOutput
.
add
(
src
.
uvw
);
vtkOutput
.
add
(
hhgDst
.
uvw
);
vtkOutput
.
add
(
ginkgoDst
.
uvw
);
vtkOutput
.
add
(
err
.
uvw
);
vtkOutput
.
write
(
level
,
0
);
}
if
(
maxError
>
eps
)
{
WALBERLA_LOG_INFO_ON_ROOT
(
"TEST FAILED!"
);
return
false
;
}
else
{
return
true
;
}
return
success
;
}
}
// namespace hyteg
...
...
Write
Preview
Supports
Markdown
0%
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!
Cancel
Please
register
or
sign in
to comment