(git:5e7fe52)
Loading...
Searching...
No Matches
optbas_frontier_orbital_screening.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!> \brief Automatic screening of frontier-orbital basis optimizations
9!> \par History
10!> 28.08.2026 created [Jan Wilhelm]
11!> \author Jan Wilhelm
12! **************************************************************************************************
15 USE cp_dbcsr_api, ONLY: dbcsr_p_type
16 USE cp_files, ONLY: close_file,&
26 USE input_constants, ONLY: atomic_guess,&
27 do_qs
36 USE kinds, ONLY: default_path_length,&
38 dp
39 USE machine, ONLY: m_getcwd
51 USE physcon, ONLY: evolt
53 USE qs_energy, ONLY: qs_energies
55 USE qs_environment, ONLY: qs_init
60 USE qs_mo_types, ONLY: get_mo_set,&
63#include "./base/base_uses.f90"
64
65 IMPLICIT NONE
66 PRIVATE
67
69
70 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'optbas_frontier_orbital_screening'
71
72 TYPE frontier_orbital_screening_candidate_type
73 REAL(KIND=dp) :: condition_number = 0.0_dp
74 REAL(KIND=dp) :: gap = 0.0_dp
75 REAL(KIND=dp) :: energy = 0.0_dp
76 TYPE(basis_optimization_type) :: opt_bas
77 END TYPE frontier_orbital_screening_candidate_type
78
79 abstract INTERFACE
80! **************************************************************************************************
81!> \brief ...
82!> \param opt_bas ...
83!> \param input_declaration ...
84!> \param para_env ...
85!> \param globenv ...
86!> \param training_input ...
87!> \param reference ...
88! **************************************************************************************************
89 SUBROUTINE basis_optimization_driver(opt_bas, input_declaration, para_env, globenv, training_input, reference)
93 TYPE(basis_optimization_type) :: opt_bas
94 TYPE(section_type), POINTER :: input_declaration
95 TYPE(mp_para_env_type), POINTER :: para_env
96 TYPE(global_environment_type), POINTER :: globenv
97 TYPE(section_vals_type), OPTIONAL, POINTER :: training_input
99 DIMENSION(:), INTENT(IN), OPTIONAL, TARGET :: reference
100 END SUBROUTINE basis_optimization_driver
101 END INTERFACE
102
103CONTAINS
104
105! **************************************************************************************************
106!> \brief Run serial frontier-orbital optimizations and evaluate their HOMO-LUMO gaps with new SCFs.
107!> \param input_declaration ...
108!> \param section ...
109!> \param para_env ...
110!> \param globenv ...
111!> \param frontier_screening_section ...
112!> \param optimize_basis_driver ...
113! **************************************************************************************************
114 SUBROUTINE run_frontier_orbital_screening(input_declaration, section, para_env, globenv, frontier_screening_section, &
115 optimize_basis_driver)
116 TYPE(section_type), POINTER :: input_declaration
117 TYPE(section_vals_type), POINTER :: section
118 TYPE(mp_para_env_type), POINTER :: para_env
119 TYPE(global_environment_type), POINTER :: globenv
120 TYPE(section_vals_type), POINTER :: frontier_screening_section
121
122 PROCEDURE(basis_optimization_driver) :: optimize_basis_driver
123
124 INTEGER, PARAMETER :: number_parameter_sets = 5
125 REAL(kind=dp), DIMENSION(6, number_parameter_sets), PARAMETER :: &
126 pre_tabulated_parameters = reshape( &
127 [10.0_dp, 10.0_dp, 10.0_dp, 10.0_dp, 0.001_dp, 0.001_dp, &
128 30.0_dp, 30.0_dp, 30.0_dp, 10.0_dp, 0.001_dp, 0.001_dp, &
129 10.0_dp, 30.0_dp, 30.0_dp, 10.0_dp, 0.001_dp, 0.001_dp, &
130 10.0_dp, 30.0_dp, 30.0_dp, 3.0_dp, 0.001_dp, 0.001_dp, &
131 10.0_dp, 30.0_dp, 30.0_dp, 10.0_dp, 0.001_dp, 0.01_dp], &
132 [6, number_parameter_sets])
133
134 CHARACTER(LEN=default_path_length) :: final_basis_file, main_dir
135 INTEGER :: i, n_candidates, unit_nr
136 REAL(kind=dp) :: initial_condition_number, initial_energy, initial_gap, &
137 reference_condition_number, reference_energy, reference_gap
138 TYPE(cp_logger_type), POINTER :: logger
140 ALLOCATABLE, DIMENSION(:), TARGET :: reference
141 TYPE(frontier_orbital_screening_candidate_type), ALLOCATABLE, &
142 DIMENSION(:) :: candidates
143
144! Rows are occupied, virtual, empty, gap, condition, and coefficient weights.
145
146 CALL check_frontier_orbital_screening_input(section)
147 CALL section_vals_val_get(frontier_screening_section, "NUMBER_OF_OPTIMIZATIONS", i_val=n_candidates)
148 IF (n_candidates < 1 .OR. n_candidates > number_parameter_sets) THEN
149 CALL cp_abort(__location__, &
150 "NUMBER_OF_OPTIMIZATIONS must be between 1 and "// &
151 trim(cp_to_string(number_parameter_sets)))
152 END IF
153
154 CALL m_getcwd(main_dir)
155 ALLOCATE (candidates(n_candidates), reference(1))
156 logger => cp_get_default_logger()
157 unit_nr = -1
158 IF (para_env%is_source()) unit_nr = cp_logger_get_default_unit_nr(logger)
159
160 CALL run_frontier_orbital_reference_scf(section, para_env, globenv, reference(1), &
161 reference_gap, reference_energy, &
162 reference_condition_number)
163
164 DO i = 1, n_candidates
165 CALL optimize_basis_init_read_input(candidates(i)%opt_bas, section, para_env, &
166 quiet_output=.true., embedded_training=.true.)
167 IF (candidates(i)%opt_bas%method /= method_mo_fit_occ_virtual) THEN
168 cpabort("Internal error while initializing FRONTIER_ORBITAL_SCREENING")
169 END IF
170 IF (candidates(i)%opt_bas%ntraining_sets /= 1 .OR. candidates(i)%opt_bas%ncombinations /= 1) THEN
171 CALL cp_abort(__location__, &
172 "FRONTIER_ORBITAL_SCREENING currently supports exactly one training system "// &
173 "and one candidate basis assignment")
174 END IF
175
176 IF (i == 1) THEN
177 final_basis_file = work_path(main_dir, candidates(i)%opt_bas%output_basis_file)
178 IF (unit_nr > 0) THEN
179 WRITE (unit_nr, '(A)') ""
180 WRITE (unit_nr, '(1X,A)') repeat("=", 79)
181 WRITE (unit_nr, '(1X,A)') "Optimize basis set to improve frontier orbitals:"
182 WRITE (unit_nr, '(1X,A)') "Using pre-tabulated parameters in the optimization"
183 WRITE (unit_nr, '(1X,A)') repeat("=", 79)
184 WRITE (unit_nr, '(A)') " "
185 END IF
186 END IF
187
188 candidates(i)%opt_bas%method = method_mo_fit_occ_virtual
189 candidates(i)%opt_bas%use_condition_number = .true.
190 candidates(i)%opt_bas%write_frequency = 5000
191 candidates(i)%opt_bas%fval_weight = 1.0_dp
192 candidates(i)%opt_bas%occupied_weight = pre_tabulated_parameters(1, i)
193 candidates(i)%opt_bas%virtual_weight = pre_tabulated_parameters(2, i)
194 candidates(i)%opt_bas%empty_overlap_weight = pre_tabulated_parameters(3, i)
195 candidates(i)%opt_bas%gap_weight = pre_tabulated_parameters(4, i)
196 candidates(i)%opt_bas%condition_weight = pre_tabulated_parameters(5, i)
197 candidates(i)%opt_bas%coefficient_weight = pre_tabulated_parameters(6, i)
198 candidates(i)%opt_bas%gap_energy_scale = 1.0_dp/evolt
199 candidates(i)%opt_bas%virtual_energy_cutoff = 3.0_dp/evolt
200 candidates(i)%opt_bas%virtual_energy_smoothing = 0.2_dp/evolt
201 IF (unit_nr > 0) THEN
202 WRITE (unit_nr, '(1X,A,I0,A,I0,A)') "Candidate ", i, " of ", n_candidates, &
203 ": optimizing basis set ..."
204 END IF
205 CALL optimize_basis_driver(candidates(i)%opt_bas, input_declaration, para_env, globenv, &
206 training_input=section, reference=reference)
207 END DO
208
209 CALL run_frontier_orbital_scf(candidates(1)%opt_bas, section, para_env, globenv, &
210 optimized_basis=.false., &
211 gap=initial_gap, energy=initial_energy, &
212 condition_number=initial_condition_number)
213
214 DO i = 1, n_candidates
215 CALL run_frontier_orbital_scf(candidates(i)%opt_bas, section, para_env, globenv, &
216 optimized_basis=.true., &
217 gap=candidates(i)%gap, energy=candidates(i)%energy, &
218 condition_number=candidates(i)%condition_number)
219 END DO
220
221 CALL write_frontier_orbital_basis_file(final_basis_file, candidates, &
222 reference_gap, reference_energy, reference_condition_number, para_env)
223 CALL print_frontier_orbital_summary(unit_nr, final_basis_file, section, candidates, &
224 reference_gap, reference_energy, reference_condition_number, &
225 initial_gap, initial_energy, initial_condition_number)
226
227 DO i = 1, n_candidates
228 CALL deallocate_basis_optimization_type(candidates(i)%opt_bas)
229 END DO
230 CALL frontier_orbitals_reference_release(reference(1))
231 DEALLOCATE (candidates, reference)
232
233 END SUBROUTINE run_frontier_orbital_screening
234
235! **************************************************************************************************
236!> \brief Check the single-file input contract of frontier-orbital screening.
237!> \param section ...
238! **************************************************************************************************
239 SUBROUTINE check_frontier_orbital_screening_input(section)
240 TYPE(section_vals_type), POINTER :: section
241
242 INTEGER :: method, nforce_eval, ntraining
243 LOGICAL :: dft_explicit, keyword_explicit
244 TYPE(section_vals_type), POINTER :: dft_section, force_eval_section, &
245 optbas_section, training_section
246
247 optbas_section => section_vals_get_subs_vals(section, "OPTIMIZE_BASIS")
248
249 CALL reject_controlled_keyword(optbas_section, "BASIS_WORK_FILE")
250 CALL reject_controlled_keyword(optbas_section, "WRITE_FREQUENCY")
251 CALL reject_controlled_keyword(optbas_section, "USE_CONDITION_NUMBER")
252 CALL reject_controlled_keyword(optbas_section, "RESIDUUM_WEIGHT")
253 CALL reject_controlled_keyword(optbas_section, "CONDITION_WEIGHT")
254 CALL reject_controlled_keyword(optbas_section, "BASIS_COMBINATIONS")
255 CALL reject_controlled_keyword(optbas_section, "GROUP_PARTITION")
256 CALL section_vals_val_get(optbas_section, "BASIS_TEMPLATE_FILE", explicit=keyword_explicit)
257 IF (.NOT. keyword_explicit) THEN
258 cpabort("FRONTIER_ORBITAL_SCREENING requires BASIS_TEMPLATE_FILE")
259 END IF
260
261 training_section => section_vals_get_subs_vals(optbas_section, "TRAINING_FILES")
262 CALL section_vals_get(training_section, n_repetition=ntraining)
263 IF (ntraining /= 0) CALL controlled_parameter_error("TRAINING_FILES")
264
265 force_eval_section => section_vals_get_subs_vals(section, "FORCE_EVAL")
266 CALL section_vals_get(force_eval_section, n_repetition=nforce_eval)
267 IF (nforce_eval /= 1) THEN
268 CALL cp_abort(__location__, &
269 "FRONTIER_ORBITAL_SCREENING requires exactly one FORCE_EVAL in the same input")
270 END IF
271 CALL section_vals_val_get(force_eval_section, "METHOD", i_val=method)
272 IF (method /= do_qs) THEN
273 cpabort("FRONTIER_ORBITAL_SCREENING requires a Quickstep FORCE_EVAL")
274 END IF
275 dft_section => section_vals_get_subs_vals(force_eval_section, "DFT")
276 CALL section_vals_get(dft_section, explicit=dft_explicit)
277 IF (.NOT. dft_explicit) THEN
278 CALL cp_abort(__location__, &
279 "FRONTIER_ORBITAL_SCREENING requires an explicit FORCE_EVAL%DFT section")
280 END IF
281 END SUBROUTINE check_frontier_orbital_screening_input
282
283! **************************************************************************************************
284!> \brief Reject an OPTIMIZE_BASIS keyword controlled by frontier-orbital screening.
285!> \param section ...
286!> \param keyword_name ...
287! **************************************************************************************************
288 SUBROUTINE reject_controlled_keyword(section, keyword_name)
289 TYPE(section_vals_type), POINTER :: section
290 CHARACTER(LEN=*), INTENT(IN) :: keyword_name
291
292 LOGICAL :: explicit
293
294 CALL section_vals_val_get(section, keyword_name, explicit=explicit)
295 IF (explicit) CALL controlled_parameter_error("OPTIMIZE_BASIS%"//trim(keyword_name))
296
297 END SUBROUTINE reject_controlled_keyword
298
299! **************************************************************************************************
300!> \brief Abort for an input parameter replaced by frontier-orbital screening.
301!> \param parameter_name ...
302! **************************************************************************************************
303 SUBROUTINE controlled_parameter_error(parameter_name)
304 CHARACTER(LEN=*), INTENT(IN) :: parameter_name
305
306 CALL cp_abort(__location__, &
307 trim(parameter_name)//" is not allowed together with FRONTIER_ORBITAL_SCREENING "// &
308 "because it is overwritten automatically")
309
310 END SUBROUTINE controlled_parameter_error
311
312! **************************************************************************************************
313!> \brief Run and retain the large-basis reference from the embedded FORCE_EVAL.
314!> \param section ...
315!> \param para_env ...
316!> \param globenv ...
317!> \param reference ...
318!> \param gap ...
319!> \param energy ...
320!> \param condition_number ...
321! **************************************************************************************************
322 SUBROUTINE run_frontier_orbital_reference_scf(section, para_env, globenv, reference, &
323 gap, energy, condition_number)
324 TYPE(section_vals_type), POINTER :: section
325 TYPE(mp_para_env_type), POINTER :: para_env
326 TYPE(global_environment_type), POINTER :: globenv
328 INTENT(OUT) :: reference
329 REAL(kind=dp), INTENT(OUT) :: gap, energy, condition_number
330
331 INTEGER :: outer_print_level
332 TYPE(cp_logger_type), POINTER :: logger
333 TYPE(qs_environment_type), POINTER :: qs_env
334 TYPE(section_vals_type), POINTER :: input_file
335
336 NULLIFY (input_file, logger, qs_env)
337 CALL section_vals_duplicate(section, input_file)
338 CALL section_vals_val_set(input_file, "GLOBAL%PRINT_LEVEL", i_val=silent_print_level)
339 CALL section_vals_val_set(input_file, "FORCE_EVAL%DFT%SCF%SCF_GUESS", i_val=atomic_guess)
340 CALL section_vals_val_set(input_file, "GLOBAL%PROGRAM_RUN_INFO%_SECTION_PARAMETERS_", &
341 i_val=debug_print_level)
342 CALL section_vals_val_set(input_file, "GLOBAL%REFERENCES%_SECTION_PARAMETERS_", &
343 i_val=debug_print_level)
344 CALL section_vals_val_set(input_file, "GLOBAL%TIMINGS%_SECTION_PARAMETERS_", &
345 i_val=debug_print_level)
346 CALL section_vals_val_set(input_file, &
347 "FORCE_EVAL%DFT%SCF%PRINT%RESTART%_SECTION_PARAMETERS_", &
348 i_val=debug_print_level + 1)
349 CALL section_vals_val_set(input_file, &
350 "FORCE_EVAL%DFT%SCF%PRINT%RESTART_HISTORY%_SECTION_PARAMETERS_", &
351 i_val=debug_print_level + 1)
352 logger => cp_get_default_logger()
353 outer_print_level = logger%iter_info%print_level
354 logger%iter_info%print_level = silent_print_level
355 CALL create_silent_qs_env(input_file, para_env, globenv, qs_env)
356 CALL qs_energies(qs_env)
357 CALL get_frontier_orbital_scf_result(qs_env, gap, energy, condition_number)
358 CALL frontier_orbitals_reference_init(qs_env, reference)
359 CALL qs_env_release(qs_env)
360 DEALLOCATE (qs_env)
361 logger%iter_info%print_level = outer_print_level
362 CALL section_vals_release(input_file)
363
364 END SUBROUTINE run_frontier_orbital_reference_scf
365
366! **************************************************************************************************
367!> \brief Run one silent SCF using a compact basis held in memory.
368!> \param opt_bas ...
369!> \param section ...
370!> \param para_env ...
371!> \param globenv ...
372!> \param optimized_basis ...
373!> \param gap ...
374!> \param energy ...
375!> \param condition_number ...
376! **************************************************************************************************
377 SUBROUTINE run_frontier_orbital_scf(opt_bas, section, para_env, globenv, &
378 optimized_basis, gap, energy, condition_number)
379 TYPE(basis_optimization_type), INTENT(IN) :: opt_bas
380 TYPE(section_vals_type), POINTER :: section
381 TYPE(mp_para_env_type), POINTER :: para_env
382 TYPE(global_environment_type), POINTER :: globenv
383 LOGICAL, INTENT(IN) :: optimized_basis
384 REAL(kind=dp), INTENT(OUT) :: gap, energy, condition_number
385
386 INTEGER :: outer_print_level
387 TYPE(cp_logger_type), POINTER :: logger
388 TYPE(qs_environment_type), POINTER :: qs_env
389 TYPE(section_vals_type), POINTER :: input_file
390
391 NULLIFY (input_file, logger, qs_env)
392 gap = 0.0_dp
393 energy = 0.0_dp
394 condition_number = 0.0_dp
395 CALL section_vals_duplicate(section, input_file)
396 CALL prepare_frontier_orbital_scf_input(input_file, opt_bas)
397 logger => cp_get_default_logger()
398 outer_print_level = logger%iter_info%print_level
399 logger%iter_info%print_level = silent_print_level
400 CALL create_silent_qs_env(input_file, para_env, globenv, qs_env)
401 IF (optimized_basis) CALL update_basis_set(opt_bas, 1, "ORB", qs_env)
402 CALL qs_energies(qs_env)
403 CALL get_frontier_orbital_scf_result(qs_env, gap, energy, condition_number)
404 CALL qs_env_release(qs_env)
405 DEALLOCATE (qs_env)
406 logger%iter_info%print_level = outer_print_level
407 CALL section_vals_release(input_file)
408
409 END SUBROUTINE run_frontier_orbital_scf
410
411! **************************************************************************************************
412!> \brief Initialize Quickstep directly under the active CP2K environment without nested startup.
413!> \param input_file ...
414!> \param para_env ...
415!> \param globenv ...
416!> \param qs_env ...
417! **************************************************************************************************
418 SUBROUTINE create_silent_qs_env(input_file, para_env, globenv, qs_env)
419 TYPE(section_vals_type), POINTER :: input_file
420 TYPE(mp_para_env_type), POINTER :: para_env
421 TYPE(global_environment_type), POINTER :: globenv
422 TYPE(qs_environment_type), POINTER :: qs_env
423
424 TYPE(section_vals_type), POINTER :: force_env_section, subsys_section
425
426 force_env_section => section_vals_get_subs_vals(input_file, "FORCE_EVAL")
427 subsys_section => section_vals_get_subs_vals(force_env_section, "SUBSYS")
428 ALLOCATE (qs_env)
429 CALL qs_env_create(qs_env, globenv)
430 CALL qs_init(qs_env, para_env, input_file, globenv=globenv, &
431 force_env_section=force_env_section, subsys_section=subsys_section, &
432 use_motion_section=.true., silent=.true.)
433
434 END SUBROUTINE create_silent_qs_env
435
436! **************************************************************************************************
437!> \brief Extract the gap, energy, and overlap condition number from a completed SCF.
438!> \param qs_env ...
439!> \param gap ...
440!> \param energy ...
441!> \param condition_number ...
442! **************************************************************************************************
443 SUBROUTINE get_frontier_orbital_scf_result(qs_env, gap, energy, condition_number)
444 TYPE(qs_environment_type), POINTER :: qs_env
445 REAL(kind=dp), INTENT(OUT) :: gap, energy, condition_number
446
447 INTEGER :: homo, nmo
448 REAL(kind=dp), DIMENSION(2) :: condnum
449 REAL(kind=dp), DIMENSION(:), POINTER :: eigenvalues
450 TYPE(cp_blacs_env_type), POINTER :: blacs_env
451 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
452 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: smat
453 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
454 TYPE(qs_energy_type), POINTER :: qs_energy
455
456 NULLIFY (blacs_env, eigenvalues, matrix_s, mos, qs_energy, smat)
457 gap = 0.0_dp
458 CALL get_qs_env(qs_env, blacs_env=blacs_env, energy=qs_energy, matrix_s=matrix_s, mos=mos)
459 energy = qs_energy%total
460 ALLOCATE (smat(1, 1))
461 smat(1, 1)%matrix => matrix_s(1)%matrix
462 CALL overlap_condnum(smat, condnum, -1, .false., .true., .false., blacs_env)
463 condition_number = condnum(2)
464 DEALLOCATE (smat)
465 IF (SIZE(mos) /= 1) THEN
466 cpabort("FRONTIER_ORBITAL_SCREENING requires a restricted calculation")
467 END IF
468 CALL get_mo_set(mos(1), homo=homo, nmo=nmo, eigenvalues=eigenvalues)
469 IF (homo < 1 .OR. homo >= nmo) THEN
470 cpabort("FRONTIER_ORBITAL_SCREENING could not determine a HOMO-LUMO gap")
471 END IF
472 gap = eigenvalues(homo + 1) - eigenvalues(homo)
473
474 END SUBROUTINE get_frontier_orbital_scf_result
475
476! **************************************************************************************************
477!> \brief Make a parsed reference input suitable for a quiet, independent screening SCF.
478!> \param input_file ...
479!> \param opt_bas ...
480! **************************************************************************************************
481 SUBROUTINE prepare_frontier_orbital_scf_input(input_file, opt_bas)
482 TYPE(section_vals_type), POINTER :: input_file
483 TYPE(basis_optimization_type), INTENT(IN) :: opt_bas
484
485 CHARACTER(LEN=default_string_length) :: element
486 CHARACTER(LEN=default_string_length), &
487 DIMENSION(:), POINTER :: basis_info
488 INTEGER :: ifit, ikind, nbasis_files, nkinds
489 LOGICAL :: element_explicit, found
490 TYPE(section_vals_type), POINTER :: dft_section, kind_section, subsys_section
491
492 CALL section_vals_val_set(input_file, "GLOBAL%PRINT_LEVEL", i_val=silent_print_level)
493 CALL section_vals_val_set(input_file, "FORCE_EVAL%DFT%SCF%SCF_GUESS", i_val=atomic_guess)
494 CALL section_vals_val_set(input_file, &
495 "FORCE_EVAL%DFT%SCF%PRINT%RESTART%_SECTION_PARAMETERS_", &
496 i_val=debug_print_level + 1)
497 CALL section_vals_val_set(input_file, &
498 "FORCE_EVAL%DFT%SCF%PRINT%RESTART_HISTORY%_SECTION_PARAMETERS_", &
499 i_val=debug_print_level + 1)
500
501 dft_section => section_vals_get_subs_vals(input_file, "FORCE_EVAL%DFT")
502 CALL section_vals_val_get(dft_section, "BASIS_SET_FILE_NAME", n_rep_val=nbasis_files)
503 IF (nbasis_files < 1) THEN
504 cpabort("The screening reference input has no basis-set file")
505 END IF
507 dft_section, "BASIS_SET_FILE_NAME", i_rep_val=1, &
508 c_val=discover_file(opt_bas%template_basis_file))
509
510 subsys_section => section_vals_get_subs_vals(input_file, "FORCE_EVAL%SUBSYS")
511 kind_section => section_vals_get_subs_vals(subsys_section, "KIND")
512 CALL section_vals_get(kind_section, n_repetition=nkinds)
513 DO ikind = 1, nkinds
514 CALL section_vals_val_get(kind_section, "ELEMENT", explicit=element_explicit, &
515 i_rep_section=ikind)
516 IF (element_explicit) THEN
517 CALL section_vals_val_get(kind_section, "ELEMENT", c_val=element, i_rep_section=ikind)
518 ELSE
519 CALL section_vals_val_get(kind_section, "_SECTION_PARAMETERS_", &
520 c_val=element, i_rep_section=ikind)
521 END IF
522 CALL uppercase(element)
523 found = .false.
524 DO ifit = 1, opt_bas%nkind
525 IF (trim(element) == trim(opt_bas%kind_basis(ifit)%element)) THEN
526 NULLIFY (basis_info)
527 CALL section_vals_val_get(kind_section, "BASIS_SET", c_vals=basis_info, &
528 i_rep_val=1, i_rep_section=ikind)
529 basis_info(SIZE(basis_info)) = opt_bas%kind_basis(ifit)%flex_basis(0)%basis_name
530 found = .true.
531 EXIT
532 END IF
533 END DO
534 IF (.NOT. found) THEN
535 CALL cp_abort(__location__, &
536 "Every KIND in the screening reference input must have a corresponding "// &
537 "FIT_KIND: "//trim(element))
538 END IF
539 END DO
540
541 END SUBROUTINE prepare_frontier_orbital_scf_input
542
543! **************************************************************************************************
544!> \brief Write all optimized candidates to one CP2K basis file.
545!> \param filename ...
546!> \param candidates ...
547!> \param reference_gap ...
548!> \param reference_energy ...
549!> \param reference_condition_number ...
550!> \param para_env ...
551! **************************************************************************************************
552 SUBROUTINE write_frontier_orbital_basis_file(filename, candidates, &
553 reference_gap, reference_energy, reference_condition_number, para_env)
554 CHARACTER(LEN=*), INTENT(IN) :: filename
555 TYPE(frontier_orbital_screening_candidate_type), &
556 DIMENSION(:) :: candidates
557 REAL(kind=dp), INTENT(IN) :: reference_gap, reference_energy, &
558 reference_condition_number
559 TYPE(mp_para_env_type), POINTER :: para_env
560
561 INTEGER :: candidate, ibasis, ikind, unit_nr
562
563 IF (para_env%is_source()) THEN
564 CALL open_file(file_name=filename, file_status="UNKNOWN", file_action="WRITE", unit_number=unit_nr)
565 ELSE
566 unit_nr = -999
567 END IF
568 DO candidate = 1, SIZE(candidates)
569 IF (unit_nr > 0) THEN
570 WRITE (unit_nr, '(A)') "#"
571 WRITE (unit_nr, '(A,I0)') "# Optimized basis set ", candidate
572 WRITE (unit_nr, '(A,F12.6,A)') "# Reference HOMO-LUMO gap: ", reference_gap*evolt, " eV"
573 WRITE (unit_nr, '(A,F12.6,A)') "# Basis HOMO-LUMO gap: ", candidates(candidate)%gap*evolt, " eV"
574 WRITE (unit_nr, '(A,F12.6,A)') "# Absolute gap error: ", &
575 abs(candidates(candidate)%gap - reference_gap)*evolt, " eV"
576 WRITE (unit_nr, '(A,ES15.6)') "# Reference condition number: ", reference_condition_number
577 WRITE (unit_nr, '(A,ES15.6)') &
578 "# Basis condition number: ", candidates(candidate)%condition_number
579 WRITE (unit_nr, '(A,F22.12,A)') "# Reference total energy: ", reference_energy, " hartree"
580 WRITE (unit_nr, '(A,F22.12,A)') "# Basis total energy: ", candidates(candidate)%energy, " hartree"
581 WRITE (unit_nr, '(A)') "#"
582 END IF
583 DO ikind = 1, candidates(candidate)%opt_bas%nkind
584 DO ibasis = 0, candidates(candidate)%opt_bas%kind_basis(ikind)%nbasis_deriv
585 candidates(candidate)%opt_bas%kind_basis(ikind)%flex_basis(ibasis)%basis_name = &
586 trim(candidates(candidate)%opt_bas%kind_basis(ikind)%flex_basis(ibasis)%basis_name)// &
587 "_"//trim(adjustl(cp_to_string(candidate)))
588 CALL write_basis(candidates(candidate)%opt_bas%kind_basis(ikind)%flex_basis(ibasis), &
589 candidates(candidate)%opt_bas%kind_basis(ikind)%element, unit_nr)
590 END DO
591 END DO
592 END DO
593 IF (para_env%is_source()) CALL close_file(unit_number=unit_nr)
594
595 END SUBROUTINE write_frontier_orbital_basis_file
596
597! **************************************************************************************************
598!> \brief Print the two-line column headings shared by screening result tables.
599!> \param unit_nr ...
600! **************************************************************************************************
601 SUBROUTINE print_frontier_orbital_table_header(unit_nr)
602 INTEGER, INTENT(IN) :: unit_nr
603
604 WRITE (unit_nr, '(1X,A,T14,A,T24,A,T46,A,T59,A)') &
605 "Basis set", "Gap / eV", "Abs. error to", "Condition", "Total energy / Ha"
606 WRITE (unit_nr, '(T24,A,T46,A)') "ref. basis / meV", "number"
607
608 END SUBROUTINE print_frontier_orbital_table_header
609
610! **************************************************************************************************
611!> \brief Collect reference and initial basis-set names for every fitted atom kind.
612!> \param section ...
613!> \param opt_bas ...
614!> \param element_symbols ...
615!> \param reference_basis_names ...
616!> \param initial_basis_names ...
617! **************************************************************************************************
618 SUBROUTINE get_frontier_orbital_basis_sets(section, opt_bas, element_symbols, &
619 reference_basis_names, initial_basis_names)
620 TYPE(section_vals_type), POINTER :: section
621 TYPE(basis_optimization_type), INTENT(IN) :: opt_bas
622 CHARACTER(LEN=default_string_length), &
623 ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: element_symbols, reference_basis_names, &
624 initial_basis_names
625
626 CHARACTER(LEN=default_string_length) :: element
627 CHARACTER(LEN=default_string_length), &
628 DIMENSION(:), POINTER :: basis_info
629 INTEGER :: ifit, ikind, nkinds
630 LOGICAL :: element_explicit, found
631 TYPE(section_vals_type), POINTER :: kind_section, subsys_section
632
633 subsys_section => section_vals_get_subs_vals(section, "FORCE_EVAL%SUBSYS")
634 kind_section => section_vals_get_subs_vals(subsys_section, "KIND")
635 CALL section_vals_get(kind_section, n_repetition=nkinds)
636
637 ALLOCATE (element_symbols(opt_bas%nkind), reference_basis_names(opt_bas%nkind), &
638 initial_basis_names(opt_bas%nkind))
639 DO ifit = 1, opt_bas%nkind
640 found = .false.
641 DO ikind = 1, nkinds
642 CALL section_vals_val_get(kind_section, "ELEMENT", explicit=element_explicit, &
643 i_rep_section=ikind)
644 IF (element_explicit) THEN
645 CALL section_vals_val_get(kind_section, "ELEMENT", c_val=element, i_rep_section=ikind)
646 ELSE
647 CALL section_vals_val_get(kind_section, "_SECTION_PARAMETERS_", &
648 c_val=element, i_rep_section=ikind)
649 END IF
650 CALL uppercase(element)
651 IF (trim(element) == trim(opt_bas%kind_basis(ifit)%element)) THEN
652 NULLIFY (basis_info)
653 CALL section_vals_val_get(kind_section, "BASIS_SET", c_vals=basis_info, &
654 i_rep_val=1, i_rep_section=ikind)
655 element_symbols(ifit) = opt_bas%kind_basis(ifit)%element
656 reference_basis_names(ifit) = basis_info(SIZE(basis_info))
657 initial_basis_names(ifit) = opt_bas%kind_basis(ifit)%basis_name
658 found = .true.
659 EXIT
660 END IF
661 END DO
662 IF (.NOT. found) THEN
663 CALL cp_abort(__location__, &
664 "Could not find the reference basis set for fitted atom kind "// &
665 trim(opt_bas%kind_basis(ifit)%element))
666 END IF
667 END DO
668
669 END SUBROUTINE get_frontier_orbital_basis_sets
670
671! **************************************************************************************************
672!> \brief Print the compact, aligned human-readable screening summary.
673!> \param unit_nr ...
674!> \param filename ...
675!> \param section ...
676!> \param candidates ...
677!> \param reference_gap ...
678!> \param reference_energy ...
679!> \param reference_condition_number ...
680!> \param initial_gap ...
681!> \param initial_energy ...
682!> \param initial_condition_number ...
683! **************************************************************************************************
684 SUBROUTINE print_frontier_orbital_summary(unit_nr, filename, section, candidates, &
685 reference_gap, reference_energy, reference_condition_number, &
686 initial_gap, initial_energy, initial_condition_number)
687 INTEGER, INTENT(IN) :: unit_nr
688 CHARACTER(LEN=*), INTENT(IN) :: filename
689 TYPE(section_vals_type), POINTER :: section
690 TYPE(frontier_orbital_screening_candidate_type), &
691 DIMENSION(:), INTENT(IN) :: candidates
692 REAL(kind=dp), INTENT(IN) :: reference_gap, reference_energy, reference_condition_number, &
693 initial_gap, initial_energy, initial_condition_number
694
695 CHARACTER(LEN=default_string_length), &
696 ALLOCATABLE, DIMENSION(:) :: element_symbols, initial_basis_names, &
697 reference_basis_names
698 INTEGER :: candidate, separator
699
700 IF (unit_nr <= 0) RETURN
701 separator = scan(trim(filename), "/", back=.true.)
702 WRITE (unit_nr, '(A)') ""
703 WRITE (unit_nr, '(1X,A)') repeat("-", 79)
704 WRITE (unit_nr, '(1X,A)') &
705 "SCF calcs. with ref. basis set, initial small and optimized basis sets"
706 WRITE (unit_nr, '(1X,A)') repeat("-", 79)
707 WRITE (unit_nr, '(A)') ""
708 CALL get_frontier_orbital_basis_sets(section, candidates(1)%opt_bas, element_symbols, &
709 reference_basis_names, initial_basis_names)
710 CALL print_frontier_orbital_basis_sets(unit_nr, element_symbols, reference_basis_names, &
711 initial_basis_names)
712 DEALLOCATE (element_symbols, reference_basis_names, initial_basis_names)
713 WRITE (unit_nr, '(A)') ""
714 CALL print_frontier_orbital_table_header(unit_nr)
715 WRITE (unit_nr, '(A)') ""
716 WRITE (unit_nr, '(1X,A,T14,F8.3,T24,F16.1,T46,ES11.3,T59,F17.12)') &
717 "Reference", reference_gap*evolt, 0.0_dp, reference_condition_number, reference_energy
718 WRITE (unit_nr, '(1X,A,T14,F8.3,T24,F16.1,T46,ES11.3,T59,F17.12)') &
719 "Initial", initial_gap*evolt, abs(initial_gap - reference_gap)*evolt*1000.0_dp, &
720 initial_condition_number, initial_energy
721 DO candidate = 1, SIZE(candidates)
722 WRITE (unit_nr, '(1X,A,I0,T14,F8.3,T24,F16.1,T46,ES11.3,T59,F17.12)') &
723 "Basis ", candidate, candidates(candidate)%gap*evolt, &
724 abs(candidates(candidate)%gap - reference_gap)*evolt*1000.0_dp, &
725 candidates(candidate)%condition_number, candidates(candidate)%energy
726 END DO
727 WRITE (unit_nr, '(A)') ""
728 WRITE (unit_nr, '(1X,A)') repeat("-", 79)
729 WRITE (unit_nr, '(A)') ""
730 WRITE (unit_nr, '(1X,A,A)') &
731 "Basis set file containing all optimized basis sets: ", trim(filename(separator + 1:))
732 WRITE (unit_nr, '(A)') ""
733 WRITE (unit_nr, '(1X,A)') repeat("=", 79)
734 WRITE (unit_nr, '(A)') ""
735
736 END SUBROUTINE print_frontier_orbital_summary
737
738! **************************************************************************************************
739!> \brief Join a screening working directory and filename.
740!> \param directory ...
741!> \param filename ...
742!> \return ...
743! **************************************************************************************************
744 PURE FUNCTION work_path(directory, filename) RESULT(path)
745 CHARACTER(LEN=*), INTENT(IN) :: directory, filename
746 CHARACTER(LEN=default_path_length) :: path
747
748 INTEGER :: n
749
750 n = len_trim(directory)
751 IF (filename(1:1) == "/") THEN
752 path = filename
753 ELSE IF (n == 0 .OR. directory(n:n) == "/") THEN
754 path = trim(directory)//filename
755 ELSE
756 path = trim(directory)//"/"//filename
757 END IF
758
759 END FUNCTION work_path
760
methods related to the blacs parallel environment
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
character(len=default_path_length) function, public discover_file(file_name)
Checks various locations for a file name.
Definition cp_files.F:521
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
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer, parameter, public debug_print_level
integer, parameter, public silent_print_level
Define type storing the global information of a run. Keep the amount of stored data small....
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public atomic_guess
integer, parameter, public do_qs
objects that represent the structure of input sections and the data contained in an input section
subroutine, public section_vals_val_set(section_vals, keyword_name, i_rep_section, i_rep_val, val, l_val, i_val, r_val, c_val, l_vals_ptr, i_vals_ptr, r_vals_ptr, c_vals_ptr)
sets the requested value
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_duplicate(section_vals_in, section_vals_out, i_rep_start, i_rep_end)
creates a deep copy from section_vals_in to section_vals_out
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
recursive subroutine, public section_vals_release(section_vals)
releases the given object
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public default_path_length
Definition kinds.F:58
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_getcwd(curdir)
...
Definition machine.F:607
Interface to the message passing library MPI.
subroutine, public update_basis_set(opt_bas, bas_id, basis_type, qs_env)
...
Automatic screening of frontier-orbital basis optimizations.
subroutine, public run_frontier_orbital_screening(input_declaration, section, para_env, globenv, frontier_screening_section, optimize_basis_driver)
Run serial frontier-orbital optimizations and evaluate their HOMO-LUMO gaps with new SCFs.
Utilities for frontier-orbital basis optimization.
subroutine, public frontier_orbitals_reference_init(qs_env, reference)
Diagonalize and store the frozen reference Hamiltonian.
subroutine, public frontier_orbitals_reference_release(reference)
Release the stored reference eigenvalues and eigenvectors.
subroutine, public print_frontier_orbital_basis_sets(unit_nr, element_symbols, reference_basis_names, initial_basis_names)
Print reference and initial basis-set names for every fitted atom kind.
subroutine, public deallocate_basis_optimization_type(opt_bas)
Deallocate everything which was allocated before. Note not all arrays are used depending on the type ...
integer, parameter, public method_mo_fit_occ_virtual
subroutine, public optimize_basis_init_read_input(opt_bas, root_section, para_env, quiet_output, embedded_training)
initialize all parts of the optimization type and read input settings
subroutine, public write_basis(basis, element, unit_nr)
Write a basis set file which can be used from CP2K.
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
Calculation of overlap matrix condition numbers.
Definition qs_condnum.F:13
subroutine, public overlap_condnum(matrixkp_s, condnum, iunit, norml1, norml2, use_arnoldi, blacs_env)
Calculation of the overlap matrix Condition Number.
Definition qs_condnum.F:66
Perform a QUICKSTEP wavefunction optimization (single point).
Definition qs_energy.F:14
subroutine, public qs_energies(qs_env, consistent_energies, calc_forces)
Driver routine for QUICKSTEP single point wavefunction optimization.
Definition qs_energy.F:71
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, matrix_vhxc, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
subroutine, public qs_env_release(qs_env)
releases the given qs_env (see doc/ReferenceCounting.html)
subroutine, public qs_env_create(qs_env, globenv)
allocates and intitializes a qs_env
subroutine, public qs_init(qs_env, para_env, root_section, globenv, cp_subsys, kpoint_env, qmmm, qmmm_env_qm, force_env_section, subsys_section, use_motion_section, silent, multip, charge)
Read the input and the database files for the setup of the QUICKSTEP environment.
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
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.
Utilities for string manipulations.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
represent a blacs multidimensional parallel environment (for the mpi corrispective see cp_paratypes/m...
type of a logger, at the moment it contains just a print level starting at which level it should be l...
contains the initially parsed file and the initial parallel environment
represent a section of the input file
stores all the informations relevant to an mpi environment
type containing all information needed for basis matching