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

Problem with COMMON

davidgraham
Beginner
2,066 Views
My code is old and is using lots of variables in different places to holdfile names.
At present all these variables are dimensioned to 80.
I want to increase this to say 255.
Therefore to make it supportable in the future I want to define one varialbe, say FileNameLength as 255.
integer,parameter:: FileNameLength=250
character*(FileNameLength) cFileName
This works OK on its own, but I get problems with duplicate definitions with 'COMMON' satements which are used to dimension many of the variables.
What is the solution to this?
Thanks,
David
0 Kudos
13 Replies
Steven_L_Intel1
Employee
2,066 Views
I don't quite understand the nature of the problem. There's nothing wrong with what you have shown so far. Can you show a self-contained example that demonstrates the problem?
0 Kudos
jim_dempsey
Beginner
2,066 Views

Perhaps you are including several header files some of which may declare the same common block but with different/different allocations of variables?

Also your given declaration for cFileName is not in a COMMON.

Jim Dempsey

0 Kudos
davidgraham
Beginner
2,066 Views

The problem is that I have FileNameLength defined in a common block AND in the program.

The program has

include 'fnames.gcb'

integer,parameter:: FileNameLength=250
character*(FileNameLength) cFileName

etc...

The common block is in file 'Fnames.gcb'

integer,parameter:: FileNameLength=250
character*(FileNameLength) cgbf,CCOD
common/fnames/ cgbf,CCOD

The error message is:

This name has already been assigned a data type. [FILENAMELENGTH]

as FileNameLength is defined both in the program & in the common block.
I have triedFileNameLength in a Module and using USE.
There must be a simple way of defining a variable that I can use in the program and in a common block.
Hope this helps,
David
0 Kudos
greldak
Beginner
2,066 Views

FileNameLength isn't a variable - you have declared it as a PARAMETER value and are attempting to assign a value to it twice.

Also make sure you aren't mixing up 250 and 255 for your name lengths

0 Kudos
Steven_L_Intel1
Employee
2,066 Views
More simply, you are declaring the name FileNameLength twice, which is not allowed. Remove one of the definitions.
0 Kudos
davidgraham
Beginner
2,066 Views

I want to use the variable 'FileNameLength' in several Common blocks.

I have tried removing them, to leave only one, but get the error messages:

'A COMMON block data object must not be an automatic object.'

and

'This name has not been given an explicit type. [FILENAMELENGTH]'

I'm getting confused,

David

0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,066 Views
The best way to do it is to have it in the include file (just as you have it now) and ONLY include the file wherever the symbols are needed. You appear to have a mixture of include and re-spelling of definitions.

Jugoslav
0 Kudos
davidgraham
Beginner
2,066 Views

I'm not sure if I follow you.

I have made a new common block called fnl.gcb:

integer:: FileNameLength=250
common/FNL/FileNameLength

It wouldn't compile with 'Parameter'.

Then in each program that needs this variable or has an include file that needs this variable I have added include 'fnl.gcb'.

When I compile, I get an error on the first program which containsa common block.

Error: A COMMON block data object must not be an automatic object.

I don't know what that error messagemeans.

I don't think I have any spelling problems.

David
0 Kudos
Jugoslav_Dujic
Valued Contributor II
2,066 Views
Your first version of .gcb file was perfectly fine. This one won't work -- you need a PARAMETER to declare length of a character within the common block (that's what compiler tells you that "COMMON block data object must not be an automatic object"), and you can't put a parameter within a common block, because it's not a variable.

Your original problem was that you defined FileNameLength twice, once in .gcb file and other time again in code (.for file) (that's what I meant by "spelled"). The solution was just to remove the re-declarations.

Jugoslav
0 Kudos
jim_dempsey
Beginner
2,066 Views

David,

If you can, why not dispense with COMMON. You can do this by creating a module containing the arrays, variables and constant parameters. I've done this on a Solution with 11 project files and ~700 source modules. It is a bit of work but you can do it incrimentaly. You could start with

-----------------------------

! mod_common.f90
module mod_common
integer,parameter:: FileNameLength=250
character*(FileNameLength) cFileName
end module mod_common
-----------------------
Then insert "use mod_common" at the top of the routines that use FileNameLength or cFileName.
Then as you find more items that you would like better control over you can place them in there too.
You will find that this is a relatively easy way to convert a fixed dimension array in COMMON to an allocatable array. No source code changes other than for the COMMON/mod_common, the use mod_common, and the allocation in the init code. All array references remain untouched.
Jim Dempsey
0 Kudos
davidgraham
Beginner
2,066 Views
I have created the module fnl:
Module fnl
! file name length
integer,parameter:: FileNameLength=250
end module
Then added 'use fnl' to any procedures that require it.
The common blocks defining the variable just then need:
character*(FileNameLength) cgbf
I think that's it sorted, thanks.
David
0 Kudos
jim_dempsey
Beginner
2,066 Views
Keep in mind that you can start placing more features into the module section. Converting an array from fixed size in common to allocatable in the module is relatively easy to do (once you insert the "use foo"). Also it makes for easier code maintenance. Especialy when you compile one set of subroutines with one set of includes with COMMONs and a different set of subroutimes with a different set of includes with COMMONs only to find during debugging that the common COMMONs aren't quite the same. Using modules forces a singular instance of a formerly named variable in COMMON.
One of the steps along the learning curve to using modules is often the include files for COMMON use EQUIVELENCE.. To overcome this use UNION
COMMON Array, Array1
DIMENSION Array(10,10), Array1(100)
EQUIVELENCE (Array(1,1) Array1(1))
becomes
union
map
real :: Array(10,10)
end map
map
real :: Array1(100)
end map
end union
Then as you progress through your changes that some routines may have a common array(10,10) and others use the same name but different extents or rank. To easily overcome this use a derrived type and use the Fortran Preprocessor with #define.
module foo
...
type badabing
union
map
real :: Array(10,10)
end map
map
real :: Array1(100)
end map
end union
end type badabing
type badabang
union
map
real :: Array(10,10)
end map
map
real :: Array1(100)
end map
end union
end type badabang
type(badabing) :: bing
type(badabang) :: bang
end module foo
Then in the include files that are used in the souce files that require the badabing have
#define Array badabing.Array
#define Array1 badaging.Array1
That is it. No souce code changes to differentiate the references. You do have to select the appropriate #define but that is easier and less error prone that search and replace.
Jim Dempsey
0 Kudos
jim_dempsey
Beginner
2,066 Views

oops us

#define Array bing.Array

#define Array1 bing.Array1

0 Kudos
Reply