65 SUBROUTINE compute_s_square(mos, matrix_s, s_square, s_square_ideal, mo_derivs, strength)
69 REAL(kind=
dp),
INTENT(OUT) :: s_square, s_square_ideal
70 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(INOUT), &
72 REAL(kind=
dp),
INTENT(IN),
OPTIONAL :: strength
74 CHARACTER(len=*),
PARAMETER :: routinen =
'compute_s_square'
76 INTEGER :: handle, i, j, nalpha, nao, nao_beta, &
77 nbeta, ncol_local, nmo_alpha, &
79 LOGICAL :: has_uniform_occupation_alpha, &
80 has_uniform_occupation_beta
82 REAL(kind=
dp),
CONTIGUOUS,
DIMENSION(:, :), &
90 CALL timeset(routinen, handle)
93 NULLIFY (fm_struct_tmp)
97 SELECT CASE (
SIZE(mos))
101 s_square_ideal = 0.0_dp
103 cpassert(
PRESENT(mo_derivs) .OR.
PRESENT(strength))
105 CALL get_mo_set(mo_set=mos(1), mo_coeff=c_alpha, homo=nalpha, nmo=nmo_alpha, nao=nao)
106 CALL get_mo_set(mo_set=mos(2), mo_coeff=c_beta, homo=nbeta, nmo=nmo_beta, nao=nao_beta)
107 cpassert(nao == nao_beta)
112 IF (has_uniform_occupation_alpha .AND. has_uniform_occupation_beta)
THEN
114 s_square_ideal = real((nalpha - nbeta)*(nalpha - nbeta + 2), kind=
dp)/4.0_dp
118 nrow_global=nalpha, ncol_global=nbeta)
120 CALL cp_fm_create(catscb, fm_struct_tmp, name=
"C(alpha)^T*S*C(beta)")
128 CALL parallel_gemm(
'T',
'N', nalpha, nbeta, nao, 1.0_dp, c_alpha, scb, 0.0_dp, catscb)
130 CALL cp_fm_get_info(catscb, local_data=local_data, nrow_local=nrow_local, ncol_local=ncol_local)
134 s2 = s2 + local_data(i, j)**2
137 CALL para_env%sum(s2)
138 s_square = s_square_ideal + nbeta - s2
140 IF (
PRESENT(mo_derivs))
THEN
141 cpassert(
SIZE(mo_derivs, 1) == 2)
143 CALL get_mo_set(mo_set=mos(1), uniform_occupation=has_uniform_occupation_alpha)
144 cpassert(has_uniform_occupation_alpha)
145 CALL get_mo_set(mo_set=mos(2), uniform_occupation=has_uniform_occupation_beta)
146 cpassert(has_uniform_occupation_beta)
148 CALL parallel_gemm(
'N',
'T', nao, nalpha, nbeta, -strength, scb, catscb, 1.0_dp, mo_derivs(1))
151 CALL cp_fm_create(sca, fm_struct_tmp, name=
"S*C(alpha)")
155 CALL parallel_gemm(
'N',
'N', nao, nbeta, nalpha, -strength, sca, catscb, 1.0_dp, mo_derivs(2))
161 IF (.NOT. has_uniform_occupation_alpha)
THEN
162 cphint(
"The alpha orbitals (MOs) have a non-uniform occupation")
164 IF (.NOT. has_uniform_occupation_beta)
THEN
165 cphint(
"The beta orbitals (MOs) have a non-uniform occupation")
167 cphint(
"Skipping S**2 calculation")
171 cpabort(
"Alpha, beta, what else?")
174 CALL timestop(handle)
190 s2_restraint_control, just_energy)
194 TYPE(
cp_fm_type),
DIMENSION(:),
INTENT(INOUT) :: mo_derivs
195 REAL(kind=
dp) :: energy
197 LOGICAL :: just_energy
199 CHARACTER(len=*),
PARAMETER :: routinen =
's2_restraint'
202 REAL(kind=
dp) :: s_square, s_square_ideal
204 CALL timeset(routinen, handle)
206 SELECT CASE (s2_restraint_control%functional_form)
208 IF (just_energy)
THEN
212 mo_derivs, s2_restraint_control%strength)
214 energy = s2_restraint_control%strength*(s_square - s2_restraint_control%target)
215 s2_restraint_control%s2_order_p = s_square
222 CALL timestop(handle)
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_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 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.