73 SUBROUTINE wfn_mix(mos, particle_set, dft_section, qs_kind_set, para_env, output_unit, &
74 unoccupied_orbs, scf_env, matrix_s, marked_states, for_rtp)
81 INTEGER :: output_unit
83 OPTIONAL,
POINTER :: unoccupied_orbs
87 INTEGER,
DIMENSION(:, :, :),
OPTIONAL,
POINTER :: marked_states
88 LOGICAL,
OPTIONAL :: for_rtp
90 CHARACTER(len=*),
PARAMETER :: routinen =
'wfn_mix'
92 CHARACTER(LEN=default_path_length) :: read_file_name
93 INTEGER :: handle, homo, i_rep, ispin, mark_ind, mark_number, n_rep, nmo, orig_mo_index, &
94 orig_spin_index, orig_type, restart_unit, result_mo_index, result_spin_index
95 LOGICAL :: explicit, is_file, my_for_rtp, &
96 overwrite_mos, reverse_mo_index
97 REAL(kind=
dp) :: orig_scale, orthonormality, result_scale
100 TYPE(
mo_set_type),
ALLOCATABLE,
DIMENSION(:) :: mos_new, mos_orig_ext
103 CALL timeset(routinen, handle)
110 IF (
PRESENT(for_rtp))
THEN
116 IF (output_unit > 0)
THEN
117 WRITE (output_unit,
'()')
118 WRITE (output_unit,
'(T2,A)')
"Performing wfn mixing"
119 WRITE (output_unit,
'(T2,A)')
"====================="
122 ALLOCATE (mos_new(
SIZE(mos)))
123 DO ispin = 1,
SIZE(mos)
128 NULLIFY (fm_struct_vector)
129 CALL cp_fm_struct_create(fm_struct_vector, template_fmstruct=mos(1)%mo_coeff%matrix_struct, &
138 IF (.NOT. explicit) n_rep = 0
143 CALL section_vals_val_get(update_section,
"RESULT_MO_INDEX", i_rep_section=i_rep, i_val=result_mo_index)
144 CALL section_vals_val_get(update_section,
"RESULT_MARKED_STATE", i_rep_section=i_rep, i_val=mark_number)
145 CALL section_vals_val_get(update_section,
"RESULT_SPIN_INDEX", i_rep_section=i_rep, i_val=result_spin_index)
147 CALL section_vals_val_get(update_section,
"RESULT_SCALE", i_rep_section=i_rep, r_val=result_scale)
150 IF (mark_number .GT. 0) result_mo_index = marked_states(mark_number, result_spin_index, mark_ind)
155 CALL section_vals_val_get(update_section,
"ORIG_MO_INDEX", i_rep_section=i_rep, i_val=orig_mo_index)
156 CALL section_vals_val_get(update_section,
"ORIG_MARKED_STATE", i_rep_section=i_rep, i_val=mark_number)
157 CALL section_vals_val_get(update_section,
"ORIG_SPIN_INDEX", i_rep_section=i_rep, i_val=orig_spin_index)
162 IF (mark_number .GT. 0) orig_mo_index = marked_states(mark_number, orig_spin_index, mark_ind)
166 CALL section_vals_val_get(update_section,
"REVERSE_MO_INDEX", i_rep_section=i_rep, l_val=reverse_mo_index)
171 IF (reverse_mo_index)
THEN
172 CALL cp_fm_to_fm(mos(orig_spin_index)%mo_coeff, matrix_x, 1, &
175 CALL cp_fm_to_fm(mos(orig_spin_index)%mo_coeff, matrix_x, 1, &
176 mos(orig_spin_index)%nmo - orig_mo_index + 1, 1)
180 CALL get_mo_set(mos(orig_spin_index), homo=homo, nmo=nmo)
182 IF (orig_mo_index + homo <= nmo)
THEN
183 CALL cp_fm_to_fm(mos(orig_spin_index)%mo_coeff, matrix_x, 1, orig_mo_index + homo, 1)
184 ELSE IF (.NOT.
ASSOCIATED(unoccupied_orbs))
THEN
185 CALL cp_abort(__location__, &
186 "If ORIG_TYPE is set to VIRTUAL, the array unoccupied_orbs must be associated! "// &
187 "For instance, ask in the SCF section to compute virtual orbitals after the GS optimization.")
189 CALL cp_fm_to_fm(unoccupied_orbs(orig_spin_index), matrix_x, 1, orig_mo_index, 1)
195 c_val=read_file_name)
196 IF (read_file_name ==
"EMPTY") &
197 CALL cp_abort(__location__, &
198 "If ORIG_TYPE is set to EXTERNAL, a file name should be set in ORIG_EXT_FILE_NAME "// &
199 "so that it can be used as the orginal MO.")
201 ALLOCATE (mos_orig_ext(
SIZE(mos)))
202 DO ispin = 1,
SIZE(mos)
206 IF (para_env%is_source())
THEN
207 INQUIRE (file=trim(read_file_name), exist=is_file)
209 CALL cp_abort(__location__, &
210 "Reference file not found! Name of the file CP2K looked for: "//trim(read_file_name))
212 CALL open_file(file_name=read_file_name, &
213 file_action=
"READ", &
214 file_form=
"UNFORMATTED", &
216 unit_number=restart_unit)
219 particle_set=particle_set, natom=
SIZE(particle_set, 1), &
220 rst_unit=restart_unit)
221 IF (para_env%is_source())
CALL close_file(unit_number=restart_unit)
223 IF (reverse_mo_index)
THEN
224 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
227 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
228 mos_orig_ext(orig_spin_index)%nmo - orig_mo_index + 1, 1)
230 DO ispin = 1,
SIZE(mos_orig_ext)
233 DEALLOCATE (mos_orig_ext)
237 IF (reverse_mo_index)
THEN
238 CALL cp_fm_to_fm(mos_new(result_spin_index)%mo_coeff, matrix_y, &
239 1, result_mo_index, 1)
241 CALL cp_fm_to_fm(mos_new(result_spin_index)%mo_coeff, matrix_y, &
242 1, mos_new(result_spin_index)%nmo - result_mo_index + 1, 1)
249 IF (reverse_mo_index)
THEN
250 CALL cp_fm_to_fm(matrix_y, mos_new(result_spin_index)%mo_coeff, &
251 1, 1, result_mo_index)
253 CALL cp_fm_to_fm(matrix_y, mos_new(result_spin_index)%mo_coeff, &
254 1, 1, mos_new(result_spin_index)%nmo - result_mo_index + 1)
262 DO ispin = 1,
SIZE(mos_new)
263 CALL cp_fm_to_fm(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff)
264 IF (mos_new(1)%use_mo_coeff_b) &
266 IF (mos(1)%use_mo_coeff_b) &
276 IF (output_unit > 0)
THEN
277 WRITE (output_unit,
'()')
278 WRITE (output_unit,
'(T2,A,T61,E20.4)') &
279 "Maximum deviation from MO S-orthonormality", orthonormality
280 WRITE (output_unit,
'(T2,A)')
"Writing new MOs to file"
285 DO ispin = 1,
SIZE(mos_new)
286 IF (overwrite_mos)
THEN
287 CALL cp_fm_to_fm(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff)
288 IF (mos_new(1)%use_mo_coeff_b) &
291 IF (mos(1)%use_mo_coeff_b) &
297 DO ispin = 1,
SIZE(mos_new)
304 CALL timestop(handle)