ddx 1.0.0
Libary for domain-decomposition methods for polarizable continuum models
ddx.f90
1
2module ddx
3! Get ddcosmo-module
4use ddx_cosmo
5! Get ddpcm-module
6use ddx_pcm
7! Get ddlpb-module
8use ddx_lpb
9
11implicit none
12
13contains
14
16
55subroutine ddinit(model, nsph, coords, radii, eps, ddx_data, ddx_error, &
56 & force, kappa, eta, shift, lmax, ngrid, incore, maxiter, &
57 & jacobi_ndiis, enable_fmm, pm, pl, nproc, logfile, adjoint, &
58 & eps_int, switching)
59
60 ! mandatory arguments
61 integer, intent(in) :: model, nsph
62 real(dp), intent(in) :: coords(3, nsph), radii(nsph)
63 type(ddx_type), target, intent(out) :: ddx_data
64 type(ddx_error_type), intent(inout) :: ddx_error
65 real(dp), intent(in) :: eps
66
67 ! optional arguments
68 integer, intent(in), optional :: force, adjoint, lmax, ngrid, incore, &
69 & maxiter, jacobi_ndiis, enable_fmm, pm, pl, nproc, switching
70 real(dp), intent(in), optional :: kappa, eta, shift, eps_int
71 character(len=255), intent(in), optional :: logfile
72
73 ! local copies of the optional arguments with default values
74 integer :: local_force = default_force
75 integer :: local_adjoint = default_adjoint
76 integer :: local_lmax = default_lmax
77 integer :: local_ngrid = default_ngrid
78 integer :: local_incore = default_incore
79 integer :: local_maxiter = default_maxiter
80 integer :: local_jacobi_ndiis = default_jacobi_ndiis
81 integer :: local_enable_fmm = default_enable_fmm
82 integer :: local_pm = default_pm
83 integer :: local_pl = default_pl
84 integer :: local_nproc = default_nproc
85 integer :: local_switching = default_switching
86
87 real(dp) :: local_kappa = default_kappa
88 real(dp) :: local_eta = default_eta
89 real(dp) :: local_shift
90 real(dp) :: local_eps_int = default_eps_int
91
92 character(len=255) :: local_logfile = default_logfile
93
94 ! arrays for x, y, z coordinates
95 real(dp), allocatable :: x(:), y(:), z(:)
96 integer :: info
97
98 ! The default switching shift depends on the model
99 if (model.lt.1 .or. model.gt.3) then
100 call update_error(ddx_error, "ddinit: wrong value of `model`")
101 return
102 end if
103 local_shift = default_se(model)
104
105 ! Update local variables with provided optional arguments
106 if (present(force)) local_force = force
107 if (present(lmax)) local_lmax = lmax
108 if (present(ngrid)) local_ngrid = ngrid
109 if (present(incore)) local_incore = incore
110 if (present(maxiter)) local_maxiter = maxiter
111 if (present(jacobi_ndiis)) local_jacobi_ndiis = jacobi_ndiis
112 if (present(enable_fmm)) local_enable_fmm = enable_fmm
113 if (present(pm)) local_pm = pm
114 if (present(pl)) local_pl = pl
115 if (present(nproc)) local_nproc = nproc
116 if (present(kappa)) local_kappa = kappa
117 if (present(eta)) local_eta = eta
118 if (present(logfile)) local_logfile = logfile
119 if (present(switching)) local_switching = switching
120 if (present(shift)) local_shift = shift
121
122 ! this are not yet supported, but they will probably
123 if (present(adjoint)) then
124 local_adjoint = adjoint
125 call update_error(ddx_error, &
126 & "ddinit: adjoint argument is not yet supported")
127 return
128 end if
129 if (present(eps_int)) then
130 local_eps_int = eps_int
131 call update_error(ddx_error, &
132 & "ddinit: eps_int argument is not yet supported")
133 return
134 end if
135
136 allocate(x(nsph), y(nsph), z(nsph), stat=info)
137 if (info .ne. 0) then
138 call update_error(ddx_error, "ddinit: allocation failed")
139 return
140 end if
141 x = coords(1,:)
142 y = coords(2,:)
143 z = coords(3,:)
144
145 call allocate_model(nsph, x, y, z, radii, model, local_lmax, local_ngrid, &
146 & local_force, local_enable_fmm, local_pm, local_pl, local_shift, &
147 & local_eta, eps, local_kappa, local_incore, local_maxiter, &
148 & local_jacobi_ndiis, local_nproc, local_logfile, local_switching, &
149 & ddx_data, ddx_error)
150
151 deallocate(x, y, z, stat=info)
152 if (info.ne.0) then
153 call update_error(ddx_error, "ddinit: deallocation failed")
154 return
155 end if
156end subroutine ddinit
157
176subroutine ddrun(ddx_data, state, electrostatics, psi, tol, esolv, &
177 & ddx_error, force, read_guess)
178 type(ddx_type), intent(inout) :: ddx_data
179 type(ddx_state_type), intent(inout) :: state
180 type(ddx_electrostatics_type), intent(in) :: electrostatics
181 real(dp), intent(in) :: psi(ddx_data % constants % nbasis, &
182 & ddx_data % params % nsph)
183 real(dp), intent(in) :: tol
184 real(dp), intent(out) :: esolv
185 type(ddx_error_type), intent(inout) :: ddx_error
186 real(dp), intent(out), optional :: force(3, ddx_data % params % nsph)
187 logical, intent(in), optional :: read_guess
188 ! local variables
189 logical :: do_guess
190
191 ! decide if the guess has to be read or must be done
192 if (present(read_guess)) then
193 do_guess = .not.read_guess
194 else
195 do_guess = .true.
196 end if
197
198 ! if the forces are to be computed, but the array is not passed, raise
199 ! an error
200 if ((.not.present(force)) .and. (ddx_data % params % force .eq. 1)) then
201 call update_error(ddx_error, &
202 & "ddrun: forces are to be computed, but the optional force" // &
203 & " array has not been passed.")
204 return
205 end if
206
207 call setup(ddx_data % params, ddx_data % constants, &
208 & ddx_data % workspace, state, electrostatics, psi, ddx_error)
209 if (ddx_error % flag .ne. 0) then
210 call update_error(ddx_error, "ddrun: setup returned an error, exiting")
211 return
212 end if
213
214 ! solve the primal linear system
215 if (do_guess) then
216 call fill_guess(ddx_data % params, ddx_data % constants, &
217 & ddx_data % workspace, state, tol, ddx_error)
218 if (ddx_error % flag .ne. 0) then
219 call update_error(ddx_error, &
220 & "ddrun: fill_guess returned an error, exiting")
221 return
222 end if
223 end if
224 call solve(ddx_data % params, ddx_data % constants, &
225 & ddx_data % workspace, state, tol, ddx_error)
226 if (ddx_error % flag .ne. 0) then
227 call update_error(ddx_error, "ddrun: solve returned an error, exiting")
228 return
229 end if
230
231 ! compute the energy
232 call energy(ddx_data % params, ddx_data % constants, &
233 & ddx_data % workspace, state, esolv, ddx_error)
234 if (ddx_error % flag .ne. 0) then
235 call update_error(ddx_error, "ddrun: energy returned an error, exiting")
236 return
237 end if
238
239 ! solve the primal linear system
240 if (ddx_data % params % force .eq. 1) then
241 if (do_guess) then
242 call fill_guess_adjoint(ddx_data % params, ddx_data % constants, &
243 & ddx_data % workspace, state, tol, ddx_error)
244 if (ddx_error % flag .ne. 0) then
245 call update_error(ddx_error, &
246 & "ddrun: fill_guess_adjoint returned an error, exiting")
247 return
248 end if
249 end if
250 call solve_adjoint(ddx_data % params, ddx_data % constants, &
251 & ddx_data % workspace, state, tol, ddx_error)
252 if (ddx_error % flag .ne. 0) then
253 call update_error(ddx_error, &
254 & "ddrun: solve_adjoint returned an error, exiting")
255 return
256 end if
257 end if
258
259 ! compute the forces
260 if (ddx_data % params % force .eq. 1) then
261 force = zero
262 call solvation_force_terms(ddx_data % params, ddx_data % constants, &
263 & ddx_data % workspace, state, electrostatics, force, ddx_error)
264 if (ddx_error % flag .ne. 0) then
265 call update_error(ddx_error, &
266 & "ddrun: solvation_force_terms returned an error, exiting")
267 return
268 end if
269 end if
270
271end subroutine ddrun
272
285subroutine setup(params, constants, workspace, state, electrostatics, &
286 & psi, ddx_error)
287 implicit none
288 type(ddx_params_type), intent(in) :: params
289 type(ddx_constants_type), intent(inout) :: constants
290 type(ddx_workspace_type), intent(inout) :: workspace
291 type(ddx_state_type), intent(inout) :: state
292 type(ddx_electrostatics_type), intent(in) :: electrostatics
293 real(dp), intent(in) :: psi(constants % nbasis, params % nsph)
294 type(ddx_error_type), intent(inout) :: ddx_error
295
296 if (params % model .eq. 1) then
297 call cosmo_setup(params, constants, workspace, state, &
298 & electrostatics % phi_cav, psi, ddx_error)
299 else if (params % model .eq. 2) then
300 call pcm_setup(params, constants, workspace, state, &
301 & electrostatics % phi_cav, psi, ddx_error)
302 else if (params % model .eq. 3) then
303 call lpb_setup(params, constants, workspace, state, &
304 & electrostatics % phi_cav, electrostatics % e_cav, &
305 & psi, ddx_error)
306 else
307 call update_error(ddx_error, "Unknow model in setup.")
308 return
309 end if
310
311end subroutine setup
312
323subroutine fill_guess(params, constants, workspace, state, tol, ddx_error)
324 implicit none
325 type(ddx_params_type), intent(in) :: params
326 type(ddx_constants_type), intent(inout) :: constants
327 type(ddx_workspace_type), intent(inout) :: workspace
328 type(ddx_state_type), intent(inout) :: state
329 real(dp), intent(in) :: tol
330 type(ddx_error_type), intent(inout) :: ddx_error
331
332 if (.not.state % rhs_done) then
333 call update_error(ddx_error, &
334 & "In fill_guess, the RHS is not initialized")
335 return
336 end if
337
338 if (params % model .eq. 1) then
339 call cosmo_guess(params, constants, workspace, state, ddx_error)
340 else if (params % model .eq. 2) then
341 call pcm_guess(params, constants, workspace, state, ddx_error)
342 else if (params % model .eq. 3) then
343 call lpb_guess(params, constants, workspace, state, tol, ddx_error)
344 else
345 call update_error(ddx_error, "Unknow model in fill_guess.")
346 return
347 end if
348
349 if (ddx_error % flag .eq. 0) then
350 state % guess_done = .true.
351 state % solved = .false.
352 end if
353
354end subroutine fill_guess
355
366subroutine fill_guess_adjoint(params, constants, workspace, state, tol, ddx_error)
367 implicit none
368 type(ddx_params_type), intent(in) :: params
369 type(ddx_constants_type), intent(inout) :: constants
370 type(ddx_workspace_type), intent(inout) :: workspace
371 type(ddx_state_type), intent(inout) :: state
372 real(dp), intent(in) :: tol
373 type(ddx_error_type), intent(inout) :: ddx_error
374
375 if (.not.state % adjoint_rhs_done) then
376 call update_error(ddx_error, &
377 & "In fill_guess_adjoint, the adjoint RHS is not initialized")
378 return
379 end if
380
381 if (params % model .eq. 1) then
382 call cosmo_guess_adjoint(params, constants, workspace, state, ddx_error)
383 else if (params % model .eq. 2) then
384 call pcm_guess_adjoint(params, constants, workspace, state, ddx_error)
385 else if (params % model .eq. 3) then
386 call lpb_guess_adjoint(params, constants, workspace, state, tol, ddx_error)
387 else
388 call update_error(ddx_error, "Unknow model in fill_guess_adjoint.")
389 return
390 end if
391
392 if (ddx_error % flag .eq. 0) then
393 state % adjoint_guess_done = .true.
394 state % adjoint_solved = .false.
395 end if
396
397end subroutine fill_guess_adjoint
398
409subroutine solve(params, constants, workspace, state, tol, ddx_error)
410 implicit none
411 type(ddx_params_type), intent(in) :: params
412 type(ddx_constants_type), intent(inout) :: constants
413 type(ddx_workspace_type), intent(inout) :: workspace
414 type(ddx_state_type), intent(inout) :: state
415 real(dp), intent(in) :: tol
416 type(ddx_error_type), intent(inout) :: ddx_error
417
418 if (.not.state % rhs_done) then
419 call update_error(ddx_error, "In solve, the RHS is not initialized")
420 return
421 end if
422 if (.not.(state % solved .or. state % guess_done)) then
423 call update_error(ddx_error, &
424 & "In solve, no guess or previous solution is provided")
425 return
426 end if
427
428 if (params % model .eq. 1) then
429 call cosmo_solve(params, constants, workspace, state, tol, ddx_error)
430 else if (params % model .eq. 2) then
431 call pcm_solve(params, constants, workspace, state, tol, ddx_error)
432 else if (params % model .eq. 3) then
433 call lpb_solve(params, constants, workspace, state, tol, ddx_error)
434 else
435 call update_error(ddx_error, "Unknow model in solve.")
436 return
437 end if
438
439 if (ddx_error % flag .eq. 0) then
440 state % solved = .true.
441 end if
442
443end subroutine solve
444
455subroutine solve_adjoint(params, constants, workspace, state, tol, ddx_error)
456 implicit none
457 type(ddx_params_type), intent(in) :: params
458 type(ddx_constants_type), intent(inout) :: constants
459 type(ddx_workspace_type), intent(inout) :: workspace
460 type(ddx_state_type), intent(inout) :: state
461 real(dp), intent(in) :: tol
462 type(ddx_error_type), intent(inout) :: ddx_error
463
464 if (.not.state % adjoint_rhs_done) then
465 call update_error(ddx_error, &
466 & "In solve_adjoint, the RHS is not initialized")
467 return
468 end if
469 if (.not.(state % adjoint_solved .or. state % adjoint_guess_done)) then
470 call update_error(ddx_error, &
471 & "In solve_adjoint, no guess or previous solution is provided")
472 return
473 end if
474
475 if (params % model .eq. 1) then
476 call cosmo_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
477 else if (params % model .eq. 2) then
478 call pcm_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
479 else if (params % model .eq. 3) then
480 call lpb_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
481 else
482 call update_error(ddx_error, "Unknow model in solve_adjoint.")
483 return
484 end if
485
486 if (ddx_error % flag .eq. 0) then
487 state % adjoint_solved = .true.
488 end if
489
490end subroutine solve_adjoint
491
502subroutine energy(params, constants, workspace, state, solvation_energy, ddx_error)
503 implicit none
504 type(ddx_params_type), intent(in) :: params
505 type(ddx_constants_type), intent(in) :: constants
506 type(ddx_workspace_type), intent(in) :: workspace
507 type(ddx_state_type), intent(in) :: state
508 type(ddx_error_type), intent(inout) :: ddx_error
509 real(dp), intent(out) :: solvation_energy
510
511 ! dummy operation on unused interface arguments
512 if (allocated(workspace % tmp_pot)) continue
513
514 if (.not.state % solved) then
515 call update_error(ddx_error, &
516 & "In energy, the solution is not available.")
517 return
518 end if
519 if (.not.state % adjoint_rhs_done) then
520 call update_error(ddx_error, &
521 & "In energy, the adjoint RHS is not initialized")
522 return
523 end if
524
525
526 if (params % model .eq. 1) then
527 call cosmo_energy(constants, state, solvation_energy, ddx_error)
528 else if (params % model .eq. 2) then
529 call pcm_energy(constants, state, solvation_energy, ddx_error)
530 else if (params % model .eq. 3) then
531 call lpb_energy(constants, state, solvation_energy, ddx_error)
532 else
533 call update_error(ddx_error, "Unknow model in energy.")
534 return
535 end if
536
537end subroutine energy
538
552subroutine solvation_force_terms(params, constants, workspace, &
553 & state, electrostatics, force, ddx_error)
554 implicit none
555 type(ddx_params_type), intent(in) :: params
556 type(ddx_constants_type), intent(in) :: constants
557 type(ddx_workspace_type), intent(inout) :: workspace
558 type(ddx_state_type), intent(inout) :: state
559 type(ddx_electrostatics_type), intent(in) :: electrostatics
560 real(dp), intent(out) :: force(3, params % nsph)
561 type(ddx_error_type), intent(inout) :: ddx_error
562
563 if (.not.state % solved) then
564 call update_error(ddx_error, &
565 & "In solvation_force_terms, the solution is not available.")
566 return
567 end if
568 if (.not.state % adjoint_solved) then
569 call update_error(ddx_error, &
570 & "In solvation_force_terms, the adjoint solution is not available.")
571 return
572 end if
573 if (.not.state % rhs_done) then
574 call update_error(ddx_error, &
575 & "In solvation_force_terms, the RHS is not initialized")
576 return
577 end if
578 if (.not.state % adjoint_rhs_done) then
579 call update_error(ddx_error, &
580 & "In solvation_force_terms, the adjoint RHS is not initialized")
581 return
582 end if
583
584 if (params % model .eq. 1) then
585 call cosmo_solvation_force_terms(params, constants, workspace, &
586 & state, electrostatics % e_cav, force, ddx_error)
587 else if (params % model .eq. 2) then
588 call pcm_solvation_force_terms(params, constants, workspace, &
589 & state, electrostatics % e_cav, force, ddx_error)
590 else if (params % model .eq. 3) then
591 call lpb_solvation_force_terms(params, constants, workspace, &
592 & state, electrostatics % g_cav, force, ddx_error)
593 else
594 call update_error(ddx_error, "Unknow model in solvation_force_terms.")
595 return
596 end if
597
598end subroutine solvation_force_terms
599
600end module ddx
subroutine setup(params, constants, workspace, state, electrostatics, psi, ddx_error)
Setup the state for the different models.
Definition: ddx.f90:287
subroutine fill_guess_adjoint(params, constants, workspace, state, tol, ddx_error)
Do a guess for the adjoint linear system for the different models.
Definition: ddx.f90:367
subroutine solve_adjoint(params, constants, workspace, state, tol, ddx_error)
Solve the adjoint linear system for the different models.
Definition: ddx.f90:456
subroutine solvation_force_terms(params, constants, workspace, state, electrostatics, force, ddx_error)
Compute the solvation terms of the forces (solute aspecific) for the different models....
Definition: ddx.f90:554
subroutine fill_guess(params, constants, workspace, state, tol, ddx_error)
Do a guess for the primal linear system for the different models.
Definition: ddx.f90:324
subroutine energy(params, constants, workspace, state, solvation_energy, ddx_error)
Compute the energy for the different models.
Definition: ddx.f90:503
subroutine ddinit(model, nsph, coords, radii, eps, ddx_data, ddx_error, force, kappa, eta, shift, lmax, ngrid, incore, maxiter, jacobi_ndiis, enable_fmm, pm, pl, nproc, logfile, adjoint, eps_int, switching)
Wrapper to the initialization routine which supports optional arguments. This will make future mainte...
Definition: ddx.f90:59
subroutine ddrun(ddx_data, state, electrostatics, psi, tol, esolv, ddx_error, force, read_guess)
Main solver routine.
Definition: ddx.f90:178
subroutine solve(params, constants, workspace, state, tol, ddx_error)
Solve the primal linear system for the different models.
Definition: ddx.f90:410
subroutine cosmo_guess(params, constants, workspace, state, ddx_error)
Do a guess for the primal ddCOSMO linear system.
Definition: ddx_cosmo.f90:90
subroutine cosmo_solve(params, constants, workspace, state, tol, ddx_error)
Solve the primal ddCOSMO linear system.
Definition: ddx_cosmo.f90:135
subroutine cosmo_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
Solve the adjoint ddCOSMO linear system.
Definition: ddx_cosmo.f90:167
subroutine cosmo_solvation_force_terms(params, constants, workspace, state, e_cav, force, ddx_error)
Compute the solvation term of the forces (solute aspecific). This must be summed to the solute specif...
Definition: ddx_cosmo.f90:205
subroutine cosmo_setup(params, constants, workspace, state, phi_cav, psi, ddx_error)
Given the potential at the cavity points, assemble the RHS for ddCOSMO or for ddPCM.
Definition: ddx_cosmo.f90:59
subroutine cosmo_guess_adjoint(params, constants, workspace, state, ddx_error)
Do a guess for the adjoint ddCOSMO linear system.
Definition: ddx_cosmo.f90:112
subroutine cosmo_energy(constants, state, esolv, ddx_error)
Compute the ddCOSMO energy.
Definition: ddx_cosmo.f90:33
subroutine lpb_solve(params, constants, workspace, state, tol, ddx_error)
Solve the ddLPB primal linear system.
Definition: ddx_lpb.f90:194
subroutine lpb_energy(constants, state, esolv, ddx_error)
Compute the ddLPB energy.
Definition: ddx_lpb.f90:109
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.
Definition: ddx_lpb.f90:37
subroutine lpb_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
Solve the adjoint ddLPB linear system.
Definition: ddx_lpb.f90:242
subroutine lpb_guess_adjoint(params, constants, workspace, state, tol, ddx_error)
Do a guess for the adjoint ddLPB linear system.
Definition: ddx_lpb.f90:164
subroutine lpb_guess(params, constants, workspace, state, tol, ddx_error)
Do a guess for the primal ddLPB linear system.
Definition: ddx_lpb.f90:133
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...
Definition: ddx_lpb.f90:293
subroutine pcm_setup(params, constants, workspace, state, phi_cav, psi, ddx_error)
Given the potential at the cavity points, assemble the RHS for ddCOSMO or for ddPCM.
Definition: ddx_pcm.f90:56
subroutine pcm_guess(params, constants, workspace, state, ddx_error)
Do a guess for the primal ddPCM linear system.
Definition: ddx_pcm.f90:86
subroutine pcm_energy(constants, state, esolv, ddx_error)
Compute the ddPCM energy.
Definition: ddx_pcm.f90:32
subroutine pcm_solvation_force_terms(params, constants, workspace, state, e_cav, force, ddx_error)
Compute the solvation contribution to the ddPCM forces.
Definition: ddx_pcm.f90:243
subroutine pcm_solve(params, constants, workspace, state, tol, ddx_error)
Solve the ddPCM primal linear system.
Definition: ddx_pcm.f90:131
subroutine pcm_solve_adjoint(params, constants, workspace, state, tol, ddx_error)
Solve the ddPCM adjpint linear system.
Definition: ddx_pcm.f90:185
subroutine pcm_guess_adjoint(params, constants, workspace, state, ddx_error)
Do a guess for the adjoint ddPCM linear system.
Definition: ddx_pcm.f90:108
High-level subroutines for ddcosmo.
Definition: ddx_cosmo.f90:13
Module defining default parameters, for consistency between the various initialization routines.
Definition: ddx_defaults.f90:3
High-level subroutines for ddlpb.
Definition: ddx_lpb.f90:13
High-level subroutines for ddpcm.
Definition: ddx_pcm.f90:13
High-level module of the ddX software.
Definition: ddx.f90:2