Search code examples
modulefortranderived-types

Can a Fortran derived type have components from different modules?


I am developing a derived type. It keeps growing and is making the module in which it resides unwieldy. Is there a way to break up the module into multiple modules and have the derived type obtain its components from the various modules?


Solution

  • As @francescalus points out, you can use derived types from other modules to create new derived types. I think his example was a little short, so I wrote a small example which I hope will give you an idea of how something like this could work. Perhaps the example is longer than strictly necessary, but I was enjoying myself.

    My derived type describes travel plans, consisting of luggage and an itinerary. It comes with a subroutine that will print a given travel plan.

    module travel
    use Luggage
    use Routing
       type tTravel
           type(tItinerary) :: trip
           type(tSuitcase)  :: suitcase
       end type tTravel
    contains
       subroutine printTravel(travel)
       implicit none
           type(tTravel), intent(in) :: travel
           print '(a)','    Luggage:'
           call printSuitcase(travel%suitcase)
           print '(a)','    Itinerary:'
           call printItinerary(travel%trip)
       end subroutine printTravel
    end module travel
    

    The two components of the travel plans, luggage and itinerary, each have their own module. First, the Luggage-module:

    module Luggage
       type tSuitcase
           integer :: socks = 2
           integer :: shirts = 1
           integer :: underwear = 1
           integer :: raincoats = 0
       end type tSuitcase
    contains
       subroutine printSuitcase(suitcase)
       implicit none
           type(tSuitcase), intent(in) :: suitcase
           print '(i10,a)', suitcase%socks,'  socks'
           print '(i10,a)', suitcase%shirts,'  shirts'
           print '(i10,a)', suitcase%underwear,'  underwear'
           print '(i10,a)', suitcase%raincoats,'  raincoats'
       end subroutine printSuitcase
    end module Luggage
    

    and next, the Itinerary module:

    module Routing
       integer,          parameter :: &
         HOME=1,     MONACO=2,   IBIZA=3,     BIARRITZ=4, &
         nDESTINATIONS=4
       character(len=8), parameter :: destination_names(nDESTINATIONS) = (/ &
         'Home    ', 'Monaco  ', 'Ibiza   ', 'Biarritz' /)
       integer, parameter :: maxTripLen = 100
    
       type tItinerary
           integer  :: length = 0
           integer  :: destinations(maxTripLen)
       end type tItinerary
    contains
       subroutine addDestination(trip,destination)
       implicit none
           type(tItinerary), intent(inout) :: trip
           integer,          intent(in)    :: destination
           if (destination<1 .or. destination>nDESTINATIONS) &
              stop('illegal destination')
           if (trip%length >= maxTripLen) stop('Trip too long')
           trip%length = trip%length + 1
           trip%destinations(trip%length) = destination
       end subroutine AddDestination
    
       subroutine printItinerary(trip)
       implicit none
           type(tItinerary), intent(in) :: trip
           integer :: i
           if (trip%length==0) then
              print '(a)','        Empty itinerary'
           else
              print '(100(a))','        '//trim(destination_names(trip%destinations(1))), &
                 ('-',trim(destination_names(trip%destinations(i))), i=2,trip%length)
           end if
       end subroutine printItinerary
    end module Routing
    

    Now all I need is a main program:

    program nestedModule
    use travel
    implicit none
       type(tTravel) :: plans
    
       print '(a)','Before planning anything:'
       call printTravel(plans)
    
       print *
       print '(a)','Planning a trip ... hold on'
       print *
       call addDestination(plans%trip,HOME)
       call addDestination(plans%trip,IBIZA)
       call addDestination(plans%trip,BIARRITZ)
       call addDestination(plans%trip,HOME)
    
       print '(a)','Now my plans are:'
       Call printTravel(plans)
    end program nestedModule