spx_density_summation.f90 Source File


Contents


Source Code

!> author: 左志华
!> date: 2022-06-17
!>
!> 针对实粒子进行密度求和:<br>
!> 1. 连续密度法;<br>
!> 2. 正则密度求和法;<br>
!> 3. 密度求和法。
module spx_density_summation

    use spx_kinds, only: rk
    use spx_particle, only: particle_type
    use spx_nnps_pairs, only: nnps_pairs_type
    use spx_smoothed_kernel_function, only: skf_obj
    use spx_configuration, only: spc_obj
    implicit none

    private
    public :: dsm_obj

    !> 密度求和
    type density_summation
        procedure(density_summation_fcn), pointer, nopass :: density  !! 密度求和函数指针
    contains
        procedure :: init
    end type density_summation

    type(density_summation) :: dsm_obj  !! 密度求和对象

    abstract interface
        !> Density summation <br>
        !> 密度求和
        subroutine density_summation_fcn(particle, pairs, n)
            import :: particle_type, nnps_pairs_type
            type(particle_type), intent(inout) :: particle      !! particle <br>
                                                                !! 区域
            type(nnps_pairs_type), intent(in) :: pairs               !! particle pairs <br>
                                                                !! 粒子对
            integer, intent(in) :: n                            !! 实弹性粒子数, numbers(1)
        end subroutine density_summation_fcn

    end interface

contains

    !> 初始化
    subroutine init(self)
        class(density_summation), intent(inout) :: self

        select case (spc_obj%density_summation_method)
        case ('continuous')
            self%density => continuous_density_summation
        case ('normalized')
            self%density => normalized_density_summation
        case ('denormalized')
            self%density => denormalized_density_summation
        case default
            self%density => denormalized_density_summation
        end select

    end subroutine init

    !> 对所有实粒子粒子进行非正则化密度求和
    subroutine denormalized_density_summation(particle, pairs, n)
        type(particle_type), intent(inout) :: particle      !! 区域
        type(nnps_pairs_type), intent(in) :: pairs          !! 粒子对
        integer, intent(in) :: n                            !! 实弹性粒子数 \( N_{real} \)
        integer :: i

        particle%rho(:n) = skf_obj%selfden*particle%mass(:n)              ! 计算自身对密度的影响,并初始化当前步长密度值

        do i = 1, pairs%len                        ! 计算密度求和
            associate (ip => pairs%items(2*i - 1), jp => pairs%items(2*i))

                if (ip <= n .and. jp <= n) then
                    if (particle%itype(ip) /= particle%itype(jp)) cycle
                    particle%rho(ip) = particle%rho(ip) + particle%mass(jp)*pairs%wdwdx(1, i)
                    particle%rho(jp) = particle%rho(jp) + particle%mass(ip)*pairs%wdwdx(1, i)
                end if

            end associate
        end do

    end subroutine denormalized_density_summation

    !> Normalized density summation <br>
    !> 对所有粒子进行正则化密度求和法
    !> @note 计算量较密度求和法大
    pure subroutine normalized_density_summation(particle, pairs, n)
        type(particle_type), intent(inout) :: particle  !! particle <br>
                                                        !! 区域
        type(nnps_pairs_type), intent(in) :: pairs           !! particle pairs <br>
                                                        !! 粒子对
        integer, intent(in) :: n                        !! 实弹性粒子数, numbers(1)
                                                        !! @note 用以定义本地数组长度
        integer :: i
        real(rk) :: rho_tmp(n), wi(n)                   !! 分母部分

        rho_tmp(:n) = particle%rho(:n)                  ! 临时存储密度值

        particle%rho(:n) = skf_obj%selfden*particle%mass(:n)
        wi(:n) = particle%rho(:n)/rho_tmp(:n)

        do concurrent(i=1:pairs%len)            ! 计算密度求和
            associate (ip => pairs%items(2*i - 1), jp => pairs%items(2*i))

                if (ip <= n .and. jp <= n) then
                    if (particle%itype(ip) /= particle%itype(jp)) cycle
                    particle%rho(ip) = particle%rho(ip) + particle%mass(jp)*pairs%wdwdx(1, i)
                    particle%rho(jp) = particle%rho(jp) + particle%mass(ip)*pairs%wdwdx(1, i)
                    wi(ip) = wi(ip) + particle%mass(jp)*pairs%wdwdx(1, i)/rho_tmp(jp)
                    wi(jp) = wi(jp) + particle%mass(ip)*pairs%wdwdx(1, i)/rho_tmp(ip)
                end if

            end associate
        end do

        particle%rho(:n) = particle%rho(:n)/wi(:n)  ! 正则化密度

    end subroutine normalized_density_summation

    !> Continuous density summation <br>
    !> 基于连续性方程的连续密度法,计算密度的增量以在时间积分算法中更新密度值
    !> @todo itype 相同才进行密度求和?
    pure subroutine continuous_density_summation(particle, pairs, n)
        type(particle_type), intent(inout) :: particle  !! particle <br>
                                                        !! 区域
        type(nnps_pairs_type), intent(in) :: pairs           !! particle pairs <br>
                                                        !! 粒子对
        integer, intent(in) :: n                        !! 实弹性粒子数, numbers(1)
        integer :: i
        real(rk) :: dvel(2)

        particle%drho(:n) = 0.0_rk
        do concurrent(i=1:pairs%len)
            associate (ip => pairs%items(2*i - 1), jp => pairs%items(2*i))

                if (ip <= n .and. jp <= n) then
                    if (particle%itype(ip) /= particle%itype(jp)) cycle
                    dvel(:) = particle%vel(:, ip) - particle%vel(:, jp)

                    associate (vcc => sum(dvel(:)*pairs%wdwdx(2:3, i)))
                        particle%drho(ip) = particle%drho(ip) + particle%mass(jp)*vcc
                        particle%drho(jp) = particle%drho(jp) + particle%mass(ip)*vcc
                    end associate
                end if

            end associate
        end do

    end subroutine continuous_density_summation

end module spx_density_summation