Imagine a procedure that needs some work space to do its thing. If the user does not provide said work space, then the procedure allocates it internally. Otherwise, the work space passed by the user is employed.
What is the recommended pattern to implement this functionality? Is the approach below OK, or are there better options? Thanks.
module foo_mod
implicit none
contains
subroutine foo(n, res, work)
!! A procedure that needs a work array
integer, intent(in) :: n
!! problem dimension
real, intent(out) :: res
!! result
real, intent(inout), optional, target :: work(:)
!! user-supplied work space; intent(inout) is required in the 'true' application
real, pointer :: lwork(:) ! local (internal) work space
integer :: lenwork, i
lenwork = length_work(n)
if (present(work)) then
if (size(work) == lenwork) then
lwork => work
end if
else
allocate(lwork(lenwork))
end if
! Core part of the code
! in this case, something silly where the work array is used
lwork = 0
do i = 1, lenwork
lwork(i) = i
end do
res = sum(lwork)
! Pointer deallocation required (unlike allocatable arrays)
if (present(work)) then
lwork => null()
else
deallocate(lwork)
end if
end subroutine foo
integer function length_work(n)
integer, intent(in) :: n
length_work = n**2 + n**3 ! some long formula
end function
end module foo_mod
program test
use foo_mod
implicit none
integer, parameter :: n=2
real :: res
real, allocatable :: work(:)
! call without 'work'
call foo(n, res)
print *, "without 'work':", res
! call with 'work'
allocate(work(length_work(n)))
call foo(n, res, work=work)
print *, "with 'work':", res, work(size(work))
end program test