46#include "./base/base_uses.f90"
52 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'qs_mom_methods'
55 PRIVATE :: mom_is_unique_orbital_indices, mom_reoccupy_orbitals
69 FUNCTION mom_is_unique_orbital_indices(iarr)
RESULT(is_unique)
70 INTEGER,
DIMENSION(:),
POINTER :: iarr
73 CHARACTER(len=*),
PARAMETER :: routineN =
'mom_is_unique_orbital_indices'
75 INTEGER :: handle, norbs
76 INTEGER,
DIMENSION(:),
POINTER :: tmp_iarr
78 CALL timeset(routinen, handle)
80 cpassert(
ASSOCIATED(iarr))
84 ALLOCATE (tmp_iarr(norbs))
92 IF (tmp_iarr(1) < 0 .OR. (tmp_iarr(1) == 0 .AND. norbs > 1))
THEN
93 cpabort(
"MOM: all molecular orbital indices must be positive integer numbers")
101 CALL timestop(handle)
103 END FUNCTION mom_is_unique_orbital_indices
116 SUBROUTINE mom_reoccupy_orbitals(mo_set, deocc_orb_set, occ_orb_set, spin)
117 TYPE(mo_set_type),
INTENT(INOUT) :: mo_set
118 INTEGER,
DIMENSION(:),
POINTER :: deocc_orb_set, occ_orb_set
119 CHARACTER(len=*),
INTENT(in) :: spin
121 CHARACTER(len=*),
PARAMETER :: routineN =
'mom_reoccupy_orbitals'
123 CHARACTER(len=10) :: str_iorb, str_norbs
124 CHARACTER(len=3) :: str_prefix
125 INTEGER :: handle, homo, iorb, lfomo, nao, nmo, &
127 REAL(kind=
dp) :: maxocc
128 REAL(kind=
dp),
DIMENSION(:),
POINTER :: occ_nums
130 CALL timeset(routinen, handle)
135 norbs =
SIZE(deocc_orb_set)
138 cpassert(
SIZE(deocc_orb_set) ==
SIZE(occ_orb_set))
141 CALL set_mo_set(mo_set=mo_set, uniform_occupation=.false.)
143 IF (deocc_orb_set(1) /= 0 .AND. occ_orb_set(1) /= 0)
THEN
144 CALL get_mo_set(mo_set=mo_set, maxocc=maxocc, &
145 nao=nao, nmo=nmo, occupation_numbers=occ_nums)
147 IF (deocc_orb_set(norbs) > nao .OR. occ_orb_set(norbs) > nao)
THEN
151 IF (deocc_orb_set(norbs) >= occ_orb_set(norbs))
THEN
152 iorb = deocc_orb_set(norbs)
155 iorb = occ_orb_set(norbs)
160 CALL cp_abort(__location__,
"Unable to "//trim(str_prefix)//
"occupy "// &
161 trim(spin)//
" orbital No. "//trim(str_iorb)// &
162 " since its index exceeds the number of atomic orbital functions available ("// &
163 trim(str_norbs)//
"). Please consider using a larger basis set.")
166 IF (deocc_orb_set(norbs) > nmo .OR. occ_orb_set(norbs) > nmo)
THEN
168 IF (deocc_orb_set(norbs) >= occ_orb_set(norbs))
THEN
169 iorb = deocc_orb_set(norbs)
171 iorb = occ_orb_set(norbs)
174 IF (iorb - nmo > 1)
THEN
184 CALL cp_abort(__location__,
"The number of molecular orbitals ("//trim(str_norbs)// &
185 ") is not enough to perform MOM calculation. Please add "// &
186 trim(str_iorb)//
" extra orbital"//trim(str_prefix)// &
187 " using the ADDED_MOS keyword in the SCF section of your input file.")
192 IF (occ_nums(deocc_orb_set(iorb)) <= 0.0_dp)
THEN
195 CALL cp_abort(__location__,
"The "//trim(spin)//
" orbital No. "// &
196 trim(str_iorb)//
" is not occupied thus it cannot be deoccupied.")
199 IF (occ_nums(occ_orb_set(iorb)) > 0.0_dp)
THEN
202 CALL cp_abort(__location__,
"The "//trim(spin)//
" orbital No. "// &
203 trim(str_iorb)//
" is already occupied thus it cannot be reoccupied.")
206 occ_nums(occ_orb_set(iorb)) = occ_nums(deocc_orb_set(iorb))
207 occ_nums(deocc_orb_set(iorb)) = 0.0_dp
212 IF (occ_nums(lfomo) /= maxocc)
EXIT
217 IF (occ_nums(homo) > 0.0_dp)
EXIT
220 CALL set_mo_set(mo_set=mo_set, homo=homo, lfomo=lfomo)
222 ELSE IF (deocc_orb_set(1) /= 0 .OR. occ_orb_set(1) /= 0)
THEN
223 CALL cp_abort(__location__, &
224 "Incorrect multiplicity of the MOM reference electronic state")
227 CALL timestop(handle)
229 END SUBROUTINE mom_reoccupy_orbitals
241 INTEGER,
INTENT(in) :: nspins
242 TYPE(
mo_set_type),
DIMENSION(:),
INTENT(INOUT) :: mos
246 CHARACTER(len=*),
PARAMETER :: routinen =
'do_mom_guess'
248 CHARACTER(len=10) :: str_iter
249 INTEGER :: handle, ispin, scf_iter
251 REAL(kind=
dp) :: maxa
254 CALL timeset(routinen, handle)
258 IF (scf_control%diagonalization%mom_type ==
momtype_mom)
THEN
260 ELSE IF (scf_control%diagonalization%mom_type ==
momtype_imom)
THEN
266 (mom_is_unique_orbital_indices(scf_control%diagonalization%mom_deoccA) .AND. &
267 mom_is_unique_orbital_indices(scf_control%diagonalization%mom_deoccB) .AND. &
268 mom_is_unique_orbital_indices(scf_control%diagonalization%mom_occA) .AND. &
269 mom_is_unique_orbital_indices(scf_control%diagonalization%mom_occB)))
THEN
270 CALL cp_abort(__location__, &
271 "Duplicate orbital indices were found in the MOM section")
275 IF (nspins == 1 .AND. (scf_control%diagonalization%mom_deoccB(1) /= 0 &
276 .OR. scf_control%diagonalization%mom_occB(1) /= 0))
THEN
278 CALL cp_warn(__location__,
"Maximum overlap method will"// &
279 " ignore beta orbitals since neither UKS nor ROKS calculation is performed")
283 IF (
SIZE(scf_control%diagonalization%mom_deoccA) /= &
284 SIZE(scf_control%diagonalization%mom_occA) .OR. &
286 SIZE(scf_control%diagonalization%mom_deoccB) /= &
287 SIZE(scf_control%diagonalization%mom_occB)))
THEN
289 CALL cp_abort(__location__,
"Incorrect multiplicity of the MOM reference"// &
290 " electronic state or inconsistent number of electrons")
300 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
303 IF (maxa > 0.0_dp)
THEN
313 IF (nspins >= 1)
THEN
314 CALL mom_reoccupy_orbitals(mos(1), &
315 scf_control%diagonalization%mom_deoccA, &
316 scf_control%diagonalization%mom_occA,
'alpha')
320 IF (nspins >= 2)
THEN
321 CALL mom_reoccupy_orbitals(mos(2), &
322 scf_control%diagonalization%mom_deoccB, &
323 scf_control%diagonalization%mom_occB,
'beta')
336 IF (scf_control%diagonalization%mom_start < scf_iter)
THEN
337 IF (scf_control%diagonalization%mom_start > 0)
THEN
341 CALL cp_warn(__location__, &
342 "The maximum overlap method will be activated at the SCF iteration No. "// &
343 trim(str_iter)//
" due to the SCF guess method used.")
345 scf_control%diagonalization%mom_start = scf_iter
346 ELSE IF (scf_control%diagonalization%mom_start > scf_iter .AND. &
347 (scf_control%diagonalization%mom_occA(1) > 0 .OR. scf_control%diagonalization%mom_occB(1) > 0))
THEN
350 CALL cp_warn(__location__, &
351 "The maximum overlap method will be activated at the SCF iteration No. "// &
352 trim(str_iter)//
" because an excited state calculation has been requested")
353 scf_control%diagonalization%mom_start = scf_iter
357 scf_control%diagonalization%mom_didguess = .true.
359 CALL timestop(handle)
378 SUBROUTINE do_mom_diag(scf_env, mos, matrix_ks, matrix_s, scf_control, scf_section, diis_step)
380 TYPE(
mo_set_type),
DIMENSION(:),
INTENT(INOUT) :: mos
381 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: matrix_ks, matrix_s
384 LOGICAL,
INTENT(INOUT) :: diis_step
386 CHARACTER(len=*),
PARAMETER :: routinen =
'do_mom_diag'
388 INTEGER :: handle, homo, iproj, ispin, lfomo, nao, &
390 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: inds
391 REAL(kind=
dp) :: maxocc
392 REAL(kind=
dp),
DIMENSION(:),
POINTER :: occ_nums, proj, tmp_occ_nums
395 TYPE(
cp_fm_type),
POINTER :: mo_coeff, mo_coeff_ref, overlap, svec
397 CALL timeset(routinen, handle)
399 IF (.NOT. scf_control%diagonalization%mom_didguess)
THEN
400 CALL cp_abort(__location__, &
401 "The current implementation of the maximum overlap method is incompatible with the initial SCF guess")
405 nspins =
SIZE(matrix_ks)
408 IF (scf_env%iter_count >= scf_control%diagonalization%mom_start)
THEN
409 IF (.NOT.
ASSOCIATED(scf_env%mom_ref_mo_coeff))
THEN
410 ALLOCATE (scf_env%mom_ref_mo_coeff(nspins))
412 NULLIFY (ao_mo_fmstruct)
413 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, occupation_numbers=occ_nums)
415 CALL cp_fm_create(scf_env%mom_ref_mo_coeff(ispin), ao_mo_fmstruct)
418 IF (scf_control%diagonalization%mom_type ==
momtype_imom)
THEN
419 CALL cp_fm_to_fm(mo_coeff, scf_env%mom_ref_mo_coeff(ispin))
426 IF (.NOT.
ASSOCIATED(scf_env%mom_overlap))
THEN
427 ALLOCATE (scf_env%mom_overlap(nspins))
429 NULLIFY (blacs_env, mo_mo_fmstruct)
430 CALL get_mo_set(mo_set=mos(ispin), nmo=nmo, mo_coeff=mo_coeff)
432 CALL cp_fm_struct_create(mo_mo_fmstruct, nrow_global=nmo, ncol_global=nmo, context=blacs_env)
433 CALL cp_fm_create(scf_env%mom_overlap(ispin), mo_mo_fmstruct)
439 IF (.NOT.
ASSOCIATED(scf_env%mom_s_mo_coeff))
THEN
440 ALLOCATE (scf_env%mom_s_mo_coeff(nspins))
442 NULLIFY (ao_mo_fmstruct)
443 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
445 CALL cp_fm_create(scf_env%mom_s_mo_coeff(ispin), ao_mo_fmstruct)
450 IF (scf_control%diagonalization%mom_type ==
momtype_mom)
THEN
452 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, occupation_numbers=occ_nums)
453 CALL cp_fm_to_fm(mo_coeff, scf_env%mom_ref_mo_coeff(ispin))
460 CALL general_eigenproblem(scf_env, mos, matrix_ks, matrix_s, scf_control, scf_section, diis_step)
462 IF (scf_env%iter_count >= scf_control%diagonalization%mom_start)
THEN
466 CALL get_mo_set(mo_set=mos(ispin), maxocc=maxocc, mo_coeff=mo_coeff, &
467 nao=nao, nmo=nmo, occupation_numbers=occ_nums)
469 mo_coeff_ref => scf_env%mom_ref_mo_coeff(ispin)
470 overlap => scf_env%mom_overlap(ispin)
471 svec => scf_env%mom_s_mo_coeff(ispin)
477 CALL parallel_gemm(
'T',
'N', nmo, nmo, nao, 1.0_dp, mo_coeff_ref, svec, 0.0_dp, overlap)
481 ALLOCATE (tmp_occ_nums(nmo))
484 SELECT CASE (scf_control%diagonalization%mom_proj_formula)
490 proj(iproj) = abs(proj(iproj))
498 cpabort(
"Unimplemented projection formula")
501 tmp_occ_nums(:) = occ_nums(:)
503 CALL sort(tmp_occ_nums, nmo, inds)
505 CALL sort(proj, nmo, inds)
509 occ_nums(inds(iproj)) = tmp_occ_nums(iproj)
512 DEALLOCATE (tmp_occ_nums)
518 IF (occ_nums(lfomo) /= maxocc)
EXIT
523 IF (occ_nums(homo) > 0.0_dp)
EXIT
526 CALL set_mo_set(mo_set=mos(ispin), homo=homo, lfomo=lfomo)
535 CALL timestop(handle)
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public barca2018
integer, save, public gilbert2008
methods related to the blacs parallel environment
DBCSR operations in CP2K.
subroutine, public cp_dbcsr_sm_fm_multiply(matrix, fm_in, fm_out, ncol, alpha, beta)
multiply a dbcsr with a fm matrix
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
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_get_info(matrix, name, nrow_global, ncol_global, nrow_block, ncol_block, nrow_local, ncol_local, row_indices, col_indices, local_data, context, nrow_locals, ncol_locals, matrix_struct, para_env)
returns all kind of information about the full matrix
subroutine, public cp_fm_vectorssum(matrix, sum_array, dir)
summing up all the elements along the matrix's i-th index or
subroutine, public cp_fm_vectorsnorm(matrix, norm_array)
find the inorm of each column norm_{j}= sqrt( \sum_{i} A_{ij}*A_{ij} )
subroutine, public cp_fm_maxabsval(matrix, a_max, ir_max, ic_max)
find the maximum absolute value of the matrix element maxval(abs(matrix))
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
Defines the basic variable types.
integer, parameter, public dp
basic linear algebra operations for full matrixes
collects routines that calculate density matrices
Definition and initialisation of the mo data type.
subroutine, public set_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, uniform_occupation, kts, mu, flexible_electron_count)
Set the components of a MO set data structure.
subroutine, public get_mo_set(mo_set, maxocc, homo, lfomo, nao, nelectron, n_el_f, nmo, eigenvalues, occupation_numbers, mo_coeff, mo_coeff_b, uniform_occupation, kts, mu, flexible_electron_count)
Get the components of a MO set data structure.
methods for deltaSCF calculations
subroutine, public do_mom_diag(scf_env, mos, matrix_ks, matrix_s, scf_control, scf_section, diis_step)
do an SCF iteration, then compute occupation numbers of the new molecular orbitals according to their...
subroutine, public do_mom_guess(nspins, mos, scf_control, p_rmpv)
initial guess for the maximum overlap method
Different diagonalization schemes that can be used for the iterative solution of the eigenvalue probl...
subroutine, public general_eigenproblem(scf_env, mos, matrix_ks, matrix_s, scf_control, scf_section, diis_step)
the inner loop of scf, specific to diagonalization with S matrix basically, in goes the ks matrix out...
module that contains the definitions of the scf types
parameters that control an scf iteration
Utilities for string manipulations.
subroutine, public integer_to_string(inumber, string)
Converts an integer number to a string. The WRITE statement will return an error message,...
All kind of helpful little routines.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
keeps the information about the structure of a full matrix