9

I get the fortran runtime warning "An array temporary was created" when running my code (compiled with gfortran) and I would like to know if there is a better way to solve this warning.

My original code is something like this:

allocate(flx_est(lsign,3))
allocate(flx_err(lsign,3))
do i=1,lsign
call combflx_calc(flx_est(i,:),flx_err(i,:))
enddo

Inside the subroutine I define the variables like this:

subroutine combflx_calc(flx_est,flx_err)
use,intrinsic              :: ISO_Fortran_env, only: real64
implicit none
real(real64),intent(inout) :: flx_est(3),flx_err(3)

flux_est and flx_err vectors may change inside the subroutine depending on several conditions and I need to update their values accordingly.

Fortran does not seem to like this structure. I can solve it defining temporary variables:

tmp_flx_est=flx_est(i,:)
tmp_flx_err=flx_err(i,:)
call combflx_calc(tmp_flx_est,tmp_flx_err)
flx_est(i,:)=tmp_flx_est
flx_err(i,:)=tmp_flx_err

But it seems to me quite a silly way to fix it.

As you may see I'm not an expert with Fortran, so any help is more than welcome.

francescalus
  • 30,576
  • 16
  • 61
  • 96
cardogar
  • 359
  • 1
  • 4
  • 17
  • 2
    In what way is your "fix" fixing anything? The temporary is still there, you are just making it manually. – Vladimir F Героям слава Mar 04 '15 at 16:43
  • Not fixing, masking is better. I didn't see the potential harm of my initial approach so I just wanted to get rid of the warning – cardogar Mar 04 '15 at 16:57
  • I disagree that masking is better than fixing. If you wanted to mask you could simply not compile with runtime checking enabled. – casey Mar 04 '15 at 16:59
  • Most of often it is better to disable useless warning, than obfuscate the code, but it is your project. – Vladimir F Героям слава Mar 04 '15 at 16:59
  • I was requested to use the compilation flag for detecting warnings because I should not have any. I thought the warning was not dangerous, just minor compilation issue. But I now understand better the issue so I will try to really solve it. Thanks – cardogar Mar 04 '15 at 17:05
  • This problem may result in a performance decrease, but won't result in an incorrect output will it? – Matt Ellis Apr 12 '19 at 10:23

2 Answers2

15

One way is to pass an assumed shape array

real(real64),intent(inout) :: flx_est(:),flx_err(:)

the other is to exchange the dimensions of your array, so that you can pass a contiguous section of the 2D array.

call combflx_calc(flx_est(:,i),flx_err(:,i))

The problem is that the explicit size dummy arguments of your procedure (var(n)) require contiguous arrays. The assumed shape arrays can have some stride.

  • Indeed when I use assumed-shape arguments I get "Error: Explicit interface required for 'combflx_calc' at (1): assumed-shape argument". But exchanging dimensions implies quite a huge and tedious work though. Thanks for your ideas! – cardogar Mar 04 '15 at 17:09
  • It means what it says. You must have explicit interface. All procedures should be placed in a module. – Vladimir F Героям слава Mar 04 '15 at 17:11
  • I did: `interface subroutine combflx_calc(flx_est,flx_err) use,intrinsic :: ISO_Fortran_env, only: real64 real(real64),intent(inout) :: flx_est(:),flx_err(:) end subroutine combflx_calc end interface` It seems to work without warnings, do you think that's correct? – cardogar Mar 04 '15 at 17:19
  • 3
    Interface blocks are also possible, but modern Fortran really prefers modules. – Vladimir F Героям слава Mar 04 '15 at 17:19
  • I'm not familiar with the use of the modules for defining procedures. I have only use them to define variables that are going to be used/changed in several subroutines. Would you mind please to give me an example? – cardogar Mar 04 '15 at 17:25
  • 2
    http://stackoverflow.com/questions/11953087/proper-use-of-modules-in-fortran http://en.wikipedia.org/wiki/Fortran_95_language_features#Modules – Vladimir F Героям слава Mar 04 '15 at 17:28
14

Your array temporary is being created because you are passing a strided array to your subroutine. Fortran arrays are column major so the leftmost index varies fastest in an array, or better said, the leftmost index is contiguous in memory and each variable to the right is strided over those to the left.

When you call

call combflx_calc(flx_est(i,:),flx_err(i,:))

These slices are arrays of your 3-vector strided by the length of lsign. The subroutine expects variables of a single dimension contiguous in memory, which the variable you pass into it is not. Thus, a temporary must be made for the subroutine to operate on and then copied back into your array slice.

Your "fix" does not change this, it just not longer warns about a temporary because you are using an explicitly created variable rather than the runtime doing it for you.

Vladimir's answer gives you options to avoid the temporary, so I will not duplicate them here.

casey
  • 6,855
  • 1
  • 24
  • 37