- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Fortran experts,
I am currently attempting to remove commons from a legacy code in order to be able to dynamically allocate the corresponding sizes and then reduce the memory usage. I would like to know if there is a way to allocate a memory area using the malloc function and then to map several variables to this memory area. I would like to do something like:
real(8) Array(*) pointer (ptr, Array) C real(8) VAR1 real(8) VAR2 real(8) VAR3(NC,NC) C ptr = malloc((NC*NC+2)*sizeof(0.D0))
Question : How to map VAR1 to Array(1), VAR2 to Array(2) and VAR3 to Array(3:2*NC*NC-1) ?
I have tried using derived type with unions and maps but this not really satisfying especially for arrays of dynamic sizes (like VAR3(NC,NC) above).
Do you think that using typed pointer association could do the job ?
Best regards,
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why not just allocate(var1,var2,var3(nc,nc),stat=istat ) it will grab some memory of the correct size.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Given the improvements to dynamic memory allocation facility in the language since the Fortran 2003 standard, it's unclear why you'd do need to do such mapping. And app4619 mentioned, why not use standard language features rather than use malloc?
Things like operations shown in the code below are now fairly easy given the support of standard features in Intel Fortran 16.0:
program p !.. local variables integer, allocatable, target :: iarr(:) integer, pointer :: i1 integer, pointer :: i2 integer, pointer :: i3(:,:) integer :: nc integer :: i integer :: j iarr = [ (i, i=1,20) ] i1 => iarr(1) i2 => iarr(2) nc = 3 i3(1:nc,1:nc) => iarr(3:2+nc*nc) print *, " i1 = ", i1, " , iarr(1) = ", iarr(1) print *, " i2 = ", i2, " , iarr(2) = ", iarr(2) write(*,"(*(4x,g0))") "j","i","i3(j,i)","iarr(2+nc*(i-1)+j))" do i = 1, nc do j = 1, nc write(*,"(*(4x,g0))") j, i, i3(j,i), iarr(2+nc*(i-1)+j) end do end do i1 => null() i2 => null() i3 => null() deallocate( iarr, stat=i ) stop end program p
i1 = 1 , iarr(1) = 1 i2 = 2 , iarr(2) = 2 j i i3(j,i) iarr(2+nc*(i-1)+j)) 1 1 3 3 2 1 4 4 3 1 5 5 1 2 6 6 2 2 7 7 3 2 8 8 1 3 9 9 2 3 10 10 3 3 11 11 Press any key to continue . . .
But any such mapping would involve aliasing (Fortran standard POINTERs) and you would know the need to be most careful with their use.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The main problem is that I need to gather all the pointers into another structure and pass the pointer on this structure to an external application which in charge of the persistency and the management of the different set of variables corresponding to different calculations conditions and configurations
I had imagined that I could move all the variables belonging to a common block into a derived type that I will allocate at runtime and store the address of this derived type into the main structure. Nevertheless I was looking for another solution which would not require too many changes.
Anyway I am curious about the declaration you wrote. Is it possible to directly allocate a scalar variable ? I thought it was necessary that the variable as the allocatable attribute along with a dimension.
Best regards,
Phil,
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
netphilou31 wrote:
The main problem is that I need to gather all the pointers into another structure and pass the pointer on this structure to an external application which in charge of the persistency and the management of the different set of variables corresponding to different calculations conditions and configurations
I had imagined that I could move all the variables belonging to a common block into a derived type that I will allocate at runtime and store the address of this derived type into the main structure. Nevertheless I was looking for another solution which would not require too many changes.
Anyway I am curious about the declaration you wrote. Is it possible to directly allocate a scalar variable ? I thought it was necessary that the variable as the allocatable attribute along with a dimension.
Best regards,
Phil,
See this thread: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/593294
If your "external application" is not in Fortran and your Fortran code is "library" type of code, an option might be to let the external application handle the memory part, as discussed in the above thread. Note this is just a suggestion, especially because your original post involving malloc's and subsequent query suggest your expertise may be in C, C++ type of languages.
Re: "Is it possible to directly allocate a scalar variable ?", yes this is supported starting with the Fortran 2003 standard.
Re: " I am curious about the declaration you wrote.. I thought it was necessary that the variable as the allocatable attribute along with a dimension." which one? Are you curious about [fortran]integer, allocatable, target :: iarr(:)[/fortran] which is the same as [fortran]integer, allocatable, dimension(:), target :: iarr[/fortran]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yes you can allocate a scalar but it needs the allocatable attribute
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The snippet of code in Quote #1 is using essentially F77+extensions to achieve some purpose which is not completely clear. The f2003 standard has incorporated features which go massively beyond the capabilities you are going to need. Given that, perhaps the best thing is to dream, and to summarize what you would like the compiler to do if only it had essentially unlimited capabilities that could be applied to your problem. It likely is possible that your dreams could be translated into code, so dream big and be specific.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for all of the replies, I will study the suggestions and read the mentioned thread above.
Thanks again.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
netphilou31 wrote:
The main problem is that I need to gather all the pointers into another structure and pass the pointer on this structure to an external application which in charge of the persistency and the management of the different set of variables corresponding to different calculations conditions and configurations
From IVF documentation: Contents | Compiler Reference | Mixed Language Programming | Standard Fortran and C Interoperability
subroutine Simulation(alpha, beta, gamma, delta, arrays) BIND(C) use, intrinsic :: ISO_C_BINDING implicit none integer (C_LONG), value :: alpha real (C_DOUBLE), intent(inout) :: beta integer (C_LONG), intent(out) :: gamma real (C_DOUBLE),dimension(*),intent(in) :: delta type, BIND(C) :: pass integer (C_INT) :: lenc, lenf type (C_PTR) :: c, f end type pass type (pass), intent(inout) :: arrays real (C_FLOAT), ALLOCATABLE, target, save :: eta(:) real (C_FLOAT), pointer :: c_array(:) ... ! Associate c_array with an array allocated in C call C_F_POINTER (arrays%c, c_array, (/arrays%lenc/) ) ... ! Allocate an array and make it available in C arrays%lenf = 100 ALLOCATE (eta(arrays%lenf)) arrays%f = c_loc(eta) ... end subroutine Simulation
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
subroutine SendToManagement use YourModuleContainingArray use, intrinsic :: ISO_C_BINDING implicit none type, BIND(C) :: pass integer (C_INT) :: lenc, lenf type (C_PTR) :: c, f end type pass type (pass) :: passArrays passArrays%lenc = SIZE(ArrayCinModule) passArrays%c = C_LOC(ArrayCinModule) passArrays%lenf = SIZE(ArrayFinModule) passArrays%f = C_LOC(ArrayFinModule) call ManagementSend(passArrays) end subroutine SendToManagement
The above is a subset of #9 for sending some Fortran arrays to C
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Jim,
Seems to be interresting. I am currently on abusiness trip do I will study this asap.
For your information the external application is in Delphi but I think that it can handle C calling convention.
Thanks,
Phil.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have followed the discussion but I still do not fully understand the problem.
In any case:
- I use 'common' areas containing (in addition to scalars and arrays) pointers to dynamically allocated areas.
- I use to swap-out / swap-in their content either to files or other unstructured allocated areas with no problems and without any use of C/C++ interfaces.
- A common area when clearly structured provides a simple way to have many variables shared across the various subroutines.
If you provide an example of one of your 'common' areas the problem would be more clear.
Regards
![](/skins/images/872293744008A34B36F8ABF94A46CC66/responsive_peak/images/icon_anonymous_message.png)
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page