CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > General Forums > Main CFD Forum

[Fortran] Passing array arguments in recursive function

Register Blogs Community New Posts Updated Threads Search

Like Tree8Likes
  • 2 Post By sbaffini
  • 1 Post By flotus1
  • 1 Post By flotus1
  • 1 Post By sbaffini
  • 1 Post By sbaffini
  • 1 Post By Gerry Kan
  • 1 Post By Gerry Kan

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   September 15, 2022, 02:18
Default [Fortran] Passing array arguments in recursive function
  #1
Senior Member
 
Gerry Kan's Avatar
 
Gerry Kan
Join Date: May 2016
Posts: 347
Rep Power: 10
Gerry Kan is on a distinguished road
Howdy Folks (and Fortran Connoisseurs):

Say, I have a recursive function that operates on an 1D array. Would it be more memory efficient to pass the entire array with optional bounds

Code:
recursive subroutine recurse ( x, i0, i1 )

! arguments

   integer, dimension(:) :: x
   integer, intent(in), optional :: i0, i1  ! default to 1, size(x) respectively

! code and termination conditions here

   call recurse ( x, i0, i1 )
   
end subroutine
Or can I pass only a subset the array indicated by the lower and upper bounds?

Code:
recursive subroutine recurse ( x )

! arguments

   integer, dimension(:) :: x

! internal variables

   integer :: i0, i1

! code and termination conditions here

   call recurse ( x(i0:i1) )
   
end subroutine
My assumption is that with method 1, the entire array is passed by reference and the recursive operation will be done in place. In the second method, an temporary instance of the array subset will be created for every level of recursion because of the bounds (I further assume that if I only change the lower bounds it will simply be a pointer shift so I am not using extra memory to store the array). Or is the compiler smart enough to recognize that and will pass the pointers at the start and end of the array?

Thanks in advance, Gerry.

P.S. - My current implementation uses the first method so there is no ambiguity here.
Gerry Kan is offline   Reply With Quote

Old   September 15, 2022, 04:12
Default
  #2
Senior Member
 
sbaffini's Avatar
 
Paolo Lampitella
Join Date: Mar 2009
Location: Italy
Posts: 2,152
Blog Entries: 29
Rep Power: 39
sbaffini will become famous soon enoughsbaffini will become famous soon enough
Send a message via Skype™ to sbaffini
As long as you pass contiguous array sections, the compiler should not create a temporary. I know this because I used to get runtime warnings for the cases where a temporary was created.

I have several recursive functions and I typically use approach 2. So, while this isn't a definitive test, I never get any warnings from those recursive calls.

You might still want to look at the shenanigans of the different ways to declare the input array, which I never remember after the implementation, but you should be fine with both approaches (still, for recursive functions, I prefer 2).

However, I still suggest you to make a test to have a definitive answer.
Gerry Kan and aerosayan like this.
sbaffini is offline   Reply With Quote

Old   September 15, 2022, 04:18
Default
  #3
Super Moderator
 
flotus1's Avatar
 
Alex
Join Date: Jun 2012
Location: Germany
Posts: 3,399
Rep Power: 46
flotus1 has a spectacular aura aboutflotus1 has a spectacular aura about
My guess is that it should not matter with 1D arrays (i.e. stride 1). Both implementations should™ pass by reference without creating a temporary.
To be sure, you can run your code with some debug flags enabled. At least gfortran has runtime warnings for creating temporary arrays.
The only way to be sure which is faster -if any- is to actually measure run times.
And it's probably a good idea to declare intent for array x.
Gerry Kan likes this.
flotus1 is offline   Reply With Quote

Old   September 15, 2022, 05:55
Default
  #4
Senior Member
 
Gerry Kan's Avatar
 
Gerry Kan
Join Date: May 2016
Posts: 347
Rep Power: 10
Gerry Kan is on a distinguished road
Quote:
Originally Posted by flotus1 View Post
And it's probably a good idea to declare intent for array x.
Your experience might by different, but I never had any good experience with INTENT(OUT) or INTENT(INOUT). When I do this the subroutine in question will screw up the data in x and I end up getting total nonsense.

Like I said, I might be doing it wrong.

Gerry.

Last edited by Gerry Kan; September 19, 2022 at 04:25.
Gerry Kan is offline   Reply With Quote

Old   September 15, 2022, 07:41
Default
  #5
Senior Member
 
sbaffini's Avatar
 
Paolo Lampitella
Join Date: Mar 2009
Location: Italy
Posts: 2,152
Blog Entries: 29
Rep Power: 39
sbaffini will become famous soon enoughsbaffini will become famous soon enough
Send a message via Skype™ to sbaffini
Quote:
Originally Posted by Gerry Kan View Post
Your experience might by different, but I never had any good experience with INTENT(OUT) or INTENT(INOUT). When I do this the subroutine in question will screw the data in x and I end up getting total nonsense.

Like I said, I might be doing it wrong.

Gerry.
This should be something of great concern to be soon investigated and fixed. If you understand their basic meaning (IN -> can't be modified, OUT -> allows modifications but don't count on preserving previous values, INOUT -> allows modifications, but will otherwise retain previous values), and I guess you do, then something wrong was happening in the code (with respect to the declared intents).

The only case where this would be ok (as there is no choice) is when the code must strictly adhere to F77
sbaffini is offline   Reply With Quote

Old   September 15, 2022, 12:04
Default
  #6
Super Moderator
 
flotus1's Avatar
 
Alex
Join Date: Jun 2012
Location: Germany
Posts: 3,399
Rep Power: 46
flotus1 has a spectacular aura aboutflotus1 has a spectacular aura about
I concur. If your code breaks when declaring the proper intent for passed variables, then it is already broken before adding intent.

The right intent is this:
The subroutine writes to these variables, but does not need the initial values -> intent(out)
The subroutine needs the initial values as they were passed, but does not write to them -> intent(in)
Both -> intent(inout)

It may sound like an unnecessary extra step, but it really helps avoiding bugs and unintended features.
naffrancois likes this.
flotus1 is offline   Reply With Quote

Old   September 19, 2022, 05:23
Default
  #7
Senior Member
 
Gerry Kan's Avatar
 
Gerry Kan
Join Date: May 2016
Posts: 347
Rep Power: 10
Gerry Kan is on a distinguished road
I am referring to passing INTENT(OUT) arrays as subroutine arguments.

Somehow when I pass an already allocated array, I end up getting results that don't make any sense. My only guess is that the INTENT(OUT) array is expected to be allocated inside the subroutine, and ignores the fact that it has already been allocated. Why it doesn't cause a run-time error but instead gives me garbage was beyond me.

I also tried this with INOUT but with no avail.

Gerry.
Gerry Kan is offline   Reply With Quote

Old   September 19, 2022, 05:33
Default
  #8
Senior Member
 
sbaffini's Avatar
 
Paolo Lampitella
Join Date: Mar 2009
Location: Italy
Posts: 2,152
Blog Entries: 29
Rep Power: 39
sbaffini will become famous soon enoughsbaffini will become famous soon enough
Send a message via Skype™ to sbaffini
Quote:
Originally Posted by Gerry Kan View Post
I am referring to passing INTENT(OUT) arrays as subroutine arguments.

Somehow when I passed an already allocated array, I end up getting results that don't make any sense. My only guess is that the INTENT(OUT) array is expected to be allocated inside the subroutine, and ignores the fact that it has already been allocated. Why it didn't cause a run-time error but instead gave me garbage was beyond me.

Gerry.
Yes indeed, that's in the standard, allocatable, intent(out) arguments get deallocated if they were previously allocated. When accessing their memory you are then accessing some unallocated part of memory, and by default it doesn't give run-time errors unless specific flags are on during compilation.
You want INOUT here (which, in general, doesn't hurt to use as default when you don't know exactly)

I've seen my solver run smoothly on a mesh which, with the proper compilation flags on the mesher, couldn't even be produced because of a floating point error (which also don't get signaled by default) so, the take home message is to have a very conservative set of compilation flags to use in testing before going to the production phase.

EDIT: if INOUT doesn't work neither, then the problem should be somewhere else, maybe another routine where the same happens?
Gerry Kan likes this.
sbaffini is offline   Reply With Quote

Old   September 19, 2022, 06:38
Default
  #9
Senior Member
 
Gerry Kan's Avatar
 
Gerry Kan
Join Date: May 2016
Posts: 347
Rep Power: 10
Gerry Kan is on a distinguished road
Paolo:

It is good to know that the official behavior matched my empirical observations.

For the instances that caused problems, I have managed to isolate it to my own subroutine by printing the values immediately before and after the offending subroutine call.

On the other hand, would INTENT(INOUT) have the same function of not defining the INTENT at all?

Gerry.
Gerry Kan is offline   Reply With Quote

Old   September 19, 2022, 06:53
Default
  #10
Senior Member
 
sbaffini's Avatar
 
Paolo Lampitella
Join Date: Mar 2009
Location: Italy
Posts: 2,152
Blog Entries: 29
Rep Power: 39
sbaffini will become famous soon enoughsbaffini will become famous soon enough
Send a message via Skype™ to sbaffini
Quote:
Originally Posted by Gerry Kan View Post
Paolo:

It is good to know that the official behavior matched my empirical observations.

For the instances that caused problems, I have managed to isolate it to my own subroutine by printing the values immediately before and after the offending subroutine call.

On the other hand, would INTENT(INOUT) have the same function of not defining the INTENT at all?

Gerry.
No intent is not really like intent(inout) as, for example, with no intent, you could pass in a parameter and that, without proper controls, would go unnoticed according to my understanding. But I'm sure there is some more formal way to tell apart the two cases.

If you check the input before the call to your routine (and it is ok) and after the call (and it is not) and there is no possible side effect from other parts of the code, then I don't honestly know what might be the issue here.

In these case one tries to reach a minimum working example of something that doesn't work
sbaffini is offline   Reply With Quote

Old   September 19, 2022, 06:58
Default
  #11
Senior Member
 
sbaffini's Avatar
 
Paolo Lampitella
Join Date: Mar 2009
Location: Italy
Posts: 2,152
Blog Entries: 29
Rep Power: 39
sbaffini will become famous soon enoughsbaffini will become famous soon enough
Send a message via Skype™ to sbaffini
Maybe it might have something to do with this:

https://www.cs.rpi.edu/~szymansk/OOF90/bugs.html#2
Gerry Kan likes this.
sbaffini is offline   Reply With Quote

Old   September 19, 2022, 10:21
Default
  #12
Senior Member
 
Gerry Kan's Avatar
 
Gerry Kan
Join Date: May 2016
Posts: 347
Rep Power: 10
Gerry Kan is on a distinguished road
Paolo:

I came across this a few years ago. Looking back it could be the case, since the subroutine in question only serves to modify part of the array.

Thanks, Gerry.
sbaffini likes this.
Gerry Kan is offline   Reply With Quote

Old   September 21, 2022, 13:10
Default
  #13
Senior Member
 
Gerry Kan's Avatar
 
Gerry Kan
Join Date: May 2016
Posts: 347
Rep Power: 10
Gerry Kan is on a distinguished road
Paolo:

On INTENT(INOUT) vs no INTENT, here is a little discussion that should clarify things.

https://stackoverflow.com/questions/...mitting-intent


Gerry.
sbaffini likes this.
Gerry Kan is offline   Reply With Quote

Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Point Set Profile User Function with Field Function Arguments wcj1n18 STAR-CCM+ 0 March 23, 2022 05:47
[blockMesh] Errors during blockMesh meshing Madeleine P. Vincent OpenFOAM Meshing & Mesh Conversion 51 May 30, 2016 10:51
[blockMesh] non-orthogonal faces and incorrect orientation? nennbs OpenFOAM Meshing & Mesh Conversion 7 April 17, 2013 05:42
Problem with compile the setParabolicInlet ivanyao OpenFOAM Running, Solving & CFD 6 September 5, 2008 20:50
Droplet Evaporation Christian Main CFD Forum 2 February 27, 2007 06:27


All times are GMT -4. The time now is 02:25.