Home > Archive > Fortran > June 2007 > type/rank mismatch error
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
type/rank mismatch error
|
|
| estevino@gmail.com 2007-06-29, 7:06 pm |
| Hi,
I'm using gfortran 4.3.0 on Mac OSX 10.4.8.
I'm having a problem compiling a two modules and a main.
One module looks like
MODULE calculate
CONTAINS
SUBROUTINE some_op(a,b,c)
USE nrtype
IMPLICIT NONE
REAL, INTENT(IN) :: a
REAL, DIMENSION(:), INTENT(IN) :: b
REAL, DIMENSION(:), INTENT(OUT) :: c
....
END SUBROUTINE some_op
END MODULE calculate
Another module contains several subroutines that take 'calculate' as a
procedure argument and makes a call to the routine 'some_op' inside --
this looks like
MODULE various
USE calculate
CONTAINS
SUBROUTINE number1(x,y,some_op)
....
END SUBROUTINE number1
SUBROUTINE number2(x,y,some_op)
....
END SUBROUTINE number2
END MODULE various
When I try to compile the object, I get a type/rank mismatch error:
[color=darkred]
various.f90:118.47:
call number1(x,y,some_op)
1
Error: Type/rank mismatch in argument 'some_op' at
(1)various.f90:118.47:
These procedures are not defined anywhere else, so I'm at a loss to
explain why this is occurring. Any help?
| |
|
| On Jun 29, 12:25 am, estev...@gmail.com wrote:
> Hi,
> I'm using gfortran 4.3.0 on Mac OSX 10.4.8.
> I'm having a problem compiling a two modules and a main.
> One module looks like
>
> MODULE calculate
> CONTAINS
> SUBROUTINE some_op(a,b,c)
> USE nrtype
> IMPLICIT NONE
> REAL, INTENT(IN) :: a
> REAL, DIMENSION(:), INTENT(IN) :: b
> REAL, DIMENSION(:), INTENT(OUT) :: c
> ...
> END SUBROUTINE some_op
> END MODULE calculate
>
> Another module contains several subroutines that take 'calculate' as a
> procedure argument and makes a call to the routine 'some_op' inside --
> this looks like
>
> MODULE various
> USE calculate
> CONTAINS
> SUBROUTINE number1(x,y,some_op)
> ...
^^^ elipsis? You just did not include the most important part,here.
How exactly are the arguments to the subroutine being defined? typed?
The last argument is a subroutine itself. How is that being handle?
gsal
| |
| Jugoslav Dujic 2007-06-29, 7:06 pm |
| estevino@gmail.com wrote:
| Hi,
| I'm using gfortran 4.3.0 on Mac OSX 10.4.8.
| I'm having a problem compiling a two modules and a main.
| One module looks like
|
| MODULE calculate
| CONTAINS
| SUBROUTINE some_op(a,b,c)
| USE nrtype
| IMPLICIT NONE
| REAL, INTENT(IN) :: a
| REAL, DIMENSION(:), INTENT(IN) :: b
| REAL, DIMENSION(:), INTENT(OUT) :: c
| ...
| END SUBROUTINE some_op
| END MODULE calculate
|
| Another module contains several subroutines that take 'calculate' as a
| procedure argument and makes a call to the routine 'some_op' inside --
| this looks like
|
| MODULE various
| USE calculate
| CONTAINS
| SUBROUTINE number1(x,y,some_op)
| ...
| END SUBROUTINE number1
| SUBROUTINE number2(x,y,some_op)
| ...
| END SUBROUTINE number2
| END MODULE various
|
| When I try to compile the object, I get a type/rank mismatch error:
|
||| gfortran -c calculate.f90 various.f90
|
| various.f90:118.47:
|
| call number1(x,y,some_op)
| 1
| Error: Type/rank mismatch in argument 'some_op' at
| (1)various.f90:118.47:
|
| These procedures are not defined anywhere else, so I'm at a loss to
| explain why this is occurring. Any help?
I must say I'm as to the intent of the code. The code, as shown,
violates the simple rule that
*Any formal (dummy) argument of a routine must be declared locally
in the routine, not elsewhere*
in other words, if you defined some_op in the module "calculate", you
must not redefine some_op elsewhere (at least, not in a scope which
USEs the module "calculate")
Let's simplify the case, using something other than routine; it
is the same error (whose should be better worded by the compiler) as:
MODULE calculate
INTEGER:: some_number
END MODULE calculate
MODULE various
USE calculate
CONTAINS
SUBROUTINE number1(x,y,some_number)
Error; redefinition-----------^
Now, I'm as to the intent of the code. Allowing myself the
grave sin of guessing as to the intent, you want:
1) either to plainly CALL some_op from number1 and number2, in
which case you need:
MODULE various
USE calculate
CONTAINS
SUBROUTINE number1(x,y)
....
CALL some_op(x, z, f)
END SUBROUTINE number1
2) ...or, judging on your misguided (no offense intended) wording:
| Another module contains several subroutines that take 'calculate' as a
| procedure argument and makes a call to the routine 'some_op' inside --
| this looks like
[A module name, "calculate", can NOT be a procedure argument]
....you want to pass a routine of "signature" like the one of some_op
as an actual argument to the number1. In that case, you still have to
declare that signature *locally*:
MODULE various
CONTAINS
SUBROUTINE number1(x,y,some_op)
REAL, INTENT(WHATEVER):: x,y
INTERFACE
SUBROUTINE some_op(a,b,c)
USE nrtype
IMPLICIT NONE
REAL, INTENT(IN) :: a
REAL, DIMENSION(:), INTENT(IN) :: b
REAL, DIMENSION(:), INTENT(OUT) :: c
END SUBROUTINE some_op
END SUBROUTINE
END INTERFACE
!Body of number1
....
END SUBROUTINE number1
....
END MODULE Various
Note that the INTERFACE keyword specifies that you're declaring a
"placeholder", i.e. a "signature" or "prototype" of the routine, which
may have any name you want. The actual some_op will be defined in
the calling program. And no, you cannot define such interface elsewhere
than within the routine whose dummy argument it is. Fortran doesn't
have "function typedefs" or "function pointers" like C/C++.
If that's the intent, what you *can* do to save retyping of the
INTERFACE block in a zillion places, is to move it to an INCLUDEd
file, i.e.
File Calculate.fd
----------------------
INTERFACE
SUBROUTINE some_op(...)
...
END INTERFACE
----------------------
MODULE various
CONTAINS
SUBROUTINE number1(x,y,some_op)
REAL, INTENT(WHATEVER):: x,y
INCLUDE "Calculate.fd"
Note the (huge) semantic difference between INCLUDE and USE: the
former is just a "text substitution" or a "macro". The latter
always declares a "real thing".
--
Jugoslav
___________
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.
| |
| Richard Maine 2007-06-29, 7:06 pm |
| Jugoslav Dujic <jdujic@yahoo.com> wrote:
> estevino@gmail.com wrote:
....[module calulate, which defines some_op]
> | MODULE various
> | USE calculate
> | CONTAINS
> | SUBROUTINE number1(x,y,some_op)
> | ...
> | END SUBROUTINE number1
> | SUBROUTINE number2(x,y,some_op)
> | ...
> | END SUBROUTINE number2
> | END MODULE various
> I must say I'm as to the intent of the code. The code, as shown,
> violates the simple rule that
>
> *Any formal (dummy) argument of a routine must be declared locally
> in the routine, not elsewhere*
Um. I'm by that "rule". I think I know what you mean, but the
expression of it confuses me. You can, of course, define things of that
same name elsewhere all you want.That just doesn't constitute defining
the dummy argument.
> in other words, if you defined some_op in the module "calculate", you
> must not redefine some_op elsewhere (at least, not in a scope which
> USEs the module "calculate")
True, but the code shown doesn't do that. It defines some_op in module
procedures that are *NOT* in the same scope as the USE statement. It
makes a huge difference. See host association. The use of those names as
dummy arguments blocks the host association of the name imported by the
USE.
I actually think I agree with some of your subsequent guesses about the
likely intent of the code. Anyway, they seem plausible. I'm just
quibbling about the above stuff.
--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
| |
| Jugoslav Dujic 2007-06-29, 7:06 pm |
| Richard Maine wrote:
| Jugoslav Dujic <jdujic@yahoo.com> wrote:
|
|| estevino@gmail.com wrote:
| ...[module calulate, which defines some_op]
||| MODULE various
||| USE calculate
||| CONTAINS
||| SUBROUTINE number1(x,y,some_op)
||| ...
||| END SUBROUTINE number1
||| SUBROUTINE number2(x,y,some_op)
||| ...
||| END SUBROUTINE number2
||| END MODULE various
|
|| I must say I'm as to the intent of the code. The code, as shown,
|| violates the simple rule that
||
|| *Any formal (dummy) argument of a routine must be declared locally
|| in the routine, not elsewhere*
|
| Um. I'm by that "rule". I think I know what you mean, but the
| expression of it confuses me. You can, of course, define things of that
| same name elsewhere all you want.That just doesn't constitute defining
| the dummy argument.
|
|| in other words, if you defined some_op in the module "calculate", you
|| must not redefine some_op elsewhere (at least, not in a scope which
|| USEs the module "calculate")
|
| True, but the code shown doesn't do that. It defines some_op in module
| procedures that are *NOT* in the same scope as the USE statement. It
| makes a huge difference. See host association. The use of those names as
| dummy arguments blocks the host association of the name imported by the
| USE.
I overlooked the fact that, in case of host association, the local
declaration overrides the host-associated declaration. Thus, one
may have two different entities of the same name "accessible" (for
want of a better word) in the same scope, but only the one from the
inner scope will be visible and usable.
The OP didn't show us enough code to confirm the meaning of some_op
as the dummy argument of number1. From the naming and explanation,
I judged that the intent was "use declaration as from module calculate"
rather than "use the local declaration, overriding the one from
host-association".
Still, I don't see what's wrong with the rule as written: the *entity*
referred to by formal argument must be declared in the routine itself
(let's put the issue of implicit typing aside); it is local to the
routine ab definitio. Other same-named entities may or may not exist
in the host scope, but they won't be accessible anyway.
In any case, avoiding re-using the same name for different entities
in inner and outer scope is a good rule of thumb (I overlooked the
overriding thingo as I use that rule of thumb myself, so tend to
forget that it's allowable).
[Please, pardon my loose usage of standardese above; while I'm familiar
with it, I'm not always able to find the exact precise wording on my own.
I hope that the message does get through though.]
--
Jugoslav
___________
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.
| |
| estevino@gmail.com 2007-06-29, 7:06 pm |
| Richard, Jugoslav,
Thank you both for clarifying the issue, which was one of scope and a
namespace confusion. My previous post was perhaps not clear --
probably as opaque as this code. As before, the module is
MODULE calculate
CONTAINS
SUBROUTINE some_op(a,b,c)
USE nrtype
IMPLICIT NONE
REAL, INTENT(IN) :: a
REAL, DIMENSION(:), INTENT(IN) :: b
REAL, DIMENSION(:), INTENT(OUT) :: c
c = a*b
END SUBROUTINE some_op
END MODULE calculate
Of course, an external routine would USE calculate and call some_op,
having already defined what a,b,c are.
The module throwing the error contains four subroutines, each of which
take a subroutine as a procedure argument. What is worse, two
subroutines call other subroutines that also have the *same* procedure
argument. In code,
MODULE various
USE calculate
CONTAINS
SUBROUTINE number1(x,y,some_op)
....
call number2(x,y,some_op)
END SUBROUTINE number1
SUBROUTINE number2(x,y,some_op)
call number3(x,y,some_op)
END SUBROUTINE number2
....
END MODULE various
After your informative posts, I reread the scoping rules (surprise,
noob F90 programmer). I realized that the external driver would make
a call to number1 like this:
PROGRAM driver
USE calculate <-------- this USE allows the driver
to use the subroutine in module calculate
USE various <-------- contains subroutines that
do dirty work
! variables...
call number1(aa,bb,some_op) <-------- here I can address the
name of the subroutine directly
....
END PROGRAM
Inside MODULE various, both the SUBROUTINE declarations, AND any
subsequent nested subroutine calls that also need 'some_op' inside
must have a different name for their dummies, with an appropriate
EXTERNAL declaration for those dummy args. So, the original module
various should look more like
MODULE various
USE calculate
CONTAINS
SUBROUTINE number1(x1,y1,op1)
EXTERNAL :: op1
REAL :: x1,y1
.... other calcs
call number2(x1,y1,op1)
END SUBROUTINE number1
!
SUBROUTINE number2(x2,y2,op2)
EXTERNAL :: op2
call number3(x2,y2,op2)
END SUBROUTINE number2
....
END MODULE various
This way, there isn't confusion about the naming of the module.
However, this seems to me an obfuscated way of coding. Is there some
way to name the subroutine some_op consistently?
Thanks for your help and expertise!
| |
|
|
<estevino@gmail.com> wrote in message
news:1183130878.777871.123690@e16g2000pri.googlegroups.com...
> Richard, Jugoslav,
>
> Thank you both for clarifying the issue, which was one of scope and a
> namespace confusion. My previous post was perhaps not clear --
> probably as opaque as this code. As before, the module is
>
<snip>
>
> After your informative posts, I reread the scoping rules (surprise,
> noob F90 programmer). I realized that the external driver would make
> a call to number1 like this:
>
> PROGRAM driver
> USE calculate <-------- this USE allows the driver
> to use the subroutine in module calculate
> USE various <-------- contains subroutines that
> do dirty work
> ! variables...
> call number1(aa,bb,some_op) <-------- here I can address the
> name of the subroutine directly
> ...
> END PROGRAM
>
> Inside MODULE various, both the SUBROUTINE declarations, AND any
> subsequent nested subroutine calls that also need 'some_op' inside
> must have a different name for their dummies, with an appropriate
> EXTERNAL declaration for those dummy args. So, the original module
> various should look more like
>
> MODULE various
> USE calculate
> CONTAINS
> SUBROUTINE number1(x1,y1,op1)
> EXTERNAL :: op1
> REAL :: x1,y1
> ... other calcs
> call number2(x1,y1,op1)
> END SUBROUTINE number1
> !
> SUBROUTINE number2(x2,y2,op2)
> EXTERNAL :: op2
> call number3(x2,y2,op2)
> END SUBROUTINE number2
> ...
> END MODULE various
>
> This way, there isn't confusion about the naming of the module.
>
> However, this seems to me an obfuscated way of coding. Is there some
> way to name the subroutine some_op consistently?
>
> Thanks for your help and expertise!
>
If you are _always_ going to eventually call "some_op" then there is no need
to pass it to the various "number" routines - just do a call some_op at the
appropriate place, providing you have the appropriate "USE calculate" giving
you access to the some_op subroutine (which you do have in the code you
showed).
But if the "number" routines are to be general purpose then *any*
appropriate routine can be passed, from the caller, as the actual argument
to op1, op2 etc, along with *any* appropriate values/variables for the other
arguments. In fact you could replace op1, op2 etc with just op in each of
the number routines indicating that each expects an external routine of some
sort.
Les
| |
| estevino@gmail.com 2007-06-29, 7:06 pm |
| On Jun 29, 9:14 am, "Les" <l.neil...@nospam.acecad.co.uk> wrote:
> <estev...@gmail.com> wrote in message
>
> news:1183130878.777871.123690@e16g2000pri.googlegroups.com...
>
>
>
>
>
> <snip>
>
>
>
>
>
>
>
>
> If you are _always_ going to eventually call "some_op" then there is no need
> to pass it to the various "number" routines - just do a call some_op at the
> appropriate place, providing you have the appropriate "USE calculate" giving
> you access to the some_op subroutine (which you do have in the code you
> showed).
>
> But if the "number" routines are to be general purpose then *any*
> appropriate routine can be passed, from the caller, as the actual argument
> to op1, op2 etc, along with *any* appropriate values/variables for the other
> arguments. In fact you could replace op1, op2 etc with just op in each of
> the number routines indicating that each expects an external routine of some
> sort.
>
> Les
Thanks Les! In this case, passing the subroutine is really not
necessary. Your comment turned the light bulb on in my head!
Thanks everyone for their help!
|
|
|
|
|