(git:ccc2433)
atom_basis.F
Go to the documentation of this file.
1 !--------------------------------------------------------------------------------------------------!
2 ! CP2K: A general program to perform molecular dynamics simulations !
3 ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 ! !
5 ! SPDX-License-Identifier: GPL-2.0-or-later !
6 !--------------------------------------------------------------------------------------------------!
7 
8 MODULE atom_basis
9  USE atom_fit, ONLY: atom_fit_basis
10  USE atom_output, ONLY: atom_print_basis,&
14  USE atom_types, ONLY: &
15  atom_basis_type, atom_integrals, atom_optimization_type, atom_orbitals, atom_p_type, &
16  atom_potential_type, atom_state, create_atom_orbs, create_atom_type, init_atom_basis, &
21  get_maxl_occ,&
24  cp_logger_type
27  USE input_constants, ONLY: do_analytic
30  section_vals_type,&
32  USE kinds, ONLY: default_string_length,&
33  dp
34  USE periodic_table, ONLY: nelem,&
35  ptable
36 #include "./base/base_uses.f90"
37 
38  IMPLICIT NONE
39  PRIVATE
40  PUBLIC :: atom_basis_opt
41 
42  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'atom_basis'
43 
44 CONTAINS
45 
46 ! **************************************************************************************************
47 !> \brief Optimize the atomic basis set.
48 !> \param atom_section ATOM input section
49 !> \par History
50 !> * 04.2009 created starting from the subroutine atom_energy() [Juerg Hutter]
51 ! **************************************************************************************************
52  SUBROUTINE atom_basis_opt(atom_section)
53  TYPE(section_vals_type), POINTER :: atom_section
54 
55  CHARACTER(len=*), PARAMETER :: routinen = 'atom_basis_opt'
56 
57  CHARACTER(LEN=2) :: elem
58  CHARACTER(LEN=default_string_length), &
59  DIMENSION(:), POINTER :: tmpstringlist
60  INTEGER :: do_eric, do_erie, handle, i, im, in, &
61  iunit, iw, k, maxl, mb, method, mo, &
62  n_meth, n_rep, nr_gh, reltyp, zcore, &
63  zval, zz
64  INTEGER, DIMENSION(0:lmat) :: maxn
65  INTEGER, DIMENSION(:), POINTER :: cn
66  LOGICAL :: do_gh, eri_c, eri_e, had_ae, had_pp, &
67  pp_calc
68  REAL(kind=dp), DIMENSION(0:lmat, 10) :: pocc
69  TYPE(atom_basis_type), POINTER :: ae_basis, pp_basis
70  TYPE(atom_integrals), POINTER :: ae_int, pp_int
71  TYPE(atom_optimization_type) :: optimization
72  TYPE(atom_orbitals), POINTER :: orbitals
73  TYPE(atom_p_type), DIMENSION(:, :), POINTER :: atom_info
74  TYPE(atom_potential_type), POINTER :: ae_pot, p_pot
75  TYPE(atom_state), POINTER :: state
76  TYPE(cp_logger_type), POINTER :: logger
77  TYPE(section_vals_type), POINTER :: basis_section, method_section, &
78  opt_section, potential_section, &
79  powell_section, xc_section
80 
81  CALL timeset(routinen, handle)
82 
83  ! What atom do we calculate
84  CALL section_vals_val_get(atom_section, "ATOMIC_NUMBER", i_val=zval)
85  CALL section_vals_val_get(atom_section, "ELEMENT", c_val=elem)
86  zz = 0
87  DO i = 1, nelem
88  IF (ptable(i)%symbol == elem) THEN
89  zz = i
90  EXIT
91  END IF
92  END DO
93  IF (zz /= 1) zval = zz
94 
95  ! read and set up inofrmation on the basis sets
96  ALLOCATE (ae_basis, pp_basis)
97  basis_section => section_vals_get_subs_vals(atom_section, "AE_BASIS")
98  NULLIFY (ae_basis%grid)
99  CALL init_atom_basis(ae_basis, basis_section, zval, "AE")
100  NULLIFY (pp_basis%grid)
101  basis_section => section_vals_get_subs_vals(atom_section, "PP_BASIS")
102  CALL init_atom_basis(pp_basis, basis_section, zval, "PP")
103 
104  ! print general and basis set information
105  logger => cp_get_default_logger()
106  iw = cp_print_key_unit_nr(logger, atom_section, "PRINT%PROGRAM_BANNER", extension=".log")
107  IF (iw > 0) CALL atom_print_info(zval, "Atomic Basis Optimization", iw)
108  CALL cp_print_key_finished_output(iw, logger, atom_section, "PRINT%PROGRAM_BANNER")
109 
110  ! read and setup information on the pseudopotential
111  NULLIFY (potential_section)
112  potential_section => section_vals_get_subs_vals(atom_section, "POTENTIAL")
113  ALLOCATE (ae_pot, p_pot)
114  CALL init_atom_potential(p_pot, potential_section, zval)
115  CALL init_atom_potential(ae_pot, potential_section, -1)
116 
117  ! if the ERI's are calculated analytically, we have to precalculate them
118  eri_c = .false.
119  CALL section_vals_val_get(atom_section, "COULOMB_INTEGRALS", i_val=do_eric)
120  IF (do_eric == do_analytic) eri_c = .true.
121  eri_e = .false.
122  CALL section_vals_val_get(atom_section, "EXCHANGE_INTEGRALS", i_val=do_erie)
123  IF (do_erie == do_analytic) eri_e = .true.
124  CALL section_vals_val_get(atom_section, "USE_GAUSS_HERMITE", l_val=do_gh)
125  CALL section_vals_val_get(atom_section, "GRID_POINTS_GH", i_val=nr_gh)
126 
127  ! information on the states to be calculated
128  CALL section_vals_val_get(atom_section, "MAX_ANGULAR_MOMENTUM", i_val=maxl)
129  maxn = 0
130  CALL section_vals_val_get(atom_section, "CALCULATE_STATES", i_vals=cn)
131  DO in = 1, min(SIZE(cn), 4)
132  maxn(in - 1) = cn(in)
133  END DO
134  DO in = 0, lmat
135  maxn(in) = min(maxn(in), ae_basis%nbas(in))
136  maxn(in) = min(maxn(in), pp_basis%nbas(in))
137  END DO
138 
139  ! read optimization section
140  opt_section => section_vals_get_subs_vals(atom_section, "OPTIMIZATION")
141  CALL read_atom_opt_section(optimization, opt_section)
142 
143  had_ae = .false.
144  had_pp = .false.
145 
146  ! Check for the total number of electron configurations to be calculated
147  CALL section_vals_val_get(atom_section, "ELECTRON_CONFIGURATION", n_rep_val=n_rep)
148  ! Check for the total number of method types to be calculated
149  method_section => section_vals_get_subs_vals(atom_section, "METHOD")
150  CALL section_vals_get(method_section, n_repetition=n_meth)
151 
152  ! integrals
153  ALLOCATE (ae_int, pp_int)
154 
155  ALLOCATE (atom_info(n_rep, n_meth))
156 
157  DO in = 1, n_rep
158  DO im = 1, n_meth
159 
160  NULLIFY (atom_info(in, im)%atom)
161  CALL create_atom_type(atom_info(in, im)%atom)
162 
163  atom_info(in, im)%atom%optimization = optimization
164 
165  atom_info(in, im)%atom%z = zval
166  xc_section => section_vals_get_subs_vals(method_section, "XC", i_rep_section=im)
167  atom_info(in, im)%atom%xc_section => xc_section
168 
169  ALLOCATE (state)
170 
171  ! get the electronic configuration
172  CALL section_vals_val_get(atom_section, "ELECTRON_CONFIGURATION", i_rep_val=in, &
173  c_vals=tmpstringlist)
174 
175  ! set occupations
176  CALL atom_set_occupation(tmpstringlist, state%occ, state%occupation, state%multiplicity)
177  state%maxl_occ = get_maxl_occ(state%occ)
178  state%maxn_occ = get_maxn_occ(state%occ)
179 
180  ! set number of states to be calculated
181  state%maxl_calc = max(maxl, state%maxl_occ)
182  state%maxl_calc = min(lmat, state%maxl_calc)
183  state%maxn_calc = 0
184  DO k = 0, state%maxl_calc
185  state%maxn_calc(k) = max(maxn(k), state%maxn_occ(k))
186  END DO
187 
188  ! is there a pseudo potential
189  pp_calc = any(index(tmpstringlist(1:), "CORE") /= 0)
190  IF (pp_calc) THEN
191  ! get and set the core occupations
192  CALL section_vals_val_get(atom_section, "CORE", c_vals=tmpstringlist)
193  CALL atom_set_occupation(tmpstringlist, state%core, pocc)
194  zcore = zval - nint(sum(state%core))
195  CALL set_atom(atom_info(in, im)%atom, zcore=zcore, pp_calc=.true.)
196  had_pp = .true.
197  CALL set_atom(atom_info(in, im)%atom, basis=pp_basis, potential=p_pot)
198  state%maxn_calc(:) = min(state%maxn_calc(:), pp_basis%nbas(:))
199  cpassert(all(state%maxn_calc(:) >= state%maxn_occ))
200  ELSE
201  state%core = 0._dp
202  CALL set_atom(atom_info(in, im)%atom, zcore=zval, pp_calc=.false.)
203  had_ae = .true.
204  CALL set_atom(atom_info(in, im)%atom, basis=ae_basis, potential=ae_pot)
205  state%maxn_calc(:) = min(state%maxn_calc(:), ae_basis%nbas(:))
206  cpassert(all(state%maxn_calc(:) >= state%maxn_occ))
207  END IF
208 
209  CALL section_vals_val_get(method_section, "METHOD_TYPE", i_val=method, i_rep_val=im)
210  CALL section_vals_val_get(method_section, "RELATIVISTIC", i_val=reltyp, i_rep_section=im)
211  CALL set_atom(atom_info(in, im)%atom, method_type=method, relativistic=reltyp)
212  CALL set_atom(atom_info(in, im)%atom, state=state)
213  CALL set_atom(atom_info(in, im)%atom, coulomb_integral_type=do_eric, &
214  exchange_integral_type=do_erie)
215  atom_info(in, im)%atom%hfx_pot%do_gh = do_gh
216  atom_info(in, im)%atom%hfx_pot%nr_gh = nr_gh
217 
218  IF (atom_consistent_method(method, state%multiplicity)) THEN
219  iw = cp_print_key_unit_nr(logger, atom_section, "PRINT%METHOD_INFO", extension=".log")
220  CALL atom_print_method(atom_info(in, im)%atom, iw)
221  CALL cp_print_key_finished_output(iw, logger, atom_section, "PRINT%METHOD_INFO")
222  iw = cp_print_key_unit_nr(logger, atom_section, "PRINT%POTENTIAL", extension=".log")
223  IF (pp_calc) THEN
224  IF (iw > 0) CALL atom_print_potential(p_pot, iw)
225  ELSE
226  IF (iw > 0) CALL atom_print_potential(ae_pot, iw)
227  END IF
228  CALL cp_print_key_finished_output(iw, logger, atom_section, "PRINT%POTENTIAL")
229  ELSE
230  cpabort("METHOD_TYPE and MULTIPLICITY are incompatible")
231  END IF
232 
233  NULLIFY (orbitals)
234  mo = maxval(state%maxn_calc)
235  mb = maxval(atom_info(in, im)%atom%basis%nbas)
236  CALL create_atom_orbs(orbitals, mb, mo)
237  CALL set_atom(atom_info(in, im)%atom, orbitals=orbitals)
238 
239  END DO
240  END DO
241 
242  ! Start the Optimization
243  powell_section => section_vals_get_subs_vals(atom_section, "POWELL")
244  iw = cp_print_key_unit_nr(logger, atom_section, "PRINT%SCF_INFO", extension=".log")
245  iunit = cp_print_key_unit_nr(logger, atom_section, "PRINT%FIT_BASIS", extension=".log")
246  IF (had_ae) THEN
247  pp_calc = .false.
248  CALL atom_fit_basis(atom_info, ae_basis, pp_calc, iunit, powell_section)
249  END IF
250  IF (had_pp) THEN
251  pp_calc = .true.
252  CALL atom_fit_basis(atom_info, pp_basis, pp_calc, iunit, powell_section)
253  END IF
254  CALL cp_print_key_finished_output(iunit, logger, atom_section, "PRINT%FIT_BASIS")
255  CALL cp_print_key_finished_output(iw, logger, atom_section, "PRINT%SCF_INFO")
256  iw = cp_print_key_unit_nr(logger, atom_section, "PRINT%BASIS_SET", extension=".log")
257  IF (iw > 0) THEN
258  CALL atom_print_basis(ae_basis, iw, " All Electron Basis")
259  CALL atom_print_basis(pp_basis, iw, " Pseudopotential Basis")
260  END IF
261  CALL cp_print_key_finished_output(iw, logger, atom_section, "PRINT%BASIS_SET")
262 
263  CALL release_atom_basis(ae_basis)
264  CALL release_atom_basis(pp_basis)
265 
266  CALL release_atom_potential(p_pot)
267  CALL release_atom_potential(ae_pot)
268 
269  DO in = 1, n_rep
270  DO im = 1, n_meth
271  CALL release_atom_type(atom_info(in, im)%atom)
272  END DO
273  END DO
274  DEALLOCATE (atom_info)
275 
276  DEALLOCATE (ae_pot, p_pot, ae_basis, pp_basis, ae_int, pp_int)
277 
278  CALL timestop(handle)
279 
280  END SUBROUTINE atom_basis_opt
281 
282 END MODULE atom_basis
subroutine, public atom_basis_opt(atom_section)
Optimize the atomic basis set.
Definition: atom_basis.F:53
routines that fit parameters for /from atomic calculations
Definition: atom_fit.F:11
subroutine, public atom_fit_basis(atom_info, basis, pptype, iunit, powell_section)
...
Definition: atom_fit.F:175
Routines that print various information about an atomic kind.
Definition: atom_output.F:11
subroutine, public atom_print_basis(atom_basis, iw, title)
Print atomic basis set.
Definition: atom_output.F:293
subroutine, public atom_print_method(atom, iw)
Print information about the electronic structure method in use.
Definition: atom_output.F:504
subroutine, public atom_print_potential(potential, iw)
Print information about the pseudo-potential.
Definition: atom_output.F:640
subroutine, public atom_print_info(zval, info, iw)
Print an information string related to the atomic kind.
Definition: atom_output.F:64
Define the atom type and its sub types.
Definition: atom_types.F:15
subroutine, public read_atom_opt_section(optimization, opt_section)
...
Definition: atom_types.F:2395
subroutine, public create_atom_type(atom)
...
Definition: atom_types.F:944
subroutine, public release_atom_type(atom)
...
Definition: atom_types.F:968
subroutine, public release_atom_potential(potential)
...
Definition: atom_types.F:2521
subroutine, public init_atom_basis(basis, basis_section, zval, btyp)
Initialize the basis for the atomic code.
Definition: atom_types.F:375
integer, parameter, public lmat
Definition: atom_types.F:67
subroutine, public set_atom(atom, basis, state, integrals, orbitals, potential, zcore, pp_calc, do_zmp, doread, read_vxc, method_type, relativistic, coulomb_integral_type, exchange_integral_type, fmat)
...
Definition: atom_types.F:1009
subroutine, public init_atom_potential(potential, potential_section, zval)
...
Definition: atom_types.F:2421
subroutine, public release_atom_basis(basis)
...
Definition: atom_types.F:910
subroutine, public create_atom_orbs(orbs, mbas, mo)
...
Definition: atom_types.F:1055
Some basic routines for atomic calculations.
Definition: atom_utils.F:15
pure logical function, public atom_consistent_method(method, multiplicity)
Check that the atomic multiplicity is consistent with the electronic structure method.
Definition: atom_utils.F:2189
pure integer function, dimension(0:lmat), public get_maxn_occ(occupation)
Return the maximum principal quantum number of occupied orbitals.
Definition: atom_utils.F:302
subroutine, public atom_set_occupation(ostring, occupation, wfnocc, multiplicity)
Set occupation of atomic orbitals.
Definition: atom_utils.F:104
pure integer function, public get_maxl_occ(occupation)
Return the maximum orbital quantum number of occupied orbitals.
Definition: atom_utils.F:282
various routines to log and control the output. The idea is that decisions about where to log should ...
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 function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_analytic
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_string_length
Definition: kinds.F:57
Periodic Table related data definitions.
type(atom), dimension(0:nelem), public ptable
integer, parameter, public nelem