0

How would I pass as an input to a subroutine a field of a derived data type?

I have a linked list that I want to loop trough and I want to work on a specific field only, but I would like to have the field "name" as input so that I can call the same function on different fields of the list.

For instance:

program main

implicit none

! -----  variables declaration


type :: element
   real                       :: u1
   real                       :: u2
   type (element), pointer    :: next => null()
end type element

type (element), pointer       :: first, last, iele

! -----  code

allocate( first )
last => first
first %u1 = 0
first %u2 = 0
allocate( first %next )
last => first %next
last %u1 = 10
last %u2 = 20

call addten( u1, first )
call addten( u2, first ) 

iele => first
do while ( associated( iele ) )
   write(*,*) iele %u1
   iele => iele %next
end do


end program main

! =====

subroutine addten( u, first )

implicit none

! -----  variables declaration

type :: element
   real                       :: u1
   real                       :: u2
   type (element), pointer    :: next => null()
end type element

real, pointer                 :: u
type (element), pointer       :: iele

! -----  code

iele => first
do while ( associated( iele ) )
   iele %u = iele %u + 10 
   iele => iele %next
end do


end subroutine addten

1 Answers1

1

According to the Fortran standard if you define the type in two places, it is not the same type although it has the same name and definition. You must make the procedure internal using contains or even better place it in a module in which you define the type.

In your case you want to go through the linked list, sou you want to pass the whole variable first, but mabe as a pointer:

  type(element), pointer, intent(in) :: first

After that you must know which component you change in the soubrutine. It is not possible to pass this information directly, you need to pass some auxiliary variable that your subroutine understands as a switch:

  integer, intent(in) :: comp

  select case (comp)
     case (1)
         !add to component u1
     case (2)
         !add to component u2
   end select

So it may look like (not tested):

module list
  implicit none

  type :: element
     real                       :: u1
     real                       :: u2
     type (element), pointer    :: next => null()
  end type element

!here any other subroutines directly connected to the list object

end module list


module other_list_procedures
  use list

  implicit none

  subroutine addten( comp, first )
    type (element), pointer, intent(in) :: first
    integer, intent(in) :: comp
    type (element), pointer     :: iele

    iele => first
    do while ( associated( iele ) )
      select case (comp)
         case (1)
             iele%u1 = iele%u1 + 10 
         case (2)
             iele%u2 = iele%u2 + 10 
       end select      

      iele => iele%next
    end do


  end subroutine addten

end module
Community
  • 1
  • 1