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.
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.
(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.
Related
I'm trying to learn Fortran, and I've found that there aren't very many tutorials out there (probably due to it being an old language). The ones I have found are vague and undescriptive, and as I've gone into more complex things it has become harder and harder to guess what said tutorials are saying.My current issue is with creating types. The tutorial contains examples such as:
module m_shapes
implicit none
private
public t_square
type :: t_square
real :: side
contains
procedure :: area ! procedure declaration
end type
contains
! Procedure definition
real function area(self) result(res)
class(t_square), intent(in) :: self
res = self%side**2
end function
end module m_shapes
This compiles fine, so I know it works.
When I try to do something similar like this:
program type_test
implicit none
type :: thingy(a)
real :: a
end type
end program
It doesn't compile with errors like "The component at (1) that appears in the type parameter list at (2) has neither the KIND nor LEN attribute"
The tutorial I found does not explain types well enough, and I've tried things like real,kind :: a = kind(0.0), but to no avail. Does anybody know what's wrong?
Thanks in advance.
You did not explain, what you actually want to do. Or your words are not nearly clear enough. We can tell you why your attempt produces the error, but I have no idea what you actually want to do.
Perhaps you just wanted
program type_test
implicit none
type :: thingy
real :: a
end type
end program
without the (a)? That declares a simple type with one component. But hard to guess if this is what you wanted and what you tried with the (a).
It does not declare any variable with that type. That is done using
type(thingy) :: var
The syntax
type :: thingy(a)
real :: a
end type
attempts to declare a parametrized derived type. These types can depend on a kind or length parameter. These parameters must be integers. If it is a kind parameter, it allows to declare variables of the type with varying values of these parameters. Then the kind of some components of the type (you know what kind is, right? Fortran 90 kind parameter ) get their kind according to the value of the parameter. If it is a length parameter, it allows the length of some array or string components of the derived type to be parametrized - set during the variable declaration.
These parameters that appear in the parenthesis must be integer components and must have the kind or len attribute.
For example
type :: param_type(k,l)
integer, kind :: k
integer, len :: l
real(kind=k), dimension(l) :: array
end type param_type
type(param_type(kind(1.), 10)) :: o_sp_10
type(param_type(kind(1.d0), 20)) :: o_dp_20
The values of the parameters are set during the declaration of those o_sp_10 and o_dp_20 objects. I do not want to go into more details.
If I want to prevent module data from being changed during program execution, I seem to have at least three options in Fortran:
1. using the SAVE statement
module mymod
implicit none
save
integer :: i = 1
end mymod
2. using the PROTECTED attribute
module mymod
implicit none
integer, protected :: i = 1
end mymod
3. using the PARAMETER attribute
module mymod
implicit none
integer, parameter :: i = 1
end mymod
What are the differences and implications of the three options?
This answer addresses the non-subtle aspects of the use of the entities named i. There are a few other considerations to be made in more complicated cases. It also uses the term variable definition context. Loosely speaking, this means where a variable may appear such that its value could change. This would be things like being the left-hand side of an assignment; appearing as a do variable or corresponding to an intent(out) argument.
i may appear in a variable definition context whenever it is accessible.
i (as a non-pointer object), where it is accessible, can appear in a variable definition context only in the scope of its module or descendants of that module.
i can never appear in a variable definition context: it is a constant not a variable.
The save attribute (in the current standard any module variable has this attribute; even i in the second example is saved) does not control modification.
I am mostly doing scientific programming in Python and do not have a whole lot of Fortran (90/95) experience. For one of my projects I want to define a derived type and overload a bunch of operators for that type. Critically, I'd like one of the variables of the derived type to an array of variable length; at least, I need two different lengths in different parts of the code. How can I best achieve this efficiently and avoiding code duplication?
My first approach was to use an allocatable array but that involved several allocate statements throughout the code including the overloaded operators. It also led to difficulties when using the code in an MPI application.
My current approach is two define a type of the same name in two separate modules and use one or the other in different parts of the code. The overloaded operators can be shared using a header file (mytype_operators.h in the example below).
module mod1
type mytype
real :: x1
real,dimension(1) :: x2
end type mytype
#include "mytype_operators.h"
end module mod1
module mod2
type mytype
real :: x1
real,dimension(10) :: x2
end type mytype
#include "mytype_operators.h"
end module mod2
Unfortunately, there is one module in the code with subroutines that I would like to use for both types. Currently I have two copies of that code; one with "use mod1", the other with "use mod2". Can I improve this and avoid the code duplication?
Your case is very suitable for using a Fortran feature introduced in the 2003 standard (and adopted much later by compilers) named parameterized derived types. First of all, you should check the compliance status of your compiler to know if it's fully supported.
This feature allows you to pass custom parameters when declaring or constructing a derived-type, so internal functionality will be adjusted accordingly. They are good for having different behaviour alternatives grouped in a single type name, possibly with considerable coding or storage differences. There are 2 types of parameters:
kind parameters behave much like the kind specifier of intrinsic types. Kind parameters of all variables must be known at compile time and are treated practically as constant values. The convenience is that you could change it easily (in code time) by altering just a value in the declaration or construction. This is commonly used for specializing the kind of components of intrinsic type.
len parameters behave much like the len specifier of intrinsic character type. You can define len parameters at compile time or runtime, and a len parameter of a variable cannot change unless you declared it allocatable. Moreover, you can have arguments with assumed len-parameters in procedures, and avoid code verbosity. This is commonly used as a "length" or "dimension" parameter for a derived type, because you can use them in the declaration of array bounds and character length.
In general, type parameters are used to mimic the functionality of intrinsic types in derived types, but you could also get "creative" and use it for other things, like the dimension-space of a transformation-matrix type; for a custom "union type" (like an enumeration); as the nature of a physical quantity in a "units of measurement" data-type (a real value annotated with "mass" unity is not directly compatible with a "temperature" one, but they can be handled pretty much the same way in the code); the "arity" of a tuple type...
module mod1
type :: mytype(n)
integer, len :: n
real :: x1
real, dimension(n) :: x2
end type mytype
contains
! your operations here...
end module mod1
And use it like this:
program test_pdt
use mod1
implicit none
type(mytype(10)) :: mt10
type(mytype(1)) :: mt1
integer :: i
mt10%x1 = 40.0
mt10%x2 = [(0.5 * i, i = 1, 10)]
mt1 = mytype(1)(20.0, [30.0])
call sub(mt10)
call sub1(mt1)
contains
subroutine sub(m)
! accepts values with any "n" parameter
type(mytype(*)) :: m
! you can also use them in declarations
integer, dimension(m%n + 1) :: y
type(mytype(m%n)) :: w
print *, m%n, w%n, size(y)
end
subroutine sub1(m)
type(mytype(1)) :: m ! only accepts values with n=1
print *, m%x1, m%x2, m%n
end
end
Warning:
This is feature, despite of having been announced many years ago, was just recently added to most compilers, and you should be aware that there are still some bugs in implementation. You should probably be fine with regular use, but I often face false syntax errors in some corner cases, and even ICE sometimes.
I am using fortran for a while, but I didn't check the implicit cast issue when using subroutines in fortran.
For example
subroutine printa(a)
double precision :: a
...
endsubroutine printa
When I called the subroutine
call printa(1)
I saw error #6633: The type of the actual argument differs from the type of the dummy argument. [1]
I know it is because I use an integer instead of a double precision as an input parameter. But I just realized that there is no implicit cast when using subroutines.
If I want a subroutine which handles integer and double precision data, it seems I have to define 2 subroutines for doing these things. Is there a way to make the implicit cast happen (just like the function calling in c)? Or there is another way to make it?
Thanks.
It is fundamental in Fortran that reals (including different precisions) and integers are different and that you need different subroutines to handle them. If you want the convenience of having a single call, similar to Fortran intrinsics such as sin which are implicitly several different functions, you can write the several different procedures and then create a generic interface to select between them. Fortran will then select the correct actual procedure based on the actual arguments, to match the dummy arguments. Here is an example that does it by rank of the array argument: how to write wrapper for 'allocate'. It can also be done, as you wish, by type of the argument.
You can overload a subroutine name so that when the "wrong" type of argument is supplied it is converted to right type and used to call the subroutine, as shown below.
module foo
implicit none
interface printa
module procedure print_int,print_real
end interface printa
contains
!
subroutine print_real(x)
real, intent(in) :: x
print*,"number is ",x
end subroutine print_real
!
subroutine print_int(i)
integer, intent(in) :: i
call print_real(real(i))
end subroutine print_int
!
end module foo
program main
use foo, only: printa
implicit none
call printa(1)
call printa(1.0)
end program main
Output:
number is 1.
number is 1.
I have two routines whose difference is only in the order of arguments, but I would like to use them through an interface, so that the proper one is invoked according to the order of the arguments when invoked. The compiler complains that it cannot distinguish them, and my guess is because if I use the syntax for named arguments at call, it won't know which one to call. One workaround would be to use different names for the arguments, but I was wondering if there's a way to disable named argument call style.
Example, this is the situation I am trying to handle
module Foo
interface Bar
module procedure Bar1
module procedure Bar2
end interface
contains
subroutine Bar1(i,r)
integer, intent(in) :: i
real, intent(in) :: r
print *, "bar1"
end subroutine
subroutine Bar2(r,i)
real, intent(in) :: r
integer, intent(in) :: i
print *, "bar2"
end subroutine
end module
program fuux
use Foo
integer :: i
real :: r
r = 5.0
i = 3
call Bar(i,r) ! note that if I call Bar(i=i, r=r) the compiler cannot disambiguate
! so it will complain at the interface statement
end program
I do not know of any way to do what you suggest, or rather to do what I think you are suggesting in the phrase 'disable named argument call style'. If this answer infuriates, disappoints or displeases in any way, post some code and we (SO I mean, I have not too many airs and graces and rarely use the royal 'we') might be able to suggest a cunning trick which will please you.
EDIT
No direct way to do what you want to do springs to mind. The first workround that occurs to me is to define a subroutine called bar which takes the series of arguments in a canonical order and simply calls bar1, bar2 (and any other baby bars you care to define) with the arguments in the appropriate order.