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

Problems with MODULE

Hans-henrik_F_
Débutant
2 499 Visites

Hi,

I am relative new to Fortran, so forgive me for 3 simple questions:

1) I have made a MODULE like this in Fortran 90 using intel fortran visual compiler and get an error in the code line "CompMF( N2     )..." below:

MODULE SSBGAS

    IMPLICIT NONE

    Integer         N2,     O2,     H2,      Ar,     CO

    Parameter( N2     =   1)
    Parameter( O2     =   2)
    Parameter( H2     =   3)
    Parameter( Ar     =   4)
    Parameter( CO     =   5)

    INTEGER, PARAMETER :: MaxCom = 38
    Character*18   CompMF( MaxCom)

    CONTAINS
   
    CompMF( N2     )   = 'N2' ! Here I have problems...?? error #6274: This statement must not appear in the specification part of a module


! If I write DATA CompMF( N2     )   / 'N2' / it works fine but isn't the DATA stamement obsolete ?

    END MODULE SSBGAS

2) Again, in the same module:

Data (CCpGas( i, N2 ), i=1,9) / 2.89054E+01 ,&

5.36709E-03 , -4.03662E-05 ,&

1.18534E-07 , -1.48467E-10 ,&

9.89388E-14 , -3.69281E-17 ,&

7.31369E-21 , -6.00168E-25 /

!This works fine but isn't the DATA statement obsolete? what should I write instead of using the DATA statement??

!If I write

CCpGas( 1, N2 ) = 2.89054E+01
CCpGas( 2, N2 ) = 5.36709E-03
CCpGas( 3, N2 ) = -4.03662E-05
CCpGas( 4, N2 ) = 1.18534E-07
CCpGas( 5, N2 ) = -1.48467E-10
CCpGas( 6, N2 ) = 9.89388E-14
CCpGas( 7, N2 ) = -3.69281E-17
CCpGas( 8, N2 ) = 7.31369E-21
CCpGas( 9, N2 ) = -6.00168E-25

!I get an error like "error #6274: This statement must not appear in the specification part of a module"??

 

3) In the end of the MODULE I write SAVE but I get the error "A specification statement cannot appear in the executable section" ??

 
0 Compliments
8 Réponses
mecej4
Contributeur émérite III
2 499 Visites

You can look up the Fortran documentation to get the syntax correct. You cannot put executable statements after CONTAINS without first creating a subprogram (subroutine, function, etc.). However, if all that you want is to initialize variables, you do not need a CONTAINS block at all. For example,

MODULE SSBGAS

    IMPLICIT NONE

    Integer, Parameter ::  N2 = 1, &
                           O2 = 2, &
                           H2 = 3, &
                           Ar = 4, &
                           CO = 5

    INTEGER, PARAMETER :: MaxCom = 5

    Character(18) :: CompMF( MaxCom) = ['N2', 'O2', 'H2', 'Ar', 'CO']

END MODULE SSBGAS

You can supply declarations and initializations for other variables, e.g., Cp_gas, in a similar way.

 

0 Compliments
pbkenned1
Employé
2 499 Visites

An internal subroutine needs to begin with either a function-stmt or subroutine-stmt.  ifort catches this, gfortran assumes it's an illegal function statement.  Just to illustrate, the following compiles, but isn't a good solution:

    CONTAINS
    subroutine init_CompMF()
       CompMF( N2     )   = 'N2' ! Here I have problems..
    end subroutine init_CompMF
 

Patrick

0 Compliments
FortranFan
Contributeur émérite III
2 499 Visites

Welcome to this forum.

Take a look at this forum topic.  Would you be interested in reviewing some of the books recommended therein, especially in Quotes #5 and #6?  It may help you greatly in the long run if you plan to do more with Fortran.

In your example, you need a procedure (SUBROUTINE/FUNCTION) following the CONTAINS part of the module and perform the assignment for CompMF in such a procedure.  But you may want to take some time to understand the Fortran details and your program needs and requirements.  You have "named constants" (PARAMETER attribute) for N2, etc.  So shouldn't their molecular formula be "named constants" too?  Meaning you don't expect CompMF(N2) to be anything other than 'N2', do you?  If so, you can declare CompMF as constant and assign it values using a constructor in its declaration itself as shown below:

    
      character(len=*), parameter :: CompMF(MaxCom) = [ character(len=18) :: 'N2', 'O2', 'H2',      &
                                                        'Ar', 'CO', .. ]  !.. Fill in the rest

And yes, a DATA statement in the execution scope is obsolescent in current Fortran standard, but most compilers will continue supporting it for all the legacy code out there.  But it may be good idea to avoid it if you can, especially in new code.

0 Compliments
Hans-henrik_F_
Débutant
2 499 Visites
Hi, Thanks for a VERY fast reply... 2) In the case of compMF, I understand. But the initialization of CCpGas is not clear to me. CCpGas is a 2-dimenional static array with a sie of 9x38 and it becomes very difficult to fill this very large array up with data in one code line, i.e., using the [ ]?? Isn't the DATA statement the easiest?? Could some one give me a simple example of how to fill the CCpGas array with data in the case of a 2-dimensional vaiable? hmmm... I'm a little suprised of how difficult it is to input data in a MODULE wihtout the DATA statement...
0 Compliments
Hans-henrik_F_
Débutant
2 499 Visites

FortranFan: I forgot to comment on your writing:

A) I'm using Fortran 90 for Engineers & Scientists by Nyhoff an Leestma which I find very usefull

B) Thank you for the explanion of CONTAINS

C) Yes, CompMF shoul be a named constant. Thank you for the comment!

D) As far as I understand the array declaration and initialization, I would have to both declare and initialize the non-allocatable array CCpGas in one code line? I think this is a bit excessive because it is a 9x38 array.... In this case, a DATA statemen just seems to be easiest...

 

0 Compliments
mecej4
Contributeur émérite III
2 499 Visites

You can continue an initialization expression over many lines, ending all but the last line with '&'. Intel allows you up to 511 lines per statement in free form source, and each line can be very long. You can initialize a two-dimensional array with the intrinsic RESHAPE applied to a one-dimensional initializer list.

An alternative would be to keep a long list of constants in a file, and read the contents of the file into the 2-D array as part of program initialization.

0 Compliments
FortranFan
Contributeur émérite III
2 499 Visites

Hans-henrik F. wrote:

Hi,

Thanks for a VERY fast reply...

2) In the case of compMF, I understand. But the initialization of CCpGas is not clear to me. CCpGas is a 2-dimenional static array with a sie of 9x38 and it becomes very difficult to fill this very large array up with data in one code line, i.e., using the [ ]?? Isn't the DATA statement the easiest??

Could some one give me a simple example of how to fill the CCpGas array with data in the case of a 2-dimensional vaiable?

hmmm... I'm a little suprised of how difficult it is to input data in a MODULE wihtout the DATA statement...

Presumably CCpGas corresponds to coefficients in a simple polynomial model for the ideal gas heat capacity representation for each of the gases and those are probably constants too.  You may wish to rethink your program structure and perhaps look into using a derived type (data structure) for each of the fluids:

module SSBGAS

   implicit none

   private

   type gas
      integer :: id
      character(len=18) :: mf
      real :: cp_coeff(9)
   end type gas

   type(gas), parameter, public :: n2 = gas( 1, "n2", [ 2.89054E+01,  &
                                                        5.36709E-03,  &
                                                       -4.03662E-05,  &
                                                        1.18534E-07,  &
                                                       -1.48467E-10,  &
                                                        9.89388E-14,  &
                                                       -3.69281E-17,  &
                                                        7.31369E-21,  &
                                                       -6.00168E-25 ] )

end module SSBGAS

This way, in any of the code that you need to apply the fluid information, you only need to add statements such as "use SSBGAS, only : n2", etc. and the information becomes available such as n2%id which corresponds to your current integer variable N2 and n2%mf for the molecular formula 'N2', and n2%cp_coeff(i) (with i from 1 through 9) for the constants.

Of course, many alternate code design patterns are available.  The book by Leestma and Nyhoff is also very valuable; look therein for many of the application examples and you'll find many ideas for use of derived types.

0 Compliments
IanH
Contributeur émérite III
2 499 Visites

As already stated upthread, but just in case the significance was missed - it is the positioning of a data statement in the execution part of a scope that is obsolescent, not the use of a data statement itself.  If you want to continue using a data statement then that's fine - just put it in the specification part of the relevant scope.  For a module that means that it goes prior to the CONTAINS statement. 

My personal preference in this sort of situation is to build up the "large" constant from smaller constants.  Something along the lines of:

REAL, PARAMETER, PRIVATE :: CCpGas_N2(9)  &
    = [ 2.89054E+01, 5.36709E-03 , -4.03662E-05,  &
        1.18534E-07, -1.48467E-10,  9.89388E-14,  &
        -3.69281E-17,  7.31369E-21 , -6.00168E-25 ]

REAL, PARAMETER, PRIVATE :: CCpGas_O2(9)  &
    = [ ... ]

REAL, PARAMETER, PUBLIC :: CCpGas(9,MaxCom)  &
    = RESHAPE( [  &
        CCpGas_N2,  &
        CCpGas_O2,  &
        ... ],  &
      [9,MaxCom] )    

Fortran 2008 introduces implied shape arrays, which can help here in terms of reducing repetition of shape information.

This approach still applies when the large constant is of derived type that aggregates properties for a particular component into a single object - you can define a constant for each component, and then assemble the constants into an array indexed by component number.

 

 

0 Compliments
Répondre