Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29249 Discussions

Problem with user defined types and subroutines

Bill_Doss
Beginner
751 Views
When I compile the following, I get a error stating that the derived type 'my_struct' is being used before it is defined (on line 10):


program abc
implicit none
type :: MY_STRUCT
sequence
integer*4 :: m, n
end type MY_STRUCT
interface
subroutine def(m, n, a)
integer*4, intent(in) :: m, n
type (MY_STRUCT), intent(out) :: a
end subroutine def
end interface
integer*4 :: m, n
type(MY_STRUCT) :: a
m = 0
n = 20
call def(m, n, a)
print*, 'a.mrows = ', a%m
print*, 'a.ncols = ', a%n
end program abc
subroutine def(m, n, a)
implicit none
integer*4, intent(in) :: m, n
type (MY_STRUCT), intent(out) :: a
a%m = m
a%n = n
end subroutine def
However, the below does compile:
program abc
implicit none
type :: MY_STRUCT
sequence
integer*4 :: m, n
end type MY_STRUCT
integer*4 :: m, n
type(MY_STRUCT) :: a
m = 0
n = 20
a%m = m
a%n = n
print*, 'a.mrows = ', a%m
print*, 'a.ncols = ', a%n
end program abc
What gives? Thanks times infinity!!
Bill
0 Kudos
6 Replies
Steven_L_Intel1
Employee
751 Views
See Domestic or Imported?

But I would also slap your wrist with a ruler for writing an INTERFACE block for a Fortran routine. This is almost always unnecessary and error-prone. Put "def" in a module or make it a CONTAINed routine.
0 Kudos
Bill_Doss
Beginner
751 Views
Steve,
Thanks for the response.
This morning, after doing some more research with Mr. Google, I came across the "Domestic or Imported" article. Using that, I was able to solve my problem. (I came back here to post an update when I saw your response--I don't know why I didn't get an e-mail notification?)
Now I must ask that you don't slap me too hard as only recently have I begun to relearn Fortran. And by recently I mean within the past couple months. Prior to that, I haven't seen Fortran since the middle 1980's. Heck, I didn't even know people were still using it!!
I will not be a baby, however, so I extend my arm and await my punishment :)
Is there a good reference, book, article, whatever that could help with some of these nuances?
Thanks again
Bill
0 Kudos
Steven_L_Intel1
Employee
751 Views
There are several good books on modern Fortran, but I don't know if they go into recommendations like this. "Modern Fortran Explained" is probably the best choice. You can go read all my blog posts (including the older Visual Fortran Newsletters) to get my take on some of these issues.

I will spare your wrist this time - just don't do it again!

Welcome back to Fortran! It's not dead yet!
0 Kudos
OP1
New Contributor III
751 Views
Steve,

Could you please explain why having an INTERFACE block is bad practice? When you have hundreds+ of subroutines, some of them usually quite large in themselves, it's just not practical to put them (even just a few of them) in one module. There is a code browsing issue, but a module compilation issue as well (every time you make a modification to a subroutine the module is recompiled).

My understanding of your statement is then that each subroutine (which requires an interface) should go in its own module, as in:

MODULE MYSUB_INT
CONTAINS
SUBROUTINE MYSUB
...
END SUBROUTINE MYSUB
END MODULE SUB_INT

A calling unit would just then USE MYSUB_INT.

Is this a correct interpretation?

Thanks,

Olivier
0 Kudos
IanH
Honored Contributor III
751 Views
I group related procedures together into a tree like heirarchy of modules - where some modules may contain just one procedure, others may contain many, others may contain none (they are just types or variables or parameters), some modules just group other modules together in a convenient manner.

I don't see why it's a code browsing issue - grouping related things together typically improves browsability, and there's still reasonable flexibility in how you divide modules and procedures up amongst source files. If you have a requirement for one procedure per file you can use INCLUDE lines to achive that, if you have a requirement for one big source file then you can have one big source file with all the modules concatenated together (though you need to consider the order of dependencies - i.e. your program ends up being at the bottom of the file). Neither extreme appeal to me - I just have one module per file.

Yes - despite reasonable granularity in the mapping of modules to source files you will get compilation cascades that affect total build time. So I look forward to submodules, but that said ... is it really such a drama? Small price to pay for the safety guarantee in my mind. Release builds often have interprocedural optimisation turned on, which makes the cascade time mostly moot, and if you are having to compile your entire source base to debug some low level procedure then perhaps some thinking about intermediate test programs is in order.
0 Kudos
Steven_L_Intel1
Employee
751 Views
You can group all the related subroutines together in a module. I am certainly not recommending one module per routine.

The reason I say it is bad practice is that you are declaring the routine twice. And as we all know, if you write something twice it is probably wrong in one of them. It is a maintenance problem to remember to update the interface block when you change the routine. If you have the routines in a module, they create their own interface. INTERFACE blocks should be reserved for special cases, primarily non-Fortran code.
0 Kudos
Reply