0

Hi I have tried to create a minimal, complete, and verifiable example sample code below to emphasize the one error message I am getting. The error is "Type Mismatch in argument 'func0' at (1); passed REAL(4) to COMPLEX(4).

I indicated in the code where the error message from (1) is. It occurs when I try to call a subroutine within another subroutine.

I originally tried to add implicit none into Sub2, however then I get an error message saying func0,func1 do not have implicit types.

I tried to follow the logic of this post : How to call and use a subroutine inside another subroutine in fortran?

Module Sample

integer :: n,m

contains 

subroutine Sub1(func0,func1)

implicit none

   complex, dimension(-10:10, -10:10), intent(inout) :: func0,func1
   complex, dimension(-10:10, -10:10) :: Deriv0,Deriv1


     do while (100 > 0.000001) 

        Deriv0 = Deriv(func0)
        Deriv1 = Deriv(func1)

     end do

end subroutine Sub1

subroutine Sub2(func3)
!implicit none : if this line is not commented out, I still get error messages saying func0,func1 do not have implicit types

   real,dimension(0:20), intent(inout) :: Func3

   call Sub1(func0,func1) !error message from here, this is line (1)

end subroutine  Sub2

function Deriv(func)
implicit none

complex, dimension(-10:10, -10:10) :: func, Deriv

   do n=-9,9
   do m=-9,9

     Deriv(n,m) = func(n+1,m)-2*func(n,m)

   end do
   end do

end function Deriv

End Module Sample

How can I fix this error? Thanks.

Community
  • 1
  • 1
Jeff Faraci
  • 403
  • 13
  • 28

2 Answers2

2

There are a number of concepts here we concern ourselves with: scoping; association; and inheritance.

In the code of the question there are four scoping units: the module sample and the three procedures (two subroutines and one function). These are all distinct, but some information is shared between them.

Looking first at the implicit statement. In the module there is no implicit so default typing rules apply in the module's scoping unit. (Although nothing in the module is implicitly typed - the module variables and the function are all explicitly declared.) sub1 and deriv each have implicit none so the typing rule (no implicit typing) is stated clearly there.

With implicit none specified in sub2 there is a compiler complaint about no explicit type declaration of func0 and func1; without implicit none the scoping unit sub2 inherits the typing rules of its host (the module) and so func0 and func1 are real.

You can read about scoping units and typing rules in another question and its answers. In summary, put implicit none in the module.

This typing of func0 and func1 leads us to another aspect of scoping. sub1 and sub2 are entirely different scoping units. The only way those two subroutines can share knowledge about declarations is through association of one form.

There are two forms of association going on here: host association and argument association.

Host association is that each subroutine has access to the variables n and m. They don't reference those variables so let's ignore them. Host association also gives an explicit interface of sub1 in sub2 which allows the compiler to complain about the type mismatch.

In the scoping unit of sub2 there is no explicit declaration of func0 and func1. This is an error with implicit none in force; with default implicit typing rules they are real scalar variables or functions with real scalar results. If you want them to be complex arrays you are just going to have to declare them as such.

Argument association comes about in the following way. We associate the dummy arguments of sub1 with the actual arguments of sub2. The crucial thing here is association: two distinct things happen to refer to the same object. The two procedures don't share anything that isn't explicitly stated in each. To be able to have an actual argument associated with those dummy arguments something appropriate has to exist in the scope of sub2. Currently nothing does.


In short: you need to have a suitable declaration of func0 and func1 in sub2. These may be local variables or dummy arguments, depending on how you want the program to flow.

francescalus
  • 30,576
  • 16
  • 61
  • 96
  • This is very helpful for me. I was able to fix the errors by declaring func0,func1 in sub2 as you suggested. I also added implicit none into the module. Thanks a lot for all of the other explanations too. If I have any questions I'll let you know but I don't as of now, this is all very very clear. Thanks! – Jeff Faraci May 01 '17 at 00:48
0

(Disclaimer: I don't actually know Fortran. This answer is a WAG.)

In your Sub2 subroutine, neither func0 nor func1 are declared, and they're not parameters. Unlike the other parts of your code, Sub2 does not contain an implicit none directive, so the compiler assumes you intended func0 to be a REAL variable, which then leads to a type error (because Sub1 requires a COMPLEX variable).

I can't tell you how to fix this because your code never calls Sub2 anywhere, but presumably you have to get two COMPLEX variables from somewhere to pass to Sub1.

melpomene
  • 84,125
  • 8
  • 85
  • 148
  • Ya I realized there is no implicit none, when I added it I just got other error messages about func0, func1 not having implicit types. So I figured I would first start with this one error message first. Func0, Func1 shouldn't be defined In my Sub2, thats exactly why I am calling Sub1 which is where func0, func1 are defined. I think the part 'contains' calls all the subroutines and functions in my module, I don't explicitly 'call' each function/subroutine. I only used this call here because sub2 needs sub1. Thanks for your answer,you may be right. But I don't know how to fix it – Jeff Faraci Apr 30 '17 at 17:42
  • For ex: my code never calls sub1 or function Deriv, however I get no errors from there. My module has 'contains' which takes care of this (I think?) Once I added this subroutine Sub2, I get errors when I try to call Sub1. Obviously something is wrong with this logic, how do you suggest calling Sub2 then? I never call Sub1 or Function Deriv, so why do I have to call Sub2? – Jeff Faraci Apr 30 '17 at 17:51
  • @Integrals You don't have to call `Sub2`; it just might have given me a clue as to how you intended it to be used. Right now I have no idea what this code is supposed to achieve, which is why I can't tell you what to do instead. – melpomene Apr 30 '17 at 18:01
  • Thanks for your help. This is just a sample code to indicate the error message I get. It doesn't indicate what I am trying to achieve. Let me try to explain that clearly, sorry about that. So my code contains a Module which 'contains' Subroutine 1, subroutine 2 and a function. Subroutine 1 uses information from my function, I don't explicitly 'call' this though. Subroutine 2 is supposed to use information from Subroutine 1, so I used 'call' for that. The overall code uses sub 1,2 and the function. That's all. Is that helpful or still not? IF not, what are you looking to know exactly? – Jeff Faraci Apr 30 '17 at 18:07
  • Should I use the implicit none statement? If so, I then have different error messages that func0, func1 do not have implicit types. How can I fix that? I'm not sure which error is actually the one I need to be going after; not having implicit types or the one in my post above. Thanks again. Sorry for the confusion on my end. – Jeff Faraci Apr 30 '17 at 18:16
  • @Integrals This all sounds backwards to me. `func0` and `func1` are inputs to `Sub1`; you can't use them to get information out from `Sub1`. And as far as I can tell, `Sub1` has no visible effects anyway, so calling it does nothing. – melpomene Apr 30 '17 at 18:21
  • Yes func0, func1 are inputs to sub1 and Sub1 only uses the Function called Deriv(func). Sub2 needs func0,func1, which is why i'm calling Sub1. If calling sub1 does nothing, how can I get the information needed in Sub2 from Sub1? Do I need to use a 'call'? Or should I just stick to the 'contains' in my module? Thanks – Jeff Faraci Apr 30 '17 at 18:25