GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 82.0% 123 / 0 / 150
Functions: 55.6% 5 / 0 / 9
Branches: 34.5% 194 / 0 / 563

mform/m_mform_coupled_solver.F90
Line Branch Exec Source
1 !> @brief Module containing the linear solver for coupled block systems of m-form equations
2 module m_mform_coupled_solver
3 use m_common, only: wp, VERBOSITY_WARN_ON_FAILURE
4 use petscis
5 use m_mform_basis, only: MFormSpace
6 use m_mform_constraint_global, only: MFormConstraint
7 use m_mform_matrix, only: AbstractMatrix
8 use m_mform_solver, only: AbstractSolver, get_constrained_petsc_matrix
9 use m_mform_solver, only: SolverInitOptions, SolverSolveOptions, SolverInitTraits
10 #include "petsc.fi"
11 #include "timer.fi"
12
13 implicit none
14 private
15
16 public :: MatrixHolder, CoupledSolver
17
18 !> @brief Wrapper type that allows passing heterogeneous polymorphic matrix blocks.
19 !>
20 !> The wrapped matrix is a non-owning copy of the object state and should not call
21 !> matrix-specific destroy; the original matrix object owns the PETSc resources.
22 type MatrixHolder
23 class(AbstractMatrix), allocatable :: elt
24 contains
25 procedure :: init => init_matrix_holder
26 procedure :: destroy => destroy_matrix_holder
27 end type
28
29 !> @brief Solver for coupled block systems assembled into a PETSc nested matrix
30 type, extends(AbstractSolver) :: CoupledSolver
31 integer :: nr_blocks = 0
32 type(MFormSpace), allocatable :: spaces(:)
33 type(MFormConstraint), allocatable :: constraints(:)
34 ! Stored row-major as [(1,1), (1,2), ..., (n,n)] for MatCreateNest.
35 Mat, allocatable :: block_mats(:)
36 contains
37 procedure :: init => init_coupled_solver
38 procedure :: solve => solve_coupled_solver
39 procedure :: destroy => destroy_coupled_solver
40 end type
41
42 contains
43
44 !> @brief Initialize a matrix holder from any AbstractMatrix-derived object
45 64 subroutine init_matrix_holder(this, mat)
46 class(MatrixHolder), intent(inout) :: this
47 class(AbstractMatrix), intent(in) :: mat
48
49 32 call this%destroy()
50
2/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 32 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 32 times.
32 allocate (this%elt, source=mat)
51 32 end subroutine init_matrix_holder
52
53 !> @brief Destroy a matrix holder
54 64 subroutine destroy_matrix_holder(this)
55 class(MatrixHolder), intent(inout) :: this
56
57
3/4
✓ Branch 2 → 3 taken 32 times.
✓ Branch 2 → 7 taken 32 times.
✓ Branch 3 → 4 taken 32 times.
✗ Branch 3 → 6 not taken.
96 if (allocated(this%elt)) deallocate (this%elt)
58 64 end subroutine destroy_matrix_holder
59
60 !> @brief Initialize the coupled solver for a square block system
61
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 8 times.
8 subroutine init_coupled_solver(this, amat_blocks, constraint1, constraint2, constraint3, coord_transform, options)
62 use m_mform_basis, only: size
63 use m_mform_constraint_abstract, only: MFormConstraintLocal
64 use m_coord_transform_abstract, only: CoordTransformAbstract
65 use m_mform_solver, only: create_ksp
66
67 class(CoupledSolver), intent(inout) :: this
68 type(MatrixHolder), intent(in) :: amat_blocks(:, :)
69 class(MFormConstraintLocal), optional, intent(in) :: constraint1, constraint2, constraint3
70 class(CoordTransformAbstract), optional, intent(in) :: coord_transform
71 type(SolverInitOptions), optional, intent(in) :: options
72
73 PC :: pc
74 integer :: i, j, n_blocks, ierr, idx, default_max_iter
75 logical :: has_constraints, coupled_is_symmetric, coupled_is_spd
76 type(SolverInitTraits) :: traits
77
78 TIMER_DECL(t_total)
79 TIMER_INIT_START(t_total, "CoupledSolver::init")
80
81 8 call this%destroy()
82
83
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 8 times.
8 if (size(amat_blocks, 1) /= size(amat_blocks, 2)) then
84 error stop "CoupledSolver::init_coupled_solver: coupled block matrix must be square."
85 end if
86
87 8 n_blocks = size(amat_blocks, 1)
88
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 8 times.
8 if (n_blocks <= 0) then
89 error stop "CoupledSolver::init_coupled_solver: coupled block matrix must be non-empty."
90 end if
91
92
2/2
✓ Branch 9 → 10 taken 16 times.
✓ Branch 9 → 16 taken 8 times.
24 do i = 1, n_blocks
93
2/2
✓ Branch 10 → 11 taken 32 times.
✓ Branch 10 → 14 taken 16 times.
56 do j = 1, n_blocks
94
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 32 times.
48 if (.not. allocated(amat_blocks(i, j)%elt)) then
95 error stop "CoupledSolver::init_coupled_solver: all matrix holders must be initialized."
96 end if
97 end do
98 end do
99
100 8 this%nr_blocks = n_blocks
101
8/14
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 8 times.
✓ Branch 19 → 18 taken 8 times.
✗ Branch 19 → 20 not taken.
✓ Branch 20 → 21 taken 8 times.
✗ Branch 20 → 22 not taken.
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 24 taken 8 times.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 8 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 28 taken 8 times.
✓ Branch 29 → 30 taken 16 times.
✓ Branch 29 → 31 taken 8 times.
40 allocate (this%spaces(n_blocks))
102
103
2/2
✓ Branch 32 → 33 taken 16 times.
✓ Branch 32 → 41 taken 8 times.
24 do i = 1, n_blocks
104
4/8
✓ Branch 33 → 34 taken 16 times.
✗ Branch 33 → 37 not taken.
✓ Branch 34 → 35 taken 16 times.
✗ Branch 34 → 36 not taken.
✓ Branch 37 → 38 taken 16 times.
✗ Branch 37 → 40 not taken.
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 40 taken 16 times.
24 this%spaces(i) = amat_blocks(i, i)%elt%space_col
105 end do
106
107
2/2
✓ Branch 42 → 43 taken 16 times.
✓ Branch 42 → 53 taken 8 times.
24 do i = 1, n_blocks
108
2/2
✓ Branch 43 → 44 taken 32 times.
✓ Branch 43 → 51 taken 16 times.
56 do j = 1, n_blocks
109
1/2
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 32 times.
32 if (amat_blocks(i, j)%elt%space_row%m /= this%spaces(i)%m) then
110 error stop "CoupledSolver::init_coupled_solver: inconsistent row m-form space across a block row."
111 end if
112
1/2
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 32 times.
32 if (amat_blocks(i, j)%elt%space_col%m /= this%spaces(j)%m) then
113 error stop "CoupledSolver::init_coupled_solver: inconsistent column m-form space across a block column."
114 end if
115
116
1/2
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 32 times.
48 if (amat_blocks(i, j)%elt%space_col%m /= amat_blocks(j, i)%elt%space_row%m) then
117 error stop "CoupledSolver::init_coupled_solver: coupled block dimensions are not mutually compatible."
118 end if
119 end do
120 end do
121
122
2/12
✓ Branch 54 → 55 taken 8 times.
✗ Branch 54 → 56 not taken.
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 60 taken 8 times.
✗ Branch 56 → 57 not taken.
✗ Branch 56 → 58 not taken.
✗ Branch 57 → 58 not taken.
✗ Branch 57 → 60 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 58 → 104 not taken.
✗ Branch 59 → 60 not taken.
✗ Branch 59 → 104 not taken.
8 has_constraints = present(constraint1) .or. present(constraint2) .or. present(constraint3)
123 if (has_constraints) then
124
14/22
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 8 times.
✓ Branch 62 → 61 taken 8 times.
✗ Branch 62 → 63 not taken.
✓ Branch 63 → 64 taken 8 times.
✗ Branch 63 → 65 not taken.
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 8 times.
✗ Branch 67 → 68 not taken.
✓ Branch 67 → 69 taken 8 times.
✗ Branch 69 → 70 not taken.
✓ Branch 69 → 71 taken 8 times.
✓ Branch 72 → 73 taken 40 times.
✓ Branch 72 → 74 taken 8 times.
✓ Branch 75 → 76 taken 16 times.
✓ Branch 75 → 86 taken 8 times.
✗ Branch 76 → 77 not taken.
✓ Branch 76 → 78 taken 16 times.
✓ Branch 80 → 81 taken 80 times.
✓ Branch 80 → 85 taken 16 times.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 80 times.
160 allocate (this%constraints(n_blocks))
125
2/2
✓ Branch 87 → 88 taken 16 times.
✓ Branch 87 → 103 taken 8 times.
24 do j = 1, n_blocks
126 16 call this%constraints(j)%init(this%spaces(j))
127
2/4
✓ Branch 89 → 90 taken 16 times.
✗ Branch 89 → 93 not taken.
✓ Branch 90 → 91 taken 16 times.
✗ Branch 90 → 93 not taken.
16 if (present(constraint1)) call this%constraints(j)%insert(constraint1, coord_transform=coord_transform)
128
2/4
✓ Branch 93 → 94 taken 16 times.
✗ Branch 93 → 97 not taken.
✓ Branch 94 → 95 taken 16 times.
✗ Branch 94 → 97 not taken.
16 if (present(constraint2)) call this%constraints(j)%insert(constraint2, coord_transform=coord_transform)
129
1/4
✗ Branch 97 → 98 not taken.
✓ Branch 97 → 101 taken 16 times.
✗ Branch 98 → 99 not taken.
✗ Branch 98 → 101 not taken.
16 if (present(constraint3)) call this%constraints(j)%insert(constraint3, coord_transform=coord_transform)
130 24 call this%constraints(j)%assemble()
131 end do
132 end if
133
134 8 this%options = SolverInitOptions()
135
1/2
✓ Branch 105 → 106 taken 8 times.
✗ Branch 105 → 107 not taken.
8 if (present(options)) this%options = options
136 coupled_is_symmetric = .true.
137 coupled_is_spd = .false.
138
2/2
✓ Branch 108 → 109 taken 16 times.
✓ Branch 108 → 116 taken 8 times.
24 do i = 1, n_blocks
139
2/2
✓ Branch 109 → 110 taken 32 times.
✓ Branch 109 → 114 taken 16 times.
56 do j = 1, n_blocks
140
4/4
✓ Branch 110 → 111 taken 16 times.
✓ Branch 110 → 112 taken 16 times.
✓ Branch 111 → 112 taken 8 times.
✓ Branch 111 → 113 taken 8 times.
48 coupled_is_symmetric = coupled_is_symmetric .and. amat_blocks(i, j)%elt%is_symmetric
141 end do
142 end do
143
144 8 traits%is_symmetric = coupled_is_symmetric
145 traits%is_spd = coupled_is_spd
146 8 traits%is_parallel = this%spaces(1)%tp_spaces(1)%domain%nr_ranks > 1
147 traits%is_diffdiff = .false.
148 traits%m_form = -1
149 8 traits%allow_ams = .false.
150
151 8 call this%options%init_from_traits(traits)
152
153 8 default_max_iter = this%options%max_iter
154
1/2
✓ Branch 118 → 119 taken 8 times.
✗ Branch 118 → 120 not taken.
8 if (default_max_iter < 0) default_max_iter = 0
155
1/2
✓ Branch 120 → 121 taken 8 times.
✗ Branch 120 → 128 not taken.
8 if (default_max_iter == 0) then
156 8 default_max_iter = 0
157
2/2
✓ Branch 122 → 123 taken 16 times.
✓ Branch 122 → 127 taken 8 times.
24 do i = 1, n_blocks
158
1/2
✓ Branch 123 → 124 taken 16 times.
✗ Branch 123 → 125 not taken.
24 if (allocated(this%constraints)) then
159 16 default_max_iter = default_max_iter + this%constraints(i)%nr_cols
160 else
161 default_max_iter = default_max_iter + size(this%spaces(i))
162 end if
163 end do
164 end if
165
166 8 call this%options%apply_default_solve_options(default_max_iter, VERBOSITY_WARN_ON_FAILURE)
167
168
8/14
✗ Branch 129 → 130 not taken.
✓ Branch 129 → 131 taken 8 times.
✓ Branch 131 → 130 taken 8 times.
✗ Branch 131 → 132 not taken.
✓ Branch 132 → 133 taken 8 times.
✗ Branch 132 → 134 not taken.
✗ Branch 134 → 135 not taken.
✓ Branch 134 → 136 taken 8 times.
✗ Branch 136 → 137 not taken.
✓ Branch 136 → 138 taken 8 times.
✗ Branch 138 → 139 not taken.
✓ Branch 138 → 140 taken 8 times.
✓ Branch 141 → 142 taken 32 times.
✓ Branch 141 → 143 taken 8 times.
56 allocate (this%block_mats(n_blocks*n_blocks))
169 idx = 0
170
2/2
✓ Branch 143 → 144 taken 16 times.
✓ Branch 143 → 155 taken 8 times.
24 do i = 1, n_blocks
171
2/2
✓ Branch 144 → 145 taken 32 times.
✓ Branch 144 → 153 taken 16 times.
56 do j = 1, n_blocks
172 32 idx = idx + 1
173
1/2
✓ Branch 145 → 146 taken 32 times.
✗ Branch 145 → 149 not taken.
48 if (allocated(this%constraints)) then
174 call get_constrained_petsc_matrix(this%block_mats(idx), amat_blocks(i, j)%elt%mat, this%constraints(j), &
175 32 coeff=amat_blocks(i, j)%elt%constraint_coeff(), constraint_res=this%constraints(i))
176 else
177 PetscCall(MatConvert(amat_blocks(i, j)%elt%mat, "same", MAT_INITIAL_MATRIX, this%block_mats(idx), ierr))
178 end if
179 end do
180 end do
181
182
1/2
✗ Branch 157 → 158 not taken.
✓ Branch 157 → 159 taken 8 times.
8 PetscCall(MatCreateNest(this%spaces(1)%tp_spaces(1)%domain%comm, n_blocks, PETSC_NULL_IS_ARRAY, n_blocks, \
183 PETSC_NULL_IS_ARRAY, this%block_mats, this%mat, ierr))
184
1/2
✗ Branch 160 → 161 not taken.
✓ Branch 160 → 162 taken 8 times.
8 PetscCall(MatAssemblyBegin(this%mat, MAT_FINAL_ASSEMBLY, ierr))
185
1/2
✗ Branch 163 → 164 not taken.
✓ Branch 163 → 165 taken 8 times.
8 PetscCall(MatAssemblyEnd(this%mat, MAT_FINAL_ASSEMBLY, ierr))
186
187 8 call create_ksp(this%mat_ksp, this%mat, this%spaces(1), this%options)
188
189 TIMER_STOP(t_total)
190 8 end subroutine init_coupled_solver
191
192 !> @brief Solve the coupled system using nested PETSc vectors
193
2/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 8 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 8 times.
8 subroutine solve_coupled_solver(this, x, b, options)
194 use m_common, only: VERBOSITY_WARN_NEVER, VERBOSITY_WARN_ON_FAILURE, VERBOSITY_WARN_ALWAYS, VERBOSITY_ERROR_ON_FAILURE
195 use m_mform_basis, only: MFormFun, get_petsc
196 use m_mform_constraint_global, only: CONSTRAINT_EXTRACTION, CONSTRAINT_PROJECTION
197
198 class(CoupledSolver), intent(inout) :: this
199 type(MFormFun), intent(inout) :: x(:)
200 type(MFormFun), intent(in) :: b(:)
201 type(SolverSolveOptions), optional, intent(in) :: options
202
203 integer :: i, n_blocks, ierr, verbosity_
204 real(wp) :: rtol_, atol_
205 integer :: max_iter_
206 character(len=512) :: warn_msg
207 logical :: failure
208
209 Vec, allocatable :: b_vec(:), b_proj_vec(:), x_proj_vec(:), x_vec(:)
210 Vec :: b_nest, x_nest
211
212 TIMER_DECL(t_total)
213 TIMER_DECL(t_solve)
214 TIMER_DECL(t_constraint)
215 TIMER_INIT_START(t_total, "CoupledSolver::solve")
216
217 8 n_blocks = this%nr_blocks
218
219
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 8 times.
8 if (size(x) /= n_blocks .or. size(b) /= n_blocks) then
220 error stop "CoupledSolver::solve_coupled_solver: x and b must match number of block unknowns."
221 end if
222
223 8 rtol_ = this%options%rtol
224 8 atol_ = this%options%atol
225 8 max_iter_ = this%options%max_iter
226
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 16 taken 8 times.
8 if (present(options)) then
227 if (options%rtol >= 0._wp) rtol_ = options%rtol
228 if (options%atol >= 0._wp) atol_ = options%atol
229 if (options%max_iter >= 0) max_iter_ = options%max_iter
230 end if
231
232
1/2
✓ Branch 16 → 17 taken 8 times.
✗ Branch 16 → 20 not taken.
8 if (this%spaces(1)%tp_spaces(1)%domain%my_rank > 0) then
233 verbosity_ = VERBOSITY_WARN_NEVER
234 else
235 8 verbosity_ = this%options%verbosity
236
1/2
✓ Branch 17 → 18 taken 8 times.
✗ Branch 17 → 19 not taken.
8 if (present(options)) then
237 if (options%verbosity >= 0) verbosity_ = options%verbosity
238 end if
239 end if
240
241
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 8 times.
8 PetscCall(KSPSetTolerances(this%mat_ksp, rtol_, atol_, 1.e10_wp, max_iter_, ierr))
242
243
26/44
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 8 times.
✓ Branch 25 → 24 taken 8 times.
✗ Branch 25 → 26 not taken.
✓ Branch 26 → 27 taken 8 times.
✗ Branch 26 → 28 not taken.
✓ Branch 28 → 29 taken 8 times.
✗ Branch 28 → 30 not taken.
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 8 times.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 8 times.
✓ Branch 35 → 36 taken 16 times.
✓ Branch 35 → 37 taken 8 times.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 8 times.
✓ Branch 39 → 38 taken 8 times.
✗ Branch 39 → 40 not taken.
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 8 times.
✗ Branch 42 → 43 not taken.
✓ Branch 42 → 44 taken 8 times.
✓ Branch 44 → 45 taken 16 times.
✓ Branch 44 → 46 taken 8 times.
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 48 taken 8 times.
✓ Branch 48 → 47 taken 8 times.
✗ Branch 48 → 49 not taken.
✗ Branch 49 → 50 not taken.
✓ Branch 49 → 51 taken 8 times.
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 53 taken 8 times.
✓ Branch 53 → 54 taken 16 times.
✓ Branch 53 → 55 taken 8 times.
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 57 taken 8 times.
✓ Branch 57 → 56 taken 8 times.
✗ Branch 57 → 58 not taken.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 60 taken 8 times.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 8 times.
✓ Branch 62 → 63 taken 16 times.
✓ Branch 62 → 64 taken 8 times.
112 allocate (b_vec(n_blocks), b_proj_vec(n_blocks), x_proj_vec(n_blocks), x_vec(n_blocks))
244
245
2/2
✓ Branch 64 → 65 taken 16 times.
✓ Branch 64 → 101 taken 8 times.
24 do i = 1, n_blocks
246
1/2
✗ Branch 65 → 66 not taken.
✓ Branch 65 → 67 taken 16 times.
16 if (this%spaces(i)%m /= b(i)%space%m) then
247 error stop "CoupledSolver::solve_coupled_solver: m-form spaces of rhs blocks do not match row spaces."
248 end if
249
250 16 call get_petsc(b_vec(i), b(i))
251
252
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 75 taken 16 times.
16 if (.not. allocated(this%constraints)) then
253 PetscCall(VecDuplicate(b_vec(i), b_proj_vec(i), ierr))
254 PetscCall(VecCopy(b_vec(i), b_proj_vec(i), ierr))
255 else
256 TIMER_INIT_START(t_constraint, "apply_constraint")
257 32 select case (this%constraints(i)%mode)
258 case (CONSTRAINT_EXTRACTION)
259
1/2
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 79 taken 16 times.
16 PetscCall(VecCreate(this%spaces(1)%tp_spaces(1)%domain%comm, b_proj_vec(i), ierr))
260
1/2
✗ Branch 80 → 81 not taken.
✓ Branch 80 → 82 taken 16 times.
16 PetscCall(VecSetSizes(b_proj_vec(i), this%constraints(i)%my_nr_cols, this%constraints(i)%nr_cols, ierr))
261
1/2
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 16 times.
16 PetscCall(VecSetFromOptions(b_proj_vec(i), ierr))
262
1/2
✗ Branch 86 → 87 not taken.
✓ Branch 86 → 88 taken 16 times.
16 PetscCall(VecAssemblyBegin(b_proj_vec(i), ierr))
263
1/2
✗ Branch 89 → 90 not taken.
✓ Branch 89 → 94 taken 16 times.
16 PetscCall(VecAssemblyEnd(b_proj_vec(i), ierr))
264 case (CONSTRAINT_PROJECTION)
265
1/5
✓ Branch 75 → 76 taken 16 times.
✗ Branch 75 → 91 not taken.
✗ Branch 75 → 94 not taken.
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 94 not taken.
16 PetscCall(VecDuplicate(b_vec(i), b_proj_vec(i), ierr))
266 end select
267
1/2
✗ Branch 95 → 96 not taken.
✓ Branch 95 → 97 taken 16 times.
16 PetscCall(MatMultTranspose(this%constraints(i)%mat, b_vec(i), b_proj_vec(i), ierr))
268 TIMER_STOP(t_constraint)
269 end if
270
271
1/2
✗ Branch 98 → 99 not taken.
✓ Branch 98 → 100 taken 16 times.
24 PetscCall(VecDuplicate(b_proj_vec(i), x_proj_vec(i), ierr))
272 end do
273
274
1/2
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 105 taken 8 times.
8 PetscCall(VecCreateNest(this%spaces(1)%tp_spaces(1)%domain%comm, n_blocks, PETSC_NULL_IS_ARRAY, b_proj_vec, b_nest, ierr))
275
1/2
✗ Branch 106 → 107 not taken.
✓ Branch 106 → 108 taken 8 times.
8 PetscCall(VecCreateNest(this%spaces(1)%tp_spaces(1)%domain%comm, n_blocks, PETSC_NULL_IS_ARRAY, x_proj_vec, x_nest, ierr))
276
277 TIMER_INIT_START(t_solve, "KSPsolve")
278
1/2
✗ Branch 109 → 110 not taken.
✓ Branch 109 → 111 taken 8 times.
8 PetscCall(KSPSolve(this%mat_ksp, b_nest, x_nest, ierr))
279 TIMER_STOP(t_solve)
280
281
1/2
✗ Branch 112 → 113 not taken.
✓ Branch 112 → 114 taken 8 times.
8 PetscCall(KSPGetIterationNumber(this%mat_ksp, this%last_nr_iterations, ierr))
282
1/2
✗ Branch 115 → 116 not taken.
✓ Branch 115 → 117 taken 8 times.
8 PetscCall(KSPGetResidualNorm(this%mat_ksp, this%last_residual_norm, ierr))
283
1/2
✗ Branch 118 → 119 not taken.
✓ Branch 118 → 120 taken 8 times.
8 PetscCall(KSPGetConvergedReason(this%mat_ksp, this%last_converged_reason, ierr))
284
285
1/2
✓ Branch 120 → 121 taken 8 times.
✗ Branch 120 → 134 not taken.
8 if (verbosity_ > VERBOSITY_WARN_NEVER) then
286 8 warn_msg = this%get_warning_message(failure)
287
1/2
✗ Branch 122 → 123 not taken.
✓ Branch 122 → 129 taken 8 times.
8 if (failure) then
288 if (verbosity_ == VERBOSITY_ERROR_ON_FAILURE) then
289 error stop trim(warn_msg)
290 else
291 write (*, '(A)') trim(warn_msg)
292 end if
293
1/2
✗ Branch 129 → 130 not taken.
✓ Branch 129 → 134 taken 8 times.
8 else if (verbosity_ == VERBOSITY_WARN_ALWAYS) then
294 write (*, '(A)') trim(warn_msg)
295 end if
296 end if
297
298
2/2
✓ Branch 135 → 136 taken 16 times.
✓ Branch 135 → 156 taken 8 times.
24 do i = 1, n_blocks
299
1/2
✗ Branch 137 → 138 not taken.
✓ Branch 137 → 139 taken 16 times.
16 PetscCall(VecDuplicate(b_vec(i), x_vec(i), ierr))
300
301
1/2
✓ Branch 139 → 140 taken 16 times.
✗ Branch 139 → 147 not taken.
16 if (allocated(this%constraints)) then
302 TIMER_START(t_constraint)
303
1/2
✓ Branch 140 → 141 taken 16 times.
✗ Branch 140 → 144 not taken.
16 if (this%constraints(i)%mode == CONSTRAINT_EXTRACTION) then
304
1/2
✗ Branch 142 → 143 not taken.
✓ Branch 142 → 150 taken 16 times.
16 PetscCall(MatMult(this%constraints(i)%mat, x_proj_vec(i), x_vec(i), ierr))
305 else
306 PetscCall(VecCopy(x_proj_vec(i), x_vec(i), ierr))
307 end if
308 TIMER_STOP(t_constraint)
309 else
310 PetscCall(VecCopy(x_proj_vec(i), x_vec(i), ierr))
311 end if
312
313
1/2
✗ Branch 150 → 151 not taken.
✓ Branch 150 → 153 taken 16 times.
24 if (x(i)%is_initialized()) then
314 call x(i)%reset(x_vec(i))
315 else
316 16 call x(i)%init(this%spaces(i), x_vec(i))
317 end if
318 end do
319
320
1/2
✗ Branch 158 → 159 not taken.
✓ Branch 158 → 160 taken 8 times.
8 PetscCall(VecDestroy(b_nest, ierr))
321
1/2
✗ Branch 161 → 162 not taken.
✓ Branch 161 → 163 taken 8 times.
8 PetscCall(VecDestroy(x_nest, ierr))
322
323
2/2
✓ Branch 163 → 164 taken 16 times.
✓ Branch 163 → 177 taken 8 times.
24 do i = 1, n_blocks
324
1/2
✗ Branch 165 → 166 not taken.
✓ Branch 165 → 167 taken 16 times.
16 PetscCall(VecDestroy(b_vec(i), ierr))
325
1/2
✗ Branch 168 → 169 not taken.
✓ Branch 168 → 170 taken 16 times.
16 PetscCall(VecDestroy(b_proj_vec(i), ierr))
326
1/2
✗ Branch 171 → 172 not taken.
✓ Branch 171 → 173 taken 16 times.
16 PetscCall(VecDestroy(x_proj_vec(i), ierr))
327
1/2
✗ Branch 174 → 175 not taken.
✓ Branch 174 → 176 taken 16 times.
24 PetscCall(VecDestroy(x_vec(i), ierr))
328 end do
329
330 TIMER_STOP(t_total)
331
5/18
✓ Branch 6 → 7 taken 8 times.
✗ Branch 6 → 8 not taken.
✓ Branch 178 → 179 taken 8 times.
✗ Branch 178 → 180 not taken.
✓ Branch 180 → 181 taken 8 times.
✗ Branch 180 → 182 not taken.
✓ Branch 182 → 183 taken 8 times.
✗ Branch 182 → 184 not taken.
✓ Branch 184 → 185 taken 8 times.
✗ Branch 184 → 202 not taken.
✗ Branch 187 → 188 not taken.
✗ Branch 187 → 189 not taken.
✗ Branch 191 → 192 not taken.
✗ Branch 191 → 193 not taken.
✗ Branch 195 → 196 not taken.
✗ Branch 195 → 197 not taken.
✗ Branch 199 → 200 not taken.
✗ Branch 199 → 203 not taken.
16 end subroutine solve_coupled_solver
332
333 !> @brief Destroy the coupled solver
334 16 subroutine destroy_coupled_solver(this)
335 class(CoupledSolver), intent(inout) :: this
336
337 integer :: i, ierr
338
339
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 16 times.
16 PetscCall(MatDestroy(this%mat, ierr))
340
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 16 times.
16 PetscCall(KSPDestroy(this%mat_ksp, ierr))
341
342
2/2
✓ Branch 8 → 9 taken 8 times.
✓ Branch 8 → 19 taken 8 times.
16 if (allocated(this%block_mats)) then
343
2/2
✓ Branch 10 → 11 taken 32 times.
✓ Branch 10 → 15 taken 8 times.
40 do i = 1, size(this%block_mats)
344
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 32 times.
40 PetscCall(MatDestroy(this%block_mats(i), ierr))
345 end do
346
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 8 times.
8 deallocate (this%block_mats)
347 end if
348
349
2/2
✓ Branch 19 → 20 taken 8 times.
✓ Branch 19 → 102 taken 8 times.
16 if (allocated(this%constraints)) then
350
2/2
✓ Branch 21 → 22 taken 16 times.
✓ Branch 21 → 24 taken 8 times.
24 do i = 1, size(this%constraints)
351 24 call this%constraints(i)%destroy()
352 end do
353
15/72
✓ Branch 25 → 26 taken 8 times.
✗ Branch 25 → 99 not taken.
✓ Branch 27 → 28 taken 16 times.
✓ Branch 27 → 99 taken 8 times.
✓ Branch 28 → 29 taken 16 times.
✗ Branch 28 → 30 not taken.
✓ Branch 31 → 32 taken 80 times.
✓ Branch 31 → 75 taken 16 times.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 35 taken 80 times.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 35 not taken.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 74 taken 80 times.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 38 not taken.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 51 not taken.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 50 not taken.
✗ Branch 41 → 42 not taken.
✗ Branch 41 → 43 not taken.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 47 not taken.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
✗ Branch 51 → 52 not taken.
✗ Branch 51 → 62 not taken.
✗ Branch 53 → 54 not taken.
✗ Branch 53 → 61 not taken.
✗ Branch 54 → 55 not taken.
✗ Branch 54 → 56 not taken.
✗ Branch 56 → 57 not taken.
✗ Branch 56 → 58 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 58 → 60 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 73 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 72 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
✗ Branch 67 → 68 not taken.
✗ Branch 67 → 69 not taken.
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 71 not taken.
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 16 times.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 79 taken 16 times.
✗ Branch 79 → 80 not taken.
✓ Branch 79 → 81 taken 16 times.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 16 times.
✗ Branch 83 → 84 not taken.
✓ Branch 83 → 85 taken 16 times.
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 98 taken 16 times.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 97 not taken.
✗ Branch 88 → 89 not taken.
✗ Branch 88 → 90 not taken.
✗ Branch 90 → 91 not taken.
✗ Branch 90 → 92 not taken.
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 94 not taken.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 96 not taken.
✗ Branch 99 → 100 not taken.
✓ Branch 99 → 101 taken 8 times.
104 deallocate (this%constraints)
354 end if
355
356
6/8
✓ Branch 102 → 103 taken 8 times.
✓ Branch 102 → 111 taken 8 times.
✓ Branch 104 → 105 taken 16 times.
✓ Branch 104 → 108 taken 8 times.
✓ Branch 105 → 106 taken 16 times.
✗ Branch 105 → 107 not taken.
✗ Branch 108 → 109 not taken.
✓ Branch 108 → 110 taken 8 times.
32 if (allocated(this%spaces)) deallocate (this%spaces)
357 16 this%nr_blocks = 0
358 end subroutine destroy_coupled_solver
359
360 end module m_mform_coupled_solver
361