28 use,
intrinsic :: iso_fortran_env
43 integer :: iunit, ierr, ii, jj, iter, read_iter, ntime, nvel, ivel
44 integer :: istart, iend, energy_steps, out_file
45 real(real64),
allocatable :: time(:), velocities(:, :)
46 real(real64),
allocatable :: total_current(:, :), ftcurr(:, :, :), curr(:, :)
47 real(real64),
allocatable :: heat_current(:,:), ftheatcurr(:,:,:), heatcurr(:,:)
48 complex(real64),
allocatable :: invdielectric(:, :)
49 type(ions_t),
pointer :: ions
50 type(space_t) :: space
51 type(spectrum_t) :: spectrum
53 type(batch_t) :: currb, ftcurrb, heatcurrb, ftheatcurrb
54 real(real64) :: ww, curtime, deltat, integral(1:2), v0
55 character(len=MAX_PATH_LEN) :: ref_filename
56 integer :: ref_file, time_steps_ref, kk
57 real(real64),
allocatable :: velcm(:), vel0(:), current(:), current_ref(:, :)
58 real(real64) :: dt_ref, tt, start_time
59 integer :: ifreq, max_freq
60 integer :: skip, smearing
61 logical :: from_forces
62 character(len=120) :: header
63 real(real64) :: excess_charge, qtot, javerage
113 if (spectrum%end_time <
m_zero) spectrum%end_time = huge(spectrum%end_time)
119 qtot = -(ions%val_charge() + excess_charge)
121 if (from_forces)
then
123 call messages_write(
'Info: Reading coordinates from td.general/coordinates')
133 nvel = ions%natoms*ions%space%dim
135 safe_allocate(time(1:ntime))
136 safe_allocate(velocities(1:nvel, 1:ntime))
147 read(unit = iunit, iostat = ierr, fmt = *) read_iter, curtime, &
148 ((ions%pos(jj, ii), jj = 1, 3), ii = 1, ions%natoms), &
149 ((ions%vel(jj, ii), jj = 1, 3), ii = 1, ions%natoms)
153 if (ierr /= 0 .or. curtime >= spectrum%end_time)
then
159 assert(iter == read_iter + 1)
161 if (curtime >= spectrum%start_time .and. mod(iter, skip) == 0)
then
163 time(ntime) = curtime
165 do ii = 1, ions%natoms
166 do jj = 1, ions%space%dim
185 call messages_write(
'Info: Reading total current from td.general/total_current')
199 safe_allocate(total_current(1:space%dim, 1:ntime))
200 safe_allocate(heat_current(1:space%dim, 1:ntime))
201 safe_allocate(time(1:ntime))
204 read(iunit, *) read_iter, time(iter), (total_current(ii, iter), ii = 1, space%dim)
215 ref_file =
io_open(trim(ref_filename)//
'/total_current', action=
'read', status=
'old', die=.false.)
216 if (ref_file < 0)
then
217 message(1) =
"Cannot open reference file '"//trim(
io_workpath(trim(ref_filename)//
'/total_current'))//
"'"
222 if (time_steps_ref < ntime)
then
223 message(1) =
"The reference calculation does not contain enought time steps"
227 if (.not.
is_close(dt_ref, time(2)-time(1)))
then
228 message(1) =
"The time step of the reference calculation is different from the current calculation"
233 time_steps_ref = time_steps_ref + 1
234 safe_allocate(current_ref(1:space%dim, 1:time_steps_ref))
236 do ii = 1, time_steps_ref
237 read(ref_file, *) jj, tt, (current_ref(kk, ii), kk = 1, space%dim)
242 total_current(kk, iter) = total_current(kk, iter) - current_ref(kk, iter)
245 safe_deallocate_a(current_ref)
247 start_time = spectrum%start_time
258 javerage = javerage + total_current(kk, iter)
260 javerage = javerage/ntime
262 total_current(kk, iter) = total_current(kk, iter) - javerage
269 call messages_write(
"Cannot find the 'td.general/total_current' file.")
270 call messages_write(
"Conductivity will only be calculated from the forces")
274 safe_allocate(total_current(1:space%dim, 1:ntime))
275 safe_allocate(heat_current(1:space%dim, 1:ntime))
276 safe_allocate(time(1:ntime))
278 total_current(1:space%dim, 1:ntime) =
m_zero
295 read(iunit, *) read_iter, time(iter), (heat_current(ii, iter), ii = 1, space%dim)
302 call messages_write(
"Cannot find the 'td.general/heat_current' file.")
303 call messages_write(
"Thermal conductivity will only be calculated from the forces")
306 heat_current(1:space%dim, 1:ntime) =
m_zero
312 safe_allocate(curr(ntime, 1:space%dim))
313 safe_allocate(heatcurr(ntime, 1:space%dim))
314 safe_allocate(vel0(1:space%dim))
315 safe_allocate(velcm(1:space%dim))
316 safe_allocate(current(1:space%dim))
323 if (from_forces)
then
327 do ii = 1, ions%natoms
329 vel0(jj) = vel0(jj) + velocities(ivel, iter)/real(ions%natoms, real64)
339 do ii = 1, ions%natoms
341 velcm(jj) = velcm(jj) + velocities(ivel, iter)/real(ions%natoms, real64)
342 current(jj) = current(jj) + &
343 ions%mass(ii)/ions%latt%rcell_volume*(velocities(ivel, iter) - vel0(jj))
348 integral(1) = integral(1) + deltat/vel0(1)*(vel0(1)*qtot/ions%latt%rcell_volume + current(1))
349 integral(2) = integral(2) + &
350 deltat/vel0(1)*(vel0(1)*qtot/ions%latt%rcell_volume - total_current(1, iter)/ions%latt%rcell_volume)
352 curr(iter, 1:space%dim) = vel0(1:space%dim)*qtot/ions%latt%rcell_volume + current(1:space%dim)
355 curr(iter, 1:space%dim) = total_current(1:space%dim, iter)/ions%latt%rcell_volume
356 heatcurr(iter,1:space%dim) = heat_current(1:space%dim, iter)/ions%latt%rcell_volume
359 if (from_forces)
write(iunit,*) iter, iter*deltat, curr(iter, 1:space%dim)
363 safe_deallocate_a(velcm)
364 safe_deallocate_a(current)
367 if (from_forces)
call io_close(iunit)
371 istart = max(1, istart)
374 safe_allocate(ftcurr(1:energy_steps, 1:space%dim, 1:2))
377 call spectrum_signal_damp(spectrum%damp, spectrum%damp_factor, istart, iend, spectrum%start_time, deltat, currb)
379 call batch_init(ftcurrb, 1, 1, space%dim, ftcurr(:, :, 1))
381 istart, iend, spectrum%start_time, deltat, currb, spectrum%min_energy, spectrum%max_energy, &
382 spectrum%energy_step, ftcurrb)
385 call batch_init(ftcurrb, 1, 1, space%dim, ftcurr(:, :, 2))
387 istart, iend, spectrum%start_time, deltat, currb, spectrum%min_energy, spectrum%max_energy, &
388 spectrum%energy_step, ftcurrb)
398 write(unit = iunit, iostat = ierr, fmt =
'(a)') &
399 '###########################################################################################################################'
400 write(unit = iunit, iostat = ierr, fmt =
'(8a)')
'# HEADER'
401 write(unit = iunit, iostat = ierr, fmt =
'(a,a,a)') &
403 write(unit = iunit, iostat = ierr, fmt =
'(a)') &
404 '###########################################################################################################################'
406 v0 = norm2(vel0(1:space%dim))
407 if (.not. from_forces .or. v0 < epsilon(v0)) v0 =
m_one
416 vel0(1:space%dim) = vel0(1:space%dim) /
p_c
417 v0 = norm2(vel0(1:space%dim))
421 do ifreq = 1, energy_steps
422 ww = spectrum%energy_step*(ifreq - 1) + spectrum%min_energy
424 transpose(ftcurr(ifreq, 1:space%dim, 1:2)/v0)
433 safe_allocate(invdielectric(1:space%dim, 1:energy_steps))
434 do ifreq = 1, energy_steps
435 ww = max((ifreq-1)*spectrum%energy_step + spectrum%min_energy,
m_epsilon)
437 invdielectric(1:space%dim, ifreq) = (vel0(1:space%dim) +
m_four *
m_pi * &
438 cmplx(ftcurr(ifreq, 1:space%dim, 2),-ftcurr(ifreq, 1:space%dim, 1), real64) / ww) / v0
443 select case (space%dim)
445 write(header,
'(3a15)')
'# energy',
'Re x',
'Im x'
447 write(header,
'(5a15)')
'# energy',
'Re x',
'Im x',
'Re y',
'Im y'
449 write(header,
'(7a15)')
'# energy',
'Re x',
'Im x',
'Re y',
'Im y',
'Re z',
'Im z'
451 write(out_file,
'(a)') trim(header)
452 do ifreq = 1, energy_steps
453 ww = (ifreq-1)*spectrum%energy_step + spectrum%min_energy
454 select case (space%dim)
456 write(out_file,
'(3e15.6)') ww, &
457 real(invdielectric(1, ifreq), real64), aimag(invdielectric(1, ifreq))
459 write(out_file,
'(5e15.6)') ww, &
460 real(invdielectric(1, ifreq), real64), aimag(invdielectric(1, ifreq)), &
461 real(invdielectric(2, ifreq), real64), aimag(invdielectric(2, ifreq))
463 write(out_file,
'(7e15.6)') ww, &
464 real(invdielectric(1, ifreq), real64), aimag(invdielectric(1, ifreq)), &
465 real(invdielectric(2, ifreq), real64), aimag(invdielectric(2, ifreq)), &
466 real(invdielectric(3, ifreq), real64), aimag(invdielectric(3, ifreq))
471 safe_deallocate_a(ftcurr)
472 safe_deallocate_a(invdielectric)
476 safe_allocate(ftheatcurr(1:energy_steps, 1:space%dim, 1:2))
480 call batch_init(heatcurrb, 1, 1, space%dim, heatcurr)
484 call batch_init(ftheatcurrb, 1, 1, space%dim, ftheatcurr(:, :, 1))
486 1, ntime,
m_zero, deltat, heatcurrb, spectrum%min_energy, spectrum%max_energy, spectrum%energy_step, ftheatcurrb)
487 call ftheatcurrb%end()
489 call batch_init(ftheatcurrb, 1, 1, space%dim, ftheatcurr(:, :, 2))
491 1, ntime,
m_zero, deltat, heatcurrb, spectrum%min_energy, spectrum%max_energy, spectrum%energy_step, ftheatcurrb)
492 call ftheatcurrb%end()
501 write(unit = iunit, iostat = ierr, fmt =
'(a)') &
502 '###########################################################################################################################'
503 write(unit = iunit, iostat = ierr, fmt =
'(8a)')
'# HEADER'
504 write(unit = iunit, iostat = ierr, fmt =
'(a,a,a)') &
506 write(unit = iunit, iostat = ierr, fmt =
'(a)') &
507 '###########################################################################################################################'
509 v0 = norm2(vel0(1:space%dim))
510 if (.not. from_forces .or. v0 < epsilon(v0)) v0 =
m_one
512 do ifreq = 1, energy_steps
513 ww = spectrum%energy_step*(ifreq - 1) + spectrum%min_energy
515 transpose(ftheatcurr(ifreq, 1:space%dim, 1:2)/v0)
521 safe_deallocate_a(ftheatcurr)
522 safe_deallocate_a(vel0)
526 safe_deallocate_p(ions)
528 safe_deallocate_a(total_current)
529 safe_deallocate_a(heat_current)
530 safe_deallocate_a(time)
initialize a batch with existing memory
This module implements batches of mesh functions.
subroutine, public getopt_init(ierr)
Initializes the getopt machinery. Must be called before attempting to parse the options....
subroutine, public getopt_end
subroutine, public global_end()
Finalise parser varinfo file, and MPI.
real(real64), parameter, public m_zero
real(real64), parameter, public m_four
real(real64), parameter, public m_pi
some mathematical constants
type(mpi_comm), parameter, public serial_dummy_comm
Alias MPI_COMM_UNDEFINED for the specific use case of initialising Octopus utilities with no MPI supp...
subroutine, public init_octopus_globals(comm)
Initialise Octopus-specific global constants and files. This routine performs no initialisation calls...
real(real64), parameter, public m_epsilon
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
real(real64), parameter, public m_one
This module implements the underlying real-space grid.
subroutine, public io_init(defaults)
If the argument defaults is present and set to true, then the routine will not try to read anything f...
subroutine, public io_close(iunit, grp)
subroutine, public io_skip_header(iunit)
subroutine, public io_end()
character(len=max_path_len) function, public io_workpath(path, namespace)
integer function, public io_open(file, namespace, action, status, form, position, die, recl, grp)
This module is intended to contain "only mathematical" functions and procedures.
subroutine, public messages_end()
subroutine, public messages_init(output_dir)
subroutine, public messages_warning(no_lines, all_nodes, namespace)
subroutine, public messages_obsolete_variable(namespace, name, rep)
subroutine, public messages_info(no_lines, iunit, verbose_limit, stress, all_nodes, namespace)
character(len=256), dimension(max_lines), public message
to be output by fatal, warning
subroutine, public messages_fatal(no_lines, only_root_writes, namespace)
subroutine, public messages_input_error(namespace, var, details, row, column)
subroutine, public messages_experimental(name, namespace)
type(namespace_t), public global_namespace
logical function, public parse_is_defined(namespace, name)
subroutine, public parser_init()
Initialise the Octopus parser.
subroutine, public parser_end()
End the Octopus parser.
integer function, public parse_block(namespace, name, blk, check_varinfo_)
subroutine, public profiling_end(namespace)
subroutine, public profiling_init(namespace)
Create profiling subdirectory.
integer, parameter, public smear_semiconductor
subroutine, public spectrum_fix_time_limits(spectrum, time_steps, dt, istart, iend, ntiter)
subroutine, public spectrum_fourier_transform(method, transform, noise, time_start, time_end, t0, time_step, time_function, energy_start, energy_end, energy_step, energy_function)
Computes the sine, cosine, (or "exponential") Fourier transform of the real function given in the tim...
subroutine, public spectrum_init(spectrum, namespace, default_energy_step, default_max_energy)
subroutine, public spectrum_signal_damp(damp_type, damp_factor, time_start, time_end, t0, time_step, time_function)
integer, parameter, public spectrum_transform_cos
integer, parameter, public spectrum_transform_sin
subroutine, public spectrum_count_time_steps(namespace, iunit, time_steps, dt)
pure integer function, public spectrum_nenergy_steps(spectrum)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
character(len=20) pure function, public units_abbrev(this)
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
subroutine, public unit_system_init(namespace)