(git:73bd903)
Loading...
Searching...
No Matches
eri_mme_gaussian.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! **************************************************************************************************
9!> \brief Methods related to properties of Hermite and Cartesian Gaussian functions.
10!> \par History
11!> 2015 09 created
12!> \author Patrick Seewald
13! **************************************************************************************************
14
16 USE kinds, ONLY: dp
17 USE mathconstants, ONLY: gamma1
19#include "../base/base_uses.f90"
20
21 IMPLICIT NONE
22
23 PRIVATE
24
25 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .false.
26
27 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'eri_mme_gaussian'
28
29 INTEGER, PARAMETER, PUBLIC :: eri_mme_coulomb = 1, &
30 eri_mme_yukawa = 2, &
32
33 PUBLIC :: &
38
39CONTAINS
40
41! **************************************************************************************************
42!> \brief Create matrix to transform between cartesian and hermite gaussian
43!> basis functions.
44!> \param zet exponent
45!> \param l_max ...
46!> \param h_to_c transformation matrix with dimensions (0:l_max, 0:l_max)
47!> \note is idempotent, so transformation is the same
48!> in both directions.
49! **************************************************************************************************
50 PURE SUBROUTINE create_hermite_to_cartesian(zet, l_max, h_to_c)
51 REAL(kind=dp), INTENT(IN) :: zet
52 INTEGER, INTENT(IN) :: l_max
53 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
54 INTENT(OUT) :: h_to_c
55
56 INTEGER :: k, l
57
58 ALLOCATE (h_to_c(-1:l_max + 1, 0:l_max))
59 h_to_c(:, :) = 0.0_dp
60 h_to_c(0, 0) = 1.0_dp
61 DO l = 0, l_max - 1
62 DO k = 0, l + 1
63 h_to_c(k, l + 1) = -(k + 1)*h_to_c(k + 1, l) + 2.0_dp*zet*h_to_c(k - 1, l)
64 END DO
65 END DO
66
67 END SUBROUTINE create_hermite_to_cartesian
68
69! **************************************************************************************************
70!> \brief Norm of 1d Hermite-Gauss functions
71!> \param zet ...
72!> \param l ...
73!> \return ...
74! **************************************************************************************************
75 PURE FUNCTION hermite_gauss_norm(zet, l) RESULT(norm)
76 REAL(kind=dp), INTENT(IN) :: zet
77 INTEGER, DIMENSION(3), INTENT(IN) :: l
78 REAL(kind=dp) :: norm
79
80 norm = 1.0_dp/sqrt((2.0_dp*zet)**(sum(l) - 1.5_dp)*(gamma1(l(1))*gamma1(l(2))*gamma1(l(3))))
81
82 END FUNCTION hermite_gauss_norm
83
84! **************************************************************************************************
85!> \brief Get minimax coefficient a_i and w_i for approximating
86!> 1/G^2 by sum_i w_i exp(-a_i G^2)
87!> \param n_minimax Number of minimax terms
88!> \param cutoff Plane Wave cutoff
89!> \param G_min Minimum absolute value of G
90!> \param minimax_aw Minimax coefficients a_i, w_i
91!> \param potential potential to use. Accepts the following values:
92!> 1: coulomb potential V(r)=1/r
93!> 2: yukawa potential V(r)=e(-a*r)/r
94!> 3: long-range coulomb erf(a*r)/r
95!> \param pot_par potential parameter a for yukawa V(r)=e(-a*r)/r or long-range coulomb V(r)=erf(a*r)/r
96!> \param err_minimax Maximum error MAX (|1/G^2-\sum_i w_i exp(-a_i G^2)|)
97! **************************************************************************************************
98 SUBROUTINE get_minimax_coeff_v_gspace(n_minimax, cutoff, G_min, minimax_aw, potential, pot_par, err_minimax)
99 INTEGER, INTENT(IN) :: n_minimax
100 REAL(kind=dp), INTENT(IN) :: cutoff, g_min
101 REAL(kind=dp), DIMENSION(:), INTENT(OUT) :: minimax_aw
102 INTEGER, INTENT(IN), OPTIONAL :: potential
103 REAL(kind=dp), INTENT(IN), OPTIONAL :: pot_par
104 REAL(kind=dp), INTENT(OUT), OPTIONAL :: err_minimax
105
106 INTEGER :: potential_prv
107 REAL(kind=dp) :: g_max, minimax_rc
108 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: a, w
109
110 IF (PRESENT(potential)) THEN
111 potential_prv = potential
112 ELSE
113 potential_prv = eri_mme_coulomb
114 END IF
115
116 IF (potential_prv > 3) THEN
117 cpabort("unknown potential")
118 END IF
119
120 IF ((potential_prv >= 2) .AND. .NOT. PRESENT(pot_par)) THEN
121 cpabort("potential parameter pot_par required for yukawa or long-range Coulomb")
122 END IF
123
124 ! Note: G_c = SQRT(2*cutoff) cutoff in 1 cartesian direction
125 ! G_max = SQRT(3*G_c**2) maximum absolute value of G vector
126 ! Minimax approx. needs to be valid in range [G_min, G_max]
127
128 ! 1) compute minimax coefficients
129
130 g_max = sqrt(3.0_dp*2.0_dp*cutoff)
131 cpassert(g_max > g_min)
132 IF (potential_prv == eri_mme_coulomb .OR. potential_prv == eri_mme_longrange) THEN
133 minimax_rc = (g_max/g_min)**2
134 ELSE IF (potential_prv == eri_mme_yukawa) THEN
135 minimax_rc = (g_max**2 + pot_par**2)/(g_min**2 + pot_par**2)
136 END IF
137
138 CALL get_exp_minimax_coeff(n_minimax, minimax_rc, minimax_aw, err_minimax)
139
140 ALLOCATE (a(n_minimax)); ALLOCATE (w(n_minimax))
141 a(:) = minimax_aw(:n_minimax)
142 w(:) = minimax_aw(n_minimax + 1:)
143 SELECT CASE (potential_prv)
144 ! Scale minimax coefficients to incorporate different Fourier transforms
145 CASE (eri_mme_coulomb)
146 ! FT = 1/G**2
147 a(:) = a/g_min**2
148 w(:) = w/g_min**2
149 CASE (eri_mme_yukawa)
150 ! FT = 1/(G**2 + pot_par**2)
151 w(:) = w*exp((-a*pot_par**2)/(g_min**2 + pot_par**2))/(g_min**2 + pot_par**2)
152 a(:) = a/(g_min**2 + pot_par**2)
153 CASE (eri_mme_longrange)
154 ! FT = exp(-(G/pot_par)**2)/G**2
155 ! approximating 1/G**2 as for Coulomb:
156 a(:) = a/g_min**2
157 w(:) = w/g_min**2
158 ! incorporate exponential factor:
159 a(:) = a + 1.0_dp/pot_par**2
160 END SELECT
161 minimax_aw = [a(:), w(:)]
162
163 IF (PRESENT(err_minimax)) THEN
164 IF (potential_prv == eri_mme_coulomb) THEN
165 err_minimax = err_minimax/g_min**2
166 ELSE IF (potential_prv == eri_mme_yukawa) THEN
167 err_minimax = err_minimax/(g_min**2 + pot_par**2)
168 ELSE IF (potential_prv == eri_mme_longrange) THEN
169 err_minimax = err_minimax/g_min**2 ! approx. of Coulomb
170 err_minimax = err_minimax*exp(-g_min**2/pot_par**2) ! exponential factor
171 END IF
172 END IF
173
174 END SUBROUTINE get_minimax_coeff_v_gspace
175
176! **************************************************************************************************
177!> \brief Expand 1d product of cartesian (or hermite) gaussians into single hermite gaussians:
178!> Find E_t^{lm} s.t.
179!> F(l, a, r-R1) * F(m, b, r-R2) = sum_{t=0}^{l+m} E_t^{lm} H(t, p, r-R_P)
180!> with p = a + b, R_P = (a*R1 + b*R2)/p. The function F can be either Cartesian
181!> Gaussian or Hermite Gaussian.
182!> \param l ...
183!> \param m ...
184!> \param a ...
185!> \param b ...
186!> \param R1 ...
187!> \param R2 ...
188!> \param H_or_C_product 1: cartesian product, 2: hermite product
189!> \param E ...
190! **************************************************************************************************
191 PURE SUBROUTINE create_gaussian_overlap_dist_to_hermite(l, m, a, b, R1, R2, H_or_C_product, E)
192 INTEGER, INTENT(IN) :: l, m
193 REAL(kind=dp), INTENT(IN) :: a, b, r1, r2
194 INTEGER, INTENT(IN) :: h_or_c_product
195 REAL(kind=dp), DIMENSION(-1:l+m+1, -1:l, -1:m), &
196 INTENT(OUT) :: e
197
198 INTEGER :: ll, mm, t
199 REAL(kind=dp) :: c1, c2, c3
200
201 e(:, :, :) = 0.0_dp
202 e(0, 0, 0) = exp(-a*b/(a + b)*(r1 - r2)**2) ! cost: exp_w flops
203
204 c1 = 0.5_dp/(a + b)
205 c2 = (b/(a + b))*(r2 - r1)
206 c3 = (a/(a + b))*(r1 - r2)
207
208 IF (h_or_c_product == 1) THEN ! Cartesian overlap dist
209 DO mm = 0, m
210 DO ll = 0, l
211 DO t = 0, ll + mm + 1
212 IF (ll < l) THEN
213 e(t, ll + 1, mm) = c1*e(t - 1, ll, mm) + & ! cost: 8 flops
214 c2*e(t, ll, mm) + &
215 (t + 1)*e(t + 1, ll, mm)
216 END IF
217 IF (mm < m) THEN
218 e(t, ll, mm + 1) = c1*e(t - 1, ll, mm) + & ! cost: 8 flops
219 c3*e(t, ll, mm) + &
220 (t + 1)*e(t + 1, ll, mm)
221 END IF
222 END DO
223 END DO
224 END DO
225 ELSE ! Hermite overlap dist
226 DO mm = 0, m
227 DO ll = 0, l
228 DO t = 0, ll + mm + 1
229 IF (ll < l) THEN
230 e(t, ll + 1, mm) = a*(2*c1*e(t - 1, ll, mm) + & ! cost: 16 flops
231 2*c2*e(t, ll, mm) + &
232 2*(t + 1)*e(t + 1, ll, mm) - &
233 2*ll*e(t, ll - 1, mm))
234 END IF
235 IF (mm < m) THEN
236 e(t, ll, mm + 1) = b*(2*c1*e(t - 1, ll, mm) + & ! cost: 16 flops
237 2*c3*e(t, ll, mm) + &
238 2*(t + 1)*e(t + 1, ll, mm) - &
239 2*mm*e(t, ll, mm - 1))
240
241 END IF
242 END DO
243 END DO
244 END DO
245 END IF
246
248END MODULE eri_mme_gaussian
Methods related to properties of Hermite and Cartesian Gaussian functions.
pure real(kind=dp) function, public hermite_gauss_norm(zet, l)
Norm of 1d Hermite-Gauss functions.
pure subroutine, public create_hermite_to_cartesian(zet, l_max, h_to_c)
Create matrix to transform between cartesian and hermite gaussian basis functions.
integer, parameter, public eri_mme_longrange
integer, parameter, public eri_mme_coulomb
subroutine, public get_minimax_coeff_v_gspace(n_minimax, cutoff, g_min, minimax_aw, potential, pot_par, err_minimax)
Get minimax coefficient a_i and w_i for approximating 1/G^2 by sum_i w_i exp(-a_i G^2).
pure subroutine, public create_gaussian_overlap_dist_to_hermite(l, m, a, b, r1, r2, h_or_c_product, e)
Expand 1d product of cartesian (or hermite) gaussians into single hermite gaussians: Find E_t^{lm}...
integer, parameter, public eri_mme_yukawa
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of mathematical constants and functions.
real(kind=dp), dimension(0:maxfac), parameter, public gamma1
Routines to calculate the minimax coefficients in order to approximate 1/x as a sum over exponential ...
Definition minimax_exp.F:29
subroutine, public get_exp_minimax_coeff(k, rc, aw, mm_error, which_coeffs)
Get best minimax approximation for given input parameters. Automatically chooses the most exact set o...