How to pass a Cray pointer into subroutine? - fortran

I pass a Cray pointer which be mapped with a variable into a Fortran subroutine. It is described as below:
program test
integer val
pointer (ptr_val, val)
print *, "1:", loc(val)
print *, "1:", ptr_val
CALL DPMALLOC(ptr_val, sizeof(val))
print *, "2:", loc(val)
print *, "2:", ptr_val
val = 999
call foo(val)
end program test
subroutine foo(val)
integer val
print *, "3:",val
print *, "3:", loc(val)
print *, "3:", ptr_val
call DPMALLOC(ptr_val, sizeof(val))
print *, "4:", ptr_val
print *, "4:", loc(val)
return
end subroutine foo
void dpmalloc_(void **data, int *size){
*data =(void *) malloc(*size);
printf("malloc\n");
}
Output:
1: 0
1 0
2: 30743328
2: 30743328
3: 999
3: 30743328
3: 7.82827652E-38
4: 7.82833033E-38
4: 30743328
Therefore, it seems I cannot use a global pointer in subroutine. How can I fix it?

As francescalus points you really should be always using IMPLICIT NONE. It is very very important. If you must don't have to care about strict FORTRAN77 compatibility, because Cray pointers are an extension anyway. So do use IMPLICIT NONE!
That will tell you that ptr_val was undefined in the subroutine.
Instead you should pass the pointer, not the array, and declare the pointer association again in the subroutine:
program test
implicit none
integer val
pointer (ptr_val, val)
print *, "1:", loc(val)
print *, "1:", ptr_val
CALL DPMALLOC(ptr_val, sizeof(val))
print *, "2:", loc(val)
print *, "2:", ptr_val
val = 999
call foo(ptr_val)
end program test
subroutine foo(ptr_val)
implicit none
integer val
pointer (ptr_val, val)
print *, "3:",val
print *, "3:", loc(val)
print *, "3:", ptr_val
call DPMALLOC(ptr_val, sizeof(val))
print *, "4:", ptr_val
print *, "4:", loc(val)
return
end subroutine foo
output:
> ./a.out
1: 0
1: 0
malloc
2: 10391632
2: 10391632
3: 999
3: 10391632
3: 10391632
malloc
4: 10391392
4: 10391392

Related

How can I make my program go back to a "main menu" after a subroutine?

I am making a physics calculator in Fortran and I have run into a problem. Recently I had some assistance with my code that makes it possible to do, say, a speed calculation, and then go back to the menu to do a time calculation. However, I just added 2 other settings (E= mc2 and current/charge/time), with another menu to choose which one you want to use. My current code (which I will input below) only takes you back to the calculation menu. How would I go about making it so that after you click a button you go back to the main menu?
module kinematics
implicit none
real :: t, d, s
contains
subroutine time_from_distance_and_speed()
print *, 'Input distance in metres'
read *, d
print *, 'Input speed in metres per second'
read *, s
t = d / s
print*, 'Time is ', s
end subroutine
subroutine distance_from_speed_and_time()
print *, 'Input speed in metres per second'
read *, s
print *, 'Input time in seconds'
read *, t
d = s * t
print*, 'Distance is ', d
end subroutine
subroutine speed_from_time_and_distance()
print *, 'Input distance in metres'
read *, d
print *, 'Input time in seconds'
read *, t
s = d / t
print *, 'Speed is ', s
end subroutine
end module
module electronics
implicit none
real :: Q, I, T
contains
subroutine charge_from_current_and_time()
print *, 'Input current in amps'
read *, I
print *, 'Input time in seconds'
read *, T
Q = I * T
print*, 'Charge is ', Q
end subroutine
subroutine current_from_charge_and_time()
print *, 'Input charge in coulombs'
read *, Q
print *, 'Input time in seconds'
read *, T
I = Q/T
print*, 'Current is ', I
end subroutine
subroutine time_from_current_and_charge()
print *, 'Input current in coulombs'
read *, Q
print *, 'Input charge in amps'
read *, I
T = Q/I
print*,'time is ', T
end subroutine
end module
module energy
implicit none
real :: e, m, c
contains
subroutine energy_from_mass_and_lspeed()
print *, 'Warning- speed of light rounded to 300000000'
read *,
print *, 'Input mass in kilograms'
read *, m
c = 300000000
e = m * c * c
print*, 'Energy is ', e
end subroutine
end module
program bike
use kinematics
use electronics
use energy
implicit none
integer :: gg, pp
print *, 'Press 0 for speed, distance, and time. Press 1 for current, charge and time. Press 2 for E= mc^2'
read *, pp
if ( pp == 0 ) then
do while(.true.)
print *, 'Press 1 for speed, 2 for distance, and 3 for time'
read *, gg
if(gg == 1) then
call speed_from_time_and_distance
else if(gg == 2) then
call distance_from_speed_and_time
else if(gg == 3) then
call time_from_distance_and_speed
end if
print *, 'Press 5 to exit the console, or press 4 to do another calculation'
read *, gg
if(gg== 5) then
exit
end if
end do
end if
if ( pp == 1 ) then
do while(.true.)
print *, 'Press 1 for charge, 2 for current, and 3 for time'
read *, gg
if(gg == 1) then
call charge_from_current_and_time
else if(gg == 2) then
call current_from_charge_and_time
else if(gg == 3) then
call time_from_current_and_charge
end if
print *, 'Press 5 to exit the console, or press 4 to do another calculation'
read *, gg
if(gg== 5) then
exit
end if
end do
end if
if ( pp == 2 ) then
do while(.true.)
call energy_from_mass_and_lspeed
print *, 'Press 5 to exit the console, or press 4 to do another calculation'
read *, gg
if(gg== 5) then
exit
end if
end do
end if
end program

How do I use modules correctly in a Fortran program?

I built a speed, distance, and time calculator. I thought that it would be cool if you could go back to the main menu and calculate time after your original calculation (as an example). How would I do this by using modules? Here are the modules I have created:
module menu
real :: s ! speed
real :: d ! distance
real :: t ! time
real :: gg ! this is how I am going to switch between distance, time, and speed
print *, 'Press 1 for speed, 2 for distance, and 3 for time'
read*, gg
end menu
module speed
print *, 'Input distance in metres'
read *, d
print *, 'Input time in seconds'
read *, t
s = d / t
print *, 'Speed is ', s
end speed
module stay or leave
print *, 'Press 4 to go back to menu, or press 5 to exit the console'
read *, gg
end stay or leave
module distance
print *, 'Input speed in metres per second'
read *, s
print *, 'Input time in seconds'
read *, t
d = s * t
print*, 'Distance is ', d
end distance
module time
print *, 'Input distance in metres'
read *, d
print *, 'Input speed in metres per second'
read *, s
t = d / s
print*, 'Time is ', s
end time
You are using module as a subroutine. A module is a collection of related subroutines, user types and other related data. There is no need to use modules in this example (at least not in the way it is shown above).
But if you had to use modules I have included an example below. The module definition contains the following subroutines
time_from_distance_and_speed()
distance_from_speed_and_time()
speed_from_time_and_distance()
and three common variables t, d, s used in the calculations. Although in general it not recommended re-using the same variables in different routines, this is done here for illustrative purposes to show how "global" variables can be defined in the module level.
Module
Here the module contains the variable definitions which are common to the procedures it contains. It also defines the three calculation processes.
module kinematics
implicit none
real :: t, d, s
contains
subroutine time_from_distance_and_speed()
print *, 'Input distance in metres'
read *, d
print *, 'Input speed in metres per second'
read *, s
t = d / s
print*, 'Time is ', s
end subroutine
subroutine distance_from_speed_and_time()
print *, 'Input speed in metres per second'
read *, s
print *, 'Input time in seconds'
read *, t
d = s * t
print*, 'Distance is ', d
end subroutine
subroutine speed_from_time_and_distance()
print *, 'Input distance in metres'
read *, d
print *, 'Input time in seconds'
read *, t
s = d / t
print *, 'Speed is ', s
end subroutine
end module
Program
Here the main program uses the module defined above and calls the appropriate method depending on the user input.
program bike
use kinematics
integer :: gg
do while(.true.)
print *, 'Press 1 for speed, 2 for distance, and 3 for time'
read*, gg
if(gg == 1) then
call speed_from_time_and_distance
else if(gg == 2) then
call distance_from_speed_and_time
else if(gg == 3) then
call time_from_distance_and_speed
end if
print *, 'Press 5 to exit the console, anything else will repeat'
read *, gg
if(gg== 5) then
exit
end if
end do
end program

Fortran - Jump other subroutine

I am trying to jump other subroutine in Fortran code. I used the return function but it is not working in some cases. Is there any way to jump to other subroutine. I made a simple example to define the problem. If the condition is in the same subroutine, I can use goto label but I need to jump different subroutine. If the condition is correct (case = .True.), I don't want to calculate that subroutine so I will skip that subroutine, I will start to use the new data. For example, if i=3 and case=true, the program shouldn't print a=8 in the 3rd loop and jump the do loop in subroutine abc.
----------------------------------------------
subroutine abc()
do i=1, 5
!if case is true, start to program from here.
call vector ()
end do
end subroutine
-------------------------------------
subroutine vector()
if (case = .True.)then
*****JUMP call vector in main program *****
print *,"skip and jump "
return
a= 8
print *, a
else
b= 9
print *, b
print *, "continue the process "
end if
end subroutine
------------------------------------------------
-----output should be-------
9
9
skip and jump
9
9

checking input type in fortran read statement

I have put a check in error made in the input as:
integer :: lsp
chksp:do
write(*,*) "#Enter Number"
read(*,*,iostat=istat)lsp
if (istat==0) then
exit chksp
else
write(*,*)"Number can only be integer. Re-enter!"
end if
end do chksp
The problem is, it can detect error if a character value in enteres, instead of a numeric value; but it cannot detect error, if a real value is entered, instead of a integer.
Any way to force it detect integer only?
NB: May be problem with ifort; gfortran is happy with the code.
You can specify the format to request an integer:
program enter_int
implicit none
integer :: ierror, intVal
do
write(*,*) "Enter an integer number"
read(*,'(i10)',iostat=ierror) intval
if ( ierror == 0 ) then
exit
endif
write(*,*) 'An error occured - please try again'
enddo
write(*,*) 'I got: ', intVal
end program
Then, providing a float fails.
Something like the following?
ian#ian-pc:~/test/stackoverflow$ cat read.f90
Program readit
Integer :: val
Integer :: iostat
val = -9999
Do
Read( *, '( i20 )', iostat = iostat ) val
If( iostat == 0 ) Then
Write( *, * ) 'val = ', val
Else
Write( *, * ) 'oh dear!!'
End If
End Do
End Program readit
ian#ian-pc:~/test/stackoverflow$ nagfor -o read read.f90
NAG Fortran Compiler Release 5.3.1(907)
[NAG Fortran Compiler normal termination]
ian#ian-pc:~/test/stackoverflow$ ./read
10
val = 10
10.0
oh dear!!
safs
oh dear!!
123dfs23
oh dear!!
^C
ian#ian-pc:~/test/stackoverflow$ gfortran -o read read.f90
ian#ian-pc:~/test/stackoverflow$ ./read
10
val = 10
10.0
oh dear!!
dsfs
oh dear!!
^C
ian#ian-pc:~/test/stackoverflow$

Fortran PAPIF_stop always reads 0

I have a simple program in fortran that uses PAPI APIs to read performance counter values. All APIs (PAPIF_start, PAPIF_stop etc.) all work correctly (meaning, returns PAPI_OK). However, the values that PAPIF_stop reads are always 0. I tried another profiling software on BG/Q to ensure that these values should not be 0. Any idea why this might be the case? This is my first ever attempt at writing a fortran code. So it may very well be a fortran issue that is not evident to me. Will appreciate any help.
Thanks!
--DE
c-----------------------------------------------------------------------
subroutine papi_add_events(event_set)
integer, intent(inout) :: event_set
include 'f77papi.h'
c create the eventset
integer check
integer*8 event_code
event_set = PAPI_NULL
call PAPIF_create_eventset(event_set, check)
if (check .ne. PAPI_OK) then
print *, 'Error in subroutine PAPIF_create_eventset'
call abort
end if
!event_code = PAPI_L1_DCM ! Total L1 Data Cache misses
call PAPIF_event_name_to_code('PAPI_FP_INS', event_code, check)
if (check .NE. PAPI_OK) then
print *, 'Abort After PAPIF_event_name_to_code: ', check
call abort
endif
call PAPIF_add_event(event_set, event_code, check)
if (check .NE. PAPI_OK) then
print *, 'Abort PAPIF_add_events1: ', check, ' ', event_code
call abort
endif
!event_code = PAPI_MEM_RCY ! Cycle stalled waiting for memory reads
call PAPIF_event_name_to_code('PAPI_TOT_CYC', event_code, check)
call PAPIF_add_event(event_set, event_code, check)
if (check .NE. PAPI_OK) then
print *, 'Abort PAPIF_add_events2: ', check, ' ', event_code
call abort
endif
call PAPIF_start(event_set, check)
if(check .ne. PAPI_OK) then
print *, 'Abort after PAPIF_start: ', check
call abort
endif
return
end
c-----------------------------------------------------------------------
subroutine papi_stop_counting(event_set, values)
integer, intent(in) :: event_set
integer*8, intent(inout) :: values(*) !shows an array
c Local variable
integer check
include 'f77papi.h'
! stop counting
call PAPIF_stop(event_set, values(1), check) !*Not sure if it should be values(1) or values*
if (check .ne. PAPI_OK) then
print *, 'Abort after PAPIF_stop: ', check
call abort
endif
return
end
c-----------------------------------------------------------------------
I am calling these subroutines from another function like this:
subroutine myfunction
integer event_set ! For papi
integer*8 values(50) !For reading papi values
call papi_lib_init ! *Not shown, but is present and works. *
call papi_add_events(event_set)
do_flops()
call papi_stop_counting(event_set, values)
print *, 'Value 1: ', values(1)
print *, 'Value 2: ', values(2)
return
end
The output I get is:
Value 1: 0
Value 2: 0
http://www.cisl.ucar.edu/css/staff/rory/papi/papi.php?p=bas
plz PAPIF_create_eventset first!