Octopus
target_density.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
27 use epot_oct_m
28 use global_oct_m
29 use grid_oct_m
32 use io_oct_m
34 use ions_oct_m
36 use, intrinsic :: iso_fortran_env
38 use math_oct_m
39 use mesh_oct_m
46 use parser_oct_m
49 use space_oct_m
54 use string_oct_m
55 use td_oct_m
56 use target_oct_m
57 use types_oct_m
58 use unit_oct_m
60
61
62 implicit none
63
64 private
65 public :: target_density_t
66
68 type, extends(target_t) :: target_density_t
69 private
70 real(real64), allocatable :: rho(:)
71 real(real64), allocatable :: td_fitness(:)
72 real(real64) :: density_weight
73 real(real64) :: curr_weight
74 integer :: strt_iter_curr_tg
75 real(real64), allocatable :: spatial_curr_wgt(:)
76 contains
77 procedure :: init => target_init_density
78 procedure :: cleanup => target_end_density
79 procedure :: j1 => target_j1_density
80 procedure :: apply_chi => target_chi_density
81 procedure :: output => target_output_density
82 procedure :: tdcalc => target_tdcalc_density
83 procedure :: inh => target_inh_density
84 end type target_density_t
85
86
87contains
88
89 ! ----------------------------------------------------------------------
91 subroutine target_init_density(tg, gr, kpoints, namespace, space, ions, qcs, td, w0, oct, ep, restart)
92 class(target_density_t), intent(inout) :: tg
93 type(grid_t), intent(in) :: gr
94 type(kpoints_t), intent(in) :: kpoints
95 type(namespace_t), intent(in) :: namespace
96 class(space_t), intent(in) :: space
97 type(ions_t), intent(in) :: ions
98 type(opt_control_state_t), intent(inout) :: qcs
99 type(td_t), intent(in) :: td
100 real(real64), intent(in) :: w0
101 type(oct_t), intent(in) :: oct
102 type(epot_t), intent(inout) :: ep
103 type(restart_t), intent(inout) :: restart
104
105 integer :: ip, ist, jst, cstr_dim(space%dim), ib, idim, jj, no_constraint, no_ptpair, iqn
106 type(block_t) :: blk
107 real(real64) :: psi_re, psi_im, xx(space%dim), rr, fact, xend, xstart
108 real(real64), allocatable :: xp(:), tmp_box(:, :)
109 complex(real64), allocatable :: rotation_matrix(:, :), psi(:, :)
110 type(states_elec_t) :: tmp_st
111 character(len=1024) :: expression
112 type(states_elec_t), pointer :: stin
113
114 push_sub(target_init_density)
115
117
118 message(1) = 'Info: Target is a combination of a density and/or a current functional.'
119 call messages_info(1, namespace=namespace)
120
121 tg%move_ions = td%ions_dyn%ions_move()
122 tg%dt = td%dt
123
124 tg%curr_functional = oct_no_curr
125 tg%curr_weight = m_zero
126 tg%strt_iter_curr_tg = 0
127
128 !%Variable OCTTargetDensity
129 !%Type string
130 !%Section Calculation Modes::Optimal Control
131 !%Description
132 !% If <tt>OCTTargetOperator = oct_tg_density</tt>, then one must supply the target density
133 !% that should be searched for. This one can do by supplying a string through
134 !% the variable <tt>OCTTargetDensity</tt>. Alternately, give the special string <tt>"OCTTargetDensityFromState"</tt>
135 !% to specify the expression via the block <tt>OCTTargetDensityFromState</tt>.
136 !%End
137
138 !%Variable OCTTargetDensityFromState
139 !%Type block
140 !%Default no
141 !%Section Calculation Modes::Optimal Control
142 !%Description
143 !% If <tt>OCTTargetOperator = oct_tg_density</tt>, and <tt>OCTTargetDensity = "OCTTargetDensityFromState"</tt>,
144 !% you must specify a <tt>OCTTargetDensityState</tt> block, in order to specify which linear
145 !% combination of the states present in <tt>restart/gs</tt> is used to
146 !% create the target density.
147 !%
148 !% The syntax is the same as the <tt>TransformStates</tt> block.
149 !%End
150
151 if (parse_is_defined(namespace, 'OCTTargetDensity')) then
152 tg%density_weight = m_one
153 safe_allocate(tg%rho(1:gr%np))
154 tg%rho = m_zero
155 call parse_variable(namespace, 'OCTTargetDensity', "0", expression)
156
157 if (trim(expression) == 'OCTTargetDensityFromState') then
158
159 if (parse_block(namespace, 'OCTTargetDensityFromState', blk) == 0) then
160 call states_elec_copy(tmp_st, tg%st)
161 call states_elec_deallocate_wfns(tmp_st)
162 call states_elec_look_and_load(restart, namespace, space, tmp_st, gr, kpoints, &
163 fixed_occ=.true.)
164
165 safe_allocate(rotation_matrix(1:tmp_st%nst, 1:tmp_st%nst))
167 rotation_matrix = diagonal_matrix(tmp_st%nst, m_z1)
169 do ist = 1, tg%st%nst
170 do jst = 1, parse_block_cols(blk, ist - 1)
171 call parse_block_cmplx(blk, ist - 1, jst - 1, rotation_matrix(jst, ist))
172 end do
173 end do
175 safe_allocate(psi(1:gr%np, 1:tg%st%d%dim))
177 do iqn = tg%st%d%kpt%start, tg%st%d%kpt%end
179 if (states_are_real(tg%st)) then
180 call states_elec_rotate(tmp_st, gr, real(rotation_matrix, real64) , iqn)
181 else
182 call states_elec_rotate(tmp_st, gr, rotation_matrix, iqn)
183 end if
184
185 do ist = tg%st%st_start, tg%st%st_end
186 call states_elec_get_state(tmp_st, gr, ist, iqn, psi)
187 call states_elec_set_state(tg%st, gr, ist, iqn, psi)
188 end do
189
190 end do
191
192 safe_deallocate_a(rotation_matrix)
193 safe_deallocate_a(psi)
194 call states_elec_end(tmp_st)
195
196 call density_calc(tg%st, gr, tg%st%rho)
197 do ip = 1, gr%np
198 tg%rho(ip) = sum(tg%st%rho(ip, 1:tg%st%d%spin_channels))
199 end do
200 call parse_block_end(blk)
201 else
202 call messages_variable_is_block(namespace, 'OCTTargetDensityFromState')
203 end if
204
205 else
206
207 call conv_to_c_string(expression)
208 do ip = 1, gr%np
209 call mesh_r(gr, ip, rr, coords = xx)
210 ! parse user-defined expression
211 call parse_expression(psi_re, psi_im, space%dim, xx, rr, m_zero, expression)
212 tg%rho(ip) = psi_re
213 end do
214 ! Normalize
215 rr = dmf_integrate(gr, tg%rho)
216 tg%rho = (-tg%st%val_charge) * tg%rho/rr
217 end if
218
219 else
220 tg%density_weight = m_zero
221 end if
222
223 !%Variable OCTCurrentFunctional
224 !%Type integer
225 !%Section Calculation Modes::Optimal Control
226 !%Default oct_no_curr
227 !%Description
228 !% (Experimental) The variable <tt>OCTCurrentFunctional</tt> describes which kind of
229 !% current target functional <math>J1_c[j]</math> is to be used.
230 !%Option oct_no_curr 0
231 !% No current functional is used, no current calculated.
232 !%Option oct_curr_square 1
233 !% Calculates the square of current <math>j</math>:
234 !% <math>J1_c[j] = {\tt OCTCurrentWeight} \int{\left| j(r) \right|^2 dr}</math>.
235 !% For <tt>OCTCurrentWeight</tt> < 0, the current will be minimized (useful in combination with
236 !% target density in order to obtain stable final target density), while for
237 !% <tt>OCTCurrentWeight</tt> > 0, it will be maximized (useful in combination with a target density
238 !% in order to obtain a high-velocity impact, for instance). It is a static target, to be reached at
239 !% total time.
240 !%Option oct_max_curr_ring 2
241 !% Maximizes the current of a quantum ring in one direction. The functional maximizes the <math>z</math> projection of the
242 !% outer product between the position <math>\vec{r}</math> and the current <math>\vec{j}</math>:
243 !% <math>J1[j] = {\tt OCTCurrentWeight} \int{(\vec{r} \times \vec{j}) \cdot \hat{z} dr}</math>.
244 !% For <tt>OCTCurrentWeight</tt> > 0, the
245 !% current flows in counter-clockwise direction, while for <tt>OCTCurrentWeight</tt> < 0, the current is clockwise.
246 !%Option oct_curr_square_td 3
247 !% The time-dependent version of <tt>oct_curr_square</tt>. In fact, calculates the
248 !% square of current in time interval [<tt>OCTStartTimeCurrTg</tt>,
249 !% total time = <tt>TDMaximumIter</tt> * <tt>TDTimeStep</tt>].
250 !% Set <tt>TDPropagator</tt> = <tt>crank_nicolson</tt>.
251 !%End
252
253 !%Variable OCTCurrentWeight
254 !%Type float
255 !%Section Calculation Modes::Optimal Control
256 !%Default 0.0
257 !%Description
258 !% In the case of simultaneous optimization of density <math>n</math> and current <math>j</math>, one can tune the importance
259 !% of the current functional <math>J1_c[j]</math>, as the respective functionals might not provide results on the
260 !% same scale of magnitude. <math>J1[n,j]= J1_d[n]+ {\tt OCTCurrentWeight}\ J1_c[j]</math>. Be aware that its
261 !% sign is crucial for the chosen <tt>OCTCurrentFunctional</tt> as explained there.
262 !%End
263
264 !%Variable OCTStartIterCurrTg
265 !%Type integer
266 !%Section Calculation Modes::Optimal Control
267 !%Default 0
268 !%Description
269 !% Allows for a time-dependent target for the current without defining it for the total
270 !% time-interval of the simulation.
271 !% Thus it can be switched on at the iteration desired, <tt>OCTStartIterCurrTg</tt> >= 0
272 !% and <tt>OCTStartIterCurrTg</tt> < <tt>TDMaximumIter</tt>.
273 !% Tip: If you would like to specify a real time for switching
274 !% the functional on rather than the number of steps, just use something
275 !% like:
276 !% <tt>OCTStartIterCurrTg</tt> = 100.0 / <tt>TDTimeStep</tt>.
277 !%End
278
279 !%Variable OCTSpatialCurrWeight
280 !%Type block
281 !%Section Calculation Modes::Optimal Control
282 !%Description
283 !% Can be seen as a position-dependent <tt>OCTCurrentWeight</tt>. Consequently, it
284 !% weights contribution of current <math>j</math> to its functional <math>J1_c[j]</math> according to the position in space.
285 !% For example, <tt>oct_curr_square</tt> thus becomes
286 !% <math>J1_c[j] = {\tt OCTCurrentWeight} \int{\left| j(r) \right|^2 {\tt OCTSpatialCurrWeight}(r) dr}</math>.
287 !%
288 !% It is defined as <tt>OCTSpatialCurrWeight</tt><math>(r) = g(x) g(y) g(z)</math>, where
289 !% <math>g(x) = \sum_{i} 1/(1+e^{-{\tt fact} (x-{\tt startpoint}_i)}) - 1/(1+e^{-{\tt fact} (x-{\tt endpoint}_i)})</math>.
290 !% If not specified, <math>g(x) = 1</math>.
291 !%
292 !% Each <math>g(x)</math> is represented by one line of the block that has the following form
293 !%
294 !% <tt>%OCTSpatialCurrWeight
295 !% <br>&nbsp;&nbsp; dimension | fact | startpoint_1 | endpoint_1 | startpoint_2 | endpoint_2 |...
296 !% <br>%</tt>
297 !%
298 !% There are no restrictions on the number of lines, nor on the number of pairs of start- and endpoints.
299 !% Attention: <tt>startpoint</tt> and <tt>endpoint</tt> have to be supplied pairwise
300 !% with <tt>startpoint < endpoint</tt>. <tt>dimension > 0</tt> is integer, <tt>fact</tt> is float.
301 !%End
302
303 call parse_variable(namespace, 'OCTCurrentFunctional', oct_no_curr, tg%curr_functional)
304 select case (tg%curr_functional)
305 case (oct_no_curr)
307 if (.not. allocated(stin%current)) then
308 safe_allocate(stin%current( 1:gr%np_part, 1:space%dim, 1:stin%d%nspin))
309 stin%current= m_zero
310 end if
311 end select
312
313 call parse_variable(namespace, 'OCTCurrentWeight', m_zero, tg%curr_weight)
314 write(message(1), '(a,i3)') 'Info: OCTCurrentFunctional = ', tg%curr_functional
315 write(message(2), '(a,f8.3)') 'Info: OCTCurrentWeight = ', tg%curr_weight
316 call messages_info(2, namespace=namespace)
317
318 if (target_mode(tg) == oct_targetmode_td) then
319 call parse_variable(namespace, 'OCTStartIterCurrTg', 0, tg%strt_iter_curr_tg)
320 if (tg%strt_iter_curr_tg < 0) then
321 call messages_input_error(namespace, 'OCTStartIterCurrTg', 'Must be positive.')
322 elseif (tg%strt_iter_curr_tg >= td%max_iter) then
323 call messages_input_error(namespace, 'OCTStartIterCurrTg', 'Has to be < TDMaximumIter.')
324 end if
325 write(message(1), '(a,i3)') 'Info: TargetMode = ', target_mode(tg)
326 write(message(2), '(a,i8)') 'Info: OCTStartIterCurrTg = ', tg%strt_iter_curr_tg
327 call messages_info(2, namespace=namespace)
328 tg%dt = td%dt
329 safe_allocate(tg%td_fitness(0:td%max_iter))
330 tg%td_fitness = m_zero
331 else
332 tg%strt_iter_curr_tg = 0
333 end if
334
335 if (parse_is_defined(namespace, 'OCTSpatialCurrWeight')) then
336 if (parse_block(namespace, 'OCTSpatialCurrWeight', blk) == 0) then
337 safe_allocate(tg%spatial_curr_wgt(1:gr%np_part))
338 safe_allocate(xp(1:gr%np_part))
339 safe_allocate(tmp_box(1:gr%np_part, 1:space%dim))
340
341 no_constraint = parse_block_n(blk)
342 tmp_box = m_zero
343 cstr_dim = 0
344 do ib = 1, no_constraint
345 call parse_block_integer(blk, ib - 1, 0, idim)
346 if (idim <= 0 .or. idim > space%dim) then
347 write(message(1), '(a,i3)') 'Error in "OCTSpatialCurrWeight" block, line:', ib
348 write(message(2), '(a)' ) '"dimension" has to be positive'
349 write(message(3), '(a)' ) 'and must not exceed dimensions of the system.'
350 call messages_fatal(3, namespace=namespace)
351 end if
352 cstr_dim(idim) = 1
353 xp(1:gr%np_part) = gr%x_t(1:gr%np_part, idim)
354
355 call parse_block_float(blk, ib - 1, 1, fact)
356
357 no_ptpair = parse_block_cols(blk, ib-1) - 2
358 if (mod(no_ptpair,2) /= 0) then
359 write(message(1), '(a,i3)') 'Error in "OCTSpatialCurrWeight" block, line:', ib
360 write(message(2), '(a)' ) 'Each interval needs start and end point!'
361 call messages_fatal(2, namespace=namespace)
362 end if
363
364 do jj= 2, no_ptpair, 2
365 call parse_block_float(blk, ib - 1, jj, xstart)
366 call parse_block_float(blk, ib - 1, jj+1, xend)
367
368 if (xstart >= xend) then
369 write(message(1), '(a,i3)') 'Error in "OCTSpatialCurrWeight" block, line:', ib
370 write(message(2), '(a)' ) 'Set "startpoint" < "endpoint" '
371 call messages_fatal(2, namespace=namespace)
372 end if
373
374 do ip = 1, gr%np_part
375 tmp_box(ip,idim) = tmp_box(ip,idim) + m_one/(m_one+exp(-fact*(xp(ip)-xstart))) - &
376 m_one/(m_one+exp(-fact*(xp(ip)-xend)))
377 end do
378 end do
379
380 end do
381
382 do idim = 1, space%dim
383 if (cstr_dim(idim) == 0) tmp_box(:,idim) = m_one
384 end do
385 tg%spatial_curr_wgt(1:gr%np_part) = product(tmp_box(1:gr%np_part, 1:space%dim),2)
386 safe_deallocate_a(xp)
387 safe_deallocate_a(tmp_box)
388
389 call parse_block_end(blk)
390 else
391 call messages_input_error(namespace, 'OCTSpatialCurrWeight', 'Has to be specified as a block.')
392 end if
393 end if
394
395 nullify(stin)
396 pop_sub(target_init_density)
397 end subroutine target_init_density
398
399
400 ! ----------------------------------------------------------------------
402 subroutine target_end_density(tg, oct)
403 class(target_density_t), intent(inout) :: tg
404 type(oct_t), intent(in) :: oct
405
406 push_sub(target_end_density)
407
408 safe_deallocate_a(tg%rho)
409 safe_deallocate_a(tg%spatial_curr_wgt)
410 select case (tg%curr_functional)
411 case (oct_curr_square_td)
412 safe_deallocate_a(tg%td_fitness)
413 end select
414
415 pop_sub(target_end_density)
416 end subroutine target_end_density
417
418
419 ! ----------------------------------------------------------------------
420 subroutine target_output_density(tg, namespace, space, gr, dir, ions, hm, outp)
421 class(target_density_t), intent(inout) :: tg
422 type(namespace_t), intent(in) :: namespace
423 class(space_t), intent(in) :: space
424 type(grid_t), intent(in) :: gr
425 character(len=*), intent(in) :: dir
426 type(ions_t), intent(in) :: ions
427 type(hamiltonian_elec_t), intent(in) :: hm
428 type(output_t), intent(in) :: outp
429
430 integer :: ierr
431 push_sub(target_output_density)
432
433 call io_mkdir(trim(dir), namespace)
434
435 if (tg%density_weight > m_zero) then
436 call dio_function_output(outp%how(0), trim(dir), 'density_target', namespace, space, gr, &
437 tg%rho, units_out%length**(-space%dim), ierr, pos=ions%pos, atoms=ions%atom)
438 end if
439
440
441 pop_sub(target_output_density)
442 end subroutine target_output_density
443 ! ----------------------------------------------------------------------
444
445
446 ! ----------------------------------------------------------------------
448 real(real64) function target_j1_density(tg, namespace, gr, kpoints, qcpsi, ions) result(j1)
449 class(target_density_t), intent(inout) :: tg
450 type(namespace_t), intent(in) :: namespace
451 type(grid_t), intent(in) :: gr
452 type(kpoints_t), intent(in) :: kpoints
453 type(opt_control_state_t), intent(inout) :: qcpsi
454 type(ions_t), optional, intent(in) :: ions
455
456 integer :: ip, maxiter
457 real(real64) :: currfunc_tmp
458 real(real64), allocatable :: local_function(:)
459 type(states_elec_t), pointer :: psi
460
461 push_sub(target_j1_density)
462
463 psi => opt_control_point_qs(qcpsi)
464
465 if (tg%density_weight > m_zero) then
466 safe_allocate(local_function(1:gr%np))
467 do ip = 1, gr%np
468 local_function(ip) = - ( sqrt(psi%rho(ip, 1)) - sqrt(tg%rho(ip)) )**2
469 end do
470 j1 = tg%density_weight * dmf_integrate(gr, local_function)
471 safe_deallocate_a(local_function)
472 else
473 j1 = m_zero
474 end if
475
476 ! current functionals are conveniently combined with others
477 if (tg%curr_functional /= oct_no_curr) then
478 select case (target_mode(tg))
480 currfunc_tmp = jcurr_functional(tg, gr, kpoints, psi)
481 case (oct_targetmode_td)
482 maxiter = size(tg%td_fitness) - 1
483 currfunc_tmp = m_half * tg%dt * tg%td_fitness(tg%strt_iter_curr_tg) + &
484 m_half * tg%dt * tg%td_fitness(maxiter) + &
485 tg%dt * sum(tg%td_fitness(tg%strt_iter_curr_tg+1:maxiter-1))
486 end select
487 if (conf%devel_version) then
488 write(message(1), '(6x,a,f12.5)') " => Other functional = ", j1
489 write(message(2), '(6x,a,f12.5)') " => Current functional = ", currfunc_tmp
490 call messages_info(2)
491 end if
492 ! accumulating functional values
493 j1 = j1 + currfunc_tmp
494 end if
495
496 nullify(psi)
497 pop_sub(target_j1_density)
498 end function target_j1_density
499
500
501 ! ----------------------------------------------------------------------
503 subroutine target_chi_density(tg, namespace, gr, kpoints, qcpsi_in, qcchi_out, ions)
504 class(target_density_t), intent(inout) :: tg
505 type(namespace_t), intent(in) :: namespace
506 type(grid_t), intent(in) :: gr
507 type(kpoints_t), intent(in) :: kpoints
508 type(opt_control_state_t), target, intent(inout) :: qcpsi_in
509 type(opt_control_state_t), target, intent(inout) :: qcchi_out
510 type(ions_t), intent(in) :: ions
511
512 integer :: no_electrons, ip, ist, ib, ik
513 complex(real64), allocatable :: zpsi(:, :)
514 type(states_elec_t), pointer :: psi_in, chi_out
516 push_sub(target_chi_density)
517
518 psi_in => opt_control_point_qs(qcpsi_in)
519 chi_out => opt_control_point_qs(qcchi_out)
520
521 do ik = chi_out%d%kpt%start, chi_out%d%kpt%end
522 do ib = chi_out%group%block_start, chi_out%group%block_end
523 call batch_set_zero(chi_out%group%psib(ib, ik))
524 end do
525 end do
526
527 no_electrons = -nint(psi_in%val_charge)
528
529 if (tg%density_weight > m_zero) then
530
531 select case (psi_in%d%ispin)
532 case (unpolarized)
533 assert(psi_in%nik == 1)
534
535 safe_allocate(zpsi(1:gr%np, 1))
536
537 if (no_electrons == 1) then
538
539 call states_elec_get_state(psi_in, gr, 1, 1, zpsi)
540
541 do ip = 1, gr%np
542 zpsi(ip, 1) = sqrt(tg%rho(ip))*exp(m_zi*atan2(aimag(zpsi(ip, 1)), real(zpsi(ip, 1),real64) ))
543 end do
544
545 call states_elec_set_state(chi_out, gr, 1, 1, zpsi)
546
547 else
548 do ist = psi_in%st_start, psi_in%st_end
549
550 call states_elec_get_state(psi_in, gr, ist, 1, zpsi)
551
552 do ip = 1, gr%np
553 if (psi_in%rho(ip, 1) > 1.0e-8_real64) then
554 zpsi(ip, 1) = psi_in%occ(ist, 1)*sqrt(tg%rho(ip)/psi_in%rho(ip, 1))*zpsi(ip, 1)
555 else
556 zpsi(ip, 1) = m_zero !sqrt(tg%rho(ip))
557 end if
558 end do
559
560 call states_elec_set_state(chi_out, gr, ist, 1, zpsi)
561
562 end do
563 end if
564
565 case (spin_polarized)
566 message(1) = 'Error in target.target_chi_density: spin_polarized.'
567 call messages_fatal(1)
568 case (spinors)
569 message(1) = 'Error in target.target_chi_density: spinors.'
570 call messages_fatal(1)
571 end select
572
573 end if
574
575 if (tg%curr_functional /= oct_no_curr) then
576 if (target_mode(tg) == oct_targetmode_static) then
577 call chi_current(tg, gr, kpoints, m_one, psi_in, chi_out)
578 end if
579 end if
580
581 nullify(psi_in)
582 nullify(chi_out)
583 pop_sub(target_chi_density)
584 end subroutine target_chi_density
585
586
587 ! ---------------------------------------------------------
590 subroutine target_tdcalc_density(tg, namespace, space, hm, gr, ions, ext_partners, psi, time, max_time)
591 class(target_density_t), intent(inout) :: tg
592 type(namespace_t), intent(in) :: namespace
593 class(space_t), intent(in) :: space
594 type(hamiltonian_elec_t), intent(inout) :: hm
595 type(grid_t), intent(in) :: gr
596 type(ions_t), intent(inout) :: ions
597 type(partner_list_t), intent(in) :: ext_partners
598 type(states_elec_t), intent(inout) :: psi
599 integer, intent(in) :: time
600 integer, intent(in) :: max_time
601
602 push_sub(target_tdcalc_density)
603
604 tg%td_fitness(time) = m_zero
605
606 if (time >= tg%strt_iter_curr_tg) then
607 tg%td_fitness(time) = jcurr_functional(tg, gr, hm%kpoints, psi)
608 end if
609
610
611 pop_sub(target_tdcalc_density)
612 end subroutine target_tdcalc_density
613 ! ----------------------------------------------------------------------
614
615
616 ! ---------------------------------------------------------------
618 subroutine target_inh_density(tg, psi, gr, kpoints, time, inh, iter)
619 class(target_density_t), intent(inout) :: tg
620 type(states_elec_t), intent(inout) :: psi
621 type(grid_t), intent(in) :: gr
622 type(kpoints_t), intent(in) :: kpoints
623 real(real64), intent(in) :: time
624 type(states_elec_t), intent(inout) :: inh
625 integer, intent(in) :: iter
626
627 integer :: ik, ib
628
629 push_sub(target_inh_density)
630
631 do ik = inh%d%kpt%start, inh%d%kpt%end
632 do ib = inh%group%block_start, inh%group%block_end
633 call batch_set_zero(inh%group%psib(ib, ik))
634 end do
635 end do
636
637 if (abs(nint(time/tg%dt)) >= tg%strt_iter_curr_tg) then
638 call chi_current(tg, gr, kpoints, -1.0_real64, psi, inh)
639 end if
640
641 pop_sub(target_inh_density)
642 end subroutine target_inh_density
643 !----------------------------------------------------------
644
645
646 ! ----------------------------------------------------------------------
649 real(real64) function jcurr_functional(tg, gr, kpoints, psi) result(jcurr)
650 type(target_density_t), intent(in) :: tg
651 type(grid_t), intent(in) :: gr
652 type(kpoints_t), intent(in) :: kpoints
653 type(states_elec_t), intent(inout) :: psi
654
655 integer :: ip
656 real(real64), allocatable :: semilocal_function(:)
657
658 push_sub(jcurr_functional)
659
660 jcurr = m_zero
661 assert(psi%nik == 1)
662 safe_allocate(semilocal_function(1:gr%np))
663 semilocal_function = m_zero
664
665 select case (tg%curr_functional)
666 case (oct_no_curr)
667 semilocal_function = m_zero
668
669 case (oct_curr_square,oct_curr_square_td)
670 call states_elec_calc_quantities(gr, psi, kpoints, .false., paramagnetic_current=psi%current)
671 do ip = 1, gr%np
672 semilocal_function(ip) = sum(psi%current(ip, 1:gr%box%dim, 1)**2)
673 end do
674
675 case (oct_max_curr_ring)
676 call states_elec_calc_quantities(gr, psi, kpoints, .false., paramagnetic_current=psi%current)
677
678 if (gr%box%dim /= 2) then
679 call messages_not_implemented('Target for dimension != 2')
680 end if
681
682 do ip = 1, gr%np
683 ! func = j_y * x - j_x * y
684 semilocal_function(ip) = psi%current(ip, 2, 1) * gr%x(1, ip) - &
685 psi%current(ip, 1, 1) * gr%x(2, ip)
686 end do
687 case default
688 message(1) = 'Error in target.jcurr_functional: chosen target does not exist'
689 call messages_fatal(1)
690 end select
691
692
693 if (is_spatial_curr_wgt(tg)) then
694 do ip = 1, gr%np
695 semilocal_function(ip) = semilocal_function(ip) * tg%spatial_curr_wgt(ip)
696 end do
697 end if
698
699 jcurr = tg%curr_weight * dmf_integrate(gr, semilocal_function)
700
701 safe_deallocate_a(semilocal_function)
702
703 pop_sub(jcurr_functional)
704 end function jcurr_functional
705 !-----------------------------------------------------------------------
706
707 ! ----------------------------------------------------------------------
708 ! Calculates current-specific boundary condition
709 !-----------------------------------------------------------------------
710 subroutine chi_current(tg, gr, kpoints, factor, psi_in, chi)
711 type(target_density_t), intent(in) :: tg
712 type(grid_t), intent(in) :: gr
713 type(kpoints_t), intent(in) :: kpoints
714 real(real64), intent(in) :: factor
715 type(states_elec_t), intent(inout) :: psi_in
716 type(states_elec_t), intent(inout) :: chi
717
718 complex(real64), allocatable :: grad_psi_in(:,:,:), zpsi(:, :), zchi(:, :)
719 real(real64), allocatable :: div_curr_psi_in(:,:)
720 integer :: ip, ist, idim
721
722 push_sub(chi_current)
723 safe_allocate(grad_psi_in(1:gr%np_part, 1:gr%box%dim, 1))
724
725 if (target_mode(tg) == oct_targetmode_td) then
726 call states_elec_calc_quantities(gr, psi_in, kpoints, .false., paramagnetic_current=psi_in%current)
727 end if
728
729 select case (tg%curr_functional)
730 case (oct_no_curr)
731 !nothing to do
732
733 case (oct_curr_square,oct_curr_square_td)
734 ! components current weighted by its position in the mesh, np_part included,
735 ! since needed for the divergence of current.
736 if (is_spatial_curr_wgt(tg)) then
737 do idim = 1, gr%box%dim
738 do ip = 1, gr%np_part
739 psi_in%current(ip, idim, 1) = psi_in%current(ip, idim, 1) * tg%spatial_curr_wgt(ip)
740 end do
741 end do
742 end if
743
744 safe_allocate(div_curr_psi_in(1:gr%np_part, 1))
745 safe_allocate(zpsi(1:gr%np_part, 1:psi_in%d%dim))
746 safe_allocate(zchi(1:gr%np_part, 1:psi_in%d%dim))
747
748 call dderivatives_div(gr%der, psi_in%current(:, :, 1), div_curr_psi_in(:,1))
749
750 ! the boundary condition
751 do ist = psi_in%st_start, psi_in%st_end
752
753 call states_elec_get_state(psi_in, gr, ist, 1, zpsi)
754 call states_elec_get_state(chi, gr, ist, 1, zchi)
755
756 call zderivatives_grad(gr%der, zpsi(:, 1), grad_psi_in(:, :, 1))
757
758 do idim = 1, psi_in%d%dim
759 do ip = 1, gr%np
760 zchi(ip, idim) = zchi(ip, idim) - factor*m_zi*tg%curr_weight* &
761 (m_two*sum(psi_in%current(ip, 1:gr%box%dim, 1)*grad_psi_in(ip, 1:gr%box%dim, 1)) + &
762 div_curr_psi_in(ip, 1)*zpsi(ip, idim))
763 end do
764 end do
765
766 call states_elec_set_state(chi, gr, ist, 1, zchi)
767
768 end do
769
770 safe_deallocate_a(div_curr_psi_in)
771 safe_deallocate_a(zpsi)
772 safe_deallocate_a(zchi)
773
774 case (oct_max_curr_ring)
775
776 safe_allocate(zpsi(1:gr%np_part, 1:psi_in%d%dim))
777 safe_allocate(zchi(1:gr%np_part, 1:psi_in%d%dim))
778
779 do ist = psi_in%st_start, psi_in%st_end
780
781 call states_elec_get_state(psi_in, gr, ist, 1, zpsi)
782 call states_elec_get_state(chi, gr, ist, 1, zchi)
783
784 call zderivatives_grad(gr%der, zpsi(:, 1), grad_psi_in(:, :, 1))
785
786 if (is_spatial_curr_wgt(tg)) then
787
788 do ip = 1, gr%np
789 zchi(ip, 1) = zchi(ip, 1) + factor*m_zi*tg%curr_weight*tg%spatial_curr_wgt(ip)* &
790 (grad_psi_in(ip, 1, 1)*gr%x(2, ip) - grad_psi_in(ip, 2, 1)*gr%x(1, ip))
791 end do
792
793 else
794
795 do ip = 1, gr%np
796 zchi(ip, 1) = zchi(ip, 1) + factor*m_zi*tg%curr_weight* &
797 (grad_psi_in(ip, 1, 1)*gr%x(2, ip) - grad_psi_in(ip, 2, 1)*gr%x(1, ip))
798 end do
799
800 end if
801
802 call states_elec_set_state(chi, gr, ist, 1, zchi)
803
804 end do
806 safe_deallocate_a(zpsi)
807 safe_deallocate_a(zchi)
808
809 case default
810 message(1) = 'Error in target.chi_current: chosen target does not exist'
811 call messages_fatal(1)
812 end select
813
814 safe_deallocate_a(grad_psi_in)
815 pop_sub(chi_current)
816 end subroutine chi_current
817 ! ----------------------------------------------------------------------
818
819
820 ! ----------------------------------------------------------------------
821 logical pure function is_spatial_curr_wgt(tg)
822 type(target_density_t), intent(in) :: tg
823
824 is_spatial_curr_wgt = allocated(tg%spatial_curr_wgt)
825
826 end function is_spatial_curr_wgt
827 ! ----------------------------------------------------------------------
828
829end module target_density_oct_m
830
831!! Local Variables:
832!! mode: f90
833!! coding: utf-8
834!! End:
double exp(double __x) __attribute__((__nothrow__
double sqrt(double __x) __attribute__((__nothrow__
double atan2(double __y, double __x) __attribute__((__nothrow__
This module implements common operations on batches of mesh functions.
Definition: batch_ops.F90:118
This module implements a calculator for the density and defines related functions.
Definition: density.F90:122
subroutine, public density_calc(st, gr, density, istin)
Computes the density from the orbitals in st.
Definition: density.F90:653
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
real(real64), parameter, public m_zero
Definition: global.F90:200
type(conf_t), public conf
Global instance of Octopus configuration.
Definition: global.F90:190
complex(real64), parameter, public m_z1
Definition: global.F90:211
real(real64), parameter, public m_half
Definition: global.F90:206
real(real64), parameter, public m_one
Definition: global.F90:201
This module implements the underlying real-space grid.
Definition: grid.F90:119
This module defines classes and functions for interaction partners.
subroutine, public dio_function_output(how, dir, fname, namespace, space, mesh, ff, unit, ierr, pos, atoms, grp, root)
Top-level IO routine for functions defined on the mesh.
Definition: io.F90:116
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:361
This module is intended to contain "only mathematical" functions and procedures.
Definition: math.F90:117
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
Definition: mesh.F90:120
pure subroutine, public mesh_r(mesh, ip, rr, origin, coords)
return the distance to the origin for a given grid point
Definition: mesh.F90:342
subroutine, public messages_variable_is_block(namespace, name)
Definition: messages.F90:1024
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
subroutine, public messages_input_error(namespace, var, details, row, column)
Definition: messages.F90:691
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
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.
type(states_elec_t) function, pointer, public opt_control_point_qs(ocs)
this module contains the low-level part of the output system
Definition: output_low.F90:117
logical function, public parse_is_defined(namespace, name)
Definition: parser.F90:463
integer function, public parse_block(namespace, name, blk, check_varinfo_)
Definition: parser.F90:623
pure logical function, public states_are_real(st)
subroutine, public states_elec_end(st)
finalize the states_elec_t object
subroutine, public states_elec_deallocate_wfns(st)
Deallocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_copy(stout, stin, exclude_wfns, exclude_eigenval, special)
make a (selective) copy of a states_elec_t object
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_look_and_load(restart, namespace, space, st, mesh, kpoints, fixed_occ, is_complex, packed)
subroutine, public conv_to_c_string(str)
converts to c string
Definition: string.F90:234
logical pure function is_spatial_curr_wgt(tg)
subroutine target_chi_density(tg, namespace, gr, kpoints, qcpsi_in, qcchi_out, ions)
subroutine target_tdcalc_density(tg, namespace, space, hm, gr, ions, ext_partners, psi, time, max_time)
subroutine target_inh_density(tg, psi, gr, kpoints, time, inh, iter)
Inhomogeneous term for the current density target.
subroutine target_end_density(tg, oct)
real(real64) function target_j1_density(tg, namespace, gr, kpoints, qcpsi, ions)
subroutine target_init_density(tg, gr, kpoints, namespace, space, ions, qcs, td, w0, oct, ep, restart)
subroutine chi_current(tg, gr, kpoints, factor, psi_in, chi)
subroutine target_output_density(tg, namespace, space, gr, dir, ions, hm, outp)
real(real64) function jcurr_functional(tg, gr, kpoints, psi)
Calculates a current functional that may be combined with other functionals found in function target_...
Optimal-control targets: abstract base class and public interface.
Definition: target.F90:132
integer, parameter, public oct_targetmode_static
Definition: target.F90:261
integer, parameter, public oct_targetmode_td
Definition: target.F90:261
integer, parameter, public oct_max_curr_ring
Definition: target.F90:265
integer, parameter, public oct_no_curr
Definition: target.F90:265
integer, parameter, public oct_curr_square_td
Definition: target.F90:265
integer, parameter, public oct_curr_square
Definition: target.F90:265
integer pure function, public target_mode(tg)
Definition: target.F90:497
Definition: td.F90:116
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
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
The states_elec_t class contains all electronic wave functions.
Target on the density and/or the current.
Abstract optimal-control target.
Definition: target.F90:172
int true(void)