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
416 message(1) =
"Debug: Writing gauge field restart."
417 call messages_info(1, namespace=gfield%namespace)
420 safe_allocate(vecpot(1:gfield%space%dim, 1:2))
425 call drestart_write_binary(restart,
"gauge_field", 2*gfield%space%dim, vecpot, err)
426 safe_deallocate_a(vecpot)
427 if (err /= 0) ierr = ierr + 1
430 message(1) =
"Debug: Writing gauge field restart done."
431 call messages_info(1, namespace=gfield%namespace)
440 type(restart_t),
intent(in) :: restart
442 integer,
intent(out) :: ierr
445 real(real64),
allocatable :: vecpot(:,:)
451 if (restart_skip(restart))
then
458 message(1) =
"Debug: Reading gauge field restart."
459 call messages_info(1, namespace=gfield%namespace)
462 safe_allocate(vecpot(1:gfield%space%dim, 1:2))
463 call drestart_read_binary(restart,
"gauge_field", 2*gfield%space%dim, vecpot, err)
464 if (err /= 0) ierr = ierr + 1
468 safe_deallocate_a(vecpot)
471 message(1) =
"Debug: Reading gauge field restart done."
472 call messages_info(1, namespace=gfield%namespace)
482 type(grid_t),
intent(in) :: gr
483 integer,
intent(in) :: spin_channels
484 real(real64),
intent(in) :: current(:,:,:)
485 real(real64),
optional,
intent(in) :: lrc_alpha
487 integer :: idir, ispin
488 real(real64) :: lrc_alpha_
492 lrc_alpha_ = optional_default(lrc_alpha, m_zero)
494 select case (this%dynamics)
495 case (option__gaugefielddynamics__none)
496 this%force(1:this%space%dim) = m_zero
498 case (option__gaugefielddynamics__polarization)
499 do idir = 1, this%space%periodic_dim
500 this%force(idir) = m_zero
501 do ispin = 1, spin_channels
502 if(lrc_alpha_ > m_epsilon)
then
503 this%force(idir) = this%force(idir) + &
504 lrc_alpha*p_c/this%volume*dmf_integrate(gr, current(:, idir, ispin))
506 this%force(idir) = this%force(idir) - &
507 m_four*m_pi*p_c/this%volume*dmf_integrate(gr, current(:, idir, ispin))
523 type(algorithmic_operation_t),
intent(in) :: operation
524 real(real64),
intent(in) :: dt
525 real(real64),
intent(in) :: time
529 select case (operation%id)
534 case (verlet_update_pos)
536 case (verlet_compute_acc)
539 case (verlet_compute_vel)
540 this%vecpot_vel(1:this%space%dim) = this%vecpot_vel(1:this%space%dim) + &
541 m_half * dt * (this%vecpot_acc(1:this%space%dim) + this%force(1:this%space%dim))
543 message(1) =
"Unsupported TD operation."
544 call messages_fatal(1, namespace=this%namespace)
554 type(c_ptr),
intent(inout) :: out_gauge
555 integer,
intent(in) :: iter
558 character(len=50) :: aux
559 real(real64) :: temp(this%space%dim)
561 if (.not. mpi_grp_is_root(mpi_world))
return
566 call write_iter_clear(out_gauge)
567 call write_iter_string(out_gauge,
'################################################################################')
568 call write_iter_nl(out_gauge)
569 call write_iter_string(out_gauge,
'# HEADER')
570 call write_iter_nl(out_gauge)
573 call write_iter_header_start(out_gauge)
575 do idir = 1, this%space%dim
576 write(aux,
'(a2,i1,a1)')
'A(', idir,
')'
577 call write_iter_header(out_gauge, aux)
579 do idir = 1, this%space%dim
580 write(aux,
'(a6,i1,a1)')
'dA/dt(', idir,
')'
581 call write_iter_header(out_gauge, aux)
583 do idir = 1, this%space%dim
584 write(aux,
'(a10,i1,a1)')
'd^2A/dt^2(', idir,
')'
585 call write_iter_header(out_gauge, aux)
587 call write_iter_nl(out_gauge)
598 call write_iter_string(out_gauge,
'################################################################################')
599 call write_iter_nl(out_gauge)
603 call write_iter_start(out_gauge)
605 do idir = 1, this%space%dim
606 temp(idir) = units_from_atomic(units_out%energy, this%vecpot(idir))
608 call write_iter_double(out_gauge, temp, this%space%dim)
610 do idir = 1, this%space%dim
611 temp(idir) = units_from_atomic(units_out%energy / units_out%time, this%vecpot_vel(idir))
613 call write_iter_double(out_gauge, temp, this%space%dim)
615 do idir = 1, this%space%dim
616 temp(idir) = units_from_atomic(units_out%energy / units_out%time**2, this%vecpot_acc(idir))
618 call write_iter_double(out_gauge, temp, this%space%dim)
620 call write_iter_nl(out_gauge)
639 class(interaction_surrogate_t),
intent(inout) :: interaction
643 select type (interaction)
645 message(1) =
"Unsupported interaction."
646 call messages_fatal(1)
655 class(interaction_surrogate_t),
intent(inout) :: interaction
659 select type (interaction)
661 message(1) =
"Unsupported interaction."
662 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