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)) &
93 cpabort(
"MOM: all molecular orbital indices must be positive integer numbers")
100 CALL timestop(handle)
102 END FUNCTION mom_is_unique_orbital_indices
115 SUBROUTINE mom_reoccupy_orbitals(mo_set, deocc_orb_set, occ_orb_set, spin)
116 TYPE(mo_set_type),
INTENT(INOUT) :: mo_set
117 INTEGER,
DIMENSION(:),
POINTER :: deocc_orb_set, occ_orb_set
118 CHARACTER(len=*),
INTENT(in) :: spin
120 CHARACTER(len=*),
PARAMETER :: routineN =
'mom_reoccupy_orbitals'
122 CHARACTER(len=10) :: str_iorb, str_norbs
123 CHARACTER(len=3) :: str_prefix
124 INTEGER :: handle, homo, iorb, lfomo, nao, nmo, &
126 REAL(kind=
dp) :: maxocc
127 REAL(kind=
dp),
DIMENSION(:),
POINTER :: occ_nums
129 CALL timeset(routinen, handle)
134 norbs =
SIZE(deocc_orb_set)
137 cpassert(
SIZE(deocc_orb_set) ==
SIZE(occ_orb_set))
140 CALL set_mo_set(mo_set=mo_set, uniform_occupation=.false.)
142 IF (deocc_orb_set(1) /= 0 .AND. occ_orb_set(1) /= 0)
THEN
143 CALL get_mo_set(mo_set=mo_set, maxocc=maxocc, &
144 nao=nao, nmo=nmo, occupation_numbers=occ_nums)
146 IF (deocc_orb_set(norbs) > nao .OR. occ_orb_set(norbs) > nao)
THEN
150 IF (deocc_orb_set(norbs) >= occ_orb_set(norbs))
THEN
151 iorb = deocc_orb_set(norbs)
154 iorb = occ_orb_set(norbs)
159 CALL cp_abort(__location__,
"Unable to "//trim(str_prefix)//
"occupy "// &
160 trim(spin)//
" orbital No. "//trim(str_iorb)// &
161 " since its index exceeds the number of atomic orbital functions available ("// &
162 trim(str_norbs)//
"). Please consider using a larger basis set.")
165 IF (deocc_orb_set(norbs) > nmo .OR. occ_orb_set(norbs) > nmo)
THEN
167 IF (deocc_orb_set(norbs) >= occ_orb_set(norbs))
THEN
168 iorb = deocc_orb_set(norbs)
170 iorb = occ_orb_set(norbs)
173 IF (iorb - nmo > 1)
THEN
183 CALL cp_abort(__location__,
"The number of molecular orbitals ("//trim(str_norbs)// &
184 ") is not enough to perform MOM calculation. Please add "// &
185 trim(str_iorb)//
" extra orbital"//trim(str_prefix)// &
186 " using the ADDED_MOS keyword in the SCF section of your input file.")
191 IF (occ_nums(deocc_orb_set(iorb)) <= 0.0_dp)
THEN
194 CALL cp_abort(__location__,
"The "//trim(spin)//
" orbital No. "// &
195 trim(str_iorb)//
" is not occupied thus it cannot be deoccupied.")
198 IF (occ_nums(occ_orb_set(iorb)) > 0.0_dp)
THEN
201 CALL cp_abort(__location__,
"The "//trim(spin)//
" orbital No. "// &
202 trim(str_iorb)//
" is already occupied thus it cannot be reoccupied.")
205 occ_nums(occ_orb_set(iorb)) = occ_nums(deocc_orb_set(iorb))
206 occ_nums(deocc_orb_set(iorb)) = 0.0_dp
211 IF (occ_nums(lfomo) /= maxocc)
EXIT
216 IF (occ_nums(homo) > 0.0_dp)
EXIT
219 CALL set_mo_set(mo_set=mo_set, homo=homo, lfomo=lfomo)
221 ELSE IF (deocc_orb_set(1) /= 0 .OR. occ_orb_set(1) /= 0)
THEN
222 CALL cp_abort(__location__, &
223 "Incorrect multiplicity of the MOM reference electronic state")
226 CALL timestop(handle)
228 END SUBROUTINE mom_reoccupy_orbitals
240 INTEGER,
INTENT(in) :: nspins
241 TYPE(
mo_set_type),
DIMENSION(:),
INTENT(INOUT) :: mos
245 CHARACTER(len=*),
PARAMETER :: routinen =
'do_mom_guess'
247 CHARACTER(len=10) :: str_iter
248 INTEGER :: handle, ispin, scf_iter
250 REAL(kind=
dp) :: maxa
253 CALL timeset(routinen, handle)
257 IF (scf_control%diagonalization%mom_type ==
momtype_mom)
THEN
259 ELSE IF (scf_control%diagonalization%mom_type ==
momtype_imom)
THEN
265 (mom_is_unique_orbital_indices(scf_control%diagonalization%mom_deoccA) .AND. &
266 mom_is_unique_orbital_indices(scf_control%diagonalization%mom_deoccB) .AND. &
267 mom_is_unique_orbital_indices(scf_control%diagonalization%mom_occA) .AND. &
268 mom_is_unique_orbital_indices(scf_control%diagonalization%mom_occB))) &
269 CALL cp_abort(__location__, &
270 "Duplicate orbital indices were found in the MOM section")
273 IF (nspins == 1 .AND. (scf_control%diagonalization%mom_deoccB(1) /= 0 &
274 .OR. scf_control%diagonalization%mom_occB(1) /= 0))
THEN
276 CALL cp_warn(__location__,
"Maximum overlap method will"// &
277 " ignore beta orbitals since neither UKS nor ROKS calculation is performed")
281 IF (
SIZE(scf_control%diagonalization%mom_deoccA) /= &
282 SIZE(scf_control%diagonalization%mom_occA) .OR. &
284 SIZE(scf_control%diagonalization%mom_deoccB) /= &
285 SIZE(scf_control%diagonalization%mom_occB)))
THEN
287 CALL cp_abort(__location__,
"Incorrect multiplicity of the MOM reference"// &
288 " electronic state or inconsistent number of electrons")
298 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
301 IF (maxa > 0.0_dp)
THEN
312 CALL mom_reoccupy_orbitals(mos(1), &
313 scf_control%diagonalization%mom_deoccA, &
314 scf_control%diagonalization%mom_occA,
'alpha')
318 CALL mom_reoccupy_orbitals(mos(2), &
319 scf_control%diagonalization%mom_deoccB, &
320 scf_control%diagonalization%mom_occB,
'beta')
332 IF (scf_control%diagonalization%mom_start < scf_iter)
THEN
333 IF (scf_control%diagonalization%mom_start > 0)
THEN
337 CALL cp_warn(__location__, &
338 "The maximum overlap method will be activated at the SCF iteration No. "// &
339 trim(str_iter)//
" due to the SCF guess method used.")
341 scf_control%diagonalization%mom_start = scf_iter
342 ELSE IF (scf_control%diagonalization%mom_start > scf_iter .AND. &
343 (scf_control%diagonalization%mom_occA(1) > 0 .OR. scf_control%diagonalization%mom_occB(1) > 0))
THEN
346 CALL cp_warn(__location__, &
347 "The maximum overlap method will be activated at the SCF iteration No. "// &
348 trim(str_iter)//
" because an excited state calculation has been requested")
349 scf_control%diagonalization%mom_start = scf_iter
353 scf_control%diagonalization%mom_didguess = .true.
355 CALL timestop(handle)
374 SUBROUTINE do_mom_diag(scf_env, mos, matrix_ks, matrix_s, scf_control, scf_section, diis_step)
376 TYPE(
mo_set_type),
DIMENSION(:),
INTENT(INOUT) :: mos
377 TYPE(
dbcsr_p_type),
DIMENSION(:),
POINTER :: matrix_ks, matrix_s
380 LOGICAL,
INTENT(INOUT) :: diis_step
382 CHARACTER(len=*),
PARAMETER :: routinen =
'do_mom_diag'
384 INTEGER :: handle, homo, iproj, ispin, lfomo, nao, &
386 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: inds
387 REAL(kind=
dp) :: maxocc
388 REAL(kind=
dp),
DIMENSION(:),
POINTER :: occ_nums, proj, tmp_occ_nums
391 TYPE(
cp_fm_type),
POINTER :: mo_coeff, mo_coeff_ref, overlap, svec
393 CALL timeset(routinen, handle)
395 IF (.NOT. scf_control%diagonalization%mom_didguess) &
396 CALL cp_abort(__location__, &
397 "The current implementation of the maximum overlap method is incompatible with the initial SCF guess")
400 nspins =
SIZE(matrix_ks)
403 IF (scf_env%iter_count >= scf_control%diagonalization%mom_start)
THEN
404 IF (.NOT.
ASSOCIATED(scf_env%mom_ref_mo_coeff))
THEN
405 ALLOCATE (scf_env%mom_ref_mo_coeff(nspins))
407 NULLIFY (ao_mo_fmstruct)
408 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, occupation_numbers=occ_nums)
410 CALL cp_fm_create(scf_env%mom_ref_mo_coeff(ispin), ao_mo_fmstruct)
413 IF (scf_control%diagonalization%mom_type ==
momtype_imom)
THEN
414 CALL cp_fm_to_fm(mo_coeff, scf_env%mom_ref_mo_coeff(ispin))
421 IF (.NOT.
ASSOCIATED(scf_env%mom_overlap))
THEN
422 ALLOCATE (scf_env%mom_overlap(nspins))
424 NULLIFY (blacs_env, mo_mo_fmstruct)
425 CALL get_mo_set(mo_set=mos(ispin), nmo=nmo, mo_coeff=mo_coeff)
427 CALL cp_fm_struct_create(mo_mo_fmstruct, nrow_global=nmo, ncol_global=nmo, context=blacs_env)
428 CALL cp_fm_create(scf_env%mom_overlap(ispin), mo_mo_fmstruct)
434 IF (.NOT.
ASSOCIATED(scf_env%mom_s_mo_coeff))
THEN
435 ALLOCATE (scf_env%mom_s_mo_coeff(nspins))
437 NULLIFY (ao_mo_fmstruct)
438 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff)
440 CALL cp_fm_create(scf_env%mom_s_mo_coeff(ispin), ao_mo_fmstruct)
445 IF (scf_control%diagonalization%mom_type ==
momtype_mom)
THEN
447 CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, occupation_numbers=occ_nums)
448 CALL cp_fm_to_fm(mo_coeff, scf_env%mom_ref_mo_coeff(ispin))
455 CALL general_eigenproblem(scf_env, mos, matrix_ks, matrix_s, scf_control, scf_section, diis_step)
457 IF (scf_env%iter_count >= scf_control%diagonalization%mom_start)
THEN
461 CALL get_mo_set(mo_set=mos(ispin), maxocc=maxocc, mo_coeff=mo_coeff, &
462 nao=nao, nmo=nmo, occupation_numbers=occ_nums)
464 mo_coeff_ref => scf_env%mom_ref_mo_coeff(ispin)
465 overlap => scf_env%mom_overlap(ispin)
466 svec => scf_env%mom_s_mo_coeff(ispin)
472 CALL parallel_gemm(
'T',
'N', nmo, nmo, nao, 1.0_dp, mo_coeff_ref, svec, 0.0_dp, overlap)
476 ALLOCATE (tmp_occ_nums(nmo))
479 SELECT CASE (scf_control%diagonalization%mom_proj_formula)
485 proj(iproj) = abs(proj(iproj))
493 cpabort(
"Unimplemented projection formula")
496 tmp_occ_nums(:) = occ_nums(:)
498 CALL sort(tmp_occ_nums, nmo, inds)
500 CALL sort(proj, nmo, inds)
504 occ_nums(inds(iproj)) = tmp_occ_nums(iproj)
507 DEALLOCATE (tmp_occ_nums)
513 IF (occ_nums(lfomo) /= maxocc)
EXIT
518 IF (occ_nums(homo) > 0.0_dp)
EXIT
521 CALL set_mo_set(mo_set=mos(ispin), homo=homo, lfomo=lfomo)
530 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, use_sp)
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