(git:744416f)
Loading...
Searching...
No Matches
cp_ddapc_methods.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 contains information regarding the decoupling/recoupling method of Bloechl
10!> \author Teodoro Laino
11! **************************************************************************************************
13 USE cell_types, ONLY: cell_type
20 USE kahan_sum, ONLY: accurate_sum
21 USE kinds, ONLY: dp
22 USE mathconstants, ONLY: fourpi,&
23 oorootpi,&
24 pi,&
25 twopi
26 USE mathlib, ONLY: diamat_all,&
31 USE pw_types, ONLY: pw_c1d_gs_type,&
34#include "./base/base_uses.f90"
35
36 IMPLICIT NONE
37 PRIVATE
38 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .false.
39 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp_ddapc_methods'
40 PUBLIC :: ddapc_eval_gfunc, &
50
51CONTAINS
52
53! **************************************************************************************************
54!> \brief ...
55!> \param gfunc ...
56!> \param w ...
57!> \param gcut ...
58!> \param rho_tot_g ...
59!> \param radii ...
60! **************************************************************************************************
61 SUBROUTINE ddapc_eval_gfunc(gfunc, w, gcut, rho_tot_g, radii)
62 REAL(kind=dp), DIMENSION(:, :), POINTER :: gfunc
63 REAL(kind=dp), DIMENSION(:), POINTER :: w
64 REAL(kind=dp), INTENT(IN) :: gcut
65 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
66 REAL(kind=dp), DIMENSION(:), POINTER :: radii
67
68 CHARACTER(len=*), PARAMETER :: routinen = 'ddapc_eval_gfunc'
69
70 INTEGER :: e_dim, handle, ig, igauss, s_dim
71 REAL(kind=dp) :: g2, gcut2, rc, rc2
72
73 CALL timeset(routinen, handle)
74 gcut2 = gcut*gcut
75 !
76 s_dim = rho_tot_g%pw_grid%first_gne0
77 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
78 ALLOCATE (gfunc(s_dim:e_dim, SIZE(radii)))
79 ALLOCATE (w(s_dim:e_dim))
80 gfunc = 0.0_dp
81 w = 0.0_dp
82 DO igauss = 1, SIZE(radii)
83 rc = radii(igauss)
84 rc2 = rc*rc
85 DO ig = s_dim, e_dim
86 g2 = rho_tot_g%pw_grid%gsq(ig)
87 IF (g2 > gcut2) EXIT
88 gfunc(ig, igauss) = exp(-g2*rc2/4.0_dp)
89 END DO
90 END DO
91 DO ig = s_dim, e_dim
92 g2 = rho_tot_g%pw_grid%gsq(ig)
93 IF (g2 > gcut2) EXIT
94 w(ig) = fourpi*(g2 - gcut2)**2/(g2*gcut2)
95 END DO
96 CALL timestop(handle)
97 END SUBROUTINE ddapc_eval_gfunc
98
99! **************************************************************************************************
100!> \brief Computes the B vector for the solution of the linear system
101!> \param bv ...
102!> \param gfunc ...
103!> \param w ...
104!> \param particle_set ...
105!> \param radii ...
106!> \param rho_tot_g ...
107!> \param gcut ...
108!> \par History
109!> 08.2005 created [tlaino]
110!> \author Teodoro Laino
111! **************************************************************************************************
112 SUBROUTINE build_b_vector(bv, gfunc, w, particle_set, radii, rho_tot_g, gcut)
113 REAL(kind=dp), DIMENSION(:), INTENT(INOUT) :: bv
114 REAL(kind=dp), DIMENSION(:, :), POINTER :: gfunc
115 REAL(kind=dp), DIMENSION(:), POINTER :: w
116 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
117 REAL(kind=dp), DIMENSION(:), POINTER :: radii
118 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
119 REAL(kind=dp), INTENT(IN) :: gcut
120
121 CHARACTER(len=*), PARAMETER :: routinen = 'build_b_vector'
122
123 COMPLEX(KIND=dp) :: phase
124 INTEGER :: e_dim, handle, idim, ig, igauss, igmax, &
125 iparticle, s_dim
126 REAL(kind=dp) :: arg, g2, gcut2, gvec(3), rvec(3)
127 REAL(kind=dp), DIMENSION(:), POINTER :: my_bv, my_bvw
128
129 CALL timeset(routinen, handle)
130 NULLIFY (my_bv, my_bvw)
131 gcut2 = gcut*gcut
132 s_dim = rho_tot_g%pw_grid%first_gne0
133 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
134 igmax = 0
135 DO ig = s_dim, e_dim
136 g2 = rho_tot_g%pw_grid%gsq(ig)
137 IF (g2 > gcut2) EXIT
138 igmax = ig
139 END DO
140 IF (igmax >= s_dim) THEN
141 ALLOCATE (my_bv(s_dim:igmax))
142 ALLOCATE (my_bvw(s_dim:igmax))
143 !
144 DO iparticle = 1, SIZE(particle_set)
145 rvec = particle_set(iparticle)%r
146 my_bv = 0.0_dp
147 DO ig = s_dim, igmax
148 gvec = rho_tot_g%pw_grid%g(:, ig)
149 arg = dot_product(gvec, rvec)
150 phase = cmplx(cos(arg), -sin(arg), kind=dp)
151 my_bv(ig) = w(ig)*real(conjg(rho_tot_g%array(ig))*phase, kind=dp)
152 END DO
153 DO igauss = 1, SIZE(radii)
154 idim = (iparticle - 1)*SIZE(radii) + igauss
155 DO ig = s_dim, igmax
156 my_bvw(ig) = my_bv(ig)*gfunc(ig, igauss)
157 END DO
158 bv(idim) = accurate_sum(my_bvw)
159 END DO
160 END DO
161 DEALLOCATE (my_bvw)
162 DEALLOCATE (my_bv)
163 ELSE
164 DO iparticle = 1, SIZE(particle_set)
165 DO igauss = 1, SIZE(radii)
166 idim = (iparticle - 1)*SIZE(radii) + igauss
167 bv(idim) = 0.0_dp
168 END DO
169 END DO
170 END IF
171 CALL timestop(handle)
172 END SUBROUTINE build_b_vector
173
174! **************************************************************************************************
175!> \brief Computes the A matrix for the solution of the linear system
176!> \param Am ...
177!> \param gfunc ...
178!> \param w ...
179!> \param particle_set ...
180!> \param radii ...
181!> \param rho_tot_g ...
182!> \param gcut ...
183!> \param g_dot_rvec_sin ...
184!> \param g_dot_rvec_cos ...
185!> \par History
186!> 08.2005 created [tlaino]
187!> \author Teodoro Laino
188!> \note NB accept g_dot_rvec_* arrays
189! **************************************************************************************************
190 SUBROUTINE build_a_matrix(Am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
191 REAL(kind=dp), DIMENSION(:, :), INTENT(INOUT) :: am
192 REAL(kind=dp), DIMENSION(:, :), POINTER :: gfunc
193 REAL(kind=dp), DIMENSION(:), POINTER :: w
194 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
195 REAL(kind=dp), DIMENSION(:), POINTER :: radii
196 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
197 REAL(kind=dp), INTENT(IN) :: gcut
198 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: g_dot_rvec_sin, g_dot_rvec_cos
199
200 CHARACTER(len=*), PARAMETER :: routinen = 'build_A_matrix'
201
202 INTEGER :: e_dim, handle, idim1, idim2, ig, &
203 igauss1, igauss2, igmax, iparticle1, &
204 iparticle2, istart_g, s_dim
205 REAL(kind=dp) :: g2, gcut2, tmp
206 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: my_am, my_amw
207 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: gfunc_sq
208
209!NB precalculate as many things outside of the innermost loop as possible, in particular w(ig)*gfunc(ig,igauus1)*gfunc(ig,igauss2)
210
211 CALL timeset(routinen, handle)
212 gcut2 = gcut*gcut
213 s_dim = rho_tot_g%pw_grid%first_gne0
214 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
215 igmax = 0
216 DO ig = s_dim, e_dim
217 g2 = rho_tot_g%pw_grid%gsq(ig)
218 IF (g2 > gcut2) EXIT
219 igmax = ig
220 END DO
221 IF (igmax >= s_dim) THEN
222 ALLOCATE (my_am(s_dim:igmax))
223 ALLOCATE (my_amw(s_dim:igmax))
224 ALLOCATE (gfunc_sq(s_dim:igmax, SIZE(radii), SIZE(radii)))
225
226 DO igauss1 = 1, SIZE(radii)
227 DO igauss2 = 1, SIZE(radii)
228 gfunc_sq(s_dim:igmax, igauss1, igauss2) = w(s_dim:igmax)*gfunc(s_dim:igmax, igauss1)*gfunc(s_dim:igmax, igauss2)
229 END DO
230 END DO
231
232 DO iparticle1 = 1, SIZE(particle_set)
233 DO iparticle2 = iparticle1, SIZE(particle_set)
234 DO ig = s_dim, igmax
235 !NB replace explicit dot product and cosine with cos(A+B) formula - much faster
236 my_am(ig) = (g_dot_rvec_cos(ig - s_dim + 1, iparticle1)*g_dot_rvec_cos(ig - s_dim + 1, iparticle2) + &
237 g_dot_rvec_sin(ig - s_dim + 1, iparticle1)*g_dot_rvec_sin(ig - s_dim + 1, iparticle2))
238 END DO
239 DO igauss1 = 1, SIZE(radii)
240 idim1 = (iparticle1 - 1)*SIZE(radii) + igauss1
241 istart_g = 1
242 IF (iparticle2 == iparticle1) istart_g = igauss1
243 DO igauss2 = istart_g, SIZE(radii)
244 idim2 = (iparticle2 - 1)*SIZE(radii) + igauss2
245 my_amw(s_dim:igmax) = my_am(s_dim:igmax)*gfunc_sq(s_dim:igmax, igauss1, igauss2)
246 !NB no loss of accuracy in my test cases
247 !tmp = accurate_sum(my_Amw)
248 tmp = sum(my_amw)
249 am(idim2, idim1) = tmp
250 am(idim1, idim2) = tmp
251 END DO
252 END DO
253 END DO
254 END DO
255 DEALLOCATE (gfunc_sq)
256 DEALLOCATE (my_amw)
257 DEALLOCATE (my_am)
258 END IF
259 CALL timestop(handle)
260 END SUBROUTINE build_a_matrix
261
262! **************************************************************************************************
263!> \brief Computes the derivative of B vector for the evaluation of the Pulay forces
264!> \param dbv ...
265!> \param gfunc ...
266!> \param w ...
267!> \param particle_set ...
268!> \param radii ...
269!> \param rho_tot_g ...
270!> \param gcut ...
271!> \param iparticle0 ...
272!> \par History
273!> 08.2005 created [tlaino]
274!> \author Teodoro Laino
275! **************************************************************************************************
276 SUBROUTINE build_der_b_vector(dbv, gfunc, w, particle_set, radii, rho_tot_g, gcut, iparticle0)
277 REAL(kind=dp), DIMENSION(:, :), INTENT(INOUT) :: dbv
278 REAL(kind=dp), DIMENSION(:, :), POINTER :: gfunc
279 REAL(kind=dp), DIMENSION(:), POINTER :: w
280 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
281 REAL(kind=dp), DIMENSION(:), INTENT(IN) :: radii
282 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
283 REAL(kind=dp), INTENT(IN) :: gcut
284 INTEGER, INTENT(IN) :: iparticle0
285
286 CHARACTER(len=*), PARAMETER :: routinen = 'build_der_b_vector'
287
288 COMPLEX(KIND=dp) :: dphase
289 INTEGER :: e_dim, handle, idim, ig, igauss, igmax, &
290 iparticle, s_dim
291 REAL(kind=dp) :: arg, g2, gcut2
292 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: my_dbvw
293 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: my_dbv
294 REAL(kind=dp), DIMENSION(3) :: gvec, rvec
295
296 CALL timeset(routinen, handle)
297 gcut2 = gcut*gcut
298 s_dim = rho_tot_g%pw_grid%first_gne0
299 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
300 igmax = 0
301 DO ig = s_dim, e_dim
302 g2 = rho_tot_g%pw_grid%gsq(ig)
303 IF (g2 > gcut2) EXIT
304 igmax = ig
305 END DO
306 IF (igmax >= s_dim) THEN
307 ALLOCATE (my_dbv(3, s_dim:igmax))
308 ALLOCATE (my_dbvw(s_dim:igmax))
309 DO iparticle = 1, SIZE(particle_set)
310 IF (iparticle /= iparticle0) cycle
311 rvec = particle_set(iparticle)%r
312 DO ig = s_dim, igmax
313 gvec = rho_tot_g%pw_grid%g(:, ig)
314 arg = dot_product(gvec, rvec)
315 dphase = -cmplx(sin(arg), cos(arg), kind=dp)
316 my_dbv(:, ig) = w(ig)*real(conjg(rho_tot_g%array(ig))*dphase, kind=dp)*gvec(:)
317 END DO
318 DO igauss = 1, SIZE(radii)
319 idim = (iparticle - 1)*SIZE(radii) + igauss
320 DO ig = s_dim, igmax
321 my_dbvw(ig) = my_dbv(1, ig)*gfunc(ig, igauss)
322 END DO
323 dbv(idim, 1) = accurate_sum(my_dbvw)
324 DO ig = s_dim, igmax
325 my_dbvw(ig) = my_dbv(2, ig)*gfunc(ig, igauss)
326 END DO
327 dbv(idim, 2) = accurate_sum(my_dbvw)
328 DO ig = s_dim, igmax
329 my_dbvw(ig) = my_dbv(3, ig)*gfunc(ig, igauss)
330 END DO
331 dbv(idim, 3) = accurate_sum(my_dbvw)
332 END DO
333 END DO
334 DEALLOCATE (my_dbvw)
335 DEALLOCATE (my_dbv)
336 ELSE
337 DO iparticle = 1, SIZE(particle_set)
338 IF (iparticle /= iparticle0) cycle
339 DO igauss = 1, SIZE(radii)
340 idim = (iparticle - 1)*SIZE(radii) + igauss
341 dbv(idim, 1:3) = 0.0_dp
342 END DO
343 END DO
344 END IF
345 CALL timestop(handle)
346 END SUBROUTINE build_der_b_vector
347
348! **************************************************************************************************
349!> \brief Computes the derivative of the A matrix for the evaluation of the
350!> Pulay forces
351!> \param dAm ...
352!> \param gfunc ...
353!> \param w ...
354!> \param particle_set ...
355!> \param radii ...
356!> \param rho_tot_g ...
357!> \param gcut ...
358!> \param iparticle0 ...
359!> \param nparticles ...
360!> \param g_dot_rvec_sin ...
361!> \param g_dot_rvec_cos ...
362!> \par History
363!> 08.2005 created [tlaino]
364!> \author Teodoro Laino
365!> \note NB accept g_dot_rvec_* arrays
366! **************************************************************************************************
367 SUBROUTINE build_der_a_matrix_rows(dAm, gfunc, w, particle_set, radii, &
368 rho_tot_g, gcut, iparticle0, nparticles, g_dot_rvec_sin, g_dot_rvec_cos)
369 REAL(kind=dp), DIMENSION(:, :, :), INTENT(INOUT) :: dam
370 REAL(kind=dp), DIMENSION(:, :), POINTER :: gfunc
371 REAL(kind=dp), DIMENSION(:), POINTER :: w
372 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
373 REAL(kind=dp), DIMENSION(:), POINTER :: radii
374 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
375 REAL(kind=dp), INTENT(IN) :: gcut
376 INTEGER, INTENT(IN) :: iparticle0, nparticles
377 REAL(kind=dp), DIMENSION(:, :), INTENT(IN) :: g_dot_rvec_sin, g_dot_rvec_cos
378
379 CHARACTER(len=*), PARAMETER :: routinen = 'build_der_A_matrix_rows'
380
381 INTEGER :: e_dim, handle, ig, igauss2, igmax, &
382 iparticle1, iparticle2, s_dim
383 REAL(kind=dp) :: g2, gcut2
384
385!NB calculate derivatives for a block of particles, just the row parts (since derivative matrix is symmetric)
386!NB Use DGEMM to speed up calculation, can't do accurate_sum() anymore because dgemm does the sum over g
387
388 EXTERNAL dgemm
389 REAL(kind=dp), ALLOCATABLE :: lhs(:, :), rhs(:, :)
390 INTEGER :: nr, np, ng, icomp, ipp
391
392 CALL timeset(routinen, handle)
393 gcut2 = gcut*gcut
394 s_dim = rho_tot_g%pw_grid%first_gne0
395 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
396 igmax = 0
397 DO ig = s_dim, e_dim
398 g2 = rho_tot_g%pw_grid%gsq(ig)
399 IF (g2 > gcut2) EXIT
400 igmax = ig
401 END DO
402
403 nr = SIZE(radii)
404 np = SIZE(particle_set)
405 ng = igmax - s_dim + 1
406 IF (igmax >= s_dim) THEN
407 ALLOCATE (lhs(nparticles*nr, ng))
408 ALLOCATE (rhs(ng, np*nr))
409
410 ! rhs with first term of sin(g.(rvec1-rvec2))
411 ! rhs has all parts that depend on iparticle2
412 DO iparticle2 = 1, np
413 DO igauss2 = 1, nr
414 rhs(1:ng, (iparticle2 - 1)*nr + igauss2) = g_dot_rvec_sin(1:ng, iparticle2)*gfunc(s_dim:igmax, igauss2)
415 END DO
416 END DO
417 DO icomp = 1, 3
418 ! create lhs, which has all parts that depend on iparticle1
419 DO ipp = 1, nparticles
420 iparticle1 = iparticle0 + ipp - 1
421 DO ig = s_dim, igmax
422 lhs((ipp - 1)*nr + 1:(ipp - 1)*nr + nr, ig - s_dim + 1) = w(ig)*rho_tot_g%pw_grid%g(icomp, ig)* &
423 gfunc(ig, 1:nr)*g_dot_rvec_cos(ig - s_dim + 1, iparticle1)
424 END DO
425 END DO ! ipp
426 ! do main multiply
427 CALL dgemm('N', 'N', nparticles*nr, np*nr, ng, 1.0d0, lhs(1, 1), nparticles*nr, rhs(1, 1), &
428 ng, 0.0d0, dam((iparticle0 - 1)*nr + 1, 1, icomp), np*nr)
429 ! do extra multiplies to compensate for missing factor of 2
430 DO ipp = 1, nparticles
431 iparticle1 = iparticle0 + ipp - 1
432 CALL dgemm('N', 'N', nr, nr, ng, 1.0d0, lhs((ipp - 1)*nr + 1, 1), nparticles*nr, rhs(1, (iparticle1 - 1)*nr + 1), &
433 ng, 1.0d0, dam((iparticle1 - 1)*nr + 1, (iparticle1 - 1)*nr + 1, icomp), np*nr)
434 END DO
435 ! now extra columns to account for factor of 2 in some rhs columns
436 END DO ! icomp
437
438 ! rhs with second term of sin(g.(rvec1-rvec2))
439 ! rhs has all parts that depend on iparticle2
440 DO iparticle2 = 1, np
441 DO igauss2 = 1, nr
442 rhs(1:ng, (iparticle2 - 1)*nr + igauss2) = -g_dot_rvec_cos(1:ng, iparticle2)*gfunc(s_dim:igmax, igauss2)
443 END DO
444 END DO
445 DO icomp = 1, 3
446 ! create lhs, which has all parts that depend on iparticle1
447 DO ipp = 1, nparticles
448 iparticle1 = iparticle0 + ipp - 1
449 DO ig = s_dim, igmax
450 lhs((ipp - 1)*nr + 1:(ipp - 1)*nr + nr, ig - s_dim + 1) = w(ig)*rho_tot_g%pw_grid%g(icomp, ig)*gfunc(ig, 1:nr)* &
451 g_dot_rvec_sin(ig - s_dim + 1, iparticle1)
452 END DO
453 END DO
454 ! do main multiply
455 CALL dgemm('N', 'N', nparticles*nr, np*nr, ng, 1.0d0, lhs(1, 1), nparticles*nr, rhs(1, 1), &
456 ng, 1.0d0, dam((iparticle0 - 1)*nr + 1, 1, icomp), np*nr)
457 ! do extra multiples to compensate for missing factor of 2
458 DO ipp = 1, nparticles
459 iparticle1 = iparticle0 + ipp - 1
460 CALL dgemm('N', 'N', nr, nr, ng, 1.0d0, lhs((ipp - 1)*nr + 1, 1), nparticles*nr, rhs(1, (iparticle1 - 1)*nr + 1), &
461 ng, 1.0d0, dam((iparticle1 - 1)*nr + 1, (iparticle1 - 1)*nr + 1, icomp), np*nr)
462 END DO
463 END DO
464
465 DEALLOCATE (rhs)
466 DEALLOCATE (lhs)
467 ELSE
468 ! Some ranks may not own G-vectors below the cutoff.
469 dam((iparticle0 - 1)*nr + 1:(iparticle0 + nparticles - 1)*nr, :, :) = 0.0_dp
470 END IF
471 CALL timestop(handle)
472 END SUBROUTINE build_der_a_matrix_rows
473
474! **************************************************************************************************
475!> \brief deallocate g_dot_rvec_* arrays
476!> \param g_dot_rvec_sin ...
477!> \param g_dot_rvec_cos ...
478! **************************************************************************************************
479 SUBROUTINE cleanup_g_dot_rvec_sin_cos(g_dot_rvec_sin, g_dot_rvec_cos)
480 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: g_dot_rvec_sin, g_dot_rvec_cos
481
482 IF (ALLOCATED(g_dot_rvec_sin)) DEALLOCATE (g_dot_rvec_sin)
483 IF (ALLOCATED(g_dot_rvec_cos)) DEALLOCATE (g_dot_rvec_cos)
484 END SUBROUTINE cleanup_g_dot_rvec_sin_cos
485
486! **************************************************************************************************
487!> \brief precompute sin(g.r) and cos(g.r) for quicker evaluations of sin(g.(r1-r2)) and cos(g.(r1-r2))
488!> \param rho_tot_g ...
489!> \param particle_set ...
490!> \param gcut ...
491!> \param g_dot_rvec_sin ...
492!> \param g_dot_rvec_cos ...
493! **************************************************************************************************
494 SUBROUTINE prep_g_dot_rvec_sin_cos(rho_tot_g, particle_set, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
495 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
496 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
497 REAL(kind=dp), INTENT(IN) :: gcut
498 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: g_dot_rvec_sin, g_dot_rvec_cos
499
500 INTEGER :: e_dim, ig, igmax, iparticle, s_dim
501 REAL(kind=dp) :: g2, g_dot_rvec, gcut2, rvec(3)
502
503 gcut2 = gcut*gcut
504 s_dim = rho_tot_g%pw_grid%first_gne0
505 e_dim = rho_tot_g%pw_grid%ngpts_cut_local
506 igmax = 0
507 DO ig = s_dim, e_dim
508 g2 = rho_tot_g%pw_grid%gsq(ig)
509 IF (g2 > gcut2) EXIT
510 igmax = ig
511 END DO
512
513 IF (igmax >= s_dim) THEN
514 ALLOCATE (g_dot_rvec_sin(1:igmax - s_dim + 1, SIZE(particle_set)))
515 ALLOCATE (g_dot_rvec_cos(1:igmax - s_dim + 1, SIZE(particle_set)))
516
517 DO iparticle = 1, SIZE(particle_set)
518 rvec = particle_set(iparticle)%r
519 DO ig = s_dim, igmax
520 g_dot_rvec = dot_product(rho_tot_g%pw_grid%g(:, ig), rvec)
521 g_dot_rvec_sin(ig - s_dim + 1, iparticle) = sin(g_dot_rvec)
522 g_dot_rvec_cos(ig - s_dim + 1, iparticle) = cos(g_dot_rvec)
523 END DO
524 END DO
525 ELSE
526 ! Pass valid zero-sized arrays to the downstream routines.
527 ALLOCATE (g_dot_rvec_sin(0, SIZE(particle_set)))
528 ALLOCATE (g_dot_rvec_cos(0, SIZE(particle_set)))
529 END IF
530
531 END SUBROUTINE prep_g_dot_rvec_sin_cos
532
533! **************************************************************************************************
534!> \brief Computes the inverse AmI of the Am matrix
535!> \param GAmI ...
536!> \param c0 ...
537!> \param gfunc ...
538!> \param w ...
539!> \param particle_set ...
540!> \param gcut ...
541!> \param rho_tot_g ...
542!> \param radii ...
543!> \param iw ...
544!> \param Vol ...
545!> \par History
546!> 12.2005 created [tlaino]
547!> \author Teodoro Laino
548! **************************************************************************************************
549 SUBROUTINE ddapc_eval_ami(GAmI, c0, gfunc, w, particle_set, gcut, &
550 rho_tot_g, radii, iw, Vol)
551 REAL(kind=dp), DIMENSION(:, :), POINTER :: gami
552 REAL(kind=dp), INTENT(OUT) :: c0
553 REAL(kind=dp), DIMENSION(:, :), POINTER :: gfunc
554 REAL(kind=dp), DIMENSION(:), POINTER :: w
555 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
556 REAL(kind=dp), INTENT(IN) :: gcut
557 TYPE(pw_c1d_gs_type), INTENT(IN) :: rho_tot_g
558 REAL(kind=dp), DIMENSION(:), POINTER :: radii
559 INTEGER, INTENT(IN) :: iw
560 REAL(kind=dp), INTENT(IN) :: vol
561
562 CHARACTER(len=*), PARAMETER :: routinen = 'ddapc_eval_AmI'
563
564 INTEGER :: handle, ndim
565 REAL(kind=dp) :: condition_number, inv_error
566 REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: ame, cv
567 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: am, ami, amw, g_dot_rvec_cos, &
568 g_dot_rvec_sin
569
570!NB for precomputation of sin(g.r) and cos(g.r)
571
572 CALL timeset(routinen, handle)
573 ndim = SIZE(particle_set)*SIZE(radii)
574 ALLOCATE (am(ndim, ndim))
575 ALLOCATE (ami(ndim, ndim))
576 ALLOCATE (gami(ndim, ndim))
577 ALLOCATE (cv(ndim))
578 am = 0.0_dp
579 ami = 0.0_dp
580 cv = 1.0_dp/vol
581 !NB precompute sin(g.r) and cos(g.r) for faster evaluation of cos(g.(r1-r2)) in build_A_matrix()
582 CALL prep_g_dot_rvec_sin_cos(rho_tot_g, particle_set, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
583 CALL build_a_matrix(am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
584 CALL cleanup_g_dot_rvec_sin_cos(g_dot_rvec_sin, g_dot_rvec_cos)
585 am(:, :) = am(:, :)/(vol*vol)
586 CALL rho_tot_g%pw_grid%para%group%sum(am)
587 IF (iw > 0) THEN
588 ! Checking conditions numbers and eigenvalues
589 ALLOCATE (amw(ndim, ndim))
590 ALLOCATE (ame(ndim))
591 amw(:, :) = am
592 CALL diamat_all(amw, ame)
593 condition_number = maxval(abs(ame))/minval(abs(ame))
594 WRITE (iw, '(T3,A)') " Eigenvalues of Matrix A:"
595 WRITE (iw, '(T3,4E15.8)') ame
596 WRITE (iw, '(T3,A,1E15.9)') " Condition number:", condition_number
597 IF (condition_number > 1.0e12_dp) THEN
598 WRITE (iw, fmt="(/,T2,A)") &
599 "WARNING: high condition number => possibly ill-conditioned matrix"
600 END IF
601 DEALLOCATE (amw)
602 DEALLOCATE (ame)
603 END IF
604 CALL invert_matrix(am, ami, inv_error, "N", improve=.false.)
605 IF (iw > 0) THEN
606 WRITE (iw, '(T3,A,F15.9)') " Error inverting the A matrix: ", inv_error
607 END IF
608 c0 = dot_product(cv, matmul(ami, cv))
609 DEALLOCATE (am)
610 DEALLOCATE (cv)
611 gami = ami
612 DEALLOCATE (ami)
613 CALL timestop(handle)
614 END SUBROUTINE ddapc_eval_ami
615
616! **************************************************************************************************
617!> \brief Evaluates the Ewald term E2 and E3 energy term for the decoupling/coupling
618!> of periodic images
619!> \param cp_para_env ...
620!> \param coeff ...
621!> \param factor ...
622!> \param cell ...
623!> \param multipole_section ...
624!> \param particle_set ...
625!> \param M ...
626!> \param radii ...
627!> \par History
628!> 08.2005 created [tlaino]
629!> \author Teodoro Laino
630!> \note NB receive cp_para_env for parallelization
631! **************************************************************************************************
632 RECURSIVE SUBROUTINE ewald_ddapc_pot(cp_para_env, coeff, factor, cell, multipole_section, &
633 particle_set, M, radii)
634 TYPE(mp_para_env_type), INTENT(IN) :: cp_para_env
635 TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: coeff
636 REAL(kind=dp), INTENT(IN) :: factor
637 TYPE(cell_type), POINTER :: cell
638 TYPE(section_vals_type), POINTER :: multipole_section
639 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
640 REAL(kind=dp), DIMENSION(:, :), POINTER :: m
641 REAL(kind=dp), DIMENSION(:), POINTER :: radii
642
643 CHARACTER(len=*), PARAMETER :: routinen = 'ewald_ddapc_pot'
644
645 INTEGER :: ewmdim, handle, iaxis, idim, idim1, idim2, idimo, igauss1, igauss2, ip1, ip2, &
646 iparticle1, iparticle2, istart_g, k1, k2, k3, n_rep, ndim, r1, r2, r3
647 INTEGER, DIMENSION(3) :: gmax, image_cell, rmax, rmin
648 LOGICAL :: analyt
649 REAL(kind=dp) :: alpha, eps, ew_neut, fac, fac3, frac_radius, fs, g_ewald, galpha, gsq, &
650 gsqi, ij_fac, my_val, r, r2tmp, r_ewald, rc1, rc12, rc2, rc22, rcut, rcut2, t1, tol, tol1
651 REAL(kind=dp), DIMENSION(3) :: g_index, gvec, ra, rvec, svec
652 REAL(kind=dp), DIMENSION(:), POINTER :: ewm
653
654 NULLIFY (ewm)
655 CALL timeset(routinen, handle)
656 cpassert(.NOT. ASSOCIATED(m))
657 cpassert(ASSOCIATED(radii))
658 rcut = min(norm2(cell%hmat(:, 1)), norm2(cell%hmat(:, 2)), norm2(cell%hmat(:, 3)))/2.0_dp
659 CALL section_vals_val_get(multipole_section, "RCUT", n_rep_val=n_rep)
660 IF (n_rep == 1) CALL section_vals_val_get(multipole_section, "RCUT", r_val=rcut)
661 CALL section_vals_val_get(multipole_section, "EWALD_PRECISION", r_val=eps)
662 CALL section_vals_val_get(multipole_section, "ANALYTICAL_GTERM", l_val=analyt)
663 ! The spline interpolation path is only valid for orthorhombic grids.
664 analyt = analyt .OR. .NOT. cell%orthorhombic .OR. .NOT. ASSOCIATED(coeff)
665 rcut2 = rcut**2
666 !
667 ! Setting-up parameters for Ewald summation
668 !
669 eps = min(abs(eps), 0.5_dp)
670 tol = sqrt(abs(log(eps*rcut)))
671 alpha = sqrt(abs(log(eps*rcut*tol)))/rcut
672 galpha = 1.0_dp/(4.0_dp*alpha*alpha)
673 tol1 = sqrt(-log(eps*rcut*(2.0_dp*tol*alpha)**2))
674 IF (cell%orthorhombic) THEN
675 DO iaxis = 1, 3
676 gmax(iaxis) = nint(0.25_dp + cell%hmat(iaxis, iaxis)*alpha*tol1/pi)
677 END DO
678 ELSE
679 DO iaxis = 1, 3
680 gmax(iaxis) = ceiling(alpha*tol1*norm2(cell%hmat(:, iaxis))/pi)
681 END DO
682 END IF
683 fac = 1.e0_dp/cell%deth
684 fac3 = fac*pi
685 ew_neut = -fac*pi/alpha**2
686 !
687 ewmdim = SIZE(particle_set)*(SIZE(particle_set) + 1)/2
688 ndim = SIZE(particle_set)*SIZE(radii)
689 ALLOCATE (ewm(ewmdim))
690 ALLOCATE (m(ndim, ndim))
691 m = 0.0_dp
692 !
693 idim = 0
694 ewm = 0.0_dp
695 DO iparticle1 = 1, SIZE(particle_set)
696 ip1 = (iparticle1 - 1)*SIZE(radii)
697 DO iparticle2 = 1, iparticle1
698 ij_fac = 1.0_dp
699 IF (iparticle1 == iparticle2) ij_fac = 0.5_dp
700
701 ip2 = (iparticle2 - 1)*SIZE(radii)
702 idim = idim + 1
703 !NB parallelization, done here so indexing is right
704 IF (mod(iparticle1, cp_para_env%num_pe) /= cp_para_env%mepos) cycle
705 !
706 ! Real-Space Contribution
707 !
708 my_val = 0.0_dp
709 rvec = particle_set(iparticle1)%r - particle_set(iparticle2)%r
710 r_ewald = 0.0_dp
711 IF (iparticle1 /= iparticle2) THEN
712 ra = rvec
713 r2tmp = dot_product(ra, ra)
714 IF (r2tmp <= rcut2) THEN
715 r = sqrt(r2tmp)
716 t1 = erfc(alpha*r)/r
717 r_ewald = t1
718 END IF
719 END IF
720 svec = matmul(cell%h_inv, rvec)
721 DO iaxis = 1, 3
722 frac_radius = rcut*norm2(cell%h_inv(iaxis, :))
723 rmin(iaxis) = floor(-svec(iaxis) - frac_radius)
724 rmax(iaxis) = ceiling(-svec(iaxis) + frac_radius)
725 END DO
726 DO r1 = rmin(1), rmax(1)
727 DO r2 = rmin(2), rmax(2)
728 DO r3 = rmin(3), rmax(3)
729 IF ((r1 == 0) .AND. (r2 == 0) .AND. (r3 == 0)) cycle
730 image_cell = [r1, r2, r3]
731 ra = rvec + matmul(cell%hmat, real(image_cell, kind=dp))
732 r2tmp = dot_product(ra, ra)
733 IF (r2tmp <= rcut2) THEN
734 r = sqrt(r2tmp)
735 t1 = erfc(alpha*r)/r
736 r_ewald = r_ewald + t1*ij_fac
737 END IF
738 END DO
739 END DO
740 END DO
741 !
742 ! G-space Contribution
743 !
744 IF (analyt) THEN
745 g_ewald = 0.0_dp
746 DO k1 = 0, gmax(1)
747 DO k2 = -gmax(2), gmax(2)
748 DO k3 = -gmax(3), gmax(3)
749 IF (k1 == 0 .AND. k2 == 0 .AND. k3 == 0) cycle
750 fs = 2.0_dp; IF (k1 == 0) fs = 1.0_dp
751 g_index = [real(k1, kind=dp), real(k2, kind=dp), real(k3, kind=dp)]
752 gvec = twopi*matmul(transpose(cell%h_inv), g_index)
753 gsq = dot_product(gvec, gvec)
754 gsqi = fs/gsq
755 t1 = fac*gsqi*exp(-galpha*gsq)
756 g_ewald = g_ewald + t1*cos(dot_product(gvec, rvec))
757 END DO
758 END DO
759 END DO
760 ELSE
761 g_ewald = eval_interp_spl3_pbc(rvec, coeff)
762 END IF
763 !
764 ! G-EWALD, R-EWALD
765 !
766 g_ewald = r_ewald + fourpi*g_ewald
767 !
768 ! Self Contribution
769 !
770 IF (iparticle1 == iparticle2) THEN
771 g_ewald = g_ewald - 2.0_dp*alpha*oorootpi
772 END IF
773 !
774 IF (iparticle1 /= iparticle2) THEN
775 ra = rvec
776 r = norm2(ra)
777 my_val = factor/r
778 END IF
779 ewm(idim) = my_val - factor*g_ewald
780 END DO ! iparticle2
781 END DO ! iparticle1
782 !NB sum over parallelized contributions of different nodes
783 CALL cp_para_env%sum(ewm)
784 idim = 0
785 DO iparticle2 = 1, SIZE(particle_set)
786 ip2 = (iparticle2 - 1)*SIZE(radii)
787 idimo = (iparticle2 - 1)
788 idimo = idimo*(idimo + 1)/2
789 DO igauss2 = 1, SIZE(radii)
790 idim2 = ip2 + igauss2
791 rc2 = radii(igauss2)
792 rc22 = rc2*rc2
793 DO iparticle1 = 1, iparticle2
794 ip1 = (iparticle1 - 1)*SIZE(radii)
795 idim = idimo + iparticle1
796 istart_g = 1
797 IF (iparticle1 == iparticle2) istart_g = igauss2
798 DO igauss1 = istart_g, SIZE(radii)
799 idim1 = ip1 + igauss1
800 rc1 = radii(igauss1)
801 rc12 = rc1*rc1
802 m(idim1, idim2) = ewm(idim) - factor*ew_neut - factor*fac3*(rc12 + rc22)
803 m(idim2, idim1) = m(idim1, idim2)
804 END DO
805 END DO
806 END DO ! iparticle2
807 END DO ! iparticle1
808 DEALLOCATE (ewm)
809 CALL timestop(handle)
810 END SUBROUTINE ewald_ddapc_pot
811
812! **************************************************************************************************
813!> \brief Evaluates the electrostatic potential due to a simple solvation model
814!> Spherical cavity in a dieletric medium
815!> \param solvation_section ...
816!> \param particle_set ...
817!> \param M ...
818!> \param radii ...
819!> \par History
820!> 08.2006 created [tlaino]
821!> \author Teodoro Laino
822! **************************************************************************************************
823 SUBROUTINE solvation_ddapc_pot(solvation_section, particle_set, M, radii)
824 TYPE(section_vals_type), POINTER :: solvation_section
825 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
826 REAL(kind=dp), DIMENSION(:, :), POINTER :: m
827 REAL(kind=dp), DIMENSION(:), POINTER :: radii
828
829 INTEGER :: i, idim, idim1, idim2, igauss1, igauss2, ip1, ip2, iparticle1, iparticle2, &
830 istart_g, j, l, lmax, n_rep1, n_rep2, ndim, output_unit, weight
831 INTEGER, DIMENSION(:), POINTER :: list
832 LOGICAL :: fixed_center
833 REAL(kind=dp) :: center(3), eps_in, eps_out, factor, &
834 mass, mycos, r1, r2, rs, rvec(3)
835 REAL(kind=dp), DIMENSION(:), POINTER :: pos, r0
836 REAL(kind=dp), DIMENSION(:, :), POINTER :: cost, locp
837
838 fixed_center = .false.
839 output_unit = cp_logger_get_default_io_unit()
840 ndim = SIZE(particle_set)*SIZE(radii)
841 ALLOCATE (m(ndim, ndim))
842 m = 0.0_dp
843 eps_in = 1.0_dp
844 CALL section_vals_val_get(solvation_section, "EPS_OUT", r_val=eps_out)
845 CALL section_vals_val_get(solvation_section, "LMAX", i_val=lmax)
846 CALL section_vals_val_get(solvation_section, "SPHERE%RADIUS", r_val=rs)
847 CALL section_vals_val_get(solvation_section, "SPHERE%CENTER%XYZ", n_rep_val=n_rep1)
848 IF (n_rep1 /= 0) THEN
849 CALL section_vals_val_get(solvation_section, "SPHERE%CENTER%XYZ", r_vals=r0)
850 center = r0
851 ELSE
852 CALL section_vals_val_get(solvation_section, "SPHERE%CENTER%ATOM_LIST", &
853 n_rep_val=n_rep2)
854 IF (n_rep2 /= 0) THEN
855 CALL section_vals_val_get(solvation_section, "SPHERE%CENTER%ATOM_LIST", i_vals=list)
856 CALL section_vals_val_get(solvation_section, "SPHERE%CENTER%WEIGHT_TYPE", i_val=weight)
857 ALLOCATE (r0(3))
858 SELECT CASE (weight)
859 CASE (weight_type_unit)
860 r0 = 0.0_dp
861 DO i = 1, SIZE(list)
862 r0 = r0 + particle_set(list(i))%r
863 END DO
864 r0 = r0/real(SIZE(list), kind=dp)
865 CASE (weight_type_mass)
866 r0 = 0.0_dp
867 mass = 0.0_dp
868 DO i = 1, SIZE(list)
869 r0 = r0 + particle_set(list(i))%r*particle_set(list(i))%atomic_kind%mass
870 mass = mass + particle_set(list(i))%atomic_kind%mass
871 END DO
872 r0 = r0/mass
873 END SELECT
874 center = r0
875 CALL section_vals_val_get(solvation_section, "SPHERE%CENTER%FIXED", l_val=fixed_center)
876 IF (fixed_center) THEN
877 CALL section_vals_val_set(solvation_section, "SPHERE%CENTER%XYZ", &
878 r_vals_ptr=r0)
879 ELSE
880 DEALLOCATE (r0)
881 END IF
882 END IF
883 END IF
884 cpassert(n_rep1 /= 0 .OR. n_rep2 /= 0)
885 ! Potential calculation
886 ALLOCATE (locp(0:lmax, SIZE(particle_set)))
887 ALLOCATE (pos(SIZE(particle_set)))
888 ALLOCATE (cost(SIZE(particle_set), SIZE(particle_set)))
889 ! Determining the single atomic contribution to the dielectric dipole
890 DO i = 1, SIZE(particle_set)
891 rvec = particle_set(i)%r - center
892 r2 = dot_product(rvec, rvec)
893 r1 = sqrt(r2)
894 IF (r1 >= rs) THEN
895 IF (output_unit > 0) THEN
896 WRITE (output_unit, '(A,I6,A)') "Atom number :: ", i, " is out of the solvation sphere"
897 WRITE (output_unit, '(2(A,F12.6))') "Distance from the center::", r1, " Radius of the sphere::", rs
898 END IF
899 cpabort("Unable to evaluate electrostatic potential in solution")
900 END IF
901 locp(:, i) = 0.0_dp
902 IF (r1 /= 0.0_dp) THEN
903 DO l = 0, lmax
904 locp(l, i) = (r1**l*real(l + 1, kind=dp)*(eps_in - eps_out))/ &
905 (rs**(2*l + 1)*eps_in*(real(l, kind=dp)*eps_in + real(l + 1, kind=dp)*eps_out))
906 END DO
907 ELSE
908 ! limit for r->0
909 locp(0, i) = (eps_in - eps_out)/(rs*eps_in*eps_out)
910 END IF
911 pos(i) = r1
912 END DO
913 ! Particle-Particle potential energy matrix
914 cost = 0.0_dp
915 DO i = 1, SIZE(particle_set)
916 DO j = 1, i
917 factor = 0.0_dp
918 IF (pos(i)*pos(j) /= 0.0_dp) THEN
919 mycos = dot_product(particle_set(i)%r - center, particle_set(j)%r - center)/(pos(i)*pos(j))
920 IF (abs(mycos) > 1.0_dp) mycos = sign(1.0_dp, mycos)
921 DO l = 0, lmax
922 factor = factor + locp(l, i)*pos(j)**l*legendre(mycos, l, 0)
923 END DO
924 ELSE
925 factor = locp(0, i)
926 END IF
927 cost(i, j) = factor
928 cost(j, i) = factor
929 END DO
930 END DO
931 ! Computes the full potential energy matrix
932 idim = 0
933 DO iparticle2 = 1, SIZE(particle_set)
934 ip2 = (iparticle2 - 1)*SIZE(radii)
935 DO igauss2 = 1, SIZE(radii)
936 idim2 = ip2 + igauss2
937 DO iparticle1 = 1, iparticle2
938 ip1 = (iparticle1 - 1)*SIZE(radii)
939 istart_g = 1
940 IF (iparticle1 == iparticle2) istart_g = igauss2
941 DO igauss1 = istart_g, SIZE(radii)
942 idim1 = ip1 + igauss1
943 m(idim1, idim2) = cost(iparticle1, iparticle2)
944 m(idim2, idim1) = m(idim1, idim2)
945 END DO
946 END DO
947 END DO
948 END DO
949 DEALLOCATE (cost)
950 DEALLOCATE (pos)
951 DEALLOCATE (locp)
952 END SUBROUTINE solvation_ddapc_pot
953
954END MODULE cp_ddapc_methods
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Handles all functions related to the CELL.
Definition cell_types.F:15
contains information regarding the decoupling/recoupling method of Bloechl
subroutine, public cleanup_g_dot_rvec_sin_cos(g_dot_rvec_sin, g_dot_rvec_cos)
deallocate g_dot_rvec_* arrays
subroutine, public build_der_b_vector(dbv, gfunc, w, particle_set, radii, rho_tot_g, gcut, iparticle0)
Computes the derivative of B vector for the evaluation of the Pulay forces.
subroutine, public build_b_vector(bv, gfunc, w, particle_set, radii, rho_tot_g, gcut)
Computes the B vector for the solution of the linear system.
subroutine, public build_a_matrix(am, gfunc, w, particle_set, radii, rho_tot_g, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
Computes the A matrix for the solution of the linear system.
subroutine, public solvation_ddapc_pot(solvation_section, particle_set, m, radii)
Evaluates the electrostatic potential due to a simple solvation model Spherical cavity in a dieletric...
subroutine, public prep_g_dot_rvec_sin_cos(rho_tot_g, particle_set, gcut, g_dot_rvec_sin, g_dot_rvec_cos)
precompute sin(g.r) and cos(g.r) for quicker evaluations of sin(g.(r1-r2)) and cos(g....
recursive subroutine, public ewald_ddapc_pot(cp_para_env, coeff, factor, cell, multipole_section, particle_set, m, radii)
Evaluates the Ewald term E2 and E3 energy term for the decoupling/coupling of periodic images.
subroutine, public ddapc_eval_ami(gami, c0, gfunc, w, particle_set, gcut, rho_tot_g, radii, iw, vol)
Computes the inverse AmI of the Am matrix.
subroutine, public build_der_a_matrix_rows(dam, gfunc, w, particle_set, radii, rho_tot_g, gcut, iparticle0, nparticles, g_dot_rvec_sin, g_dot_rvec_cos)
Computes the derivative of the A matrix for the evaluation of the Pulay forces.
subroutine, public ddapc_eval_gfunc(gfunc, w, gcut, rho_tot_g, radii)
...
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...
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public weight_type_unit
integer, parameter, public weight_type_mass
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
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
sums arrays of real/complex numbers with much reduced round-off as compared to a naive implementation...
Definition kahan_sum.F:29
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Definition list.F:24
Definition of mathematical constants and functions.
real(kind=dp), parameter, public oorootpi
real(kind=dp), parameter, public pi
real(kind=dp), parameter, public fourpi
real(kind=dp), parameter, public twopi
real(kind=dp), dimension(0:maxfac), parameter, public fac
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Definition mathlib.F:381
Interface to the message passing library MPI.
Define the data structure for the particle information.
different utils that are useful to manipulate splines on the regular grid of a pw
real(kind=dp) function, public eval_interp_spl3_pbc(vec, pw)
Evaluates the PBC interpolated Spline (pw) function on the generic input vector (vec).
Calculate spherical harmonics.
real(kind=dp) function, public legendre(x, l, m)
...
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
stores all the informations relevant to an mpi environment