67 real(real64) :: rashba_coupling
68 type(nl_operator_t),
pointer,
public :: kinetic
69 real(real64),
allocatable,
public :: potential(:, :)
70 real(real64),
allocatable,
public :: Impotential(:, :)
71 real(real64),
allocatable,
public :: uniform_magnetic_field(:)
73 real(real64),
allocatable,
public :: magnetic_field(:, :)
75 real(real64),
allocatable,
public :: zeeman_pot(:, :)
76 real(real64),
allocatable,
public :: uniform_vector_potential(:)
80 real(real64),
allocatable,
public :: vector_potential(:, :)
81 type(accel_mem_t) :: potential_accel
82 type(accel_mem_t) :: impotential_accel
115 integer,
parameter,
public :: &
116 TERM_ALL = huge(1), &
126 integer,
parameter,
public :: &
127 FIELD_POTENTIAL = 1, &
139 class(hamiltonian_elec_base_t),
intent(inout) :: this
140 integer,
intent(in) :: nspin
141 real(real64),
intent(in) :: mass
142 real(real64),
intent(in) :: rashba_coupling
148 this%rashba_coupling = rashba_coupling
157 class(hamiltonian_elec_base_t),
intent(inout) :: this
163 if (
allocated(this%Impotential))
then
168 safe_deallocate_a(this%potential)
169 safe_deallocate_a(this%Impotential)
170 safe_deallocate_a(this%vector_potential)
171 safe_deallocate_a(this%uniform_vector_potential)
172 safe_deallocate_a(this%uniform_magnetic_field)
173 safe_deallocate_a(this%magnetic_field)
174 safe_deallocate_a(this%zeeman_pot)
186 integer,
intent(in) :: np
190 push_sub(hamiltonian_elec_clear)
192 if (
allocated(this%potential))
then
193 do ispin = 1, this%nspin
201 if (
allocated(this%Impotential))
then
202 do ispin = 1, this%nspin
205 this%Impotential(ip, ispin) =
m_zero
210 if (
allocated(this%uniform_vector_potential))
then
211 this%uniform_vector_potential =
m_zero
214 if (
allocated(this%vector_potential))
then
215 this%vector_potential =
m_zero
218 if (
allocated(this%uniform_magnetic_field))
then
219 this%uniform_magnetic_field =
m_zero
222 if (
allocated(this%magnetic_field))
then
223 this%magnetic_field =
m_zero
226 if (
allocated(this%zeeman_pot))
then
230 pop_sub(hamiltonian_elec_clear)
239 class(
mesh_t),
intent(in) :: mesh
240 integer,
intent(in) :: field
241 logical,
intent(in) :: complex_potential
247 if (
bitand(field_potential, field) /= 0)
then
248 if (.not.
allocated(this%potential))
then
249 safe_allocate(this%potential(1:mesh%np, 1:this%nspin))
250 do ispin = 1, this%nspin
253 this%potential(ip, ispin) =
m_zero
256 if (complex_potential)
then
257 safe_allocate(this%Impotential(1:mesh%np, 1:this%nspin))
258 do ispin = 1, this%nspin
261 this%Impotential(ip, ispin) =
m_zero
267 if (complex_potential)
then
276 if (.not.
allocated(this%uniform_vector_potential))
then
277 safe_allocate(this%uniform_vector_potential(1:mesh%box%dim))
278 this%uniform_vector_potential =
m_zero
283 if (.not.
allocated(this%vector_potential))
then
284 safe_allocate(this%vector_potential(1:mesh%box%dim, 1:mesh%np))
285 this%vector_potential =
m_zero
290 if (.not.
allocated(this%uniform_magnetic_field))
then
291 safe_allocate(this%uniform_magnetic_field(1:max(mesh%box%dim, 3)))
292 this%uniform_magnetic_field =
m_zero
298 if (.not.
allocated(this%magnetic_field))
then
299 safe_allocate(this%magnetic_field(1:mesh%np, 1:max(mesh%box%dim, 3)))
300 this%magnetic_field =
m_zero
301 safe_allocate(this%zeeman_pot(1:mesh%np, 1:this%nspin))
319 class(
mesh_t),
intent(in) :: mesh
320 real(real64),
intent(in) :: gyromagnetic_ratio
321 integer,
intent(in) :: ispin
323 real(real64) :: cc, b_perp2
325 logical,
save :: warning_shown = .false.
329 if (
allocated(this%uniform_vector_potential) .and.
allocated(this%vector_potential))
then
331 do idir = 1, mesh%box%dim
334 this%vector_potential(idir, ip) = &
335 this%vector_potential(idir, ip) + this%uniform_vector_potential(idir)
338 safe_deallocate_a(this%uniform_vector_potential)
342 if (.not.
allocated(this%magnetic_field))
then
355 if (
allocated(this%uniform_magnetic_field) )
then
360 this%magnetic_field(ip, idir) = this%magnetic_field(ip, idir) + this%uniform_magnetic_field(idir)
373 this%zeeman_pot(ip, 1) = cc*this%magnetic_field(ip, 3)
374 this%zeeman_pot(ip, 2) = - cc*this%magnetic_field(ip, 3)
375 b_perp2 = b_perp2 + this%magnetic_field(ip, 1)**2 + this%magnetic_field(ip, 2)**2
377 call mesh%allreduce(b_perp2)
378 if (b_perp2 >
m_epsilon .and. .not. warning_shown)
then
379 message(1) =
"The magnetic field has x or y components, which do not enter the Zeeman term"
380 message(2) =
"for spin-polarized calculations (spin axis z). Use spinors to include them."
382 warning_shown = .
true.
388 this%zeeman_pot(ip, 1) = cc*this%magnetic_field(ip, 3)
389 this%zeeman_pot(ip, 2) = - cc*this%magnetic_field(ip, 3)
390 this%zeeman_pot(ip, 3) = cc*this%magnetic_field(ip, 1)
391 this%zeeman_pot(ip, 4) = - cc*this%magnetic_field(ip, 2)
394 safe_deallocate_a(this%uniform_magnetic_field)
405 class(
mesh_t),
intent(in) :: mesh
407 integer :: offset, ispin
413 do ispin = 1, this%nspin
414 call accel_write_buffer(this%potential_accel, mesh%np, this%potential(:, ispin), offset = offset)
415 if(
allocated(this%Impotential))
then
416 call accel_write_buffer(this%impotential_accel, mesh%np, this%Impotential(:, ispin), offset = offset)
429 class(
mesh_t),
intent(in) :: mesh
431 logical :: complex_potential
443 if (.not.
allocated(this%potential))
then
448 complex_potential =
allocated(this%Impotential)
452 if (complex_potential)
then
457 call this%accel_copy_pot(mesh)
465 logical pure function hamiltonian_elec_base_has_magnetic(this) result(has_magnetic)
468 has_magnetic =
allocated(this%vector_potential) &
469 .or.
allocated(this%uniform_magnetic_field) &
470 .or.
allocated(this%magnetic_field)
477 logical pure function hamiltonian_elec_base_has_zeeman(this) result(has_zeeman)
480 has_zeeman =
allocated(this%zeeman_pot)
487 logical pure function hamiltonian_elec_base_has_vector_potential(this) result(has_vector_potential)
490 has_vector_potential =
allocated(this%vector_potential) &
491 .or.
allocated(this%uniform_vector_potential)
498 class(mesh_t),
intent(in) :: mesh
499 type(derivatives_t),
intent(in) :: der
500 type(states_elec_dim_t),
intent(in) :: std
501 type(wfs_elec_t),
target,
intent(in) :: psib
502 type(wfs_elec_t),
target,
intent(inout) :: vpsib
504 integer :: ist, idim, ip
505 complex(real64),
allocatable :: psi(:, :), vpsi(:, :), grad(:, :, :)
509 if (abs(this%rashba_coupling) < m_epsilon)
then
513 assert(std%ispin == spinors)
514 assert(mesh%box%dim == 2)
515 assert(psib%type() == type_cmplx)
516 assert(vpsib%type() == type_cmplx)
518 safe_allocate(psi(1:mesh%np_part, 1:std%dim))
519 safe_allocate(vpsi(1:mesh%np, 1:std%dim))
520 safe_allocate(grad(1:mesh%np, 1:mesh%box%dim, 1:std%dim))
523 call batch_get_state(psib, ist, mesh%np_part, psi)
524 call batch_get_state(vpsib, ist, mesh%np, vpsi)
527 call zderivatives_grad(der, psi(:, idim), grad(:, :, idim), ghost_update = .false., set_bc = .false.)
530 if (
allocated(this%vector_potential))
then
532 vpsi(ip, 1) = vpsi(ip, 1) - &
533 (this%rashba_coupling) * cmplx(this%vector_potential(2, ip), this%vector_potential(1, ip), real64) * psi(ip, 2)
534 vpsi(ip, 2) = vpsi(ip, 2) - &
535 (this%rashba_coupling) * cmplx(this%vector_potential(2, ip), -this%vector_potential(1, ip), real64) * psi(ip, 1)
540 vpsi(ip, 1) = vpsi(ip, 1) - &
541 this%rashba_coupling*( grad(ip, 1, 2) - m_zi*grad(ip, 2, 2))
542 vpsi(ip, 2) = vpsi(ip, 2) + &
543 this%rashba_coupling*( grad(ip, 1, 1) + m_zi*grad(ip, 2, 1))
546 call batch_set_state(vpsib, ist, mesh%np, vpsi)
549 safe_deallocate_a(grad)
550 safe_deallocate_a(vpsi)
551 safe_deallocate_a(psi)
558#include "hamiltonian_elec_base_inc.F90"
561#include "complex.F90"
562#include "hamiltonian_elec_base_inc.F90"
subroutine, public accel_free_buffer(this, async)
subroutine, public accel_detach_buffer(this)
Clear a buffer handle without freeing device memory.
pure logical function, public accel_is_enabled()
integer, parameter, public accel_mem_read_only
This module implements batches of mesh functions.
This module implements common operations on batches of mesh functions.
This module contains interfaces for BLAS routines You should not use these routines directly....
This module calculates the derivatives (gradients, Laplacians, etc.) of a function.
integer, parameter, public spinors
integer, parameter, public spin_polarized
real(real64), parameter, public m_zero
real(real64), parameter, public m_epsilon
real(real64), parameter, public m_half
real(real64), parameter, public p_c
Electron gyromagnetic ratio, see Phys. Rev. Lett. 130, 071801 (2023)
logical pure function hamiltonian_elec_base_has_vector_potential(this)
return .true. of the Hamiltonian contains any vector potential
subroutine hamiltonian_elec_base_accel_copy_pot(this, mesh)
copy the potential to the acceleration device buffer
subroutine, public dhamiltonian_elec_base_local_sub(potential, mesh, std, ispin, psib, vpsib, Impotential, potential_accel, impotential_accel, async)
apply a local potential to a set of states
subroutine hamiltonian_elec_base_update_magnetic_terms(this, mesh, gyromagnetic_ratio, ispin)
update the magnetic terms of the hamiltonian_elec_base_t.
integer, parameter, public term_local_external
subroutine hamiltonian_elec_base_rashba(this, mesh, der, std, psib, vpsib)
subroutine dhamiltonian_elec_base_local(this, mesh, std, ispin, psib, vpsib, async)
apply the local potential (stored in the hamiltonian) to the states
integer, parameter, public field_uniform_magnetic_field
subroutine zhamiltonian_elec_base_magnetic(this, mesh, der, std, ispin, psib, vpsib)
apply magnetic terms form the Hamiltonian to the wave functions
subroutine hamiltonian_elec_base_allocate(this, mesh, field, complex_potential)
This function ensures that the corresponding field is allocated.
integer, parameter, public field_uniform_vector_potential
integer, parameter, public field_vector_potential
subroutine hamiltonian_elec_base_clear(this, np)
This functions sets to zero all fields that are currently allocated.
logical pure function hamiltonian_elec_base_has_magnetic(this)
return .true. if the Hamiltonian contains any magnetic field
subroutine hamiltonian_elec_base_end(this)
Finalizer for hamiltonian_elec_base_t.
integer, parameter, public term_mgga
integer, parameter, public term_others
integer, parameter, public term_non_local_potential
integer, parameter, public term_rdmft_occ
integer, parameter, public term_kinetic
subroutine zhamiltonian_elec_base_local(this, mesh, std, ispin, psib, vpsib, async)
apply the local potential (stored in the hamiltonian) to the states
subroutine dhamiltonian_elec_base_magnetic(this, mesh, der, std, ispin, psib, vpsib)
apply magnetic terms form the Hamiltonian to the wave functions
logical pure function hamiltonian_elec_base_has_zeeman(this)
return .true. of the Hamiltonian contains a zeeman term
integer, parameter, public field_magnetic_field
subroutine, public zhamiltonian_elec_base_local_sub(potential, mesh, std, ispin, psib, vpsib, Impotential, potential_accel, impotential_accel, async)
apply a local potential to a set of states
subroutine hamiltonian_elec_base_init(this, nspin, mass, rashba_coupling)
initialize the hamiltonian_elec_base_t object
subroutine, public hamiltonian_elec_base_accel_rebuild(this, mesh)
Rebuild accelerator buffers after an intrinsic copy.
integer, parameter, public term_dft_u
integer, parameter, public term_local_potential
This module is intended to contain "only mathematical" functions and procedures.
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
This module defines non-local operators.
This module handles spin dimensions of the states and the k-point distribution.
type(type_t), parameter, public type_float
The basic Hamiltonian for electronic system.
Describes mesh distribution to nodes.