(git:b2ae3e3)
Loading...
Searching...
No Matches
qs_scf_wfn_mix.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Does all kind of post scf calculations for GPW/GAPW
10!> \par History
11!> Started as a copy from the relevant part of qs_scf
12!> \author Joost VandeVondele (10.2003)
13! **************************************************************************************************
15 USE cp_dbcsr_api, ONLY: dbcsr_p_type
17 USE cp_files, ONLY: close_file,&
23 USE cp_fm_types, ONLY: cp_fm_create,&
34 USE kinds, ONLY: default_path_length,&
35 dp
46 USE qs_scf_types, ONLY: qs_scf_env_type,&
48#include "./base/base_uses.f90"
49
50 IMPLICIT NONE
51 PRIVATE
52
53 ! Global parameters
54 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_wfn_mix'
55 PUBLIC :: wfn_mix
56
57CONTAINS
58
59! **************************************************************************************************
60!> \brief writes a new 'mixed' set of mos to restart file, without touching the current MOs
61!> \param mos ...
62!> \param particle_set ...
63!> \param dft_section ...
64!> \param qs_kind_set ...
65!> \param para_env ...
66!> \param output_unit ...
67!> \param unoccupied_orbs ...
68!> \param scf_env ...
69!> \param matrix_s ...
70!> \param marked_states ...
71!> \param for_rtp ...
72! **************************************************************************************************
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)
75
76 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
77 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
78 TYPE(section_vals_type), POINTER :: dft_section
79 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
80 TYPE(mp_para_env_type), POINTER :: para_env
81 INTEGER :: output_unit
82 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN), &
83 OPTIONAL, POINTER :: unoccupied_orbs
84 TYPE(qs_scf_env_type), OPTIONAL, POINTER :: scf_env
85 TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
86 POINTER :: matrix_s
87 INTEGER, DIMENSION(:, :, :), OPTIONAL, POINTER :: marked_states
88 LOGICAL, OPTIONAL :: for_rtp
89
90 CHARACTER(len=*), PARAMETER :: routinen = 'wfn_mix'
91
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
98 TYPE(cp_fm_struct_type), POINTER :: fm_struct_vector
99 TYPE(cp_fm_type) :: matrix_x, matrix_y
100 TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: mos_new, mos_orig_ext
101 TYPE(section_vals_type), POINTER :: update_section, wfn_mix_section
102
103 CALL timeset(routinen, handle)
104 wfn_mix_section => section_vals_get_subs_vals(dft_section, "PRINT%WFN_MIX")
105 CALL section_vals_get(wfn_mix_section, explicit=explicit)
106
107 ! only perform action if explicitly required
108 IF (explicit) THEN
109
110 IF (PRESENT(for_rtp)) THEN
111 my_for_rtp = for_rtp
112 ELSE
113 my_for_rtp = .false.
114 END IF
115
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)') "====================="
120 END IF
121
122 ALLOCATE (mos_new(SIZE(mos)))
123 DO ispin = 1, SIZE(mos)
124 CALL duplicate_mo_set(mos_new(ispin), mos(ispin))
125 END DO
126
127 ! a single vector matrix structure
128 NULLIFY (fm_struct_vector)
129 CALL cp_fm_struct_create(fm_struct_vector, template_fmstruct=mos(1)%mo_coeff%matrix_struct, &
130 ncol_global=1)
131 CALL cp_fm_create(matrix_x, fm_struct_vector, name="x")
132 CALL cp_fm_create(matrix_y, fm_struct_vector, name="y")
133 CALL cp_fm_struct_release(fm_struct_vector)
134
135 update_section => section_vals_get_subs_vals(wfn_mix_section, "UPDATE")
136 CALL section_vals_get(update_section, n_repetition=n_rep)
137 CALL section_vals_get(update_section, explicit=explicit)
138 IF (.NOT. explicit) n_rep = 0
139
140 ! Mix the MOs as : y = ay + bx
141 DO i_rep = 1, n_rep
142 ! The occupied MO that will be modified or saved, 'y'
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)
146 ! result_scale is the 'a' coefficient
147 CALL section_vals_val_get(update_section, "RESULT_SCALE", i_rep_section=i_rep, r_val=result_scale)
148
149 mark_ind = 1
150 IF (mark_number > 0) result_mo_index = marked_states(mark_number, result_spin_index, mark_ind)
151
152 ! The MO that will be added to the previous one, 'x'
153 CALL section_vals_val_get(update_section, "ORIG_TYPE", i_rep_section=i_rep, &
154 i_val=orig_type)
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)
158 ! orig_scale is the 'b' coefficient
159 CALL section_vals_val_get(update_section, "ORIG_SCALE", i_rep_section=i_rep, r_val=orig_scale)
160
161 IF (orig_type == wfn_mix_orig_virtual) mark_ind = 2
162 IF (mark_number > 0) orig_mo_index = marked_states(mark_number, orig_spin_index, mark_ind)
163
164 CALL section_vals_val_get(wfn_mix_section, "OVERWRITE_MOS", l_val=overwrite_mos)
165
166 CALL section_vals_val_get(update_section, "REVERSE_MO_INDEX", i_rep_section=i_rep, l_val=reverse_mo_index)
167
168 ! First get a copy of the proper orig
169 ! Origin is in an occupied MO
170 IF (orig_type == wfn_mix_orig_occ) THEN
171 IF (reverse_mo_index) THEN
172 CALL cp_fm_to_fm(mos(orig_spin_index)%mo_coeff, matrix_x, 1, &
173 orig_mo_index, 1)
174 ELSE
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)
177 END IF
178 ! Origin is an unoccupied MO
179 ELSE IF (orig_type == wfn_mix_orig_virtual) THEN
180 CALL get_mo_set(mos(orig_spin_index), homo=homo, nmo=nmo)
181 ! check whether the MO is already available in the original MO set
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.")
188 ELSE
189 CALL cp_fm_to_fm(unoccupied_orbs(orig_spin_index), matrix_x, 1, orig_mo_index, 1)
190 END IF
191
192 ! Origin is to be read from an external .wfn file
193 ELSE IF (orig_type == wfn_mix_orig_external) THEN
194 CALL section_vals_val_get(update_section, "ORIG_EXT_FILE_NAME", i_rep_section=i_rep, &
195 c_val=read_file_name)
196 IF (read_file_name == "EMPTY") THEN
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.")
200 END IF
201
202 ALLOCATE (mos_orig_ext(SIZE(mos)))
203 DO ispin = 1, SIZE(mos)
204 CALL duplicate_mo_set(mos_orig_ext(ispin), mos(ispin))
205 END DO
206
207 IF (para_env%is_source()) THEN
208 INQUIRE (file=trim(read_file_name), exist=is_file)
209 IF (.NOT. is_file) THEN
210 CALL cp_abort(__location__, &
211 "Reference file not found! Name of the file CP2K looked for: "//trim(read_file_name))
212 END IF
213
214 CALL open_file(file_name=read_file_name, &
215 file_action="READ", &
216 file_form="UNFORMATTED", &
217 file_status="OLD", &
218 unit_number=restart_unit)
219 END IF
220 CALL read_mos_restart_low(mos_orig_ext, para_env=para_env, qs_kind_set=qs_kind_set, &
221 particle_set=particle_set, natom=SIZE(particle_set, 1), &
222 rst_unit=restart_unit)
223 IF (para_env%is_source()) CALL close_file(unit_number=restart_unit)
224
225 IF (reverse_mo_index) THEN
226 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
227 orig_mo_index, 1)
228 ELSE
229 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
230 mos_orig_ext(orig_spin_index)%nmo - orig_mo_index + 1, 1)
231 END IF
232 DO ispin = 1, SIZE(mos_orig_ext)
233 CALL deallocate_mo_set(mos_orig_ext(ispin))
234 END DO
235 DEALLOCATE (mos_orig_ext)
236 END IF
237
238 ! Second, get a copy of the target
239 IF (reverse_mo_index) THEN
240 CALL cp_fm_to_fm(mos_new(result_spin_index)%mo_coeff, matrix_y, &
241 1, result_mo_index, 1)
242 ELSE
243 CALL cp_fm_to_fm(mos_new(result_spin_index)%mo_coeff, matrix_y, &
244 1, mos_new(result_spin_index)%nmo - result_mo_index + 1, 1)
245 END IF
246
247 ! Third, perform the mix
248 CALL cp_fm_scale_and_add(result_scale, matrix_y, orig_scale, matrix_x)
249
250 ! and copy back in the result mos
251 IF (reverse_mo_index) THEN
252 CALL cp_fm_to_fm(matrix_y, mos_new(result_spin_index)%mo_coeff, &
253 1, 1, result_mo_index)
254 ELSE
255 CALL cp_fm_to_fm(matrix_y, mos_new(result_spin_index)%mo_coeff, &
256 1, 1, mos_new(result_spin_index)%nmo - result_mo_index + 1)
257 END IF
258 END DO
259
260 CALL cp_fm_release(matrix_x)
261 CALL cp_fm_release(matrix_y)
262
263 IF (my_for_rtp) THEN
264 DO ispin = 1, SIZE(mos_new)
265 CALL cp_fm_to_fm(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff)
266 IF (mos_new(1)%use_mo_coeff_b) THEN
267 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos_new(ispin)%mo_coeff_b)
268 END IF
269 IF (mos(1)%use_mo_coeff_b) THEN
270 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff_b)
271 END IF
272 END DO
273 ELSE
274 IF (scf_env%method == special_diag_method_nr) THEN
275 CALL calculate_orthonormality(orthonormality, mos)
276 ELSE
277 CALL calculate_orthonormality(orthonormality, mos, matrix_s(1)%matrix)
278 END IF
279
280 IF (output_unit > 0) THEN
281 WRITE (unit=output_unit, fmt="(/,T2,A,T61,E20.4)") &
282 "Maximum deviation from MO S-orthonormality", orthonormality
283 WRITE (unit=output_unit, fmt="(T2,A)") "Writing new MOs to file"
284 END IF
285
286 ! Write wavefunction restart file
287 DO ispin = 1, SIZE(mos_new)
288 IF (overwrite_mos) THEN
289 CALL cp_fm_to_fm(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff)
290 IF (mos_new(1)%use_mo_coeff_b) THEN
291 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos_new(ispin)%mo_coeff_b)
292 END IF
293 END IF
294 IF (mos(1)%use_mo_coeff_b) THEN
295 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff_b)
296 END IF
297 END DO
298 CALL write_mo_set_to_restart(mos_new, particle_set, dft_section=dft_section, &
299 qs_kind_set=qs_kind_set)
300 END IF
301
302 DO ispin = 1, SIZE(mos_new)
303 CALL deallocate_mo_set(mos_new(ispin))
304 END DO
305 DEALLOCATE (mos_new)
306
307 END IF
308
309 CALL timestop(handle)
310
311 END SUBROUTINE wfn_mix
312
313END MODULE qs_scf_wfn_mix
DBCSR operations in CP2K.
subroutine, public copy_fm_to_dbcsr(fm, matrix, keep_sparsity)
Copy a BLACS matrix to a dbcsr matrix.
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:311
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:122
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
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
Definition cp_fm_types.F:15
subroutine, public cp_fm_create(matrix, matrix_struct, name, nrow, ncol, set_zero)
creates a new full matrix with the given structure
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public wfn_mix_orig_virtual
integer, parameter, public wfn_mix_orig_external
integer, parameter, public wfn_mix_orig_occ
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_get(section_vals, ref_count, n_repetition, n_subs_vals_rep, section, explicit)
returns various attributes about the section_vals
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_path_length
Definition kinds.F:58
Interface to the message passing library MPI.
Define the data structure for the particle information.
Define the quickstep kind type and their sub types.
Definition and initialisation of the mo data type.
Definition qs_mo_io.F:21
subroutine, public read_mos_restart_low(mos, para_env, qs_kind_set, particle_set, natom, rst_unit, multiplicity, rt_mos, natom_mismatch)
Reading the mos from apreviously defined restart file.
Definition qs_mo_io.F:695
subroutine, public write_mo_set_to_restart(mo_array, particle_set, dft_section, qs_kind_set, matrix_ks)
...
Definition qs_mo_io.F:117
collects routines that perform operations directly related to MOs
subroutine, public calculate_orthonormality(orthonormality, mo_array, matrix_s)
...
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public duplicate_mo_set(mo_set_new, mo_set_old)
allocate a new mo_set, and copy the old data
subroutine, public deallocate_mo_set(mo_set)
Deallocate a wavefunction 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.
module that contains the definitions of the scf types
integer, parameter, public special_diag_method_nr
Does all kind of post scf calculations for GPW/GAPW.
subroutine, public wfn_mix(mos, particle_set, dft_section, qs_kind_set, para_env, output_unit, unoccupied_orbs, scf_env, matrix_s, marked_states, for_rtp)
writes a new 'mixed' set of mos to restart file, without touching the current MOs
keeps the information about the structure of a full matrix
represent a full matrix
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.