ddx 1.0.0
Libary for domain-decomposition methods for polarizable continuum models
ddx_driver.f90
Go to the documentation of this file.
1
11
15program main
16use ddx
17use ddx_input
19use omp_lib
20implicit none
21
22character(len=255) :: fname
23character(len=2047) :: banner
24type(ddx_type) :: ddx_data
25type(ddx_state_type) :: state
26type(ddx_error_type) :: ddx_error
27type(ddx_electrostatics_type) :: electrostatics
28real(dp), allocatable :: psi(:, :), force(:, :), charges(:), &
29 & multipoles(:, :)
30real(dp) :: tol, esolv, start_time, finish_time
31integer :: i, isph, info
32100 format(1x,a,es11.4e2,a)
33200 format(1x,a,i4,a,es21.14)
34300 format(1x,a,i4)
35400 format(1x,a,es25.16e3)
36500 format(1x,i5,3es25.16e3)
37
38! Get the input file from the command line arguments
39call get_command_argument(1, fname)
40write(6, *) "Using provided file ", trim(fname), " as a config file"
41
42! STEP 1: Initialization of the model.
43! Read the input file and call "allocate_model" to initialize the model.
44! The model is a container for all the parameters, precomputed constants
45! and preallocated workspaces.
46start_time = omp_get_wtime()
47call ddfromfile(fname, ddx_data, tol, charges, ddx_error)
48finish_time = omp_get_wtime()
49write(*, 100) "Initialization time:", finish_time - start_time, " seconds"
50call check_error(ddx_error)
51
52! STEP 2: Initialization of the state.
53! The state is a high level object which is related to solving the
54! solvation problem for a given solute. A state must be used with a
55! model (ddx_data). Different states can be used at the same time with
56! a given model, for instance when solving for different solutes,
57! or for different states of the solute.
58call allocate_state(ddx_data % params, ddx_data % constants, state, ddx_error)
59call check_error(ddx_error)
60
61! Print the ddX banner
62call get_banner(banner)
63write(6, *) trim(banner)
64
65! STEP 3: Building the required RHSs and electrostatic properties.
66!
67! dd models require two different kind of RHS. The primal RHS which is
68! based on electrostatic properties, and the adjoint RHS which is a
69! representation of the density in spherical harmonics (with extra steps).
70! Furthermore, when computing the forces, electrostatic properties of
71! order +1 are required to compute the force contribution from the RHS.
72!
73! ddLPB is slightly more complicated as its primal RHS requires also
74! the electric field, and if forces are to be computed, requires the
75! electric field gradient.
76!
77! For convenience all the required electrostatic properties are computed
78! together in STEP 3a. The adjoint RHS is computed in STEP 3b.
79
80! STEP 3a: electrostatic properties for primal RHS and for the forces.
81
82start_time = omp_get_wtime()
83
84! The ddx_multipolar_solute provides routines to compute the
85! electrostatic properties up to field gradient for multipolar
86! distributions of arbitrary order, provided that they are given in
87! real spherical harmonics. Here we have charges, so we need to convert
88! them to monopoles. For charges the conversion is simply a scaling by
89! 1/sqrt(four*pi). For more complicated cases, up to the 16-poles, check
90! https://en.wikipedia.org/wiki/Table_of_spherical_harmonics#Real_spherical_harmonics
91allocate(multipoles(1, ddx_data % params % nsph), stat=info)
92if (info .ne. 0) then
93 write(6, *) "Allocation failed in ddx_driver"
94 stop 1
95end if
96multipoles(1, :) = charges/sqrt4pi
97
98! compute the required electrostatics properties for a multipolar solute
99call multipole_electrostatics(ddx_data % params, ddx_data % constants, &
100 & ddx_data % workspace, multipoles, 0, electrostatics, ddx_error)
101
102finish_time = omp_get_wtime()
103write(*, 100) "Electrostatic properties time:", finish_time-start_time, &
104 & " seconds"
105
106! STEP 3b: adjoint RHS.
107start_time = omp_get_wtime()
108allocate(psi(ddx_data % constants % nbasis, ddx_data % params % nsph), &
109 & stat=info)
110if (info .ne. 0) then
111 write(6, *) "Allocation failed in ddx_driver"
112 stop 1
113end if
114call multipole_psi(ddx_data % params, multipoles, 0, psi)
115finish_time = omp_get_wtime()
116write(*, 100) "Psi time:", finish_time-start_time, " seconds"
117
118if (ddx_data % params % force .eq. 1) then
119 allocate(force(3, ddx_data % params % nsph), stat=info)
120 if (info .ne. 0) then
121 write(6, *) "Allocation failed in ddx_driver"
122 stop 1
123 end if
124 call ddrun(ddx_data, state, electrostatics, psi, tol, esolv, ddx_error, &
125 & force)
126else
127 call ddrun(ddx_data, state, electrostatics, psi, tol, esolv, ddx_error)
128end if
129call check_error(ddx_error)
130
131if (ddx_data % params % force .eq. 1) write(*, 100) &
132 & "solvation force terms time:", state % force_time, " seconds"
133
134! STEP 8: if required compute the solute specific contributions to the
135! forces.
136if (ddx_data % params % force .eq. 1) then
137 start_time = omp_get_wtime()
138 call multipole_force_terms(ddx_data % params, ddx_data % constants, &
139 & ddx_data % workspace, state, 0, multipoles, force, ddx_error)
140 call check_error(ddx_error)
141 finish_time = omp_get_wtime()
142 write(*, 100) "multipolar force terms time:", &
143 & finish_time - start_time, " seconds"
144end if
145
146! From now on, we print the results.
147
148! Print info on the primal ddPCM system
149if (ddx_data % params % model .eq. 2) then
150 ! Print each iteration if needed
151 do i = 1, state % phieps_niter
152 write(6, 200) "iter=", i, " relative difference: ", &
153 & state % phieps_rel_diff(i)
154 end do
155 ! Print number of iterations and time
156 write(6, 100) "ddpcm step time: ", state % phieps_time, &
157 & " seconds"
158 write(6, 300) "ddpcm step iterations: ", &
159 & state % phieps_niter
160end if
161
162! Print info on the primal ddLPB system
163if (ddx_data % params % model .eq. 3) then
164 ! Print each iteration if needed
165 do i = 1, state % x_lpb_niter
166 write(6, 200) "iter=", i, " relative difference: ", &
167 & state % x_lpb_rel_diff(i)
168 end do
169 ! Print number of iterations and time
170 write(6, 100) "ddlpb step time: ", state % x_lpb_time, &
171 & " seconds, of which:"
172 write(6, 100) " ddcosmo: ", state % xs_time, " seconds"
173 write(6, 100) " hsp: ", state % hsp_time, " seconds"
174 write(6, 100) " coupling terms: ", state % x_lpb_time &
175 & - state % xs_time - state % hsp_time, " seconds"
176 write(6, 300) "ddlpb step iterations: ", state % x_lpb_niter
177end if
178
179! Print info on the primal ddCOSMO system
180! Print each iteration if needed
181if ((ddx_data % params % model.eq.1) .or. &
182 & (ddx_data % params % model.eq.2)) then
183 do i = 1, state % xs_niter
184 write(6, 200) "iter=", i, " relative difference: ", &
185 & state % xs_rel_diff(i)
186 end do
187 ! Print number of iterations and time
188 write(6, 100) "ddcosmo step time: ", state % xs_time, " seconds"
189 write(6, 300) "ddcosmo step iterations: ", state % xs_niter
190end if
191
192! Print info on the adjoint solver
193if (ddx_data % params % force .eq. 1) then
194 ! Print info on the adjoint ddCOSMO system
195 if ((ddx_data % params % model.eq.1) .or. &
196 & (ddx_data % params % model.eq.2)) then
197 do i = 1, state % s_niter
198 write(6, 200) "iter=", i, " relative difference: ", &
199 & state % s_rel_diff(i)
200 end do
201 ! Print number of iterations and time
202 write(6, 100) "adjoint ddcosmo step time: ", state % s_time, " seconds"
203 write(6, 300) "adjoint ddcosmo step iterations: ", state % s_niter
204 end if
205
206 ! Print info on the adjoint ddPCM system
207 if (ddx_data % params % model .eq. 2) then
208 ! Print each iteration if needed
209 do i = 1, state % y_niter
210 write(6, 200) "iter=", i, " relative difference: ", &
211 & state % y_rel_diff(i)
212 end do
213 write(6, 100) "adjoint ddpcm step time: ", state % y_time, " seconds"
214 write(6, 300) "adjoint ddpcm step iterations: ", state % y_niter
215 end if
216
217 ! Print info on the adjoint ddLPB system
218 if (ddx_data % params % model .eq. 3) then
219 do i = 1, state % x_adj_lpb_niter
220 write(6, 200) "iter=", i, " relative difference: ", &
221 & state % x_adj_lpb_rel_diff(i)
222 end do
223 ! Print number of iterations and time
224 write(6, 100) "adjoint ddlpb step time: ", &
225 & state % x_adj_lpb_time, " seconds, of which:"
226 write(6, 100) " adjoint ddcosmo: ", state % s_time, " seconds"
227 write(6, 100) " adjoint hsp: ", state % hsp_adj_time, " seconds"
228 write(6, 100) " adjoint coupling terms: ", state % x_adj_lpb_time &
229 & - state % s_time - state % hsp_adj_time, " seconds"
230 write(6, 200) "adjoint ddlpb step iterations: ", &
231 & state % x_adj_lpb_niter
232 end if
233end if
234
235write(6, 400) "Solvation energy (Hartree):", esolv
236write(6, 400) "Solvation energy (kcal/mol):", esolv*tokcal
237if (ddx_data % params % force .eq. 1) then
238 write(6, *) "Full forces (kcal/mol/A)"
239 do isph = 1, ddx_data % params % nsph
240 write(6, 500) isph, force(:, isph)*tokcal/toang
241 end do
242end if
243
244! Clean the workspace.
245
246deallocate(psi, multipoles, charges, stat=info)
247if (info .ne. 0) then
248 write(6, *) "Deallocation failed in ddx_driver"
249 stop 1
250end if
251if (allocated(force)) then
252 deallocate(force, stat=info)
253 if (info .ne. 0) then
254 write(6, *) "Deallocation failed in ddx_driver"
255 stop 1
256 end if
257end if
258
259call deallocate_electrostatics(electrostatics, ddx_error)
260call deallocate_state(state, ddx_error)
261call deallocate_model(ddx_data, ddx_error)
262
263end program main
program main
Standalone application of ddX: this program can compute the solvation energy and forces for a solute ...
Definition: ddx_driver.f90:15
subroutine ddfromfile(fname, ddx_data, tol, charges, ddx_error)
Read the configuration from ddX input file and return a ddx_data structure.
Definition: ddx_input.f90:38
subroutine ddrun(ddx_data, state, electrostatics, psi, tol, esolv, ddx_error, force, read_guess)
Main solver routine.
Definition: ddx.f90:178
subroutine multipole_electrostatics(params, constants, workspace, multipoles, mmax, electrostatics, ddx_error)
Given a multipolar distribution, compute the required electrostatic properties for the chosen model.
subroutine multipole_force_terms(params, constants, workspace, state, mmax, multipoles, forces, ddx_error)
Given a multipolar distribution in real spherical harmonics and centered on the spheres,...
subroutine multipole_psi(params, multipoles, mmax, psi)
Given a multipolar distribution, assemble the RHS psi. The multipoles must be centered on the ddx sph...
Functionality to read input files for the standalone driver.
Definition: ddx_input.f90:3
Routines to build rhs (phi and psi)
High-level module of the ddX software.
Definition: ddx.f90:2