我是 Fortran 的新手,正在開發一個代碼,我經常在其中對兩種相似的派生型別進行操作(在這種情況下,代表科學計算代碼中的粒子模型)。這兩種型別是相同的,除了一種只有平移位置和速度分量,而另一種還包括角位置和速度。
type(particle_A)
real :: position(3)
real :: velocity(3)
end type
type(particle_B)
real :: position(6)
real :: velocity(6)
end type
我有另一種派生型別,它對兩種粒子的陣列進行分組(以及實際應用程式中的一些其他資料):
type(particleGroup)
type(particle_A), allocatable :: particleA_array(:)
integer :: NparticlesA
type(particle_B), allocatable :: particleB_array(:)
integer :: NparticlesB
character(len=30) :: particle_kind
end type
如果更多粒子進入此特定程序的模擬,則在運行時分配和重新分配兩個陣列。根據particle_kind設定的內容(在初始化期間),我想遍歷這兩個陣列之一并呼叫一些子程式(例如,用于更新位置和速度)。像這樣的東西(在回圈第一個陣列的情況下)
do iParticle = 1, nParticlesA
call updateVelocity( particleGroup%particleA_array(iParticle) )
end do
這用于回圈第二個陣列
do iParticle = 1, nParticlesB
call updateVelocity( particleGroup%particleB_array(iParticle) )
end do
updateVelocity使用介面塊實作的通用程序。Fortran 中有沒有辦法在初始化期間存盤要回圈的陣列(作為指標?),這樣我就不必particle_kind在每次回圈迭代時檢查?或者有沒有更好的方法來處理這個問題?
uj5u.com熱心網友回復:
如果您只對使用其中一個 ParticleA 或 ParticleB在運行時感興趣,那么您可以使用多型陣列來實作您想要的。
您首先必須定義一個父類,ParticleA并且ParticleB可以從該父類繼承,例如
module Particle_module
implicit none
type, abstract :: Particle
contains
procedure(Particle_update_velocity), deferred :: update_velocity
end type
interface
subroutine Particle_update_velocity(this)
import Particle
class(Particle), intent(inout) :: this
end subroutine
end interface
end module
然后你可以ParticleA寫成
module ParticleA_module
use Particle_module
implicit none
type, extends(Particle) :: ParticleA
real :: position(3)
real :: velocity(3)
contains
procedure :: update_velocity => ParticleA_update_velocity
end type
contains
subroutine ParticleA_update_velocity(this)
class(ParticleA), intent(inout) :: this
! ParticleA's update_velocity code goes here.
end subroutine
end module
和類似地對于ParticleB。
這將允許您撰寫ParticleGroup為具有單個多型陣列,它可以是型別ParticleA或ParticleB在運行時,例如
module ParticleGroup_module
use Particle_module
implicit none
type :: ParticleGroup
class(Particle), allocatable :: particles(:)
integer :: no_particles
contains
procedure :: update_velocities => ParticleGroup_update_velocities
end type
contains
subroutine ParticleGroup_update_velocities(this)
class(ParticleGroup), intent(inout) :: this
integer :: i
do i=1,this%no_particles
call this%particles(i)%update_velocity()
enddo
end subroutine
end module
然后你可以使用這些類
program p
use Particle_module
use ParticleA_module
use ParticleB_module
use ParticleGroup_module
implicit none
type(ParticleGroup) :: particle_group
! Fill out the variables of `particle_group`.
! Note that the `%particles` array now has the concrete type of `ParticleA`.
particle_group%particles = [ &
& ParticleA([0., 0., 0.], [1., 2., 3.]), &
& ParticleA([1., 1., 1.], [2., 3., 1.]) &
& ]
particle_group%no_particles = 2
! Call all the `update_velocity` subroutines.
call particle_group%update_velocities()
end program
在簡單的示例中,particle_group%no_particles單獨保存 tosize(particle_group%particles)是多余的,但我想如果您開始執行更高級的記憶體存盤策略(例如 C std::vector 樣式存盤),您可能需要它。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/462803.html
