Octopus
target_velocity.F90
Go to the documentation of this file.
1!! Copyright (C) 2002-2006 M. Marques, A. Castro, A. Rubio, G. Bertsch
2!!
3!! This program is free software; you can redistribute it and/or modify
4!! it under the terms of the GNU General Public License as published by
5!! the Free Software Foundation; either version 2, or (at your option)
6!! any later version.
7!!
8!! This program is distributed in the hope that it will be useful,
9!! but WITHOUT ANY WARRANTY; without even the implied warranty of
10!! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11!! GNU General Public License for more details.
12!!
13!! You should have received a copy of the GNU General Public License
14!! along with this program; if not, write to the Free Software
15!! Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16!! 02110-1301, USA.
17!!
18
19#include "global.h"
20
23 use debug_oct_m
25 use epot_oct_m
26 use global_oct_m
27 use grid_oct_m
30 use, intrinsic :: iso_fortran_env
31 use io_oct_m
32 use ions_oct_m
40 use output_oct_m
42 use parser_oct_m
45 use space_oct_m
47 use string_oct_m
48 use target_oct_m
49 use td_oct_m
50
51 implicit none
52
53 private
54 public :: target_velocity_t
55
57 type, extends(target_t) :: target_velocity_t
58 private
59 character(len=4096) :: vel_input_string
60 character(len=1024), allocatable :: vel_der_array(:,:)
61 real(real64), allocatable :: grad_local_pot(:,:,:)
62 real(real64), allocatable :: rho(:)
63 real(real64), allocatable :: td_fitness(:)
64 contains
65 procedure :: init => target_init_velocity
66 procedure :: cleanup => target_end_velocity
67 procedure :: j1 => target_j1_velocity
68 procedure :: apply_chi => target_chi_velocity
69 procedure :: output => target_output_velocity
70 procedure :: tdcalc => target_tdcalc_velocity
71 procedure :: inh => target_inh_velocity
72 end type target_velocity_t
73
74
75contains
76
77 ! ----------------------------------------------------------------------
79 subroutine target_init_velocity(tg, gr, kpoints, namespace, space, ions, qcs, td, w0, oct, ep, restart)
80 class(target_velocity_t), intent(inout) :: tg
81 type(grid_t), intent(in) :: gr
82 type(kpoints_t), intent(in) :: kpoints
83 type(namespace_t), intent(in) :: namespace
84 class(space_t), intent(in) :: space
85 type(ions_t), intent(in) :: ions
86 type(opt_control_state_t), intent(inout) :: qcs
87 type(td_t), intent(in) :: td
88 real(real64), intent(in) :: w0
89 type(oct_t), intent(in) :: oct
90 type(epot_t), intent(inout) :: ep
91 type(restart_t), intent(inout) :: restart
92
93 integer :: iatom, ist, jst, jj
94 real(real64), allocatable :: vl(:), vl_grad(:,:)
95 type(block_t) :: blk
96 character(len=1024) :: expression
97
98 push_sub(target_init_velocity)
99
100 !%Variable OCTVelocityTarget
101 !%Type block
102 !%Section Calculation Modes::Optimal Control
103 !%Description
104 !% If <tt>OCTTargetOperator = oct_tg_velocity</tt>, then one must supply the
105 !% target to optimize in terms of the ionic velocities. This is done by
106 !% supplying a string through the block <tt>OCTVelocityTarget</tt>.
107 !% Each velocity component is supplied by <tt>"v[n_atom,vec_comp]"</tt>,
108 !% where <tt>n_atom</tt> is the atom number, corresponding to the
109 !% <tt>Coordinates</tt> block, and <tt>vec_comp</tt> is the corresponding
110 !% vector component of the velocity. The target string can be
111 !% supplied by using several lines in this block.
112 !% As an example, the following target can be used to maximize the
113 !% velocity difference between atom 1 and 2 (in a 3D system):
114 !%
115 !% <tt>%OCTVelocityTarget
116 !% <br> "(v[1,1]-v[2,1])^2 + (v[1,2]-v[2,2])^2 + "
117 !% <br> "(v[1,3]-v[2,3])^2"
118 !% <br>%</tt>
119 !%
120 !%End
121
122 !%Variable OCTVelocityDerivatives
123 !%Type block
124 !%Section Calculation Modes::Optimal Control
125 !%Description
126 !% If <tt>OCTTargetOperator = oct_tg_velocity</tt>, and
127 !% <tt>OCTScheme = oct_cg</tt> or <tt>OCTScheme = oct_bfgs</tt>
128 !% then you must supply the target in terms of the ionic velocities AND
129 !% the derivatives of the target with respect to the ionic velocity components.
130 !% The derivatives are supplied via strings through the block
131 !% <tt>OCTVelocityDerivatives</tt>.
132 !% Each velocity component is supplied by <tt>"v[n_atom,vec_comp]"</tt>,
133 !% while <tt>n_atom</tt> is the atom number, corresponding to the
134 !% <tt>Coordinates</tt> block, and <tt>vec_comp</tt> is the corresponding
135 !% vector component of the velocity. The first line of the
136 !% <tt>OCTVelocityDerivatives</tt> block contains the derivatives
137 !% with respect to <tt>v[1,*]</tt>, the second with respect to <tt>v[2,*]</tt> and so
138 !% on. The first column contains all derivatives with respect <tt>v[*,1]</tt>,
139 !% the second with respect to <tt>v[*,2]</tt> and the third w.r.t. <tt>v[*,3]</tt>.
140 !% As an example, we show the <tt>OCTVelocityDerivatives</tt> block
141 !% corresponding to the target shown in the <tt>OCTVelocityTarget</tt>
142 !% help section:
143 !%
144 !% <tt>%OCTVelocityDerivatives
145 !% <br> " 2*(v[1,1]-v[2,1])" | " 2*(v[1,2]-v[2,2])" | " 2*(v[1,3]-v[2,3])"
146 !% <br> "-2*(v[1,1]-v[2,1])" | "-2*(v[1,2]-v[2,2])" | "-2*(v[1,3]-v[2,3])"
147 !% <br>%</tt>
148 !%
149 !%End
150
151 if (parse_block(namespace, 'OCTVelocityTarget', blk) == 0) then
152 tg%vel_input_string = " "
153 do jj=0, parse_block_n(blk)-1
154 call parse_block_string(blk, jj, 0, expression)
155 tg%vel_input_string = trim(tg%vel_input_string) // trim(expression)
156 end do
158 else
159 message(1) = 'If OCTTargetOperator = oct_tg_velocity, then you must give the shape'
160 message(2) = 'of this target in the block "OCTVelocityTarget".'
161 call messages_fatal(2, namespace=namespace)
162 end if
164 tg%move_ions = td%ions_dyn%ions_move()
165 if (tg%move_ions) then
166 message(1) = 'If OCTTargetOperator = oct_tg_velocity, then you must not allow the ions'
167 message(2) = 'to move. If you want to move the ions, then you can get the same functionality'
168 message(3) = 'with OCTTargetOperator = oct_tg_classical.'
169 call messages_fatal(3, namespace=namespace)
170 end if
171
172 if (oct%algorithm == option__octscheme__oct_cg .or. oct%algorithm == option__octscheme__oct_bfgs) then
173 if (parse_block(namespace, 'OCTVelocityDerivatives', blk) == 0) then
174 safe_allocate(tg%vel_der_array(1:ions%natoms,1:gr%box%dim))
175 do ist=0, ions%natoms-1
176 do jst=0, gr%box%dim-1
177 call parse_block_string(blk, ist, jst, tg%vel_der_array(ist+1, jst+1))
178 end do
179 end do
180 call parse_block_end(blk)
181 else
182 message(1) = 'If OCTTargetOperator = oct_tg_velocity, and'
183 message(2) = 'OCTScheme = oct_cg, or OCTScheme = oct_bfgs then you must define the'
184 message(3) = 'blocks "OCTVelocityTarget" AND "OCTVelocityDerivatives"'
185 call messages_fatal(3, namespace=namespace)
186 end if
187 end if
188
189 safe_allocate(tg%grad_local_pot(1:ions%natoms, 1:gr%np, 1:gr%box%dim))
190 safe_allocate(vl(1:gr%np_part))
191 safe_allocate(vl_grad(1:gr%np, 1:gr%box%dim))
192 safe_allocate(tg%rho(1:gr%np))
193
194 ! calculate gradient of each species potential
195 do iatom = 1, ions%natoms
196 vl(:) = m_zero
197 vl_grad(:,:) = m_zero
198 call epot_local_potential(ep, namespace, ions%space, ions%latt, gr, ions%atom(iatom)%species, &
199 ions%pos(:, iatom), iatom, vl)
200 call dderivatives_grad(gr%der, vl, vl_grad)
201 do ist = 1, gr%np
202 do jst=1, gr%box%dim
203 tg%grad_local_pot(iatom, ist, jst) = vl_grad(ist, jst)
204 end do
205 end do
206 end do
207 safe_deallocate_a(vl)
208 safe_deallocate_a(vl_grad)
209
210 ! Note that the calculation of the gradient of the potential
211 ! is wrong at the borders of the box, since it assumes zero boundary
212 ! conditions. The best way to solve this problems is to define the
213 ! target making use of the definition of the forces based on the gradient
214 ! of the density, rather than on the gradient of the potential.
215
216 tg%dt = td%dt
217 safe_allocate(tg%td_fitness(0:td%max_iter))
218 tg%td_fitness = m_zero
219
220 pop_sub(target_init_velocity)
221 end subroutine target_init_velocity
222
223
224 ! ----------------------------------------------------------------------
226 subroutine target_end_velocity(tg, oct)
227 class(target_velocity_t), intent(inout) :: tg
228 type(oct_t), intent(in) :: oct
229
230 push_sub(target_end_velocity)
231
232 if (oct%algorithm == option__octscheme__oct_cg .or. oct%algorithm == option__octscheme__oct_bfgs) then
233 safe_deallocate_a(tg%vel_der_array)
234 safe_deallocate_a(tg%grad_local_pot)
235 safe_deallocate_a(tg%rho)
236 end if
237 safe_deallocate_a(tg%td_fitness)
238
239 pop_sub(target_end_velocity)
240 end subroutine target_end_velocity
241
242
243 ! ----------------------------------------------------------------------
244 subroutine target_output_velocity(tg, namespace, space, gr, dir, ions, hm, outp)
245 class(target_velocity_t), intent(inout) :: tg
246 type(namespace_t), intent(in) :: namespace
247 class(space_t), intent(in) :: space
248 type(grid_t), intent(in) :: gr
249 character(len=*), intent(in) :: dir
250 type(ions_t), intent(in) :: ions
251 type(hamiltonian_elec_t), intent(in) :: hm
252 type(output_t), intent(in) :: outp
253
254 push_sub(target_output_velocity)
255
256 call io_mkdir(trim(dir), namespace)
257 call output_states(outp, namespace, space, trim(dir), tg%st, gr, ions, hm, -1)
258
260 end subroutine target_output_velocity
261 ! ----------------------------------------------------------------------
262
263
264 ! ----------------------------------------------------------------------
266 real(real64) function target_j1_velocity(tg, namespace, gr, kpoints, qcpsi, ions) result(j1)
267 class(target_velocity_t), intent(inout) :: tg
268 type(namespace_t), intent(in) :: namespace
269 type(grid_t), intent(in) :: gr
270 type(kpoints_t), intent(in) :: kpoints
271 type(opt_control_state_t), intent(inout) :: qcpsi
272 type(ions_t), optional, intent(in) :: ions
273
274 integer :: i
275 real(real64) :: f_re, dummy(3)
276 real(real64), allocatable :: x(:, :)
277 character(len=4096) :: inp_string
278 push_sub(target_j1_velocity)
279
280 safe_allocate(x(1:ions%natoms, 1:ions%space%dim))
281 do i = 1, ions%natoms
282 x(i, :) = ions%vel(:, i)
283 end do
284
285 f_re = m_zero
286 dummy(:) = m_zero
287 inp_string = tg%vel_input_string
288 call parse_array(inp_string, x, 'v')
289 call conv_to_c_string(inp_string)
290 call parse_expression(f_re, dummy(1), 1, dummy(1:3), dummy(1), dummy(1), inp_string)
291 j1 = f_re
292
293 safe_deallocate_a(x)
294 pop_sub(target_j1_velocity)
295 end function target_j1_velocity
296
297
298 ! ----------------------------------------------------------------------
300 subroutine target_chi_velocity(tg, namespace, gr, kpoints, qcpsi_in, qcchi_out, ions)
301 class(target_velocity_t), intent(inout) :: tg
302 type(namespace_t), intent(in) :: namespace
303 type(grid_t), intent(in) :: gr
304 type(kpoints_t), intent(in) :: kpoints
305 type(opt_control_state_t), target, intent(inout) :: qcpsi_in
306 type(opt_control_state_t), target, intent(inout) :: qcchi_out
307 type(ions_t), intent(in) :: ions
308
309 integer :: ip, ist, jst, ik, ib
310 character(len=1024) :: temp_string
311 real(real64) :: df_dv, dummy(3)
312 real(real64), allocatable :: x(:, :)
313 type(states_elec_t), pointer :: chi_out
314 push_sub(target_chi_velocity)
315
316 chi_out => opt_control_point_qs(qcchi_out)
317
318 !we have a time-dependent target --> Chi(T)=0
319 do ik = chi_out%d%kpt%start, chi_out%d%kpt%end
320 do ib = chi_out%group%block_start, chi_out%group%block_end
321 call batch_set_zero(chi_out%group%psib(ib, ik))
322 end do
323 end do
324
325 safe_allocate(x(1:ions%natoms, 1:ions%space%dim))
326 do ip = 1, ions%natoms
327 x(ip, :) = ions%vel(:, ip)
328 end do
329
330 !calculate dF/dn, which is the time-independent part of the inhomogenous term for the propagation of Chi
331 df_dv = m_zero
332 dummy(:) = m_zero
333 tg%rho(:) = m_zero
334 do ist = 1, ions%natoms
335 do jst=1, gr%box%dim
336 temp_string = tg%vel_der_array(ist, jst)
337 call parse_array(temp_string, x, 'v')
338 call conv_to_c_string(temp_string)
339 call parse_expression(df_dv, dummy(1), 1, dummy(1:3), dummy(1), dummy(1), temp_string)
340 tg%rho(:) = tg%rho(:) + df_dv*tg%grad_local_pot(ist,:,jst)/ions%mass(ist)
341 end do
342 end do
343
344 safe_deallocate_a(x)
345 nullify(chi_out)
346 pop_sub(target_chi_velocity)
347 end subroutine target_chi_velocity
348
349
350 ! ---------------------------------------------------------------
352 subroutine target_inh_velocity(tg, psi, gr, kpoints, time, inh, iter)
353 class(target_velocity_t), intent(inout) :: tg
354 type(states_elec_t), intent(inout) :: psi
355 type(grid_t), intent(in) :: gr
356 type(kpoints_t), intent(in) :: kpoints
357 real(real64), intent(in) :: time
358 type(states_elec_t), intent(inout) :: inh
359 integer, intent(in) :: iter
360
361 integer :: ik, ist, ip, idim
362 complex(real64), allocatable :: zpsi(:)
363
364 push_sub(target_inh_velocity)
365
366 safe_allocate(zpsi(1:gr%np))
367
368 do ik = inh%d%kpt%start, inh%d%kpt%end
369 do ist = inh%st_start, inh%st_end
370 do idim = 1, inh%d%dim
371 call states_elec_get_state(psi, gr, idim, ist, ik, zpsi)
372 do ip = 1, gr%np
373 zpsi(ip) = -psi%occ(ist, ik)*tg%rho(ip)*zpsi(ip)
374 end do
375 call states_elec_set_state(inh, gr, idim, ist, ik, zpsi)
376 end do
377 end do
378 end do
379
380 safe_deallocate_a(zpsi)
381
382 pop_sub(target_inh_velocity)
383 end subroutine target_inh_velocity
384 !----------------------------------------------------------
385
386
387 ! ---------------------------------------------------------
390 subroutine target_tdcalc_velocity(tg, namespace, space, hm, gr, ions, ext_partners, psi, time, max_time)
391 class(target_velocity_t), intent(inout) :: tg
392 type(namespace_t), intent(in) :: namespace
393 class(space_t), intent(in) :: space
394 type(hamiltonian_elec_t), intent(inout) :: hm
395 type(grid_t), intent(in) :: gr
396 type(ions_t), intent(inout) :: ions
397 type(partner_list_t), intent(in) :: ext_partners
398 type(states_elec_t), intent(inout) :: psi
399 integer, intent(in) :: time
400 integer, intent(in) :: max_time
401
402 complex(real64), allocatable :: opsi(:, :), zpsi(:, :)
403 integer :: iatom, ik, ist, idim
404 real(real64) :: dt
405 push_sub(target_tdcalc_velocity)
406
407 tg%td_fitness(time) = m_zero
408
409 safe_allocate(zpsi(1:gr%np_part, 1))
410 safe_allocate(opsi(1:gr%np_part, 1))
411 opsi = m_z0
412 ! WARNING This does not work for spinors.
413 do iatom = 1, ions%natoms
414 ions%tot_force(:, iatom) = hm%ep%fii(1:gr%box%dim, iatom)
415 do ik = 1, psi%nik
416 do ist = 1, psi%nst
417 do idim = 1, gr%box%dim
418 call states_elec_get_state(psi, gr, ist, ik, zpsi)
419 opsi(1:gr%np, 1) = tg%grad_local_pot(iatom, 1:gr%np, idim)*zpsi(1:gr%np, 1)
420 ions%tot_force(idim, iatom) = ions%tot_force(idim, iatom) &
421 + real(psi%occ(ist, ik)*zmf_dotp(gr, psi%d%dim, opsi, zpsi), real64)
422 end do
423 end do
424 end do
425 end do
426 safe_deallocate_a(opsi)
427 safe_deallocate_a(zpsi)
428
429 dt = tg%dt
430 if ((time == 0) .or. (time == max_time)) dt = tg%dt * m_half
431 do iatom = 1, ions%natoms
432 ions%vel(:, iatom) = ions%vel(:, iatom) + ions%tot_force(:, iatom) * dt / ions%mass(iatom)
433 end do
434
436 end subroutine target_tdcalc_velocity
437 ! ----------------------------------------------------------------------
438
439end module target_velocity_oct_m
440
441!! Local Variables:
442!! mode: f90
443!! coding: utf-8
444!! End:
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
subroutine, public dderivatives_grad(der, ff, op_ff, ghost_update, set_bc, to_cartesian)
apply the gradient to a mesh function
subroutine, public epot_local_potential(ep, namespace, space, latt, mesh, species, pos, iatom, vpsl)
Definition: epot.F90:511
real(real64), parameter, public m_zero
Definition: global.F90:200
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines classes and functions for interaction partners.
Definition: io.F90:116
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:361
This module defines various routines, operating on mesh functions.
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
Definition: messages.F90:162
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
Definition: messages.F90:410
This module contains the definition of the oct_t data type, which contains some of the basic informat...
This module holds the "opt_control_state_t" datatype, which contains a quantum-classical state.
this module contains the low-level part of the output system
Definition: output_low.F90:117
this module contains the output system
Definition: output.F90:117
subroutine, public output_states(outp, namespace, space, dir, st, gr, ions, hm, iter)
Definition: output.F90:1091
subroutine, public parse_block_string(blk, l, c, res, convert_to_c)
Definition: parser.F90:818
subroutine, public parse_array(inp_string, x, arraychar)
A very primitive way to "preprocess" a string that contains reference to the elements of a two-dimens...
Definition: parser.F90:713
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
subroutine, public conv_to_c_string(str)
converts to c string
Definition: string.F90:234
Optimal-control targets: abstract base class and public interface.
Definition: target.F90:132
real(real64) function target_j1_velocity(tg, namespace, gr, kpoints, qcpsi, ions)
subroutine target_init_velocity(tg, gr, kpoints, namespace, space, ions, qcs, td, w0, oct, ep, restart)
subroutine target_inh_velocity(tg, psi, gr, kpoints, time, inh, iter)
Inhomogeneous term for the velocity target.
subroutine target_end_velocity(tg, oct)
subroutine target_tdcalc_velocity(tg, namespace, space, hm, gr, ions, ext_partners, psi, time, max_time)
subroutine target_chi_velocity(tg, namespace, gr, kpoints, qcpsi_in, qcchi_out, ions)
subroutine target_output_velocity(tg, namespace, space, gr, dir, ions, hm, outp)
Definition: td.F90:116
Description of the grid, containing information on derivatives, stencil, and symmetries.
Definition: grid.F90:171
!brief The oct_t datatype stores the basic information about how the OCT run is done.
This is the datatype that contains the objects that are propagated: in principle this could be both t...
output handler class
Definition: output_low.F90:166
Abstract optimal-control target.
Definition: target.F90:172
Target as a function of the ionic velocities.