I would like to create a parametrized derived type inside a procedure and operate on the type's member. The following code works and writes out 4 and 8, as expected.
module mod1
implicit none
type :: pdt(n)
integer, len :: n
integer :: a(n), b(n)
end type
end module mod1
program main
use mod1
implicit none
type(pdt(4)) :: aa
print *, aa%n
print *, func(4)
contains
integer function func(n) result(m)
integer :: n
type(pdt(n)) :: pdttest
m = 2*pdttest%n
end function
end program
The problem arises when I place the procedure func in a separate module, in which case pdttest%n is uninitialized. Compiling using gfortran 11.2.0 with the flag -Wall returns:
Warning: ‘pdttest.n’ is used uninitialized [-Wuninitialized]
What could be the cause of this?
module mod2
use mod1
implicit none
contains
integer function func(n) result(m)
integer :: n
type(pdt(n)) :: pdttest
m = 2*pdttest%n
end function
end module
Related
UPDATE: My modified code looks like this:
program run_module_test
use module_test
implicit none
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
call update(xyzArray)
write(6,*)'xyzArray',xyzArray
end program run_module_test
module module_test
implicit none
TYPE :: newXYZ
real(4) :: x, u
real(4) :: y, v
real(4) :: z, w
real(4),dimension(3) :: uvw
END TYPE
integer(4) :: shape = 3
contains
subroutine update(xyzArray)
integer(4) :: i
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
allocate( xyzArray(shape) )
do i = 1, shape
xyzArray(i)%x = 0
xyzArray(i)%y = 0
xyzArray(i)%z = 0
xyzArray(i)%u = 0
xyzArray(i)%v = 0
xyzArray(i)%w = 0
xyzArray(i)%uvw = (/0,0,0/)
end do
return
end subroutine update
end module module_test
When they are compiled, they generate a similar error:
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
1
Error: ALLOCATABLE attribute conflicts with DUMMY attribute at (1)
When I eliminate the argument in update() subroutine, I receive a contradictory error:
TYPE(newXYZ), allocatable, intent(inout) :: xyzArray(:)
1
Error: Symbol at (1) is not a DUMMY variable
Have I eliminated the sources of error pointed out in the helpful suggestions? Could this be a compiler related error (using mpi90)?
~~~First Edit~~~
I have a subroutine whose input argument is an array of user defined type XYZ. I wish to deallocate xyzArray and allocate/modify it to a different size in the body of the subroutine. I attempted the method suggested by changing array dimensions in fortran, but when I do the following:
subroutine update(xyzArray, ...)
...
TYPE (XYZ), allocatable :: xyzArray(:)
I receive an error message:
Error: ALLOCATABLE attribute conflicts with DUMMY attribute at (1)
When I try:
subroutine update(xyzArray, ...)
...
deallocate( xyzArray(myshape) )
allocate( xyzArray(newshape) )
I receive error messages:
Error: Expression in DEALLOCATE statement at (1) must be ALLOCATABLE or a POINTER
Error: Expression in ALLOCATE statement at (1) must be ALLOCATABLE or a POINTER
What do I need to do to change the size of the array in the subroutine?
To do this:
The dummy argument must be allocatable. Allocatable dummy arguments require a compiler that implements the relevant part of the Fortran 2003 standard (or a Fortran 95 compiler that implements the so called "allocatable" TR).
An explicit interface to the procedure is required (the procedure must be a module procedure, an internal procedure or have an interface block in the calling scope).
The dummy argument must not be intent(in). If you are not using the allocation status or other aspects of the value of the dummy argument at all in the subroutine then intent(out) may be appropriate (if allocated beforehand the dummy argument will be automatically deallocated when the procedure is called), otherwise intent(inout) or no intent.
(Your second block of example code has a syntax error with the deallocate statement - you should simply specify the xyzArray variable, leave off the (myshape) shape specification))
For example, in a module:
subroutine update(xyzArray)
type(xyz), allocatable, intent(inout) :: xyzArray(:)
...
if (allocated(xyzArray)) deallocate(xyzArray)
allocate(xyzArray(newshape))
...
If you are sure, you want to deallocate the array in your subroutine, you can declare the dummy argument being intent(out), so that it is deallocated automatically when the subroutine is entered:
module whatever
implicit none
type :: xyz
:
end type xyz
contains
subroutine update(xyzArray)
type(xyz), allocatable, intent(out) :: xyzArray(:)
:
allocate(xyzArray(someshape))
:
end subroutine update
end module whatever
As already noted by IanH, the process must have an explicit interface (e.g. being enclosed in a module) and in the caller program you must declare the actual argument allocatable:
program test
use whatever
implicit none
type(xyz), allocatable :: array(:)
:
call update(array)
:
end program test
I am using Fortran 90 and the Intel compiler.
I am very confused using a function in a subroutine. My code is (I deleted everything unimportant):
program test
INTEGER :: seed=5
REAL :: nor_ran_number1, nor_ran_number2
CALL Box_Muller_transform(seed,nor_ran_number1,nor_ran_number2)
end program test
double precision function grnd(SEED)
grnd=5
return
end
SUBROUTINE Box_Muller_transform (seed,nor_ran_number1,nor_ran_number2)
implicit none
INTEGER, INTENT(in) :: seed
REAL, INTENT(out) :: nor_ran_number1, nor_ran_number2
nor_ran_number1 = grnd(seed)
nor_ran_number2 = grnd(seed)
end SUBROUTINE Box_Muller_transform
The compiler returns:
error #6404: This name does not have a type, and must have an explicit
type. [GRND]
nor_ran_number1 = grnd(seed)
------------------^
I found this and understand that the function "grad" is not visible inside "Box_Muller_transform". However then I would expect the following code to produce the same error:
program test
INTEGER ::a=5, b
call sub(a,b)
write(*,*) b
end program
SUBROUTINE sub(a,b)
INTEGER, INTENT(in) ::a
INTEGER, INTENT(out) ::b
b = fun(a)
end subroutine sub
function fun(a)
INTEGER :: fun
INTEGER :: a
fun = a*a
end function fun
But this is working.
I would be very happy if someone could point out the difference and explain the simplest way to solve this problem.
Functions must have their return value defined. Since you are using implicit none in your first example, the type of the return value of grnd must be defined explicitly:
SUBROUTINE Box_Muller_transform (seed,nor_ran_number1,nor_ran_number2)
implicit none
INTEGER, INTENT(in) :: seed
REAL, INTENT(out) :: nor_ran_number1, nor_ran_number2
double precision :: grnd
nor_ran_number1 = grnd(seed)
nor_ran_number2 = grnd(seed)
end SUBROUTINE Box_Muller_transform
In the second example, you have not specified implicit none in sub, therefore fun is assumed to be of (implicit) type real. The compiler seems to silently cast this to integer.
I am getting a compiler error with the gfortran v4.9.0 compiler when using the private statement within a derived type class that is used to form a polymorphic object. Conversely, ifort v14.0.2 does compile this code successfully and the executable runs without error. The example source code below results in the following error message from gfortran:
ch2605.poly.f90:58.2:
s %x = shape_type(3)
1
Error: Assignment to an allocatable polymorphic variable at (1) is not
yet supported
If the private statement is commented out and the entire shape_module attributes/methods are made public, then gfortran compiles the code successfully. My 2 questions are:
1) Is the gfortran error message above correct in this case?
2) Is there anything I should do differently when attempting to make the contents of the base derived type shape_type private?
Note: I have adapted this example source code from ch2605_2.f90 on the fortranplus website.
! Test to demonstrate problem private attributesin polymorphic
! derived type using gfortan v4.9.0 (works OK in ifort v14.0.2)
module shape_module
implicit none
private ! *** Commenting out this statement works with gfortran v4.9.0
type shape_type
integer :: n_
character(len=2), allocatable, dimension(:) :: cname_
contains
procedure, pass(this) :: get_size
end type shape_type
interface shape_type
module procedure shape_type_constructor
end interface
interface assignment (=)
module procedure generic_shape_assign
end interface
public :: shape_type, generic_shape_assign
public :: shape_type_constructor, get_size ! *** Not even this works.
contains
type (shape_type) function shape_type_constructor(n)
implicit none
integer, intent (in) :: n
shape_type_constructor%n_ = n
allocate ( shape_type_constructor%cname_(n) )
end function shape_type_constructor
integer function get_size(this)
implicit none
class (shape_type), intent (in) :: this
get_size = size(this%cname_)
end function get_size
subroutine generic_shape_assign(lhs,rhs)
implicit none
class (shape_type), intent (out), allocatable :: lhs
class (shape_type), intent (in) :: rhs
allocate (lhs,source=rhs)
end subroutine generic_shape_assign
end module shape_module
module shape_wrapper_module
use shape_module
type shape_wrapper
class (shape_type), allocatable :: x
end type shape_wrapper
end module shape_wrapper_module
program ch2605_mod
use shape_module
use shape_wrapper_module
implicit none
type (shape_wrapper) :: s
s %x = shape_type(3)
print *, 'size = ', s%x%get_size()
end program ch2605_mod
Is it possible to pass real part of a complex array to a subroutine in Fortran without storing the real part in another array and pass that? e.g. instead of
Z = complex array;
X = real(Z)
call foo(X)
Do the following
Z = complex array
call foo(real(Z))
This gives me a compiler error! I am using an intel compiler ifort.
Sure, it works:
module testmod
implicit none
integer, parameter :: dp = kind(1.0d0)
contains
subroutine realsub(array)
real(dp), intent(in) :: array(:)
print *, array
end subroutine realsub
end module testmod
program testprog
use testmod
implicit none
complex(dp) :: array(3)
array(:) = [ (1.0_dp, 1.0_dp), (3.0_dp, 2.0_dp), (-1.0_dp, 3.0_dp) ]
call realsub(real(array))
end program testprog
program main
real, parameter :: a = 1
!real :: a
!a=1
res = func(a)
write(*,*) res
end program main
function func(a)
real, parameter :: b=a+1 !(*)
func = b
return
end function func
My compiler complains at the line marked (*). Is there a way to set the value of a constant with a value coming outside that function?
You can't declare "b" as a parameter since its value is not constant at compile time, since it depends on the function argument.
It is a good idea to use "implicit none" so that you are sure to declare all variables. Also to place your procedures into a module and "use" that module so that the interface is known to the caller. As in:
module my_funcs
implicit none
contains
function func(a)
real :: func
real, intent (in) :: a
real :: b
b = a + 1
func = b
return
end function func
end module my_funcs
program main
use my_funcs
implicit none
real, parameter :: a = 1
real :: res
res = func(a)
write(*,*) res
end program main
#M. S. B.'s answer is fine if run-time initialization is acceptable to you. If you really do want a Fortran parameter, which is set at compile time, then you can do it like this:
program main
implicit none
real, parameter :: a = 1.0
real :: res
res = func()
write(*,*) res
contains
function func()
real, parameter :: b = a + 1.0
real :: func
func = b
end function func
end program main
I suspect part of the confusion is due to differences in language. Often "parameter" is used to mean an argument of a function, but in Fortran it is never used that way. Instead it means something similar to const in C/C++. So, it is not clear to me from your question whether you really want a Fortran parameter or not.
In my example above, the parameter a is known inside func via host association, which is Fortran lingo for nested scopes. You can also do it with modules, via use association, but it is a bit more verbose:
module mypars
implicit none
real, parameter :: a = 1.0
end module mypars
module myfuncs
implicit none
contains
function func()
use mypars, only: a
real, parameter :: b = a + 1.0
real :: func
func = b
end function func
end module myfuncs
program main
use myfuncs, only: func
implicit none
real :: res
res = func()
print *, res
end program main