35subroutine lpb_setup(params, constants, workspace, state, phi_cav, &
36 & e_cav, psi, ddx_error)
38 type(ddx_params_type),
intent(in) :: params
39 type(ddx_constants_type),
intent(inout) :: constants
40 type(ddx_workspace_type),
intent(inout) :: workspace
41 type(ddx_state_type),
intent(inout) :: state
42 type(ddx_error_type),
intent(inout) :: ddx_error
43 real(dp),
intent(in) :: phi_cav(constants % ncav)
44 real(dp),
intent(in) :: e_cav(3, constants % ncav)
45 real(dp),
intent(in) :: psi(constants % nbasis, params % nsph)
48 state % rhs_adj_lpb(:, :, 1) = psi
54 call convert_ddcosmo(params, constants, -1, state % rhs_adj_lpb(:,:,1))
55 state % rhs_adj_lpb(:, :, 2) = 0.0d0
60 state % phi_grid = zero
64 call ddcav_to_grid_work(params % ngrid, params % nsph, &
65 & constants % ncav, constants % icav_ia, &
66 & constants % icav_ja, phi_cav, state % phi_grid)
67 workspace % tmp_cav = phi_cav * constants % ui_cav
68 call ddcav_to_grid_work(params % ngrid, params % nsph, &
69 & constants % ncav, constants % icav_ia, &
70 & constants % icav_ja, workspace % tmp_cav, &
71 & workspace % tmp_grid)
72 state % g_lpb = - workspace % tmp_grid
75 state % gradphi_cav = - e_cav
78 call wghpot_f(params, constants, workspace, state % gradphi_cav, &
79 & state % f_lpb, ddx_error)
82 state % rhs_lpb = zero
85 call ddintegrate(params % nsph, constants % nbasis, &
86 & params % ngrid, constants % vwgrid, &
87 & constants % vgrid_nbasis, state % g_lpb, state % rhs_lpb(:,:,1))
88 call ddintegrate(params % nsph, constants % nbasis, &
89 & params % ngrid, constants % vwgrid, &
90 & constants % vgrid_nbasis, state % f_lpb, state % rhs_lpb(:,:,2))
91 state % rhs_lpb(:,:,1) = state % rhs_lpb(:,:,1) + state % rhs_lpb(:,:,2)
93 if (ddx_error % flag .eq. 0)
then
94 state % rhs_done = .true.
95 state % adjoint_rhs_done = .true.
110 type(ddx_constants_type),
intent(in) :: constants
111 type(ddx_state_type),
intent(in) :: state
112 type(ddx_error_type),
intent(inout) :: ddx_error
113 real(dp),
intent(out) :: esolv
114 real(dp),
external :: ddot
117 if (ddx_error % flag .eq. 0)
continue
119 esolv = pt5*ddot(constants % n, state % x_lpb(:,:,1), 1, state % psi, 1)
132subroutine lpb_guess(params, constants, workspace, state, tol, ddx_error)
134 type(ddx_params_type),
intent(in) :: params
135 type(ddx_constants_type),
intent(inout) :: constants
136 type(ddx_workspace_type),
intent(inout) :: workspace
137 type(ddx_state_type),
intent(inout) :: state
138 real(dp),
intent(in) :: tol
139 type(ddx_error_type),
intent(inout) :: ddx_error
142 constants % inner_tol = sqrt(tol)
145 workspace % ddcosmo_guess = zero
146 workspace % hsp_guess = zero
147 call prec_tx(params, constants, workspace, state % rhs_lpb, &
148 & state % x_lpb, ddx_error)
165 type(ddx_params_type),
intent(in) :: params
166 type(ddx_constants_type),
intent(inout) :: constants
167 type(ddx_workspace_type),
intent(inout) :: workspace
168 type(ddx_state_type),
intent(inout) :: state
169 real(dp),
intent(in) :: tol
170 type(ddx_error_type),
intent(inout) :: ddx_error
173 constants % inner_tol = sqrt(tol)
176 workspace % ddcosmo_adj_guess = zero
177 workspace % hsp_adj_guess = zero
178 call prec_tstarx(params, constants, workspace, state % rhs_adj_lpb, &
179 & state % x_adj_lpb, ddx_error)
193subroutine lpb_solve(params, constants, workspace, state, tol, ddx_error)
195 type(ddx_params_type),
intent(in) :: params
196 type(ddx_constants_type),
intent(inout) :: constants
197 type(ddx_workspace_type),
intent(inout) :: workspace
198 type(ddx_state_type),
intent(inout) :: state
199 real(dp),
intent(in) :: tol
200 type(ddx_error_type),
intent(inout) :: ddx_error
201 real(dp) :: start_time
203 state % x_lpb_niter = params % maxiter
204 workspace % xs_time = zero
205 workspace % hsp_time = zero
208 start_time = omp_get_wtime()
209 call jacobi_diis_external(params, constants, workspace, &
210 & 2*constants % n, tol, state % rhs_lpb, state % x_lpb, &
211 & state % x_lpb_niter, state % x_lpb_rel_diff,
cx,
prec_tx, rmsnorm, &
213 if (ddx_error % flag.ne. 0)
then
214 call update_error(ddx_error,
'Jacobi solver failed to converge " // &
218 state % x_lpb_time = omp_get_wtime() - start_time
224 call convert_ddcosmo(params, constants, -1, state % x_lpb(:,:,1))
227 state % xs_time = workspace % xs_time
228 state % hsp_time = workspace % hsp_time
243 type(ddx_params_type),
intent(in) :: params
244 type(ddx_constants_type),
intent(inout) :: constants
245 type(ddx_workspace_type),
intent(inout) :: workspace
246 type(ddx_state_type),
intent(inout) :: state
247 real(dp),
intent(in) :: tol
248 type(ddx_error_type),
intent(inout) :: ddx_error
250 real(dp) :: start_time
252 state % x_adj_lpb_niter = params % maxiter
253 workspace % s_time = zero
254 workspace % hsp_adj_time = zero
257 start_time = omp_get_wtime()
258 call jacobi_diis_external(params, constants, workspace, &
259 & 2*constants % n, tol, state % rhs_adj_lpb, state % x_adj_lpb, &
260 & state % x_adj_lpb_niter, state % x_adj_lpb_rel_diff, &
262 if (ddx_error % flag .ne. 0)
then
263 call update_error(ddx_error,
'Jacobi solver failed to ' // &
264 &
'converge in ddlpb_solve_adjoint')
267 state % x_adj_lpb_time = omp_get_wtime() - start_time
269 state % q = state % x_adj_lpb(:, :, 1)
272 state % s_time = workspace % s_time
273 state % hsp_adj_time = workspace % hsp_adj_time
275 call lpb_derivative_setup(params, constants, workspace, state, ddx_error)
292 & state, hessianphi_cav, force, ddx_error)
294 type(ddx_params_type),
intent(in) :: params
295 type(ddx_constants_type),
intent(in) :: constants
296 type(ddx_workspace_type),
intent(inout) :: workspace
297 type(ddx_state_type),
intent(inout) :: state
298 real(dp),
intent(in) :: hessianphi_cav(3, 3, constants % ncav)
299 real(dp),
intent(out) :: force(3, params % nsph)
300 type(ddx_error_type),
intent(inout) :: ddx_error
303 real(dp),
dimension(constants % nbasis) :: basloc, vplm
304 real(dp),
dimension(3, constants % nbasis) :: dbasloc
305 real(dp),
dimension(params % lmax + 1) :: vsin, vcos
308 real(dp),
allocatable :: normal_hessian_cav(:,:), &
309 & diff_re(:,:), scaled_xr(:,:)
310 integer :: isph, icav, igrid, istat
312 real(dp),
external :: ddot, dnrm2
313 real(dp) :: start_time, finish_time
315 start_time = omp_get_wtime()
316 allocate(normal_hessian_cav(3, constants % ncav), &
317 & diff_re(constants % nbasis, params % nsph), &
318 & scaled_xr(constants % nbasis, params % nsph), stat=istat)
320 call update_error(ddx_error,
'Allocation failed in ddlpb_force_worker')
325 call convert_ddcosmo(params, constants, 1, state % x_lpb(:, :, 1))
336 normal_hessian_cav = zero
338 do isph = 1, params % nsph
339 do igrid = 1, params % ngrid
340 if(constants % ui(igrid, isph) .gt. zero)
then
343 normal_hessian_cav(:, icav) = normal_hessian_cav(:,icav) +&
344 & hessianphi_cav(:,i,icav)*constants % cgrid(i,igrid)
351 scaled_xr = state % x_lpb(:,:,1)
352 call convert_ddcosmo(params, constants, -1, scaled_xr)
357 do isph = 1, params % nsph
359 call contract_grad_l(params, constants, isph, scaled_xr, &
360 & state % x_adj_r_grid, basloc, dbasloc, vplm, vcos, vsin, &
363 call contract_grad_b(params, constants, isph, state % x_lpb(:,:,2), &
364 & state % x_adj_e_grid, force(:, isph))
366 call contract_grad_u(params, constants, isph, state % x_adj_r_grid, &
367 & state % phi_grid, force(:, isph))
371 call contract_grad_c(params, constants, workspace, state % x_lpb(:,:,1), &
372 & state % x_lpb(:,:,2), state % x_adj_r_grid, state % x_adj_e_grid, &
373 & state % x_adj_lpb(:,:,1), state % x_adj_lpb(:,:,2), force, &
374 & diff_re, ddx_error)
375 if (ddx_error % flag .ne. 0)
then
376 call update_error(ddx_error, &
377 &
"contract_grad_C returned an error, exiting")
385 do isph = 1, params % nsph
386 do igrid = 1, params % ngrid
387 if(constants % ui(igrid, isph) .ne. zero)
then
389 state % zeta(icav) = constants % wgrid(igrid) * &
390 & constants % ui(igrid, isph) * ddot(constants % nbasis, &
391 & constants % vgrid(1, igrid), 1, &
392 & state % x_adj_lpb(1, isph, 1), 1)
398 call contract_grad_f(params, constants, workspace, &
399 & state % x_adj_lpb(:,:,1) + state % x_adj_lpb(:,:,2), &
400 & state % x_adj_re_grid, state % gradphi_cav, &
401 & normal_hessian_cav, force, state, ddx_error)
402 if (ddx_error % flag .ne. 0)
then
403 call update_error(ddx_error, &
404 &
"contract_grad_f returned an error, exiting")
410 deallocate(normal_hessian_cav, diff_re, scaled_xr, stat=istat)
412 call update_error(ddx_error,
'Deallocation failed in ddlpb_force_worker')
418 call convert_ddcosmo(params, constants, -1, state % x_lpb(:, :, 1))
424 state % gradphi_cav = - state % gradphi_cav
425 call zeta_grad(params, constants, state, state % gradphi_cav, force)
426 state % gradphi_cav = - state % gradphi_cav
428 finish_time = omp_get_wtime()
429 state % force_time = finish_time - start_time
442subroutine lpb_derivative_setup(params, constants, workspace, state, ddx_error)
444 type(ddx_params_type),
intent(in) :: params
445 type(ddx_constants_type),
intent(in) :: constants
446 type(ddx_workspace_type),
intent(inout) :: workspace
447 type(ddx_state_type),
intent(inout) :: state
448 type(ddx_error_type),
intent(inout) :: ddx_error
450 real(dp),
allocatable :: coefy_d(:, :, :)
451 integer :: istat, jsph, igrid0, icav, isph, igrid, l0, m0, ind0, &
453 real(dp) :: rijn, sum_int, fac
454 real(dp) :: work(constants % lmax0 + 1), coef(constants % nbasis0), &
455 & vij(3), vtij(3), sij(3)
456 complex(dp) :: work_complex(constants % lmax0 + 1)
460 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
461 & constants % nbasis, one, constants % vgrid, &
462 & constants % vgrid_nbasis, state % x_adj_lpb(:, :, 1), &
463 & constants % nbasis, zero, state % x_adj_r_grid, params % ngrid)
464 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
465 & constants % nbasis, one, constants % vgrid, &
466 & constants % vgrid_nbasis, state % x_adj_lpb(:, :, 2), &
467 & constants % nbasis, zero, state % x_adj_e_grid, params % ngrid)
468 state % x_adj_re_grid = state % x_adj_r_grid + state % x_adj_e_grid
470 if (params % fmm .eq. 0)
then
471 allocate(coefy_d(constants % ncav, params % ngrid, params % nsph), &
474 call update_error(ddx_error,
"allocation ddx_error in " // &
475 &
"ddlpb_derivative_setup")
479 do jsph = 1, params % nsph
480 do igrid0 = 1, params % ngrid
482 do isph = 1, params % nsph
483 do igrid = 1, params % ngrid
484 if(constants % ui(igrid, isph) .gt. zero)
then
486 vij = params % csph(:,isph) + params % rsph(isph) &
487 & *constants % cgrid(:,igrid) &
488 & - params % csph(:,jsph)
489 rijn = sqrt(dot_product(vij,vij))
490 if (rijn.ne.zero)
then
495 do l0 = 0, constants % lmax0
497 ind0 = l0**2 + l0 + m0 + 1
499 & constants % vgrid(ind0, igrid0) * &
500 & constants % C_ik(l0, jsph)
503 vtij = vij*params % kappa
504 call fmm_m2p_bessel_work(vtij, constants % lmax0, &
505 & constants % vscales, &
506 & constants % sk_ri(:, jsph), one, &
507 & coef, zero, coefy_d(icav, igrid0, jsph), &
508 & work_complex, work)
514 do jsph = 1, params % nsph
515 do igrid0 = 1, params % ngrid
518 do isph = 1, params % nsph
519 do igrid = 1, params % ngrid
520 if(constants % ui(igrid, isph) .gt. zero)
then
522 sum_int = sum_int + coefy_d(icav, igrid0, jsph) &
523 & *state % x_adj_re_grid(igrid, isph) &
524 & *constants % wgrid(igrid) &
525 & *constants % ui(igrid, isph)
529 state % phi_n(igrid0, jsph) = &
530 & - (params % epsp/params % eps)*sum_int
537 do isph = 1, params % nsph
538 workspace % tmp_grid(:, isph) = state % x_adj_re_grid(:, isph) * &
539 & constants % wgrid(:) * constants % ui(:, isph)
542 call tree_m2p_bessel_adj(params, constants, constants % lmax0, one, &
543 & workspace % tmp_grid, zero, params % lmax, workspace % tmp_sph)
544 call tree_l2p_bessel_adj(params, constants, one, &
545 & workspace % tmp_grid, zero, workspace % tmp_node_l)
546 call tree_l2l_bessel_rotation_adj(params, constants, &
547 & workspace % tmp_node_l)
548 call tree_m2l_bessel_rotation_adj(params, constants, &
549 & workspace % tmp_node_l, workspace % tmp_node_m)
550 call tree_m2m_bessel_rotation_adj(params, constants, &
551 & workspace % tmp_node_m)
553 if(constants % lmax0 .lt. params % pm)
then
554 do isph = 1, params % nsph
555 inode = constants % snode(isph)
556 workspace % tmp_sph(1:constants % nbasis0, isph) = &
557 & workspace % tmp_sph(1:constants % nbasis0, isph) + &
558 & workspace % tmp_node_m(1:constants % nbasis0, inode)
561 indl = (params % pm+1)**2
562 do isph = 1, params % nsph
563 inode = constants % snode(isph)
564 workspace % tmp_sph(1:indl, isph) = &
565 & workspace % tmp_sph(1:indl, isph) + &
566 & workspace % tmp_node_m(:, inode)
570 do isph = 1, params % nsph
571 do l0 = 0, constants % lmax0
572 ind0 = l0*l0 + l0 + 1
573 workspace % tmp_sph(ind0-l0:ind0+l0, isph) = &
574 & workspace % tmp_sph(ind0-l0:ind0+l0, isph) * &
575 & constants % C_ik(l0, isph)
579 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
580 & constants % nbasis0, -params % epsp/params % eps, &
581 & constants % vgrid, constants % vgrid_nbasis, &
582 & workspace % tmp_sph, constants % nbasis, zero, &
583 & state % phi_n, params % ngrid)
588 do isph = 1, params % nsph
589 do igrid = 1, params % ngrid
590 if (constants % ui(igrid, isph) .gt. zero)
then
592 fac = - constants % ui(igrid, isph)*constants % wgrid(igrid) &
593 & *state % phi_n(igrid, isph)
594 state % zeta_dip(1, icav) = fac*constants % cgrid(1, igrid)
595 state % zeta_dip(2, icav) = fac*constants % cgrid(2, igrid)
596 state % zeta_dip(3, icav) = fac*constants % cgrid(3, igrid)
601 if (
allocated(coefy_d))
then
602 deallocate(coefy_d, stat=istat)
604 call update_error(ddx_error, &
605 &
"deallocation ddx_error in ddlpb_derivative_setup")
610end subroutine lpb_derivative_setup
subroutine lpb_solve(params, constants, workspace, state, tol, ddx_error)
Solve the ddLPB primal linear system.
subroutine lpb_energy(constants, state, esolv, ddx_error)
Compute the ddLPB energy.
subroutine lpb_setup(params, constants, workspace, state, phi_cav, e_cav, psi, ddx_error)
Given the potential and the electric field at the cavity points, assemble the RHS for ddLPB.
subroutine lpb_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
Solve the adjoint ddLPB linear system.
subroutine lpb_guess_adjoint(params, constants, workspace, state, tol, ddx_error)
Do a guess for the adjoint ddLPB linear system.
subroutine lpb_guess(params, constants, workspace, state, tol, ddx_error)
Do a guess for the primal ddLPB linear system.
subroutine lpb_solvation_force_terms(params, constants, workspace, state, hessianphi_cav, force, ddx_error)
Compute the solvation terms of the forces (solute aspecific). This must be summed to the solute speci...
High-level subroutines for ddlpb.
Operators shared among ddX methods.
subroutine prec_tx(params, constants, workspace, x, y, ddx_error)
Apply the preconditioner to the primal ddLPB linear system |Yr| = |A^-1 0 |*|Xr| |Ye| |0 B^-1 | |Xe|.
subroutine cstarx(params, constants, workspace, x, y, ddx_error)
ddLPB adjoint matrix-vector product
subroutine cx(params, constants, workspace, x, y, ddx_error)
ddLPB matrix-vector product
subroutine prec_tstarx(params, constants, workspace, x, y, ddx_error)
Apply the preconditioner to the ddLPB adjoint linear system.