module classes_dirac_distribution_plus use, intrinsic :: iso_fortran_env, only: DP => REAL64 use data_constants, only: PI use procedures_checks, only: check_positive implicit none private type, abstract, public :: Abstract_Dirac_Distribution_Plus contains procedure(Abstrac_get_width), deferred :: get_width procedure(Abstract_get), deferred :: get end type Abstract_Dirac_Distribution_Plus abstract interface pure real(DP) function Abstrac_get_width(this) import :: DP, Abstract_Dirac_Distribution_Plus class(Abstract_Dirac_Distribution_Plus), intent(in) :: this end function Abstrac_get_width pure real(DP) function Abstract_get(this, distance) import :: DP, Abstract_Dirac_Distribution_Plus class(Abstract_Dirac_Distribution_Plus), intent(in) :: this real(DP), intent(in) :: distance end function Abstract_get end interface type, extends(Abstract_Dirac_Distribution_Plus), public :: Rectangular_Dirac_Distribution_Plus private real(DP) :: delta_distance = 0._DP !volume dependency? contains procedure :: set => Rectangular_set procedure :: get_width => Rectangular_get_width procedure :: get => Rectangular_get end type Rectangular_Dirac_Distribution_Plus type, extends(Abstract_Dirac_Distribution_Plus), public :: Gaussian_Dirac_Distribution_Plus private real(DP) :: max_distance = 0._DP real(DP) :: std_dev = 0._DP !! \( \sigma \) contains procedure :: set => Gaussian_set procedure :: get_width => Gaussian_get_width procedure :: get => Gaussian_get end type Gaussian_Dirac_Distribution_Plus type, extends(Abstract_Dirac_Distribution_Plus), public :: Null_Dirac_Distribution_Plus contains procedure :: get_width => Null_get_width procedure :: get => Null_get end type Null_Dirac_Distribution_Plus contains !implementation Rectangular_Dirac_Distribution_Plus subroutine Rectangular_set(this, delta_distance) class(Rectangular_Dirac_Distribution_Plus), intent(inout) :: this real(DP), intent(in) :: delta_distance call check_positive("Rectangular_Dirac_Distribution_Plus: set", "delta_distance", & delta_distance) this%delta_distance = delta_distance end subroutine Rectangular_set !> \[ \mathrm{d}r \] pure real(DP) function Rectangular_get_width(this) result(width) class(Rectangular_Dirac_Distribution_Plus), intent(in) :: this width = this%delta_distance end function Rectangular_get_width !> \[ \frac{1}{\mathrm{d}r} \] pure real(DP) function Rectangular_get(this, distance) result(distribution) !change name? class(Rectangular_Dirac_Distribution_Plus), intent(in) :: this real(DP), intent(in) :: distance if (distance <= this%delta_distance) then distribution = 1._DP/this%delta_distance else distribution = 0._DP end if end function Rectangular_get !end implementation Rectangular_Dirac_Distribution_Plus !implementation Gaussian_Dirac_Distribution_Plus subroutine Gaussian_set(this, max_distance, num_std_devs) class(Gaussian_Dirac_Distribution_Plus), intent(inout) :: this real(DP), intent(in) :: max_distance integer :: num_std_devs !! \( \mathsf{n}_\sigma \) call check_positive("Gaussian_Dirac_Distribution_Plus: set", "max_distance", max_distance) this%max_distance = max_distance call check_positive("Gaussian_Dirac_Distribution_Plus: set", "num_std_devs", num_std_devs) this%std_dev = this%max_distance / real(num_std_devs, DP) end subroutine Gaussian_set !> \[ \mathsf{n}_\sigma \sigma \] pure real(DP) function Gaussian_get_width(this) result(width) class(Gaussian_Dirac_Distribution_Plus), intent(in) :: this width = this%max_distance end function Gaussian_get_width !> \[ !> r \mapsto \frac{1}{\sigma} \sqrt{\frac{2}{\pi}} !> \exp\left( -\frac{r^2}{2 \sigma^2} \right) !> \] pure real(DP) function Gaussian_get(this, distance) result(distribution) class(Gaussian_Dirac_Distribution_Plus), intent(in) :: this real(DP), intent(in) :: distance if (distance <= this%max_distance) then distribution = sqrt(2._DP / PI) / this%std_dev * & exp(-distance**2 / 2._DP / this%std_dev**2) else distribution = 0._DP end if end function Gaussian_get !end implementation Gaussian_Dirac_Distribution_Plus !implementation Null_Dirac_Distribution_Plus pure real(DP) function Null_get_width(this) result(width) class(Null_Dirac_Distribution_Plus), intent(in) :: this width = 0._DP end function Null_get_width pure real(DP) function Null_get(this, distance) result(distribution) class(Null_Dirac_Distribution_Plus), intent(in) :: this real(DP), intent(in) :: distance distribution = 0._DP end function Null_get !end implementation Null_Dirac_Distribution_Plus end module classes_dirac_distribution_plus