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

Problem with using module to declare variables for subroutines ( The attributes of this name conflict with those made accessible by a USE statement)

GoldenRetriever
초급자
1,833 조회수
Hi there, I have use a module to delcare all the variables used in the main program and subroutines but It seems not work when calling the subroutine. I include a simple problem below, pls have a look..

Could anyone know why and any solution for that pls?
Thank very much for any suggestion..

! **************************************************************************************************************************************

MODULE TD_VARS
IMPLICIT NONE
REAL, ALLOCATABLE, DIMENSION(:,:) :: A,B,C
END MODULE TD_VARS
! **************************************************************************************************************************************

Program TD_Test1
INCLUDE 'link_fnl_static.h'
!DEC$ OBJCOMMENT LIB:'libiomp5md.lib'
USE IMSL_LIBRARIES
USE TD_VARS
IMPLICIT NONE
INTEGER :: i,j
ALLOCATE(A(3,3))
A = 1.1
CALL Sub1 (A)
END PROGRAM TD_Test1

! **************************************************************************************************************************************
SUBROUTINE Sub1(A)
INCLUDE 'link_fnl_static.h'
!DEC$ OBJCOMMENT LIB:'libiomp5md.lib'
USE IMSL_LIBRARIES
USE TD_VARS
IMPLICIT NONE
REAL, INTENT(IN), DIMENSION(:,:) :: A !Input matrix
ALLOCATE(B(3,3))
B = A
! CALL Sub2(A)
END SUBROUTINE Sub1

! **ERRORS**********************************************************************************************************************************

Error 1 error #6401: The attributes of this name conflict with those made accessible by a USE statement.

Error 2 error #6445: A dummy argument is required in this context.


0 포인트
5 응답
Les_Neilson
소중한 기여자 II
1,833 조회수

As error 1 says you have an array A in the module TD_VARS *and* a dummy argument also called A
I almost suggested you should remove the USE TD_VARS from SUB1 but I see you have an assignment to the array B (from the module)
You could rename the dummy argument A to something else (eg Z)BUT then you wouldhave an aliasing situation where

call sub1(A)
and
subroutine Sub1(Z)

would still mean you are trying to access the array A via the module and the subroutine argument

I suggest that if your code isalways going to call sub1 with the array A then don't !
Remove it from the argument list and always and only access it through the module i.e. USE TD_VARS

If your subroutines Sub1 and Sub2 do work on the module arrays why not make themcontained within the module?

Module td_vars
real, allocatable, dimension(:,:) :: a,b,c
contains
subroutine sub1
... work with arrays a,bor c
end subroutine sub1
subroutine sub2
... do other work on a,b or c
end subroutine sub2
end module

My personal style also adds allocate, reallocate (i.e. re-size) if necessary, and deallocate routines. Thus keeping the data and the actions neatly together whenever possible.

Les
0 포인트
GoldenRetriever
초급자
1,833 조회수

Thanks Les for your reply. Your options do make sense to me, just a little bit hesitance to apply them as for the reasons:
1. Rename the dummy argument A to something else (eg Z): in my program, there are too many arrays so if I rename them then the number of arrays significantly increased. Also the array name chose based on its identity as well for example (ELEMENT_INFO...) if I have to rename them to something like ELEMENT_INFO_1, or ELEMENT_INFO_SUB.. then it might make a bit confused in debugging progress later on when trying to identify what is the array for..

2. Move the subroutines inside the module: I group the subroutines for different purposes and locate them in different files just for the easy of management. So I might not choose to contain them all inside a single module then.

Currently I tried one option and It seems work. For any array used in subroutine dummy argument, instead of declare the array in the module; I declare them in the main program. It is likely I have to go with this option and move some arrays in module to the main program. (But still prefer to have all the variables declared in one single module insteadJ)

Thanks n cheers

TD

0 포인트
Les_Neilson
소중한 기여자 II
1,833 조회수
You can still have all of your arrays in a module andUSE that module in the main program.

If you always pass (as arguments to the subroutine)ALL of the arraysthat the subroutineworks withthen you do not need the USE TD_VARS inthat subroutine.

The confusion only occurs when you try, in a subroutine, to access the same data from both the passed in arguments AND the module.

Les
0 포인트
abhimodak
새로운 기여자 I
1,833 조회수
Not exactly related to the problem here but using "private" attribute for the data that only a module should see also helps to package things better. In many cases, having a private statement and then specifying the public entities can work better.

Abhi
0 포인트
IanH
명예로운 기여자 III
1,833 조회수
...or add an ONLY clause to the USE statements that specifies only the bits from the module that you want, i.e.

USE TD_VARS, ONLY: B

This offers a source-self-documentation benefit, in that in large, complicated procedures you can work out where certain symbols come from. But don't forget ASSIGNMENT(=) if your module defines that for a type that's in use (from rueful personal experience... it'd be nice to have a compiler warning about that).
0 포인트
응답