!> author: 左志华 !> date: 2022-07-02 !> license: BSD 3-Clause !> !> External forces <br> !> 外力:1. 重力;2. 边界排斥力。 module spx_external_force use spx_kinds, only: rk use seakeeping_module, only: g use spx_particle, only: particle_type use spx_pif_h5part, only: pif_obj use spx_nnps_pairs, only: nnps_pairs_type use spx_configuration, only: spc_obj use spx_env, only: rgn_obj implicit none private public :: exf_obj !> 外力求解 type external_force_type procedure(external_force_fcn), pointer :: run real(rk) :: r0 !! 排斥力半径 real(rk) :: dd !! 速度最大值的平方量级 contains procedure :: init end type external_force_type type(external_force_type) :: exf_obj integer, parameter :: p1 = 12, p2 = 4 !! p1, p2 are used to calculate the boundary repulsion <br> !! p1, p2 用来计算边界排斥力 abstract interface !> Solve the external force <br> !> 外力求解,涉及重力和边界力 subroutine external_force_fcn(self, particle, pairs, acc, n) import :: particle_type, nnps_pairs_type, rk, external_force_type class(external_force_type), intent(inout) :: self type(particle_type), intent(in) :: particle !! particle <br> !! 区域 type(nnps_pairs_type), intent(in) :: pairs !! Pairs <br> !! 粒子对 real(rk), intent(inout) :: acc(:, :) !! Acceleration <br> !! 加速度 integer, intent(in) :: n !! 实粒子数, nreal end subroutine external_force_fcn end interface contains !> 初始化 subroutine init(self) class(external_force_type), intent(inout) :: self if (spc_obj%has_gravity) then self%run => external_force_with_gravity else self%run => external_force_without_gravity end if self%r0 = 0.9_rk*rgn_obj%hsml self%dd = (spc_obj%c0/2)**2 end subroutine init !> 含重力、排斥力的外力求解 subroutine external_force_with_gravity(self, particle, pairs, acc, n) class(external_force_type), intent(inout) :: self type(particle_type), intent(in) :: particle !! 区域 type(nnps_pairs_type), intent(in) :: pairs !! 粒子对 real(rk), intent(inout) :: acc(:, :) !! 加速度 \( F_{external} = -g + F_{boundary} \) integer, intent(in) :: n !! 实粒子数 \( N_{real} \) integer :: i ! -------------------------------- 计算重力 --------------------------------- ! acc(2, :n) = acc(2, :n) - g ! 仅对实体粒子起作用,虚粒子不需要求解加速度而运动 ! ----------------------------- 计算边界排斥力 ------------------------------- ! do i = 1, pairs%len associate (ip => pairs%items(2*i - 1), jp => pairs%items(2*i), r => pairs%rdx(3*i - 2)) select case (pairs%contact_type(i)) case (3:4) if (r < self%r0) then associate (f => ((self%r0/r)**p1 - (self%r0/r)**p2)/(r*r), & dx => pairs%rdx(3*i - 1:3*i)) acc(:, ip) = acc(:, ip) + self%dd*dx(:)*f acc(:, jp) = acc(:, jp) - self%dd*dx(:)*f end associate end if end select end associate end do end subroutine external_force_with_gravity !> 排斥力的外力求解 (无重力) pure subroutine external_force_without_gravity(self, particle, pairs, acc, n) class(external_force_type), intent(inout) :: self type(particle_type), intent(in) :: particle !! 区域 type(nnps_pairs_type), intent(in) :: pairs !! 粒子对 real(rk), intent(inout) :: acc(:, :) !! 加速度 \( F_{external} = F_{boundary} \) integer, intent(in) :: n !! 实粒子数 \( N_{real} \) integer :: i ! ----------------------------- 计算边界排斥力 ------------------------------- ! do i = 1, pairs%len associate (ip => pairs%items(2*i - 1), jp => pairs%items(2*i), r => pairs%rdx(3*i - 2)) select case (pairs%contact_type(i)) case (3:4) if (r < self%r0) then associate (f => ((self%r0/r)**p1 - (self%r0/r)**p2)/(r*r), & dx => pairs%rdx(3*i - 1:3*i)) acc(:, ip) = acc(:, ip) + self%dd*dx(:)*f acc(:, jp) = acc(:, jp) - self%dd*dx(:)*f end associate end if end select end associate end do end subroutine external_force_without_gravity end module spx_external_force