mas*_*p88 3 arrays fortran allocation fortran90
我试图在每次运行后保存并重用一个2D变量但我得到一些错误,如自动对象无法保存等.这是子程序:
subroutine dust_sum_test(ngrid,count,dust_in,dust_out)
!Subroutine to accumulate and release dust in timely manner
implicit none
integer,intent(in)::ngrid
integer,intent(in)::count
real,intent(in)::dust_in(ngrid)
real,intent(out)::dust_out(ngrid)
real,save::dmsdust(ngrid,99999) ! dummy local variable
integer::i
if (count.gt.1) then
dmsdust(:,count)=dmsdust(:,count-1)+dust_in
dust_out=dmsdust(:,count)
else
dust_out=dust_in
dmsdust(:,count)=0.0
endif
write(*,*)'The current count is = ', count
end subroutine dust_sum_test
Run Code Online (Sandbox Code Playgroud)
我需要使用以前的dmsdust值添加当前值.请让我知道如何解决这个问题.
错误是正确的 - 您无法保存自动数组.出现此特定错误的原因是:
dmsdust每次dust_sum_test执行时都会自动形成一个基于输入的大小dmsdust.dmsdust自动阵列也是如此.您的子程序每次运行时都会dust_sum_test获取值ngrid,但每次都没有ngrid相同的保证.如果第一次运行ngrid是1而第二次ngrid是2,该怎么办?如何dmsdust保存并改变形状?所以编译器不会让你犯这个错误.
您问题的真正解决方案是改变您的方法.你的问题没有说明为什么你需要存储历史dust,但我认为你这样做.但是,您没有理由将它存储在此子例程中!事实上,将它存储在子程序中(作为saved值)意味着它很难访问.相反,我相信还有另外两个不错的选择.
模块是现代fortran的主要产品,可以存储数据和子程序.您可以保留dust此模块的历史记录,并在模块内外访问它.实现看起来像:
module mymod
implicit none
real, allocatable :: dmsdust(:,:)
contains
subroutine init_dmsdust(ngrid)
integer, intent(IN) :: ngrid
allocate(dmsdust(ngrid,9999))
end subroutine init_dmsdust
subroutine dust_sum_test(ngrid,count,dust_in,dust_out)
! -- all your other code, but now dmsdust is not an automatic array
end subroutine dust_sum_test
end module mymod
Run Code Online (Sandbox Code Playgroud)
在此实现中,您必须init_dmsdust在开始时调用一次以分配存储空间.然后在每次调用时使用它dmsdust.您可以dmsdust通过向代码的另一部分添加访问子例程mymod或use变量dmsdust来访问.
该解决方案更简单但不具有可扩展性或优雅性.而不是给予dust_sum_test保留的工作dmsdust,使任何例程负责调用dust_sum_testallocate和pass dmsdust.调用例程的一部分如下所示:
allocate(dmsdust(ngrid,9999))
do count=1,max ! -- The main loop
call dust_sum_test(ngrid,count,dust_in,dust_out,dmsdust)
! some other stuff
enddo
Run Code Online (Sandbox Code Playgroud)
然后子程序看起来像:
subroutine dust_sum_test(ngrid,count,dust_in,dust_out,dmsdust)
implicit none
real, intent(INOUT) :: dmsdust(:,:)
! -- All the other stuff
end subroutine dust_sum_test
Run Code Online (Sandbox Code Playgroud)
这样调用例程可以访问,dmsdust并且已知它总是具有相同的大小.
Ross解释了错误的来源,并提供了一些合理的其他方法.下面是答案中未提及的另一个.我不是说它更好,或者推荐它.
虽然自动对象不能具有该save属性,但可分配的数组可以.保存的本地可分配对象保留其分配状态,如果已分配,则保留其形状(如果是数组)和值.
real, allocatable, save :: dmsdust(:,:) ! Initially not allocated
...
! Our first-time initialization and subsequent consistency check follows
if (.not.allocated(dmsdust)) then
allocate(dmsdust(ngrid,99999), source=0.)
else
if (size(dmsdust,1).ne.ngrid) error stop ! or some other handling
end if
Run Code Online (Sandbox Code Playgroud)