I am working with R, but need to do a lot of number crunching, which I want to do in fortran. I am relatively new to R and a newbie to fortran... I already have a working R program, which I would like to optimize. I created a Fortran program solving a system of ODE's, which I keep in a subroutine. I additionally use a module called aux.f90 to store the parameters and a function which creates a signal that is fed into the equations. This works as intended and the data is saved in a .txt file.
What I would like to do now is to create an R front-end that tosses the Fortran program the parameters, such as the length of the simulation or the number of steps used in the solution. Then Fortran does the heavy lifting, saves the results in the file and I can use R to visualize the data from the file. See the Fortran code below:
! The auxiliary module contains all parameters
module aux
implicit none
integer,parameter :: n = 2**8 ! number of steps
real(kind=4) :: jout = 0.5 ! for normal metabolism
real(kind=4) :: alp = 4.0 ! factor for growth
real(kind=4) :: bet = 1.0 ! benefit value
real(kind=4) :: etay = 0.1 ! cost value y
real(kind=4) :: etaz = 0.10 ! cost value z
real(kind=4) :: h = 3.0 ! Hill coefficient
real(kind=4) :: Kx = 0.07 ! saturation coefficient
real(kind=4) :: t1 = 0.0, t2 = 30.0 ! start and end point of the simulation
contains ! function f(t) to create a step signal
real(kind=4) function f(t)
implicit none
real(kind=4), intent(in) :: t ! taking time value
real(kind=4) :: tt
!real(kind=4), intent(out) :: s ! giving out the signal
real(kind=4) :: period = 5 ! defining the period length
tt = MODULO(t,period)
! Signal function
if (tt > 0.5*period) then
f = 1
else
f = 0
endif
end function
end module aux
! The program solving the ODE system and giving the output as a fileprogram ffl
program ffl
use aux ! Use module aux
implicit none
integer :: m,j ! iteration variable
real(kind=4), dimension(6) :: b =(/0.0, 0.2, 0.4, 0.6, 0.8, 1.0/) ! expression
real(kind=4) :: dt ! time resolution
real(kind=4), dimension(n) :: t ! time vector
real(kind=4), dimension(4) :: x_new, x_aux, y_new, y_aux, q0 ! vectors
! computing the time vector
dt=(t2-t1)/real(n) ! calculating time resolution
t(1) = t1 ! setting first time value to t1 = 0
do m = 1,n ! filling the time vector
t(m) = t(m-1)+dt
end do
open(unit = 10,file = 'ffl.txt', status = 'unknown')
do j=1,6
k = b(j)
! initial conditions
q0(1) = 0 ! x
q0(2) = k ! y
q0(3) = 0 ! z
q0(4) = 0 ! w
!open(unit = 10,file = 'ffl.txt', status = 'unknown')
x_new = q0 ! set initial conditions
write(10,*)t(1),x_new(1),x_new(2),x_new(3),x_new(4) ! saving data
do m = 2,n
! Solving with a second order method
call derivate(t(m-1),x_new,y_new) ! call the derivate routine
x_aux = x_new + dt*y_new
call derivate(t(m),x_aux,y_aux)
x_new = x_new + 0.5*dt*(y_new+y_aux)
write(10,*)t(m),x_new(1),x_new(2),x_new(3),x_new(4) ! saving data
end do
end do
close(10)
end program ffl
! The subroutine derivate gives the system of ODE's to be solved
subroutine derivate(time,y,z)
use aux ! Use module aux
implicit none
real(kind=4), intent(in) :: time ! input: time vector
real(kind=4), dimension(4), intent(in) :: y ! input: initial conditions vector
real(kind=4), dimension(4), intent(out):: z ! output: results vector
z(1) = f(time)-y(1) !dx/dt
z(2) = k+(1-k)*((1+Kx)*(y(1)**h))/((y(1)**h)+Kx)-y(2) !dy/dt
z(3) = ((1+Kx)*(y(1)**h)/((y(1)**h)+Kx)*((1+Kx)*(y(2)**h))/((y(2)**h)+Kx)-y(3)) !dz/dt
z(4) = f(time)*y(3)-etay*(k+(1-k)*((1+Kx)*(y(1)**h))/((y(1)**h)+Kx)) & !dw/dt
-etaz*(((1+Kx)*(y(1)**h))/((y(1)**h)+Kx)*((1+Kx)*(y(2)**h))/((y(2)**h)+Kx))
end subroutine derivate
I have read the "Writing R extensions" document, but did not find it very helpful...
NOW to the questions: Since R needs a Fortran subroutine, i would like to create a wrapper subroutine in fortran that makes use of my existing files, which I can then call from R. However, i can't find a way to create this wrapper subroutine in the first place. Is it even possible to call an actual program in a subroutine? I couldn't find anything helpful online.
A program is supposed to be linked as an executable, so you can't call it from a subroutine - or you call the executable (with SYSTEM in gfortran), but you could do that directly from R.
The easy way to call Fortran from R is the .Fortran R function, which calls a Fortran subroutine (not a function, nor a program).
The basic steps are :
compile a Fortran DLL, exporting the subroutines you need (of course they may be wrappers for other subroutines or functions)
put the DLL in a directory in your system path
from R, load the DLL with dyn.load
call your subroutine with .Fortran.
If you use gfortran, you may just install Rtools, which has everything you need. If you want to use another compiler, you may have some trouble, especially with names.
From your comment to user2188538's answer, I see you already know all these steps, but be very careful with symbol names. From the .Fortran help: Use .Fortran with care for compiled Fortran 9x code: it may not work if the Fortran 9x compiler used differs from the Fortran 77 compiler used when configuring R, especially if the subroutine name is not lower-case or includes an underscore. It is also possible to use .C and do any necessary symbol-name translation yourself.
Also, I suspect your wrapper subroutine should not reside inside a module, or you may have extra trouble with names. But this is only a limitation for the wrapper function, which must be visible from R.
You can check the exported names in your DLL (send objdump -x your.so to a file and look for exported symbols). And check also in R, with is.loaded("your.symbol"), after loading the DLL. Be aware that usually, gfortran appends an extra underscore to names, whereas it's not needed when you call .Fortran from R. As described above, you may use .C instead (but then, remember Fortran arguments are passed by reference).
To check that you understand the whole process, I suggest you test it on a trivial example, such as a unique subroutine mysub(x,y,z) that does only z=x+y. When this one runs, you can elaborate on it to call more complex routines.
edit
You should not use assumed-shape or deferred-shape arrays, when you pass arrays arguments from R to Fortran, but only assumed-size arrays, that is, the usual array passing in Fortran 77. This is because R knows only how to pass a pointer to raw data, whereas assumed-shape and deferred-shape need more information, and R does not know the data structure to do that.
For example, you can do that:
subroutine mysub(n, a)
real :: a(n, n)
...
end subroutine
But this will amost certainly fail:
subroutine mysub(a)
real :: a(:, :)
...
end subroutine
Also, you can't pass function arguments from R to Fortran, as that would need a special data structure for the callback (under the hood, R is a Scheme dialect, and it uses S-expressions). You may do that in C, through .C or .Call (see help for .Call and R Internals).
You can indeed call Fortran from R using the .Foreign function in the R base package (see ?.Foreign). For some clear examples on how to do this, see the following page on how to call Fortran (as well as C) from R: http://users.stat.umn.edu/~geyer/rc/
Related
How can I call from R a Fortran subroutine with a character argument? My attempt to do so does not work, although I am able to call Fortran subroutines with double precision arguments. For the Fortran code
subroutine square(x,x2)
double precision, intent(in) :: x
double precision, intent(out) :: x2
x2 = x*x
end subroutine square
subroutine pow(c,x,y)
character (len=255), intent(in) :: c
double precision, intent(in) :: x
double precision, intent(out) :: y
if (c == "s") then
y = x**2
else if (c == "c") then
y = x**3
else
y = -999.0d0 ! signals bad argument
end if
end subroutine pow
and R code
dyn.load("power.dll") # dll created with gfortran -shared -fPIC -o power.dll power.f90
x <- 3.0
foo <- .C("square_",as.double(x),as.double(0.0))
print(foo)
bar <- .C("pow_",as.character("c"),as.double(x),as.double(0.0))
print(bar)
The output from
C:\programs\R\R-3.6.1\bin\x64\rterm.exe --vanilla --slave < xcall_power.r
is
[[1]]
[1] 3
[[2]]
[1] 9
[[1]]
[1] "c"
[[2]]
[1] 3
[[3]]
[1] -999
When you use .C to call a Fortran subroutine the calling treats character arguments as being C-style char **. This is not compatible with the Fortran dummy argument of type character(len=255).
You have two 'simple' approaches available:
modify the Fortran subroutine to accept arguments looking like char **
use .Fortran instead of .C
Modifying the Fortran subroutine to use C interoperability with char ** is better the subject of a new question (for its breadth and being not specific to your R problem). In general, I prefer writing Fortran procedures to be used in R as exposing a C interoperable interface and .C or .Call. With what follows you may also come to that conclusion.
Even the R documentation is not optimistic about passing character arguments with .Fortran:
‘.Fortran’ passes the first (only) character string of a character vector as a C character array to Fortran: that may be usable as ‘character*255’ if its true length is passed separately. Only up to 255 characters of the string are passed back. (How well this works, and even if it works at all, depends on the C and Fortran compilers and the platform.)
You will need to read your documentation about argument passing conventions, such as that for gfortran (consult the appropriate version as these conventions may change).
With .Fortran and gfortran then with a procedure that is not C-interoperable you will need to pass a "hidden" argument to the Fortran procedure specifying the length of the character argument. That is true for explicit length characters (constant length, even length-1, or not) and assumed-length characters.
For gfortran before version 7, this hidden argument is of (R) type integer. Using pow of the question, or with assumed-length argument, we can try something like
bar <- .Fortran("pow", as.character("c"), as.double(x), as.double(0.0), 255L)
Note, however, that this is not standard and inherently not portable. Indeed, as janneb comments and the documentation linked above state, how you pass this hidden argument from R to a gfortran-compiled procedure depends on the version of gfortran used. Using 255L at the end probably won't work beyond gfortran 7. Instead you will need to pass the hidden argument as something matching an integer(c_size_t) (possibly a 64-bit integer). For compilers other than gfortran you may need to do something quite different.
It really is best to use a C-interoperable procedure either with argument interoperable with char ** (using .C) or char [] (using .Fortran). As I say, it's worth going for the first option here, as that leaves more flexibility (like longer characters, more portability, and more character arguments).
I'd like to turn a legacy Fortran code into modern Fortran compliant code, so I can turn on compiler warnings, interface checking, etc. At this stage I don't want to change the functionality, just make it work as close as possible to what it was, and still keep compilers happy.
My current problem is that the code at many places passes arrays of the wrong types, e.g. a real array to a subroutine that has an integer dummy argument. This is not a bug per se in the code, since it is intentional and it works as intended (at least in common configurations). Now, how could I do the same and while keeping the code compliant? Consider the following example:
program cast
implicit none
double precision :: a(10)
call fill_dble(a,10)
call print_dble(a,10)
call fill_int(a,10)
!call fill_int(cast_to_int(a),10)
call print_dble(a,10)
call print_int(a(1),10)
!call print_int(cast_to_int(a),10)
call print_dble(a(6),5)
contains
function cast_to_int(a) result(b)
use iso_c_binding
implicit none
double precision, target :: a(*)
integer, pointer :: b(:)
call c_f_pointer(c_loc(a(1)), b, [1])
end function
end program
subroutine fill_dble(b,n)
implicit none
integer :: n, i
double precision :: b(n)
do i = 1, n
b(i) = i
end do
end subroutine
subroutine print_dble(b,n)
implicit none
integer :: n
double precision :: b(n)
write(6,'(10es12.4)') b
end subroutine
subroutine fill_int(b,n)
implicit none
integer :: n, b(n), i
do i = 1, n
b(i) = i
end do
end subroutine
subroutine print_int(b,n)
implicit none
integer :: n, b(n)
write(6,'(10i4)') b
end subroutine
When I compile it and run it (gfortran 4.8 or ifort 18), I get, as expected:
1.0000E+00 2.0000E+00 3.0000E+00 4.0000E+00 5.0000E+00 6.0000E+00 7.0000E+00 8.0000E+00 9.0000E+00 1.0000E+01
4.2440-314 8.4880-314 1.2732-313 1.6976-313 2.1220-313 6.0000E+00 7.0000E+00 8.0000E+00 9.0000E+00 1.0000E+01
1 2 3 4 5 6 7 8 9 10
6.0000E+00 7.0000E+00 8.0000E+00 9.0000E+00 1.0000E+01
The first half of the real array is corrupted with integers (because integers are half the size), but when printed as integers the "right" values are there. But this is non-compliant code. When I try to fix it by activating the cast_to_int function (and disabling the calls without it) I get indeed something that compiles without warning, and with gfortran I get the same result. With ifort, however, I get:
1.0000E+00 2.0000E+00 3.0000E+00 4.0000E+00 5.0000E+00 6.0000E+00 7.0000E+00 8.0000E+00 9.0000E+00 1.0000E+01
1.0000E+00 2.0000E+00 3.0000E+00 4.0000E+00 5.0000E+00 6.0000E+00 7.0000E+00 8.0000E+00 9.0000E+00 1.0000E+01
0******** 0 5 6 7 8 9 10
6.0000E+00 7.0000E+00 8.0000E+00 9.0000E+00 1.0000E+01
which I can't understand. Moreover, ifort with -O0 crashes (and it doesn't with the other version).
I know the code is still not quite correct, because the pointer returned by cast_to_int is still of size 1, but I believe that should be a different problem.
What am I doing wrong, or how can I get ifort do what I want?
EDIT: Following #VladimirF's reply, I add, after implicit none:
subroutine fill_int(b,n)
!dec$ attributes no_arg_check :: b
integer :: n, b(n)
end subroutine
subroutine print_int(b,n)
!dec$ attributes no_arg_check :: b
integer :: n, b(n)
end subroutine
end interface
but compiling with warnings on still gives me an error:
$ ifort cast2.f90 -warn all
cast2.f90(17): error #6633: The type of the actual argument differs from the type of the dummy argument. [A]
call fill_int(a,10)
--------------^
cast2.f90(20): error #6633: The type of the actual argument differs from the type of the dummy argument. [A]
call print_int(a(1),10)
---------------^
compilation aborted for cast2.f90 (code 1)
Intel Fortran supports the !dec$ attributes no_arg_check directive. It instructs the compiler "that type and shape matching rules related to explicit interfaces are to be ignored".
"It can be applied to an individual dummy argument name or to the routine name, in which case the option is applied to all dummy arguments in that interface."
It should be applied to a module procedure (or an interface block), so you should move your functions and subroutines into a module.
Many other compilers have similar directives.
What is wrong about your code? As a rule of thumb, do not ever use any Fortran functions that return pointers. They are pure evil. Fortran pointers are completely different from C pointers.
When you do call fill_int(cast_to_int(a),10) what happens is that the expression cast_to_int(a) is evaluated and the result is an array. Now depending on the optimizations the compiler may choose to pass the address of the original pointer, but it may also create a copy of the result integer array and pass a copy to the subroutine.
Also, your array a does not have the target attribute, so the address used inside cast_to_int(a) is only valid inside the function and is not valid after it returns.
You should make the b inside the main program and just pass b instead of a. It will work similar to equivalence. Looking at the values stored as a different type will be not standard-conforming anyway. This form of type punning is not allowed.
I found a possible general solution that seems to work. The code I have to deal with looks something like this:
subroutine some_subroutine(a,b,c,d,...)
real a(*),b(*),c(*),d(*)
! many more declarations, including common blocks
!...
call other_subroutine(a,b(idx),c,...)
!...
end subroutine some_subroutine
! this typically in another file:
subroutine other_subroutine(x,y,z,...)
real x(*)
integer y(*)
logical z(*)
! other declarations and common blocks
! unreadable code with calls to other procedures
! not clear which which arguments are input and output
end subroutine other_subroutine
I now modify it to be:
subroutine some_subroutine(a,b,c,d,...)
real a(*),b(*),c(*),d(*)
! many more declarations, including common blocks
call inner_sub(b,c)
contains
subroutine inner_sub(b,c)
use iso_c_binding
real, target :: b(*),c(*)
integer, pointer :: ib(:)
logical, pointer :: lc(:)
!...
call c_f_pointer(c_loc(b(idx)),ib,[1]) ! or use the actual length if I can figure it out
call c_f_pointer(c_loc(c(1)),lc,[1])
call other_subroutine(a,ib,lc,...)
nullify(ib,lc)
!...
end subroutine inner_sub
end subroutine some_subroutine
leaving other_subroutine untouched. If I use directly the target attribute on the outer routine, I have to add an explicit interface to anything calling it, so instead I wrap the inner code. By using contains I don't need to pass all variables, just those that will be "punned". The c_f_pointer call should be done right before the problematic call, since index variables (idx in the example) could be in common blocks and changed in other calls, for example.
Any pitfalls, apart from those already present in the original code?
Generally speaking I want to rename allocatable variables in a derived type that are passed through subroutine arguments. Writing everything with 'derived%type_xx' is not so pleasant. Besides, I don't want to spend extra memory on copying the values of the derived type to a new variable which costs new allocated memory. Furthermore, I know allocatable arrays are preferred than pointers for many reasons. I try to define pointers to the allocatable variable, but failed. I tried this because I want to simplify my code, both to be readable and not to be too long. I wonder if there's a way of achieving the goal? Thanks.
Here's the demonstration code:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1) :: input
input%longname_1 = input%longname_1 + input%longname_2 ! Use one line to show what I mean
END SUBROUTINE
And here's what failed:
Module module_type
IMPLICIT NONE
TYPE type_1
REAL,ALLOCATABLE :: longname_1(:), longname_2(:)
END TYPE
END MODULE
!------------------------------------------------------------------------------------------
SUBROUTINE TEST(input)
USE MODULE module_type
IMPLICIT NONE
TYPE(type_1),TARGET :: input
REAL,POINTER :: a => input%longname_1 &
& b => input%longname_2
a = a + b ! much better for reading
END SUBROUTINE
It seems like a small issue, but I'd like to read my code without too much pain in the future. So what's the best option? Thanks a lot.
You can use the ASSOCIATE construct to associate a simple name with a more complex designator or expression.
You could also use the subobjects of the derived type as actual arguments to a procedure that carried out the operation.
You pointer approach failed because you had a rank mismatch - you were attempting to associate scalar pointers with array targets. You may also have had problems if an explicit interface to your procedure was not available in the calling scope. An explicit interface is required for procedures with dummy arguments with the TARGET attribute.
Use of pointers for this sort of simple name aliasing may reduce the ability of the compiler to optimize the code. Something like ASSOCIATE should be preferred.
Update: After #IanH made his comment, I have gone back to check: I was completely and utterly wrong on why your code failed. As he pointed out in his answer, the main issue is that pointer and target have to have the same rank, so you'd have to declare a and b as:
real, pointer :: a(:), b(:)
Secondly, before you can actually point these pointers to the targets, the targets have to be allocated. Here's an example that works:
program allocatable_target
implicit none
type :: my_type
integer, allocatable :: my_array(:)
end type my_type
type(my_type), target :: dummy
integer, pointer :: a(:)
allocate(dummy%my_array(10))
a => dummy%my_array
a = 10
print *, dummy%my_array
end program allocatable_target
If you have a Fortran 2003 compatible compiler, you can use associate -- which is specifically meant for this kind of issue. Here's an example:
program associate_example
implicit none
type :: my_type
integer, allocatable :: long_name_1(:), long_name_2(:)
end type my_type
type(my_type) :: input
integer :: i
allocate(input%long_name_1(100), input%long_name_2(100))
associate (a=>input%long_name_1, b=>input%long_name_2)
a = (/ (i, i = 1, 100, 1) /)
b = (/ (2*i+4, i = 1, 100, 1) /)
a = a + b
end associate
print *, input%long_name_1
end program associate_example
Inside the associate block, you can use a and b as a shortform for the declared longer named variables.
But other than that, I suggest you get an editor with proper code completion, then long variable names are not that much of an issue any more. At the moment I'm trying out Atom and am quite happy with it. But I have used vim with the proper expansions for a long time.
I need to implement a tree structure in Fortran for a project, so I've read various guides online explaining how to do it. However, I keep getting errors or weird results.
Let's say I want to build a binary tree where each node stores an integer value. I also want to be able to insert new values into a tree and to print the nodes of the tree. So I wrote a type "tree" that contains an integer, two pointers towards the children sub-trees and a boolean which I set to .true. if there are no children sub-trees:
module class_tree
implicit none
type tree
logical :: isleaf
integer :: value
type (tree), pointer :: left,right
end type tree
interface new
module procedure newleaf
end interface
interface insert
module procedure inserttree
end interface
interface print
module procedure printtree
end interface
contains
subroutine newleaf(t,n)
implicit none
type (tree), intent (OUT) :: t
integer, intent (IN) :: n
t % isleaf = .true.
t % value = n
nullify (t % left)
nullify (t % right)
end subroutine newleaf
recursive subroutine inserttree(t,n)
implicit none
type (tree), intent (INOUT) :: t
integer, intent (IN) :: n
type (tree), target :: tleft,tright
if (t % isleaf) then
call newleaf(tleft,n)
call newleaf(tright,n)
t % isleaf = .false.
t % left => tleft
t % right => tright
else
call inserttree(t % left,n)
endif
end subroutine inserttree
recursive subroutine printtree(t)
implicit none
type (tree), intent (IN) :: t
if (t % isleaf) then
write(*,*) t % value
else
write(*,*) t % value
call printtree(t % left)
call printtree(t % right)
endif
end subroutine printtree
end module class_tree
The insertion is always done into the left sub-tree unless trying to insert into a leaf. In that case, the insertion is done into both sub-trees to make sure a node has always 0 or 2 children. The printing is done in prefix traversal.
Now if I try to run the following program:
program main
use class_tree
implicit none
type (tree) :: t
call new(t,0)
call insert(t,1)
call insert(t,2)
call print(t)
end program main
I get the desired output 0 1 2 2 1. But if I add "call insert(t,3)" after "call insert(t,2)" and run again, the output is 0 1 2 0 and then I get a segfault.
I tried to see whether the fault happened during insertion or printing so I tried to run:
program main
use class_tree
implicit none
type (tree) :: t
call new(t,0)
call insert(t,1)
call insert(t,2)
write(*,*) 'A'
call insert(t,3)
write(*,*) 'B'
call print(t)
end program main
It makes the segfault go away but I get a very weird output A B 0 1 2673568 6 1566250180.
When searching online for similar errors, I got results like here where it says it might be due to too many recursive calls. However, the call to insert(t,3) should only contain 3 recursive calls... I've also tried to compile using gfortran with -g -Wall -pedantic -fbounds-check and run with a debugger. It seems the fault happens at the "if (t % isleaf)" line in the printing subroutine, but I have no idea how to make sense of that.
Edit:
Following the comments, I have compiled with -g -fbacktrace -fcheck=all -Wall in gfortran and tried to check the state of the memory. I'm quite new to this so I'm not sure I'm using my debugger (gdb) correctly.
After the three insertions and before the call to print, it seems that everything went well: for example when I type p t % left % left % right % value in gdb I get the expected output (that is 3). If I just type p t, the output is (.FALSE.,0,x,y), where x and y are hexadecimal numbers (memory addresses, I guess). However, if I try p t % left, I get something like a "description" of the pointer:
PTR TO -> (Type tree
logical(kind=4) :: isleaf
integer(kind=4) :: value
which repeats itself a lot since each pointer points to a tree that contains two pointers. I would have expected an output similar to that of p t, but I have no idea whether that's normal.
I also tried to examine the memory: for example if I type x/4uw t % left, I get 4 words, the first 2 words seem to correspond to isleaf and value, the last 2 to memory addresses. By following the memory addresses like that, I managed to visit all the nodes and I didn't find anything wrong.
The segfault happens within the printing routine. If I type p t after the fault, it says I cannot access the 0x0 address. Does that mean my tree is somehow modified when I try to print it?
The reason for your problems is the fact, that variables, which get out of scope, are not valid anymore. This is in contrast to languages like Python, where the number of existing pointers is relevant (refcount).
In your particular case, this means, that the calls to newleaf(left, n) and newleaf(right, n) set the values of left and right, resp., but these variables get ouf of scope and, thus, invalid.
A better approach is to allocate each leaf as it is needed (except the first one, since this is already allocated and will not get out of scope till the end of the program).
recursive subroutine inserttree(t,n)
implicit none
type (tree), intent (INOUT) :: t
integer, intent (IN) :: n
if (t % isleaf) then
allocate(t%left)
allocate(t%right)
call newleaf(t%left,n)
call newleaf(t%right,n)
t % isleaf = .false.
else
call inserttree(t % left,n)
endif
end subroutine inserttree
I saw this question:
Fortran dynamic objects
and the accepted answer made me question if I wrote the following function safely (without allowing a memory leak)
function getValues3D(this) result(vals3D)
implicit none
type(allBCs),intent(in) :: this
real(dpn),dimension(:,:,:),pointer :: vals3D
integer,dimension(3) :: s
if (this%TF3D) then
s = shape(this%vals3D)
if (associated(this%vals3D)) then
stop "possible memory leak - p was associated"
endif
allocate(vals3D(s(1),s(2),s(3)))
vals3D = this%vals3D
else; call propertyNotAssigned('vals3D','getValues3D')
endif
end function
This warning shows up when I run my code, but shouldn't my this%vals3D be associated if it was previously (to this function) set? I'm currently running into memory errors, and they started showing up when I introduced a new module with this function in it.
Any help is greatly appreciated.
I think I wasn't specific enough. I would like to make the following class, and know how to implement the class, safely in terms of memory. That is:
module vectorField_mod
use constants_mod
implicit none
type vecField1D
private
real(dpn),dimension(:),pointer :: x
logical :: TFx = .false.
end type
contains
subroutine setX(this,x)
implicit none
type(vecField1D),intent(inout) :: this
real(dpn),dimension(:),target :: x
allocate(this%x(size(x)))
this%x = x
this%TFx = .true.
end subroutine
function getX(this) result(res)
implicit none
real(dpn),dimension(:),pointer :: res
type(vecField1D),intent(in) :: this
nullify(res)
allocate(res(size(this%x)))
if (this%TFx) then
res = this%x
endif
end function
end module
Where the following code tests this module
program testVectorField
use constants_mod
use vectorField_mod
implicit none
integer,parameter :: Nx = 150
real(dpn),parameter :: x_0 = 0.0
real(dpn),parameter :: x_N = 1.0
real(dpn),parameter :: dx = (x_N - x_0)/dble(Nx-1)
real(dpn),dimension(Nx) :: x = (/(x_0+dble(i)*dx,i=0,Nx-1)/)
real(dpn),dimension(Nx) :: f
real(dpn),dimension(:),pointer :: fp
type(vecField1D) :: f1
integer :: i
do i=1,Nx
f(i) = sin(x(i))
enddo
do i=1,10**5
call setX(f1,f) !
f = getX(f1) ! Should I use this?
fp = getX(f1) ! Or this?
fp => getX(f1) ! Or even this?
enddo
end program
Currently, I'm running on windows. When I CTR-ALT-DLT, and view performance, the "physical memory usage histery" increases with every loop iteration. This is why I assume that I have a memory leak.
So I would like to repose my question: Is this a memory leak? (The memory increases with every one of the above cases). If so, is there a way I avoid the memory leak while still using pointers? If not, then what is happening, should I be concerned and is there a way to reduce the severity of this behavior?
Sorry for the initial vague question. I hope this is more to the point.
Are you really restricted to Fortran 90? In Fortran 2003 you would use an allocatable function result for this. This is much safer. Using pointer function results, whether you have a memory leak with this code or not depends on how you reference the function, which you don't show. If you must return a pointer from a procedure, it is much safer to return it via a subroutine argument.
BUT...
This function is pointless. There's no point testing the association status of this%vals3D` after you've referenced it as the argument to SHAPE in the previous line. If the pointer component is disassocated (or has undefined pointer association status), then you are not permitted to reference it.
Further, if the pointer component is associated, all you do is call stop!
Perhaps you have transcribed the code to the question incorrectly?
If you simply delete the entire if construct starting with if (associated(this%vals3D))... then your code may make sense.
BUT...
if this%TF3D is true, then this%vals3D must be associated.
when you reference the function, you must use pointer assignment
array_ptr => getValues3D(foo)
! ^
! |
! + this little character is very important.
Forget that little character and you are using normal assignment. Syntactically valid, difficult to pick the difference when reading code and, in this case, potentially a source of memory corruption or leaks that might go undetected until the worst possible moment, in addition to the usual pitfalls of using pointers (e.g. you need to DEALLOCATE array_ptr before you reuse it or it goes out of scope). This is why functions returning pointer results are considered risky.
Your complete code shows several memory leaks. Every time you allocate something that is a POINTER - you need to pretty much guarantee that there will be a matching DEALLOCATE.
You have a loop in your test code. ALLOCATE gets called a lot - in both the setter and the getter. Where are the matching DEALLOCATE statements?
Every time setX is called, any previously allocated memory for the x component of your type will be leaked. Since you call the function 10^5 times, you will waste 100000-1 copies. If you know that the size of this%x will never change, simply check to see if a previous call had already allocated the memory by checking to see if ASSOCIATED(this%x) is true. If it is, skip the allocation and move directly to the assignment statement. If the size does change, then you will first have to deallocate the old copy before allocating new space.
Two other minor comments on setX: The TARGET attribute of the dummy argument x appears superfluous since you never take a pointer of that argument. Second, the TFx component of your type also seems superfluous since you can instead check if x is allocated.
For the function getX, why not skip the allocation completely, and merely set res => this%x? Admittedly, this will return a direct reference to the underlying data, which maybe you want to avoid.
In your loop,
do i=1,10**5
call setX(f1,f) !
f = getX(f1) ! Should I use this?
fp = getX(f1) ! Or this?
fp => getX(f1) ! Or even this?
enddo
fp => getX(f1) will allow you to obtain a pointer to the underlying x component of your type (if you adopt my change above). The other two use assignment operators and will copy data from the result of getX into either f, or (if it is previously allocated) fp. If fp is not allocated, the code will crash.
If you do not want to grant direct access to the underlying data, then I suggest that the return value of getX should be defined as an automatic array with the size determined by this%x. That is, you can write the function as
function getX(this) result(res)
implicit none
type(vecField1D),intent(in) :: this
real(dpn),dimension(size(this%x,1)) :: res
res = this%x
end function