module classes_dlc_weight use, intrinsic :: iso_fortran_env, only: DP => REAL64 use data_constants, only: num_dimensions, PI use classes_periodic_box, only: Abstract_Periodic_Box use classes_reciprocal_lattice, only: Abstract_Reciprocal_Lattice use classes_permittivity, only: Abstract_Permittivity implicit none private type, abstract, public :: Abstract_DLC_Weight private class(Abstract_Periodic_Box), pointer :: periodic_box => null() integer :: reci_numbers(num_dimensions) = 0 real(DP) :: permittivity = 0._DP real(DP), dimension(:, :), allocatable :: weight contains procedure :: construct => Abstract_construct procedure :: destroy => Abstract_destroy procedure :: target => Abstract_target procedure :: reset => Abstract_reset procedure :: get => Abstract_get end type Abstract_DLC_Weight type, extends(Abstract_DLC_Weight), public :: Concrete_DLC_Weight end type Concrete_DLC_Weight type, extends(Abstract_DLC_Weight), public :: Null_DLC_Weight contains procedure :: construct => Null_construct procedure :: destroy => Null_destroy procedure :: target => Null_target procedure :: reset => Null_reset procedure :: get => Null_get end type Null_DLC_Weight contains !implementation Abstract_DLC_Weight !> @note cf. [[classes_des_reci_weight:Abstract_construct]] for !> [[classes_dlc_weight:Abstract_reset]] subroutine Abstract_construct(this, periodic_box, reciprocal_lattice, permittivity) class(Abstract_DLC_Weight), intent(out) :: this class(Abstract_Periodic_Box), intent(in) :: periodic_box class(Abstract_Reciprocal_Lattice), intent(in) :: reciprocal_lattice class(Abstract_Permittivity), intent(in) :: permittivity call this%target(periodic_box) this%reci_numbers = reciprocal_lattice%get_numbers() this%permittivity = permittivity%get() allocate(this%weight(0:this%reci_numbers(1), 0:this%reci_numbers(2))) this%weight = 0._DP end subroutine Abstract_construct subroutine Abstract_destroy(this) class(Abstract_DLC_Weight), intent(inout) :: this if (allocated(this%weight)) deallocate(this%weight) this%periodic_box => null() end subroutine Abstract_destroy subroutine Abstract_target(this, periodic_box) class(Abstract_DLC_Weight), intent(inout) :: this class(Abstract_Periodic_Box), target, intent(in) :: periodic_box this%periodic_box => periodic_box end subroutine Abstract_target subroutine Abstract_reset(this) class(Abstract_DLC_Weight), intent(inout) :: this real(DP) :: box_size(num_dimensions), wave_vector(2), wave_norm integer :: n_1, n_2 box_size = this%periodic_box%get_size() do n_2 = 0, this%reci_numbers(2) wave_vector(2) = 2._DP*PI * real(n_2, DP) / box_size(2) do n_1 = 0, this%reci_numbers(1) wave_vector(1) = 2._DP*PI * real(n_1, DP) / box_size(1) if (n_1**2 + n_2**2 > this%reci_numbers(1)**2) cycle if (n_1 == 0 .and. n_2 == 0) then this%weight(n_1, n_2) = 0._DP else wave_norm = norm2(wave_vector) this%weight(n_1, n_2) = 1._DP / (2._DP*this%permittivity*product(box_size(1:2))) / & (wave_norm * (exp(wave_norm*box_size(3)) - 1._DP)) end if end do end do end subroutine Abstract_reset !> \[ !> w(\vec{k}_{1:2}) = !> \begin{cases} !> 0 & \text{if } \vec{k}_{1:2} = \vec{0} \\ !> \frac{1}{2\epsilon S} \frac{1}{k_{1:2} (e^{k_{1:2} L_3} - 1)} & \text{else} !> \end{cases} !> \] pure real(DP) function Abstract_get(this, n_1, n_2) result(weight) class(Abstract_DLC_Weight), intent(in) :: this integer, intent(in) :: n_1, n_2 weight = this%weight(abs(n_1), abs(n_2)) end function Abstract_get !end implementation Abstract_DLC_Weight !implementation Null_DLC_Weight subroutine Null_construct(this, periodic_box, reciprocal_lattice, permittivity) class(Null_DLC_Weight), intent(out) :: this class(Abstract_Periodic_Box), intent(in) :: periodic_box class(Abstract_Reciprocal_Lattice), intent(in) :: reciprocal_lattice class(Abstract_Permittivity), intent(in) :: permittivity end subroutine Null_construct subroutine Null_destroy(this) class(Null_DLC_Weight), intent(inout) :: this end subroutine Null_destroy subroutine Null_target(this, periodic_box) class(Null_DLC_Weight), intent(inout) :: this class(Abstract_Periodic_Box), target, intent(in) :: periodic_box end subroutine Null_target subroutine Null_reset(this) class(Null_DLC_Weight), intent(inout) :: this end subroutine Null_reset pure real(DP) function Null_get(this, n_1, n_2) result(weight) class(Null_DLC_Weight), intent(in) :: this integer, intent(in) :: n_1, n_2 weight = 0._DP end function Null_get !end implementation Null_DLC_Weight end module classes_dlc_weight