44#include "./base/base_uses.f90"
64 CHARACTER(len=*),
PARAMETER :: routinen =
'pao_param_init_linpot'
66 INTEGER :: acol, arow, handle, iatom, ikind, n, &
68 INTEGER,
DIMENSION(:),
POINTER :: blk_sizes_pri, col_blk_size, row_blk_size
69 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_v_terms
70 REAL(
dp),
DIMENSION(:, :, :),
POINTER :: v_blocks
76 CALL timeset(routinen, handle)
80 dft_control=dft_control, &
81 particle_set=particle_set, &
84 IF (dft_control%nspins /= 1) cpabort(
"open shell not yet implemented")
87 ALLOCATE (row_blk_size(natoms), col_blk_size(natoms))
89 CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
91 col_blk_size(iatom) = nterms
96 row_blk_size = blk_sizes_pri**2
98 name=
"PAO matrix_V_terms", &
99 dist=pao%diag_distribution, &
101 row_blk_size=row_blk_size, &
102 col_blk_size=col_blk_size)
104 DEALLOCATE (row_blk_size, col_blk_size)
112 iatom = arow; cpassert(arow == acol)
113 nterms =
SIZE(block_v_terms, 2)
114 IF (nterms == 0) cycle
115 n = blk_sizes_pri(iatom)
116 cpassert(n*n ==
SIZE(block_v_terms, 1))
117 ALLOCATE (v_blocks(n, n, nterms))
118 CALL linpot_calc_terms(pao, qs_env, iatom, v_blocks)
119 block_v_terms = reshape(v_blocks, (/n*n, nterms/))
120 DEALLOCATE (v_blocks)
125 CALL pao_param_linpot_regularizer(pao)
127 IF (pao%precondition) &
128 CALL pao_param_linpot_preconditioner(pao)
132 CALL timestop(handle)
139 SUBROUTINE pao_param_linpot_regularizer(pao)
142 CHARACTER(len=*),
PARAMETER :: routinen =
'pao_param_linpot_regularizer'
144 INTEGER :: acol, arow, handle, i, iatom, j, k, &
146 INTEGER,
DIMENSION(:),
POINTER :: blk_sizes_nterms
149 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: s_evals
150 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: s, s_evecs
151 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_r, v_terms
154 CALL timeset(routinen, handle)
156 IF (pao%iw > 0)
WRITE (pao%iw, *)
"PAO| Building linpot regularizer"
158 CALL dbcsr_get_info(pao%matrix_V_terms, col_blk_size=blk_sizes_nterms)
162 template=pao%matrix_V_terms, &
164 row_blk_size=blk_sizes_nterms, &
165 col_blk_size=blk_sizes_nterms, &
175 iatom = arow; cpassert(arow == acol)
176 CALL dbcsr_get_block_p(matrix=pao%matrix_V_terms, row=iatom, col=iatom, block=v_terms, found=found)
177 cpassert(
ASSOCIATED(v_terms))
178 nterms =
SIZE(v_terms, 2)
179 IF (nterms == 0) cycle
182 ALLOCATE (s(nterms, nterms))
183 s(:, :) = matmul(transpose(v_terms), v_terms)
186 ALLOCATE (s_evals(nterms), s_evecs(nterms, nterms))
192 v = pao%linpot_regu_delta/s_evals(k)
193 w = pao%linpot_regu_strength*min(1.0_dp, abs(v))
196 block_r(i, j) = block_r(i, j) + w*s_evecs(i, k)*s_evecs(j, k)
202 DEALLOCATE (s, s_evals, s_evecs)
207 CALL timestop(handle)
208 END SUBROUTINE pao_param_linpot_regularizer
214 SUBROUTINE pao_param_linpot_preconditioner(pao)
217 CHARACTER(len=*),
PARAMETER :: routinen =
'pao_param_linpot_preconditioner'
219 INTEGER :: acol, arow, handle, i, iatom, j, k, &
221 INTEGER,
DIMENSION(:),
POINTER :: blk_sizes_nterms
223 REAL(
dp) :: eval_capped
224 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: s_evals
225 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: s, s_evecs
226 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_precon, block_precon_inv, &
230 CALL timeset(routinen, handle)
232 IF (pao%iw > 0)
WRITE (pao%iw, *)
"PAO| Building linpot preconditioner"
234 CALL dbcsr_get_info(pao%matrix_V_terms, col_blk_size=blk_sizes_nterms)
237 template=pao%matrix_V_terms, &
239 row_blk_size=blk_sizes_nterms, &
240 col_blk_size=blk_sizes_nterms, &
241 name=
"PAO matrix_precon")
244 CALL dbcsr_create(pao%matrix_precon_inv, template=pao%matrix_precon, name=
"PAO matrix_precon_inv")
252 iatom = arow; cpassert(arow == acol)
253 nterms =
SIZE(block_v_terms, 2)
254 IF (nterms == 0) cycle
256 CALL dbcsr_get_block_p(matrix=pao%matrix_precon, row=iatom, col=iatom, block=block_precon, found=found)
257 CALL dbcsr_get_block_p(matrix=pao%matrix_precon_inv, row=iatom, col=iatom, block=block_precon_inv, found=found)
258 cpassert(
ASSOCIATED(block_precon))
259 cpassert(
ASSOCIATED(block_precon_inv))
261 ALLOCATE (s(nterms, nterms))
262 s(:, :) = matmul(transpose(block_v_terms), block_v_terms)
265 ALLOCATE (s_evals(nterms), s_evecs(nterms, nterms))
270 block_precon = 0.0_dp
271 block_precon_inv = 0.0_dp
273 eval_capped = max(pao%linpot_precon_delta, s_evals(k))
276 block_precon(i, j) = block_precon(i, j) + s_evecs(i, k)*s_evecs(j, k)/sqrt(eval_capped)
277 block_precon_inv(i, j) = block_precon_inv(i, j) + s_evecs(i, k)*s_evecs(j, k)*sqrt(eval_capped)
282 DEALLOCATE (s, s_evecs, s_evals)
287 CALL timestop(handle)
288 END SUBROUTINE pao_param_linpot_preconditioner
300 IF (pao%precondition)
THEN
317 INTEGER,
INTENT(IN) :: ikind
318 INTEGER,
INTENT(OUT) :: nparams
320 INTEGER :: pao_basis_size
322 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
324 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
327 basis_set=basis_set, &
328 pao_basis_size=pao_basis_size)
330 IF (pao_basis_size == basis_set%nsgf)
THEN
334 SELECT CASE (pao%parameterization)
340 cpabort(
"unknown parameterization")
359 LOGICAL,
INTENT(IN) :: gradient
360 REAL(
dp),
INTENT(INOUT),
OPTIONAL :: penalty
361 REAL(
dp),
DIMENSION(:, :),
INTENT(INOUT),
OPTIONAL :: forces
363 CHARACTER(len=*),
PARAMETER :: routinen =
'pao_calc_AB_linpot'
369 CALL timeset(routinen, handle)
371 CALL dbcsr_create(matrix_u, matrix_type=
"N", dist=pao%diag_distribution, template=matrix_s(1)%matrix)
377 CALL pao_calc_u_linpot(pao, qs_env, matrix_u, matrix_m, pao%matrix_G, penalty, forces)
380 CALL pao_calc_u_linpot(pao, qs_env, matrix_u, penalty=penalty)
385 CALL timestop(handle)
398 SUBROUTINE pao_calc_u_linpot(pao, qs_env, matrix_U, matrix_M, matrix_G, penalty, forces)
402 TYPE(
dbcsr_type),
OPTIONAL :: matrix_m, matrix_g
403 REAL(
dp),
INTENT(INOUT),
OPTIONAL :: penalty
404 REAL(
dp),
DIMENSION(:, :),
INTENT(INOUT),
OPTIONAL :: forces
406 CHARACTER(len=*),
PARAMETER :: routinen =
'pao_calc_U_linpot'
408 INTEGER :: acol, arow, handle, iatom, kterm, n, &
411 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: gaps
412 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: evals
413 REAL(
dp),
DIMENSION(:),
POINTER :: vec_m2, vec_v
414 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_g, block_m1, block_m2, block_r, &
415 block_u, block_v, block_v_terms, &
417 REAL(
dp),
DIMENSION(:, :, :),
POINTER :: m_blocks
418 REAL(kind=
dp) :: regu_energy
422 CALL timeset(routinen, handle)
424 cpassert(
PRESENT(matrix_g) .EQV.
PRESENT(matrix_m))
427 ALLOCATE (gaps(natoms), evals(10, natoms))
429 gaps(:) = huge(1.0_dp)
436 iatom = arow; cpassert(arow == acol)
437 CALL dbcsr_get_block_p(matrix=pao%matrix_R, row=iatom, col=iatom, block=block_r, found=found)
438 CALL dbcsr_get_block_p(matrix=matrix_u, row=iatom, col=iatom, block=block_u, found=found)
439 cpassert(
ASSOCIATED(block_r) .AND.
ASSOCIATED(block_u))
443 ALLOCATE (vec_v(n*n))
445 CALL dbcsr_get_block_p(matrix=pao%matrix_V_terms, row=iatom, col=iatom, block=block_v_terms, found=found)
446 cpassert(
ASSOCIATED(block_v_terms))
447 nterms =
SIZE(block_v_terms, 2)
449 vec_v = matmul(block_v_terms, block_x(:, 1))
450 block_v(1:n, 1:n) => vec_v(:)
453 IF (maxval(abs(block_v - transpose(block_v))/max(1.0_dp, maxval(abs(block_v)))) > 1e-12) &
454 cpabort(
"block_V not symmetric")
455 block_v = 0.5_dp*(block_v + transpose(block_v))
459 IF (
PRESENT(penalty) .AND. nterms > 0) &
460 regu_energy = regu_energy + dot_product(block_x(:, 1), matmul(block_r, block_x(:, 1)))
463 gap=gaps(iatom), evals=evals(:, iatom))
465 IF (
PRESENT(matrix_g))
THEN
466 cpassert(
PRESENT(matrix_m))
467 CALL dbcsr_get_block_p(matrix=matrix_m, row=iatom, col=iatom, block=block_m1, found=found)
470 IF (
ASSOCIATED(block_m1) .AND.
SIZE(block_v_terms) > 0)
THEN
471 ALLOCATE (vec_m2(n*n))
472 block_m2(1:n, 1:n) => vec_m2(:)
475 m1=block_m1, g=block_m2, gap=gaps(iatom), evals=evals(:, iatom))
476 IF (maxval(abs(block_m2 - transpose(block_m2))) > 1e-14_dp) &
477 cpabort(
"matrix not symmetric")
480 IF (
PRESENT(matrix_g))
THEN
481 CALL dbcsr_get_block_p(matrix=matrix_g, row=iatom, col=iatom, block=block_g, found=found)
482 cpassert(
ASSOCIATED(block_g))
483 block_g(:, 1) = matmul(vec_m2, block_v_terms)
484 IF (
PRESENT(penalty)) &
485 block_g = block_g + 2.0_dp*matmul(block_r, block_x)
489 IF (
PRESENT(forces))
THEN
490 ALLOCATE (m_blocks(n, n, nterms))
492 m_blocks(:, :, kterm) = block_m2*block_x(kterm, 1)
494 CALL linpot_calc_forces(pao, qs_env, iatom=iatom, m_blocks=m_blocks, forces=forces)
495 DEALLOCATE (m_blocks)
505 IF (
PRESENT(penalty))
THEN
507 CALL group%sum(penalty)
508 CALL group%sum(regu_energy)
509 penalty = penalty + regu_energy
513 IF (.NOT.
PRESENT(forces))
THEN
515 CALL group%sum(evals)
516 IF (pao%iw_fockev > 0)
THEN
518 WRITE (pao%iw_fockev, *)
"PAO| atom:", iatom,
" fock evals around gap:", evals(:, iatom)
524 IF (pao%iw_gap > 0)
THEN
526 WRITE (pao%iw_gap, *)
"PAO| atom:", iatom,
" fock gap:", gaps(iatom)
530 IF (pao%iw > 0)
WRITE (pao%iw, *)
"PAO| linpot regularization energy:", regu_energy
531 IF (pao%iw > 0)
WRITE (pao%iw,
"(A,E20.10,A,T71,I10)")
" PAO| min_gap:", minval(gaps),
" for atom:", minloc(gaps)
534 DEALLOCATE (gaps, evals)
535 CALL timestop(handle)
537 END SUBROUTINE pao_calc_u_linpot
546 SUBROUTINE linpot_calc_terms(pao, qs_env, iatom, V_blocks)
549 INTEGER,
INTENT(IN) :: iatom
550 REAL(
dp),
DIMENSION(:, :, :),
INTENT(OUT) :: v_blocks
552 SELECT CASE (pao%parameterization)
558 cpabort(
"unknown parameterization")
561 END SUBROUTINE linpot_calc_terms
571 SUBROUTINE linpot_calc_forces(pao, qs_env, iatom, M_blocks, forces)
574 INTEGER,
INTENT(IN) :: iatom
575 REAL(
dp),
DIMENSION(:, :, :),
INTENT(IN) :: m_blocks
576 REAL(
dp),
DIMENSION(:, :),
INTENT(INOUT) :: forces
578 SELECT CASE (pao%parameterization)
584 cpabort(
"unknown parameterization")
587 END SUBROUTINE linpot_calc_forces
598 CHARACTER(len=*),
PARAMETER :: routinen =
'pao_param_initguess_linpot'
600 INTEGER :: acol, arow, handle, i, iatom, j, k, n, &
602 INTEGER,
DIMENSION(:),
POINTER :: pri_basis_size
605 REAL(
dp),
ALLOCATABLE,
DIMENSION(:) :: s_evals
606 REAL(
dp),
ALLOCATABLE,
DIMENSION(:, :) :: s, s_evecs, s_inv
607 REAL(
dp),
DIMENSION(:),
POINTER :: v_guess_vec
608 REAL(
dp),
DIMENSION(:, :),
POINTER :: block_x, v_guess, v_terms
611 CALL timeset(routinen, handle)
620 iatom = arow; cpassert(arow == acol)
621 CALL dbcsr_get_block_p(matrix=pao%matrix_V_terms, row=iatom, col=iatom, block=v_terms, found=found)
622 cpassert(
ASSOCIATED(v_terms))
623 nterms =
SIZE(v_terms, 2)
624 IF (nterms == 0) cycle
627 n = pri_basis_size(iatom)
628 ALLOCATE (v_guess_vec(n*n))
629 v_guess(1:n, 1:n) => v_guess_vec
633 ALLOCATE (s(nterms, nterms))
634 s(:, :) = matmul(transpose(v_terms), v_terms)
637 ALLOCATE (s_evals(nterms), s_evecs(nterms, nterms))
642 ALLOCATE (s_inv(nterms, nterms))
645 w = s_evals(k)/(s_evals(k)**2 + pao%linpot_init_delta)
648 s_inv(i, j) = s_inv(i, j) + w*s_evecs(i, k)*s_evecs(j, k)
654 block_x(:, 1) = matmul(matmul(s_inv, transpose(v_terms)), v_guess_vec)
657 DEALLOCATE (v_guess_vec, s, s_evecs, s_evals, s_inv)
662 CALL timestop(handle)
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_iterator_next_block(iterator, row, column, block, block_number_argument_has_been_removed, row_size, col_size, row_offset, col_offset)
...
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_start(iterator, matrix, shared, dynamic, dynamic_byrows)
...
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.
integer, parameter, public dp
Machine interface based on Fortran 2003 and POSIX.
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Collection of simple mathematical functions and subroutines.
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...
Interface to the message passing library MPI.
Full parametrization of Fock matrix, ie. the identity parametrization.
subroutine, public linpot_full_calc_terms(v_blocks)
Builds potential terms.
subroutine, public linpot_full_count_terms(qs_env, ikind, nterms)
Count number of terms for given atomic kind.
Rotationally invariant parametrization of Fock matrix.
subroutine, public linpot_rotinv_calc_forces(qs_env, iatom, m_blocks, forces)
Calculate force contribution from rotinv parametrization.
subroutine, public linpot_rotinv_calc_terms(qs_env, iatom, v_blocks)
Calculate all potential terms of the rotinv parametrization.
subroutine, public linpot_rotinv_count_terms(qs_env, ikind, nterms)
Count number of terms for given atomic kind.
Common framework for using eigenvectors of a Fock matrix as PAO basis.
subroutine, public pao_calc_u_block_fock(pao, iatom, v, u, penalty, gap, evals, m1, g)
Calculate new matrix U and optinally its gradient G.
Common framework for a linear parametrization of the potential.
subroutine, public pao_param_finalize_linpot(pao)
Finalize the linear potential parametrization.
subroutine, public pao_param_init_linpot(pao, qs_env)
Initialize the linear potential parametrization.
subroutine, public pao_calc_ab_linpot(pao, qs_env, ls_scf_env, gradient, penalty, forces)
Takes current matrix_X and calculates the matrices A and B.
subroutine, public pao_param_count_linpot(pao, qs_env, ikind, nparams)
Returns the number of potential terms for given atomic kind.
subroutine, public pao_param_initguess_linpot(pao, qs_env)
Calculate initial guess for matrix_X.
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.
Define the data structure for the particle information.
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, 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, 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, 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, ecoul_1c, rho0_s_rs, rho0_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)
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, 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, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.