31 INTEGER,
PARAMETER :: k = 3, n = 5
32 REAL(kind=
dp),
PARAMETER :: eps = 2.0e-11_dp
35 REAL(kind=
dp),
DIMENSION(n, k) :: gradient, gradient_rotated, hessian_x, &
36 output, output_reference, &
37 output_rotated, x_reference
38 REAL(kind=
dp),
DIMENSION(n) :: full_evals
39 REAL(kind=
dp),
DIMENSION(k) :: occ_evals
40 REAL(kind=
dp),
DIMENSION(k, k) :: occupied_h, q, rotation, rotation_2, &
48 NULLIFY (blacs_env, fm_struct, para_env)
55 context=blacs_env, para_env=para_env)
56 CALL cp_fm_create(matrix_in, fm_struct, name=
"covariant test input")
57 CALL cp_fm_create(matrix_out, fm_struct, name=
"covariant test output")
61 context=blacs_env, para_env=para_env)
62 ALLOCATE (preconditioner_env%fm)
63 CALL cp_fm_create(preconditioner_env%fm, fm_struct, name=
"spectral eigenvectors")
67 context=blacs_env, para_env=para_env)
68 ALLOCATE (preconditioner_env%occ_rotation)
69 CALL cp_fm_create(preconditioner_env%occ_rotation, fm_struct, name=
"occupied rotation")
73 preconditioner_env%energy_gap = 0.10_dp
74 ALLOCATE (preconditioner_env%full_evals(n), preconditioner_env%occ_evals(k))
75 full_evals = [0.8_dp, 1.3_dp, 2.1_dp, 3.0_dp, 4.4_dp]
76 occ_evals = [-0.9_dp, -0.2_dp, 0.35_dp]
77 preconditioner_env%full_evals = full_evals
78 preconditioner_env%occ_evals = occ_evals
80 CALL set_identity(preconditioner_env%fm, n)
81 CALL make_rotation(0.43_dp, -0.31_dp, rotation)
86 gradient(i, j) = sin(0.37_dp*real(2*i + j,
dp)) + &
87 0.2_dp*cos(0.19_dp*real(i - 3*j,
dp))
88 x_reference(i, j) = cos(0.23_dp*real(i + 2*j,
dp)) - &
89 0.1_dp*sin(0.41_dp*real(3*i - j,
dp))
94 CALL apply_model(gradient, rotation, full_evals, occ_evals, &
95 preconditioner_env%energy_gap, output_reference)
96 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output)
97 CALL assert_close(output, output_reference, eps,
"Explicit covariant spectral inverse")
102 occupied_h = occupied_h + occ_evals(j)*outer_product(rotation(:, j), rotation(:, j))
104 hessian_x = -matmul(x_reference, occupied_h)
106 hessian_x(i, :) = hessian_x(i, :) + full_evals(i)*x_reference(i, :)
108 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, hessian_x, output)
109 CALL assert_close(output, x_reference, eps,
"Frozen-H Sylvester inverse")
112 CALL make_rotation(-0.37_dp, 0.28_dp, rotation_gauge)
113 rotation_2 = matmul(transpose(rotation_gauge), rotation)
114 gradient_rotated = matmul(gradient, rotation_gauge)
116 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient_rotated, output_rotated)
117 CALL assert_close(output_rotated, matmul(output_reference, rotation_gauge), eps, &
118 "Occupied-gauge covariance")
121 occ_evals = [-0.4_dp, -0.4_dp, 0.2_dp]
122 preconditioner_env%occ_evals = occ_evals
124 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output)
125 CALL plane_rotation(0.61_dp, 1, 2, q)
126 rotation_2 = matmul(rotation, q)
128 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output_rotated)
129 CALL assert_close(output_rotated, output, eps,
"Degenerate occupied subspace")
132 preconditioner_env%energy_gap = 0.75_dp
133 preconditioner_env%occ_evals = [0.7_dp, 0.9_dp, 1.1_dp]
135 CALL apply_fm(preconditioner_env, matrix_in, matrix_out, gradient, output)
136 IF (sum(gradient*output) <= 0.0_dp)
THEN
137 error stop
"Gap-floor inverse is not positive definite"
145 DEALLOCATE (para_env)
157 SUBROUTINE apply_fm(preconditioner_env, matrix_in, matrix_out, input, RESULT)
160 TYPE(
cp_fm_type),
INTENT(IN) :: matrix_in, matrix_out
161 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: input
162 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: result
179 SUBROUTINE apply_model(input, rotation, full_evals, occ_evals, gap, RESULT)
181 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: input, rotation
182 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: full_evals, occ_evals
183 REAL(KIND=
dp),
INTENT(IN) :: gap
184 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: result
188 DIMENSION(SIZE(input, 1), SIZE(input, 2)) :: canonical
190 canonical = matmul(input, rotation)
191 DO j = 1,
SIZE(input, 2)
192 DO i = 1,
SIZE(input, 1)
193 canonical(i, j) = canonical(i, j)/max(gap, full_evals(i) - occ_evals(j))
196 result = matmul(canonical, transpose(rotation))
198 END SUBROUTINE apply_model
206 SUBROUTINE make_rotation(angle_12, angle_23, rotation)
208 REAL(KIND=
dp),
INTENT(IN) :: angle_12, angle_23
209 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: rotation
212 DIMENSION(SIZE(rotation, 1), SIZE(rotation, 2)) :: r12, r23
214 CALL plane_rotation(angle_12, 1, 2, r12)
215 CALL plane_rotation(angle_23, 2, 3, r23)
216 rotation = matmul(r12, r23)
218 END SUBROUTINE make_rotation
227 SUBROUTINE plane_rotation(angle, axis_1, axis_2, rotation)
229 REAL(KIND=
dp),
INTENT(IN) :: angle
230 INTEGER,
INTENT(IN) :: axis_1, axis_2
231 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(OUT) :: rotation
236 DO i = 1,
SIZE(rotation, 1)
237 rotation(i, i) = 1.0_dp
239 rotation(axis_1, axis_1) = cos(angle)
240 rotation(axis_2, axis_2) = cos(angle)
241 rotation(axis_1, axis_2) = -sin(angle)
242 rotation(axis_2, axis_1) = sin(angle)
244 END SUBROUTINE plane_rotation
251 SUBROUTINE set_identity(matrix, n)
254 INTEGER,
INTENT(IN) :: n
257 REAL(KIND=
dp),
DIMENSION(n, n) :: identity
261 identity(i, i) = 1.0_dp
265 END SUBROUTINE set_identity
273 PURE FUNCTION outer_product(left, right)
RESULT(product)
275 REAL(KIND=
dp),
DIMENSION(:),
INTENT(IN) :: left, right
276 REAL(KIND=
dp),
DIMENSION(SIZE(left), SIZE(right)) :: product
280 DO j = 1,
SIZE(right)
282 product(i, j) = left(i)*right(j)
286 END FUNCTION outer_product
295 SUBROUTINE assert_close(actual, reference, tolerance, label)
297 REAL(KIND=
dp),
DIMENSION(:, :),
INTENT(IN) :: actual, reference
298 REAL(KIND=
dp),
INTENT(IN) :: tolerance
299 CHARACTER(LEN=*),
INTENT(IN) :: label
301 IF (maxval(abs(actual - reference)) > tolerance)
THEN
302 WRITE (*,
'(A)') trim(label)
303 error stop
"Matrix comparison failed"
306 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