29 use,
intrinsic :: iso_fortran_env
73 type(space_t),
public :: space
74 real(real64),
allocatable :: vecpot(:)
75 real(real64),
allocatable :: vecpot_vel(:)
76 real(real64),
allocatable :: vecpot_acc(:)
77 real(real64),
allocatable :: vecpot_kick(:)
78 real(real64),
allocatable :: force(:)
80 logical :: with_gauge_field = .false.
82 real(real64) :: kicktime
84 real(real64) :: volume
101 class(gauge_field_t),
pointer :: this
102 type(namespace_t),
intent(in) :: namespace
103 real(real64),
intent(in) :: volume
112 this%namespace =
namespace_t(
"GaugeField", parent=namespace)
116 this%space =
space_t(namespace)
118 this%with_gauge_field = .false.
122 safe_allocate(this%vecpot(1:this%space%dim))
123 safe_allocate(this%vecpot_vel(1:this%space%dim))
124 safe_allocate(this%vecpot_acc(1:this%space%dim))
125 safe_allocate(this%vecpot_kick(1:this%space%dim))
126 safe_allocate(this%force(1:this%space%dim))
148 call parse_variable(namespace,
'GaugeFieldDynamics', option__gaugefielddynamics__polarization, this%dynamics)
158 call parse_variable(namespace,
'GaugeFieldPropagate', .false., this%with_gauge_field)
179 this%with_gauge_field = .
true.
181 do ii = 1, this%space%dim
186 if (.not. this%space%is_periodic())
then
187 message(1) =
"GaugeVectorField is intended for periodic systems."
204 if (abs(this%kicktime) <=
m_epsilon)
then
205 this%vecpot(1:this%space%dim) = this%vecpot_kick(1:this%space%dim)
220 if (kpoints%use_symmetries)
then
224 message(1) =
"The GaugeVectorField breaks (at least) one of the symmetries used to reduce the k-points."
225 message(2) =
"Set SymmetryBreakDir equal to GaugeVectorField."
241 this%with_gauge_field = .false.
242 safe_deallocate_a(this%vecpot)
243 safe_deallocate_a(this%vecpot_vel)
244 safe_deallocate_a(this%vecpot_acc)
245 safe_deallocate_a(this%vecpot_kick)
246 safe_deallocate_a(this%force)
256 is_propagated = this%with_gauge_field
263 is_used = this%with_gauge_field .or. (norm2(this%vecpot_kick(1:this%space%dim)) > m_epsilon)
271 real(real64),
intent(in) :: vec_pot(:)
274 this%vecpot(1:this%space%dim) = vec_pot(1:this%space%dim)
283 real(real64),
intent(in) :: vec_pot_vel(:)
286 this%vecpot_vel(1:this%space%dim) = vec_pot_vel(1:this%space%dim)
295 real(real64),
intent(out) :: vec_pot(:)
298 vec_pot(1:this%space%dim) = this%vecpot(1:this%space%dim)
307 real(real64),
intent(out) :: vec_pot_vel(:)
310 vec_pot_vel(1:this%space%dim) = this%vecpot_vel(1:this%space%dim)
319 real(real64),
intent(out) :: vec_pot_acc(:)
322 vec_pot_acc(1:this%space%dim) = this%vecpot_acc(1:this%space%dim)
330 real(real64),
intent(in) :: dt
331 real(real64),
intent(in) :: time
333 logical,
save :: warning_shown = .false.
338 this%vecpot_acc(1:this%space%dim) = this%force(1:this%space%dim)
341 if (this%kicktime > m_zero .and. time-dt <= this%kicktime .and. time > this%kicktime)
then
342 this%vecpot(1:this%space%dim) = this%vecpot(1:this%space%dim) + this%vecpot_kick(1:this%space%dim)
343 call messages_write(
' ---------------- Applying gauge kick ----------------')
344 call messages_info(namespace=this%namespace)
347 this%vecpot(1:this%space%dim) = this%vecpot(1:this%space%dim) + dt * this%vecpot_vel(1:this%space%dim) + &
348 m_half * dt**2 * this%force(1:this%space%dim)
351 do idim = 1, this%space%dim
352 if (.not. warning_shown .and. abs(this%vecpot_kick(idim)) > m_epsilon .and. &
353 abs(this%vecpot(idim))> abs(this%vecpot_kick(idim))*1.01 .and. .not. this%kicktime > m_zero)
then
355 warning_shown = .
true.
357 write(message(1),
'(a)')
'It seems that the gauge-field might be diverging. You should probably check'
358 write(message(2),
'(a)')
'the simulation parameters, in particular the number of k-points.'
359 call messages_warning(2, namespace=this%namespace)
368 real(real64),
intent(in) :: qtot
372 this%wp2 = m_four*m_pi*qtot/this%volume
374 write (message(1),
'(a,f12.6,a)')
"Info: Electron-gas plasmon frequency", &
375 units_from_atomic(units_out%energy,
sqrt(this%wp2)),
" ["//trim(units_abbrev(units_out%energy))//
"]"
376 call messages_info(1, namespace=this%namespace)
387 if(
allocated(this%vecpot_vel))
then
388 energy = this%volume / (8.0_real64 * m_pi * p_c**2) * sum(this%vecpot_vel(1:this%space%dim)**2)
399 type(restart_t),
intent(in) :: restart
401 integer,
intent(out) :: ierr
404 real(real64),
allocatable :: vecpot(:,:)
410 if (restart_skip(restart))
then
415 message(1) =
"Debug: Writing gauge field restart."
416 call messages_info(1, namespace=gfield%namespace, debug_only=.
true.)
418 safe_allocate(vecpot(1:gfield%space%dim, 1:2))
423 call drestart_write_binary(restart,
"gauge_field", 2*gfield%space%dim, vecpot, err)
424 safe_deallocate_a(vecpot)
425 if (err /= 0) ierr = ierr + 1
427 message(1) =
"Debug: Writing gauge field restart done."
428 call messages_info(1, namespace=gfield%namespace, debug_only=.
true.)
436 type(restart_t),
intent(in) :: restart
438 integer,
intent(out) :: ierr
441 real(real64),
allocatable :: vecpot(:,:)
447 if (restart_skip(restart))
then
453 message(1) =
"Debug: Reading gauge field restart."
454 call messages_info(1, namespace=gfield%namespace, debug_only=.
true.)
456 safe_allocate(vecpot(1:gfield%space%dim, 1:2))
457 call drestart_read_binary(restart,
"gauge_field", 2*gfield%space%dim, vecpot, err)
458 if (err /= 0) ierr = ierr + 1
462 safe_deallocate_a(vecpot)
464 message(1) =
"Debug: Reading gauge field restart done."
465 call messages_info(1, namespace=gfield%namespace, debug_only=.
true.)
474 type(grid_t),
intent(in) :: gr
475 integer,
intent(in) :: spin_channels
476 real(real64),
intent(in) :: current(:,:,:)
477 real(real64),
optional,
intent(in) :: lrc_alpha
479 integer :: idir, ispin
480 real(real64) :: lrc_alpha_
484 lrc_alpha_ = optional_default(lrc_alpha, m_zero)
486 select case (this%dynamics)
487 case (option__gaugefielddynamics__none)
488 this%force(1:this%space%dim) = m_zero
490 case (option__gaugefielddynamics__polarization)
491 do idir = 1, this%space%periodic_dim
492 this%force(idir) = m_zero
493 do ispin = 1, spin_channels
494 if(lrc_alpha_ > m_epsilon)
then
495 this%force(idir) = this%force(idir) + &
496 lrc_alpha*p_c/this%volume*dmf_integrate(gr, current(:, idir, ispin))
498 this%force(idir) = this%force(idir) - &
499 m_four*m_pi*p_c/this%volume*dmf_integrate(gr, current(:, idir, ispin))
515 type(algorithmic_operation_t),
intent(in) :: operation
516 real(real64),
intent(in) :: dt
517 real(real64),
intent(in) :: time
521 select case (operation%id)
526 case (verlet_update_pos)
528 case (verlet_compute_acc)
531 case (verlet_compute_vel)
532 this%vecpot_vel(1:this%space%dim) = this%vecpot_vel(1:this%space%dim) + &
533 m_half * dt * (this%vecpot_acc(1:this%space%dim) + this%force(1:this%space%dim))
535 message(1) =
"Unsupported TD operation."
536 call messages_fatal(1, namespace=this%namespace)
546 type(c_ptr),
intent(inout) :: out_gauge
547 integer,
intent(in) :: iter
550 character(len=50) :: aux
551 real(real64) :: temp(this%space%dim)
553 if (.not. mpi_grp_is_root(mpi_world))
return
558 call write_iter_clear(out_gauge)
559 call write_iter_string(out_gauge,
'################################################################################')
560 call write_iter_nl(out_gauge)
561 call write_iter_string(out_gauge,
'# HEADER')
562 call write_iter_nl(out_gauge)
565 call write_iter_header_start(out_gauge)
567 do idir = 1, this%space%dim
568 write(aux,
'(a2,i1,a1)')
'A(', idir,
')'
569 call write_iter_header(out_gauge, aux)
571 do idir = 1, this%space%dim
572 write(aux,
'(a6,i1,a1)')
'dA/dt(', idir,
')'
573 call write_iter_header(out_gauge, aux)
575 do idir = 1, this%space%dim
576 write(aux,
'(a10,i1,a1)')
'd^2A/dt^2(', idir,
')'
577 call write_iter_header(out_gauge, aux)
579 call write_iter_nl(out_gauge)
590 call write_iter_string(out_gauge,
'################################################################################')
591 call write_iter_nl(out_gauge)
595 call write_iter_start(out_gauge)
597 do idir = 1, this%space%dim
598 temp(idir) = units_from_atomic(units_out%energy, this%vecpot(idir))
600 call write_iter_double(out_gauge, temp, this%space%dim)
602 do idir = 1, this%space%dim
603 temp(idir) = units_from_atomic(units_out%energy / units_out%time, this%vecpot_vel(idir))
605 call write_iter_double(out_gauge, temp, this%space%dim)
607 do idir = 1, this%space%dim
608 temp(idir) = units_from_atomic(units_out%energy / units_out%time**2, this%vecpot_acc(idir))
610 call write_iter_double(out_gauge, temp, this%space%dim)
612 call write_iter_nl(out_gauge)
631 class(interaction_surrogate_t),
intent(inout) :: interaction
635 select type (interaction)
637 message(1) =
"Unsupported interaction."
638 call messages_fatal(1)
647 class(interaction_surrogate_t),
intent(inout) :: interaction
651 select type (interaction)
653 message(1) =
"Unsupported interaction."
654 call messages_fatal(1)
double sqrt(double __x) __attribute__((__nothrow__
This module implements the basic elements defining algorithms.
subroutine, public gauge_field_set_vec_pot_vel(this, vec_pot_vel)
subroutine, public gauge_field_output_write(this, out_gauge, iter)
subroutine, public gauge_field_set_vec_pot(this, vec_pot)
subroutine gauge_field_finalize(this)
subroutine, public gauge_field_get_vec_pot_acc(this, vec_pot_acc)
subroutine, public gauge_field_load(restart, gfield, ierr)
subroutine gauge_field_copy_quantities_to_interaction(partner, interaction)
subroutine, public gauge_field_end(this)
subroutine, public gauge_field_get_vec_pot(this, vec_pot)
subroutine, public gauge_field_do_algorithmic_operation(this, operation, dt, time)
subroutine, public gauge_field_check_symmetries(this, kpoints)
subroutine, public gauge_field_get_force(this, gr, spin_channels, current, lrc_alpha)
subroutine, public gauge_field_get_vec_pot_vel(this, vec_pot_vel)
class(gauge_field_t) function, pointer, public gauge_field_init(namespace, volume)
subroutine, public gauge_field_dump(restart, gfield, ierr)
subroutine gauge_field_init_interaction_as_partner(partner, interaction)
logical pure function, public gauge_field_is_propagated(this)
logical pure function, public gauge_field_is_used(this)
subroutine, public gauge_field_init_vec_pot(this, qtot)
real(real64) function, public gauge_field_get_energy(this)
subroutine gauge_field_propagate(this, dt, time)
real(real64), parameter, public m_zero
real(real64), parameter, public m_epsilon
This module implements the underlying real-space grid.
This module defines classes and functions for interaction partners.
This module defines various routines, operating on mesh functions.
This module defines the meshes, which are used in Octopus.
subroutine, public messages_warning(no_lines, 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)
integer function, public parse_block(namespace, name, blk, check_varinfo_)
integer pure function, public symmetries_identity_index(this)
integer pure function, public symmetries_number(this)
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
Explicit interfaces to C functions, defined in write_iter_low.cc.
abstract class for general interaction partners