19 USE ieee_arithmetic,
ONLY: ieee_is_finite
23 USE iso_fortran_env,
ONLY: error_unit
35 INTEGER,
PARAMETER :: k = 3, n = 5
36 REAL(kind=
dp),
PARAMETER :: eps = 2.0e-11_dp
38 INTEGER :: i, j, rank_used
39 REAL(kind=
dp),
DIMENSION(n, k) :: gradient, gradient_rotated, hessian_x, &
40 output, output_reference, &
41 output_rotated, x_reference
42 REAL(kind=
dp),
DIMENSION(n) :: full_evals
43 REAL(kind=
dp),
DIMENSION(k) :: occ_evals
44 REAL(kind=
dp),
DIMENSION(k, k) :: occupied_h, q, rotation, rotation_2, &
46 REAL(kind=
dp),
DIMENSION(n, n) :: inverse, overlap_inverse, spectral_vectors
53 NULLIFY (blacs_env, fm_struct, para_env)
60 context=blacs_env, para_env=para_env)
61 CALL cp_fm_create(matrix_in, fm_struct, name=
"covariant test input")
62 CALL cp_fm_create(matrix_out, fm_struct, name=
"covariant test output")
66 context=blacs_env, para_env=para_env)
67 ALLOCATE (preconditioner_env%fm)
68 CALL cp_fm_create(preconditioner_env%fm, fm_struct, name=
"spectral eigenvectors")
72 context=blacs_env, para_env=para_env)
73 ALLOCATE (preconditioner_env%occ_rotation)
74 CALL cp_fm_create(preconditioner_env%occ_rotation, fm_struct, name=
"occupied rotation")
78 preconditioner_env%energy_gap = 0.10_dp
79 ALLOCATE (preconditioner_env%full_evals(n), preconditioner_env%occ_evals(k))
80 full_evals = [0.8_dp, 1.3_dp, 2.1_dp, 3.0_dp, 4.4_dp]
81 occ_evals = [-0.9_dp, -0.2_dp, 0.35_dp]
82 preconditioner_env%full_evals = full_evals
83 preconditioner_env%occ_evals = occ_evals
85 spectral_vectors = 0.0_dp
87 spectral_vectors(i, i) = 1.0_dp
90 CALL plane_rotation(0.43_dp, 1, 2, rotation)
91 CALL plane_rotation(-0.31_dp, 2, 3, q)
92 rotation = matmul(rotation, q)
97 gradient(i, j) = sin(0.37_dp*real(2*i + j,
dp)) + &
98 0.2_dp*cos(0.19_dp*real(i - 3*j,
dp))
99 x_reference(i, j) = cos(0.23_dp*real(i + 2*j,
dp)) - &
100 0.1_dp*sin(0.41_dp*real(3*i - j,
dp))
104 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output_reference)
109 occupied_h = occupied_h + occ_evals(j)*outer_product(rotation(:, j), rotation(:, j))
111 hessian_x = -matmul(x_reference, occupied_h)
113 hessian_x(i, :) = hessian_x(i, :) + full_evals(i)*x_reference(i, :)
115 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, hessian_x, output)
116 CALL assert_close(output, x_reference, eps,
"Frozen-H Sylvester inverse")
119 CALL plane_rotation(-0.37_dp, 1, 2, rotation_gauge)
120 CALL plane_rotation(0.28_dp, 2, 3, q)
121 rotation_gauge = matmul(rotation_gauge, q)
122 rotation_2 = matmul(transpose(rotation_gauge), rotation)
123 gradient_rotated = matmul(gradient, rotation_gauge)
125 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient_rotated, output_rotated)
126 CALL assert_close(output_rotated, matmul(output_reference, rotation_gauge), eps, &
127 "Occupied-gauge covariance")
130 preconditioner_env%energy_gap = 0.75_dp
131 preconditioner_env%occ_evals = [0.7_dp, 0.9_dp, 1.1_dp]
133 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output)
134 IF (sum(gradient*output) <= 0.0_dp)
THEN
135 error stop
"Gap-floor inverse is not positive definite"
142 preconditioner_env%energy_gap = 0.1_dp
143 preconditioner_env%spectral_reference = full_evals(k + 1) - 0.04_dp
144 preconditioner_env%spectral_base_scale = 1.25_dp
145 CALL plane_rotation(0.29_dp, 2, 4, spectral_vectors)
146 spectral_vectors(:, 2) = 1.2_dp*spectral_vectors(:, 2)
147 spectral_vectors(:, 4) = 0.8_dp*spectral_vectors(:, 4)
148 overlap_inverse = matmul(spectral_vectors, transpose(spectral_vectors))
150 ALLOCATE (preconditioner_env%base_fm)
151 CALL cp_fm_create(preconditioner_env%base_fm, preconditioner_env%fm%matrix_struct)
153 DO rank_used = 0, n - k
154 preconditioner_env%spectral_rank = rank_used
155 inverse = preconditioner_env%spectral_base_scale*overlap_inverse
156 DO i = k + 1, k + rank_used
157 inverse = inverse + (1.0_dp/max(preconditioner_env%energy_gap, &
158 full_evals(i) - preconditioner_env%spectral_reference) - &
159 preconditioner_env%spectral_base_scale)* &
160 outer_product(spectral_vectors(:, i), spectral_vectors(:, i))
162 output_reference = matmul(inverse, gradient)
163 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output)
164 CALL assert_close(output, output_reference, eps,
"Low-rank spectral inverse")
172 DEALLOCATE (para_env)
184 SUBROUTINE apply_fm(preconditioner_env, matrix_in, matrix_out, input, RESULT)
187 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_in, matrix_out
188 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: input
189 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: result
204 SUBROUTINE plane_rotation(angle, axis_1, axis_2, rotation)
206 REAL(KIND=
dp),
INTENT(IN) :: angle
207 INTEGER,
INTENT(IN) :: axis_1, axis_2
208 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: rotation
213 DO i = 1,
SIZE(rotation, 1)
214 rotation(i, i) = 1.0_dp
216 rotation(axis_1, axis_1) = cos(angle)
217 rotation(axis_2, axis_2) = cos(angle)
218 rotation(axis_1, axis_2) = -sin(angle)
219 rotation(axis_2, axis_1) = sin(angle)
221 END SUBROUTINE plane_rotation
229 PURE FUNCTION outer_product(left, right)
RESULT(product)
231 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: left, right
232 REAL(KIND=
dp),
DIMENSION(SIZE(left), SIZE(right)) :: product
236 DO j = 1,
SIZE(right)
238 product(i, j) = left(i)*right(j)
242 END FUNCTION outer_product
251 SUBROUTINE assert_close(actual, reference, tolerance, label)
253 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: actual, reference
254 REAL(KIND=
dp),
INTENT(IN) :: tolerance
255 CHARACTER(LEN=*),
INTENT(IN) :: label
259 IF (.NOT. all(ieee_is_finite(actual)) .OR. &
260 .NOT. all(ieee_is_finite(reference)) .OR. maxval(abs(actual - reference)) > tolerance)
THEN
262 WRITE (io_unit,
'(A,2(1X,ES13.6))') trim(label)//
": error/tolerance", &
263 maxval(abs(actual - reference)), tolerance
264 error stop
"Matrix comparison failed"
267 END SUBROUTINE assert_close
methods related to the blacs parallel environment
subroutine, public cp_blacs_env_release(blacs_env)
releases the given blacs_env
subroutine, public cp_blacs_env_create(blacs_env, para_env, blacs_grid_layout, blacs_repeatable, row_major, grid_2d)
allocates and initializes a type that represent a blacs context
represent the structure of a full matrix
subroutine, public cp_fm_struct_create(fmstruct, para_env, context, nrow_global, ncol_global, nrow_block, ncol_block, descriptor, first_p_pos, local_leading_dimension, template_fmstruct, square_blocks, force_block)
allocates and initializes a full matrix structure
subroutine, public cp_fm_struct_release(fmstruct)
releases a full matrix structure
represent a full matrix distributed on many processors
subroutine, public cp_fm_set_submatrix(fm, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
sets a submatrix of a full matrix fm(start_row:start_row+n_rows,start_col:start_col+n_cols) = alpha*o...
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
subroutine, public cp_fm_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
Defines the basic variable types.
integer, parameter, public dp
Interface to the message passing library MPI.
subroutine, public mp_world_init(mp_comm)
initializes the system default communicator
subroutine, public mp_world_finalize()
Finalize the system default communicator and MPI when CP2K owns MPI.
computes preconditioners, and implements methods to apply them currently used in qs_ot
subroutine, public apply_preconditioner_fm(preconditioner_env, matrix_in, matrix_out)
applies a previously created preconditioner to a full matrix
subroutine, public init_preconditioner(preconditioner_env, para_env, blacs_env)
...
subroutine, public destroy_preconditioner(preconditioner_env)
...
subroutine apply_fm(preconditioner_env, matrix_in, matrix_out, input, result)
Apply the production FM path to a replicated test matrix.
program ot_covariant_preconditioner_unittest
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix
stores all the informations relevant to an mpi environment