GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 77.2% 176 / 0 / 228
Functions: 73.3% 22 / 0 / 30
Branches: 46.1% 189 / 0 / 410

mform/m_mform_matrix.f90
Line Branch Exec Source
1 !> @brief Module for m-form matrices
2 !>
3 !> This module provides mass matrices for each of the m-form spaces, as well as matrix representations of the diffrential operators
4 module m_mform_matrix
5 use m_mform_basis, only: MFormSpace
6 #include "petsc.fi"
7
8 implicit none
9
10 private
11 public :: AbstractMatrix, MassMatrix, DiffMatrix, DiffDiffMatrix, ZeroMatrix
12 public :: gradient_matrix, curl_matrix, divergence_matrix, transpose
13
14 !> @brief Abstract base type for m-form matrices
15 type, abstract :: AbstractMatrix
16 !> The m-form space of the solution vector
17 type(MFormSpace) :: space_col
18
19 !> The m-form space of the residual
20 type(MFormSpace) :: space_row
21
22 !> PETSc matrix
23 Mat :: mat
24
25 !> Whether the matrix is symmetric
26 logical :: is_symmetric
27 !> Whether the matrix is symmetric positive definite
28 logical :: is_spd
29 contains
30 procedure(constraint_coeff_interface), deferred :: constraint_coeff
31 procedure :: destroy => destroy_abstract_matrix
32 end type
33
34 interface
35 pure function constraint_coeff_interface(this) result(ans)
36 use m_common, only: wp
37 import :: AbstractMatrix
38 class(AbstractMatrix), intent(in) :: this
39
40 real(wp) :: ans
41 end function constraint_coeff_interface
42 end interface
43
44 !> @brief Mass matrix
45 type, extends(AbstractMatrix) :: MassMatrix
46
47 contains
48 procedure :: init => init_mass_matrix
49 procedure :: constraint_coeff => constraint_coeff_mass
50 end type
51
52 !> @brief Matrix representation of the weak form of a differential operator (gradient, curl, divergence)
53 !>
54 !> The matrix is given by M * D, where M is the mass matrix of the next m-form space and D is the 'finite difference' matrix
55 type, extends(AbstractMatrix) :: DiffMatrix
56 contains
57 procedure :: init => init_diff_matrix
58 procedure :: constraint_coeff => constraint_coeff_diff
59 end type
60
61 !> @brief Matrix representation of the weak form of a differential operator (divgrad, curlcurl, graddiv)
62 !>
63 !> The matrix is given by D^T * M * D, where M is the mass matrix of the next m-form space and D is the 'finite difference' matrix
64 type, extends(AbstractMatrix) :: DiffDiffMatrix
65
66 contains
67 procedure :: init => init_diffdiff_matrix
68 procedure :: constraint_coeff => constraint_coeff_diffdiff
69 end type
70
71 type, extends(AbstractMatrix) :: ZeroMatrix
72 contains
73 procedure :: init => init_zero_matrix
74 procedure :: constraint_coeff => constraint_coeff_zero
75 end type
76
77 interface transpose
78 module procedure transpose_abstract_matrix
79 end interface transpose
80
81 contains
82
83 !> @brief Initialize the mass matrix for the given m-form space
84 !>
85 !> @param[inout] this The MassMatrix object to initialize
86 !> @param[in] space The MFormSpace for which to initialize the mass matrix
87 !> @param[in] coord_transform _(optional)_ The coordinate transformation associated with the m-form space
88 !> @param[in] userfun _(optional)_ A user-defined function to used to scale the inner product that defines the mass matrix
89 !> @param[in] userfun_mat _(optional)_ A user-defined matrix-valued function to used to scale the inner product that defines the
90 !> mass matrix
91 !> @param[in] n_quad_extra _(optional)_ The number of extra quadrature points to use for the mass matrix on top of those needed
92 !> for the exact integration of the product of the B-spline basis functions
93 710 subroutine init_mass_matrix(this, space, coord_transform, userfun, userfun_mat, n_quad_extra)
94 use m_common, only: user_function_3d_interface, user_function_3d_mat_interface
95 use m_coord_transform, only: CoordTransformAbstract
96
97 implicit none
98 class(MassMatrix), intent(inout) :: this
99 type(MFormSpace), intent(in) :: space
100 class(CoordTransformAbstract), optional, intent(in) :: coord_transform
101 procedure(user_function_3d_interface), optional :: userfun
102 procedure(user_function_3d_mat_interface), optional :: userfun_mat
103 integer, intent(in), optional :: n_quad_extra
104
105 710 call this%destroy()
106
107
5/8
✓ Branch 3 → 4 taken 710 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 710 times.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 710 times.
✗ Branch 7 → 10 not taken.
✓ Branch 8 → 9 taken 376 times.
✓ Branch 8 → 10 taken 334 times.
710 this%space_col = space
108
5/8
✓ Branch 10 → 11 taken 710 times.
✗ Branch 10 → 14 not taken.
✓ Branch 11 → 12 taken 710 times.
✗ Branch 11 → 13 not taken.
✓ Branch 14 → 15 taken 710 times.
✗ Branch 14 → 17 not taken.
✓ Branch 15 → 16 taken 376 times.
✓ Branch 15 → 17 taken 334 times.
710 this%space_row = space
109
110
2/2
✓ Branch 17 → 18 taken 187 times.
✓ Branch 17 → 19 taken 523 times.
710 if (space%m == 0 .or. space%m == 3) then
111 187 call init_mass_matrix_scalar(this, space, coord_transform=coord_transform, userfun=userfun, n_quad_extra=n_quad_extra)
112 else
113 call init_mass_matrix_vector(this, space, coord_transform=coord_transform, userfun=userfun, userfun_mat=userfun_mat, &
114 523 n_quad_extra=n_quad_extra)
115 end if
116
117 710 this%is_symmetric = .true.
118 710 this%is_spd = .true.
119 710 end subroutine
120
121 !> @brief Initialize the mass matrix for a scalar m-form space (i.e., m=0,3)
122 !>
123 !> @param[inout] this The MassMatrix object to initialize
124 !> @param[in] space The MFormSpace for which to initialize the mass matrix
125 !> @param[in] coord_transform _(optional)_ The coordinate transformation associated with the m-form space
126 !> @param[in] userfun _(optional)_ A user-defined function to used to scale the inner product that defines the mass matrix
127 !> @param[in] n_quad_extra _(optional)_ The number of extra quadrature points to use for the mass matrix on top of those needed
128 !> for the exact integration of the product of the B-spline basis functions
129 187 subroutine init_mass_matrix_scalar(this, space, coord_transform, userfun, n_quad_extra)
130 use m_tensorprod_matrix, only: TensorProdMat, mass_matrix, get_petsc
131 use m_common, only: user_function_3d_interface
132 use m_coord_transform, only: CoordTransformAbstract, jacobian
133
134 implicit none
135 class(MassMatrix), intent(inout) :: this
136 type(MFormSpace), intent(in) :: space
137 class(CoordTransformAbstract), optional, intent(in) :: coord_transform
138 procedure(user_function_3d_interface), optional :: userfun
139 integer, intent(in), optional :: n_quad_extra
140
141 187 type(TensorProdMat) :: M_TP
142
143
4/6
✓ Branch 2 → 3 taken 69 times.
✓ Branch 2 → 4 taken 118 times.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 69 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 8 taken 118 times.
187 if (present(coord_transform) .or. present(userfun)) then
144
2/2
✓ Branch 5 → 6 taken 51 times.
✓ Branch 5 → 7 taken 18 times.
69 if (space%m == 0) then
145 51 call mass_matrix(M_TP, space%tp_spaces(1), space%tp_spaces(1), coordfun=jacobian_wrap, n_quad_extra=n_quad_extra)
146 else ! if (space%m == 3) then
147 18 call mass_matrix(M_TP, space%tp_spaces(1), space%tp_spaces(1), coordfun=jacobian_inverse_wrap, n_quad_extra=n_quad_extra)
148 end if
149 else
150 118 call mass_matrix(M_TP, space%tp_spaces(1), space%tp_spaces(1))
151 end if
152
153 187 call get_petsc(this%mat, M_TP)
154
155
3/6
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 187 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 187 times.
✓ Branch 15 → 16 taken 187 times.
✗ Branch 15 → 17 not taken.
187 call M_TP%destroy()
156 contains
157 12286888 pure real(wp) function jacobian_wrap(xp, yp, zp)
158 use m_common, only: wp
159 real(wp), intent(in) :: xp, yp, zp
160
161
2/4
✓ Branch 2 → 3 taken 12286888 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 12286888 times.
✗ Branch 3 → 5 not taken.
12286888 if (.not. present(coord_transform)) then
162 jacobian_wrap = 1._wp
163 else
164 12286888 jacobian_wrap = jacobian(coord_transform, xp, yp, zp)
165 end if
166
167
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 12286888 times.
12286888 if (present(userfun)) then
168 jacobian_wrap = jacobian_wrap * userfun(xp, yp, zp)
169 end if
170
171 12286888 end function jacobian_wrap
172 6431964 pure real(wp) function jacobian_inverse_wrap(xp, yp, zp)
173 use m_common, only: wp
174 real(wp), intent(in) :: xp, yp, zp
175
176
2/4
✓ Branch 2 → 3 taken 6431964 times.
✗ Branch 2 → 5 not taken.
✓ Branch 3 → 4 taken 6431964 times.
✗ Branch 3 → 5 not taken.
6431964 if (.not. present(coord_transform)) then
177 jacobian_inverse_wrap = 1._wp
178 else
179 6431964 jacobian_inverse_wrap = 1._wp / jacobian(coord_transform, xp, yp, zp)
180 end if
181
182
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 6431964 times.
6431964 if (present(userfun)) then
183 jacobian_inverse_wrap = jacobian_inverse_wrap * userfun(xp, yp, zp)
184 end if
185
186 6431964 end function jacobian_inverse_wrap
187
188 end subroutine
189
190 !> @brief Initialize the mass matrix for a vector-valued m-form space (i.e., m=1,2)
191 !>
192 !> @param[inout] this The MassMatrix object to initialize
193 !> @param[in] space The MFormSpace for which to initialize the mass matrix
194 !> @param[in] coord_transform _(optional)_ The coordinate transformation associated with the m-form space
195 !> @param[in] userfun _(optional)_ A user-defined function to used to scale the inner product that defines the mass matrix
196 !> @param[in] userfun_mat _(optional)_ A user-defined matrix-valued function to used to scale the inner product that defines the
197 !> mass matrix
198 !> @param[in] n_quad_extra _(optional)_ The number of extra quadrature points to use for the mass matrix on top of those needed
199 !> for the exact integration of the product of the B-spline basis functions
200 !>
201 !> @note If both userfun and userfun_mat are present, the product of the two is used to scale the inner product defining the mass
202 !> matrix
203 523 subroutine init_mass_matrix_vector(this, space, coord_transform, userfun, userfun_mat, n_quad_extra)
204 use m_tensorprod_basis, only: size
205 use m_tensorprod_matrix, only: TensorProdMat, mass_matrix, get_petsc
206 use m_common, only: user_function_3d_interface, user_function_3d_mat_interface
207 use m_coord_transform, only: CoordTransformAbstract, jacobian, jacobian_matrix, jacobian_matrix_inv, G_matrix, G_matrix_inv
208
209 implicit none
210 class(MassMatrix), intent(inout) :: this
211 type(MFormSpace), intent(in) :: space
212 class(CoordTransformAbstract), optional, intent(in) :: coord_transform
213 procedure(user_function_3d_interface), optional :: userfun
214 procedure(user_function_3d_mat_interface), optional :: userfun_mat
215 integer, intent(in), optional :: n_quad_extra
216
217 integer :: s1, s2, s2_memory
218
219 523 type(TensorProdMat), allocatable :: M_TP_block(:, :)
220 logical :: is_diagonal
221
222
5/6
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 523 times.
✓ Branch 5 → 6 taken 1569 times.
✓ Branch 5 → 10 taken 523 times.
✓ Branch 7 → 8 taken 4707 times.
✓ Branch 7 → 9 taken 1569 times.
6799 allocate (M_TP_block(3, 3))
223
224
3/4
✓ Branch 10 → 11 taken 290 times.
✓ Branch 10 → 12 taken 233 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 290 times.
523 if (.not. present(coord_transform)) then
225 233 is_diagonal = .not. present(userfun_mat)
226 else
227
4/4
✓ Branch 13 → 14 taken 272 times.
✓ Branch 13 → 15 taken 18 times.
✓ Branch 14 → 15 taken 8 times.
✓ Branch 14 → 16 taken 264 times.
290 is_diagonal = coord_transform%is_orthogonal .and. .not. present(userfun_mat)
228 end if
229 ! Vector valued (i.e. resulting in a block matrix)
230
2/2
✓ Branch 17 → 18 taken 1569 times.
✓ Branch 17 → 32 taken 523 times.
2092 do s1 = 1, 3
231
2/2
✓ Branch 19 → 20 taken 4707 times.
✓ Branch 19 → 30 taken 1569 times.
6799 do s2 = 1, 3
232
2/2
✓ Branch 20 → 21 taken 4473 times.
✓ Branch 20 → 22 taken 234 times.
4707 if (is_diagonal) then
233
2/2
✓ Branch 21 → 22 taken 1491 times.
✓ Branch 21 → 29 taken 2982 times.
4473 if (s1 /= s2) then
234 ! If the coordinate transformation is orthogonal, the mass matrix is
235 ! block diagonal
236 cycle
237 end if
238 s2_memory = 1
239 else
240 s2_memory = s2
241 end if
242
243 ! TODO the matrix is block symmetric, hence we need not compute all of the blocks
244
245
4/6
✓ Branch 22 → 23 taken 1026 times.
✓ Branch 22 → 24 taken 699 times.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 1026 times.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 28 taken 699 times.
3294 if (present(coord_transform) .or. present(userfun) .or. present(userfun_mat)) then
246
2/2
✓ Branch 25 → 26 taken 828 times.
✓ Branch 25 → 27 taken 198 times.
1026 if (space%m == 1) then
247 call mass_matrix(M_TP_block(s1, s2_memory), space%tp_spaces(s1), space%tp_spaces(s2), coordfun=coordfun_oneform, &
248 828 & n_quad_extra=n_quad_extra)
249 else ! if (space%m == 2) then
250 call mass_matrix(M_TP_block(s1, s2_memory), space%tp_spaces(s1), space%tp_spaces(s2), coordfun=coordfun_twoform, &
251 198 & n_quad_extra=n_quad_extra)
252 end if
253 else
254 699 call mass_matrix(M_TP_block(s1, s2_memory), space%tp_spaces(s1), space%tp_spaces(s2), n_quad_extra=n_quad_extra)
255 end if
256 end do
257 end do
258
259
2/2
✓ Branch 33 → 34 taken 497 times.
✓ Branch 33 → 36 taken 26 times.
523 if (is_diagonal) then
260 497 call get_petsc(this%mat, M_TP_block(:, 1))
261 else
262 26 call get_petsc(this%mat, M_TP_block)
263 end if
264
265
2/2
✓ Branch 38 → 39 taken 1569 times.
✓ Branch 38 → 45 taken 523 times.
2092 do s1 = 1, 3
266
2/2
✓ Branch 40 → 41 taken 4707 times.
✓ Branch 40 → 43 taken 1569 times.
6799 do s2 = 1, 3
267 6276 call M_TP_block(s1, s2)%destroy()
268 end do
269 end do
270
271
8/12
✓ Branch 46 → 47 taken 523 times.
✗ Branch 46 → 55 not taken.
✓ Branch 47 → 48 taken 4707 times.
✓ Branch 47 → 55 taken 523 times.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 4707 times.
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 52 taken 4707 times.
✓ Branch 52 → 53 taken 1725 times.
✓ Branch 52 → 54 taken 2982 times.
✗ Branch 55 → 56 not taken.
✓ Branch 55 → 57 taken 523 times.
5230 deallocate (M_TP_block)
272 contains
273
274 160460208 pure real(wp) function coordfun_oneform(xp, yp, zp)
275 use m_common, only: wp
276 implicit none
277 real(wp), intent(in) :: xp, yp, zp
278
279 integer :: m, n
280 real(wp) :: tmp
281
282
2/4
✓ Branch 2 → 3 taken 160460208 times.
✗ Branch 2 → 18 not taken.
✓ Branch 3 → 4 taken 160460208 times.
✗ Branch 3 → 18 not taken.
160460208 if (present(coord_transform)) then
283
2/2
✓ Branch 4 → 5 taken 122044128 times.
✓ Branch 4 → 6 taken 38416080 times.
160460208 if (.not. present(userfun_mat)) then
284 122044128 coordfun_oneform = G_matrix_inv(coord_transform, s1, s2, xp, yp, zp)
285 else
286 coordfun_oneform = 0._wp
287
2/2
✓ Branch 7 → 8 taken 115248240 times.
✓ Branch 7 → 16 taken 38416080 times.
153664320 do n = 1, 3
288
2/2
✓ Branch 9 → 10 taken 345744720 times.
✓ Branch 9 → 14 taken 115248240 times.
499409040 do m = 1, 3
289 345744720 tmp = userfun_mat(m, n, xp, yp, zp)
290
2/2
✓ Branch 11 → 12 taken 192080400 times.
✓ Branch 11 → 13 taken 153664320 times.
460992960 if (tmp /= 0._wp) then
291 tmp = tmp * jacobian_matrix_inv(coord_transform, s1, m, xp, yp, zp) * &
292 192080400 jacobian_matrix_inv(coord_transform, s2, n, xp, yp, zp)
293
294 192080400 coordfun_oneform = coordfun_oneform + tmp
295 end if
296 end do
297 end do
298 end if
299 160460208 coordfun_oneform = coordfun_oneform * jacobian(coord_transform, xp, yp, zp)
300 else
301 if (.not. present(userfun_mat)) then
302 coordfun_oneform = 1._wp
303 else
304 coordfun_oneform = userfun_mat(s1, s2, xp, yp, zp)
305 end if
306 end if
307
308
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 23 taken 160460208 times.
160460208 if (present(userfun)) then
309 coordfun_oneform = coordfun_oneform * userfun(xp, yp, zp)
310 end if
311 160460208 end function coordfun_oneform
312
313 44397075 pure real(wp) function coordfun_twoform(xp, yp, zp)
314 use m_common, only: wp
315 implicit none
316 real(wp), intent(in) :: xp, yp, zp
317
318 integer :: m, n
319 real(wp) :: tmp
320
321
2/4
✓ Branch 2 → 3 taken 44397075 times.
✗ Branch 2 → 18 not taken.
✓ Branch 3 → 4 taken 44397075 times.
✗ Branch 3 → 18 not taken.
44397075 if (present(coord_transform)) then
322
1/2
✓ Branch 4 → 5 taken 44397075 times.
✗ Branch 4 → 6 not taken.
44397075 if (.not. present(userfun_mat)) then
323 44397075 coordfun_twoform = G_matrix(coord_transform, s1, s2, xp, yp, zp)
324 else
325 coordfun_twoform = 0._wp
326 do n = 1, 3
327 do m = 1, 3
328 tmp = userfun_mat(m, n, xp, yp, zp)
329 if (tmp /= 0._wp) then
330 tmp = tmp * jacobian_matrix(coord_transform, m, s1, xp, yp, zp) * &
331 jacobian_matrix(coord_transform, n, s2, xp, yp, zp)
332
333 coordfun_twoform = coordfun_twoform + tmp
334 end if
335 end do
336 end do
337 end if
338 44397075 coordfun_twoform = coordfun_twoform / jacobian(coord_transform, xp, yp, zp)
339 else
340 if (.not. present(userfun_mat)) then
341 coordfun_twoform = 1._wp
342 else
343 coordfun_twoform = userfun_mat(s1, s2, xp, yp, zp)
344 end if
345 end if
346
347
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 23 taken 44397075 times.
44397075 if (present(userfun)) then
348 coordfun_twoform = coordfun_twoform * userfun(xp, yp, zp)
349 end if
350 44397075 end function coordfun_twoform
351 end subroutine
352
353 !> @brief Initialize the matrix representation of the weak form of a differential operator for the given m-form space (gradient,
354 !> curl, divergence)
355 !>
356 !> @param[inout] this The DiffMatrix object to initialize
357 !> @param[in] space The MFormSpace for which to initialize the differential matrix
358 !> @param[in] coord_transform _(optional)_ The coordinate transformation associated with the m-form space
359 !> @param[in] mass _(optional)_ The MassMatrix corresponding to the next m-form space; if not provided, it is constructed
360 !> internally
361 subroutine init_diff_matrix(this, space, coord_transform, mass)
362 use m_common, only: wp
363 use m_mform_basis, only: next
364 use m_coord_transform, only: CoordTransformAbstract
365 implicit none
366
367 class(DiffMatrix), intent(out) :: this
368 type(MFormSpace), intent(in) :: space
369 class(CoordTransformAbstract), optional, intent(in) :: coord_transform
370 type(MassMatrix), optional, intent(in) :: mass
371
372 real(wp) :: EXPECTED_FILL_RATIO = 1.0_wp
373 integer :: ierr
374
375 Mat :: grad
376 type(MassMatrix) :: mass_
377
378 call this%destroy()
379
380 this%space_col = space
381 this%space_row = next(space)
382
383 call diff_matrix_derham(grad, space, this%space_row)
384 if (present(mass)) then
385 if (mass%space_col%m /= this%space_row%m) then
386 error stop "DiffMatrix::init_diff_matrix: optional argument mass must be the mass matrix corresponding to next(space)"
387 end if
388 PetscCall(MatMatMult(mass%mat, grad, MAT_INITIAL_MATRIX, EXPECTED_FILL_RATIO, this%mat, ierr))
389 else
390 call mass_%init(this%space_row, coord_transform=coord_transform)
391 PetscCall(MatMatMult(mass_%mat, grad, MAT_INITIAL_MATRIX, EXPECTED_FILL_RATIO, this%mat, ierr))
392 call mass_%destroy()
393 end if
394 PetscCall(MatDestroy(grad, ierr))
395
396 this%is_symmetric = .false.
397 this%is_spd = .false.
398 end subroutine
399
400 !> @brief Initialize the matrix representation of the weak form of a differential operator for the given m-form space (divgrad,
401 !> curlcurl, graddiv)
402 !>
403 !> @param[inout] this The DiffDiffMatrix object to initialize
404 !> @param[in] space The MFormSpace for which to initialize the differential matrix
405 !> @param[in] coord_transform _(optional)_ The coordinate transformation associated with the m-form space
406 !> @param[in] mass _(optional)_ The MassMatrix corresponding to the next m-form space; if not provided, it is constructed
407 !> internally
408 297 subroutine init_diffdiff_matrix(this, space, coord_transform, mass)
409 use m_common, only: wp
410 use m_mform_basis, only: next
411 use m_coord_transform, only: CoordTransformAbstract
412 implicit none
413
414 class(DiffDiffMatrix), intent(out) :: this
415 type(MFormSpace), intent(in) :: space
416 class(CoordTransformAbstract), optional, intent(in) :: coord_transform
417 type(MassMatrix), optional, intent(in) :: mass
418
419 real(wp) :: EXPECTED_FILL_RATIO = 1.0_wp
420 integer :: ierr
421
422 Mat :: grad
423 297 type(MassMatrix) :: mass_
424 297 type(MFormSpace) :: next_space
425
426 297 call this%destroy()
427
428
4/8
✓ Branch 6 → 7 taken 297 times.
✗ Branch 6 → 10 not taken.
✓ Branch 7 → 8 taken 297 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 11 taken 297 times.
✗ Branch 10 → 13 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 297 times.
297 this%space_col = space
429
4/8
✓ Branch 13 → 14 taken 297 times.
✗ Branch 13 → 17 not taken.
✓ Branch 14 → 15 taken 297 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 297 times.
✗ Branch 17 → 20 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 297 times.
297 this%space_row = space
430
431 297 next_space = next(space)
432
433 297 call diff_matrix_derham(grad, space, next_space)
434
2/2
✓ Branch 22 → 23 taken 40 times.
✓ Branch 22 → 28 taken 257 times.
297 if (present(mass)) then
435
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 40 times.
40 if (mass%space_col%m /= next_space%m) then
436 error stop "DiffDiffMatrix::init_diffdiff_matrix: optional argument mass must be the mass matrix corresponding to"// &
437 &" next(space)"
438 end if
439
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 34 taken 40 times.
40 PetscCall(MatPtAP(mass%mat, grad, MAT_INITIAL_MATRIX, EXPECTED_FILL_RATIO, this%mat, ierr))
440 else
441 257 call mass_%init(next_space, coord_transform=coord_transform)
442
1/2
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 257 times.
257 PetscCall(MatPtAP(mass_%mat, grad, MAT_INITIAL_MATRIX, EXPECTED_FILL_RATIO, this%mat, ierr))
443 257 call mass_%destroy()
444 end if
445
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 297 times.
297 PetscCall(MatDestroy(grad, ierr))
446
447 297 this%is_symmetric = .true.
448 297 this%is_spd = .true.
449
6/14
✓ Branch 2 → 3 taken 297 times.
✗ Branch 2 → 5 not taken.
✓ Branch 37 → 38 taken 297 times.
✗ Branch 37 → 39 not taken.
✓ Branch 39 → 40 taken 257 times.
✓ Branch 39 → 41 taken 40 times.
✓ Branch 41 → 42 taken 257 times.
✓ Branch 41 → 54 taken 40 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
✗ Branch 51 → 52 not taken.
✗ Branch 51 → 55 not taken.
594 end subroutine
450
451 !> @brief Initialize a zero matrix for the given m-form spaces
452 !>
453 !> @param[inout] this The ZeroMatrix object to initialize
454 !> @param[in] space_row The m-form space corresponding to the rows of the matrix
455 !> @param[in] space_col _(optional)_ The m-form space corresponding to the columns of the matrix
456 !>
457 !> @note If space_row is not provided, a square zero matrix on space_col is constructed
458 8 subroutine init_zero_matrix(this, space_row, space_col)
459 use m_mform_basis, only: size
460 implicit none
461
462 class(ZeroMatrix), intent(inout) :: this
463 type(MFormSpace), intent(in) :: space_row
464 type(MFormSpace), optional, intent(in) :: space_col
465
466 integer :: ierr
467 integer :: local_nz_per_row, nonlocal_nz_per_row
468
469 8 call this%destroy()
470
471
4/8
✓ Branch 3 → 4 taken 8 times.
✗ Branch 3 → 7 not taken.
✓ Branch 4 → 5 taken 8 times.
✗ Branch 4 → 6 not taken.
✓ Branch 7 → 8 taken 8 times.
✗ Branch 7 → 10 not taken.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 8 times.
8 this%space_row = space_row
472
1/2
✓ Branch 10 → 11 taken 8 times.
✗ Branch 10 → 19 not taken.
8 if (present(space_col)) then
473
4/8
✓ Branch 11 → 12 taken 8 times.
✗ Branch 11 → 15 not taken.
✓ Branch 12 → 13 taken 8 times.
✗ Branch 12 → 14 not taken.
✓ Branch 15 → 16 taken 8 times.
✗ Branch 15 → 18 not taken.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 8 times.
8 this%space_col = space_col
474 else
475 this%space_col = space_row
476 end if
477
478 8 local_nz_per_row = 0
479 8 nonlocal_nz_per_row = 0
480 call MatCreateAIJ(space_col%tp_spaces(1)%domain%comm, size(this%space_row, my_rank=.true.), &
481 & size(this%space_col, my_rank=.true.), size(this%space_row), size(this%space_col), &
482 8 & local_nz_per_row, PETSC_NULL_INTEGER_ARRAY, nonlocal_nz_per_row, PETSC_NULL_INTEGER_ARRAY, this%mat, ierr)
483
1/2
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 30 taken 8 times.
8 CHKERRQ(ierr)
484
485
1/2
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 8 times.
8 PetscCall(MatSetFromOptions(this%mat, ierr))
486
1/2
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 8 times.
8 PetscCall(MatSetUp(this%mat, ierr))
487
1/2
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 8 times.
8 PetscCall(MatAssemblyBegin(this%mat, MAT_FINAL_ASSEMBLY, ierr))
488
1/2
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 42 taken 8 times.
8 PetscCall(MatAssemblyEnd(this%mat, MAT_FINAL_ASSEMBLY, ierr))
489
490 8 this%is_symmetric = (size(this%space_row) == size(this%space_col))
491 8 this%is_spd = .false.
492 end subroutine init_zero_matrix
493
494 !> @brief Coefficient for the imposing a linear constraint on the mass matrix by means of a projection operator
495 !>
496 !> That is, when mode=CONSTRAINT_PROJECTION is used, the following matrix is constructed:
497 !> P^T * M * P + \gamma * (I - P)^T M * (I - P),
498 !> where P is the projection operator and M is the mass matrix.
499 !> This function provides the coefficient \gamma.
500 !>
501 !> @param[in] this The MassMatrix object for which to compute the coefficient
502 !>
503 !> @return The coefficient \gamma
504 105 pure function constraint_coeff_mass(this) result(ans)
505 use m_common, only: wp
506
507 class(MassMatrix), intent(in) :: this
508
509 real(wp) :: ans
510
511 ans = 1.0_wp
512 105 end function constraint_coeff_mass
513
514 !> @brief Coefficient for the imposing a linear constraint on the differential matrix by means of a projection operator
515 !>
516 !> That is, when mode=CONSTRAINT_PROJECTION is used, the following matrix is constructed:
517 !> P^T * L * D + \gamma * (I - P)^T M * (I - P),
518 !> where P is the projection operator, L is the divgrad/curlcurl/graddiv matrix.
519 !> This function provides the coefficient \gamma.
520 !>
521 !> @param[in] this The DiffDiffMatrix object for which to compute the coefficient
522 !>
523 !> @return The coefficient \gamma
524 289 pure function constraint_coeff_diffdiff(this) result(ans)
525 use m_common, only: wp
526
527 class(DiffDiffMatrix), intent(in) :: this
528
529 real(wp) :: ans
530
531 ! TODO is this good? at least now it's dimensionally consistent
532 ans = 1._wp / ((this%space_col%tp_spaces(1)%spaces(1)%h * this%space_col%tp_spaces(1)%spaces(2)%h * &
533 289 & this%space_col%tp_spaces(1)%spaces(3)%h)**(1._wp / 3._wp))
534 289 end function constraint_coeff_diffdiff
535
536 !> @brief This function is meaningless for the DiffDiffMatrix, but is required by the AbstractMatrix interface
537 pure function constraint_coeff_diff(this) result(ans)
538 use m_common, only: wp
539
540 class(DiffMatrix), intent(in) :: this
541
542 real(wp) :: ans
543
544 ! NOTE: Never used but AbstractMatrix requires it
545 ! TODO maybe have intermediate type 'AbstractSquareMatrix'?
546 ans = 1._wp
547 end function constraint_coeff_diff
548
549 !> @brief This function is meaningless for the ZeroMatrix, but is required by the AbstractMatrix interface
550 16 pure function constraint_coeff_zero(this) result(ans)
551 use m_common, only: wp
552
553 class(ZeroMatrix), intent(in) :: this
554
555 real(wp) :: ans
556
557 ans = 1._wp
558 16 end function constraint_coeff_zero
559
560 !> @brief Destroy the AbstractMatrix
561 !>
562 !> @param[inout] this The AbstractMatrix object to destroy
563 1753 subroutine destroy_abstract_matrix(this)
564 implicit none
565
566 class(AbstractMatrix), intent(inout) :: this
567 integer :: ierr
568
569
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 1753 times.
1753 PetscCall(MatDestroy(this%mat, ierr))
570 end subroutine destroy_abstract_matrix
571
572 !> @brief Create the matrix representation of the weak form of a differential operator grad/curl/div in the DeRham sequence
573 !>
574 !> @param[out] diff The matrix to create
575 !> @param[in] space The MFormSpace for which to create the differential matrix
576 !> @param[in] next_space The MFormSpace for the next m-form space in the DeRham sequence (i.e., next_space=next(space))
577 297 subroutine diff_matrix_derham(diff, space, next_space)
578 implicit none
579
580 Mat, intent(out) :: diff
581 type(MFormSpace), intent(in) :: space, next_space
582
583
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 297 times.
297 if (space%m + 1 /= next_space%m) then
584 error stop "diff_matrix_derham: space and next_space must be consecutive in the DeRham sequence"
585 end if
586
587 269 select case (space%m)
588 case (0)
589 297 call gradient_matrix(diff, space, next_space)
590 case (1)
591 28 call curl_matrix(diff, space, next_space)
592 case (2)
593
2/4
✓ Branch 4 → 5 taken 269 times.
✓ Branch 4 → 7 taken 28 times.
✗ Branch 4 → 9 not taken.
✗ Branch 4 → 10 not taken.
297 call divergence_matrix(diff, space, next_space)
594 end select
595 297 end subroutine diff_matrix_derham
596
597 !> @brief Create the matrix representation of the weak form of the gradient operator in the DeRham sequence
598 !>
599 !> @param[out] grad The matrix to create
600 !> @param[in] space The MFormSpace for which to create the gradient matrix
601 !> @param[in] next_space The MFormSpace for the next m-form space in the DeRham sequence (i.e., next_space=next(space))
602 294 subroutine gradient_matrix(grad, space, next_space)
603 use m_tensorprod, only: size
604 use m_mform_basis, only: size
605 implicit none
606
607 Mat, intent(out) :: grad
608 type(MFormSpace), intent(in) :: space, next_space
609
610 integer :: ierr, local_nz_per_row, nonlocal_nz_per_row
611 integer :: blk
612
613 294 local_nz_per_row = 2
614 294 nonlocal_nz_per_row = 2
615 call MatCreateAIJ(space%tp_spaces(1)%domain%comm, size(next_space, my_rank=.true.), size(space, my_rank=.true.), &
616 & size(next_space), size(space), &
617 & local_nz_per_row, PETSC_NULL_INTEGER_ARRAY, nonlocal_nz_per_row, &
618
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 294 times.
294 & PETSC_NULL_INTEGER_ARRAY, grad, ierr); CHKERRQ(ierr)
619
620
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 294 times.
294 PetscCall(MatSetFromOptions(grad, ierr))
621
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 294 times.
294 PetscCall(MatSetUp(grad, ierr))
622
623
2/2
✓ Branch 12 → 13 taken 602 times.
✓ Branch 12 → 15 taken 294 times.
896 do blk = 1, next_space%dimensionality
624 896 call insert_diff_matrix(grad, next_space%tp_spaces(blk), space%tp_spaces(1), blk)
625 end do
626
627
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 294 times.
294 PetscCall(MatAssemblyBegin(grad, MAT_FINAL_ASSEMBLY, ierr))
628
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 294 times.
294 PetscCall(MatAssemblyEnd(grad, MAT_FINAL_ASSEMBLY, ierr))
629 end subroutine gradient_matrix
630
631 !> @brief Create the matrix representation of the weak form of the curl operator in the DeRham sequence
632 !>
633 !> @param[out] curl The matrix to create
634 !> @param[in] space The MFormSpace for which to create the curl matrix
635 !> @param[in] next_space The MFormSpace for the next m-form space in the DeRham sequence (i.e., next_space=next(space))
636 30 subroutine curl_matrix(curl, space, next_space)
637 use m_tensorprod, only: size
638 use m_common, only: levi_civita, wp
639 use m_mform_basis, only: size
640 implicit none
641
642 Mat, intent(out) :: curl
643 type(MFormSpace), intent(in) :: space, next_space
644
645 integer :: ierr, local_nz_per_row, nonlocal_nz_per_row
646 integer :: row_blk, col_blk, dir, lc
647
648 30 local_nz_per_row = 4
649 30 nonlocal_nz_per_row = 4
650 call MatCreateAIJ(space%tp_spaces(1)%domain%comm, size(next_space, my_rank=.true.), size(space, my_rank=.true.), &
651 & size(next_space), size(space), &
652 & local_nz_per_row, PETSC_NULL_INTEGER_ARRAY, nonlocal_nz_per_row, &
653
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 30 times.
30 & PETSC_NULL_INTEGER_ARRAY, curl, ierr); CHKERRQ(ierr)
654
655
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 30 times.
30 PetscCall(MatSetFromOptions(curl, ierr))
656
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 30 times.
30 PetscCall(MatSetUp(curl, ierr))
657
658
2/2
✓ Branch 12 → 13 taken 90 times.
✓ Branch 12 → 25 taken 30 times.
120 do row_blk = 1, 3
659
2/2
✓ Branch 14 → 15 taken 270 times.
✓ Branch 14 → 23 taken 90 times.
390 do col_blk = 1, 3
660
2/2
✓ Branch 16 → 17 taken 747 times.
✓ Branch 16 → 21 taken 270 times.
1107 do dir = 1, space%dimensionality
661 747 lc = levi_civita(row_blk, dir, col_blk)
662
2/2
✓ Branch 17 → 18 taken 166 times.
✓ Branch 17 → 20 taken 581 times.
1017 if (lc /= 0) then
663 call insert_diff_matrix(curl, next_space%tp_spaces(row_blk), space%tp_spaces(col_blk), &
664 166 dir, multiply_by=real(lc, kind=wp))
665 end if
666 end do
667 end do
668 end do
669
670
1/2
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 30 times.
30 PetscCall(MatAssemblyBegin(curl, MAT_FINAL_ASSEMBLY, ierr))
671
1/2
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 32 taken 30 times.
30 PetscCall(MatAssemblyEnd(curl, MAT_FINAL_ASSEMBLY, ierr))
672 end subroutine curl_matrix
673
674 !> @brief Create the matrix representation of the weak form of the divergence operator in the DeRham sequence
675 !>
676 !> @param[out] div The matrix to create
677 !> @param[in] space The MFormSpace for which to create the divergence matrix
678 !> @param[in] next_space The MFormSpace for the next m-form space in the DeRham sequence (i.e., next_space=next(space))
679 subroutine divergence_matrix(div, space, next_space)
680 use m_tensorprod, only: size
681 use m_mform_basis, only: size
682 implicit none
683
684 Mat, intent(out) :: div
685 type(MFormSpace), intent(in) :: space, next_space
686
687 integer :: ierr, local_nz_per_row, nonlocal_nz_per_row
688 integer :: blk
689
690 local_nz_per_row = 6
691 nonlocal_nz_per_row = 6
692 call MatCreateAIJ(space%tp_spaces(1)%domain%comm, size(next_space, my_rank=.true.), size(space, my_rank=.true.), &
693 & size(next_space), size(space), &
694 & local_nz_per_row, PETSC_NULL_INTEGER_ARRAY, nonlocal_nz_per_row, &
695 & PETSC_NULL_INTEGER_ARRAY, div, ierr); CHKERRQ(ierr)
696
697 PetscCall(MatSetFromOptions(div, ierr))
698 PetscCall(MatSetUp(div, ierr))
699
700 do blk = 1, space%dimensionality
701 call insert_diff_matrix(div, next_space%tp_spaces(1), space%tp_spaces(blk), blk)
702 end do
703
704 PetscCall(MatAssemblyBegin(div, MAT_FINAL_ASSEMBLY, ierr))
705 PetscCall(MatAssemblyEnd(div, MAT_FINAL_ASSEMBLY, ierr))
706 end subroutine divergence_matrix
707
708 !> @brief Insert the finite difference matrix for the derivative in the given direction into the matrix
709 !>
710 !> @param[inout] mat The matrix to insert the finite difference matrix into
711 !> @param[in] row_space The MFormSpace corresponding to the rows of the matrix
712 !> @param[in] col_space The MFormSpace corresponding to the columns of the matrix
713 !> @param[in] diff_dir The direction of the derivative (1 for 'x', 2 for 'y', 3 for 'z')
714 !> @param[in] multiply_by _(optional)_ A scaling factor to apply to the finite difference matrix
715 !>
716 !> @note See also the 'add_difference' subroutine in m_mform_basis.f90
717 768 subroutine insert_diff_matrix(mat, row_space, col_space, diff_dir, multiply_by)
718 use m_common, only: wp
719 use m_tensorprod, only: size, TensorProdSpace, cartesian_to_linear
720
721 implicit none
722
723 Mat, intent(inout) :: mat
724 type(TensorProdSpace), intent(in) :: row_space, col_space ! NOTE: row_space = derivative(col_space, diff_dir)
725 integer, intent(in) :: diff_dir
726 real(wp), optional, intent(in) :: multiply_by
727
728 integer :: ierr
729 integer :: ir, jr, kr, ic, jc, kc
730 integer :: row, col_c, col_r
731
732 integer :: col_sze1, col_sze2, col_sze3
733
734 real(wp) :: multiply_by_
735
736
2/2
✓ Branch 2 → 3 taken 166 times.
✓ Branch 2 → 4 taken 602 times.
768 if (present(multiply_by)) then
737 166 multiply_by_ = multiply_by
738 else
739 multiply_by_ = 1._wp
740 end if
741
742 768 col_sze1 = size(col_space, 1)
743 768 col_sze2 = size(col_space, 2)
744 768 col_sze3 = size(col_space, 3)
745
746
2/2
✓ Branch 5 → 6 taken 5357 times.
✓ Branch 5 → 35 taken 768 times.
6125 do kc = row_space%rank_resp_bspline%k0, row_space%rank_resp_bspline%k1
747
2/2
✓ Branch 7 → 8 taken 71475 times.
✓ Branch 7 → 33 taken 5357 times.
77600 do jc = row_space%rank_resp_bspline%j0, row_space%rank_resp_bspline%j1
748
2/2
✓ Branch 9 → 10 taken 1155474 times.
✓ Branch 9 → 31 taken 71475 times.
1232306 do ic = row_space%rank_resp_bspline%i0, row_space%rank_resp_bspline%i1
749 1155474 call cartesian_to_linear(row_space, row, ic, jc, kc, is_on_my_responsible_subdomain=.true.)
750 1155474 call cartesian_to_linear(col_space, col_c, ic, jc, kc)
751
752 1155474 ir = ic
753 1155474 jr = jc
754 1155474 kr = kc
755 1576126 select case (diff_dir)
756 case (1)
757 420652 ir = mod(ic + 1, col_sze1)
758 case (2)
759 423358 jr = mod(jc + 1, col_sze2)
760 case (3)
761
3/4
✓ Branch 12 → 13 taken 420652 times.
✓ Branch 12 → 14 taken 423358 times.
✓ Branch 12 → 15 taken 311464 times.
✗ Branch 12 → 16 not taken.
1155474 kr = mod(kc + 1, col_sze3)
762 end select
763
764 1155474 call cartesian_to_linear(col_space, col_r, ir, jr, kr)
765
7/8
✓ Branch 18 → 19 taken 1155474 times.
✓ Branch 18 → 20 taken 1155474 times.
✓ Branch 21 → 22 taken 2310948 times.
✓ Branch 21 → 23 taken 1155474 times.
✓ Branch 24 → 25 taken 2310948 times.
✓ Branch 24 → 26 taken 1155474 times.
✗ Branch 27 → 28 not taken.
✓ Branch 27 → 30 taken 1155474 times.
8159793 PetscCall(MatSetValues(mat, 1, [row], 2, [col_c, col_r], [-multiply_by_, multiply_by_], INSERT_VALUES, ierr))
766 end do
767 end do
768 end do
769
770 end subroutine insert_diff_matrix
771
772 !> @brief Transpose the matrix
773 !>
774 !> @param[out] mat_t The transposed matrix
775 !> @param[in] mat The matrix to transpose
776
1/2
✓ Branch 2 → 3 taken 8 times.
✗ Branch 2 → 5 not taken.
8 subroutine transpose_abstract_matrix(mat_t, mat)
777 use m_common, only: wp
778 implicit none
779
780 class(AbstractMatrix), intent(in) :: mat
781 class(AbstractMatrix), intent(out) :: mat_t
782
783 integer :: ierr
784
785 8 call mat_t%destroy()
786
787
4/8
✓ Branch 6 → 7 taken 8 times.
✗ Branch 6 → 10 not taken.
✓ Branch 7 → 8 taken 8 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 11 taken 8 times.
✗ Branch 10 → 13 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 8 times.
8 mat_t%space_col = mat%space_row
788
4/8
✓ Branch 13 → 14 taken 8 times.
✗ Branch 13 → 17 not taken.
✓ Branch 14 → 15 taken 8 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 8 times.
✗ Branch 17 → 20 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 8 times.
8 mat_t%space_row = mat%space_col
789
790
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 24 taken 8 times.
8 if (mat%is_symmetric) then
791 PetscCall(MatDuplicate(mat%mat, MAT_COPY_VALUES, mat_t%mat, ierr))
792 else
793
1/2
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 8 times.
8 PetscCall(MatTranspose(mat%mat, MAT_INITIAL_MATRIX, mat_t%mat, ierr))
794 end if
795
796 8 mat_t%is_symmetric = mat%is_symmetric
797 8 mat_t%is_spd = mat%is_spd
798 end subroutine transpose_abstract_matrix
799
20/86
__m_mform_matrix_MOD___copy_m_mform_matrix_Diffdiffmatrix:
✓ Branch 2 → 3 taken 16 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 16 times.
✗ Branch 3 → 5 not taken.
✓ Branch 6 → 7 taken 16 times.
✗ Branch 6 → 8 not taken.
__m_mform_matrix_MOD___copy_m_mform_matrix_Diffmatrix:
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 9 not taken.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
__m_mform_matrix_MOD___copy_m_mform_matrix_Massmatrix:
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 9 not taken.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
__m_mform_matrix_MOD___copy_m_mform_matrix_Zeromatrix:
✓ Branch 2 → 3 taken 16 times.
✗ Branch 2 → 9 not taken.
✓ Branch 3 → 4 taken 16 times.
✗ Branch 3 → 5 not taken.
✓ Branch 6 → 7 taken 16 times.
✗ Branch 6 → 8 not taken.
__m_mform_matrix_MOD___final_m_mform_matrix_Abstractmatrix:
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 7 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 19 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 16 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
__m_mform_matrix_MOD___final_m_mform_matrix_Diffdiffmatrix:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 313 times.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✓ Branch 8 → 9 taken 313 times.
✓ Branch 8 → 17 taken 313 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 313 times.
✓ Branch 12 → 13 taken 313 times.
✗ Branch 12 → 16 not taken.
✓ Branch 13 → 14 taken 136 times.
✓ Branch 13 → 15 taken 177 times.
__m_mform_matrix_MOD___final_m_mform_matrix_Diffmatrix:
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 7 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 17 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 16 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
__m_mform_matrix_MOD___final_m_mform_matrix_Massmatrix:
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 7 not taken.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 17 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 16 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
__m_mform_matrix_MOD___final_m_mform_matrix_Zeromatrix:
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 7 taken 24 times.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
✓ Branch 8 → 9 taken 24 times.
✓ Branch 8 → 17 taken 24 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 24 times.
✓ Branch 12 → 13 taken 24 times.
✗ Branch 12 → 16 not taken.
✓ Branch 13 → 14 taken 16 times.
✓ Branch 13 → 15 taken 8 times.
706 end module m_mform_matrix
800