Big Al
Big Al

Reputation: 23

Subroutine ignores type declaration above in module

I created a type, model, in a module, and then declared a variable, md, having that type. In the subroutine contained in the module, the declaration of md above is ignored, I have to declare it explicitly again.

In the main program I don't need to declare the type of md, the use statement appears to work. Can anyone explain why the subroutine ignores the type declaration of md?

Here is the code. I am using gfortran compiler on Linux.

program main
  use struc_model
  call mod_gen(md)
  do i=1, md%ndof
    write(*,*) 'row =', i
    write(*,*) 'm=', md%m(i,:)
  end do  
end

module struc_model
  type model
    integer :: ndof
    real*8, allocatable, dimension(:,:) :: m
  end type
  type (model) :: md
  contains
  subroutine mod_gen(md)
  ! for some reason have to declare type of md again
  ! declaration above is ignored
    type (model) :: md  
    md%ndof=4
    allocate(md%m(md%ndof,md%ndof))
    md%m=0.d0
    do i=1, md%ndof
      md%m(i,i)=1.d0
    end do
  end subroutine
end module

Upvotes: 2

Views: 208

Answers (1)

francescalus
francescalus

Reputation: 32451

There are three terms of interest here: use association, host association and argument association. You can read about those in full detail with other resources, but I'll use them here in explanation.

Look first at the module. For the sake of clarity I'm going to take your variables to be of type integer. Here's a simple program

module mod
  implicit none
  integer i
end module mod

program prog
  use mod
  implicit none
  print *, i       ! i is use associated
end program prog

Here, we aren't saying that the type of i is known from the declaration through the module, we're saying that i is the variable from the module (and its type follows from that).

Now look at a simplified module:

module mod
  implicit none
  integer i

contains

  subroutine sub(i)
    integer i
  end subroutine

end module mod

So, why do I need that integer i declaration in the subroutine sub? That's because i in that subroutine, appearing as it does in the argument list, is a dummy argument. A dummy argument needs its type specifying in its scope, the subroutine. Within the subroutine a reference to i is to the dummy argument and not to the module variable: the module variable is made inaccessible.

If my program then looks like

  use mod
  call sub(i)
end program

what I'm doing is passing the module variable i---which has been use associated---to the subroutine sub as its dummy argument (through argument association).

Now, if I wanted to modify the module variable in the module's subroutine I could instead use host association

module mod
  implicit none
  integer i

contains

  subroutine sub()  ! No dummy argument i, references in here are to the module's i
  end subroutine

end module mod

program prog
  use mod
  implicit none

  call sub   ! No argument for the module's own variable
end program prog

Within that module subroutine i refers to the module variable.

But what I suspect you mean to do is have a variable in the program's scope which is passed to the subroutine. Going back to your terminology:

module struc_model
  type model
    integer :: ndof
    real*8, allocatable, dimension(:,:) :: m
  end type
  contains
  subroutine mod_gen(md)
    type (model) :: md  
    md%ndof=4
    allocate(md%m(md%ndof,md%ndof))
    md%m=0.d0
    do i=1, md%ndof
      md%m(i,i)=1.d0
    end do
  end subroutine
end module

program main
  use struc_model
  type (model) :: md    ! A variable within the program's scope
  call mod_gen(md)      ! Argument associated with the subroutine's dummy
  do i=1, md%ndof
    write(*,*) 'row =', i
    write(*,*) 'm=', md%m(i,:)
  end do  
end

In summary

module struc_model
  type model
    integer :: ndof
    real*8, allocatable, dimension(:,:) :: m
  end type
  type (model) :: md
end module

declares a module variable md and doesn't state that all variables called md are of type(model).

Upvotes: 5

Related Questions