Line data Source code
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 : ! **************************************************************************************************
9 : !> \brief Owned UPF dataset and radial conventions shared by ATOM and Quickstep.
10 : !> Dataset availability does not select an orbital representation or calculation method.
11 : ! **************************************************************************************************
12 : MODULE upf_types
13 : USE kinds, ONLY: default_path_length,&
14 : default_string_length,&
15 : dp
16 : #include "../base/base_uses.f90"
17 :
18 : IMPLICIT NONE
19 : PRIVATE
20 :
21 : ! use same value as in atom_types!
22 : INTEGER, PARAMETER :: lmat = 3
23 :
24 : TYPE upf_partial_waves_type
25 : ! Original r*phi(r), one AE/PS pair per beta projector; not the atomic guesses.
26 : REAL(dp), ALLOCATABLE :: ae_wfc(:, :), ps_wfc(:, :)
27 : INTEGER, ALLOCATABLE :: angular_momenta(:)
28 : END TYPE upf_partial_waves_type
29 :
30 : TYPE atom_upfpot_type
31 : CHARACTER(LEN=2) :: symbol = ""
32 : CHARACTER(LEN=default_string_length) :: pname = ""
33 : INTEGER, DIMENSION(0:lmat) :: econf = 0
34 : REAL(dp) :: zion = 0.0_dp
35 : CHARACTER(LEN=default_string_length) :: version = ""
36 : CHARACTER(LEN=default_path_length) :: filename = ""
37 : ! <INFO>
38 : INTEGER :: maxinfo = 100
39 : CHARACTER(LEN=default_string_length), DIMENSION(100) &
40 : :: info = ""
41 : ! <HEADER>
42 : CHARACTER(LEN=default_string_length) :: generated = ""
43 : CHARACTER(LEN=default_string_length) :: author = ""
44 : CHARACTER(LEN=default_string_length) :: date = ""
45 : CHARACTER(LEN=default_string_length) :: comment = ""
46 : CHARACTER(LEN=4) :: pseudo_type = ""
47 : CHARACTER(LEN=15) :: relativistic = ""
48 : CHARACTER(LEN=default_string_length) :: functional = ""
49 : LOGICAL :: is_ultrasoft = .FALSE.
50 : LOGICAL :: is_paw = .FALSE.
51 : LOGICAL :: is_coulomb = .FALSE.
52 : LOGICAL :: has_so = .FALSE.
53 : LOGICAL :: has_wfc = .FALSE.
54 : LOGICAL :: has_gipaw = .FALSE.
55 : LOGICAL :: paw_as_gipaw = .FALSE.
56 : LOGICAL :: core_correction = .FALSE.
57 : REAL(dp) :: total_psenergy = 0.0_dp
58 : REAL(dp) :: wfc_cutoff = 0.0_dp
59 : REAL(dp) :: rho_cutoff = 0.0_dp
60 : INTEGER :: l_max = -100
61 : INTEGER :: l_max_rho = -1
62 : INTEGER :: l_local = -1
63 : INTEGER :: mesh_size = -1
64 : INTEGER :: number_of_wfc = -1
65 : INTEGER :: number_of_proj = -1
66 : ! <MESH>
67 : REAL(dp) :: dx = 0.0_dp
68 : REAL(dp) :: xmin = 0.0_dp
69 : REAL(dp) :: rmax = 0.0_dp
70 : REAL(dp) :: zmesh = 0.0_dp
71 : REAL(dp), DIMENSION(:), ALLOCATABLE :: r, rab
72 : ! <NLCC>
73 : REAL(dp), DIMENSION(:), ALLOCATABLE :: rho_nlcc
74 : ! <LOCAL>
75 : REAL(dp), DIMENSION(:), ALLOCATABLE :: vlocal
76 : ! <NONLOCAL>: keep the tabulated projector amplitude; D includes Ry -> Hartree.
77 : ! beta stores beta(r), with the radial prefactor in PP_BETA removed.
78 : REAL(dp), DIMENSION(:, :), ALLOCATABLE :: dion
79 : REAL(dp), DIMENSION(:, :), ALLOCATABLE :: beta
80 : INTEGER, DIMENSION(:), ALLOCATABLE :: lbeta
81 : ! <AUGMENTATION>: PP_Q and r**2*Q_ij^L(r), in the original beta convention.
82 : ! The pair index is j*(j-1)/2+i for i<=j; the last dimension starts at L=0.
83 : REAL(dp), DIMENSION(:, :), ALLOCATABLE :: qij
84 : REAL(dp), DIMENSION(:, :, :), ALLOCATABLE :: qijl
85 : TYPE(upf_partial_waves_type), ALLOCATABLE :: partial_waves
86 : ! <SEMILOCAL>
87 : REAL(dp), DIMENSION(:, :), ALLOCATABLE :: vsemi
88 : END TYPE atom_upfpot_type
89 :
90 : PUBLIC :: atom_upfpot_type, upf_partial_waves_type, upf_radial_weights
91 : PUBLIC :: upf_release, upf_has_complete_partial_waves
92 : CONTAINS
93 :
94 : ! **************************************************************************************************
95 : !> \brief Composite Simpson weights for dr on the supplied UPF mesh index.
96 : !> \param pot Original radial coordinates and dr/d(index).
97 : !> \return Radial weights, with a last trapezoidal interval for an even mesh size.
98 : ! **************************************************************************************************
99 0 : FUNCTION upf_radial_weights(pot) RESULT(weights)
100 : TYPE(atom_upfpot_type), INTENT(IN) :: pot
101 : REAL(dp) :: weights(SIZE(pot%r))
102 :
103 : INTEGER :: n, ns
104 :
105 0 : n = SIZE(pot%r)
106 0 : CPASSERT(n >= 3 .AND. SIZE(pot%rab) == n)
107 0 : CPASSERT(ALL(pot%r(2:) > pot%r(:n - 1)) .AND. ALL(pot%rab > 0.0_dp))
108 0 : ns = n - 1 + MODULO(n, 2)
109 0 : weights = 0.0_dp
110 0 : weights(1:ns:2) = 2.0_dp/3.0_dp
111 0 : weights(2:ns - 1:2) = 4.0_dp/3.0_dp
112 0 : weights(1) = 1.0_dp/3.0_dp
113 0 : weights(ns) = 1.0_dp/3.0_dp
114 0 : IF (ns < n) weights(n - 1:n) = weights(n - 1:n) + 0.5_dp
115 0 : weights(:) = weights*pot%rab
116 0 : END FUNCTION upf_radial_weights
117 :
118 : ! **************************************************************************************************
119 : !> \brief Check for a complete projector-indexed pair of original AE and PS waves.
120 : !> \param pot Original UPF dataset; atomic guess waves do not satisfy this query.
121 : !> \return Whether every beta projector has a compatible full-wave pair.
122 : ! **************************************************************************************************
123 6 : PURE FUNCTION upf_has_complete_partial_waves(pot) RESULT(complete)
124 : TYPE(atom_upfpot_type), INTENT(IN) :: pot
125 : LOGICAL :: complete
126 :
127 : INTEGER :: n, nb
128 :
129 6 : complete = .FALSE.
130 6 : IF (.NOT. ALLOCATED(pot%partial_waves)) RETURN
131 4 : IF (.NOT. ALLOCATED(pot%lbeta)) RETURN
132 4 : IF (.NOT. ALLOCATED(pot%r) .OR. .NOT. ALLOCATED(pot%rab)) RETURN
133 4 : n = pot%mesh_size
134 4 : nb = pot%number_of_proj
135 4 : IF (n < 3 .OR. nb < 1 .OR. SIZE(pot%lbeta) /= nb) RETURN
136 4 : IF (SIZE(pot%r) /= n .OR. SIZE(pot%rab) /= n) RETURN
137 : ASSOCIATE (waves => pot%partial_waves)
138 4 : IF (.NOT. ALLOCATED(waves%ae_wfc) .OR. .NOT. ALLOCATED(waves%ps_wfc)) RETURN
139 2 : IF (.NOT. ALLOCATED(waves%angular_momenta)) RETURN
140 6 : IF (ANY(SHAPE(waves%ae_wfc) /= [n, nb])) RETURN
141 6 : IF (ANY(SHAPE(waves%ps_wfc) /= [n, nb])) RETURN
142 2 : IF (SIZE(waves%angular_momenta) /= nb) RETURN
143 10 : complete = ALL(waves%angular_momenta == pot%lbeta)
144 : END ASSOCIATE
145 : END FUNCTION upf_has_complete_partial_waves
146 :
147 : ! **************************************************************************************************
148 : !> \brief Release every owned field and reset metadata before reusing a dataset.
149 : !> \param pot Owned UPF dataset.
150 : ! **************************************************************************************************
151 11760 : PURE SUBROUTINE upf_release(pot)
152 : TYPE(atom_upfpot_type), INTENT(INOUT) :: pot
153 :
154 1234800 : pot = atom_upfpot_type()
155 11760 : END SUBROUTINE upf_release
156 0 : END MODULE upf_types
|