Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
iwr
amdis
Commits
2eeb5654
Commit
2eeb5654
authored
Nov 21, 2011
by
Thomas Witkowski
Browse files
Work on FETI-DP method.
parent
3509ab94
Changes
3
Hide whitespace changes
Inline
Side-by-side
AMDiS/src/parallel/PetscProblemStat.cc
View file @
2eeb5654
...
...
@@ -89,7 +89,6 @@ namespace AMDiS {
petscSolver
->
fillPetscRhs
(
rhs
);
#if 0
processMemUsage(vm, rss);
MSG("STAGE 2\n");
...
...
AMDiS/src/parallel/PetscSolverFeti.cc
View file @
2eeb5654
...
...
@@ -18,6 +18,7 @@ namespace AMDiS {
using
namespace
std
;
FetiStatisticsData
PetscSolverFeti
::
fetiStatistics
;
#ifdef HAVE_PETSC_DEV
// y = mat * x
...
...
@@ -25,17 +26,20 @@ namespace AMDiS {
{
// S_PiPi = K_PiPi - K_PiB inv(K_BB) K_BPi
double
first
=
MPI
::
Wtime
();
void
*
ctx
;
MatShellGetContext
(
mat
,
&
ctx
);
SchurPrimalData
*
data
=
static_cast
<
SchurPrimalData
*>
(
ctx
);
MatMult
(
*
(
data
->
mat_b_primal
),
x
,
data
->
tmp_vec_b
);
KSPSolve
(
*
(
data
->
ksp_b
),
data
->
tmp_vec_b
,
data
->
tmp_vec_b
);
data
->
fetiSolver
->
solveLocalProblem
(
data
->
tmp_vec_b
,
data
->
tmp_vec_b
);
MatMult
(
*
(
data
->
mat_primal_b
),
data
->
tmp_vec_b
,
data
->
tmp_vec_primal
);
MatMult
(
*
(
data
->
mat_primal_primal
),
x
,
y
);
VecAXPBY
(
y
,
-
1.0
,
1.0
,
data
->
tmp_vec_primal
);
PetscSolverFeti
::
fetiStatistics
.
nSchurPrimalApply
++
;
PetscSolverFeti
::
fetiStatistics
.
timeSchurPrimalApply
+=
MPI
::
Wtime
()
-
first
;
return
0
;
}
...
...
@@ -52,17 +56,25 @@ namespace AMDiS {
// tmp_vec_b0 = inv(K_BB) trans(L) x
MatMultTranspose
(
*
(
data
->
mat_lagrange
),
x
,
data
->
tmp_vec_b0
);
KSPSolve
(
*
(
data
->
ksp_b
),
data
->
tmp_vec_b0
,
data
->
tmp_vec_b0
);
data
->
fetiSolver
->
solveLocalProblem
(
data
->
tmp_vec_b0
,
data
->
tmp_vec_b0
);
// tmp_vec_b1 = inv(K_BB) K_BPi inv(S_PiPi) K_PiB tmp_vec_b0
MatMult
(
*
(
data
->
mat_primal_b
),
data
->
tmp_vec_b0
,
data
->
tmp_vec_primal
);
double
first
=
MPI
::
Wtime
();
KSPSolve
(
*
(
data
->
ksp_schur_primal
),
data
->
tmp_vec_primal
,
data
->
tmp_vec_primal
);
PetscSolverFeti
::
fetiStatistics
.
nSchurPrimalSolve
++
;
PetscSolverFeti
::
fetiStatistics
.
timeSchurPrimalSolve
+=
MPI
::
Wtime
()
-
first
;
MatMult
(
*
(
data
->
mat_b_primal
),
data
->
tmp_vec_primal
,
data
->
tmp_vec_b1
);
// y = L (tmp_vec_b0 + tmp_vec_b1)
VecAXPBY
(
data
->
tmp_vec_b0
,
1.0
,
1.0
,
data
->
tmp_vec_b1
);
MatMult
(
*
(
data
->
mat_lagrange
),
data
->
tmp_vec_b0
,
y
);
PetscSolverFeti
::
fetiStatistics
.
nFetiApply
++
;
return
0
;
}
...
...
@@ -183,7 +195,8 @@ namespace AMDiS {
PetscSolverFeti
::
PetscSolverFeti
()
:
PetscSolver
(),
nComponents
(
-
1
)
nComponents
(
-
1
),
schurPrimalSolver
(
0
)
{
FUNCNAME
(
"PetscSolverFeti::PetscSolverFeti()"
);
...
...
@@ -196,8 +209,14 @@ namespace AMDiS {
}
else
if
(
preconditionerName
==
"lumped"
)
{
fetiPreconditioner
=
FETI_LUMPED
;
}
else
{
ERROR_EXIT
(
"Preconditioner
\"
%s
\"
not available!
\n
"
,
preconditionerName
.
c_str
());
ERROR_EXIT
(
"Preconditioner
\"
%s
\"
not available!
\n
"
,
preconditionerName
.
c_str
());
}
Parameters
::
get
(
"parallel->feti->schur primal solver"
,
schurPrimalSolver
);
TEST_EXIT
(
schurPrimalSolver
==
0
||
schurPrimalSolver
==
1
)
(
"Wrong solver
\"
%d
\"
for the Schur primal complement!
\n
"
,
schurPrimalSolver
);
}
...
...
@@ -492,7 +511,7 @@ namespace AMDiS {
{
FUNCNAME
(
"PetscSolverFeti::createIndeB()"
);
g
lo
b
alIndexB
.
clear
();
lo
c
alIndexB
.
clear
();
DOFAdmin
*
admin
=
meshDistributor
->
getFeSpace
()
->
getAdmin
();
// === To ensure that all interior node on each rank are listen first in ===
...
...
@@ -502,15 +521,15 @@ namespace AMDiS {
for
(
int
i
=
0
;
i
<
admin
->
getUsedSize
();
i
++
)
if
(
admin
->
isDofFree
(
i
)
==
false
&&
primals
.
count
(
i
)
==
0
)
if
(
duals
.
count
(
i
)
==
0
&&
primals
.
count
(
i
)
==
0
)
g
lo
b
alIndexB
[
i
]
=
-
1
;
lo
c
alIndexB
[
i
]
=
-
1
;
// === Get correct index for all interior nodes. ===
nLocalInterior
=
0
;
for
(
DofMapping
::
iterator
it
=
g
lo
b
alIndexB
.
begin
();
it
!=
g
lo
b
alIndexB
.
end
();
++
it
)
{
it
->
second
=
nLocalInterior
+
rStartB
;
for
(
DofMapping
::
iterator
it
=
lo
c
alIndexB
.
begin
();
it
!=
lo
c
alIndexB
.
end
();
++
it
)
{
it
->
second
=
nLocalInterior
;
nLocalInterior
++
;
}
nLocalDuals
=
duals
.
size
();
...
...
@@ -524,7 +543,7 @@ namespace AMDiS {
for
(
DofIndexSet
::
iterator
it
=
duals
.
begin
();
it
!=
duals
.
end
();
++
it
)
g
lo
b
alIndexB
[
*
it
]
=
globalDualIndex
[
*
it
];
lo
c
alIndexB
[
*
it
]
=
globalDualIndex
[
*
it
]
-
rStartB
;
}
...
...
@@ -590,31 +609,47 @@ namespace AMDiS {
{
FUNCNAME
(
"PetscSolverFeti::createSchurPrimal()"
);
schurPrimalData
.
mat_primal_primal
=
&
mat_primal_primal
;
schurPrimalData
.
mat_primal_b
=
&
mat_primal_b
;
schurPrimalData
.
mat_b_primal
=
&
mat_b_primal
;
schurPrimalData
.
ksp_b
=
&
ksp_b
;
MSG
(
"MAT SCHUR PRIMAL SOLVER = %d
\n
"
,
schurPrimalSolver
);
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankB
*
nComponents
,
nOverallB
*
nComponents
,
&
(
schurPrimalData
.
tmp_vec_b
));
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
&
(
schurPrimalData
.
tmp_vec_primal
));
if
(
schurPrimalSolver
==
0
)
{
schurPrimalData
.
mat_primal_primal
=
&
mat_primal_primal
;
schurPrimalData
.
mat_primal_b
=
&
mat_primal_b
;
schurPrimalData
.
mat_b_primal
=
&
mat_b_primal
;
schurPrimalData
.
fetiSolver
=
this
;
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankB
*
nComponents
,
nOverallB
*
nComponents
,
&
(
schurPrimalData
.
tmp_vec_b
));
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
&
(
schurPrimalData
.
tmp_vec_primal
));
MatCreateShell
(
PETSC_COMM_WORLD
,
nRankPrimals
*
nComponents
,
nRankPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
&
schurPrimalData
,
&
mat_schur_primal
);
MatShellSetOperation
(
mat_schur_primal
,
MATOP_MULT
,
(
void
(
*
)(
void
))
petscMultMatSchurPrimal
);
KSPCreate
(
PETSC_COMM_WORLD
,
&
ksp_schur_primal
);
KSPSetOperators
(
ksp_schur_primal
,
mat_schur_primal
,
mat_schur_primal
,
SAME_NONZERO_PATTERN
);
KSPSetOptionsPrefix
(
ksp_schur_primal
,
"solver_sp_"
);
KSPSetFromOptions
(
ksp_schur_primal
);
}
else
{
MatDuplicate
(
mat_primal_primal
,
MAT_COPY_VALUES
,
&
mat_schur_primal
);
Mat
tmp0
,
tmp1
;
MatMatSolve
(
mat_b_b
,
mat_b_primal
,
tmp0
);
MatMatMult
(
mat_primal_b
,
tmp0
,
MAT_INITIAL_MATRIX
,
PETSC_DEFAULT
,
&
tmp1
);
MatCreateShell
(
PETSC_COMM_WORLD
,
nRankPrimals
*
nComponents
,
nRankPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
&
schurPrimalData
,
&
mat_schur_primal
);
MatShellSetOperation
(
mat_schur_primal
,
MATOP_MULT
,
(
void
(
*
)(
void
))
petscMultMatSchurPrimal
);
KSPCreate
(
PETSC_COMM_WORLD
,
&
ksp_schur_primal
);
KSPSetOperators
(
ksp_schur_primal
,
mat_schur_primal
,
mat_schur_primal
,
SAME_NONZERO_PATTERN
);
KSPSetOptionsPrefix
(
ksp_schur_primal
,
"solver_sp_"
);
KSPSetFromOptions
(
ksp_schur_primal
);
MatDestroy
(
&
tmp0
);
MatDestroy
(
&
tmp1
);
MSG
(
"EXIT!
\n
"
);
exit
(
0
);
}
}
...
...
@@ -625,7 +660,7 @@ namespace AMDiS {
schurPrimalData
.
mat_primal_primal
=
PETSC_NULL
;
schurPrimalData
.
mat_primal_b
=
PETSC_NULL
;
schurPrimalData
.
mat_b_primal
=
PETSC_NULL
;
schurPrimalData
.
ksp_b
=
PETSC_
NULL
;
schurPrimalData
.
fetiSolver
=
NULL
;
VecDestroy
(
&
schurPrimalData
.
tmp_vec_b
);
VecDestroy
(
&
schurPrimalData
.
tmp_vec_primal
);
...
...
@@ -645,7 +680,7 @@ namespace AMDiS {
fetiData
.
mat_primal_b
=
&
mat_primal_b
;
fetiData
.
mat_b_primal
=
&
mat_b_primal
;
fetiData
.
mat_lagrange
=
&
mat_lagrange
;
fetiData
.
ksp_b
=
&
ksp_b
;
fetiData
.
fetiSolver
=
this
;
fetiData
.
ksp_schur_primal
=
&
ksp_schur_primal
;
VecCreateMPI
(
PETSC_COMM_WORLD
,
...
...
@@ -681,7 +716,8 @@ namespace AMDiS {
switch
(
fetiPreconditioner
)
{
case
FETI_DIRICHLET
:
KSPCreate
(
PETSC_COMM_SELF
,
&
ksp_interior
);
KSPSetOperators
(
ksp_interior
,
mat_interior_interior
,
mat_interior_interior
,
SAME_NONZERO_PATTERN
);
KSPSetOperators
(
ksp_interior
,
mat_interior_interior
,
mat_interior_interior
,
SAME_NONZERO_PATTERN
);
KSPSetOptionsPrefix
(
ksp_interior
,
"solver_interior_"
);
KSPSetFromOptions
(
ksp_interior
);
...
...
@@ -736,7 +772,7 @@ namespace AMDiS {
fetiData
.
mat_primal_b
=
PETSC_NULL
;
fetiData
.
mat_b_primal
=
PETSC_NULL
;
fetiData
.
mat_lagrange
=
PETSC_NULL
;
fetiData
.
ksp_b
=
PETSC_
NULL
;
fetiData
.
fetiSolver
=
NULL
;
fetiData
.
ksp_schur_primal
=
PETSC_NULL
;
VecDestroy
(
&
fetiData
.
tmp_vec_b0
);
...
...
@@ -844,9 +880,9 @@ namespace AMDiS {
for
(
int
i
=
0
;
i
<
nComponents
;
i
++
)
{
DOFVector
<
double
>&
dofVec
=
*
(
vec
.
getDOFVector
(
i
));
for
(
DofMapping
::
iterator
it
=
g
lo
b
alIndexB
.
begin
();
it
!=
g
lo
b
alIndexB
.
end
();
++
it
)
{
int
petscIndex
=
(
it
->
second
-
rStartB
)
*
nComponents
+
i
;
for
(
DofMapping
::
iterator
it
=
lo
c
alIndexB
.
begin
();
it
!=
lo
c
alIndexB
.
end
();
++
it
)
{
int
petscIndex
=
it
->
second
*
nComponents
+
i
;
dofVec
[
it
->
first
]
=
localSolB
[
petscIndex
];
}
...
...
@@ -886,9 +922,12 @@ namespace AMDiS {
int
nRowsInterior
=
nLocalInterior
*
nComponents
;
int
nRowsDual
=
nLocalDuals
*
nComponents
;
MatCreateMPIAIJ
(
PETSC_COMM_WORLD
,
nRowsRankB
,
nRowsRankB
,
nRowsOverallB
,
nRowsOverallB
,
30
,
PETSC_NULL
,
0
,
PETSC_NULL
,
&
mat_b_b
);
// MatCreateMPIAIJ(PETSC_COMM_WORLD,
// nRowsRankB, nRowsRankB, nRowsOverallB, nRowsOverallB,
// 30, PETSC_NULL, 0, PETSC_NULL, &mat_b_b);
MatCreateSeqAIJ
(
PETSC_COMM_SELF
,
nRowsRankB
,
nRowsRankB
,
30
,
PETSC_NULL
,
&
mat_b_b
);
MatCreateMPIAIJ
(
PETSC_COMM_WORLD
,
nRowsRankPrimal
,
nRowsRankPrimal
,
...
...
@@ -1004,10 +1043,11 @@ namespace AMDiS {
}
else
{
// Column is not a primal variable.
TEST_EXIT_DBG
(
g
lo
b
alIndexB
.
count
(
col
(
*
icursor
)))
TEST_EXIT_DBG
(
lo
c
alIndexB
.
count
(
col
(
*
icursor
)))
(
"No global B index for DOF %d!
\n
"
,
col
(
*
icursor
));
int
colIndex
=
globalIndexB
[
col
(
*
icursor
)]
*
nComponents
+
j
;
int
colIndex
=
(
localIndexB
[
col
(
*
icursor
)]
+
rStartB
)
*
nComponents
+
j
;
if
(
rowPrimal
)
{
colsOther
.
push_back
(
colIndex
);
...
...
@@ -1023,33 +1063,31 @@ namespace AMDiS {
// === For preconditioner ===
if
(
!
rowPrimal
&&
!
colPrimal
)
{
int
rowIndex
=
g
lo
b
alIndexB
[
*
cursor
]
-
rStartB
;
int
colIndex
=
g
lo
b
alIndexB
[
col
(
*
icursor
)]
-
rStartB
;
int
rowIndex
=
lo
c
alIndexB
[
*
cursor
];
int
colIndex
=
lo
c
alIndexB
[
col
(
*
icursor
)];
if
(
rowIndex
<
nLocalInterior
)
{
if
(
colIndex
<
nLocalInterior
)
{
int
colIndex2
=
(
globalIndexB
[
col
(
*
icursor
)]
-
rStartB
)
*
nComponents
+
j
;
int
colIndex2
=
localIndexB
[
col
(
*
icursor
)]
*
nComponents
+
j
;
colsLocal
.
push_back
(
colIndex2
);
valuesLocal
.
push_back
(
value
(
*
icursor
));
}
else
{
int
colIndex2
=
(
globalIndexB
[
col
(
*
icursor
)]
-
rStartB
-
nLocalInterior
)
*
nComponents
+
j
;
int
colIndex2
=
(
localIndexB
[
col
(
*
icursor
)]
-
nLocalInterior
)
*
nComponents
+
j
;
colsLocalOther
.
push_back
(
colIndex2
);
valuesLocalOther
.
push_back
(
value
(
*
icursor
));
}
}
else
{
if
(
colIndex
<
nLocalInterior
)
{
int
colIndex2
=
(
globalIndexB
[
col
(
*
icursor
)]
-
rStartB
)
*
nComponents
+
j
;
int
colIndex2
=
localIndexB
[
col
(
*
icursor
)]
*
nComponents
+
j
;
colsLocalOther
.
push_back
(
colIndex2
);
valuesLocalOther
.
push_back
(
value
(
*
icursor
));
}
else
{
int
colIndex2
=
(
globalIndexB
[
col
(
*
icursor
)]
-
rStartB
-
nLocalInterior
)
*
nComponents
+
j
;
int
colIndex2
=
(
localIndexB
[
col
(
*
icursor
)]
-
nLocalInterior
)
*
nComponents
+
j
;
colsLocal
.
push_back
(
colIndex2
);
valuesLocal
.
push_back
(
value
(
*
icursor
));
...
...
@@ -1072,10 +1110,13 @@ namespace AMDiS {
MatSetValues
(
mat_primal_b
,
1
,
&
rowIndex
,
colsOther
.
size
(),
&
(
colsOther
[
0
]),
&
(
valuesOther
[
0
]),
ADD_VALUES
);
}
else
{
TEST_EXIT_DBG
(
g
lo
b
alIndexB
.
count
(
*
cursor
))
TEST_EXIT_DBG
(
lo
c
alIndexB
.
count
(
*
cursor
))
(
"Should not happen!
\n
"
);
int
rowIndex
=
globalIndexB
[
*
cursor
]
*
nComponents
+
i
;
// int rowIndex = (localIndexB[*cursor] + rStartB) * nComponents + i;
int
rowIndex
=
localIndexB
[
*
cursor
]
*
nComponents
+
i
;
for
(
unsigned
int
k
=
0
;
k
<
cols
.
size
();
k
++
)
cols
[
k
]
-=
rStartB
*
nComponents
;
MatSetValues
(
mat_b_b
,
1
,
&
rowIndex
,
cols
.
size
(),
&
(
cols
[
0
]),
&
(
values
[
0
]),
ADD_VALUES
);
...
...
@@ -1090,11 +1131,10 @@ namespace AMDiS {
switch
(
fetiPreconditioner
)
{
case
FETI_DIRICHLET
:
{
int
rowIndex
=
g
lo
b
alIndexB
[
*
cursor
]
-
rStartB
;
int
rowIndex
=
lo
c
alIndexB
[
*
cursor
];
if
(
rowIndex
<
nLocalInterior
)
{
int
rowIndex2
=
(
globalIndexB
[
*
cursor
]
-
rStartB
)
*
nComponents
+
i
;
int
rowIndex2
=
localIndexB
[
*
cursor
]
*
nComponents
+
i
;
MatSetValues
(
mat_interior_interior
,
1
,
&
rowIndex2
,
colsLocal
.
size
(),
&
(
colsLocal
[
0
]),
&
(
valuesLocal
[
0
]),
INSERT_VALUES
);
...
...
@@ -1104,7 +1144,7 @@ namespace AMDiS {
&
(
colsLocalOther
[
0
]),
&
(
valuesLocalOther
[
0
]),
INSERT_VALUES
);
}
else
{
int
rowIndex2
=
(
g
lo
b
alIndexB
[
*
cursor
]
-
rStartB
-
nLocalInterior
)
*
nComponents
+
i
;
(
lo
c
alIndexB
[
*
cursor
]
-
nLocalInterior
)
*
nComponents
+
i
;
MatSetValues
(
mat_duals_duals
,
1
,
&
rowIndex2
,
colsLocal
.
size
(),
&
(
colsLocal
[
0
]),
&
(
valuesLocal
[
0
]),
INSERT_VALUES
);
...
...
@@ -1119,11 +1159,11 @@ namespace AMDiS {
case
FETI_LUMPED
:
{
int
rowIndex
=
g
lo
b
alIndexB
[
*
cursor
]
-
rStartB
;
int
rowIndex
=
lo
c
alIndexB
[
*
cursor
];
if
(
rowIndex
>=
nLocalInterior
)
{
int
rowIndex2
=
(
g
lo
b
alIndexB
[
*
cursor
]
-
rStartB
-
nLocalInterior
)
*
nComponents
+
i
;
(
lo
c
alIndexB
[
*
cursor
]
-
nLocalInterior
)
*
nComponents
+
i
;
MatSetValues
(
mat_duals_duals
,
1
,
&
rowIndex2
,
colsLocal
.
size
(),
&
(
colsLocal
[
0
]),
&
(
valuesLocal
[
0
]),
INSERT_VALUES
);
...
...
@@ -1186,7 +1226,7 @@ namespace AMDiS {
// === Create solver for the non primal (thus local) variables. ===
KSPCreate
(
PETSC_COMM_
WORLD
,
&
ksp_b
);
KSPCreate
(
PETSC_COMM_
SELF
,
&
ksp_b
);
KSPSetOperators
(
ksp_b
,
mat_b_b
,
mat_b_b
,
SAME_NONZERO_PATTERN
);
KSPSetOptionsPrefix
(
ksp_b
,
"solver_b_"
);
KSPSetFromOptions
(
ksp_b
);
...
...
@@ -1200,7 +1240,8 @@ namespace AMDiS {
int
nComponents
=
vec
->
getSize
();
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankB
*
nComponents
,
nOverallB
*
nComponents
,
&
f_b
);
nRankB
*
nComponents
,
nOverallB
*
nComponents
,
&
f_b
);
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankPrimals
*
nComponents
,
nOverallPrimals
*
nComponents
,
&
f_primal
);
...
...
@@ -1217,12 +1258,11 @@ namespace AMDiS {
double
value
=
*
dofIt
;
VecSetValues
(
f_primal
,
1
,
&
index
,
&
value
,
ADD_VALUES
);
}
else
{
TEST_EXIT_DBG
(
g
lo
b
alIndexB
.
count
(
index
))
TEST_EXIT_DBG
(
lo
c
alIndexB
.
count
(
index
))
(
"Should not happen!
\n
"
);
index
=
globalIndexB
[
index
]
*
nComponents
+
i
;
double
value
=
*
dofIt
;
VecSetValues
(
f_b
,
1
,
&
index
,
&
value
,
ADD_VALUES
);
index
=
(
localIndexB
[
index
]
+
rStartB
)
*
nComponents
+
i
;
VecSetValue
(
f_b
,
index
,
*
dofIt
,
INSERT_VALUES
);
}
}
}
...
...
@@ -1234,134 +1274,38 @@ namespace AMDiS {
VecAssemblyEnd
(
f_primal
);
}
void
PetscSolverFeti
::
solveFetiMatrix
(
SystemVector
&
vec
)
{
FUNCNAME
(
"PetscSolverFeti::solveFetiMatrix()"
);
Mat
mat_lagrange_transpose
;
MatTranspose
(
mat_lagrange
,
MAT_INITIAL_MATRIX
,
&
mat_lagrange_transpose
);
// === Create nested matrix which will contain the overall FETI system. ===
Mat
A
;
Mat
nestedA
[
3
][
3
];
nestedA
[
0
][
0
]
=
mat_b_b
;
nestedA
[
0
][
1
]
=
mat_b_primal
;
nestedA
[
0
][
2
]
=
mat_lagrange_transpose
;
nestedA
[
1
][
0
]
=
mat_primal_b
;
nestedA
[
1
][
1
]
=
mat_primal_primal
;
nestedA
[
1
][
2
]
=
PETSC_NULL
;
nestedA
[
2
][
0
]
=
mat_lagrange
;
nestedA
[
2
][
1
]
=
PETSC_NULL
;
nestedA
[
2
][
2
]
=
PETSC_NULL
;
MatCreateNest
(
PETSC_COMM_WORLD
,
3
,
PETSC_NULL
,
3
,
PETSC_NULL
,
&
(
nestedA
[
0
][
0
]),
&
A
);
MatAssemblyBegin
(
A
,
MAT_FINAL_ASSEMBLY
);
MatAssemblyEnd
(
A
,
MAT_FINAL_ASSEMBLY
);
void
PetscSolverFeti
::
solveLocalProblem
(
Vec
&
rhs
,
Vec
&
sol
)
{
FUNCNAME
(
"PetscSolverFeti::solveLocalProblem()"
);
Vec
tmp
;
VecCreateSeq
(
PETSC_COMM_SELF
,
nRankB
*
nComponents
,
&
tmp
);
PetscScalar
*
tmpValues
;
VecGetArray
(
tmp
,
&
tmpValues
);
int
nRankNest
=
(
nRankB
+
nRankPrimals
+
nRankLagrange
)
*
nComponents
;
int
nOverallNest
=
(
nOverallB
+
nOverallPrimals
+
nOverallLagrange
)
*
nComponents
;
int
rStartNest
=
(
rStartB
+
rStartPrimals
+
rStartLagrange
)
*
nComponents
;
{
// === Test some matrix sizes. ===
int
matRow
,
matCol
;
MatGetLocalSize
(
A
,
&
matRow
,
&
matCol
);
TEST_EXIT_DBG
(
matRow
==
nRankNest
)(
"Should not happen!
\n
"
);
mpi
::
globalAdd
(
matRow
);
TEST_EXIT_DBG
(
matRow
==
nOverallNest
)(
"Should not happen!
\n
"
);
MatGetOwnershipRange
(
A
,
&
matRow
,
&
matCol
);
TEST_EXIT_DBG
(
matRow
==
rStartNest
)(
"Should not happen!
\n
"
);
}
// === Create rhs and solution vectors for the overall FETI system. ===
Vec
f
,
b
;
VecCreateMPI
(
PETSC_COMM_WORLD
,
nRankNest
,
nOverallNest
,
&
f
);
VecDuplicate
(
f
,
&
b
);
// === Fill rhs vector by coping the primal and non primal PETSc vectors. ===
PetscScalar
*
local_f_b
;
VecGetArray
(
f_b
,
&
local_f_b
);
PetscScalar
*
local_f_primal
;
VecGetArray
(
f_primal
,
&
local_f_primal
);
{
int
size
;
VecGetLocalSize
(
f_b
,
&
size
);
TEST_EXIT_DBG
(
size
==
nRankB
*
nComponents
)(
"Should not happen!
\n
"
);
VecGetLocalSize
(
f_primal
,
&
size
);
TEST_EXIT_DBG
(
size
==
nRankPrimals
*
nComponents
)(
"Should not happen!
\n
"
);
}
PetscScalar
*
local_f
;
VecGetArray
(
f
,
&
local_f
);
PetscScalar
*
rhsValues
;
VecGetArray
(
rhs
,
&
rhsValues
);
int
index
=
0
;
for
(
int
i
=
0
;
i
<
nRankB
*
nComponents
;
i
++
)
local_f
[
index
++
]
=
local_f_b
[
i
];
for
(
int
i
=
0
;
i
<
nRankPrimals
*
nComponents
;
i
++
)
local_f
[
index
++
]
=
local_f_primal
[
i
];
tmpValues
[
i
]
=
rhsValues
[
i
];
VecRestoreArray
(
f
,
&
local_f
);
VecRestoreArray
(
f_b
,
&
local_f_b
);
VecRestoreArray
(
f_primal
,
&
local_f_primal
);
// === Create solver and solve the overall FETI system. ===
KSP
ksp
;
KSPCreate
(
PETSC_COMM_WORLD
,
&
ksp
);
KSPSetOperators
(
ksp
,
A
,
A
,
SAME_NONZERO_PATTERN
);
KSPSetFromOptions
(
ksp
);
VecRestoreArray
(
rhs
,
&
rhsValues
);
VecRestoreArray
(
tmp
,
&
tmpValues
);
KSPSolve
(
ksp_b
,
tmp
,
tmp
);
KSPSolve
(
ksp
,
f
,
b
);
VecGetArray
(
tmp
,
&
tmpValues
);
PetscScalar
*
solValues
;
VecGetArray
(
sol
,
&
solValues
);
for
(
int
i
=
0
;
i
<
nRankB
*
nComponents
;
i
++
)
solValues
[
i
]
=
tmpValues
[
i
];
// === Reconstruct FETI solution vectors. ===
Vec
u_b
,
u_primal
;
VecDuplicate
(
f_b
,
&
u_b
);
VecDuplicate
(
f_primal
,
&
u_primal
);
VecRestoreArray
(
sol
,
&
solValues
);
VecRestoreArray
(
tmp
,
&
tmpValues
);
PetscScalar
*
local_b
;
VecGetArray
(
b
,
&
local_b
);
PetscScalar
*
local_u_b
;
VecGetArray
(
u_b
,
&
local_u_b
);
PetscScalar
*
local_u_primal
;
VecGetArray
(
u_primal
,
&
local_u_primal
);
index
=
0
;
for
(
int
i
=
0
;
i
<
nRankB
*
nComponents
;
i
++
)
local_u_b
[
i
]
=
local_b
[
index
++
];
for
(
int
i
=
0
;
i
<
nRankPrimals
*
nComponents
;
i
++
)
local_u_primal
[
i
]
=
local_b
[
index
++
];
VecRestoreArray
(
f
,
&
local_b
);
VecRestoreArray
(
u_b
,
&
local_u_b
);
VecRestoreArray
(
u_primal
,
&
local_u_primal
);
recoverSolution
(
u_b
,
u_primal
,
vec
);
VecDestroy
(
&
u_b
);
VecDestroy
(
&
u_primal
);
VecDestroy
(
&
b
);
VecDestroy
(
&
f
);
KSPDestroy
(
&
ksp
);
VecDestroy
(
&
tmp
);
}
...
...
@@ -1376,8 +1320,8 @@ namespace AMDiS {
Vec
tmp_b0
,
tmp_b1
,
tmp_lagrange0
,
tmp_primal0
,
tmp_primal1
;
MatGetVecs
(
mat_lagrange
,
PETSC_NULL
,
&
tmp_lagrange0
);
MatGetVecs
(
mat_lagrange
,
PETSC_NULL
,
&
vec_rhs
);
MatGetVecs
(
mat_b_b
,
PETSC_NULL
,
&
tmp_b0
);
MatGetVecs
(
mat_b_b
,
PETSC_NULL
,
&
tmp_b1
);
VecDuplicate
(
f_b
,
&
tmp_b0
);
VecDuplicate
(
f_b
,
&
tmp_b1
);
MatGetVecs
(
mat_primal_primal
,
PETSC_NULL
,
&
tmp_primal0
);
MatGetVecs
(
mat_primal_primal
,
PETSC_NULL
,
&
tmp_primal1
);
...
...
@@ -1387,7 +1331,8 @@ namespace AMDiS {
// d = L inv(K_BB) f_B - L inv(K_BB) K_BPi inv(S_PiPi) [f_Pi - K_PiB inv(K_BB) f_B]
// vec_rhs = L * inv(K_BB) * f_B
KSPSolve
(
ksp_b
,
f_b
,
tmp_b0
);
solveLocalProblem
(
f_b
,
tmp_b0
);
MatMult
(
mat_lagrange
,
tmp_b0
,
vec_rhs
);
// tmp_primal0 = M_PiB * inv(K_BB) * f_B
...
...
@@ -1397,11 +1342,15 @@ namespace AMDiS {
VecAXPBY
(
tmp_primal0
,
1.0
,
-
1.0
,
f_primal
);
// tmp_primal0 = inv(S_PiPi) (f_Pi - M_PiB * inv(K_BB) * f_B)
double
first
=
MPI
::
Wtime
();
KSPSolve
(
ksp_schur_primal
,
tmp_primal0
,
tmp_primal0
);
PetscSolverFeti
::
fetiStatistics
.
nSchurPrimalSolve
++
;
PetscSolverFeti
::
fetiStatistics
.
timeSchurPrimalSolve
+=
MPI
::
Wtime
()
-
first
;
//
MatMult
(
mat_b_primal
,
tmp_primal0
,
tmp_b0
);
KSPSolve
(
ksp_b
,
tmp_b0
,
tmp_b0
);
solveLocalProblem
(
tmp_b0
,
tmp_b0
);
MatMult
(
mat_lagrange
,
tmp_b0
,
tmp_lagrange0
);
//
...
...
@@ -1410,23 +1359,26 @@ namespace AMDiS {
// === Solve with FETI-DP operator. ===
first
=
MPI
::
Wtime
();
KSPSolve
(
ksp_feti
,
vec_rhs
,
vec_rhs
);