(git:71c3ab0)
Loading...
Searching...
No Matches
pao_param_exp.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Original matrix exponential parametrization
10!> \author Ole Schuett
11! **************************************************************************************************
14 USE cp_dbcsr_api, ONLY: &
20 USE kinds, ONLY: dp
21 USE mathlib, ONLY: diag_antisym,&
26 USE pao_types, ONLY: pao_env_type
29 USE qs_kind_types, ONLY: get_qs_kind,&
31#include "./base/base_uses.f90"
32
33 IMPLICIT NONE
34
35 PRIVATE
36
37 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'pao_param_exp'
38
41
42CONTAINS
43
44! **************************************************************************************************
45!> \brief Initialize matrix exponential parametrization
46!> \param pao ...
47!> \param qs_env ...
48! **************************************************************************************************
49 SUBROUTINE pao_param_init_exp(pao, qs_env)
50 TYPE(pao_env_type), POINTER :: pao
51 TYPE(qs_environment_type), POINTER :: qs_env
52
53 CHARACTER(len=*), PARAMETER :: routinen = 'pao_param_init_exp'
54
55 INTEGER :: acol, arow, handle, iatom, n
56 LOGICAL :: found
57 REAL(dp), DIMENSION(:), POINTER :: h_evals
58 REAL(dp), DIMENSION(:, :), POINTER :: block_h, block_h0, block_n, block_u0, &
59 block_v0, h_evecs
60 TYPE(dbcsr_iterator_type) :: iter
61 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
62
63 CALL timeset(routinen, handle)
64
65 CALL get_qs_env(qs_env, matrix_s=matrix_s)
66
67 ! allocate matrix_U0
68 CALL dbcsr_create(pao%matrix_U0, &
69 name="PAO matrix_U0", &
70 matrix_type="N", &
71 dist=pao%diag_distribution, &
72 template=matrix_s(1)%matrix)
73 CALL dbcsr_reserve_diag_blocks(pao%matrix_U0)
74
75 ! diagonalize each block of H0 and store eigenvectors in U0
76!$OMP PARALLEL DEFAULT(NONE) SHARED(pao,qs_env) &
77!$OMP PRIVATE(iter,arow,acol,iatom,N,found,block_H0,block_V0,block_N,block_H,block_U0,H_evecs,H_evals)
78 CALL dbcsr_iterator_start(iter, pao%matrix_U0)
79 DO WHILE (dbcsr_iterator_blocks_left(iter))
80 CALL dbcsr_iterator_next_block(iter, arow, acol, block_u0)
81 iatom = arow; cpassert(arow == acol)
82 CALL dbcsr_get_block_p(matrix=pao%matrix_H0, row=iatom, col=iatom, block=block_h0, found=found)
83 CALL dbcsr_get_block_p(matrix=pao%matrix_N_diag, row=iatom, col=iatom, block=block_n, found=found)
84 cpassert(ASSOCIATED(block_h0) .AND. ASSOCIATED(block_n))
85 n = SIZE(block_u0, 1)
86
87 ALLOCATE (block_v0(n, n))
88 CALL pao_guess_initial_potential(qs_env, iatom, block_v0)
89
90 ! construct H
91 ALLOCATE (block_h(n, n))
92 block_h = matmul(matmul(block_n, block_h0 + block_v0), block_n) ! transform into orthonormal basis
93
94 ! diagonalize H
95 ALLOCATE (h_evecs(n, n), h_evals(n))
96 h_evecs = block_h
97 CALL diamat_all(h_evecs, h_evals)
98
99 ! use eigenvectors as initial guess
100 block_u0 = h_evecs
101
102 DEALLOCATE (block_h, h_evecs, h_evals, block_v0)
103 END DO
104 CALL dbcsr_iterator_stop(iter)
105!$OMP END PARALLEL
106
107 IF (pao%precondition) THEN
108 cpabort("PAO preconditioning not supported for selected parametrization.")
109 END IF
110
111 CALL timestop(handle)
112 END SUBROUTINE pao_param_init_exp
113
114! **************************************************************************************************
115!> \brief Finalize exponential parametrization
116!> \param pao ...
117! **************************************************************************************************
119 TYPE(pao_env_type), POINTER :: pao
120
121 CALL dbcsr_release(pao%matrix_U0)
122
123 END SUBROUTINE pao_param_finalize_exp
124
125! **************************************************************************************************
126!> \brief Returns the number of parameters for given atomic kind
127!> \param qs_env ...
128!> \param ikind ...
129!> \param nparams ...
130! **************************************************************************************************
131 SUBROUTINE pao_param_count_exp(qs_env, ikind, nparams)
132 TYPE(qs_environment_type), POINTER :: qs_env
133 INTEGER, INTENT(IN) :: ikind
134 INTEGER, INTENT(OUT) :: nparams
135
136 INTEGER :: cols, pao_basis_size, pri_basis_size, &
137 rows
138 TYPE(gto_basis_set_type), POINTER :: basis_set
139 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
140
141 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
142 CALL get_qs_kind(qs_kind_set(ikind), &
143 basis_set=basis_set, &
144 pao_basis_size=pao_basis_size)
145 pri_basis_size = basis_set%nsgf
146
147 ! we only consider rotations between occupied and virtuals
148 rows = pao_basis_size
149 cols = pri_basis_size - pao_basis_size
150 nparams = rows*cols
151
152 END SUBROUTINE pao_param_count_exp
153
154! **************************************************************************************************
155!> \brief Fills matrix_X with an initial guess
156!> \param pao ...
157! **************************************************************************************************
159 TYPE(pao_env_type), POINTER :: pao
160
161 CALL dbcsr_set(pao%matrix_X, 0.0_dp) ! actual initial guess is matrix_U0
162
163 END SUBROUTINE pao_param_initguess_exp
164
165! **************************************************************************************************
166!> \brief Takes current matrix_X and calculates the matrices A and B.
167!> \param pao ...
168!> \param qs_env ...
169!> \param ls_scf_env ...
170!> \param gradient ...
171! **************************************************************************************************
172 SUBROUTINE pao_calc_ab_exp(pao, qs_env, ls_scf_env, gradient)
173 TYPE(pao_env_type), POINTER :: pao
174 TYPE(qs_environment_type), POINTER :: qs_env
175 TYPE(ls_scf_env_type), TARGET :: ls_scf_env
176 LOGICAL, INTENT(IN) :: gradient
177
178 CHARACTER(len=*), PARAMETER :: routinen = 'pao_calc_AB_exp'
179
180 INTEGER :: handle
181 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
182 TYPE(dbcsr_type) :: matrix_m, matrix_u
183
184 CALL timeset(routinen, handle)
185 CALL get_qs_env(qs_env, matrix_s=matrix_s)
186 CALL dbcsr_create(matrix_u, matrix_type="N", dist=pao%diag_distribution, template=matrix_s(1)%matrix)
187 CALL dbcsr_reserve_diag_blocks(matrix_u)
188
189 !TODO: move this condition into pao_calc_U, use matrix_N as template
190 IF (gradient) THEN
191 CALL pao_calc_grad_lnv_wrt_u(qs_env, ls_scf_env, matrix_m)
192 CALL pao_calc_u_exp(pao, matrix_u, matrix_m, pao%matrix_G)
193 CALL dbcsr_release(matrix_m)
194 ELSE
195 CALL pao_calc_u_exp(pao, matrix_u)
196 END IF
197
198 CALL pao_calc_ab_from_u(pao, qs_env, ls_scf_env, matrix_u)
199 CALL dbcsr_release(matrix_u)
200 CALL timestop(handle)
201 END SUBROUTINE pao_calc_ab_exp
202
203! **************************************************************************************************
204!> \brief Calculate new matrix U and optionally its gradient G
205!> \param pao ...
206!> \param matrix_U ...
207!> \param matrix_M ...
208!> \param matrix_G ...
209! **************************************************************************************************
210 SUBROUTINE pao_calc_u_exp(pao, matrix_U, matrix_M, matrix_G)
211 TYPE(pao_env_type), POINTER :: pao
212 TYPE(dbcsr_type) :: matrix_u
213 TYPE(dbcsr_type), OPTIONAL :: matrix_m, matrix_g
214
215 CHARACTER(len=*), PARAMETER :: routinen = 'pao_calc_U_exp'
216
217 COMPLEX(dp) :: denom
218 COMPLEX(dp), DIMENSION(:), POINTER :: evals
219 COMPLEX(dp), DIMENSION(:, :), POINTER :: block_d, evecs
220 INTEGER :: acol, arow, handle, i, iatom, j, k, m, &
221 n, nparams
222 INTEGER, DIMENSION(:), POINTER :: blk_sizes_pao, blk_sizes_pri
223 LOGICAL :: found
224 REAL(dp), DIMENSION(:, :), POINTER :: block_g, block_g_full, block_m, &
225 block_tmp, block_u, block_u0, block_x, &
226 block_x_full
227 TYPE(dbcsr_iterator_type) :: iter
228
229 CALL timeset(routinen, handle)
230
231 CALL dbcsr_get_info(pao%matrix_Y, row_blk_size=blk_sizes_pri, col_blk_size=blk_sizes_pao)
232
233!$OMP PARALLEL DEFAULT(NONE) SHARED(pao,matrix_U,matrix_M,matrix_G,blk_sizes_pri,blk_sizes_pao) &
234!$OMP PRIVATE(iter,arow,acol,iatom,N,M,nparams,i,j,k,found) &
235!$OMP PRIVATE(block_X,block_U,block_U0,block_X_full,evals,evecs) &
236!$OMP PRIVATE(block_M,block_G,block_D,block_tmp,block_G_full,denom)
237 CALL dbcsr_iterator_start(iter, pao%matrix_X)
238 DO WHILE (dbcsr_iterator_blocks_left(iter))
239 CALL dbcsr_iterator_next_block(iter, arow, acol, block_x)
240 iatom = arow; cpassert(arow == acol)
241 CALL dbcsr_get_block_p(matrix=matrix_u, row=iatom, col=iatom, block=block_u, found=found)
242 cpassert(ASSOCIATED(block_u))
243 CALL dbcsr_get_block_p(matrix=pao%matrix_U0, row=iatom, col=iatom, block=block_u0, found=found)
244 cpassert(ASSOCIATED(block_u0))
245
246 n = blk_sizes_pri(iatom) ! size of primary basis
247 m = blk_sizes_pao(iatom) ! size of pao basis
248 nparams = SIZE(block_x, 1)
249
250 ! block_X stores only rotations between occupied and virtuals
251 ! hence, we first have to build the full anti-symmetric exponent block
252 ALLOCATE (block_x_full(n, n))
253 block_x_full(:, :) = 0.0_dp
254 DO i = 1, nparams
255 block_x_full(mod(i - 1, m) + 1, m + (i - 1)/m + 1) = +block_x(i, 1)
256 block_x_full(m + (i - 1)/m + 1, mod(i - 1, m) + 1) = -block_x(i, 1)
257 END DO
258
259 ! diagonalize block_X_full
260 ALLOCATE (evals(n), evecs(n, n))
261 CALL diag_antisym(block_x_full, evecs, evals)
262
263 ! construct rotation matrix
264 block_u(:, :) = 0.0_dp
265 DO k = 1, n
266 DO i = 1, n
267 DO j = 1, n
268 block_u(i, j) = block_u(i, j) + real(exp(evals(k))*evecs(i, k)*conjg(evecs(j, k)), dp)
269 END DO
270 END DO
271 END DO
272
273 block_u = matmul(block_u0, block_u) ! prepend initial guess rotation
274
275 ! TURNING POINT (if calc grad) ------------------------------------------
276 IF (PRESENT(matrix_g)) THEN
277 cpassert(PRESENT(matrix_m))
278
279 CALL dbcsr_get_block_p(matrix=pao%matrix_G, row=iatom, col=iatom, block=block_g, found=found)
280 cpassert(ASSOCIATED(block_g))
281 CALL dbcsr_get_block_p(matrix=matrix_m, row=iatom, col=iatom, block=block_m, found=found)
282 ! don't check ASSOCIATED(block_M), it might have been filtered out.
283
284 ALLOCATE (block_d(n, n), block_tmp(n, n), block_g_full(n, n))
285 DO i = 1, n
286 DO j = 1, n
287 denom = evals(i) - evals(j)
288 IF (i == j) THEN
289 block_d(i, i) = exp(evals(i)) ! diagonal elements
290 ELSE IF (abs(denom) > 1e-10_dp) THEN
291 block_d(i, j) = (exp(evals(i)) - exp(evals(j)))/denom
292 ELSE
293 block_d(i, j) = 1.0_dp ! limit according to L'Hospital's rule
294 END IF
295 END DO
296 END DO
297
298 IF (ASSOCIATED(block_m)) THEN
299 block_tmp = matmul(transpose(block_u0), block_m)
300 ELSE
301 block_tmp = 0.0_dp
302 END IF
303 block_g_full = fold_derivatives(block_tmp, block_d, evecs)
304
305 ! return only gradient for rotations between occupied and virtuals
306 DO i = 1, nparams
307 block_g(i, 1) = 2.0_dp*block_g_full(mod(i - 1, m) + 1, m + (i - 1)/m + 1)
308 END DO
309
310 DEALLOCATE (block_d, block_tmp, block_g_full)
311 END IF
312
313 DEALLOCATE (block_x_full, evals, evecs)
314
315 END DO
316 CALL dbcsr_iterator_stop(iter)
317!$OMP END PARALLEL
318
319 CALL timestop(handle)
320 END SUBROUTINE pao_calc_u_exp
321
322! **************************************************************************************************
323!> \brief Helper routine, for calculating derivatives
324!> \param M ...
325!> \param D ...
326!> \param R ...
327!> \return ...
328! **************************************************************************************************
329 FUNCTION fold_derivatives(M, D, R) RESULT(G)
330 REAL(dp), DIMENSION(:, :), INTENT(IN) :: m
331 COMPLEX(dp), DIMENSION(:, :), INTENT(IN) :: d, r
332 REAL(dp), DIMENSION(SIZE(M, 1), SIZE(M, 1)) :: g
333
334 COMPLEX(dp), DIMENSION(:, :), POINTER :: f, rf, rm, rmr
335 INTEGER :: n
336 REAL(dp), DIMENSION(:, :), POINTER :: rfr
337
338 n = SIZE(m, 1)
339
340 ALLOCATE (rm(n, n), rmr(n, n), f(n, n), rf(n, n), rfr(n, n))
341
342 rm = matmul(transpose(conjg(r)), transpose(m))
343 rmr = matmul(rm, r)
344 f = rmr*d !Hadamard product
345 rf = matmul(r, f)
346 rfr = real(matmul(rf, transpose(conjg(r))), dp)
347
348 ! gradient dE/dX has to be anti-symmetric
349 g = 0.5_dp*(transpose(rfr) - rfr)
350
351 DEALLOCATE (rm, rmr, f, rf, rfr)
352 END FUNCTION fold_derivatives
353
354END MODULE pao_param_exp
logical function, public dbcsr_iterator_blocks_left(iterator)
...
subroutine, public dbcsr_iterator_stop(iterator)
...
subroutine, public dbcsr_get_block_p(matrix, row, col, block, found, row_size, col_size)
...
subroutine, public dbcsr_get_info(matrix, nblkrows_total, nblkcols_total, nfullrows_total, nfullcols_total, nblkrows_local, nblkcols_local, nfullrows_local, nfullcols_local, my_prow, my_pcol, local_rows, local_cols, proc_row_dist, proc_col_dist, row_blk_size, col_blk_size, row_blk_offset, col_blk_offset, distribution, name, matrix_type, group)
...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset, transposed)
...
subroutine, public dbcsr_iterator_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_reserve_diag_blocks(matrix)
Reserves all diagonal blocks.
Types needed for a linear scaling quickstep SCF run based on the density matrix.
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diag_antisym(matrix, evecs, evals)
Helper routine for diagonalizing anti symmetric matrices.
Definition mathlib.F:1930
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Definition mathlib.F:381
Original matrix exponential parametrization.
subroutine, public pao_calc_ab_exp(pao, qs_env, ls_scf_env, gradient)
Takes current matrix_X and calculates the matrices A and B.
subroutine, public pao_param_finalize_exp(pao)
Finalize exponential parametrization.
subroutine, public pao_param_initguess_exp(pao)
Fills matrix_X with an initial guess.
subroutine, public pao_param_init_exp(pao, qs_env)
Initialize matrix exponential parametrization.
subroutine, public pao_param_count_exp(qs_env, ikind, nparams)
Returns the number of parameters for given atomic kind.
Common routines for PAO parametrizations.
subroutine, public pao_calc_grad_lnv_wrt_u(qs_env, ls_scf_env, matrix_m_diag)
Helper routine, calculates partial derivative dE/dU.
subroutine, public pao_calc_ab_from_u(pao, qs_env, ls_scf_env, matrix_u_diag)
Takes current matrix_X and calculates the matrices A and B.
Factory routines for potentials used e.g. by pao_param_exp and pao_ml.
subroutine, public pao_guess_initial_potential(qs_env, iatom, block_v)
Makes an educated guess for the initial potential based on positions of neighboring atoms.
Types used by the PAO machinery.
Definition pao_types.F:12
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, cneo_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, init_u_ramping_each_scf, reltmat, ghost, monovalent, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
Provides all information about a quickstep kind.