Can a input argument of a Fortran subroutine be deallocated and allocated in the body of the subroutine?

情到浓时终转凉″ 提交于 2020-01-03 02:11:20

问题


UPDATE: My modified code looks like this:

program run_module_test
    use module_test
    implicit none   

    TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)

    call update(xyzArray)
    write(6,*)'xyzArray',xyzArray

end program run_module_test

module module_test
    implicit none

    TYPE :: newXYZ
        real(4) :: x, u
        real(4) :: y, v
        real(4) :: z, w
        real(4),dimension(3) :: uvw     
    END TYPE

    integer(4) :: shape = 3

contains

    subroutine update(xyzArray)

    integer(4) :: i
    TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
    allocate( xyzArray(shape) ) 

    do i = 1, shape
        xyzArray(i)%x = 0
        xyzArray(i)%y = 0
        xyzArray(i)%z = 0
        xyzArray(i)%u = 0
        xyzArray(i)%v = 0
        xyzArray(i)%w = 0
        xyzArray(i)%uvw = (/0,0,0/)
    end do
    return
    end subroutine update

end module module_test

When they are compiled, they generate a similar error:

 TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
                                                    1
Error: ALLOCATABLE attribute conflicts with DUMMY attribute at (1)

When I eliminate the argument in update() subroutine, I receive a contradictory error:

TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
                                                       1
Error: Symbol at (1) is not a DUMMY variable

Have I eliminated the sources of error pointed out in the helpful suggestions? Could this be a compiler related error (using mpi90)?

~~~First Edit~~~ I have a subroutine whose input argument is an array of user defined type XYZ. I wish to deallocate xyzArray and allocate/modify it to a different size in the body of the subroutine. I attempted the method suggested by changing array dimensions in fortran, but when I do the following:

subroutine update(xyzArray, ...)
...
TYPE (XYZ), allocatable :: xyzArray(:)

I receive an error message:

Error: ALLOCATABLE attribute conflicts with DUMMY attribute at (1)

When I try:

subroutine update(xyzArray, ...)
...
deallocate( xyzArray(myshape) )
allocate( xyzArray(newshape) )

I receive error messages:

Error: Expression in DEALLOCATE statement at (1) must be ALLOCATABLE or a POINTER
Error: Expression in ALLOCATE statement at (1) must be ALLOCATABLE or a POINTER

What do I need to do to change the size of the array in the subroutine?


回答1:


To do this:

  • The dummy argument must be allocatable. Allocatable dummy arguments require a compiler that implements the relevant part of the Fortran 2003 standard (or a Fortran 95 compiler that implements the so called "allocatable" TR).

  • An explicit interface to the procedure is required (the procedure must be a module procedure, an internal procedure or have an interface block in the calling scope).

  • The dummy argument must not be intent(in). If you are not using the allocation status or other aspects of the value of the dummy argument at all in the subroutine then intent(out) may be appropriate (if allocated beforehand the dummy argument will be automatically deallocated when the procedure is called), otherwise intent(inout) or no intent.

(Your second block of example code has a syntax error with the deallocate statement - you should simply specify the xyzArray variable, leave off the (myshape) shape specification))

For example, in a module:

subroutine update(xyzArray)
  type(xyz), allocatable, intent(inout) :: xyzArray(:)
  ...
  if (allocated(xyzArray)) deallocate(xyzArray)
  allocate(xyzArray(newshape))
  ...



回答2:


If you are sure, you want to deallocate the array in your subroutine, you can declare the dummy argument being intent(out), so that it is deallocated automatically when the subroutine is entered:

module whatever
  implicit none

  type :: xyz
    :
  end type xyz

  contains

    subroutine update(xyzArray)
      type(xyz), allocatable, intent(out) :: xyzArray(:)
      :
      allocate(xyzArray(someshape))
      :
    end subroutine update

  end module whatever

As already noted by IanH, the process must have an explicit interface (e.g. being enclosed in a module) and in the caller program you must declare the actual argument allocatable:

program test
  use whatever
  implicit none

  type(xyz), allocatable :: array(:)
  :
  call update(array)
  :
end program test


来源:https://stackoverflow.com/questions/13810116/can-a-input-argument-of-a-fortran-subroutine-be-deallocated-and-allocated-in-the

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!