module classes_des_real_component use, intrinsic :: iso_fortran_env, only: DP => REAL64 use data_constants, only: num_dimensions use classes_periodic_box, only: Abstract_Periodic_Box use classes_box_size_memento, only: Abstract_Box_Size_Memento use classes_component_coordinates, only: Abstract_Component_Coordinates use classes_component_dipole_moments, only: Abstract_Component_Dipole_Moments use types_particle_wrapper, only: Concrete_Particle use classes_des_real_pair, only: Abstract_DES_Real_Pair use procedures_visit_condition, only: abstract_visit_condition implicit none private type, abstract, public :: Abstract_DES_Real_Component private class(Abstract_Periodic_Box), pointer :: periodic_box => null() class(Abstract_Box_Size_Memento), pointer :: box_size_memento => null() class(Abstract_Component_Coordinates), pointer :: positions => null() class(Abstract_Component_Dipole_Moments), pointer :: dipole_moments => null() class(Abstract_DES_Real_Pair), pointer :: real_pair => null() contains procedure :: construct => Abstract_construct procedure :: destroy => Abstract_destroy procedure :: target => Abstract_target procedure :: visit => Abstract_visit end type Abstract_DES_Real_Component type, extends(Abstract_DES_Real_Component), public :: Concrete_DES_Real_Component end type Concrete_DES_Real_Component type, extends(Abstract_DES_Real_Component), public :: Null_DES_Real_Component contains procedure :: construct => Null_construct procedure :: destroy => Null_destroy procedure :: target => Null_target procedure :: visit => Null_visit end type Null_DES_Real_Component type, public :: DES_Real_Component_Wrapper class(Abstract_DES_Real_Component), allocatable :: component end type DES_Real_Component_Wrapper contains !implementation Abstract_DES_Real_Component subroutine Abstract_construct(this, periodic_box, box_size_memento, positions, & dipole_moments, real_pair) class(Abstract_DES_Real_Component), intent(out) :: this class(Abstract_Periodic_Box), target, intent(in) :: periodic_box class(Abstract_Box_Size_Memento), intent(in) :: box_size_memento class(Abstract_Component_Coordinates), target, intent(in) :: positions class(Abstract_Component_Dipole_Moments), target, intent(in) :: dipole_moments class(Abstract_DES_Real_Pair), intent(in) :: real_pair this%periodic_box => periodic_box this%positions => positions this%dipole_moments => dipole_moments call this%target(box_size_memento, real_pair) end subroutine Abstract_construct subroutine Abstract_destroy(this) class(Abstract_DES_Real_Component), intent(inout) :: this this%real_pair => null() this%dipole_moments => null() this%positions => null() this%box_size_memento => null() this%periodic_box => null() end subroutine Abstract_destroy subroutine Abstract_target(this, box_size_memento, real_pair) class(Abstract_DES_Real_Component), intent(inout) :: this class(Abstract_Box_Size_Memento), target, intent(in) :: box_size_memento class(Abstract_DES_Real_Pair), target, intent(in) :: real_pair this%box_size_memento => box_size_memento this%real_pair => real_pair end subroutine Abstract_target !> \[ !> \frac{V_\text{s}}{V} \sum_{j} [\text{c}(j, i_\text{exclude})] u \left(\left( !> \frac{V_\text{s}}{V} \right)^{1/3} \vec{r}_{ij}, \vec{\mu}_i, \vec{\mu}_j !> \right) !> \] !> cf. [[classes_box_size_memento:Abstract_get]] and !> [[classes_des_real_pair:Abstract_meet]] pure subroutine Abstract_visit(this, energy, particle, visit_condition, i_exclude) class(Abstract_DES_Real_Component), intent(in) :: this real(DP), intent(out) :: energy type(Concrete_Particle), intent(in) :: particle procedure(abstract_visit_condition) :: visit_condition integer, intent(in) :: i_exclude real(DP) :: box_size_ratio(num_dimensions), box_edge_ratio real(DP) :: vector_ij(num_dimensions) integer :: j_particle box_size_ratio = this%box_size_memento%get() / this%periodic_box%get_size() box_edge_ratio = box_size_ratio(1) energy = 0._DP do j_particle = 1, this%positions%get_num() if (.not.visit_condition(j_particle, i_exclude)) cycle vector_ij = this%periodic_box%vector(particle%position, this%positions%get(j_particle)) energy = energy + this%real_pair%meet(box_edge_ratio * vector_ij, particle%& dipole_moment, this%dipole_moments%get(j_particle)) end do energy = product(box_size_ratio) * energy end subroutine Abstract_visit !end implementation Abstract_DES_Real_Component !implementation Null_DES_Real_Component subroutine Null_construct(this, periodic_box, box_size_memento, positions, dipole_moments, & real_pair) class(Null_DES_Real_Component), intent(out) :: this class(Abstract_Periodic_Box), target, intent(in) :: periodic_box class(Abstract_Box_Size_Memento), intent(in) :: box_size_memento class(Abstract_Component_Coordinates), target, intent(in) :: positions class(Abstract_Component_Dipole_Moments), target, intent(in) :: dipole_moments class(Abstract_DES_Real_Pair), intent(in) :: real_pair end subroutine Null_construct subroutine Null_destroy(this) class(Null_DES_Real_Component), intent(inout) :: this end subroutine Null_destroy subroutine Null_target(this, box_size_memento, real_pair) class(Null_DES_Real_Component), intent(inout) :: this class(Abstract_Box_Size_Memento), target, intent(in) :: box_size_memento class(Abstract_DES_Real_Pair), target, intent(in) :: real_pair end subroutine Null_target pure subroutine Null_visit(this, energy, particle, visit_condition, i_exclude) class(Null_DES_Real_Component), intent(in) :: this real(DP), intent(out) :: energy type(Concrete_Particle), intent(in) :: particle procedure(abstract_visit_condition) :: visit_condition integer, intent(in) :: i_exclude energy = 0._DP end subroutine Null_visit !end implementation Null_DES_Real_Component end module classes_des_real_component