Octopus
static_pol.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#define RESTART_FILE 'dipoles'
21
24 use debug_oct_m
25 use elf_oct_m
27 use global_oct_m
30 use io_oct_m
32 use ions_oct_m
33 use, intrinsic :: iso_fortran_env
34 use lcao_oct_m
37 use mpi_oct_m
40 use parser_oct_m
43 use scf_oct_m
44 use space_oct_m
49 use unit_oct_m
51 use utils_oct_m
52 use v_ks_oct_m
53
54 implicit none
55
56 private
57 public :: &
59
60
61contains
62
63 ! ---------------------------------------------------------
64 subroutine static_pol_run(system, from_scratch)
65 class(*), intent(inout) :: system
66 logical, intent(in) :: from_scratch
67
68 push_sub(static_pol_run)
69
70 select type (system)
71 class is (multisystem_basic_t)
72 message(1) = "CalculationMode = static_pol not implemented for multi-system calculations"
73 call messages_fatal(1, namespace=system%namespace)
74 type is (electrons_t)
75 call static_pol_run_legacy(system, from_scratch)
76 class default
77 assert(.false.)
78 end select
79
80 pop_sub(static_pol_run)
81 end subroutine static_pol_run
82
83 ! ---------------------------------------------------------
84 subroutine static_pol_run_legacy(sys, fromScratch)
85 type(electrons_t), intent(inout) :: sys
86 logical, intent(in) :: fromScratch
87
88 type(scf_t) :: scfv
89 integer :: iunit, ios, i_start, ii, jj, is, isign, ierr, read_count, verbosity, ip
90 real(real64) :: e_field, e_field_saved
91 real(real64), allocatable :: Vpsl_save(:), trrho(:), dipole(:, :, :)
92 real(real64), allocatable :: elf(:,:), lr_elf(:,:), elfd(:,:), lr_elfd(:,:)
93 real(real64), allocatable :: lr_rho(:,:), lr_rho2(:,:), gs_rho(:,:), tmp_rho(:,:)
94 real(real64) :: center_dipole(1:sys%space%dim), diag_dipole(1:sys%space%dim), ionic_dipole(1:sys%space%dim), &
95 print_dipole(1:sys%space%dim)
96 type(born_charges_t) :: born_charges
97 logical :: calc_born, start_density_is_zero_field, write_restart_densities, calc_diagonal, verbose
98 logical :: diagonal_done, center_written, fromScratch_local, field_written
99 character(len=MAX_PATH_LEN) :: fname, dir_name
100 character(len=120) :: line(1)
101 character :: sign_char
102 type(restart_t) :: gs_restart, restart_load, restart_dump
103
104 push_sub(static_pol_run_legacy)
105
106 if (sys%hm%pcm%run_pcm) then
107 call messages_not_implemented("PCM for CalculationMode /= gs or td", namespace=sys%namespace)
108 end if
109
110 if (sys%kpoints%use_symmetries) then
111 call messages_experimental("KPoints symmetries with CalculationMode = em_resp", namespace=sys%namespace)
112 end if
113
114 call init_()
115
116 ! load wavefunctions
117 call gs_restart%init(sys%namespace, restart_gs, restart_type_load, sys%mc, ierr, mesh=sys%gr, exact=.true.)
118 if (ierr == 0) then
119 call states_elec_load(gs_restart, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
120 fixed_occ=.false., ierr=ierr)
121 end if
122 if (ierr /= 0) then
123 message(1) = "Unable to read wavefunctions."
124 call messages_fatal(1, namespace=sys%namespace)
125 end if
126 call gs_restart%end()
127
128 if (sys%space%is_periodic()) then
129 message(1) = "Electric field cannot be applied to a periodic system (currently)."
130 call messages_fatal(1, namespace=sys%namespace)
131 end if
132
133 ! set up Hamiltonian
134 message(1) = 'Info: Setting up Hamiltonian.'
135 call messages_info(1, namespace=sys%namespace)
136 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, &
137 sys%hm, calc_eigenval = .false.) ! we read them from restart
138
139 ! Allocate the dipole
140 safe_allocate(dipole(1:sys%space%dim, 1:sys%space%dim, 1:2))
141 dipole = m_zero
142
143 i_start = 1
144 center_written = .false.
145 diagonal_done = .false.
146 field_written = .false.
147
148 call restart_dump%init(sys%namespace, restart_em_resp_fd, restart_type_dump, sys%mc, ierr, mesh=sys%gr)
149
150 if (.not. fromscratch) then
151 call restart_load%init(sys%namespace, restart_em_resp_fd, restart_type_load, sys%mc, ierr, mesh=sys%gr)
152 if (ierr == 0) then
153 iunit = restart_load%open(restart_file)
154 else
155 iunit = -1
156 end if
157
158 if (iunit /= -1) then
159 ! Finds out how many dipoles have already been written.
160 rewind(iunit)
161
162 read(iunit, fmt=*, iostat = ios) e_field_saved
163 field_written = (ios == 0)
164
165 read(iunit, fmt=*, iostat = ios) (center_dipole(jj), jj = 1, sys%space%dim)
166 center_written = (ios == 0)
167
168 do ii = 1, sys%space%dim
169 read(iunit, fmt=*, iostat = ios) ((dipole(ii, jj, isign), jj = 1, sys%space%dim), isign = 1, 2)
170 if (ios /= 0) exit
171 i_start = i_start + 1
172 end do
173
174 read(iunit, fmt=*, iostat = ios) (diag_dipole(jj), jj = 1, sys%space%dim)
175 diagonal_done = (ios == 0)
176
177 call restart_load%close(iunit)
178 end if
180 ! if saved dipoles used a different e_field, we cannot use them
181 if (field_written .and. abs(e_field_saved - e_field) > m_epsilon) then
182 message(1) = "Saved dipoles are from a different electric field, cannot use them."
183 call messages_warning(1, namespace=sys%namespace)
184 center_written = .false.
185 diagonal_done = .false.
186 i_start = 1
187 end if
188
189 read_count = (i_start - 1) * 2
190 if (center_written) read_count = read_count + 1
191 if (diagonal_done) read_count = read_count + 1
192 write(message(1),'(a,i5,a)') "Using ", read_count, " dipole(s) from file."
193 call messages_info(1, namespace=sys%namespace)
194 end if
195
196 if (sys%outp%what(option__output__density) .or. &
197 sys%outp%what(option__output__pol_density)) then
198 if (i_start > 2 .and. calc_diagonal) then
199 i_start = 2
200 diagonal_done = .false.
201 !FIXME: take derivatives between yz and z (not y) so can restart from only last (z) calc
202 end if
203 end if
204
205 if (i_start == 1) then
206 ! open new file, erase old data, write e_field
207 iunit = restart_dump%open(restart_file, status='replace')
208 write(line(1), fmt='(e20.12)') e_field
209 call restart_dump%write(iunit, line, 1, ierr)
210 if (ierr /= 0) then
211 message(1) = "Unsuccessful write of electric field."
212 call messages_warning(1, namespace=sys%namespace)
213 end if
214 call restart_dump%close(iunit)
215 center_written = .false.
216 end if
217
218 ! Save local potential
219 safe_allocate(vpsl_save(1:sys%gr%np))
220 vpsl_save = sys%hm%ep%Vpsl
221
222 ! Allocate the trrho to contain the trace of the density.
223 safe_allocate(trrho(1:sys%gr%np))
224 safe_allocate(gs_rho(1:sys%gr%np, 1:sys%st%d%nspin))
225 safe_allocate(tmp_rho(1:sys%gr%np, 1:sys%st%d%nspin))
226 trrho = m_zero
227 gs_rho = m_zero
228
229 call output_init_()
230 call scf_init(scfv, sys%namespace, sys%gr, sys%ions, sys%st, sys%mc, sys%hm, sys%space)
231 call born_charges_init(born_charges, sys%namespace, sys%ions%natoms, sys%st%val_charge, &
232 sys%st%qtot, sys%space%dim)
233
234 ! now calculate the dipole without field
235
236 sys%hm%ep%vpsl(1:sys%gr%np) = vpsl_save(1:sys%gr%np)
237 call sys%hm%update(sys%gr, sys%namespace, sys%space, sys%ext_partners)
238
239 write(message(1), '(a)')
240 write(message(2), '(a)') 'Info: Calculating dipole moment for zero field.'
241 call messages_info(2, namespace=sys%namespace)
242 call scf_run(scfv, sys%namespace, sys%space, sys%mc, sys%gr, sys%ions, sys%ext_partners, sys%st, &
243 sys%ks, sys%hm, verbosity = verbosity)
244
245 gs_rho(1:sys%gr%np, 1:sys%st%d%nspin) = sys%st%rho(1:sys%gr%np, 1:sys%st%d%nspin)
246 trrho = m_zero
247 do is = 1, sys%st%d%spin_channels
248 call lalg_axpy(sys%gr%np, m_one, gs_rho(:, is), trrho)
249 end do
250
251 ! calculate dipole
252 do jj = 1, sys%space%dim
253 center_dipole(jj) = dmf_moment(sys%gr, trrho, jj, 1)
254 end do
255
256 ! Writes the dipole to file
257 if (.not. center_written) then
258 iunit = restart_dump%open(restart_file, position='append')
259 write(line(1), fmt='(6e20.12)') (center_dipole(jj), jj = 1, sys%space%dim)
260 call restart_dump%write(iunit, line, 1, ierr)
261 if (ierr /= 0) then
262 message(1) = "Unsuccessful write of center dipole."
263 call messages_warning(1, namespace=sys%namespace)
264 end if
265 call restart_dump%close(iunit)
266 end if
267
268 if (mpi_world%is_root()) then
269 ionic_dipole(1:sys%space%dim) = sys%ions%dipole()
270 print_dipole(1:sys%space%dim) = center_dipole(1:sys%space%dim) + ionic_dipole(1:sys%space%dim)
271 call output_dipole(print_dipole, sys%space%dim, namespace=sys%namespace)
272 end if
273
274 do ii = i_start, sys%space%dim
275 do isign = 1, 2
276 write(message(1), '(a)')
277 write(message(2), '(a,f6.4,5a)') 'Info: Calculating dipole moment for field ', &
278 units_from_atomic(units_out%force, (-1)**isign * e_field), ' ', &
279 trim(units_abbrev(units_out%force)), ' in the ', index2axis(ii), '-direction.'
280 call messages_info(2, namespace=sys%namespace)
281 ! there would be an extra factor of -1 in here that is for the electronic charge
282 ! except that we treat electrons as positive
283
284 !$omp parallel do
285 do ip = 1, sys%gr%np
286 sys%hm%ep%vpsl(ip) = vpsl_save(ip) + (-1)**isign * sys%gr%x_t(ip, ii) * e_field
287 end do
288 !$omp end parallel do
289 call sys%hm%update(sys%gr, sys%namespace, sys%space, sys%ext_partners)
290
291 if (isign == 1) then
292 sign_char = '+'
293 else
294 sign_char = '-'
295 end if
296
297 write(dir_name,'(a)') "field_"//index2axis(ii)//sign_char
298 fromscratch_local = fromscratch
299
300 if (.not. fromscratch) then
301 call restart_load%open_dir(trim(dir_name), ierr)
302 if (ierr == 0) then
303 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
304 fixed_occ=.false., ierr=ierr)
305 end if
306 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
307 if (ierr /= 0) fromscratch_local = .true.
308 call restart_load%close_dir()
309 end if
310
311 if (fromscratch_local) then
312 if (start_density_is_zero_field) then
313 sys%st%rho(1:sys%gr%np, 1:sys%st%d%nspin) = gs_rho(1:sys%gr%np, 1:sys%st%d%nspin)
314 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
315 else
316 call lcao_run(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, &
317 sys%hm, lmm_r = scfv%lmm_r)
318 end if
319 end if
320
321 call scf_mix_clear(scfv)
322 call scf_run(scfv, sys%namespace, sys%space, sys%mc, sys%gr, sys%ions, sys%ext_partners, sys%st, &
323 sys%ks, sys%hm, verbosity = verbosity)
324
325 trrho = m_zero
326 do is = 1, sys%st%d%spin_channels
327 call lalg_axpy(sys%gr%np, m_one, sys%st%rho(:, is), trrho)
328 end do
329
330 ! calculate dipole
331 do jj = 1, sys%space%dim
332 dipole(ii, jj, isign) = dmf_moment(sys%gr, trrho, jj, 1)
333 end do
334
335 if (mpi_world%is_root()) then
336 print_dipole(1:sys%space%dim) = dipole(ii, 1:sys%space%dim, isign) + ionic_dipole(1:sys%space%dim)
337 call output_dipole(print_dipole, sys%space%dim, namespace=sys%namespace)
338 end if
339
340 call output_cycle_()
341
342 if (write_restart_densities) then
343 call restart_dump%open_dir(trim(dir_name), ierr)
344 if (ierr == 0) then
345 call states_elec_dump(restart_dump, sys%space, sys%st, sys%gr, sys%kpoints, ierr)
346 end if
347 call restart_dump%close_dir()
348 if (ierr /= 0) then
349 message(1) = 'Unable to write states wavefunctions.'
350 call messages_warning(1, namespace=sys%namespace)
351 end if
352 end if
353 end do
354
355 ! Writes the dipole to file
356 iunit = restart_dump%open(restart_file, position='append')
357 write(line(1), '(6e20.12)') ((dipole(ii, jj, isign), jj = 1, sys%space%dim), isign = 1, 2)
358 call restart_dump%write(iunit, line, 1, ierr)
359 if (ierr /= 0) then
360 message(1) = "Unsuccessful write of dipole."
361 call messages_warning(1, namespace=sys%namespace)
362 end if
363 call restart_dump%close(iunit)
364 end do
365
366 if (.not. diagonal_done .and. calc_diagonal) then
367 write(message(1), '(a)')
368 write(message(2), '(a,f6.4,3a, f6.4, 3a)') 'Info: Calculating dipole moment for field ', &
369 units_from_atomic(units_out%force, e_field), ' ', &
370 trim(units_abbrev(units_out%force)), ' in the '//index2axis(2)//'-direction plus ', &
371 units_from_atomic(units_out%force, e_field), ' ', &
372 trim(units_abbrev(units_out%force)), ' in the '//index2axis(3)//'-direction.'
373 call messages_info(2, namespace=sys%namespace)
374
375 !$omp parallel do
376 do ip = 1, sys%gr%np
377 sys%hm%ep%vpsl(ip) = vpsl_save(ip) &
378 - (sys%gr%x_t(ip, 2) + sys%gr%x_t(ip, 3)) * e_field
379 end do
380 !$omp end parallel do
381 call sys%hm%update(sys%gr, sys%namespace, sys%space, sys%ext_partners)
382
383 if (isign == 1) then
384 sign_char = '+'
385 else
386 sign_char = '-'
387 end if
388
389 fromscratch_local = fromscratch
390
391 if (.not. fromscratch) then
392 call restart_load%open_dir("field_yz+", ierr)
393 if (ierr == 0) then
394 call states_elec_load(restart_load, sys%namespace, sys%space, sys%st, sys%gr, sys%kpoints, &
395 fixed_occ=.false., ierr=ierr)
396 end if
397 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
398 if (ierr /= 0) fromscratch_local = .true.
399 call restart_load%close_dir()
400 end if
401
402 if (fromscratch_local) then
403 if (start_density_is_zero_field) then
404 sys%st%rho(1:sys%gr%np, 1:sys%st%d%nspin) = gs_rho(1:sys%gr%np, 1:sys%st%d%nspin)
405 call v_ks_h_setup(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, sys%hm)
406 else
407 call lcao_run(sys%namespace, sys%space, sys%gr, sys%ions, sys%ext_partners, sys%st, sys%ks, &
408 sys%hm, lmm_r = scfv%lmm_r)
409 end if
410 end if
411
412 call scf_mix_clear(scfv)
413 call scf_run(scfv, sys%namespace, sys%space, sys%mc, sys%gr, sys%ions, sys%ext_partners, sys%st, &
414 sys%ks, sys%hm, verbosity = verbosity)
415
416 trrho = m_zero
417 do is = 1, sys%st%d%spin_channels
418 call lalg_axpy(sys%gr%np, m_one, sys%st%rho(:, is), trrho)
419 end do
420
421 ! calculate dipole
422 do jj = 1, sys%space%dim
423 diag_dipole(jj) = dmf_moment(sys%gr, trrho, jj, 1)
424 end do
425
426 if (mpi_world%is_root()) then
427 print_dipole(1:sys%space%dim) = diag_dipole(1:sys%space%dim) + ionic_dipole(1:sys%space%dim)
428 call output_dipole(print_dipole, sys%space%dim, namespace=sys%namespace)
429 end if
430
431 ! Writes the dipole to file
432 iunit = restart_dump%open(restart_file, position='append')
433 write(line(1), fmt='(3e20.12)') (diag_dipole(jj), jj = 1, sys%space%dim)
434 call restart_dump%write(iunit, line, 1, ierr)
435 if (ierr /= 0) then
436 message(1) = "Unsuccessful write of dipole."
437 call messages_warning(1, namespace=sys%namespace)
438 end if
439 call restart_dump%close(iunit)
440
441 if (write_restart_densities) then
442 call restart_dump%open_dir("field_yz+", ierr)
443 if (ierr == 0) then
444 call states_elec_dump(restart_dump, sys%space, sys%st, sys%gr, sys%kpoints, ierr)
445 end if
446 call restart_dump%close_dir()
447 if (ierr /= 0) then
448 message(1) = 'Unable to write states wavefunctions.'
449 call messages_warning(1, namespace=sys%namespace)
450 end if
451 end if
452
453 end if
454
455 if (.not. fromscratch) call restart_load%end()
456 call scf_end(scfv)
457 call output_end_()
458 call born_charges_end(born_charges)
459
460 safe_deallocate_a(vpsl_save)
461 safe_deallocate_a(trrho)
462 safe_deallocate_a(gs_rho)
463 safe_deallocate_a(tmp_rho)
464 safe_deallocate_a(dipole)
465 call end_()
466 pop_sub(static_pol_run_legacy)
467
468 contains
469
470 ! ---------------------------------------------------------
471 subroutine init_()
473
474 call states_elec_allocate_wfns(sys%st, sys%gr)
475
476 call messages_obsolete_variable(sys%namespace, "EMStaticField", "EMStaticElectricField")
477 !%Variable EMStaticElectricField
478 !%Type float
479 !%Default 0.01 a.u.
480 !%Section Linear Response::Static Polarization
481 !%Description
482 !% Magnitude of the static electric field used to calculate the static polarizability,
483 !% if <tt>ResponseMethod = finite_differences</tt>.
484 !%End
485 call parse_variable(sys%namespace, 'EMStaticElectricField', 0.01_real64, e_field, units_inp%force)
486 if (e_field <= m_zero) then
487 write(message(1), '(a,e14.6,a)') "Input: '", e_field, "' is not a valid EMStaticElectricField."
488 message(2) = '(Must have EMStaticElectricField > 0)'
489 call messages_fatal(2, namespace=sys%namespace)
490 end if
491
492 ! variable defined in em_resp
493 call parse_variable(sys%namespace, 'EMCalcbornCharges', .false., calc_born)
494 if (calc_born) call messages_experimental("Calculation of born effective charges", namespace=sys%namespace)
495
496 !%Variable EMStartDensityIsZeroField
497 !%Type logical
498 !%Default true
499 !%Section Linear Response::Static Polarization
500 !%Description
501 !% Use the charge density from the zero-field calculation as the starting density for
502 !% SCF calculations with applied fields. For small fields, this will be fastest.
503 !% If there is trouble converging with larger fields, set to false,
504 !% to initialize the calculation for each field from scratch, as specified by the LCAO variables.
505 !% Only applies if <tt>ResponseMethod = finite_differences</tt>.
506 !%End
507 call parse_variable(sys%namespace, 'EMStartDensityIsZeroField', .true., start_density_is_zero_field)
508
509 !%Variable EMCalcDiagonalField
510 !%Type logical
511 !%Default true
512 !%Section Linear Response::Static Polarization
513 !%Description
514 !% Calculate <i>yz</i>-field for <math>\beta_{xyz}</math> hyperpolarizability, which is sometimes harder to converge.
515 !% Only applies if <tt>ResponseMethod = finite_differences</tt>.
516 !%End
517 call parse_variable(sys%namespace, 'EMCalcDiagonalField', .true., calc_diagonal)
518
519 !%Variable EMWriteRestartDensities
520 !%Type logical
521 !%Default true
522 !%Section Linear Response::Static Polarization
523 !%Description
524 !% Write density after each calculation for restart, rather than just the resulting electronic dipole moment.
525 !% Only applies if <tt>ResponseMethod = finite_differences</tt>. Restarting from calculations at smaller
526 !% fields can be helpful if there are convergence problems.
527 !%End
528 call parse_variable(sys%namespace, 'EMWriteRestartDensities', .true., write_restart_densities)
529
530 !%Variable EMVerbose
531 !%Type logical
532 !%Default false
533 !%Section Linear Response::Static Polarization
534 !%Description
535 !% Write full SCF output.
536 !% Only applies if <tt>ResponseMethod = finite_differences</tt>.
537 !%End
538 call parse_variable(sys%namespace, 'EMVerbose', .false., verbose)
539
540 if (verbose) then
541 verbosity = verb_full
542 else
543 verbosity = verb_compact
544 end if
545
547 end subroutine init_
548
549 ! ---------------------------------------------------------
550 subroutine end_()
551
552 push_sub(end_)
553
554 call states_elec_deallocate_wfns(sys%st)
555
556 pop_sub(end_)
557 end subroutine end_
558
559
560 !-------------------------------------------------------------
561 subroutine output_init_()
562 push_sub(output_init_)
563
564 !allocate memory for what we want to output
565 if (sys%outp%what(option__output__density) .or. &
566 sys%outp%what(option__output__pol_density)) then
567 safe_allocate(lr_rho(1:sys%gr%np, 1:sys%st%d%nspin))
568 safe_allocate(lr_rho2(1:sys%gr%np, 1:sys%st%d%nspin))
569 end if
570
571 if (sys%outp%what(option__output__elf)) then
572 safe_allocate( elf(1:sys%gr%np, 1:sys%st%d%nspin))
573 safe_allocate( lr_elf(1:sys%gr%np, 1:sys%st%d%nspin))
574 safe_allocate( elfd(1:sys%gr%np, 1:sys%st%d%nspin))
575 safe_allocate(lr_elfd(1:sys%gr%np, 1:sys%st%d%nspin))
576 end if
577
578 pop_sub(output_init_)
579 end subroutine output_init_
580
581
582 !-------------------------------------------------------------
583 subroutine output_cycle_()
584 integer :: iatom, ip, ispin2
585 type(unit_t) :: fn_unit
586
587 push_sub(output_cycle_)
588
589 ! BORN CHARGES
590 if (calc_born) then
591 do iatom = 1, sys%ions%natoms
592 if (isign == 1) then
593 ! temporary assignment for use in next cycle when isign == 2
594 born_charges%charge(ii, 1:sys%space%dim, iatom) = sys%ions%tot_force(:, iatom)
595 else
596 born_charges%charge(ii, 1:sys%space%dim, iatom) = &
597 (sys%ions%tot_force(:, iatom) - born_charges%charge(ii, 1:sys%space%dim, iatom)) &
598 / (m_two*e_field)
599 born_charges%charge(ii, ii, iatom) = born_charges%charge(ii, ii, iatom) + sys%ions%charge(iatom)
600 ! since the efield is applied in the SCF calculation by just altering the external potential felt by the electrons,
601 ! the ionic force due to the efield is not included in the forces returned by the SCF run, and so the ionic
602 ! contribution to the born charge must be added by hand here
603 end if
604 end do
605 end if
606
607 !DENSITY AND POLARIZABILITY DENSITY
608 if (sys%outp%what(option__output__density) .or. &
609 sys%outp%what(option__output__pol_density)) then
610
611 if (isign == 1 .and. ii == 2) then
612 tmp_rho(1:sys%gr%np, 1:sys%st%d%nspin) = sys%st%rho(1:sys%gr%np, 1:sys%st%d%nspin)
613 ! for use in off-diagonal non-linear densities
614 end if
615
616 if (isign == 1) then
617 ! temporary assignment for use in next cycle when isign == 2
618 lr_rho(1:sys%gr%np, 1:sys%st%d%nspin) = sys%st%rho(1:sys%gr%np, 1:sys%st%d%nspin)
619 else
620 !$omp parallel private(ispin2, ip)
621 do ispin2 = 1, sys%st%d%nspin
622 !$omp do
623 do ip = 1, sys%gr%np
624 lr_rho2(ip, ispin2) = &
625 -(sys%st%rho(ip, ispin2) + lr_rho(ip, ispin2) - &
626 2 * gs_rho(ip, ispin2)) / e_field**2
627 end do
628 end do
629 do ispin2 = 1, sys%st%d%nspin
630 !$omp do
631 do ip = 1, sys%gr%np
632 lr_rho(ip, ispin2) = &
633 (sys%st%rho(ip, ispin2) - lr_rho(ip, ispin2)) / (m_two*e_field)
634 end do
635 end do
636 !$omp end parallel
637
638 !write
639 do is = 1, sys%st%d%nspin
640 if (sys%outp%what(option__output__density)) then
641 fn_unit = units_out%length**(1-sys%space%dim) / units_out%energy
642 write(fname, '(a,i1,2a)') 'fd_density-sp', is, '-', index2axis(ii)
643 call dio_function_output(sys%outp%how(option__output__density), em_resp_fd_dir, trim(fname),&
644 sys%namespace, sys%space, sys%gr, lr_rho(:, is), fn_unit, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
646 ! save the trouble of writing many copies of each density, since ii,jj = jj,ii
647 fn_unit = units_out%length**(2-sys%space%dim) / units_out%energy**2
648 do jj = ii, sys%space%dim
649 write(fname, '(a,i1,4a)') 'fd2_density-sp', is, '-', index2axis(ii), '-', index2axis(jj)
650 call dio_function_output(sys%outp%how(option__output__density), em_resp_fd_dir, trim(fname),&
651 sys%namespace, sys%space, sys%gr, lr_rho2(:, is), fn_unit, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
652 end do
653 end if
654
655 if (sys%outp%what(option__output__pol_density)) then
656 do jj = ii, sys%space%dim
657 fn_unit = units_out%length**(2-sys%space%dim) / units_out%energy
658 write(fname, '(a,i1,4a)') 'alpha_density-sp', is, '-', index2axis(ii), '-', index2axis(jj)
659 call dio_function_output(sys%outp%how(option__output__pol_density), em_resp_fd_dir, trim(fname), &
660 sys%namespace, sys%space, sys%gr, -sys%gr%x_t(:, jj) * lr_rho(:, is), &
661 fn_unit, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
662
663 fn_unit = units_out%length**(3-sys%space%dim) / units_out%energy**2
664 write(fname, '(a,i1,6a)') 'beta_density-sp', is, '-', index2axis(ii), &
665 '-', index2axis(ii), '-', index2axis(jj)
666 call dio_function_output(sys%outp%how(option__output__pol_density), em_resp_fd_dir, trim(fname), &
667 sys%namespace, sys%space, sys%gr, -sys%gr%x_t(:, jj) * lr_rho2(:, is), &
668 fn_unit, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
669 end do
670 end if
671 end do
672
673 end if
674 end if
675
676 !ELF
677 if (sys%outp%what(option__output__elf)) then
679 if (isign == 1) then
680 call elf_calc(sys%space, sys%st, sys%gr, sys%kpoints, elf, elfd)
681 else
682 call elf_calc(sys%space, sys%st, sys%gr, sys%kpoints, lr_elf, lr_elfd)
683
684 !numerical derivative
685 !$omp parallel private(ispin2, ip)
686 do ispin2 = 1, sys%st%d%nspin
687 !$omp do
688 do ip = 1, sys%gr%np
689 lr_elf(ip, ispin2) = &
690 ( lr_elf(ip, ispin2) - elf(ip, ispin2)) / (m_two * e_field)
691 end do
692 end do
693 do ispin2 = 1, sys%st%d%nspin
694 !$omp do
695 do ip = 1, sys%gr%np
696 lr_elfd(ip, ispin2) = &
697 (lr_elfd(ip, ispin2) - elfd(ip, ispin2)) / (m_two * e_field)
698 end do
699 end do
700 !$omp end parallel
701
702 !write
703 do is = 1, sys%st%d%nspin
704 write(fname, '(a,i1,2a)') 'lr_elf-sp', is, '-', index2axis(ii)
705 call dio_function_output(sys%outp%how(option__output__elf), em_resp_fd_dir, trim(fname),&
706 sys%namespace, sys%space, sys%gr, lr_elf(:, is), unit_one, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
707 write(fname, '(a,i1,2a)') 'lr_elf_D-sp', is, '-', index2axis(ii)
708 call dio_function_output(sys%outp%how(option__output__elf), em_resp_fd_dir, trim(fname),&
709 sys%namespace, sys%space, sys%gr, lr_elfd(:, is), unit_one, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
710 end do
711 end if
712
713 end if
714
715 pop_sub(output_cycle_)
716 end subroutine output_cycle_
717
718
719 !-------------------------------------------------------------
720 subroutine output_end_()
721 real(real64) :: alpha(sys%space%dim, sys%space%dim)
722 complex(real64) :: beta(sys%space%dim, sys%space%dim, sys%space%dim)
723 integer :: iunit, idir, ip, ispin2
724 type(unit_t) :: fn_unit
725 real(real64) :: freq_factor(3)
726
727 push_sub(output_end_)
728
729 call io_mkdir(em_resp_fd_dir, sys%namespace)
730
731 if ((sys%outp%what(option__output__density) .or. &
732 sys%outp%what(option__output__pol_density)) .and. calc_diagonal) then
733 !$omp parallel private(ispin2, ip)
734 do ispin2 = 1, sys%st%d%nspin
735 !$omp do
736 do ip = 1, sys%gr%np
737 lr_rho2(ip, ispin2) = &
738 -(sys%st%rho(ip, ispin2) - lr_rho(ip, ispin2) &
739 - tmp_rho(ip, ispin2) + gs_rho(ip, ispin2)) / e_field**2
740 end do
741 end do
742 !$omp end parallel
743
744 do is = 1, sys%st%d%nspin
745 if (sys%outp%what(option__output__density)) then
746 fn_unit = units_out%length**(2-sys%space%dim) / units_out%energy**2
747 write(fname, '(a,i1,a)') 'fd2_density-sp', is, '-y-z'
748 call dio_function_output(sys%outp%how(option__output__density), em_resp_fd_dir, trim(fname),&
749 sys%namespace, sys%space, sys%gr, lr_rho2(:, is), fn_unit, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
750 end if
751
752 if (sys%outp%what(option__output__pol_density)) then
753 fn_unit = units_out%length**(3-sys%space%dim) / units_out%energy**2
754 write(fname, '(a,i1,a)') 'beta_density-sp', is, '-x-y-z'
755 call dio_function_output(sys%outp%how(option__output__pol_density), em_resp_fd_dir, trim(fname),&
756 sys%namespace, sys%space, sys%gr, -sys%gr%x_t(:, 1) * lr_rho2(:, is), &
757 fn_unit, ierr, pos=sys%ions%pos, atoms=sys%ions%atom)
758 end if
759 end do
760 end if
761
762 if (mpi_world%is_root()) then ! output pol file
763 iunit = io_open(em_resp_fd_dir//'alpha', sys%namespace, action='write')
764 write(iunit, '(3a)') '# Polarizability tensor [', trim(units_abbrev(units_out%polarizability)), ']'
765
766 alpha(1:sys%space%dim, 1:sys%space%dim) = (dipole(1:sys%space%dim, 1:sys%space%dim, 1) - &
767 dipole(1:sys%space%dim, 1:sys%space%dim, 2)) / (m_two * e_field)
768
769 beta = m_zero
770
771 do idir = 1, sys%space%dim
772 beta(1:sys%space%dim, idir, idir) = &
773 -(dipole(idir, 1:sys%space%dim, 1) + dipole(idir, 1:sys%space%dim, 2) - &
774 m_two * center_dipole(1:sys%space%dim)) / e_field**2
775 beta(idir, 1:sys%space%dim, idir) = beta(1:sys%space%dim, idir, idir)
776 beta(idir, idir, 1:sys%space%dim) = beta(1:sys%space%dim, idir, idir)
777 end do
778
779 assert(sys%space%dim == 3)
780
781 if (calc_diagonal) then
782 beta(1, 2, 3) = -(diag_dipole(1) - dipole(2, 1, 1) - dipole(3, 1, 1) + center_dipole(1)) / e_field**2
783 else
784 beta(1, 2, 3) = m_zero
785 end if
786
787 beta(2, 3, 1) = beta(1, 2, 3)
788 beta(3, 1, 2) = beta(1, 2, 3)
789 beta(3, 2, 1) = beta(1, 2, 3)
790 beta(1, 3, 2) = beta(1, 2, 3)
791 beta(2, 1, 3) = beta(1, 2, 3)
792
793 call output_tensor(alpha, sys%space%dim, units_out%polarizability, iunit=iunit)
794 call io_close(iunit)
795
796 freq_factor(1:3) = m_zero ! for compatibility with em_resp version
797 if (sys%st%system_grp%is_root()) then
798 call out_hyperpolarizability(sys%gr%box, beta, freq_factor(1:3), .true., em_resp_fd_dir, sys%namespace)
799 end if
800
801 if (calc_born) then
802 call born_output_charges(born_charges, sys%ions%atom, sys%ions%charge, sys%ions%natoms, &
803 sys%namespace, sys%space%dim, em_resp_fd_dir, states_are_real(sys%st))
804 end if
805 end if
806
807 if (sys%outp%what(option__output__density) .or. &
808 sys%outp%what(option__output__pol_density)) then
809 safe_deallocate_a(lr_rho)
810 safe_deallocate_a(lr_rho2)
811 end if
812
813 if (sys%outp%what(option__output__elf)) then
814 safe_deallocate_a(lr_elf)
815 safe_deallocate_a(elf)
816 safe_deallocate_a(lr_elfd)
817 safe_deallocate_a(elfd)
818 end if
819
820 pop_sub(output_end_)
821 end subroutine output_end_
822
823 end subroutine static_pol_run_legacy
824
825end module static_pol_oct_m
826
827!! Local Variables:
828!! mode: f90
829!! coding: utf-8
830!! End:
subroutine init_(fromscratch)
Definition: geom_opt.F90:365
subroutine end_()
Definition: geom_opt.F90:826
constant times a vector plus a vector
Definition: lalg_basic.F90:173
subroutine, public born_charges_end(this)
subroutine, public born_output_charges(this, atom, charge, natoms, namespace, dim, dirname, write_real)
subroutine, public born_charges_init(this, namespace, natoms, val_charge, qtot, dim)
subroutine, public elf_calc(space, st, gr, kpoints, elf, de)
(time-dependent) electron localization function, (TD)ELF.
Definition: elf.F90:169
subroutine, public out_hyperpolarizability(box, beta, freq_factor, converged, dirname, namespace)
Ref: David M Bishop, Rev Mod Phys 62, 343 (1990) beta generalized to lack of Kleinman symmetry.
Definition: em_resp.F90:3263
character(len= *), parameter, public em_resp_fd_dir
Definition: global.F90:281
real(real64), parameter, public m_two
Definition: global.F90:202
real(real64), parameter, public m_zero
Definition: global.F90:200
real(real64), parameter, public m_epsilon
Definition: global.F90:216
real(real64), parameter, public m_one
Definition: global.F90:201
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_close(iunit, grp)
Definition: io.F90:467
subroutine, public io_mkdir(fname, namespace, parents)
Definition: io.F90:361
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
Definition: io.F90:402
subroutine, public lcao_run(namespace, space, gr, ions, ext_partners, st, ks, hm, st_start, lmm_r, known_lower_bound)
Definition: lcao.F90:769
This module defines various routines, operating on mesh functions.
real(real64) function, public dmf_moment(mesh, ff, idir, order)
This function calculates the "order" moment of the function ff.
subroutine, public messages_not_implemented(feature, namespace)
Definition: messages.F90:1068
subroutine, public messages_warning(no_lines, all_nodes, namespace)
Definition: messages.F90:525
subroutine, public messages_obsolete_variable(namespace, name, rep)
Definition: messages.F90:1000
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_experimental(name, namespace)
Definition: messages.F90:1040
subroutine, public messages_info(no_lines, iunit, debug_only, stress, all_nodes, namespace)
Definition: messages.F90:594
type(mpi_grp_t), public mpi_world
Definition: mpi.F90:272
This module implements the basic mulsisystem class, a container system for other systems.
integer, parameter, public restart_gs
Definition: restart.F90:156
integer, parameter, public restart_em_resp_fd
Definition: restart.F90:156
integer, parameter, public restart_type_dump
Definition: restart.F90:184
integer, parameter, public restart_type_load
Definition: restart.F90:184
subroutine, public scf_mix_clear(scf)
Definition: scf.F90:587
integer, parameter, public verb_full
Definition: scf.F90:206
integer, parameter, public verb_compact
Definition: scf.F90:206
subroutine, public scf_init(scf, namespace, gr, ions, st, mc, hm, space)
Definition: scf.F90:259
subroutine, public scf_end(scf)
Definition: scf.F90:557
subroutine, public scf_run(scf, namespace, space, mc, gr, ions, ext_partners, st, ks, hm, outp, verbosity, iters_done, restart_dump)
Legacy version of the SCF code.
Definition: scf.F90:838
pure logical function, public states_are_real(st)
subroutine, public states_elec_deallocate_wfns(st)
Deallocates the KS wavefunctions defined within a states_elec_t structure.
subroutine, public states_elec_allocate_wfns(st, mesh, wfs_type, skip, packed)
Allocates the KS wavefunctions defined within a states_elec_t structure.
This module handles reading and writing restart information for the states_elec_t.
subroutine, public states_elec_load(restart, namespace, space, st, mesh, kpoints, fixed_occ, ierr, iter, lr, lowest_missing, label, verbose, skip)
returns in ierr: <0 => Fatal error, or nothing read =0 => read all wavefunctions >0 => could only rea...
subroutine, public states_elec_dump(restart, space, st, mesh, kpoints, ierr, iter, lr, verbose)
subroutine static_pol_run_legacy(sys, fromScratch)
Definition: static_pol.F90:180
subroutine, public static_pol_run(system, from_scratch)
Definition: static_pol.F90:160
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
Definition: unit.F90:134
character(len=20) pure function, public units_abbrev(this)
Definition: unit.F90:225
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
type(unit_system_t), public units_inp
the units systems for reading and writing
type(unit_t), public unit_one
some special units required for particular quantities
This module is intended to contain simple general-purpose utility functions and procedures.
Definition: utils.F90:120
subroutine, public output_tensor(tensor, ndim, unit, write_average, iunit, namespace)
Definition: utils.F90:245
subroutine, public output_dipole(dipole, ndim, iunit, namespace)
Definition: utils.F90:281
character pure function, public index2axis(idir)
Definition: utils.F90:205
subroutine, public v_ks_h_setup(namespace, space, gr, ions, ext_partners, st, ks, hm, calc_eigenval, calc_current)
Definition: v_ks.F90:649
subroutine output_init_()
Definition: static_pol.F90:657
subroutine output_end_()
Definition: static_pol.F90:816
subroutine output_cycle_()
Definition: static_pol.F90:679
Class describing the electron system.
Definition: electrons.F90:221
Container class for lists of system_oct_m::system_t.
int true(void)