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?
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