I have a third-part code in fortran 77, and I have written a subroutine in fortran 90 that I would like to interface to this code. I have found that the variables are not passed correctly from one subroutine to the other. I think the reason is that the definitions of double precision in the two programs is not compatible.
I want that the variable returned to f77 is a double precision. Which real definition shall I use in f90? I am using selected_real_kind(p=15,r=307)
EDIT:
I have changed the declaration to double precision in f90, and I have verified that double precision variables are passed correctly. The problem arises when I am passing allocatable arrays from f90 to f77
The arrays are originally allocated in code f77. then I allocate some allocatable arrays in f90 and then pass them to f77, but this is not working
f77 code:
program oldprog
double precision da(100)
call sub(da)
end
subroutine sub(da)
double precision da(*)
call mynewsub(da)
end
f90 code:
subroutine mynewsub(da)
implicit none
double precision, allocatable:: da(:)
allocate(da(100))
da = 1.0
end subroutine mynewsub
I was thinking to skip the allocation in mynewsub, but then I get SIGSEGV
Your mynewsub accepts the array as allocatable argument.
That requires explicit interface in Fortran 95, and is impossible in Fortran 90, not even speaking about FORTRAN 77 which does not have allocatable at all.
You cannot do this.
And in your main program
program oldprog
double precision da(100)
the array is static. It cannot be reallocated in any way in any version of Fortran, it is fixed forever.
You should think about making it allocatable everywhere an update relevant parts of your code to Fortran 95.
Related
I need in a program to pass some allocatable arrays to subroutines, and i need to know if the way I do it are in the standard or not.
If you know where I can search for the standard of fortran, Tell me please.
Here is a little code that will better explain than words
program test
use modt99
implicit none
real(pr), dimension(:), allocatable :: vx
allocate(vx(-1:6))
vx=(/666,214,558,332,-521,-999,120,55/)
call test3(vx,vx,vx)
deallocate(vx)
end program test
with the module modt99
module modt99
contains
subroutine test3(v1,v2,v3)
real(pr), dimension(:), intent(in) :: v1
real(pr), dimension(0:), intent(in) :: v2
real(pr), dimension(:), allocatable, intent(in) :: v3
print*,'================================'
print*,v1(1:3)
print*,'================================'
print*,v2(1:3)
print*,'================================'
print*,v3(1:3)
print*,'================================'
end subroutine test3
end module modt99
on screen, I get
================================
666.000000000000 214.000000000000 558.000000000000
================================
214.000000000000 558.000000000000 332.000000000000
================================
558.000000000000 332.000000000000 -521.000000000000
================================
So are the three ways of dummy arguments in subroutine test3 legal (in what version of fortran, 90, 95, 2003?) and are their behavior normal?
The first version passes the array slice to the subroutine. Note that boundary information are not passed along in this way, arrays are assumed to start at 1 and go to size(array).
The second way is just like the first one, but you manually set the lower boundary to 0, that's why printing v3(1:3) gives you the values with an offset of 1.
The third way passes all array information to the subroutine (including boundaries), hence the "correct" indexing. Passing allocatable arrays was introduced with Fortran 2003.
Apart from the fact that you have an aliasing issue (passing the same variable to three different dummy arguments), all three versions are legal.
You can find all documents of the standards here.
Especially, take a look at the Fortran 2003 Standard, Ch. 5.1.2.5 DIMENSION attribute to see the differences between assumed shape and deferred shape arrays in dummy arguments.
I am trying to understand how to use dynamic memory in f95.
I know that the following code in f2003 works.
program main
use pippo
implicit none
integer, allocatable :: arr(:)
call createDynamic(arr)
end program main
module pippo
contains
subroutine createDynamic(arr)
implicit none
integer, allocatable,dimension(:)::arr
integer :: i,n
n=10
allocate(arr(n))
do i=1,n
arr(i) = i
end do
end subroutine createDynamic
end module pippo
I would like to write a version in f95: what is the proper way to do it?
Your code us valid Fortran 95 + the ISO/IEC TR-15581 enhancements to allocatable arrays, which allowed allocatable dummy arguments.
In pure Fortran 95 you have to allocate the array in the main program or use pointers. However, it is year 2019, almost 2020. There is very little reason to use Fortran 95 without this TR. Or even not just using most of the widely supported Fortran 2008 features.
I'm having a problem with a fortran 77 project (Yes i know it's archaic, but my prof requres us to program in fixed form fortran)
So I'm having a problem with a subroutine, which should read an N dimension Vector, which should be a column. the code for this looks like: (its still an early draft for my homework, just trying to figure out how to call a subroutine the rest of the code will be done if i can compile this problem)
Program gauss
implicit double precision (A-H,O-Z)
!he directly asked for implicit typing
call Vread(V(N))
end program
Subroutine Vread(V,N)
Implicit double precision (A-H,O-Z)
dimension V(N)
read(*,*) (V(I),I=1,N)
return
end
So my problem is: If I try to compile it with gfortran gauss.exe -o gauss.f the compiler returns with error:
Type mismatch argument 'n' at(1); passed REAL(8) to Integer(4)
In your main program you write
call Vread(V(N)) ! this passes a rank-1 vector with N elements
but your subroutine is declared
Subroutine Vread(V,N) ! this requires 2 arguments
Change the call to
call Vread(V,N)
and let your professor know that the 21st Century arrived a while age. Note too that it is possible to write 21C Fortran in fixed-form. It doesn't make much sense, but might enable you to toe the line while developing in a more modern version of the language.
!he directly asked for implicit typing
I trust that you are in a jurisdiction where you do not pay directly for your education. If you are paying fees then demand more, you're being cheated.
I am using intel fortran compiler and intel mkl for a performance check. I am passing some array sections to Fortran 77 interface with calls like
call dgemm( transa,transb,sz_s,P,P,&
a, Ts_tilde,&
sz_s,R_alpha,P,b,tr(:sz_s,:),sz_s)
as evident, tr(:sz_s,:) is not contiguous in memory and the Fortran 77 interface is expecting a continuous block and creating a temporary for this.
What I was wondering is that will there be a difference if I create my temporary array explicitly in the code for tr and copy information from that temporary back and forth before and after the operation, or will that be the same as compiler itself creating the temporary from a performance point of view? I guess compiler will always be more efficient.
And of course any more suggestions to eliminate these temporaries are welcome.
One more point, If I use the Fortran 95 interface of the library apparently, with a similar call on a simpler test problem, no warning is issued for the creation of a temporary. Then I read in the manual of mkl that Fortran 95 interface uses assumed shape arrays which explains why temporaries are not created.
However at that point, I can not seem to use some support functions like timing routines.
Namely, intel mkl has some timing support functions but if I use them with the mkl_service routine like below then I get 'This name does not have a type, and must have an explicit type' error for dsecnd. Any idea for this problem is also welcome. A simple example for this is given as
program dgemm95_test
! some modules for Fortran 95 interface
use mkl_service
use mkl95_precision
use mkl95_blas
!
implicit none
!
double precision, dimension(4,3) :: a
double precision, dimension(6,4) :: b
double precision, dimension(5,5) :: r ! result array
double precision, dimension(3,2) :: dummy_b
!
character(len=1) :: transa
character(len=1) :: transb
!
double precision :: alpha, beta, t1, t2, t
integer :: sz1, sz2
! initialize some variables
alpha = 1.0
beta = 0.0
a = 2.3
b = 4.5
r = 0.0
transa = 'n'
transb = 'n'
dummy_b = 0.0
! Fortran 95 interface
t1 = dsecnd()
call gemm( a, b(4:6,1:3:2), r(2:5,3:4),&
transa, transb, alpha, beta )
t2 = dsecnd()
!
write(*,*) r
dummy_b = r(2:4,4:5)
!
end program dgemm95_test
The temporary is absolutely necessary when passing your array section to an assumed size array dummy argument, which the old routines use, because the array section is not contiguous in memory.
You can of course make your own temporary arrays. Whether it will be faster or not depends on many factors. Among others the important thing is whether the temporary is allocated on the stack or on the heap. The Intel Fortran compiler is capable of both, there are compiler switches to control the behavior (-heap-arrays n) and it can depend on the array size. Stack allocation is much faster and it is usually the default. Automatic arrays, which you might use for your own temporary are allocated on the stack by default too. Be careful with large arrays on the stack, you can easily overflow it and cause a crash.
I would suggest you to make a performance test and use the simpler variant if it is not too slow. Probably it will be the Fortran 95 interface, but you should measure the times, really.
As for the timing, MKL manual page for second()/dsecnd() states you must includemkl_lapack.fi and doesn't speak about any Fortran95 interface. You could get away declaring it external double precision too, but I would use the include. Or use system_clock() as a portable standard Fortran 95.
everyone
I have a Fortran90 program, and the variables are in double precision or complex*16, now I have to write another program whose variables are in real or complex, and all other things are the same as the original program.
The straightforward way is to rewrite every declaration, but I'm wondering if there are other simpler ways to achieve this, I'm using gfortran as the compiler.
Thanks
Probably the cleanest (althoug not the easiest) way would be to rewrite your program to have adjustable precision for the variables:
program test
implicit none
integer, parameter :: rp = kind(1.0d0)
real(rp) :: myreal
complex(rp) :: mycomplex
By setting the parameter rp (real precision) to kind(1.0) instead of kind(1.0d0) you can switch from double to single. Alternatively, with fortran 2003 compatible compilers you can also use the names real64 and real32 after invoking the iso_fortan_env module. (UPDATE: it needs a fortran 2008 compatible compiler, not fortran 2003, see the comment of IanH).