(git:08825b9)
Loading...
Searching...
No Matches
atom_upf_unittest.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
17 USE atom_types, ONLY: &
20 release_atom_potential, sgp_pseudo, upf_pseudo
21 USE atom_upf, ONLY: atom_read_upf,&
23 atom_upfpot_type
24 USE atom_utils, ONLY: atom_core_density,&
26 USE cp_files, ONLY: close_file,&
36 USE ieee_arithmetic, ONLY: ieee_is_finite
49 USE kinds, ONLY: default_path_length,&
50 dp
51 USE libcp2k, ONLY: cp2k_finalize,&
53 USE mathconstants, ONLY: fourpi,&
54 pi
55 USE orbital_pointers, ONLY: co,&
57 nco,&
58 nso
65
66 IMPLICIT NONE
67 LOGICAL :: source_root_argument
68
69 CHARACTER(LEN=default_path_length) :: filename
70 INTEGER :: i, io_unit
71 REAL(kind=dp) :: error(6)
72 TYPE(atom_upfpot_type) :: pot
73 TYPE(atom_sgp_potential_type) :: sgp
74
75 CALL cp2k_init()
77 CALL check_core_derivatives()
78 CALL check_projector_addition_theorem()
79 CALL check_atomic_potential()
80 CALL check_upf_units()
81 CALL check_nlcc_fit()
82 CALL check_basis_origin()
83 CALL check_basis_derivatives()
84 CALL check_radial_grid_endpoints()
85 CALL check_contracted_basis_reader()
86 CALL check_basis_optimization_export()
88 CALL check_uspp_partial_waves()
89
90 ! The same temporary is reused for successive KIND sections in Quickstep.
91 ALLOCATE (pot%rho_nlcc(3))
92 pot%rho_nlcc = 1.0_dp
93 pot%core_correction = .true.
94 pot%econf = [2, 4, 0, 0]
95 pot%pname = "previous kind"
96 CALL atom_release_upf(pot)
97 IF (ALLOCATED(pot%rho_nlcc)) error stop "UPF release leaked the core density"
98 IF (pot%core_correction) error stop "UPF release retained core-correction metadata"
99 IF (any(pot%econf /= 0)) error stop "UPF release retained the previous electron configuration"
100 IF (pot%pname /= "") error stop "UPF release retained the previous potential name"
101 CALL atom_release_upf(pot)
102
103 ALLOCATE (sgp%a_nlcc(2), sgp%c_nlcc(2))
104 sgp%has_nlcc = .true.
105 sgp%n_nlcc = 2
106 sgp%is_nonlocal(2) = .true.
107 CALL atom_sgp_release(sgp)
108 IF (ASSOCIATED(sgp%a_nlcc) .OR. ASSOCIATED(sgp%c_nlcc)) error stop "SGP release leaked NLCC arrays"
109 IF (sgp%has_nlcc .OR. sgp%n_nlcc /= 0) error stop "SGP release retained NLCC metadata"
110 IF (any(sgp%is_nonlocal)) error stop "SGP release retained nonlocal channels"
111 CALL atom_sgp_release(sgp)
112
113 ! Optional external UPF files exercise the real reader and Gaussian transformation.
114 ! This also permits auditing a complete SSSP library without bundling it in CP2K.
115 DO i = 1, command_argument_count()
116 CALL get_command_argument(i, filename)
117 ! do_regtest.py passes the CP2K source root before any optional UPF audit files.
118 IF (i == 1) THEN
119 INQUIRE (file=trim(filename)//"/tests/UNIT_TESTS", exist=source_root_argument)
120 IF (source_root_argument) cycle
121 END IF
122 CALL atom_read_upf(pot, trim(filename))
123 IF (abs(sum(pot%econf) - pot%zion) > 1.e-10_dp) error stop "UPF valence count mismatch"
124 IF (.NOT. all(ieee_is_finite(pot%vlocal))) error stop "Non-finite UPF local potential"
125 IF (any(pot%r(2:) <= pot%r(:SIZE(pot%r) - 1))) error stop "UPF mesh is not increasing"
126 IF (any(pot%rab <= 0.0_dp)) error stop "Non-positive UPF mesh weights"
127 IF (ALLOCATED(pot%dion)) THEN
128 IF (.NOT. all(ieee_is_finite(pot%dion))) error stop "Non-finite UPF projector coefficients"
129 IF (.NOT. all(ieee_is_finite(pot%beta))) error stop "Non-finite UPF projectors"
130 IF (maxval(abs(pot%dion - transpose(pot%dion))) > 1.e-10_dp) error stop "Non-Hermitian UPF D matrix"
131 END IF
132 CALL sgp_construction(sgp, upf_pot=pot, error=error)
133 IF (.NOT. all(ieee_is_finite(error))) error stop "Non-finite UPF transformation errors"
134 IF (pot%core_correction) THEN
135 IF (.NOT. ASSOCIATED(sgp%a_nlcc)) error stop "Missing transformed UPF core density"
136 IF (.NOT. all(ieee_is_finite(sgp%c_nlcc))) error stop "Non-finite transformed UPF core density"
137 END IF
138 IF (io_unit > 0) WRITE (io_unit, '(A,1X,A,1X,6ES16.7)') "UPF transformation:", trim(filename), error
139 CALL atom_sgp_release(sgp)
140 CALL atom_release_upf(pot)
141 END DO
142
143 CALL cp2k_finalize()
144
145CONTAINS
146
147! **************************************************************************************************
148!> \brief ...
149! **************************************************************************************************
150 SUBROUTINE check_uspp_import()
151 CHARACTER(LEN=*), PARAMETER :: fixture = "uspp-augmentation-test.upf"
152
153 INTEGER :: unit
154 TYPE(atom_upfpot_type) :: pot
155 TYPE(cp_logger_type), POINTER :: logger
156
157 logger => cp_get_default_logger()
158 IF (logger%para_env%is_source()) THEN
159 OPEN (newunit=unit, file=fixture, status='REPLACE', action='WRITE')
160 WRITE (unit, '(A)') &
161 '<UPF version="2.0.1">', &
162 '<PP_HEADER element="Pt" pseudo_type="USPP" is_ultrasoft="true"', &
163 ' z_valence="16" mesh_size="3" number_of_proj="2" l_max="1" />', &
164 '<PP_MESH mesh="3">', &
165 '<PP_R>', &
166 '0.5 1.0 1.5', &
167 '</PP_R>', &
168 '<PP_RAB>', &
169 '0.5 0.5 0.5', &
170 '</PP_RAB>', &
171 '</PP_MESH>', &
172 '<PP_LOCAL type="real" size="3">', &
173 '6 4 2', &
174 '</PP_LOCAL>', &
175 '<PP_NONLOCAL>', &
176 '<PP_BETA.1 type="real" size="3" index="1" angular_momentum="0">', &
177 '1 4 9', &
178 '</PP_BETA.1>', &
179 '<PP_BETA.2 type="real" size="3" index="2" angular_momentum="1">', &
180 '2 -1 3', &
181 '</PP_BETA.2>', &
182 '<PP_DIJ>', &
183 '2 0 0 8', &
184 '</PP_DIJ>', &
185 '<PP_AUGMENTATION q_with_l="T" nqf="0" nqlc="3">', &
186 '<PP_Q>', &
187 '2 0 0 3', &
188 '</PP_Q>', &
189 '<PP_QIJL.2.2.0 first_index="2" second_index="2" composite_index="3" angular_momentum="0">', &
190 '-3 4 5', &
191 '</PP_QIJL.2.2.0>', &
192 '<PP_QIJL.1.1.0 type="real" size="3" first_index="1" second_index="1"', &
193 ' composite_index="1" angular_momentum="0" is_null="false">', &
194 '1 2 3', &
195 '</PP_QIJL.1.1.0>', &
196 '<PP_QIJL.1.2.1 first_index="1" second_index="2" composite_index="2" angular_momentum="1">', &
197 '4 -5 6', &
198 '</PP_QIJL.1.2.1>', &
199 '<PP_QIJL.2.2.2 first_index="2" second_index="2" composite_index="3"', &
200 ' angular_momentum="2" is_null="T" size="0"/>', &
201 '</PP_AUGMENTATION>', &
202 '</PP_NONLOCAL>', &
203 '</UPF>'
204 CLOSE (unit)
205 END IF
206 CALL logger%para_env%sync()
207 CALL atom_read_upf(pot, fixture, read_augmentation=.true.)
208 IF (any(pot%econf(0:3) /= [1, 6, 9, 0])) error stop 'Wrong 62-electron core subtraction'
209 IF (any(shape(pot%qijl) /= [3, 3, 3]) .OR. lbound(pot%qijl, 3) /= 0) error stop 'Wrong augmentation shape'
210 IF (maxval(abs(pot%qij - reshape([2._dp, 0._dp, 0._dp, 3._dp], [2, 2]))) > 1.e-14_dp) THEN
211 error stop 'PP_Q normalization changed'
212 END IF
213 IF (maxval(abs(pot%qijl(:, 1, 0) - [1._dp, 2._dp, 3._dp])) > 1.e-14_dp) error stop 'Wrong s-s augmentation'
214 IF (maxval(abs(pot%qijl(:, 2, 1) - [4._dp, -5._dp, 6._dp])) > 1.e-14_dp) error stop 'Wrong s-p augmentation'
215 IF (maxval(abs(pot%qijl(:, 3, 0) - [-3._dp, 4._dp, 5._dp])) > 1.e-14_dp) error stop 'Wrong p-p augmentation'
216 IF (any(pot%qijl(:, :, 2) /= 0._dp)) error stop 'Null augmentation was not zero initialized'
217 IF (maxval(abs(pot%beta(:, 2) - [4._dp, -1._dp, 2._dp])) > 1.e-14_dp) error stop 'USPP beta normalization changed'
218 IF (abs(pot%dion(2, 2) - 4._dp) > 1.e-14_dp) error stop 'USPP D is not in Hartree'
219 CALL atom_release_upf(pot)
220 IF (ALLOCATED(pot%qij) .OR. ALLOCATED(pot%qijl)) error stop 'Augmentation arrays were not released'
221 CALL logger%para_env%sync()
222 IF (logger%para_env%is_source()) THEN
223 OPEN (newunit=unit, file=fixture, status='OLD')
224 CLOSE (unit, status='DELETE')
225 END IF
226
227 END SUBROUTINE check_uspp_import
228
229! **************************************************************************************************
230!> \brief ...
231! **************************************************************************************************
232 SUBROUTINE check_uspp_partial_waves()
233 CHARACTER(LEN=*), PARAMETER :: fixture = 'uspp-partial-waves-test.upf'
234
235 CHARACTER(LEN=5) :: has_wfc
236 INTEGER :: unit, variant
237 TYPE(atom_upfpot_type) :: potential
238 TYPE(cp_logger_type), POINTER :: logger
239
240 logger => cp_get_default_logger()
241 DO variant = 1, 2
242 has_wfc = 'false'
243 IF (variant == 1) has_wfc = 'true'
244 IF (logger%para_env%is_source()) THEN
245 OPEN (newunit=unit, file=fixture, status='REPLACE', action='WRITE')
246 WRITE (unit, '(A)') &
247 '<UPF version="2.0.1">', &
248 '<PP_HEADER element="H" pseudo_type="US" is_ultrasoft="true" is_paw="false"', &
249 ' has_wfc="'//trim(has_wfc)//'" z_valence="1" mesh_size="3"', &
250 ' number_of_proj="2" number_of_wfc="1" l_max="1"/>', &
251 '<PP_MESH mesh="3">', &
252 '<PP_R>', '0.5 1 1.5', '</PP_R>', &
253 '<PP_RAB>', '0.5 0.5 0.5', '</PP_RAB>', '</PP_MESH>', &
254 '<PP_LOCAL>', '6 4 2', '</PP_LOCAL>', &
255 '<PP_NONLOCAL>', &
256 '<PP_BETA.1 index="1" angular_momentum="0" size="3">', '1 4 9', '</PP_BETA.1>', &
257 '<PP_BETA.2 index="2" angular_momentum="1" size="3">', '2 -1 3', '</PP_BETA.2>', &
258 '<PP_DIJ>', '2 0 0 8', '</PP_DIJ>', &
259 '<PP_AUGMENTATION q_with_l="T" nqf="0" nqlc="3">', &
260 '<PP_Q>', '2 0 0 3', '</PP_Q>', &
261 '<PP_QIJL.1.1.0 first_index="1" second_index="1" composite_index="1" angular_momentum="0">', &
262 '1 2 3', '</PP_QIJL.1.1.0>', &
263 '<PP_QIJL.1.2.1 first_index="1" second_index="2" composite_index="2" angular_momentum="1">', &
264 '4 -5 6', '</PP_QIJL.1.2.1>', &
265 '<PP_QIJL.2.2.0 first_index="2" second_index="2" composite_index="3" angular_momentum="0">', &
266 '-3 4 5', '</PP_QIJL.2.2.0>', &
267 '<PP_QIJL.2.2.2 first_index="2" second_index="2" composite_index="3" angular_momentum="2">', &
268 '0 0 0', '</PP_QIJL.2.2.2>', '</PP_AUGMENTATION>', '</PP_NONLOCAL>', &
269 '<PP_PSWFC>', '<PP_CHI.1 l="0">', '999 999 999', '</PP_CHI.1>', '</PP_PSWFC>'
270 IF (variant == 1) THEN
271 ! Reordered, deliberately unnormalized waves distinguish every index and side.
272 WRITE (unit, '(A)') &
273 '<PP_FULL_WFC number_of_wfc="2">', &
274 '<PP_PSWFC.2 type="real" size="3" l="1">', '2 3 -4', '</PP_PSWFC.2>', &
275 '<PP_AEWFC.1 index="1" l="0">', '-3 5 -7', '</PP_AEWFC.1>', &
276 '<PP_AEWFC.2 index="2" l="1">', '5 -7 9', '</PP_AEWFC.2>', &
277 '<PP_PSWFC.1 l="0">', '1 -2 3', '</PP_PSWFC.1>', '</PP_FULL_WFC>'
278 END IF
279 WRITE (unit, '(A)') '</UPF>'
280 CLOSE (unit)
281 END IF
282 CALL logger%para_env%sync()
283 IF (variant == 1) THEN
284 CALL atom_read_upf(potential, fixture, read_header=.true.)
285 IF (ALLOCATED(potential%partial_waves)) error stop 'USPP full waves imported without augmentation request'
286 CALL atom_release_upf(potential)
287 END IF
288 CALL atom_read_upf(potential, fixture, read_augmentation=.true.)
289 IF (potential%is_paw) error stop 'USPP full waves were classified as PAW'
290 IF (variant == 1) THEN
291 IF (.NOT. ALLOCATED(potential%partial_waves)) error stop 'Missing optional USPP full waves'
292 associate(waves => potential%partial_waves)
293 IF (any(shape(waves%ae_wfc) /= [3, 2])) error stop 'USPP full-wave count differs from beta count'
294 IF (any(waves%ae_wfc /= reshape([-3._dp, 5._dp, -7._dp, 5._dp, -7._dp, 9._dp], [3, 2]))) THEN
295 error stop 'USPP AE full-wave order or original normalization changed'
296 END IF
297 IF (any(waves%ps_wfc /= reshape([1._dp, -2._dp, 3._dp, 2._dp, 3._dp, -4._dp], [3, 2]))) THEN
298 error stop 'USPP PS full waves changed or were confused with atomic guesses'
299 END IF
300 IF (any(waves%angular_momenta /= [0, 1])) error stop 'Wrong USPP full-wave angular momenta'
301 END associate
302 IF (.NOT. upf_has_complete_partial_waves(potential)) error stop 'Complete original full waves not recognized'
303 DEALLOCATE (potential%partial_waves%ps_wfc)
304 IF (upf_has_complete_partial_waves(potential)) error stop 'Incomplete full-wave pair accepted'
305 ELSE
306 IF (upf_has_complete_partial_waves(potential)) error stop 'Atomic guess waves accepted as complete full waves'
307 IF (ALLOCATED(potential%partial_waves)) error stop 'USPP without full waves allocated partial-wave data'
308 END IF
309 CALL atom_release_upf(potential)
310 IF (ALLOCATED(potential%partial_waves)) error stop 'USPP full-wave data not released'
311 CALL logger%para_env%sync()
312 END DO
313 IF (logger%para_env%is_source()) THEN
314 OPEN (newunit=unit, file=fixture, status='OLD')
315 CLOSE (unit, status='DELETE')
316 END IF
317 END SUBROUTINE check_uspp_partial_waves
318
319! **************************************************************************************************
320!> \brief Check the repaired radial maps at the size that exposes endpoint cancellation.
321! **************************************************************************************************
322 SUBROUTINE check_radial_grid_endpoints()
323 INTEGER, PARAMETER :: n = 6400, types(2) = [do_gapw_gct, do_gapw_log]
324 REAL(dp), PARAMETER :: inner(2) = [4.83458313724687745e-18_dp, 6.97482911687147684e-18_dp], &
325 outer(2) = [2.06843066219244770e17_dp, 57.5213142095328827_dp]
326
327 INTEGER :: i
328 REAL(dp) :: error
329 TYPE(grid_atom_type), POINTER :: grid
330
331 NULLIFY (grid)
332 DO i = 1, SIZE(types)
333 CALL allocate_grid_atom(grid)
334 CALL create_grid_atom(grid, n, 1, 2, 0, types(i))
335 IF (.NOT. all(ieee_is_finite(grid%rad)) .OR. .NOT. all(ieee_is_finite(grid%wr))) THEN
336 error stop 'Nonfinite radial grid'
337 END IF
338 IF (any(grid%rad <= 0.0_dp) .OR. any(grid%wr <= 0.0_dp)) error stop 'Nonpositive radial grid'
339 IF (any(grid%rad(:n - 1) <= grid%rad(2:))) error stop 'Unordered radial points'
340 ! Independent analytic moments include the r**2 radial measure.
341 error = abs(sum(grid%wr*exp(-grid%rad)) - 2.0_dp)
342 error = max(error, abs(sum(grid%wr*exp(-grid%rad)/grid%rad) - 1.0_dp))
343 error = max(error, abs(sum(grid%wr*exp(-grid%rad2)) - sqrt(pi)/4.0_dp))
344 IF (error > 1.e-10_dp) error stop 'Radial moment error'
345 ! Independent high-precision endpoints reject clipping rounded cosines.
346 IF (abs(grid%rad(n)/inner(i) - 1.0_dp) > 1.e-13_dp .OR. &
347 abs(grid%rad(1)/outer(i) - 1.0_dp) > 1.e-13_dp) error stop 'Radial grid endpoint error'
348 CALL deallocate_grid_atom(grid)
349 END DO
350 END SUBROUTINE check_radial_grid_endpoints
351
352! **************************************************************************************************
353!> \brief Check primitive and contracted Gaussian derivatives on UPF meshes starting at zero.
354! **************************************************************************************************
355 SUBROUTINE check_basis_origin()
356 INTEGER :: i, l, n, variant
357 REAL(KIND=dp) :: expected(3), r(6001), rab(6001), scale
358 TYPE(atom_basis_type) :: basis, radial
359
360 CALL init_atom_basis_default_pp(basis)
361 n = maxval(basis%nbas)
362 ! A long supplied mesh must not generate an unused singular auxiliary grid.
363 r = [(0.002_dp*real(i - 1, dp), i=1, SIZE(r))]
364 rab = 0.002_dp
365 CALL atom_basis_gridrep(basis, radial, r, rab)
366 IF (any(radial%grid%rad /= r) .OR. any(radial%grid%wr /= rab*r**2)) THEN
367 error stop "Supplied UPF mesh changed during basis evaluation"
368 END IF
369 IF (maxval(abs(radial%bf(:, 1, 0) - exp(-basis%am(1, 0)*r**2))) > 1.e-14_dp) THEN
370 error stop "Incorrect basis values on long UPF mesh"
371 END IF
372 CALL release_atom_basis(radial)
373 DO variant = 1, 2
374 scale = real(variant, dp)
375 IF (variant == 2) THEN
376 basis%basis_type = cgto_basis
377 ALLOCATE (basis%cm(n, n, 0:ubound(basis%am, 2)))
378 basis%cm = 0.0_dp
379 DO i = 1, n
380 basis%cm(i, i, :) = scale
381 END DO
382 END IF
383 CALL atom_basis_gridrep(basis, radial, [0.0_dp, 1.e-16_dp, 0.1_dp], [0.1_dp, 0.1_dp, 0.1_dp])
384 IF (.NOT. all(ieee_is_finite(radial%bf)) .OR. .NOT. all(ieee_is_finite(radial%dbf)) .OR. &
385 .NOT. all(ieee_is_finite(radial%ddbf))) error stop "Nonfinite Gaussian derivatives at the UPF origin"
386 DO l = 0, ubound(basis%am, 2)
387 DO i = 1, basis%nbas(l)
388 expected = 0.0_dp
389 IF (l == 0) expected = [1.0_dp, 0.0_dp, -2.0_dp*basis%am(i, l)]
390 IF (l == 1) expected(2) = 1.0_dp
391 IF (l == 2) expected(3) = 2.0_dp
392 IF (maxval(abs([radial%bf(1, i, l), radial%dbf(1, i, l), radial%ddbf(1, i, l)] - &
393 scale*expected)) > 1.e-12_dp) error stop "Incorrect Gaussian origin limit"
394 END DO
395 END DO
396 CALL release_atom_basis(radial)
397 END DO
398 CALL release_atom_basis(basis)
399 END SUBROUTINE check_basis_origin
400
401! **************************************************************************************************
402!> \brief Differentiate radial basis values and densities independently at finite radii.
403! **************************************************************************************************
404 SUBROUTINE check_basis_derivatives()
405 REAL(dp), PARAMETER :: radius(4) = [0.08_dp, 0.3_dp, 0.9_dp, 2.1_dp], step = 2.e-4_dp
406
407 INTEGER :: i, k, l, n, variant
408 REAL(dp) :: derivative(5), errors(3), first, lap(5), &
409 r(5), reference, rho(5), second
410 REAL(dp), ALLOCATABLE :: pmat(:, :, :)
411 TYPE(atom_basis_type) :: basis, radial
412
413 CALL init_atom_basis_default_pp(basis)
414 n = maxval(basis%nbas)
415 ! Nonunit exponents and signed mixing exercise primitives and genuine contractions.
416 basis%nbas = 2
417 basis%nprim = 2
418 basis%am(1, :) = 0.37_dp
419 basis%am(2, :) = 2.3_dp
420 ALLOCATE (pmat(n, n, 0:ubound(basis%am, 2)))
421 pmat = 0.0_dp
422 pmat(1, 1, :) = 0.8_dp
423 pmat(2, 2, :) = 0.4_dp
424 pmat(1, 2, :) = -0.17_dp
425 pmat(2, 1, :) = -0.17_dp
426 errors = 0.0_dp
427 DO variant = 1, 2
428 IF (variant == 2) THEN
429 basis%basis_type = cgto_basis
430 ALLOCATE (basis%cm(n, n, 0:ubound(basis%am, 2)))
431 basis%cm = 0.0_dp
432 basis%cm(1, 1, :) = 0.7_dp
433 basis%cm(2, 1, :) = -0.2_dp
434 basis%cm(1, 2, :) = 0.1_dp
435 basis%cm(2, 2, :) = 1.3_dp
436 END IF
437 DO k = 1, SIZE(radius)
438 r = radius(k) + step*[-2.0_dp, -1.0_dp, 0.0_dp, 1.0_dp, 2.0_dp]
439 CALL atom_basis_gridrep(basis, radial, r, spread(step, 1, 5))
440 DO l = 0, ubound(basis%am, 2)
441 DO i = 1, 2
442 first = dot_product(radial%bf(:, i, l), [1.0_dp, -8.0_dp, 0.0_dp, 8.0_dp, -1.0_dp])/(12*step)
443 second = dot_product(radial%bf(:, i, l), [-1.0_dp, 16.0_dp, -30.0_dp, 16.0_dp, -1.0_dp])/(12*step**2)
444 errors(1) = max(errors(1), abs(first - radial%dbf(3, i, l))/(1 + abs(first)))
445 errors(2) = max(errors(2), abs(second - radial%ddbf(3, i, l))/(1 + abs(second)))
446 END DO
447 END DO
448 CALL atom_density(rho, pmat, radial, ubound(basis%am, 2), typ="RHO")
449 CALL atom_density(derivative, pmat, radial, ubound(basis%am, 2), typ="DER")
450 CALL atom_density(lap, pmat, radial, ubound(basis%am, 2), typ="LAP", rr=r*r)
451 first = dot_product(rho, [1.0_dp, -8.0_dp, 0.0_dp, 8.0_dp, -1.0_dp])/(12*step)
452 second = dot_product(rho, [-1.0_dp, 16.0_dp, -30.0_dp, 16.0_dp, -1.0_dp])/(12*step**2)
453 errors(1) = max(errors(1), abs(first - derivative(3))/(1 + abs(first)))
454 reference = second + 2*first/radius(k)
455 errors(3) = max(errors(3), abs(reference - lap(3))/(1 + abs(reference)))
456 CALL release_atom_basis(radial)
457 END DO
458 END DO
459 IF (io_unit > 0) WRITE (io_unit, '(A,3ES24.15)') "Atomic radial derivative/Laplacian scaled errors: ", errors
460 DEALLOCATE (pmat)
461 CALL release_atom_basis(basis)
462 IF (maxval(errors) > 2.e-7_dp) error stop "Atomic radial finite-difference derivatives disagree"
463 END SUBROUTINE check_basis_derivatives
464
465! **************************************************************************************************
466!> \brief Check fitted densities and their derivatives against an analytic reference.
467!> Evaluation points differ from the input mesh, and neither input mesh
468!> nor reference exponents coincide with the internal fitting sequence.
469! **************************************************************************************************
470 SUBROUTINE check_nlcc_fit()
471 INTEGER, PARAMETER :: nr = 1601
472 REAL(dp), PARAMETER :: amplitudes(3) = [0.02_dp, 1.7_dp, 0.4_dp], &
473 exponents(3) = [0.15_dp, 2.3_dp, 35.0_dp]
474
475 INTEGER :: i, mesh
476 REAL(dp) :: density_error, derivative, derivative_error, dx, r(nr), rab(nr), radius, &
477 reference, reference_derivative, rho(nr), value
478 REAL(dp), ALLOCATABLE :: alpha(:), coeff(:)
479
480 DO mesh = 1, 2
481 dx = log(20.0_dp/1.e-6_dp)/real(nr - 1, dp)
482 DO i = 1, nr
483 IF (mesh == 1) THEN
484 r(i) = 20.0_dp*real(i - 1, dp)/real(nr - 1, dp)
485 rab(i) = 20.0_dp/real(nr - 1, dp)
486 ELSE
487 r(i) = 1.e-6_dp*exp(dx*real(i - 1, dp))
488 rab(i) = dx*r(i)
489 END IF
490 rho(i) = sum(amplitudes*exp(-exponents*r(i)**2))
491 END DO
492 CALL fit_core_density_gaussians(r, rab, rho, alpha, coeff)
493 density_error = 0.0_dp
494 derivative_error = 0.0_dp
495 DO i = 0, 1200
496 radius = real(i, dp)*0.017_dp
497 reference = sum(amplitudes*exp(-exponents*radius**2))
498 reference_derivative = -2.0_dp*radius*sum(exponents*amplitudes*exp(-exponents*radius**2))
499 value = sum(coeff*exp(-alpha*radius**2))
500 derivative = -2.0_dp*radius*sum(alpha*coeff*exp(-alpha*radius**2))
501 density_error = max(density_error, abs(value - reference))
502 derivative_error = max(derivative_error, abs(derivative - reference_derivative))
503 END DO
504 IF (io_unit > 0) WRITE (io_unit, '(A,I2,2ES16.7)') &
505 "Core Gaussian fit, density and derivative:", mesh, density_error, derivative_error
506 IF (density_error > 2.e-7_dp) error stop "Gaussian core-density fit is inaccurate"
507 IF (derivative_error > 3.e-6_dp) error stop "Gaussian core-density derivative is inaccurate"
508 rho = 0.0_dp
509 CALL fit_core_density_gaussians(r, rab, rho, alpha, coeff)
510 IF (any(coeff /= 0.0_dp)) error stop "Zero core density generated nonzero Gaussian coefficients"
511 END DO
512 END SUBROUTINE check_nlcc_fit
513
514! **************************************************************************************************
515!> \brief Read an independent miniature UPF fixture and check its numerical convention.
516!> The values are deliberately simple and are not a physical pseudopotential.
517!> Checking beta separately matters: an inverse rescaling of D leaves the NC
518!> operator unchanged but would require rescaling USPP augmentation data too.
519! **************************************************************************************************
520 SUBROUTINE check_upf_units()
521 CHARACTER(LEN=*), PARAMETER :: fixture = &
522 'upf-units-test-with-a-potential-filename-longer-than-'// &
523 'the-default-eighty-character-string-buffer.upf'
524
525 INTEGER :: unit
526 TYPE(atom_potential_type) :: atomic
527 TYPE(cp_logger_type), POINTER :: logger
528 TYPE(section_type), POINTER :: specification
529 TYPE(section_vals_type), POINTER :: input, potential_section
530
531 logger => cp_get_default_logger()
532 IF (logger%para_env%is_source()) THEN
533 CALL open_file(fixture, unit_number=unit, file_status="REPLACE", file_action="WRITE")
534 WRITE (unit, '(A)') &
535 '<UPF version="2.0.1">', &
536 '<PP_HEADER element="He" pseudo_type="NC" z_valence="2"', &
537 ' mesh_size="3" number_of_proj="2" l_max="0" />', &
538 '<PP_MESH mesh="3">', &
539 '<PP_R type="real" size="3">', &
540 '0.5 1.0 1.5', &
541 '</PP_R>', &
542 '<PP_RAB type="real" size="3">', &
543 '0.5 0.5 0.5', &
544 '</PP_RAB>', &
545 '</PP_MESH>', &
546 '<PP_LOCAL type="real" size="3">', &
547 '6.0 4.0 2.0', &
548 '</PP_LOCAL>', &
549 '<PP_NONLOCAL>', &
550 '<PP_BETA.1 type="real" size="3" index="1" angular_momentum="0">', &
551 '1.0 4.0 9.0', &
552 '</PP_BETA.1>', &
553 '<PP_BETA.2 type="real" size="3" index="2" angular_momentum="0">', &
554 '2.0 -1.0 3.0', &
555 '</PP_BETA.2>', &
556 '<PP_DIJ type="real" size="4">', &
557 '2.0 0.4 0.4 8.0', &
558 '</PP_DIJ>', &
559 '</PP_NONLOCAL>', &
560 '</UPF>'
561 CALL close_file(unit)
562 END IF
563 CALL logger%para_env%sync()
564 NULLIFY (specification, input)
565 CALL create_atom_section(specification)
566 CALL section_vals_create(input, specification)
567 potential_section => section_vals_get_subs_vals(input, 'POTENTIAL')
568 CALL section_vals_val_set(potential_section, 'PSEUDO_TYPE', i_val=upf_pseudo)
569 CALL section_vals_val_set(potential_section, 'POTENTIAL_FILE_NAME', c_val=fixture)
570 CALL init_atom_potential(atomic, potential_section, 2)
571 associate(potential => atomic%upf_pot)
572 IF (maxval(abs(potential%vlocal - [3.0_dp, 2.0_dp, 1.0_dp])) > 1.e-14_dp) THEN
573 error stop "UPF local potential is not in Hartree"
574 END IF
575 IF (maxval(abs(potential%beta(:, 1) - [2.0_dp, 4.0_dp, 6.0_dp])) > 1.e-14_dp) THEN
576 error stop "UPF changed the first tabulated projector amplitude"
577 END IF
578 IF (maxval(abs(potential%beta(:, 2) - [4.0_dp, -1.0_dp, 2.0_dp])) > 1.e-14_dp) THEN
579 error stop "UPF changed the second tabulated projector amplitude"
580 END IF
581 IF (maxval(abs(potential%dion - reshape([1.0_dp, 0.2_dp, 0.2_dp, 4.0_dp], [2, 2]))) > 1.e-14_dp) THEN
582 error stop "UPF D matrix is not in the tabulated-projector convention"
583 END IF
584 END associate
585 CALL release_atom_potential(atomic)
586 CALL section_vals_release(input)
587 CALL section_release(specification)
588 CALL logger%para_env%sync()
589 IF (logger%para_env%is_source()) THEN
590 CALL open_file(fixture, unit_number=unit, file_status="OLD")
591 CALL close_file(unit, file_status="DELETE")
592 END IF
593 END SUBROUTINE check_upf_units
594
595! **************************************************************************************************
596!> \brief Compare the converted atomic SGP operator with analytic Gaussian integrals.
597!> This checks that atomic guesses and the Quickstep Hamiltonian describe
598!> the same radial projectors and erf-regularized local Coulomb potential.
599! **************************************************************************************************
600 SUBROUTINE check_atomic_potential()
601 INTEGER :: l
602 REAL(KIND=dp) :: a, b, p, reference
603 TYPE(atom_basis_type) :: basis
604 TYPE(atom_integrals) :: integrals
605 TYPE(atom_potential_type) :: atomic
606 TYPE(sgp_potential_type), POINTER :: potential
607
608 NULLIFY (potential)
609 CALL allocate_potential(potential)
610 potential%zeff = 1.0_dp
611 potential%core_charge_radius = 0.4_dp
612 potential%alpha_core_charge = 0.5_dp/potential%core_charge_radius**2
613 potential%n_nonlocal = 1
614 potential%lmax = 2
615 potential%is_nonlocal(0:2) = .true.
616 potential%n_local = 1
617 ALLOCATE (potential%elec_conf(0:3), potential%a_nonlocal(1), &
618 potential%c_nonlocal(1, 1, 0:2), potential%h_nonlocal(1, 0:2), &
619 potential%a_local(1), potential%c_local(1))
620 potential%elec_conf = [1, 0, 0, 0]
621 potential%a_nonlocal = 0.7_dp
622 potential%c_nonlocal = 1.0_dp/sqrt(fourpi)
623 potential%h_nonlocal = 1.0_dp
624 potential%a_local = 1.2_dp
625 potential%c_local = 0.3_dp
626 atomic%ppot_type = sgp_pseudo
627 CALL sgp_potential_conversion(potential, atomic%sgp_pot)
628 CALL init_atom_basis_default_pp(basis)
629 CALL atom_ppint_setup(integrals, basis, atomic)
630 DO l = 0, 2
631 a = basis%am(8, l) + potential%a_nonlocal(1)
632 reference = (gamma(l + 1.5_dp)/(2.0_dp*a**(l + 1.5_dp)))**2
633 IF (abs(integrals%hnl(8, 8, l) - reference) > 1.e-9_dp*abs(reference)) THEN
634 error stop "Atomic SGP nonlocal operator differs from analytic Gaussian integrals"
635 END IF
636 END DO
637 p = 2.0_dp*basis%am(8, 0)
638 b = 1.0_dp/(sqrt(2.0_dp)*potential%core_charge_radius)
639 reference = -potential%zeff*b/(2.0_dp*p*sqrt(p + b*b)) + &
640 potential%c_local(1)*gamma(1.5_dp)/(2.0_dp*(p + potential%a_local(1))**1.5_dp)
641 IF (abs(integrals%core(8, 8, 0) - reference) > 1.e-9_dp*abs(reference)) THEN
642 error stop "Atomic SGP local operator differs from analytic Gaussian integrals"
643 END IF
644 CALL atom_ppint_release(integrals)
645 CALL release_atom_basis(basis)
646 CALL deallocate_potential(potential)
647 END SUBROUTINE check_atomic_potential
648
649! **************************************************************************************************
650!> \brief Verify the physical angular kernel of Gaussian UPF projectors through l=5.
651!> For beta_l(r) = r**l exp(-a*r**2), stripping off the radial exponentials
652!> at unit vectors leaves sum_m Y_lm(u) Y_lm(v) = (2*l+1) P_l(u.v)/(4*pi).
653!> The reference uses the Legendre recurrence, independently of the Cartesian
654!> to spherical transformation used by the production projector integrals.
655! **************************************************************************************************
656 SUBROUTINE check_projector_addition_theorem()
657 INTEGER, PARAMETER :: lmax = 5
658
659 INTEGER :: i, j, l, lx, ly, lz, nc, ns
660 REAL(KIND=dp) :: cross, diagonal, p(0:lmax), u(3), v(3), x
661 REAL(KIND=dp), ALLOCATABLE :: pu(:), pv(:)
662 TYPE(sgp_potential_type), POINTER :: potential
663
664 NULLIFY (potential)
665 CALL init_orbital_pointers(lmax)
666 CALL init_spherical_harmonics(lmax, -1)
667 CALL allocate_potential(potential)
668 potential%n_nonlocal = 1
669 potential%lmax = lmax
670 potential%nppnl = sum(nco(0:lmax))
671 ALLOCATE (potential%c_nonlocal(1, 1, 0:lmax), potential%h_nonlocal(1, 0:lmax))
672 ! atom_sgp stores the radial coefficients divided by sqrt(4*pi).
673 potential%c_nonlocal = 1.0_dp/sqrt(fourpi)
674 potential%h_nonlocal = 1.0_dp
675 CALL init_potential(potential)
676 u = [0.6_dp, 0.0_dp, 0.8_dp]
677 v = [0.3_dp, -0.4_dp, 0.5_dp]
678 v = v/norm2(v)
679 x = dot_product(u, v)
680 p(0) = 1.0_dp
681 p(1) = x
682 DO l = 2, lmax
683 p(l) = ((2*l - 1)*x*p(l - 1) - (l - 1)*p(l - 2))/l
684 END DO
685 nc = 0
686 ns = 0
687 DO l = 0, lmax
688 ALLOCATE (pu(nso(l)), pv(nso(l)))
689 pu = 0.0_dp
690 pv = 0.0_dp
691 DO lx = 0, l
692 DO ly = 0, l - lx
693 lz = l - lx - ly
694 i = nc + co(lx, ly, lz)
695 DO j = 1, nso(l)
696 pu(j) = pu(j) + potential%cprj_ppnl(i, ns + j)*u(1)**lx*u(2)**ly*u(3)**lz
697 pv(j) = pv(j) + potential%cprj_ppnl(i, ns + j)*v(1)**lx*v(2)**ly*v(3)**lz
698 END DO
699 END DO
700 END DO
701 diagonal = real(2*l + 1, dp)/fourpi
702 cross = diagonal*p(l)
703 IF (abs(dot_product(pu, pu) - diagonal) > 1.e-12_dp .OR. &
704 abs(dot_product(pv, pv) - diagonal) > 1.e-12_dp .OR. &
705 abs(dot_product(pu, pv) - cross) > 1.e-12_dp) THEN
706 error stop "SGP projector kernel violates the spherical-harmonic addition theorem"
707 END IF
708 nc = nc + nco(l)
709 ns = ns + nso(l)
710 DEALLOCATE (pu, pv)
711 END DO
712 CALL deallocate_potential(potential)
713 END SUBROUTINE check_projector_addition_theorem
714
715! **************************************************************************************************
716!> \brief Verify radial derivatives and the spherical Laplacian against finite differences.
717! **************************************************************************************************
718 SUBROUTINE check_core_derivatives()
719 REAL(kind=dp), PARAMETER :: h = 1.e-4_dp
720
721 REAL(kind=dp) :: deriv(4), lap(4), lap_fd(4), minus(4), &
722 plus(4), r(4), rho(4)
723 TYPE(atom_potential_type) :: potential
724
725 potential%ppot_type = sgp_pseudo
726 potential%sgp_pot%has_nlcc = .true.
727 potential%sgp_pot%n_nlcc = 2
728 potential%sgp_pot%a_nlcc(1:2) = [0.7_dp, 2.3_dp]
729 potential%sgp_pot%c_nlcc(1:2) = [1.8_dp, -0.2_dp]
730 r = [0.0_dp, 0.1_dp, 0.7_dp, 2.0_dp]
731 rho = 0.0_dp
732 plus = 0.0_dp
733 minus = 0.0_dp
734 deriv = 0.0_dp
735 lap = 0.0_dp
736 CALL atom_core_density(rho, potential, "RHO", r)
737 CALL atom_core_density(plus, potential, "RHO", r + h)
738 CALL atom_core_density(minus, potential, "RHO", r - h)
739 CALL atom_core_density(deriv, potential, "DER", r)
740 CALL atom_core_density(lap, potential, "LAP", r)
741 IF (maxval(abs(deriv - (plus - minus)/(2.0_dp*h))) > 1.e-7_dp) THEN
742 error stop "SGP core-density derivative differs from finite differences"
743 END IF
744 lap_fd = (plus - 2.0_dp*rho + minus)/h**2
745 lap_fd(1) = 3.0_dp*lap_fd(1)
746 lap_fd(2:) = lap_fd(2:) + (plus(2:) - minus(2:))/(h*r(2:))
747 IF (maxval(abs(lap - lap_fd)) > 1.e-6_dp) error stop "SGP core-density Laplacian differs from finite differences"
748 END SUBROUTINE check_core_derivatives
749
750! **************************************************************************************************
751!> \brief Check independent shell, primitive and set counts in file and inline atomic bases.
752! **************************************************************************************************
753 SUBROUTINE check_contracted_basis_reader()
754 INTEGER, PARAMETER :: contractions(3) = [11, 1, 1], lower_l(3) = [0, 1, 2], &
755 primitives(3) = [11, 41, 2], sets(3) = [1, 1, 21], upper_l(3) = [3, 6, 3]
756 CHARACTER(LEN=1600), ALLOCATABLE :: lines(:)
757 INTEGER :: b, c, i, j, l, mode, n, nc, np, ns, row, &
758 s, t, unit
759 REAL(dp) :: alpha, coefficient, expected, &
760 normalization
761 TYPE(atom_basis_type) :: basis
762 CHARACTER(LEN=*), PARAMETER :: fixture = "atom-contracted-basis-test"
763
764 TYPE(cp_logger_type), POINTER :: logger
765 TYPE(section_type), POINTER :: specification
766 TYPE(section_vals_type), POINTER :: input, pp_basis
767
768 logger => cp_get_default_logger()
769 DO b = 1, SIZE(sets)
770 np = primitives(b)
771 nc = contractions(b)
772 ns = sets(b)
773 ALLOCATE (lines(1 + ns*(np + 1)))
774 WRITE (lines(1), '(I0)') ns
775 row = 1
776 DO s = 1, ns
777 row = row + 1
778 WRITE (lines(row), '(*(I0,1X))') 1, lower_l(b), upper_l(b), np, (nc, l=lower_l(b), upper_l(b))
779 DO i = 1, np
780 row = row + 1
781 alpha = real(10*s + i, dp)/20.0_dp
782 WRITE (lines(row), '(*(F12.6,1X))') alpha, &
783 ((real(100*s + 10*i + c + 5*l, dp)/1000.0_dp, c=1, nc), l=lower_l(b), upper_l(b))
784 END DO
785 END DO
786 IF (logger%para_env%is_source()) THEN
787 OPEN (newunit=unit, file=fixture, status="REPLACE", action="WRITE")
788 WRITE (unit, '(A)') 'H READER-TEST', (trim(lines(i)), i=1, SIZE(lines))
789 CLOSE (unit)
790 END IF
791 CALL logger%para_env%sync()
792 DO mode = 1, 2
793 NULLIFY (specification, input)
794 CALL create_atom_section(specification)
795 CALL section_vals_create(input, specification)
796 pp_basis => section_vals_get_subs_vals(input, 'PP_BASIS')
797 CALL section_vals_val_set(pp_basis, 'BASIS_TYPE', i_val=contracted_gto)
798 CALL section_vals_val_set(pp_basis, 'GRID_POINTS', i_val=32)
799 CALL section_vals_val_set(pp_basis, 'BASIS_SET', c_val='READER-TEST')
800 CALL section_vals_val_set(pp_basis, 'BASIS_SET_FILE_NAME', c_val=fixture)
801 IF (mode == 2) THEN
802 DO i = 1, SIZE(lines)
803 CALL section_vals_val_set(pp_basis, 'BASIS%_DEFAULT_KEYWORD_', i_rep_val=i, c_val=trim(lines(i)))
804 END DO
805 END IF
806 CALL init_atom_basis(basis, pp_basis, 1, 'PP')
807 DO l = 0, ubound(basis%nbas, 1)
808 n = 0
809 IF (l >= lower_l(b) .AND. l <= upper_l(b)) n = ns
810 IF (basis%nprim(l) /= n*np .OR. basis%nbas(l) /= n*nc) THEN
811 error stop "Incorrect atomic contracted basis dimensions"
812 END IF
813 DO s = 1, n
814 DO i = 1, np
815 alpha = real(10*s + i, dp)/20.0_dp
816 j = (s - 1)*np + i
817 IF (abs(basis%am(j, l) - alpha) > 1.e-14_dp) error stop "Incorrect contracted basis exponent"
818 ! Inverse square root of the analytic radial Gaussian norm.
819 normalization = sqrt(2.0_dp*(2.0_dp*alpha)**(l + 1.5_dp)/gamma(l + 1.5_dp))
820 DO t = 1, n
821 DO c = 1, nc
822 coefficient = 0.0_dp
823 IF (s == t) coefficient = real(100*s + 10*i + c + 5*l, dp)/1000.0_dp
824 expected = normalization*coefficient
825 IF (abs(basis%cm(j, (t - 1)*nc + c, l) - expected) > 1.e-12_dp*max(1.0_dp, abs(expected))) THEN
826 error stop "Incorrect contracted basis coefficient or normalization"
827 END IF
828 END DO
829 END DO
830 END DO
831 END DO
832 END DO
833 CALL release_atom_basis(basis)
834 CALL section_vals_release(input)
835 CALL section_release(specification)
836 END DO
837 CALL logger%para_env%sync()
838 IF (logger%para_env%is_source()) THEN
839 OPEN (newunit=unit, file=fixture, status="OLD")
840 CLOSE (unit, status="DELETE")
841 END IF
842 DEALLOCATE (lines)
843 END DO
844 END SUBROUTINE check_contracted_basis_reader
845
846! **************************************************************************************************
847!> \brief Verify exported orbitals use the best basis restored after Powell optimization.
848! **************************************************************************************************
849 SUBROUTINE check_basis_optimization_export()
850 CHARACTER(LEN=160) :: line
851 INTEGER :: i, j, status, unit
852 REAL(dp) :: alpha(2), coefficient(2), norm
853 REAL(dp), POINTER :: exponents(:)
854 TYPE(cp_logger_type), POINTER :: logger
855 TYPE(section_type), POINTER :: specification
856 TYPE(section_vals_type), POINTER :: input
857
858 NULLIFY (specification, input)
859 CALL create_atom_section(specification)
860 CALL section_vals_create(input, specification)
861 CALL section_vals_val_set(input, 'ELEMENT', c_val='He')
862 CALL section_vals_val_set(input, 'ELECTRON_CONFIGURATION', c_val='1s2')
863 CALL section_vals_val_set(input, 'MAX_ANGULAR_MOMENTUM', i_val=0)
864 CALL section_vals_val_set(input, 'AE_BASIS%NUM_GTO', i_val=2)
865 ALLOCATE (exponents(2))
866 exponents = [2.0_dp, 0.4_dp]
867 CALL section_vals_val_set(input, 'AE_BASIS%S_EXPONENTS', r_vals_ptr=exponents)
868 CALL section_vals_val_set(input, 'METHOD%METHOD_TYPE', i_val=do_rhf_atom)
869 CALL section_vals_val_set(input, 'OPTIMIZATION%EPS_SCF', r_val=1.e-10_dp)
870 CALL section_vals_val_set(input, 'OPTIMIZATION%N_DIIS', i_val=8)
871 CALL section_vals_val_set(input, 'OPTIMIZATION%MAX_ITER', i_val=100)
872 CALL section_vals_val_set(input, 'POWELL%MAX_FUN', i_val=5)
873 CALL section_vals_val_set(input, 'POWELL%STEP_SIZE', r_val=0.15_dp)
874 CALL section_vals_val_set(input, 'POWELL%ACCURACY', r_val=1.e-5_dp)
875 CALL section_vals_val_set(input, 'PRINT%FIT_BASIS%_SECTION_PARAMETERS_', i_val=silent_print_level)
876 CALL atom_basis_opt(input)
877 CALL section_vals_release(input)
878 CALL section_release(specification)
879
880 logger => cp_get_default_logger()
881 CALL logger%para_env%sync()
882 OPEN (newunit=unit, file='OPT_BASIS', status='OLD', action='READ')
883 DO
884 READ (unit, '(A)', iostat=status) line
885 IF (status /= 0) error stop 'Missing optimized basis orbital coefficients'
886 IF (index(line, 'L Quantum Number:') > 0) EXIT
887 END DO
888 DO i = 1, 2
889 READ (unit, *) alpha(i), coefficient(i)
890 END DO
891 CLOSE (unit)
892 IF (alpha(1) <= 2.0_dp) error stop 'Optimization did not restore the earlier best exponent'
893 norm = 0.0_dp
894 DO i = 1, 2
895 DO j = 1, 2
896 norm = norm + coefficient(i)*coefficient(j)* &
897 (2.0_dp*sqrt(alpha(i)*alpha(j))/(alpha(i) + alpha(j)))**1.5_dp
898 END DO
899 END DO
900 ! The export rounds its coefficients to eight decimal places.
901 IF (.NOT. ieee_is_finite(norm) .OR. abs(norm - 1.0_dp) > 1.e-7_dp) THEN
902 error stop 'Exported orbital is inconsistent with the optimized basis'
903 END IF
904 CALL logger%para_env%sync()
905 IF (logger%para_env%is_source()) THEN
906 OPEN (newunit=unit, file='OPT_BASIS', status='OLD')
907 CLOSE (unit, status='DELETE')
908 END IF
909 END SUBROUTINE check_basis_optimization_export
910
911END PROGRAM atom_upf_unittest
subroutine check_uspp_import()
...
program atom_upf_unittest
subroutine, public atom_basis_opt(atom_section)
Optimize the atomic basis set.
Definition atom_basis.F:53
calculate the orbitals for a given atomic kind type
subroutine, public sgp_potential_conversion(sgp_potential, sgp_atompot)
...
Calculate the atomic operator matrices.
subroutine, public atom_ppint_release(integrals)
Release memory allocated for atomic integrals (core electrons).
subroutine, public atom_ppint_setup(integrals, basis, potential)
...
subroutine, public atom_sgp_release(sgp_pot)
...
Definition atom_sgp.F:801
subroutine, public sgp_construction(sgp_pot, ecp_pot, upf_pot, orb_basis, error)
...
Definition atom_sgp.F:79
subroutine, public fit_core_density_gaussians(r, rab, rho, alpha, coeff)
Fit a tabulated core density without forming ill-conditioned normal equations. Column-normalized,...
Definition atom_sgp.F:749
Define the atom type and its sub types.
Definition atom_types.F:15
integer, parameter, public cgto_basis
Definition atom_types.F:70
subroutine, public release_atom_potential(potential)
...
subroutine, public init_atom_basis(basis, basis_section, zval, btyp)
Initialize the basis for the atomic code.
Definition atom_types.F:384
subroutine, public init_atom_potential(potential, potential_section, zval)
...
subroutine, public release_atom_basis(basis)
...
Definition atom_types.F:934
subroutine, public init_atom_basis_default_pp(basis)
...
Definition atom_types.F:723
subroutine, public atom_basis_gridrep(basis, gbasis, r, rab)
...
Definition atom_types.F:800
Routines that process Quantum Espresso UPF files.
Definition atom_upf.F:14
pure subroutine, public atom_release_upf(upfpot)
...
Definition atom_upf.F:1191
subroutine, public atom_read_upf(pot, upf_filename, read_header, read_augmentation)
...
Definition atom_upf.F:52
Some basic routines for atomic calculations.
Definition atom_utils.F:15
subroutine, public atom_core_density(corden, potential, typ, rr)
...
Definition atom_utils.F:689
subroutine, public atom_density(density, pmat, basis, maxl, typ, rr)
Map the electron density on an atomic radial grid.
Definition atom_utils.F:365
Utility routines to open and close files.
Definition cp_files.F:22
subroutine, public open_file(file_name, unit_number, file_status, file_form, file_action, file_position, file_pad, file_access, debug)
Opens a file and returns its logical unit number.
Definition cp_files.F:196
subroutine, public close_file(unit_number, file_status)
Closes an open file given by its logical unit number.
Definition cp_files.F:63
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
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 silent_print_level
Definition of the atomic potential types.
Calculation of the incomplete Gamma function F_n(t) for multi-center integrals over Cartesian Gaussia...
Definition gamma.F:15
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_rhf_atom
integer, parameter, public do_gapw_gct
integer, parameter, public contracted_gto
integer, parameter, public do_gapw_log
builds the input structure for the ATOM module
subroutine, public create_atom_section(section)
Creates the input section for the atom code.
objects that represent the structure of input sections and the data contained in an input section
recursive subroutine, public section_vals_create(section_vals, section)
creates a object where to store the values of a 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
recursive subroutine, public section_release(section)
releases the given keyword list (see doc/ReferenceCounting.html)
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_path_length
Definition kinds.F:58
CP2K C/C++ interface.
Definition libcp2k.F:20
subroutine, public cp2k_finalize()
...
Definition libcp2k.F:139
subroutine, public cp2k_init()
...
Definition libcp2k.F:104
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public fourpi
Provides Cartesian and spherical orbital pointers and indices.
subroutine, public init_orbital_pointers(maxl)
Initialize or update the orbital pointers.
integer, dimension(:, :, :), allocatable, public co
integer, dimension(:), allocatable, public nco
integer, dimension(:), allocatable, public nso
Calculation of the spherical harmonics and the corresponding orbital transformation matrices.
subroutine, public init_spherical_harmonics(maxl, output_unit)
Initialize or update the orbital transformation matrices.
subroutine, public deallocate_grid_atom(grid_atom)
Deallocate a Gaussian-type orbital (GTO) basis set data set.
subroutine, public allocate_grid_atom(grid_atom)
Initialize components of the grid_atom_type structure.
subroutine, public create_grid_atom(grid_atom, nr, na, llmax, ll, quadrature)
...
Owned UPF dataset and radial conventions shared by ATOM and Quickstep. Dataset availability does not ...
Definition upf_types.F:12
pure logical function, public upf_has_complete_partial_waves(pot)
Check for a complete projector-indexed pair of original AE and PS waves.
Definition upf_types.F:124
Provides all information about a basis set.
Definition atom_types.F:79
type of a logger, at the moment it contains just a print level starting at which level it should be l...
represent a section of the input file