passing logical variables to Fortran subroutines [duplicate] - fortran

I am trying to write a very simple function in Fortran (first-time user):
program Main
implicit none
integer function k(n)
integer, intent(in) :: n
k=n
end function k
end program Main
I get a bunch of errors:
integer function k(n)
1
Error: Syntax error in data declaration at (1)
integer, intent(in) :: n
1
Error: Unexpected data declaration statement at (1)
end function k
1
Error: Expecting END PROGRAM statement at (1)
k=n
1
Error: Symbol ‘k’ at (1) has no IMPLICIT type
k=n
1
Error: Symbol ‘n’ at (1) has no IMPLICIT type
What am I doing wrong? I'm using the last version of gfortran.

Any declared functions and subroutines local to the program block should be put after a contains statement, for example
program Main
implicit none
contains
integer function k(n)
integer, intent(in) :: n
k=n
end function k
end program Main
To give an example of a program using this you could have
program Main
implicit none
integer :: myLocalN
myLocalN = 2
print*, "My local N is ", myLocalN
print*, "The value of this squared is", sq(myLocalN)
contains
integer function sq(n)
integer, intent(in) :: n
sq=n*n
end function sq
end program Main

Related

Externally created parametrized derived type

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

How can I introduce an allocatable array which allocate in subroutine [duplicate]

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

Error: Unclassifiable statement when calling a function in Fortran

Why am I getting Error: Unclassifiable statement?
I use Fortran 95 and use compile Fortran online : http://rextester.com/l/fortran_online_compiler
program main
implicit none
real::p = 0
p=3**5 * exp(-3)/call fact(5)
print*,p
end program main
function fact(n)
implicit none
integer :: n
integer :: i
integer :: fact
if (n < 0)then
fact = 1
else
do i = 2, n, 1
fact = fact * i
end do
end if
end function fact
error:
p=3**5 * exp(-3)/call fact(5)
1 Error: Unclassifiable statement at (1)
You cannot call a function using the call statement, that is only for subroutines. You just use the function name
p=3**5 * exp(-3.0)/fact(5)
The argument to exp must be real (like -3.0).
You either have to put the function into a module (better) or make it internal (between contains and end program), or at least declare its type
integer :: fact
in the program that is calling it.

Invalid character in name `1t`

Here is my code:
!lab 4(a) solution by James Ney
program lab4_a
implicit none
integer :: n
real :: L,R
interface
function testFun (x)
real :: testFun
real, intent (in) :: x
end function testFun
end interface
print *, "lab 4(a) solution by James Ney"
print *, "Enter left and right ends of interval and number of subintervals"
read *, L,R,n
call MeshCalcs(testFun,L,R,n)
contains
subroutine MeshCalcs(F,a,b,n)
implicit none
integer, intent(in) :: n
real, intent(in) :: a,b
real :: del,fVal,xVal
integer :: 1t=0,gr=0,i
real ::F,sum=0,average
del=(b-a)/real(n)
do i=0,n
xVal=a+(i*del)
fVal=F(xVal)
sum=sum+fVal
end do
Average=sum/(n+1.0)
print "('Average is: ',f10.2)",average
do i=0,n
xVal=a+(i*del)
fVal=F(xVal)
if (fVal>average) then
gr=gr+1
else if(fVal<average) then
1t=1t+1
end if
end do
print "('number of function values greater than average =',i4)",gr
print "('number of function values less than average =',i4)",1t
end subroutine MeshCalcs
end Program Lab4_a
real function testFun(x)
real, intent (in) :: x
testFun=-(x-4.0)**2+9.0
end function testFun
and the errors I get when I try to compile with gfortran are:
lab4_2a.f90:27.20:
integer :: 1t=0,gr=0,i
1
Error: Invalid character in name at (1)
lab4_2a.f90:43.5:
1t=1t+1
1
Error: Non-numeric character in statement label at (1)
lab4_2a.f90:43.6:
1t=1t+1
1
Error: Invalid character in name at (1)
lab4_2a.f90:47.62:
print "('number of function values less than average =',i4)",1t
1
Error: Syntax error in PRINT statement at (1)
lab4_2a.f90:41.5:
gr=gr+1
1
Error: Symbol 'gr' at (1) has no IMPLICIT type
lab4_2a.f90:30.12:
do i=0,n
1
Error: Symbol 'i' at (1) has no IMPLICIT type
The first error message is quite clear (well, clear to those who already know this stuff). In this line
integer :: 1t=0,gr=0,i
the first variable declared has a name beginning with the digit 1. Fortran's rules require that all names begin with a letter or an underscore. I believe that this is common in other programming languages too. So the compiler barfs on 1t and the rest of the errors shown are probably direct consequences. Rename that variable and see what happens.

Declaring variables in function (Fortran)

I am trying to write a very simple function in Fortran (first-time user):
program Main
implicit none
integer function k(n)
integer, intent(in) :: n
k=n
end function k
end program Main
I get a bunch of errors:
integer function k(n)
1
Error: Syntax error in data declaration at (1)
integer, intent(in) :: n
1
Error: Unexpected data declaration statement at (1)
end function k
1
Error: Expecting END PROGRAM statement at (1)
k=n
1
Error: Symbol ‘k’ at (1) has no IMPLICIT type
k=n
1
Error: Symbol ‘n’ at (1) has no IMPLICIT type
What am I doing wrong? I'm using the last version of gfortran.
Any declared functions and subroutines local to the program block should be put after a contains statement, for example
program Main
implicit none
contains
integer function k(n)
integer, intent(in) :: n
k=n
end function k
end program Main
To give an example of a program using this you could have
program Main
implicit none
integer :: myLocalN
myLocalN = 2
print*, "My local N is ", myLocalN
print*, "The value of this squared is", sq(myLocalN)
contains
integer function sq(n)
integer, intent(in) :: n
sq=n*n
end function sq
end program Main