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)
105 type(ddx_constants_type),
intent(in) :: constants
106 type(ddx_state_type),
intent(in) :: state
107 type(ddx_error_type),
intent(inout) :: ddx_error
108 real(dp),
intent(out) :: esolv
109 real(dp),
external :: ddot
112 if (ddx_error % flag .eq. 0)
continue
114 esolv = pt5*ddot(constants % n, state % x_lpb(:,:,1), 1, state % psi, 1)
127subroutine lpb_guess(params, constants, workspace, state, tol, ddx_error)
129 type(ddx_params_type),
intent(in) :: params
130 type(ddx_constants_type),
intent(inout) :: constants
131 type(ddx_workspace_type),
intent(inout) :: workspace
132 type(ddx_state_type),
intent(inout) :: state
133 real(dp),
intent(in) :: tol
134 type(ddx_error_type),
intent(inout) :: ddx_error
137 constants % inner_tol = sqrt(tol)
140 workspace % ddcosmo_guess = zero
141 workspace % hsp_guess = zero
142 call prec_tx(params, constants, workspace, state % rhs_lpb, &
143 & state % x_lpb, ddx_error)
160 type(ddx_params_type),
intent(in) :: params
161 type(ddx_constants_type),
intent(inout) :: constants
162 type(ddx_workspace_type),
intent(inout) :: workspace
163 type(ddx_state_type),
intent(inout) :: state
164 real(dp),
intent(in) :: tol
165 type(ddx_error_type),
intent(inout) :: ddx_error
168 constants % inner_tol = sqrt(tol)
171 workspace % ddcosmo_guess = zero
172 workspace % hsp_guess = zero
173 call prec_tstarx(params, constants, workspace, state % rhs_adj_lpb, &
174 & state % x_adj_lpb, ddx_error)
188subroutine lpb_solve(params, constants, workspace, state, tol, ddx_error)
190 type(ddx_params_type),
intent(in) :: params
191 type(ddx_constants_type),
intent(inout) :: constants
192 type(ddx_workspace_type),
intent(inout) :: workspace
193 type(ddx_state_type),
intent(inout) :: state
194 real(dp),
intent(in) :: tol
195 type(ddx_error_type),
intent(inout) :: ddx_error
196 real(dp) :: start_time
198 state % x_lpb_niter = params % maxiter
199 workspace % xs_time = zero
200 workspace % hsp_time = zero
203 start_time = omp_get_wtime()
204 call jacobi_diis_external(params, constants, workspace, &
205 & 2*constants % n, tol, state % rhs_lpb, state % x_lpb, &
206 & state % x_lpb_niter, state % x_lpb_rel_diff,
cx,
prec_tx, rmsnorm, &
208 if (ddx_error % flag.ne. 0)
then
209 call update_error(ddx_error,
'Jacobi solver failed to converge " // &
213 state % x_lpb_time = omp_get_wtime() - start_time
219 call convert_ddcosmo(params, constants, -1, state % x_lpb(:,:,1))
222 state % xs_time = workspace % xs_time
223 state % hsp_time = workspace % hsp_time
238 type(ddx_params_type),
intent(in) :: params
239 type(ddx_constants_type),
intent(inout) :: constants
240 type(ddx_workspace_type),
intent(inout) :: workspace
241 type(ddx_state_type),
intent(inout) :: state
242 real(dp),
intent(in) :: tol
243 type(ddx_error_type),
intent(inout) :: ddx_error
245 real(dp) :: start_time
247 state % x_adj_lpb_niter = params % maxiter
248 workspace % s_time = zero
249 workspace % hsp_adj_time = zero
252 start_time = omp_get_wtime()
253 call jacobi_diis_external(params, constants, workspace, &
254 & 2*constants % n, tol, state % rhs_adj_lpb, state % x_adj_lpb, &
255 & state % x_adj_lpb_niter, state % x_adj_lpb_rel_diff, &
257 if (ddx_error % flag .ne. 0)
then
258 call update_error(ddx_error,
'Jacobi solver failed to ' // &
259 &
'converge in ddlpb_solve_adjoint')
262 state % x_adj_lpb_time = omp_get_wtime() - start_time
264 state % q = state % x_adj_lpb(:, :, 1)
267 state % s_time = workspace % s_time
268 state % hsp_adj_time = workspace % hsp_adj_time
270 call lpb_derivative_setup(params, constants, workspace, state, ddx_error)
287 & state, hessianphi_cav, force, ddx_error)
289 type(ddx_params_type),
intent(in) :: params
290 type(ddx_constants_type),
intent(in) :: constants
291 type(ddx_workspace_type),
intent(inout) :: workspace
292 type(ddx_state_type),
intent(inout) :: state
293 real(dp),
intent(in) :: hessianphi_cav(3, 3, constants % ncav)
294 real(dp),
intent(out) :: force(3, params % nsph)
295 type(ddx_error_type),
intent(inout) :: ddx_error
298 real(dp),
dimension(constants % nbasis) :: basloc, vplm
299 real(dp),
dimension(3, constants % nbasis) :: dbasloc
300 real(dp),
dimension(params % lmax + 1) :: vsin, vcos
303 real(dp),
allocatable :: normal_hessian_cav(:,:), &
304 & diff_re(:,:), scaled_xr(:,:)
305 integer :: isph, icav, igrid, istat
307 real(dp),
external :: ddot, dnrm2
308 real(dp) :: start_time, finish_time
310 start_time = omp_get_wtime()
311 allocate(normal_hessian_cav(3, constants % ncav), &
312 & diff_re(constants % nbasis, params % nsph), &
313 & scaled_xr(constants % nbasis, params % nsph), stat=istat)
315 call update_error(ddx_error,
'Allocation failed in ddlpb_force_worker')
320 call convert_ddcosmo(params, constants, 1, state % x_lpb(:, :, 1))
331 normal_hessian_cav = zero
333 do isph = 1, params % nsph
334 do igrid = 1, params % ngrid
335 if(constants % ui(igrid, isph) .gt. zero)
then
338 normal_hessian_cav(:, icav) = normal_hessian_cav(:,icav) +&
339 & hessianphi_cav(:,i,icav)*constants % cgrid(i,igrid)
346 scaled_xr = state % x_lpb(:,:,1)
347 call convert_ddcosmo(params, constants, -1, scaled_xr)
352 do isph = 1, params % nsph
354 call contract_grad_l(params, constants, isph, scaled_xr, &
355 & state % x_adj_r_grid, basloc, dbasloc, vplm, vcos, vsin, &
358 call contract_grad_b(params, constants, isph, state % x_lpb(:,:,2), &
359 & state % x_adj_e_grid, force(:, isph))
361 call contract_grad_u(params, constants, isph, state % x_adj_r_grid, &
362 & state % phi_grid, force(:, isph))
366 call contract_grad_c(params, constants, workspace, state % x_lpb(:,:,1), &
367 & state % x_lpb(:,:,2), state % x_adj_r_grid, state % x_adj_e_grid, &
368 & state % x_adj_lpb(:,:,1), state % x_adj_lpb(:,:,2), force, &
369 & diff_re, ddx_error)
370 if (ddx_error % flag .ne. 0)
then
371 call update_error(ddx_error, &
372 &
"contract_grad_C returned an error, exiting")
380 do isph = 1, params % nsph
381 do igrid = 1, params % ngrid
382 if(constants % ui(igrid, isph) .ne. zero)
then
384 state % zeta(icav) = constants % wgrid(igrid) * &
385 & constants % ui(igrid, isph) * ddot(constants % nbasis, &
386 & constants % vgrid(1, igrid), 1, &
387 & state % x_adj_lpb(1, isph, 1), 1)
393 call contract_grad_f(params, constants, workspace, &
394 & state % x_adj_lpb(:,:,1) + state % x_adj_lpb(:,:,2), &
395 & state % x_adj_re_grid, state % gradphi_cav, &
396 & normal_hessian_cav, force, state, ddx_error)
397 if (ddx_error % flag .ne. 0)
then
398 call update_error(ddx_error, &
399 &
"contract_grad_f returned an error, exiting")
405 deallocate(normal_hessian_cav, diff_re, scaled_xr, stat=istat)
407 call update_error(ddx_error,
'Deallocation failed in ddlpb_force_worker')
413 call convert_ddcosmo(params, constants, -1, state % x_lpb(:, :, 1))
419 state % gradphi_cav = - state % gradphi_cav
420 call zeta_grad(params, constants, state, state % gradphi_cav, force)
421 state % gradphi_cav = - state % gradphi_cav
423 finish_time = omp_get_wtime()
424 state % force_time = finish_time - start_time
437subroutine lpb_derivative_setup(params, constants, workspace, state, ddx_error)
439 type(ddx_params_type),
intent(in) :: params
440 type(ddx_constants_type),
intent(in) :: constants
441 type(ddx_workspace_type),
intent(inout) :: workspace
442 type(ddx_state_type),
intent(inout) :: state
443 type(ddx_error_type),
intent(inout) :: ddx_error
445 real(dp),
allocatable :: coefy_d(:, :, :)
446 integer :: istat, jsph, igrid0, icav, isph, igrid, l0, m0, ind0, &
448 real(dp) :: rijn, sum_int, fac
449 real(dp) :: work(constants % lmax0 + 1), coef(constants % nbasis0), &
450 & vij(3), vtij(3), sij(3)
451 complex(dp) :: work_complex(constants % lmax0 + 1)
455 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
456 & constants % nbasis, one, constants % vgrid, &
457 & constants % vgrid_nbasis, state % x_adj_lpb(:, :, 1), &
458 & constants % nbasis, zero, state % x_adj_r_grid, params % ngrid)
459 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
460 & constants % nbasis, one, constants % vgrid, &
461 & constants % vgrid_nbasis, state % x_adj_lpb(:, :, 2), &
462 & constants % nbasis, zero, state % x_adj_e_grid, params % ngrid)
463 state % x_adj_re_grid = state % x_adj_r_grid + state % x_adj_e_grid
465 if (params % fmm .eq. 0)
then
466 allocate(coefy_d(constants % ncav, params % ngrid, params % nsph), &
469 call update_error(ddx_error,
"allocation ddx_error in " // &
470 &
"ddlpb_derivative_setup")
474 do jsph = 1, params % nsph
475 do igrid0 = 1, params % ngrid
477 do isph = 1, params % nsph
478 do igrid = 1, params % ngrid
479 if(constants % ui(igrid, isph) .gt. zero)
then
481 vij = params % csph(:,isph) + params % rsph(isph) &
482 & *constants % cgrid(:,igrid) &
483 & - params % csph(:,jsph)
484 rijn = sqrt(dot_product(vij,vij))
485 if (rijn.ne.zero)
then
490 do l0 = 0, constants % lmax0
492 ind0 = l0**2 + l0 + m0 + 1
494 & constants % vgrid(ind0, igrid0) * &
495 & constants % C_ik(l0, jsph)
498 vtij = vij*params % kappa
499 call fmm_m2p_bessel_work(vtij, constants % lmax0, &
500 & constants % vscales, &
501 & constants % sk_ri(:, jsph), one, &
502 & coef, zero, coefy_d(icav, igrid0, jsph), &
503 & work_complex, work)
509 do jsph = 1, params % nsph
510 do igrid0 = 1, params % ngrid
513 do isph = 1, params % nsph
514 do igrid = 1, params % ngrid
515 if(constants % ui(igrid, isph) .gt. zero)
then
517 sum_int = sum_int + coefy_d(icav, igrid0, jsph) &
518 & *state % x_adj_re_grid(igrid, isph) &
519 & *constants % wgrid(igrid) &
520 & *constants % ui(igrid, isph)
524 state % phi_n(igrid0, jsph) = &
525 & - (params % epsp/params % eps)*sum_int
532 do isph = 1, params % nsph
533 workspace % tmp_grid(:, isph) = state % x_adj_re_grid(:, isph) * &
534 & constants % wgrid(:) * constants % ui(:, isph)
537 call tree_m2p_bessel_adj(params, constants, constants % lmax0, one, &
538 & workspace % tmp_grid, zero, params % lmax, workspace % tmp_sph)
539 call tree_l2p_bessel_adj(params, constants, one, &
540 & workspace % tmp_grid, zero, workspace % tmp_node_l)
541 call tree_l2l_bessel_rotation_adj(params, constants, &
542 & workspace % tmp_node_l)
543 call tree_m2l_bessel_rotation_adj(params, constants, &
544 & workspace % tmp_node_l, workspace % tmp_node_m)
545 call tree_m2m_bessel_rotation_adj(params, constants, &
546 & workspace % tmp_node_m)
548 if(constants % lmax0 .lt. params % pm)
then
549 do isph = 1, params % nsph
550 inode = constants % snode(isph)
551 workspace % tmp_sph(1:constants % nbasis0, isph) = &
552 & workspace % tmp_sph(1:constants % nbasis0, isph) + &
553 & workspace % tmp_node_m(1:constants % nbasis0, inode)
556 indl = (params % pm+1)**2
557 do isph = 1, params % nsph
558 inode = constants % snode(isph)
559 workspace % tmp_sph(1:indl, isph) = &
560 & workspace % tmp_sph(1:indl, isph) + &
561 & workspace % tmp_node_m(:, inode)
565 do isph = 1, params % nsph
566 do l0 = 0, constants % lmax0
567 ind0 = l0*l0 + l0 + 1
568 workspace % tmp_sph(ind0-l0:ind0+l0, isph) = &
569 & workspace % tmp_sph(ind0-l0:ind0+l0, isph) * &
570 & constants % C_ik(l0, isph)
574 call dgemm(
'T',
'N', params % ngrid, params % nsph, &
575 & constants % nbasis0, -params % epsp/params % eps, &
576 & constants % vgrid, constants % vgrid_nbasis, &
577 & workspace % tmp_sph, constants % nbasis, zero, &
578 & state % phi_n, params % ngrid)
583 do isph = 1, params % nsph
584 do igrid = 1, params % ngrid
585 if (constants % ui(igrid, isph) .gt. zero)
then
587 fac = - constants % ui(igrid, isph)*constants % wgrid(igrid) &
588 & *state % phi_n(igrid, isph)
589 state % zeta_dip(1, icav) = fac*constants % cgrid(1, igrid)
590 state % zeta_dip(2, icav) = fac*constants % cgrid(2, igrid)
591 state % zeta_dip(3, icav) = fac*constants % cgrid(3, igrid)
596 if (
allocated(coefy_d))
then
597 deallocate(coefy_d, stat=istat)
599 call update_error(ddx_error, &
600 &
"deallocation ddx_error in ddlpb_derivative_setup")
605end 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.