40#include "./base/base_uses.f90"
46 LOGICAL,
PRIVATE,
PARAMETER :: debug_this_module = .false.
47 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'nnp_acsf'
52 REAL(KIND=
dp),
PARAMETER,
PRIVATE :: cutoff_eq_tol = 1.0e-5_dp
89 TYPE(
nnp_type),
INTENT(INOUT),
POINTER :: nnp
90 INTEGER,
INTENT(IN) :: i
91 LOGICAL,
INTENT(IN) :: calc_forces
93 REAL(kind=
dp),
DIMENSION(:, :, :),
INTENT(INOUT), &
96 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_calc_acsf'
98 INTEGER :: handle, handle_nlist, handle_sf, ii, &
99 ind, izeta_il, j, k, l, m, n_ang1_s, &
100 n_ang2_s, n_input_nodes, n_symf_s, &
101 off, peak, s, sf, tid
102 LOGICAL :: do_forces, homo_grp
103 REAL(kind=
dp) :: angular_il, arg_il, costheta_il, cutoff_s, cutoff_sqr, dfcut3_il, &
104 dfcutdr1_il, dfcutdr2_il, dfcutdr3_il, dgdx_t1, dgdx_t2, dsymdr1_il, dsymdr2_il, &
105 dsymdr3_il, eta_il, f_il, fcut3_il, ftot_il, g_il, inv_g2_il, lam_il, pref_il, &
106 pref_lam_il, prefzeta_il, r1, r1_inv, r2, r2_inv, r2sum_il, r3, r3_inv, r3_sqr, rsqr1, &
107 rsqr2, rsqr3, sym_il, symtmp_il, tanh_il, tmp1_il, tmp2_il, tmp3_il, tmp_il, tmpzeta_il, &
109 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: ang_y, rad_y
110 REAL(kind=
dp),
DIMENSION(3) :: dcosbase1_il, dcosbase2_il, &
111 dcosbase3_il, dr1dx_il, dr2dx_il, &
112 dr3dx_il, f_jj_il, f_kk_il, rvect1, &
118 CALL timeset(routinen, handle)
122 do_forces = calc_forces
128 ALLOCATE (rad_y(nnp%n_rad(ind)))
129 ALLOCATE (ang_y(nnp%n_ang(ind)))
135 IF (nnp%rad(ind)%n_symfgrp > 0)
THEN
136 IF (.NOT. nnp%rad(ind)%symfgrp(1)%spline_built)
CALL nnp_build_radial_splines(nnp)
143 associate(workspace => nnp%neighbor_interface_state%workspace(ind, tid), &
144 neighbor => nnp%neighbor_interface_state%workspace(ind, tid)%neighbor, &
145 radial_symtmp => nnp%neighbor_interface_state%workspace(ind, tid)%radial_sym, &
146 radial_forcetmp => nnp%neighbor_interface_state%workspace(ind, tid)%radial_force, &
147 angular_symtmp => nnp%neighbor_interface_state%workspace(ind, tid)%angular_sym, &
148 angular_force3tmp => nnp%neighbor_interface_state%workspace(ind, tid)%angular_force, &
149 self_dgdr => nnp%neighbor_interface_state%workspace(ind, tid)%self_dGdr)
151 n_input_nodes = nnp%neighbor_interface_state%workspace(ind, tid)%n_input_nodes
152 IF (do_forces) self_dgdr(:, 1:n_input_nodes) = 0.0_dp
157 CALL timeset(
'nnp_acsf_neighbor_fill', handle_nlist)
158 neighbor%pbc_copies = nnp%cell_list_cache%exact_pbc_copies
161 CALL timestop(handle_nlist)
171 IF (
SIZE(neighbor%n_ang1) > 0) peak = max(peak, maxval(neighbor%n_ang1))
172 IF (
SIZE(neighbor%n_ang2) > 0) peak = max(peak, maxval(neighbor%n_ang2))
175 associate(fc_cache1 => workspace%fc_cache1, &
176 dfc_cache1 => workspace%dfc_cache1, &
177 fc_cache2 => workspace%fc_cache2, &
178 dfc_cache2 => workspace%dfc_cache2)
183 CALL timeset(
'nnp_acsf_radial', handle_sf)
184 DO s = 1, nnp%rad(ind)%n_symfgrp
185 n_symf_s = nnp%rad(ind)%symfgrp(s)%n_symf
188 associate(rad_buf => workspace%dGdr_rad(s)%data)
190 DO j = 1, neighbor%n_rad(s)
191 rvect1 = neighbor%rad(s)%dist(1:3, j)
192 r1 = neighbor%rad(s)%dist(4, j)
193 CALL nnp_calc_rad(nnp, ind, s, rvect1, r1, &
194 radial_symtmp(1:n_symf_s), &
195 radial_forcetmp(:, 1:n_symf_s))
198 m = nnp%rad(ind)%symfgrp(s)%symf(sf)
199 self_dgdr(1, m) = self_dgdr(1, m) + radial_forcetmp(1, sf)
200 self_dgdr(2, m) = self_dgdr(2, m) + radial_forcetmp(2, sf)
201 self_dgdr(3, m) = self_dgdr(3, m) + radial_forcetmp(3, sf)
202 rad_buf(1, sf, j) = -radial_forcetmp(1, sf)
203 rad_buf(2, sf, j) = -radial_forcetmp(2, sf)
204 rad_buf(3, sf, j) = -radial_forcetmp(3, sf)
205 IF (
PRESENT(stress))
THEN
207 stress(:, l, m) = stress(:, l, m) + rvect1(:)*radial_forcetmp(l, sf)
210 rad_y(m) = rad_y(m) + radial_symtmp(sf)
215 CALL timestop(handle_sf)
218 CALL timeset(
'nnp_acsf_angular', handle_sf)
224 DO s = 1, nnp%ang(ind)%n_symfgrp
225 cutoff_s = nnp%ang(ind)%symfgrp(s)%cutoff
226 cutoff_sqr = cutoff_s*cutoff_s
227 n_symf_s = nnp%ang(ind)%symfgrp(s)%n_symf
228 n_ang1_s = neighbor%n_ang1(s)
229 homo_grp = (nnp%ang(ind)%symfgrp(s)%ele(1) == nnp%ang(ind)%symfgrp(s)%ele(2))
238 n_ang2_s = neighbor%n_ang2(s)
244 IF (n_ang1_s > 0) workspace%dGdr_ang_jj(s)%data(:, 1:n_symf_s, 1:n_ang1_s) = 0.0_dp
246 IF (n_ang1_s > 0) workspace%dGdr_ang_kk(s)%data(:, 1:n_symf_s, 1:n_ang1_s) = 0.0_dp
248 IF (n_ang2_s > 0) workspace%dGdr_ang_kk(s)%data(:, 1:n_symf_s, 1:n_ang2_s) = 0.0_dp
252 CALL nnp_fill_fc_dfc_cache(neighbor%ang1(s)%dist, n_ang1_s, &
253 nnp%cut_type, cutoff_s, fc_cache1, dfc_cache1)
261 associate(jj_buf => workspace%dGdr_ang_jj(s)%data, &
262 kk_buf => workspace%dGdr_ang_kk(s)%data, &
263 grp_il => nnp%ang(ind)%symfgrp(s))
265 rvect1 = neighbor%ang1(s)%dist(1:3, j)
266 r1 = neighbor%ang1(s)%dist(4, j)
267 DO k = j + 1, n_ang1_s
268 rvect2 = neighbor%ang1(s)%dist(1:3, k)
269 r2 = neighbor%ang1(s)%dist(4, k)
270 rvect3(1) = rvect2(1) - rvect1(1)
271 rvect3(2) = rvect2(2) - rvect1(2)
272 rvect3(3) = rvect2(3) - rvect1(3)
273 r3_sqr = rvect3(1)*rvect3(1) + rvect3(2)*rvect3(2) + rvect3(3)*rvect3(3)
274 IF (r3_sqr < cutoff_sqr)
THEN
278 rsqr1 = r1*r1; rsqr2 = r2*r2; rsqr3 = r3*r3
279 r2sum_il = rsqr1 + rsqr2 + rsqr3
280 f_il = rsqr3 - rsqr1 - rsqr2
282 costheta_il = f_il/g_il
284 SELECT CASE (nnp%cut_type)
286 arg_il =
pi*r3/cutoff_s
287 fcut3_il = 0.5_dp*(cos(arg_il) + 1.0_dp)
288 dfcut3_il = -0.5_dp*sin(arg_il)*(
pi/cutoff_s)
290 tanh_il = tanh(1.0_dp - r3/cutoff_s)
291 fcut3_il = tanh_il**3
292 dfcut3_il = (-3.0_dp/cutoff_s)*(tanh_il**2 - tanh_il**4)
294 cpabort(
"NNP| Cutoff function unknown")
297 ftot_il = fc_cache1(j)*fc_cache1(k)*fcut3_il
298 dfcutdr1_il = dfc_cache1(j)*fc_cache1(k)*fcut3_il
299 dfcutdr2_il = fc_cache1(j)*dfc_cache1(k)*fcut3_il
300 dfcutdr3_il = fc_cache1(j)*fc_cache1(k)*dfcut3_il
302 r1_inv = 1.0_dp/r1; r2_inv = 1.0_dp/r2; r3_inv = 1.0_dp/r3
303 dr1dx_il(:) = rvect1(:)*r1_inv
304 dr2dx_il(:) = rvect2(:)*r2_inv
305 dr3dx_il(:) = rvect3(:)*r3_inv
307 inv_g2_il = 1.0_dp/(g_il*g_il)
309 dgdx_t1 = 2.0_dp*r2*dr1dx_il(ii)
310 dgdx_t2 = 2.0_dp*r1*dr2dx_il(ii)
311 dcosbase1_il(ii) = -2.0_dp*(rvect1(ii) + rvect2(ii))*g_il &
312 - f_il*(-(dgdx_t1 + dgdx_t2))
313 dcosbase2_il(ii) = 2.0_dp*(rvect3(ii) + rvect1(ii))*g_il &
315 dcosbase3_il(ii) = 2.0_dp*(rvect2(ii) - rvect3(ii))*g_il &
321 m = off + grp_il%symf(sf)
322 lam_il = grp_il%pack_lam(sf)
323 zeta_il = grp_il%pack_zeta(sf)
324 eta_il = grp_il%pack_eta(sf)
325 prefzeta_il = grp_il%pack_prefzeta(sf)
327 tmp_il = 1.0_dp + lam_il*costheta_il
328 IF (tmp_il <= 0.0_dp)
THEN
332 IF (grp_il%pack_use_int_zeta(sf))
THEN
333 izeta_il = grp_il%pack_izeta(sf)
334 tmpzeta_il = tmp_il**(izeta_il - 1)
336 tmpzeta_il = tmp_il**(zeta_il - 1.0_dp)
338 angular_il = tmpzeta_il*tmp_il
341 symtmp_il = exp(-eta_il*r2sum_il)
342 sym_il = prefzeta_il*angular_il*symtmp_il*ftot_il
343 ang_y(m - off) = ang_y(m - off) + sym_il
345 pref_lam_il = zeta_il*tmpzeta_il*lam_il*inv_g2_il
346 tmp_il = -2.0_dp*symtmp_il*eta_il
347 dsymdr1_il = tmp_il*r1
348 dsymdr2_il = tmp_il*r2
349 dsymdr3_il = tmp_il*r3
351 pref_il = prefzeta_il*symtmp_il*ftot_il
352 tmp1_il = prefzeta_il*angular_il*(ftot_il*dsymdr1_il + dfcutdr1_il*symtmp_il)
353 tmp2_il = prefzeta_il*angular_il*(ftot_il*dsymdr2_il + dfcutdr2_il*symtmp_il)
354 tmp3_il = prefzeta_il*angular_il*(ftot_il*dsymdr3_il + dfcutdr3_il*symtmp_il)
357 f_jj_il(ii) = pref_il*pref_lam_il*dcosbase2_il(ii) &
358 - tmp1_il*dr1dx_il(ii) + tmp3_il*dr3dx_il(ii)
359 f_kk_il(ii) = pref_il*pref_lam_il*dcosbase3_il(ii) &
360 - tmp2_il*dr2dx_il(ii) - tmp3_il*dr3dx_il(ii)
361 self_dgdr(ii, m) = self_dgdr(ii, m) &
362 + pref_il*pref_lam_il*dcosbase1_il(ii) &
363 + tmp1_il*dr1dx_il(ii) + tmp2_il*dr2dx_il(ii)
364 jj_buf(ii, sf, j) = jj_buf(ii, sf, j) + f_jj_il(ii)
365 kk_buf(ii, sf, k) = kk_buf(ii, sf, k) + f_kk_il(ii)
367 IF (
PRESENT(stress))
THEN
369 stress(:, l, m) = stress(:, l, m) &
370 - rvect1(:)*f_jj_il(l) - rvect2(:)*f_kk_il(l)
381 CALL nnp_fill_fc_dfc_cache(neighbor%ang2(s)%dist, n_ang2_s, &
382 nnp%cut_type, cutoff_s, fc_cache2, dfc_cache2)
384 associate(jj_buf => workspace%dGdr_ang_jj(s)%data, &
385 kk_buf => workspace%dGdr_ang_kk(s)%data, &
386 grp_il => nnp%ang(ind)%symfgrp(s))
388 rvect1 = neighbor%ang1(s)%dist(1:3, j)
389 r1 = neighbor%ang1(s)%dist(4, j)
391 rvect2 = neighbor%ang2(s)%dist(1:3, k)
392 r2 = neighbor%ang2(s)%dist(4, k)
393 rvect3(1) = rvect2(1) - rvect1(1)
394 rvect3(2) = rvect2(2) - rvect1(2)
395 rvect3(3) = rvect2(3) - rvect1(3)
396 r3_sqr = rvect3(1)*rvect3(1) + rvect3(2)*rvect3(2) + rvect3(3)*rvect3(3)
397 IF (r3_sqr < cutoff_sqr)
THEN
401 rsqr1 = r1*r1; rsqr2 = r2*r2; rsqr3 = r3*r3
402 r2sum_il = rsqr1 + rsqr2 + rsqr3
403 f_il = rsqr3 - rsqr1 - rsqr2
405 costheta_il = f_il/g_il
407 SELECT CASE (nnp%cut_type)
409 arg_il = pi*r3/cutoff_s
410 fcut3_il = 0.5_dp*(cos(arg_il) + 1.0_dp)
411 dfcut3_il = -0.5_dp*sin(arg_il)*(pi/cutoff_s)
413 tanh_il = tanh(1.0_dp - r3/cutoff_s)
414 fcut3_il = tanh_il**3
415 dfcut3_il = (-3.0_dp/cutoff_s)*(tanh_il**2 - tanh_il**4)
417 cpabort(
"NNP| Cutoff function unknown")
420 ftot_il = fc_cache1(j)*fc_cache2(k)*fcut3_il
421 dfcutdr1_il = dfc_cache1(j)*fc_cache2(k)*fcut3_il
422 dfcutdr2_il = fc_cache1(j)*dfc_cache2(k)*fcut3_il
423 dfcutdr3_il = fc_cache1(j)*fc_cache2(k)*dfcut3_il
425 r1_inv = 1.0_dp/r1; r2_inv = 1.0_dp/r2; r3_inv = 1.0_dp/r3
426 dr1dx_il(:) = rvect1(:)*r1_inv
427 dr2dx_il(:) = rvect2(:)*r2_inv
428 dr3dx_il(:) = rvect3(:)*r3_inv
430 inv_g2_il = 1.0_dp/(g_il*g_il)
432 dgdx_t1 = 2.0_dp*r2*dr1dx_il(ii)
433 dgdx_t2 = 2.0_dp*r1*dr2dx_il(ii)
434 dcosbase1_il(ii) = -2.0_dp*(rvect1(ii) + rvect2(ii))*g_il &
435 - f_il*(-(dgdx_t1 + dgdx_t2))
436 dcosbase2_il(ii) = 2.0_dp*(rvect3(ii) + rvect1(ii))*g_il &
438 dcosbase3_il(ii) = 2.0_dp*(rvect2(ii) - rvect3(ii))*g_il &
444 m = off + grp_il%symf(sf)
445 lam_il = grp_il%pack_lam(sf)
446 zeta_il = grp_il%pack_zeta(sf)
447 eta_il = grp_il%pack_eta(sf)
448 prefzeta_il = grp_il%pack_prefzeta(sf)
450 tmp_il = 1.0_dp + lam_il*costheta_il
451 IF (tmp_il <= 0.0_dp)
THEN
455 IF (grp_il%pack_use_int_zeta(sf))
THEN
456 izeta_il = grp_il%pack_izeta(sf)
457 tmpzeta_il = tmp_il**(izeta_il - 1)
459 tmpzeta_il = tmp_il**(zeta_il - 1.0_dp)
461 angular_il = tmpzeta_il*tmp_il
464 symtmp_il = exp(-eta_il*r2sum_il)
465 sym_il = prefzeta_il*angular_il*symtmp_il*ftot_il
466 ang_y(m - off) = ang_y(m - off) + sym_il
468 pref_lam_il = zeta_il*tmpzeta_il*lam_il*inv_g2_il
469 tmp_il = -2.0_dp*symtmp_il*eta_il
470 dsymdr1_il = tmp_il*r1
471 dsymdr2_il = tmp_il*r2
472 dsymdr3_il = tmp_il*r3
474 pref_il = prefzeta_il*symtmp_il*ftot_il
475 tmp1_il = prefzeta_il*angular_il*(ftot_il*dsymdr1_il + dfcutdr1_il*symtmp_il)
476 tmp2_il = prefzeta_il*angular_il*(ftot_il*dsymdr2_il + dfcutdr2_il*symtmp_il)
477 tmp3_il = prefzeta_il*angular_il*(ftot_il*dsymdr3_il + dfcutdr3_il*symtmp_il)
480 f_jj_il(ii) = pref_il*pref_lam_il*dcosbase2_il(ii) &
481 - tmp1_il*dr1dx_il(ii) + tmp3_il*dr3dx_il(ii)
482 f_kk_il(ii) = pref_il*pref_lam_il*dcosbase3_il(ii) &
483 - tmp2_il*dr2dx_il(ii) - tmp3_il*dr3dx_il(ii)
484 self_dgdr(ii, m) = self_dgdr(ii, m) &
485 + pref_il*pref_lam_il*dcosbase1_il(ii) &
486 + tmp1_il*dr1dx_il(ii) + tmp2_il*dr2dx_il(ii)
487 jj_buf(ii, sf, j) = jj_buf(ii, sf, j) + f_jj_il(ii)
488 kk_buf(ii, sf, k) = kk_buf(ii, sf, k) + f_kk_il(ii)
490 IF (
PRESENT(stress))
THEN
492 stress(:, l, m) = stress(:, l, m) &
493 - rvect1(:)*f_jj_il(l) - rvect2(:)*f_kk_il(l)
504 CALL timestop(handle_sf)
507 CALL timeset(
'nnp_acsf_radial', handle_sf)
508 DO s = 1, nnp%rad(ind)%n_symfgrp
510 DO j = 1, neighbor%n_rad(s)
511 rvect1 = neighbor%rad(s)%dist(1:3, j)
512 r1 = neighbor%rad(s)%dist(4, j)
513 CALL nnp_calc_rad(nnp, ind, s, rvect1, r1, radial_symtmp(1:nnp%rad(ind)%symfgrp(s)%n_symf))
514 DO sf = 1, nnp%rad(ind)%symfgrp(s)%n_symf
515 m = nnp%rad(ind)%symfgrp(s)%symf(sf)
516 rad_y(m) = rad_y(m) + radial_symtmp(sf)
520 CALL timestop(handle_sf)
523 CALL timeset(
'nnp_acsf_angular', handle_sf)
525 DO s = 1, nnp%ang(ind)%n_symfgrp
526 cutoff_s = nnp%ang(ind)%symfgrp(s)%cutoff
527 cutoff_sqr = cutoff_s*cutoff_s
528 n_symf_s = nnp%ang(ind)%symfgrp(s)%n_symf
529 n_ang1_s = neighbor%n_ang1(s)
532 CALL nnp_fill_fc_cache(neighbor%ang1(s)%dist, n_ang1_s, &
533 nnp%cut_type, cutoff_s, fc_cache1)
535 IF (nnp%ang(ind)%symfgrp(s)%ele(1) == nnp%ang(ind)%symfgrp(s)%ele(2))
THEN
537 rvect1 = neighbor%ang1(s)%dist(1:3, j)
538 r1 = neighbor%ang1(s)%dist(4, j)
539 DO k = j + 1, n_ang1_s
540 rvect2 = neighbor%ang1(s)%dist(1:3, k)
541 r2 = neighbor%ang1(s)%dist(4, k)
542 rvect3(1) = rvect2(1) - rvect1(1)
543 rvect3(2) = rvect2(2) - rvect1(2)
544 rvect3(3) = rvect2(3) - rvect1(3)
545 r3_sqr = rvect3(1)*rvect3(1) + rvect3(2)*rvect3(2) + rvect3(3)*rvect3(3)
546 IF (r3_sqr < cutoff_sqr)
THEN
548 CALL nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, r1, r2, r3, &
549 fc_cache1(j), 0.0_dp, fc_cache1(k), 0.0_dp, &
550 angular_symtmp(1:n_symf_s))
552 m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
553 ang_y(m - off) = ang_y(m - off) + angular_symtmp(sf)
560 n_ang2_s = neighbor%n_ang2(s)
561 CALL nnp_fill_fc_cache(neighbor%ang2(s)%dist, n_ang2_s, &
562 nnp%cut_type, cutoff_s, fc_cache2)
565 rvect1 = neighbor%ang1(s)%dist(1:3, j)
566 r1 = neighbor%ang1(s)%dist(4, j)
568 rvect2 = neighbor%ang2(s)%dist(1:3, k)
569 r2 = neighbor%ang2(s)%dist(4, k)
570 rvect3(1) = rvect2(1) - rvect1(1)
571 rvect3(2) = rvect2(2) - rvect1(2)
572 rvect3(3) = rvect2(3) - rvect1(3)
573 r3_sqr = rvect3(1)*rvect3(1) + rvect3(2)*rvect3(2) + rvect3(3)*rvect3(3)
574 IF (r3_sqr < cutoff_sqr)
THEN
576 CALL nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, r1, r2, r3, &
577 fc_cache1(j), 0.0_dp, fc_cache2(k), 0.0_dp, &
578 angular_symtmp(1:n_symf_s))
580 m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
581 ang_y(m - off) = ang_y(m - off) + angular_symtmp(sf)
588 CALL timestop(handle_sf)
598 CALL nnp_check_extrapolation(nnp, ind, rad_y, ang_y)
600 IF (
PRESENT(stress))
THEN
601 CALL nnp_scale_acsf(nnp, ind, do_forces, arc, rad_y, ang_y, stress)
603 CALL nnp_scale_acsf(nnp, ind, do_forces, arc, rad_y, ang_y)
606 DEALLOCATE (rad_y, ang_y)
608 CALL timestop(handle)
622 PURE SUBROUTINE nnp_fill_fc_dfc_cache(dist, n, cut_type, cutoff_s, fc_cache, dfc_cache)
623 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: dist
624 INTEGER,
INTENT(IN) :: n, cut_type
625 REAL(kind=dp),
INTENT(IN) :: cutoff_s
626 REAL(kind=dp),
DIMENSION(:),
INTENT(OUT) :: fc_cache, dfc_cache
629 REAL(kind=dp) :: arg_tmp, r_tmp, tanh_tmp
633 SELECT CASE (cut_type)
635 arg_tmp = pi*r_tmp/cutoff_s
636 fc_cache(j) = 0.5_dp*(cos(arg_tmp) + 1.0_dp)
637 dfc_cache(j) = -0.5_dp*sin(arg_tmp)*(pi/cutoff_s)
639 tanh_tmp = tanh(1.0_dp - r_tmp/cutoff_s)
640 fc_cache(j) = tanh_tmp**3
641 dfc_cache(j) = (-3.0_dp/cutoff_s)*(tanh_tmp**2 - tanh_tmp**4)
645 END SUBROUTINE nnp_fill_fc_dfc_cache
656 PURE SUBROUTINE nnp_fill_fc_cache(dist, n, cut_type, cutoff_s, fc_cache)
657 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: dist
658 INTEGER,
INTENT(IN) :: n, cut_type
659 REAL(kind=dp),
INTENT(IN) :: cutoff_s
660 REAL(kind=dp),
DIMENSION(:),
INTENT(OUT) :: fc_cache
663 REAL(kind=dp) :: r_tmp, tanh_tmp
667 SELECT CASE (cut_type)
669 fc_cache(j) = 0.5_dp*(cos(pi*r_tmp/cutoff_s) + 1.0_dp)
671 tanh_tmp = tanh(1.0_dp - r_tmp/cutoff_s)
672 fc_cache(j) = tanh_tmp**3
676 END SUBROUTINE nnp_fill_fc_cache
690 TYPE(nnp_type),
INTENT(INOUT),
POINTER :: nnp
694 IF (.NOT.
ALLOCATED(nnp%cell_list_cache))
ALLOCATE (nnp%cell_list_cache)
695 IF (.NOT.
ALLOCATED(nnp%neighbor_interface_state))
ALLOCATE (nnp%neighbor_interface_state)
696 CALL nnp_prepare_cell_list_cache(nnp)
697 CALL nnp_neighbor_interface_prepare(nnp)
702 DO ind = 1, nnp%n_ele
703 IF (nnp%rad(ind)%n_symfgrp > 0)
THEN
704 IF (.NOT. nnp%rad(ind)%symfgrp(1)%spline_built)
THEN
705 CALL nnp_build_radial_splines(nnp)
722 SUBROUTINE nnp_check_extrapolation(nnp, ind, rad_y, ang_y)
724 TYPE(nnp_type),
INTENT(INOUT) :: nnp
725 INTEGER,
INTENT(IN) :: ind
726 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: rad_y, ang_y
728 REAL(kind=dp),
PARAMETER :: threshold = 0.0001_dp
731 LOGICAL :: extrapolate
733 extrapolate = .false.
735 DO j = 1, nnp%n_rad(ind)
736 IF (rad_y(j) - nnp%rad(ind)%loc_max(j) > threshold)
THEN
738 ELSE IF (-rad_y(j) + nnp%rad(ind)%loc_min(j) > threshold)
THEN
742 DO j = 1, nnp%n_ang(ind)
743 IF (ang_y(j) - nnp%ang(ind)%loc_max(j) > threshold)
THEN
745 ELSE IF (-ang_y(j) + nnp%ang(ind)%loc_min(j) > threshold)
THEN
752 IF (extrapolate) nnp%output_expol = .true.
754 END SUBROUTINE nnp_check_extrapolation
768 SUBROUTINE nnp_scale_acsf(nnp, ind, do_forces, arc, rad_y, ang_y, stress)
770 TYPE(nnp_type),
INTENT(INOUT) :: nnp
771 INTEGER,
INTENT(IN) :: ind
772 LOGICAL,
INTENT(IN) :: do_forces
773 TYPE(nnp_arc_type),
INTENT(INOUT) :: arc
774 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: rad_y, ang_y
775 REAL(kind=dp),
DIMENSION(:, :, :),
INTENT(INOUT), &
778 INTEGER :: j, k, m, n_ang1_s, n_ang2_s, n_symf_s, &
781 REAL(kind=dp) :: scale
788 IF (nnp%center_acsf)
THEN
789 DO j = 1, nnp%n_rad(ind)
790 arc%layer(1)%node(j) = rad_y(j) - nnp%rad(ind)%loc_av(j)
793 DO j = 1, nnp%n_ang(ind)
794 arc%layer(1)%node(j + off) = ang_y(j) - nnp%ang(ind)%loc_av(j)
797 IF (nnp%scale_acsf)
THEN
798 DO j = 1, nnp%n_rad(ind)
799 arc%layer(1)%node(j) = arc%layer(1)%node(j)/ &
800 (nnp%rad(ind)%loc_max(j) - nnp%rad(ind)%loc_min(j))*(nnp%scmax - nnp%scmin) + nnp%scmin
803 DO j = 1, nnp%n_ang(ind)
804 arc%layer(1)%node(j + off) = arc%layer(1)%node(j + off)/ &
805 (nnp%ang(ind)%loc_max(j) - nnp%ang(ind)%loc_min(j))*(nnp%scmax - nnp%scmin) + nnp%scmin
808 ELSE IF (nnp%scale_acsf)
THEN
809 DO j = 1, nnp%n_rad(ind)
810 arc%layer(1)%node(j) = (rad_y(j) - nnp%rad(ind)%loc_min(j))/ &
811 (nnp%rad(ind)%loc_max(j) - nnp%rad(ind)%loc_min(j))* &
812 (nnp%scmax - nnp%scmin) + nnp%scmin
815 DO j = 1, nnp%n_ang(ind)
816 arc%layer(1)%node(j + off) = (ang_y(j) - nnp%ang(ind)%loc_min(j))/ &
817 (nnp%ang(ind)%loc_max(j) - nnp%ang(ind)%loc_min(j))* &
818 (nnp%scmax - nnp%scmin) + nnp%scmin
820 ELSE IF (nnp%scale_sigma_acsf)
THEN
821 DO j = 1, nnp%n_rad(ind)
822 arc%layer(1)%node(j) = (rad_y(j) - nnp%rad(ind)%loc_av(j))/ &
823 nnp%rad(ind)%sigma(j)*(nnp%scmax - nnp%scmin) + nnp%scmin
826 DO j = 1, nnp%n_ang(ind)
827 arc%layer(1)%node(j + off) = (ang_y(j) - nnp%ang(ind)%loc_av(j))/ &
828 nnp%ang(ind)%sigma(j)*(nnp%scmax - nnp%scmin) + nnp%scmin
831 DO j = 1, nnp%n_rad(ind)
832 arc%layer(1)%node(j) = rad_y(j)
835 DO j = 1, nnp%n_ang(ind)
836 arc%layer(1)%node(j + off) = ang_y(j)
840 IF (do_forces .AND. (nnp%scale_acsf .OR. nnp%scale_sigma_acsf))
THEN
846 associate(workspace => nnp%neighbor_interface_state%workspace(ind, tid), &
847 neighbor => nnp%neighbor_interface_state%workspace(ind, tid)%neighbor, &
848 self_dgdr => nnp%neighbor_interface_state%workspace(ind, tid)%self_dGdr)
851 DO s = 1, nnp%rad(ind)%n_symfgrp
852 n_symf_s = nnp%rad(ind)%symfgrp(s)%n_symf
853 associate(rad_buf => workspace%dGdr_rad(s)%data)
855 m = nnp%rad(ind)%symfgrp(s)%symf(sf)
856 IF (nnp%scale_acsf)
THEN
857 scale = (nnp%scmax - nnp%scmin)/ &
858 (nnp%rad(ind)%loc_max(m) - nnp%rad(ind)%loc_min(m))
860 scale = (nnp%scmax - nnp%scmin)/nnp%rad(ind)%sigma(m)
862 self_dgdr(1, m) = self_dgdr(1, m)*scale
863 self_dgdr(2, m) = self_dgdr(2, m)*scale
864 self_dgdr(3, m) = self_dgdr(3, m)*scale
865 DO j = 1, neighbor%n_rad(s)
866 rad_buf(1, sf, j) = rad_buf(1, sf, j)*scale
867 rad_buf(2, sf, j) = rad_buf(2, sf, j)*scale
868 rad_buf(3, sf, j) = rad_buf(3, sf, j)*scale
876 DO s = 1, nnp%ang(ind)%n_symfgrp
877 n_symf_s = nnp%ang(ind)%symfgrp(s)%n_symf
878 n_ang1_s = neighbor%n_ang1(s)
879 homo_grp = (nnp%ang(ind)%symfgrp(s)%ele(1) == nnp%ang(ind)%symfgrp(s)%ele(2))
884 n_ang2_s = neighbor%n_ang2(s)
886 associate(jj_buf => workspace%dGdr_ang_jj(s)%data, &
887 kk_buf => workspace%dGdr_ang_kk(s)%data)
889 m = off + nnp%ang(ind)%symfgrp(s)%symf(sf)
890 IF (nnp%scale_acsf)
THEN
891 scale = (nnp%scmax - nnp%scmin)/ &
892 (nnp%ang(ind)%loc_max(m - off) - nnp%ang(ind)%loc_min(m - off))
894 scale = (nnp%scmax - nnp%scmin)/nnp%ang(ind)%sigma(m - off)
896 self_dgdr(1, m) = self_dgdr(1, m)*scale
897 self_dgdr(2, m) = self_dgdr(2, m)*scale
898 self_dgdr(3, m) = self_dgdr(3, m)*scale
900 jj_buf(1, sf, j) = jj_buf(1, sf, j)*scale
901 jj_buf(2, sf, j) = jj_buf(2, sf, j)*scale
902 jj_buf(3, sf, j) = jj_buf(3, sf, j)*scale
905 kk_buf(1, sf, k) = kk_buf(1, sf, k)*scale
906 kk_buf(2, sf, k) = kk_buf(2, sf, k)*scale
907 kk_buf(3, sf, k) = kk_buf(3, sf, k)*scale
916 IF (
PRESENT(stress))
THEN
917 IF (nnp%scale_acsf)
THEN
918 DO j = 1, nnp%n_rad(ind)
919 stress(:, :, j) = stress(:, :, j)/(nnp%rad(ind)%loc_max(j) - nnp%rad(ind)%loc_min(j))* &
920 (nnp%scmax - nnp%scmin)
923 DO j = 1, nnp%n_ang(ind)
924 stress(:, :, j + off) = stress(:, :, j + off)/ &
925 (nnp%ang(ind)%loc_max(j) - nnp%ang(ind)%loc_min(j))* &
926 (nnp%scmax - nnp%scmin)
928 ELSE IF (nnp%scale_sigma_acsf)
THEN
929 DO j = 1, nnp%n_rad(ind)
930 stress(:, :, j) = stress(:, :, j)/nnp%rad(ind)%sigma(j)*(nnp%scmax - nnp%scmin)
933 DO j = 1, nnp%n_ang(ind)
934 stress(:, :, j + off) = stress(:, :, j + off)/nnp%ang(ind)%sigma(j)*(nnp%scmax - nnp%scmin)
939 END SUBROUTINE nnp_scale_acsf
953 SUBROUTINE nnp_calc_rad(nnp, ind, s, rvect, r, sym, force)
955 TYPE(nnp_type),
INTENT(IN),
TARGET :: nnp
956 INTEGER,
INTENT(IN) :: ind, s
957 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: rvect
958 REAL(kind=dp),
INTENT(IN) :: r
959 REAL(kind=dp),
DIMENSION(:),
INTENT(OUT) :: sym
960 REAL(kind=dp),
DIMENSION(:, :),
INTENT(OUT), &
963 INTEGER :: i, n_symf, sf
964 REAL(kind=dp) :: dh00, dh01, dh10, dh11, drdx_x, drdx_y, &
965 drdx_z, dsymdr_full, dyi, dyi1, h00, &
966 h01, h10, h10_dx, h11, h11_dx, r_inv, &
968 TYPE(nnp_symfgrp_type),
POINTER :: grp
970 grp => nnp%rad(ind)%symfgrp(s)
981 IF (r >= grp%spline_x_max)
THEN
985 IF (
PRESENT(force))
THEN
987 force(1, sf) = 0.0_dp
988 force(2, sf) = 0.0_dp
989 force(3, sf) = 0.0_dp
995 i = int(r*grp%spline_dx_inv) + 1
997 IF (i > grp%spline_n - 1) i = grp%spline_n - 1
999 t = (r - real(i - 1, kind=dp)*grp%spline_dx)*grp%spline_dx_inv
1003 h00 = 2.0_dp*t3 - 3.0_dp*t2 + 1.0_dp
1004 h10 = t3 - 2.0_dp*t2 + t
1005 h01 = -2.0_dp*t3 + 3.0_dp*t2
1007 h10_dx = h10*grp%spline_dx
1008 h11_dx = h11*grp%spline_dx
1010 IF (
PRESENT(force))
THEN
1011 dh00 = 6.0_dp*(t2 - t)
1012 dh10 = 3.0_dp*t2 - 4.0_dp*t + 1.0_dp
1014 dh11 = 3.0_dp*t2 - 2.0_dp*t
1017 drdx_x = rvect(1)*r_inv
1018 drdx_y = rvect(2)*r_inv
1019 drdx_z = rvect(3)*r_inv
1023 associate(spy_i => grp%spline_y(:, i), spy_i1 => grp%spline_y(:, i + 1), &
1024 spdy_i => grp%spline_dy(:, i), spdy_i1 => grp%spline_dy(:, i + 1))
1031 sym(sf) = h00*yi + h10_dx*dyi + h01*yi1 + h11_dx*dyi1
1032 dsymdr_full = (dh00*yi + dh01*yi1)*grp%spline_dx_inv + dh10*dyi + dh11*dyi1
1033 force(1, sf) = dsymdr_full*drdx_x
1034 force(2, sf) = dsymdr_full*drdx_y
1035 force(3, sf) = dsymdr_full*drdx_z
1039 associate(spy_i => grp%spline_y(:, i), spy_i1 => grp%spline_y(:, i + 1), &
1040 spdy_i => grp%spline_dy(:, i), spdy_i1 => grp%spline_dy(:, i + 1))
1043 sym(sf) = h00*spy_i(sf) + h10_dx*spdy_i(sf) + &
1044 h01*spy_i1(sf) + h11_dx*spdy_i1(sf)
1049 END SUBROUTINE nnp_calc_rad
1057 SUBROUTINE nnp_build_radial_splines(nnp)
1059 TYPE(nnp_type),
INTENT(INOUT),
POINTER :: nnp
1061 CHARACTER(len=*),
PARAMETER :: routinen =
'nnp_build_radial_splines'
1063 INTEGER :: handle, ind, k, n_symf, p, s, sf
1064 REAL(kind=dp) :: arg, cutoff, dfcutdr, dr, eta, exp_term, &
1065 fcut, r, rs, tanh_tmp
1067 CALL timeset(routinen, handle)
1069 DO ind = 1, nnp%n_ele
1070 DO s = 1, nnp%rad(ind)%n_symfgrp
1071 associate(grp => nnp%rad(ind)%symfgrp(s))
1074 dr = cutoff/real(nnp%rad_spline_n - 1, kind=dp)
1076 IF (
ALLOCATED(grp%spline_y))
DEALLOCATE (grp%spline_y)
1077 IF (
ALLOCATED(grp%spline_dy))
DEALLOCATE (grp%spline_dy)
1078 ALLOCATE (grp%spline_y(max(1, n_symf), nnp%rad_spline_n))
1079 ALLOCATE (grp%spline_dy(max(1, n_symf), nnp%rad_spline_n))
1080 grp%spline_n = nnp%rad_spline_n
1082 grp%spline_dx_inv = 1.0_dp/dr
1083 grp%spline_x_max = cutoff
1089 eta = nnp%rad(ind)%eta(k)
1090 rs = nnp%rad(ind)%rs(k)
1092 DO p = 1, nnp%rad_spline_n
1093 r = real(p - 1, kind=dp)*dr
1095 SELECT CASE (nnp%cut_type)
1098 fcut = 0.5_dp*(cos(arg) + 1.0_dp)
1099 dfcutdr = -0.5_dp*sin(arg)*(pi/cutoff)
1101 tanh_tmp = tanh(1.0_dp - r/cutoff)
1103 dfcutdr = (-3.0_dp/cutoff)*(tanh_tmp**2 - tanh_tmp**4)
1105 cpabort(
"NNP| Cutoff function unknown")
1108 exp_term = exp(-eta*(r - rs)**2)
1110 grp%spline_y(sf, p) = exp_term*fcut
1111 grp%spline_dy(sf, p) = exp_term*(-2.0_dp*eta*(r - rs))*fcut + &
1119 grp%spline_y(sf, nnp%rad_spline_n) = 0.0_dp
1120 grp%spline_dy(sf, nnp%rad_spline_n) = 0.0_dp
1123 grp%spline_built = .true.
1128 CALL timestop(handle)
1130 END SUBROUTINE nnp_build_radial_splines
1173 SUBROUTINE nnp_calc_ang(nnp, ind, s, rvect1, rvect2, rvect3, r1, r2, r3, &
1174 fcut_j, dfcut_j, fcut_k, dfcut_k, sym, force)
1176 TYPE(nnp_type),
INTENT(IN),
TARGET :: nnp
1177 INTEGER,
INTENT(IN) :: ind, s
1178 REAL(kind=dp),
DIMENSION(3),
INTENT(IN) :: rvect1, rvect2, rvect3
1179 REAL(kind=dp),
INTENT(IN) :: r1, r2, r3, fcut_j, dfcut_j, fcut_k, &
1181 REAL(kind=dp),
DIMENSION(:),
INTENT(OUT) :: sym
1182 REAL(kind=dp),
DIMENSION(:, :, :),
INTENT(OUT), &
1185 INTEGER :: ii, izeta, n_symf, sf
1186 LOGICAL :: do_forces
1187 REAL(kind=dp) :: angular, arg_tmp, costheta, dfcut3, dfcutdr1, dfcutdr2, dfcutdr3, dsymdr1, &
1188 dsymdr2, dsymdr3, eta, f, fcut3, fcut_rc, ftot, g, inv_g2, lam, pref_lam, prefzeta, &
1189 r2sum, rsqr1, rsqr2, rsqr3, symtmp, tanh_tmp, tmp, tmp1, tmp2, tmp3, tmpzeta, zeta
1190 REAL(kind=dp),
DIMENSION(3) :: dcosbase1, dcosbase2, dcosbase3, dgdx1, &
1191 dgdx2, dgdx3, dr1dx, dr2dx, dr3dx
1192 TYPE(nnp_symfgrp_type),
POINTER :: grp
1194 DIMENSION(nnp%ang(ind)%symfgrp(s)%n_symf) :: angular_arr, symtmp_arr, tmpzeta_arr
1201 do_forces =
PRESENT(force)
1202 grp => nnp%ang(ind)%symfgrp(s)
1204 fcut_rc = grp%cutoff
1209 r2sum = rsqr1 + rsqr2 + rsqr3
1211 f = rsqr3 - rsqr1 - rsqr2
1216 SELECT CASE (nnp%cut_type)
1218 arg_tmp = pi*r3/fcut_rc
1219 fcut3 = 0.5_dp*(cos(arg_tmp) + 1.0_dp)
1220 IF (do_forces) dfcut3 = -0.5_dp*sin(arg_tmp)*(pi/fcut_rc)
1222 tanh_tmp = tanh(1.0_dp - r3/fcut_rc)
1224 IF (do_forces) dfcut3 = (-3.0_dp/fcut_rc)*(tanh_tmp**2 - tanh_tmp**4)
1226 cpabort(
"NNP| Cutoff function unknown")
1230 ftot = fcut_j*fcut_k*fcut3
1234 dfcutdr1 = dfcut_j*fcut_k*fcut3
1235 dfcutdr2 = fcut_j*dfcut_k*fcut3
1236 dfcutdr3 = fcut_j*fcut_k*dfcut3
1238 dr1dx(:) = rvect1(:)/r1
1239 dr2dx(:) = rvect2(:)/r2
1240 dr3dx(:) = rvect3(:)/r3
1246 inv_g2 = 1.0_dp/(g*g)
1248 tmp1 = 2.0_dp*r2*dr1dx(ii)
1249 tmp2 = 2.0_dp*r1*dr2dx(ii)
1250 dgdx1(ii) = -(tmp1 + tmp2)
1254 dcosbase1(ii) = -2.0_dp*(rvect1(ii) + rvect2(ii))*g - f*dgdx1(ii)
1255 dcosbase2(ii) = 2.0_dp*(rvect3(ii) + rvect1(ii))*g - f*dgdx2(ii)
1256 dcosbase3(ii) = 2.0_dp*(rvect2(ii) - rvect3(ii))*g - f*dgdx3(ii)
1264 tmp = 1.0_dp + grp%pack_lam(sf)*costheta
1265 IF (tmp <= 0.0_dp)
THEN
1266 tmpzeta_arr(sf) = 0.0_dp
1267 angular_arr(sf) = 0.0_dp
1269 IF (grp%pack_use_int_zeta(sf))
THEN
1270 izeta = grp%pack_izeta(sf)
1271 tmpzeta_arr(sf) = tmp**(izeta - 1)
1273 tmpzeta_arr(sf) = tmp**(grp%pack_zeta(sf) - 1.0_dp)
1275 angular_arr(sf) = tmpzeta_arr(sf)*tmp
1287 symtmp_arr(sf) = exp(-grp%pack_eta(sf)*r2sum)
1293 sym(sf) = grp%pack_prefzeta(sf)*angular_arr(sf)*symtmp_arr(sf)*ftot
1299 symtmp = symtmp_arr(sf)
1300 angular = angular_arr(sf)
1301 tmpzeta = tmpzeta_arr(sf)
1302 eta = grp%pack_eta(sf)
1303 lam = grp%pack_lam(sf)
1304 zeta = grp%pack_zeta(sf)
1305 prefzeta = grp%pack_prefzeta(sf)
1309 pref_lam = zeta*tmpzeta*lam*inv_g2
1311 tmp = -2.0_dp*symtmp*eta
1316 tmp = prefzeta*symtmp*ftot
1317 tmp1 = prefzeta*angular*(ftot*dsymdr1 + dfcutdr1*symtmp)
1318 tmp2 = prefzeta*angular*(ftot*dsymdr2 + dfcutdr2*symtmp)
1319 tmp3 = prefzeta*angular*(ftot*dsymdr3 + dfcutdr3*symtmp)
1321 force(ii, 1, sf) = tmp*pref_lam*dcosbase1(ii) + tmp1*dr1dx(ii) + tmp2*dr2dx(ii)
1322 force(ii, 2, sf) = tmp*pref_lam*dcosbase2(ii) - tmp1*dr1dx(ii) + tmp3*dr3dx(ii)
1323 force(ii, 3, sf) = tmp*pref_lam*dcosbase3(ii) - tmp2*dr2dx(ii) - tmp3*dr3dx(ii)
1328 END SUBROUTINE nnp_calc_ang
1340 CHARACTER(len=2),
DIMENSION(:),
INTENT(INOUT) :: ele
1341 INTEGER,
DIMENSION(:),
INTENT(INOUT) :: nuc_ele
1343 CHARACTER(len=2) :: tmp_ele
1344 INTEGER :: i, j, loc, minimum, tmp_nuc_ele
1347 CALL get_ptable_info(ele(i), number=nuc_ele(i))
1350 DO i = 1,
SIZE(ele) - 1
1351 minimum = nuc_ele(i)
1353 DO j = i + 1,
SIZE(ele)
1354 IF (nuc_ele(j) < minimum)
THEN
1356 minimum = nuc_ele(j)
1359 tmp_nuc_ele = nuc_ele(i)
1360 nuc_ele(i) = nuc_ele(loc)
1361 nuc_ele(loc) = tmp_nuc_ele
1379 TYPE(nnp_type),
INTENT(INOUT) :: nnp
1381 INTEGER :: i, j, k, loc
1384 DO j = 1, nnp%n_rad(i) - 1
1386 DO k = j + 1, nnp%n_rad(i)
1387 IF (nnp%rad(i)%funccut(loc) > nnp%rad(i)%funccut(k))
THEN
1391 CALL nnp_swaprad(nnp%rad(i), j, loc)
1394 DO j = 1, nnp%n_rad(i) - 1
1396 DO k = j + 1, nnp%n_rad(i)
1397 IF (nnp%rad(i)%funccut(loc) == nnp%rad(i)%funccut(k) .AND. &
1398 nnp%rad(i)%eta(loc) > nnp%rad(i)%eta(k))
THEN
1402 CALL nnp_swaprad(nnp%rad(i), j, loc)
1405 DO j = 1, nnp%n_rad(i) - 1
1407 DO k = j + 1, nnp%n_rad(i)
1408 IF (nnp%rad(i)%funccut(loc) == nnp%rad(i)%funccut(k) .AND. &
1409 nnp%rad(i)%eta(loc) == nnp%rad(i)%eta(k) .AND. &
1410 nnp%rad(i)%rs(loc) > nnp%rad(i)%rs(k))
THEN
1414 CALL nnp_swaprad(nnp%rad(i), j, loc)
1417 DO j = 1, nnp%n_rad(i) - 1
1419 DO k = j + 1, nnp%n_rad(i)
1420 IF (nnp%rad(i)%funccut(loc) == nnp%rad(i)%funccut(k) .AND. &
1421 nnp%rad(i)%eta(loc) == nnp%rad(i)%eta(k) .AND. &
1422 nnp%rad(i)%rs(loc) == nnp%rad(i)%rs(k) .AND. &
1423 nnp%rad(i)%nuc_ele(loc) > nnp%rad(i)%nuc_ele(k))
THEN
1427 CALL nnp_swaprad(nnp%rad(i), j, loc)
1430 DO j = 1, nnp%n_ang(i) - 1
1432 DO k = j + 1, nnp%n_ang(i)
1433 IF (nnp%ang(i)%funccut(loc) > nnp%ang(i)%funccut(k))
THEN
1437 CALL nnp_swapang(nnp%ang(i), j, loc)
1440 DO j = 1, nnp%n_ang(i) - 1
1442 DO k = j + 1, nnp%n_ang(i)
1443 IF (nnp%ang(i)%funccut(loc) == nnp%ang(i)%funccut(k) .AND. &
1444 nnp%ang(i)%eta(loc) > nnp%ang(i)%eta(k))
THEN
1448 CALL nnp_swapang(nnp%ang(i), j, loc)
1451 DO j = 1, nnp%n_ang(i) - 1
1453 DO k = j + 1, nnp%n_ang(i)
1454 IF (nnp%ang(i)%funccut(loc) == nnp%ang(i)%funccut(k) .AND. &
1455 nnp%ang(i)%eta(loc) == nnp%ang(i)%eta(k) .AND. &
1456 nnp%ang(i)%zeta(loc) > nnp%ang(i)%zeta(k))
THEN
1460 CALL nnp_swapang(nnp%ang(i), j, loc)
1463 DO j = 1, nnp%n_ang(i) - 1
1465 DO k = j + 1, nnp%n_ang(i)
1466 IF (nnp%ang(i)%funccut(loc) == nnp%ang(i)%funccut(k) .AND. &
1467 nnp%ang(i)%eta(loc) == nnp%ang(i)%eta(k) .AND. &
1468 nnp%ang(i)%zeta(loc) == nnp%ang(i)%zeta(k) .AND. &
1469 nnp%ang(i)%lam(loc) > nnp%ang(i)%lam(k))
THEN
1473 CALL nnp_swapang(nnp%ang(i), j, loc)
1476 DO j = 1, nnp%n_ang(i) - 1
1478 DO k = j + 1, nnp%n_ang(i)
1479 IF (nnp%ang(i)%funccut(loc) == nnp%ang(i)%funccut(k) .AND. &
1480 nnp%ang(i)%eta(loc) == nnp%ang(i)%eta(k) .AND. &
1481 nnp%ang(i)%zeta(loc) == nnp%ang(i)%zeta(k) .AND. &
1482 nnp%ang(i)%lam(loc) == nnp%ang(i)%lam(k) .AND. &
1483 nnp%ang(i)%nuc_ele1(loc) > nnp%ang(i)%nuc_ele1(k))
THEN
1487 CALL nnp_swapang(nnp%ang(i), j, loc)
1490 DO j = 1, nnp%n_ang(i) - 1
1492 DO k = j + 1, nnp%n_ang(i)
1493 IF (nnp%ang(i)%funccut(loc) == nnp%ang(i)%funccut(k) .AND. &
1494 nnp%ang(i)%eta(loc) == nnp%ang(i)%eta(k) .AND. &
1495 nnp%ang(i)%zeta(loc) == nnp%ang(i)%zeta(k) .AND. &
1496 nnp%ang(i)%lam(loc) == nnp%ang(i)%lam(k) .AND. &
1497 nnp%ang(i)%nuc_ele1(loc) == nnp%ang(i)%nuc_ele1(k) .AND. &
1498 nnp%ang(i)%nuc_ele2(loc) > nnp%ang(i)%nuc_ele2(k))
THEN
1502 CALL nnp_swapang(nnp%ang(i), j, loc)
1516 SUBROUTINE nnp_swaprad(rad, i, j)
1517 TYPE(nnp_acsf_rad_type),
INTENT(INOUT) :: rad
1518 INTEGER,
INTENT(IN) :: i, j
1520 CHARACTER(len=2) :: tmpc
1522 REAL(kind=dp) :: tmpr
1524 tmpr = rad%funccut(i)
1525 rad%funccut(i) = rad%funccut(j)
1526 rad%funccut(j) = tmpr
1529 rad%eta(i) = rad%eta(j)
1533 rad%rs(i) = rad%rs(j)
1537 rad%ele(i) = rad%ele(j)
1540 tmpi = rad%nuc_ele(i)
1541 rad%nuc_ele(i) = rad%nuc_ele(j)
1542 rad%nuc_ele(j) = tmpi
1544 END SUBROUTINE nnp_swaprad
1554 SUBROUTINE nnp_swapang(ang, i, j)
1555 TYPE(nnp_acsf_ang_type),
INTENT(INOUT) :: ang
1556 INTEGER,
INTENT(IN) :: i, j
1558 CHARACTER(len=2) :: tmpc
1560 REAL(kind=dp) :: tmpr
1562 tmpr = ang%funccut(i)
1563 ang%funccut(i) = ang%funccut(j)
1564 ang%funccut(j) = tmpr
1567 ang%eta(i) = ang%eta(j)
1571 ang%zeta(i) = ang%zeta(j)
1574 tmpr = ang%prefzeta(i)
1575 ang%prefzeta(i) = ang%prefzeta(j)
1576 ang%prefzeta(j) = tmpr
1579 ang%lam(i) = ang%lam(j)
1583 ang%ele1(i) = ang%ele1(j)
1586 tmpi = ang%nuc_ele1(i)
1587 ang%nuc_ele1(i) = ang%nuc_ele1(j)
1588 ang%nuc_ele1(j) = tmpi
1591 ang%ele2(i) = ang%ele2(j)
1594 tmpi = ang%nuc_ele2(i)
1595 ang%nuc_ele2(i) = ang%nuc_ele2(j)
1596 ang%nuc_ele2(j) = tmpi
1598 END SUBROUTINE nnp_swapang
1612 TYPE(nnp_type),
INTENT(INOUT) :: nnp
1614 INTEGER :: ang, i, izeta_tmp, j, k, m, n_symf, rad, &
1616 REAL(kind=dp) :: eta_tmp, funccut, zeta_tmp
1619 nnp%rad(i)%n_symfgrp = 0
1620 nnp%ang(i)%n_symfgrp = 0
1623 DO s = 1, nnp%n_rad(i)
1624 IF (nnp%rad(i)%ele(s) == nnp%ele(j))
THEN
1625 IF (abs(nnp%rad(i)%funccut(s) - funccut) > cutoff_eq_tol)
THEN
1626 nnp%rad(i)%n_symfgrp = nnp%rad(i)%n_symfgrp + 1
1627 funccut = nnp%rad(i)%funccut(s)
1635 DO s = 1, nnp%n_ang(i)
1636 IF ((nnp%ang(i)%ele1(s) == nnp%ele(j) .AND. &
1637 nnp%ang(i)%ele2(s) == nnp%ele(k)) .OR. &
1638 (nnp%ang(i)%ele1(s) == nnp%ele(k) .AND. &
1639 nnp%ang(i)%ele2(s) == nnp%ele(j)))
THEN
1640 IF (abs(nnp%ang(i)%funccut(s) - funccut) > cutoff_eq_tol)
THEN
1641 nnp%ang(i)%n_symfgrp = nnp%ang(i)%n_symfgrp + 1
1642 funccut = nnp%ang(i)%funccut(s)
1651 ALLOCATE (nnp%rad(i)%symfgrp(nnp%rad(i)%n_symfgrp))
1652 ALLOCATE (nnp%ang(i)%symfgrp(nnp%ang(i)%n_symfgrp))
1653 DO j = 1, nnp%rad(i)%n_symfgrp
1654 nnp%rad(i)%symfgrp(j)%n_symf = 0
1656 DO j = 1, nnp%ang(i)%n_symfgrp
1657 nnp%ang(i)%symfgrp(j)%n_symf = 0
1666 DO s = 1, nnp%n_rad(i)
1667 IF (nnp%rad(i)%ele(s) == nnp%ele(j))
THEN
1668 IF (abs(nnp%rad(i)%funccut(s) - funccut) > cutoff_eq_tol)
THEN
1670 funccut = nnp%rad(i)%funccut(s)
1671 nnp%rad(i)%symfgrp(rad)%cutoff = funccut
1672 ALLOCATE (nnp%rad(i)%symfgrp(rad)%ele(1))
1673 ALLOCATE (nnp%rad(i)%symfgrp(rad)%ele_ind(1))
1674 nnp%rad(i)%symfgrp(rad)%ele(1) = nnp%ele(j)
1675 nnp%rad(i)%symfgrp(rad)%ele_ind(1) = j
1677 nnp%rad(i)%symfgrp(rad)%n_symf = nnp%rad(i)%symfgrp(rad)%n_symf + 1
1684 DO s = 1, nnp%n_ang(i)
1685 IF ((nnp%ang(i)%ele1(s) == nnp%ele(j) .AND. &
1686 nnp%ang(i)%ele2(s) == nnp%ele(k)) .OR. &
1687 (nnp%ang(i)%ele1(s) == nnp%ele(k) .AND. &
1688 nnp%ang(i)%ele2(s) == nnp%ele(j)))
THEN
1689 IF (abs(nnp%ang(i)%funccut(s) - funccut) > cutoff_eq_tol)
THEN
1691 funccut = nnp%ang(i)%funccut(s)
1692 nnp%ang(i)%symfgrp(ang)%cutoff = funccut
1693 ALLOCATE (nnp%ang(i)%symfgrp(ang)%ele(2))
1694 ALLOCATE (nnp%ang(i)%symfgrp(ang)%ele_ind(2))
1695 nnp%ang(i)%symfgrp(ang)%ele(1) = nnp%ele(j)
1696 nnp%ang(i)%symfgrp(ang)%ele(2) = nnp%ele(k)
1697 nnp%ang(i)%symfgrp(ang)%ele_ind(1) = j
1698 nnp%ang(i)%symfgrp(ang)%ele_ind(2) = k
1700 nnp%ang(i)%symfgrp(ang)%n_symf = nnp%ang(i)%symfgrp(ang)%n_symf + 1
1708 DO j = 1, nnp%rad(i)%n_symfgrp
1709 ALLOCATE (nnp%rad(i)%symfgrp(j)%symf(nnp%rad(i)%symfgrp(j)%n_symf))
1711 DO s = 1, nnp%n_rad(i)
1712 IF (nnp%rad(i)%ele(s) == nnp%rad(i)%symfgrp(j)%ele(1))
THEN
1713 IF (abs(nnp%rad(i)%funccut(s) - nnp%rad(i)%symfgrp(j)%cutoff) <= cutoff_eq_tol)
THEN
1715 nnp%rad(i)%symfgrp(j)%symf(rad) = s
1720 DO j = 1, nnp%ang(i)%n_symfgrp
1721 ALLOCATE (nnp%ang(i)%symfgrp(j)%symf(nnp%ang(i)%symfgrp(j)%n_symf))
1723 DO s = 1, nnp%n_ang(i)
1724 IF ((nnp%ang(i)%ele1(s) == nnp%ang(i)%symfgrp(j)%ele(1) .AND. &
1725 nnp%ang(i)%ele2(s) == nnp%ang(i)%symfgrp(j)%ele(2)) .OR. &
1726 (nnp%ang(i)%ele1(s) == nnp%ang(i)%symfgrp(j)%ele(2) .AND. &
1727 nnp%ang(i)%ele2(s) == nnp%ang(i)%symfgrp(j)%ele(1)))
THEN
1728 IF (abs(nnp%ang(i)%funccut(s) - nnp%ang(i)%symfgrp(j)%cutoff) <= cutoff_eq_tol)
THEN
1730 nnp%ang(i)%symfgrp(j)%symf(ang) = s
1745 DO j = 1, nnp%ang(i)%n_symfgrp
1746 n_symf = nnp%ang(i)%symfgrp(j)%n_symf
1747 ALLOCATE (nnp%ang(i)%symfgrp(j)%pack_eta(n_symf))
1748 ALLOCATE (nnp%ang(i)%symfgrp(j)%pack_zeta(n_symf))
1749 ALLOCATE (nnp%ang(i)%symfgrp(j)%pack_lam(n_symf))
1750 ALLOCATE (nnp%ang(i)%symfgrp(j)%pack_prefzeta(n_symf))
1751 ALLOCATE (nnp%ang(i)%symfgrp(j)%pack_izeta(n_symf))
1752 ALLOCATE (nnp%ang(i)%symfgrp(j)%pack_use_int_zeta(n_symf))
1754 m = nnp%ang(i)%symfgrp(j)%symf(sf)
1755 eta_tmp = nnp%ang(i)%eta(m)
1756 zeta_tmp = nnp%ang(i)%zeta(m)
1757 nnp%ang(i)%symfgrp(j)%pack_eta(sf) = eta_tmp
1758 nnp%ang(i)%symfgrp(j)%pack_zeta(sf) = zeta_tmp
1759 nnp%ang(i)%symfgrp(j)%pack_lam(sf) = nnp%ang(i)%lam(m)
1760 nnp%ang(i)%symfgrp(j)%pack_prefzeta(sf) = nnp%ang(i)%prefzeta(m)
1761 izeta_tmp = nint(zeta_tmp)
1762 nnp%ang(i)%symfgrp(j)%pack_izeta(sf) = izeta_tmp
1763 nnp%ang(i)%symfgrp(j)%pack_use_int_zeta(sf) = &
1764 (real(izeta_tmp, dp) == zeta_tmp)
1782 TYPE(nnp_type),
INTENT(INOUT) :: nnp
1783 TYPE(mp_para_env_type),
POINTER :: para_env
1784 CHARACTER(LEN=*),
INTENT(IN) :: printtag
1786 CHARACTER(len=default_string_length) :: my_label
1787 INTEGER :: i, j, unit_nr
1788 TYPE(cp_logger_type),
POINTER :: logger
1791 logger => cp_get_default_logger()
1793 my_label = trim(printtag)//
"| "
1794 IF (para_env%is_source())
THEN
1795 unit_nr = cp_logger_get_default_unit_nr(logger)
1796 WRITE (unit_nr,
'(1X,A,1X,10(I2,1X))') trim(my_label)//
" Activation functions:", nnp%actfnct(:)
1798 WRITE (unit_nr, *) trim(my_label)//
" short range atomic symmetry functions element "// &
1800 DO j = 1, nnp%n_rad(i)
1801 WRITE (unit_nr,
'(1X,A,1X,I3,1X,A2,1X,I2,1X,A2,11X,3(F6.3,1X))') trim(my_label), j, nnp%ele(i), 2, &
1802 nnp%rad(i)%ele(j), nnp%rad(i)%eta(j), &
1803 nnp%rad(i)%rs(j), nnp%rad(i)%funccut(j)
1805 DO j = 1, nnp%n_ang(i)
1806 WRITE (unit_nr,
'(1X,A,1X,I3,1X,A2,1X,I2,2(1X,A2),1X,4(F6.3,1X))') &
1807 trim(my_label), j, nnp%ele(i), 3, &
1808 nnp%ang(i)%ele1(j), nnp%ang(i)%ele2(j), &
1809 nnp%ang(i)%eta(j), nnp%ang(i)%lam(j), &
1810 nnp%ang(i)%zeta(j), nnp%ang(i)%funccut(j)
various routines to log and control the output. The idea is that decisions about where to log should ...
recursive integer function, public cp_logger_get_default_unit_nr(logger, local, skip_not_ionode)
asks the default unit number of the given logger. try to use cp_logger_get_unit_nr
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
Definition of mathematical constants and functions.
real(kind=dp), parameter, public pi
Interface to the message passing library MPI.
Functionality for atom centered symmetry functions for neural network potentials.
subroutine, public nnp_calc_acsf(nnp, i, calc_forces, arc, stress)
Calculate atom centered symmetry functions for given atom i.
subroutine, public nnp_write_acsf(nnp, para_env, printtag)
Print a summary of the active symmetry-function set on the source rank. Emits one line per element li...
subroutine, public nnp_init_acsf_groups(nnp)
Pack symmetry functions into groups that share input parameters. Builds nnprad(i)symfgrp(:) and nnpan...
subroutine, public nnp_prepare_neighbor_cache(nnp)
Prepare or update the linked-cell / Verlet cache for the current geometry. Lazily allocates nnpcell_l...
subroutine, public nnp_sort_acsf(nnp)
Sort radial and angular symmetry functions in canonical order. Radial SFs are sorted by eta (ascendin...
subroutine, public nnp_sort_ele(ele, nuc_ele)
Sort an (ele, nuc_ele) pair of arrays in ascending order of atomic number. Used to canonicalise eleme...
Linked-cell neighbour finder with a Verlet skin for the NNP descriptor. Owns the per-nnp cell-list ca...
subroutine, public nnp_prepare_cell_list_cache(nnp)
Prepare the cell-list cache for the current force evaluation: wrap positions into the primary cell,...
subroutine, public nnp_compute_neighbors_cell_list(nnp, neighbor, i)
Fill the ACSF neighbour buffers for one central atom by walking the linked-cell stencil around its bi...
Data types for neural network potentials.
integer, parameter, public nnp_cut_tanh
integer, parameter, public nnp_cut_cos
derived data types
Per-nnp persistent neighbour-interface state for the NNP hot path. Separates neighbour bookkeeping fr...
subroutine, public nnp_grp_grow_dgdr(grp, n_needed)
Ensure a per-group dG/dr buffer holds n_needed neighbours, growing by 1.5x (with an additive floor) s...
subroutine, public nnp_workspace_grow_caches(workspace, n_needed)
Ensure the four per-element angular cutoff caches hold at least n_needed entries. These 1D scratch ar...
subroutine, public nnp_neighbor_interface_reset_neighbor(nnp, ind)
Reset per-group neighbour counters for one central element before refilling the reusable buffers....
subroutine, public nnp_neighbor_interface_prepare(nnp)
Ensure pair-routing metadata and reusable workspaces are ready for the current NNP model.
Periodic Table related data definitions.
subroutine, public get_ptable_info(symbol, number, amass, ielement, covalent_radius, metallic_radius, vdw_radius, found)
Pass information about the kind given the element symbol.
type of a logger, at the moment it contains just a print level starting at which level it should be l...
stores all the informations relevant to an mpi environment
Set of angular symmetry function type.
Set of radial symmetry function type.
Data type for artificial neural networks.
Symmetry functions group type.
Main data type collecting all relevant data for neural network potentials.