(git:ed6f26b)
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
45 USE qs_scf_types, ONLY: qs_scf_env_type,&
47#include "./base/base_uses.f90"
48
49 IMPLICIT NONE
50 PRIVATE
51
52 ! Global parameters
53 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_scf_wfn_mix'
54 PUBLIC :: wfn_mix
55
56CONTAINS
57
58! **************************************************************************************************
59!> \brief writes a new 'mixed' set of mos to restart file, without touching the current MOs
60!> \param mos ...
61!> \param particle_set ...
62!> \param dft_section ...
63!> \param qs_kind_set ...
64!> \param para_env ...
65!> \param output_unit ...
66!> \param unoccupied_orbs ...
67!> \param scf_env ...
68!> \param matrix_s ...
69!> \param marked_states ...
70!> \param for_rtp ...
71! **************************************************************************************************
72 SUBROUTINE wfn_mix(mos, particle_set, dft_section, qs_kind_set, para_env, output_unit, &
73 unoccupied_orbs, scf_env, matrix_s, marked_states, for_rtp)
74
75 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
76 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
77 TYPE(section_vals_type), POINTER :: dft_section
78 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
79 TYPE(mp_para_env_type), POINTER :: para_env
80 INTEGER :: output_unit
81 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN), &
82 OPTIONAL, POINTER :: unoccupied_orbs
83 TYPE(qs_scf_env_type), OPTIONAL, POINTER :: scf_env
84 TYPE(dbcsr_p_type), DIMENSION(:), OPTIONAL, &
85 POINTER :: matrix_s
86 INTEGER, DIMENSION(:, :, :), OPTIONAL, POINTER :: marked_states
87 LOGICAL, OPTIONAL :: for_rtp
88
89 CHARACTER(len=*), PARAMETER :: routinen = 'wfn_mix'
90
91 CHARACTER(LEN=default_path_length) :: read_file_name
92 INTEGER :: handle, i_rep, ispin, mark_ind, mark_number, n_rep, orig_mo_index, &
93 orig_spin_index, orig_type, restart_unit, result_mo_index, result_spin_index
94 LOGICAL :: explicit, is_file, my_for_rtp, &
95 overwrite_mos, reverse_mo_index
96 REAL(kind=dp) :: orig_scale, orthonormality, result_scale
97 TYPE(cp_fm_struct_type), POINTER :: fm_struct_vector
98 TYPE(cp_fm_type) :: matrix_x, matrix_y
99 TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: mos_new, mos_orig_ext
100 TYPE(section_vals_type), POINTER :: update_section, wfn_mix_section
101
102 CALL timeset(routinen, handle)
103 wfn_mix_section => section_vals_get_subs_vals(dft_section, "PRINT%WFN_MIX")
104 CALL section_vals_get(wfn_mix_section, explicit=explicit)
105
106 ! only perform action if explicitly required
107 IF (explicit) THEN
108
109 IF (PRESENT(for_rtp)) THEN
110 my_for_rtp = for_rtp
111 ELSE
112 my_for_rtp = .false.
113 END IF
114
115 IF (output_unit > 0) THEN
116 WRITE (output_unit, '()')
117 WRITE (output_unit, '(T2,A)') "Performing wfn mixing"
118 WRITE (output_unit, '(T2,A)') "====================="
119 END IF
120
121 ALLOCATE (mos_new(SIZE(mos)))
122 DO ispin = 1, SIZE(mos)
123 CALL duplicate_mo_set(mos_new(ispin), mos(ispin))
124 END DO
125
126 ! a single vector matrix structure
127 NULLIFY (fm_struct_vector)
128 CALL cp_fm_struct_create(fm_struct_vector, template_fmstruct=mos(1)%mo_coeff%matrix_struct, &
129 ncol_global=1)
130 CALL cp_fm_create(matrix_x, fm_struct_vector, name="x")
131 CALL cp_fm_create(matrix_y, fm_struct_vector, name="y")
132 CALL cp_fm_struct_release(fm_struct_vector)
133
134 update_section => section_vals_get_subs_vals(wfn_mix_section, "UPDATE")
135 CALL section_vals_get(update_section, n_repetition=n_rep)
136 CALL section_vals_get(update_section, explicit=explicit)
137 IF (.NOT. explicit) n_rep = 0
138
139 ! Mix the MOs as : y = ay + bx
140 DO i_rep = 1, n_rep
141 ! The occupied MO that will be modified or saved, 'y'
142 CALL section_vals_val_get(update_section, "RESULT_MO_INDEX", i_rep_section=i_rep, i_val=result_mo_index)
143 CALL section_vals_val_get(update_section, "RESULT_MARKED_STATE", i_rep_section=i_rep, i_val=mark_number)
144 CALL section_vals_val_get(update_section, "RESULT_SPIN_INDEX", i_rep_section=i_rep, i_val=result_spin_index)
145 ! result_scale is the 'a' coefficient
146 CALL section_vals_val_get(update_section, "RESULT_SCALE", i_rep_section=i_rep, r_val=result_scale)
147
148 mark_ind = 1
149 IF (mark_number .GT. 0) result_mo_index = marked_states(mark_number, result_spin_index, mark_ind)
150
151 ! The MO that will be added to the previous one, 'x'
152 CALL section_vals_val_get(update_section, "ORIG_TYPE", i_rep_section=i_rep, &
153 i_val=orig_type)
154 CALL section_vals_val_get(update_section, "ORIG_MO_INDEX", i_rep_section=i_rep, i_val=orig_mo_index)
155 CALL section_vals_val_get(update_section, "ORIG_MARKED_STATE", i_rep_section=i_rep, i_val=mark_number)
156 CALL section_vals_val_get(update_section, "ORIG_SPIN_INDEX", i_rep_section=i_rep, i_val=orig_spin_index)
157 ! orig_scale is the 'b' coefficient
158 CALL section_vals_val_get(update_section, "ORIG_SCALE", i_rep_section=i_rep, r_val=orig_scale)
159
160 IF (orig_type == wfn_mix_orig_virtual) mark_ind = 2
161 IF (mark_number .GT. 0) orig_mo_index = marked_states(mark_number, orig_spin_index, mark_ind)
162
163 CALL section_vals_val_get(wfn_mix_section, "OVERWRITE_MOS", l_val=overwrite_mos)
164
165 CALL section_vals_val_get(update_section, "REVERSE_MO_INDEX", i_rep_section=i_rep, l_val=reverse_mo_index)
166
167 ! First get a copy of the proper orig
168 ! Origin is in the MO matrix
169 IF (orig_type == wfn_mix_orig_occ) THEN
170 IF (reverse_mo_index) THEN
171 CALL cp_fm_to_fm(mos(orig_spin_index)%mo_coeff, matrix_x, 1, &
172 orig_mo_index, 1)
173 ELSE
174 CALL cp_fm_to_fm(mos(orig_spin_index)%mo_coeff, matrix_x, 1, &
175 mos(orig_spin_index)%nmo - orig_mo_index + 1, 1)
176 END IF
177 ! Origin is in the virtual matrix
178 ELSE IF (orig_type == wfn_mix_orig_virtual) THEN
179 IF (.NOT. ASSOCIATED(unoccupied_orbs)) &
180 CALL cp_abort(__location__, &
181 "If ORIG_TYPE is set to VIRTUAL, the array unoccupied_orbs must be associated! "// &
182 "For instance, ask in the SCF section to compute virtual orbitals after the GS optimization.")
183 CALL cp_fm_to_fm(unoccupied_orbs(orig_spin_index), matrix_x, 1, orig_mo_index, 1)
184
185 ! Origin is to be read from an external .wfn file
186 ELSE IF (orig_type == wfn_mix_orig_external) THEN
187 CALL section_vals_val_get(update_section, "ORIG_EXT_FILE_NAME", i_rep_section=i_rep, &
188 c_val=read_file_name)
189 IF (read_file_name == "EMPTY") &
190 CALL cp_abort(__location__, &
191 "If ORIG_TYPE is set to EXTERNAL, a file name should be set in ORIG_EXT_FILE_NAME "// &
192 "so that it can be used as the orginal MO.")
193
194 ALLOCATE (mos_orig_ext(SIZE(mos)))
195 DO ispin = 1, SIZE(mos)
196 CALL duplicate_mo_set(mos_orig_ext(ispin), mos(ispin))
197 END DO
198
199 IF (para_env%is_source()) THEN
200 INQUIRE (file=trim(read_file_name), exist=is_file)
201 IF (.NOT. is_file) &
202 CALL cp_abort(__location__, &
203 "Reference file not found! Name of the file CP2K looked for: "//trim(read_file_name))
204
205 CALL open_file(file_name=read_file_name, &
206 file_action="READ", &
207 file_form="UNFORMATTED", &
208 file_status="OLD", &
209 unit_number=restart_unit)
210 END IF
211 CALL read_mos_restart_low(mos_orig_ext, para_env=para_env, qs_kind_set=qs_kind_set, &
212 particle_set=particle_set, natom=SIZE(particle_set, 1), &
213 rst_unit=restart_unit)
214 IF (para_env%is_source()) CALL close_file(unit_number=restart_unit)
215
216 IF (reverse_mo_index) THEN
217 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
218 orig_mo_index, 1)
219 ELSE
220 CALL cp_fm_to_fm(mos_orig_ext(orig_spin_index)%mo_coeff, matrix_x, 1, &
221 mos_orig_ext(orig_spin_index)%nmo - orig_mo_index + 1, 1)
222 END IF
223 DO ispin = 1, SIZE(mos_orig_ext)
224 CALL deallocate_mo_set(mos_orig_ext(ispin))
225 END DO
226 DEALLOCATE (mos_orig_ext)
227 END IF
228
229 ! Second, get a copy of the target
230 IF (reverse_mo_index) THEN
231 CALL cp_fm_to_fm(mos_new(result_spin_index)%mo_coeff, matrix_y, &
232 1, result_mo_index, 1)
233 ELSE
234 CALL cp_fm_to_fm(mos_new(result_spin_index)%mo_coeff, matrix_y, &
235 1, mos_new(result_spin_index)%nmo - result_mo_index + 1, 1)
236 END IF
237
238 ! Third, perform the mix
239 CALL cp_fm_scale_and_add(result_scale, matrix_y, orig_scale, matrix_x)
240
241 ! and copy back in the result mos
242 IF (reverse_mo_index) THEN
243 CALL cp_fm_to_fm(matrix_y, mos_new(result_spin_index)%mo_coeff, &
244 1, 1, result_mo_index)
245 ELSE
246 CALL cp_fm_to_fm(matrix_y, mos_new(result_spin_index)%mo_coeff, &
247 1, 1, mos_new(result_spin_index)%nmo - result_mo_index + 1)
248 END IF
249 END DO
250
251 CALL cp_fm_release(matrix_x)
252 CALL cp_fm_release(matrix_y)
253
254 IF (my_for_rtp) THEN
255 DO ispin = 1, SIZE(mos_new)
256 CALL cp_fm_to_fm(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff)
257 IF (mos_new(1)%use_mo_coeff_b) &
258 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos_new(ispin)%mo_coeff_b)
259 IF (mos(1)%use_mo_coeff_b) &
260 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff_b)
261 END DO
262 ELSE
263 IF (scf_env%method == special_diag_method_nr) THEN
264 CALL calculate_orthonormality(orthonormality, mos)
265 ELSE
266 CALL calculate_orthonormality(orthonormality, mos, matrix_s(1)%matrix)
267 END IF
268
269 IF (output_unit > 0) THEN
270 WRITE (output_unit, '()')
271 WRITE (output_unit, '(T2,A,T61,E20.4)') &
272 "Maximum deviation from MO S-orthonormality", orthonormality
273 WRITE (output_unit, '(T2,A)') "Writing new MOs to file"
274 END IF
275
276 ! *** Write WaveFunction restart file ***
277
278 DO ispin = 1, SIZE(mos_new)
279 IF (overwrite_mos) THEN
280 CALL cp_fm_to_fm(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff)
281 IF (mos_new(1)%use_mo_coeff_b) &
282 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos_new(ispin)%mo_coeff_b)
283 END IF
284 IF (mos(1)%use_mo_coeff_b) &
285 CALL copy_fm_to_dbcsr(mos_new(ispin)%mo_coeff, mos(ispin)%mo_coeff_b)
286 END DO
287 CALL write_mo_set_to_restart(mos_new, particle_set, dft_section=dft_section, qs_kind_set=qs_kind_set)
288 END IF
289
290 DO ispin = 1, SIZE(mos_new)
291 CALL deallocate_mo_set(mos_new(ispin))
292 END DO
293 DEALLOCATE (mos_new)
294
295 END IF
296
297 CALL timestop(handle)
298
299 END SUBROUTINE wfn_mix
300
301END 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.
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.