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 |