Dear Fortran black-belts and others,
I am trying to understand the rules governing the passing of parameterised derived type variables as arguments into subroutines and functions. Here is an example type definition from my program:
TYPE CoeffPairSpeciesDescr (nSpecies1, nSpecies2, nValuesMax)
INTEGER, LEN :: nSpecies1, nSpecies2, nValuesMax
INTEGER :: Species(nSpecies1, nSpecies2)
INTEGER :: nValues
DOUBLE PRECISION :: Value(nValuesMax)
After creating the parameterised derived type variable (which I only need to do once, at the start of a program run), I can only find two ways of passing it as an argument to other routines:
(1) By declaring it in the routines like this:
TYPE (CoeffPairSpeciesDescr(:,:,:)), ALLOCATABLE :: AlphaObject
where "AlphaObject" is the parameterised derived type variable.
(2) Or, like this:
TYPE (CoeffPairSpeciesDescr(NA,NB,NC)) :: AlphaObject
where NA, NB, and NC are integers whose values are known (and are the values used when the variable was allocated).
If I change the statement in (1) above to remove "ALLOCATABLE," I get the compiler error message:
test_3.for(133): error #8730: A colon may only be used as a type parameter value in the declaration of an object that has the POINTER or ALLOCATABLE attribute.
I don't understand why this should be. An ordinary array (ie, not a derived type) does not behave in this way. As Steve Lionel explained in a post several years ago:
"That an array is allocatable does not, in itself, change how you pass it to a routine. If you had an F77-style program where you changed one array to be allocatable, and allocated it, you would not have to change any other code in the program."
Why don't parameterised derived types behave in the same way? It seems odd that the parameterised derived type variable apparently has to either be declared as allocatable in every subprogram it is passed to, or declared with explicit values given to the "LEN" attributes. What am I missing?
All explanations gratefully received.
See a couple of threads on this forum for working examples:
Quote #30 in this thread: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/746406
Quote #10 in this one: https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/585069
The analogy you can draw for LEN based parameterization in a derived type is the CHARACTER intrinsic type and note how one uses LEN=* for assumed length option in a dummy argument.
In your case though, you may want to consider KIND type of parameterization for nSpecies option if it tends to be fixed for a given simulation/calculation.
Thank you. I had associated the use of "*" only with "LEN=*" for character strings, and to specify variable upper bounds for assumed size arrays (Fortran 77). I now see the analogy with the use of "LEN" in defining parameterised derived types.
I have one remaining question: where can I find a good explanation of this, and of the "KIND type of parameterization" suggested by FortranFan? An explanation for ordinary mortals, that is, and with examples. The latest edition of the textbook by Chapman doesn't seem to cover this area very well, and I don't think the Intel documentation does either.
Simon Clegg wrote:
.. where can I find a good explanation of this, and of the "KIND type of parameterization" suggested by FortranFan? An explanation for ordinary mortals, that is, and with examples. ..
The write-up you might find most useful is here: https://www.pgroup.com/lit/insider/pginsider_v5n2.htm "Object-Oriented Programming in Fortran 2003 Part 3: Parameterized Derived Types" (you may need to get an account).
With KIND type of parameterization, an analogy you can draw is floating-point precision: if a code supports an arbitrary set of options - so-called single, double, extended, etc. and given program runs/simulations are generally based on one of these, then the use of defined kinds in Fortran in terms of SELECTED_REAL_KIND( p=X ) with X=6,12,.. with the code's floating-point data makes good sense; otherwise one might just use default real or "double precision" keyword. Note with either of these approaches, the ALLOCATABLE attribute can bring in the LEN type dynamically to the size of floating point data Similarly if your parameterization for a derived type corresponds to something that is part of an arbitrary set e.g., number of dimensions which may be one of either 1D, 2D, or 3D, then with this aspect of your PDT, the KIND type may make more sense.
Note the 2 links in Quote #2 above include working examples you can download and try out; the 2 threads give the details.
Thank you. I was aware of parts 1 and 2 of the PGI series, but not 3 and 4. I registered with them, and downloaded the two most recent articles. Number three is exactly what I needed.
Thanks again for your help.