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