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

Passing input into a module and make it global for subroutines in this model

Natalia_K_
Beginner
735 Views

Hello,

I have a main program and two modules, where one module defines input used throughout the subroutines of the main program (call it commons) and the other one evaluates a function (call it mixture_mod). From the main program I call a subroutine in mixture_mod and pass some input. I would like that input to be "global" for the mixture_mod, because the subroutine uses another subroutine with the same input. The variables in two modules have the same names, and I believe that IMPLICIT NONE and PRIVATE should isolate the input variables in mixture_mod from the rest of the program. It seems not to be the case, as I receive the errors:

error #6279: A specification expression object must be a dummy argument, a COMMON block object, or an object accessible through host or use association   [NVR]    

error #6841: An automatic object must not appear in the specification part of a module.      

I am wondering  if there is a way to isolate variable names in  mixture_mod so that they do not clash with the same names used in the main program? A solution could be to rename the variables, but I am not sure this is sufficient as I would like mixture_mod to be able to stand along from the rest of the program. Or maybe this is not what causes the errors, but what then? 

Thank you in advance. The code is provided.

MODULE MIXTURE_MOD
    IMPLICIT NONE
    PRIVATE                 
    PUBLIC      :: getmixture
    INTEGER(4)  :: nvr,nfk,nx
    REAL(8)	:: x(nvr,nx),qw(nx),logphi(nx)
 CONTAINS

SUBROUTINE getmixture(nvr0,nx0,qx,qw0,logphi0,nfk0,th)
    INTEGER(4),INTENT(IN)            :: nvr0,nx0         
    INTEGER(4),INTENT(OUT)           :: nfk0         
    REAL(8),INTENT(IN)	             :: qx(nvr0,nx0),qw0(nx0),logphi0(nx0) 
    REAL(8),ALLOCATABLE,INTENT(OUT)  :: th(:) 
    REAL(8)	                     :: th0(6),fstar
    INTEGER(4)	                     :: k

nvr=nvr0; nx=nx0; x=qx; qw=qw0; logphi=logphi0;
nfk=1; k=6; th0=0d0;
CALL fcn(k,th0,fstar); 
nfk0=nfk; 
ALLOCATE(th(6)); th=th0;
END SUBROUTINE getmixture

SUBROUTINE fcn(npk,th_f,fd)
 IMPLICIT NONE
      INTEGER(4), INTENT(IN)   :: npk
      REAL(8), INTENT(IN)      :: th_f(npk)
      REAL(8), INTENT(OUT)     :: fd 
!Uses specification part of the module as intermediate input 
fd=1d0; 
END SUBROUTINE fcn

END MODULE MIXTURE_MOD

MODULE commons
   IMPLICIT NONE
   SAVE
  	INTEGER(4)		:: nvr,nfk,nk,nx
	REAL(8),ALLOCATABLE	:: qw(:),x(:,:),logphi(:)
END MODULE commons

PROGRAM test
USE commons
USE MIXTURE_MOD
IMPLICIT NONE
	REAL(8),ALLOCATABLE	:: th1(:)

nvr=2; nk=5 ; nx=nk**nvr
ALLOCATE(qw(nx),x(nvr,nx),logphi(nx))
x=1d0; qw=1d0; logphi=1d0
CALL getmixture(nvr,nx,x,qw,logphi,nfk,th1)

END PROGRAM test

   

 

0 Kudos
2 Replies
Steven_L_Intel1
Employee
735 Views

The problem you have here is not the names but that you've declared module variables x, qw and logphi as arrays whose bounds are other module variables. This doesn't work - module variables are static and come into existence when the program starts - you can't later assign values to the bounds.

What you want to do here instead is make these arrays ALLOCATABLE with deferred-shape bounds, like this:

 REAL(8), ALLOCATABLE :: x(:,:),qw(:),logphi(:)

and then allocate them to the desired size when the program starts (probably by calling a procedure in the module to do it.)

As for names, you're right that there can be a conflict if a procedure that USEs the module declares local variables of the same name.  If the module variables are used only in the module, then make them PRIVATE. Otherwise consider naming them with a prefix that makes them unique.

0 Kudos
Natalia_K_
Beginner
735 Views

I see now where my mistake was. Indeed the dimension of x,qw,logphi was based not on parameters but variable input. Thanks!

0 Kudos
Reply