(git:419edc0)
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-2025 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 .GT. 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 .GT. 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") &
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
201 ALLOCATE (mos_orig_ext(SIZE(mos)))
202 DO ispin = 1, SIZE(mos)
203 CALL duplicate_mo_set(mos_orig_ext(ispin), mos(ispin))
204 END DO
205
206 IF (para_env%is_source()) THEN
207 INQUIRE (file=trim(read_file_name), exist=is_file)
208 IF (.NOT. is_file) &
209 CALL cp_abort(__location__, &
210 "Reference file not found! Name of the file CP2K looked for: "//trim(read_file_name))
211
212 CALL open_file(file_name=read_file_name, &
213 file_action="READ", &
214 file_form="UNFORMATTED", &
215 file_status="OLD", &
216 unit_number=restart_unit)
217 END IF
218 CALL read_mos_restart_low(mos_orig_ext, para_env=para_env, qs_kind_set=qs_kind_set, &
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)
222
223 IF (reverse_mo_index) THEN
224 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
225 orig_mo_index, 1)
226 ELSE
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)
229 END IF
230 DO ispin = 1, SIZE(mos_orig_ext)
231 CALL deallocate_mo_set(mos_orig_ext(ispin))
232 END DO
233 DEALLOCATE (mos_orig_ext)
234 END IF
235
236 ! Second, get a copy of the target
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)
240 ELSE
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)
243 END IF
244
245 ! Third, perform the mix
246 CALL cp_fm_scale_and_add(result_scale, matrix_y, orig_scale, matrix_x)
247
248 ! and copy back in the result mos
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)
252 ELSE
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)
255 END IF
256 END DO
257
258 CALL cp_fm_release(matrix_x)
259 CALL cp_fm_release(matrix_y)
260
261 IF (my_for_rtp) THEN
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) &
265 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos_new(ispin)%mo_coeff_b)
266 IF (mos(1)%use_mo_coeff_b) &
267 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff_b)
268 END DO
269 ELSE
270 IF (scf_env%method == special_diag_method_nr) THEN
271 CALL calculate_orthonormality(orthonormality, mos)
272 ELSE
273 CALL calculate_orthonormality(orthonormality, mos, matrix_s(1)%matrix)
274 END IF
275
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"
281 END IF
282
283 ! *** Write WaveFunction restart file ***
284
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) &
289 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos_new(ispin)%mo_coeff_b)
290 END IF
291 IF (mos(1)%use_mo_coeff_b) &
292 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff_b)
293 END DO
294 CALL write_mo_set_to_restart(mos_new, particle_set, dft_section=dft_section, qs_kind_set=qs_kind_set)
295 END IF
296
297 DO ispin = 1, SIZE(mos_new)
298 CALL deallocate_mo_set(mos_new(ispin))
299 END DO
300 DEALLOCATE (mos_new)
301
302 END IF
303
304 CALL timestop(handle)
305
306 END SUBROUTINE wfn_mix
307
308END 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:308
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:119
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, use_sp)
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 write_mo_set_to_restart(mo_array, particle_set, dft_section, qs_kind_set)
...
Definition qs_mo_io.F:107
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:670
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.