Assignment to unallocated variable [duplicate] - fortran

This question already has answers here:
Automatic array allocation upon assignment in Fortran
(2 answers)
Closed 5 years ago.
A line in my code assigns an array to an unallocated array. I thought it was a bug but to my surprise it works just fine.
program test
implicit none
real, allocatable :: x(:,:)
real :: y(2,2)
y = 1.
x = y
print*, x
end program test
How does this work in terms of memory? The = operator here just allocates and assigns at the same time? Why is this possible and why is the compiler not complaining? I am using gfortran 5.4.0.

Since Fortran 2003, allocatable arrays will be automatically allocated (or re-allocated if the shape has changed) at run time. See for instance the Fortran 2003 features of the NAG compiler https://www.nag.com/nagware/np/r61_doc/nag_f2003.pdf or look for "realloc" in the documentation of gfortran https://gcc.gnu.org/onlinedocs/gfortran/Error-and-Warning-Options.html#Error-and-Warning-Options

That is correct, according to Section 7.2.1.3, "Interpretation of intrinsic assignments" of WD 1539-1, paragraph 3.

Related

Moment of inertia in fortran [duplicate]

This question already has answers here:
Modern Fortran equivalent of an action statement shared by nested DO and GO TO
(1 answer)
Function has no implicit type
(4 answers)
Closed 1 year ago.
I am trying to calculate the moment of inertia in fortran. The formula I am using is following: The code I am using:
program moment
implicit none
real :: cR,h,rho0,a,b,c,d,resultV,pi,resultMI,aMass,exactresMI,exactresV,r,res,z,rho
integer :: m,n
! rho0 = density, cR=capital R( radius),h= height )
rho0=10000
cR=0.05
h=0.1
a=0.d0
b=h
c=0.d0
d=cR
m=1000
n=1000
call cheb2(a,b,m,c,d,n,funV,res)
pi=4*datan(1.d0)
resultV=res*2*pi
exactresV= pi/3*cR**2*h
write(*,*)
write(*,*) "Numerical volume result =", resultV
write(*,*) "Exact volume result = ",exactresV
call cheb2(a,b,m,c,d,n,funV,res)
resultMI=res*2*pi
aMass=exactresV*rho0
exactresMI=3/10.*aMass*cR**2
write(*,*)
write(*,*) "Numerical Moment of Inertia result =", resultMI
write(*,*) "Exact Moment of Inertia result = ",exactresMI
end program
function funV(z,r)
if (r.gt.z*cR/h) then
rho=0.d0
else
rho=1.d0
end if
funV=rho*r
return
end
function funMI(z,r)
if (r.gt.z*cR/h) then
rho=rho0
else
rho=1.d0
endif
funMI=rho*r**3
return
end
include "CHEB.FOR"
Our instructor does not use "implicit none" , so I am really new to this operator. Out instructor gave us CHEB.FOR code for calculating 2 dimensional integrals. I am writing it here:
subroutine ch4xy(al,bl,cl,dl,f,ri)
implicit double precision (a-h,o-z)
common/ttxy/ t1,t2
dimension xx(4),yy(4)
c1=(al+bl)/2.d0
c2=(dl+cl)/2.d0
d1=(-al+bl)/2.d0
d2=(dl-cl)/2.d0
xx(1)=c1+d1*t1
xx(2)=c1+d1*t2
yy(1)=c2+d2*t1
yy(2)=c2+d2*t2
xx(3)=c1-d1*t1
xx(4)=c1-d1*t2
yy(3)=c2-d2*t1
yy(4)=c2-d2*t2
ss=0
do 3 i=1,4
do 3 j=1,4
ss=ss+f(xx(i),yy(j))
3 continue
ri=ss*d1*d2/4.d0
return
end
subroutine cheb2(a,b,m,c,d,n,f,r)
implicit double precision (a-h,o-z)
external f
common/ttxy/ t1,t2
t1=0.187592
t2=0.794654
hx=(b-a)/m
hy=(d-c)/n
rr=0
do 5 i=1,m
do 5 j=1,n
aa=a+(i-1)*hx
bb=aa+hx
cc=c+(j-1)*hy
dd=cc+hy
call ch4xy(aa,bb,cc,dd,f,ri)
rr=rr+ri
5 continue
r=rr
return
end
When I compile the file, a couple of errors and a warning appear:
CHEB.FOR:19:17:
19 | do 3 j=1,4
| 1
Warning: Fortran 2018 deleted feature: Shared DO termination label 3 at (1)
CHEB.FOR:36:11:
36 | do 5 j=1,n
| 1
Warning: Fortran 2018 deleted feature: Shared DO termination label 5 at (1)
momentOFinertia.f95:17:27:
17 | call cheb2(a,b,m,c,d,n,funV,res)
| 1
Error: Symbol 'funv' at (1) has no IMPLICIT type
First, I dont understand why funV is unclassifiable statement, it classifies as a function. Second, our instructor used some old operations which is apparently not valid in new fortran. I dont know what could replace "shared do".
The main problem (fixed by your edit)is that your code misses an end or end program at the end. Alternatively, you could put an end program after your functions and contains between the subroutine and the main program body. That would make the functions to be internal subprograms and would fix your other problem - no implicit type for the functions.
This - putting the functions inside the program as internal subprograms, allows the program to "see" them and then the program can correctly pass them to other procedures. Alternatively, you could make an interface block for them or declare their type and let them be external. See Why do I have to specify implicitly for a double precision return value of a function in Fortran? for more.
You also have a type mismatch. The code you got from your instructor uses double precision but your code uses the default real. You have to synchronize that. Update your code to double precision, either using double precision or using real kinds.
The compiler also warns you that your program is using deleted features. These features were deleted in modern revisions of the Fortran standards. However, the compiler remain largely backwards compatible and will compile the code including those features anyway, unless you request strictly a certain standard revision.
In this case two do-loops use one common continue statement
do 5 ...
do 5 ...
5 continue
This is not allowed and can be fixed by inserting another continue with another label or, better, by using end do.

Using varibles in subroutines without passing them in Fortran [duplicate]

This question already has answers here:
Host Association vs Use Association in Fortran
(1 answer)
What are the ways to pass a set of variable values through the subroutine to a function without common block?
(3 answers)
Closed 1 year ago.
I start to work on an older Fortran code that uses heavily the following "feature":
subroutine sample
integer*4 :: a, b
a = 1
b = 1
call increment(b)
print *, a, b ! Prints "2 2"
contains
subroutine increment(c)
implicit none
integer*4, intent(inout) :: c
c = c + 1
a = a + 1
end subroutine increment
end subroutine sample
On multiple occasions in the code, a variable from a subroutine is used in (sub)subroutine without passing it through arguments. Before someone points it out, I don't think this is a good coding paradigm, but it is a code I should work on, and I have to deal with it.
My problem is I cannot find in the Fortran language reference if this is actually legal. I never used this "feature" I thought it is not legal but this code works for 20 years compiled with GCC, intel Fortran, pgi, nvhpc without a problem. Very recently I tried to compile it with one-API, but on multiple occasions, the variables in (sub)subroutine contained rubbish data (but not all the time).
My question is if this is actually a legal thing to do? Is it only a part of other compilers dialects? Or is it an oneapi's bug?

Fortran retrieve matrix value outside of the bound without error [duplicate]

This question already has answers here:
Does Fortran have undefined behavior?
(3 answers)
I have a Fortran program that should give segmentation fault but it doesn't
(1 answer)
Closed 1 year ago.
I have a simple example of a code with two matrices, mat and mat2. mat is allocatable, the two matrices are constructed with 2X2 size.
program example
double precision , dimension(:,:), allocatable :: mat
double precision mat2(2,2)
integer nx,ny
nx=2
ny=2
allocate(mat(nx,ny))
mat(1,1)=1.d0
mat(1,2)=2.d0
mat(2,1)=3.d0
mat(2,2)=4.d0
mat2(1,1)=1.d0
mat2(1,2)=2.d0
mat2(2,1)=3.d0
mat2(2,2)=4.d0
write(*,*) mat(4,1)
write(*,*) mat2(4,1)
end program example
When compiling and executing the code using ifort (ifort version 2021.1), no error or warning is shown. The result is
4.00000000000000
4.00000000000000
When compiling and executing the code using gfortran, a warning appears :
main.f90:21.20:
write(*,*) mat2(4,1)
1
Warning: Array reference at (1) is out of bounds (4 > 2) in dimension 1
However, the execution gives the same result. I expected a segmentation fault error. This make debugging a complex program very difficult, since no error appear with this kind of error. Is this a normal behavior?

Why does not out-of bound access to an allocatable array cause an error? [duplicate]

This question already has answers here:
ifort and out of bound Index - Odd Behaviour
(2 answers)
Closed 5 years ago.
I do not understand why this code does not produce any segmentation fault. I was expecting some errors while compiling the code or in run-time, but it runs apparently correctly.
program alloc
implicit none
real, dimension(:,:), allocatable :: myVec
allocate(myVec(3,2))
myVec=1.
myVec(100,3)=10.
write(*,*) myVec(1,1)
return
end
Could somebody shed some light on this behaviour?
With gfortran, you can use the -fbounds-check compiler flag (or -C with ifort) in order to look for this kind of errors. When you compile your example with this option, the program produces:
Fortran runtime error: Index '3' of dimension 2 of array 'myvec' above upper bound of 2
As to why the program does not crash immediately, this question contains more details.

Intel Visual Fortran allocatable array of fixed length strings

Running Intel Parallel Studio 2015 and Visual Studio 2012. Fortran 2003 compatibility turned on.
Is there an issue with the following code because it caused a very confusing (for me at least) heap corruption error on my machine and I'm trying to find out if it is something I'm not understanding correctly or a compiler bug.
character(len=200), dimension(:), allocatable :: inFNs
real*8, dimension(:), allocatable :: times
inFNs = (/ "file1.dat", "file2.dat", &
"file3.dat", "file4.dat", &
"file5.dat", "file6.dat" /)
allocate(times(SIZE(inFNs))
!more code below
The code would crash without a stack trace during the allocation of times, and it would tell me that a heap corruption occurred in a window dialog in debug mode.
The way I determined there was an issue with inFNs was because the issue would occur during a later allocate call if I moved the times allocation to be above inFNs.
The error has seemed to go away (knock on wood) by changing the declaration line to:
character(len=:), dimension(:), allocatable :: inFNs
I'm sorting through another issue in my code before I can know for sure.
In Response to Duplicate Question:
This is not a duplicate of the question suggested for so many reasons that I'm truly confused as to the marking. This question deals specifically with the syntax of an allocatable array of character arrays as opposed to alloctable arrays in general. This question deal with a potential compiler bug with Intel Visual Fortran while the other is a question on differences between Intel Fortran and gFortran. This question deals with a silent crash and heap corruption while attempting to use a separate array whereas the other deals with whether or not the array in question is considered allocated after an operation.
Even more to the point the answer in the second question is irrelevant to the issue present in this question as that option being turned on or off doesn't affect the issue presented.
To say these two questions are identical is like saying I was encountering crash with the following code
real :: number
number = 4.d0
and someone asking another question asking why there is an issue with the following
real :: number
number = 4
call add3ToDouble(number)
subroutine add3ToDouble(a)
real*8 :: a
a = a + 3.d0
end subroutine add3ToDouble
and saying the answer to both being "Because ifort defaults to real(kind=4)"