- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi All,
I'm trying to save a write a derived type that contains a pointer to an unformatted file for later reading. Below is a test version. The derived type sol in module dType is separate because I'm patching together various Fortran codes (F95 and F77, etc). The current version of the code "saves" sol1, but it seems to only save the pointer references, not their values, so when sol1 is deallocated, sol2 also becomes unreferenced. I'm sure my hack on the UDTIO is not correct.
Any help would be appreciated (I'm still trying to figure out UDTIO). Thanks
-joe
module dType implicit none type, public :: sol integer:: n real(8), pointer:: vec(:) end type sol end module dType module dType_io use dType implicit none contains subroutine write_sol(dtv, unit, iostat, iomsg) class(sol), intent(in) :: dtv integer, intent(in) :: unit integer, intent(out) :: iostat character(*), intent(inout) :: iomsg write(unit, iostat=iostat, iomsg=iomsg) dtv%n write(unit, iostat=iostat, iomsg=iomsg) size(dtv%vec) write(unit, iostat=iostat, iomsg=iomsg) dtv%vec end subroutine write_sol subroutine read_sol(dtv, unit, iostat, iomsg) class(sol), intent(inout) :: dtv integer, intent(in) :: unit integer, intent(out) :: iostat character(*), intent(inout) :: iomsg integer allocSize ! read is sol type, but allocate pointer space as needed. read(unit, iostat=iostat, iomsg=iomsg) dtv%n read(unit, iostat=iostat, iomsg=iomsg) allocSize allocate( dtv%vec(allocSize) ) read(unit, iostat=iostat, iomsg=iomsg) dtv%vec end subroutine read_sol end module dType_io program directAccess use dType implicit none integer, parameter :: dp = kind(0d0) type(sol):: sol1, sol2 integer solUnit, n, sze integer i sol1%n = 10 allocate( sol1%vec(sol1%n) ) sol1%vec = [ (real(i),i=1,sol1%n) ] open(newunit=solUnit, file='test.sol', form='unformatted', status='replace', action='write') write(solUnit) sol1 close(solUnit) open(newunit=solUnit, file='test.sol', form='unformatted', status='old', action='read') read(solUnit) sol2 deallocate( sol1%vec ); nullify(sol1%vec) ! this will cause sol2 to lose reference close(solUnit) stop end program directAccess
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The code doesn't have the necessary declarations of the generic bindings or interfaces that specify that read_sol and write_sol are the procedures implementing defined IO for your type - the code is missing something like
INTERFACE READ(UNFORMATTED) MODULE PROCEDURE read_sol END INTERFACE READ(UNFORMATTED)
and similarly for the WRITE(UNFORMATTED) interface.
The code should not compile without these.
You want to be using the very latest compiler (and perhaps even a bit later than that) if you are using UDDTIO.
(Edit to later add... I tried the current beta on the code, and I see it also fails to diagnose the body-text requirement for defined input/output of an object of derived type with pointer components.
Unrelated to UDDTIO, but I can't help myself - note that DEALLOCATION of a pointer also dissociates it - the nullify after the deallocate is just wearing your keyboard out prematurely.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should also modify your read and write routines to handle the case where the pointer is NULL.
e.g. On write, when pointer is null, write 0 for size and do not take size of the array.
On read, when allocSize is 0, nullify the pointer instead of allocating the pointer.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Ian and Jim. As always, very helpful!!! I also found Ian's previous post here https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/621651#comment-1864744 to be very useful.
BTW, I am using the latest Intel compiler and the interface statements solved the problem.
cheers,
-joe
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I guess I spoke too soon. It appears when the size of the pointer becomes large (> than around 16390 elements), the write works OK, but when the read is executed it produces the IO errors:
On Write: iostat = 0 iomsg = OK
On Read: iostat = 67 iomsg = input statement requires too much data, unit -130, file C:\Users\jvallino\Projec
The read error occurs when it attempts to: read(unit, iostat=iostat, iomsg=iomsg) dtv%vec(1:allocSize) As far as I can tell, IO limits are not being violated. I'm guessing it is something simple, but I'm currently baffled. Code is below.
module dType implicit none type, public :: sol integer:: n real(8), dimension(:), pointer:: vec end type sol end module dType module dType_io use dType implicit none interface read(unformatted) procedure read_sol end interface read(unformatted) interface write(unformatted) procedure write_sol end interface write(unformatted) contains subroutine write_sol(dtv, unit, iostat, iomsg) class(sol), intent(in) :: dtv integer, intent(in) :: unit integer, intent(out) :: iostat character(*), intent(inout) :: iomsg write(unit, iostat=iostat, iomsg=iomsg) dtv%n write(unit, iostat=iostat, iomsg=iomsg) size(dtv%vec) write(unit, iostat=iostat, iomsg=iomsg) dtv%vec(1:size(dtv%vec)) end subroutine write_sol subroutine read_sol(dtv, unit, iostat, iomsg) class(sol), intent(inout) :: dtv integer, intent(in) :: unit integer, intent(out) :: iostat character(*), intent(inout) :: iomsg integer allocSize ! read is sol type, but allocate pointer space as needed. read(unit, iostat=iostat, iomsg=iomsg) dtv%n read(unit, iostat=iostat, iomsg=iomsg) allocSize allocate( dtv%vec(allocSize) ) read(unit, iostat=iostat, iomsg=iomsg) dtv%vec(1:allocSize) end subroutine read_sol end module dType_io program testUDDTIO use dType use dType_io implicit none integer, parameter :: dp = kind(0d0) type(sol):: sol1, sol2 integer solUnit, n, sze character*80 iomsg integer i, iostat sol1%n = 16390 allocate( sol1%vec(sol1%n) ) sol1%vec = [ (real(i),i=1,sol1%n) ] iomsg = 'OK' open(newunit=solUnit, file='test.sol', form='unformatted', status='replace', action='write') write(solUnit, iostat=iostat, iomsg=iomsg) sol1 write(*,'(a,i4,2a)') 'On Write: iostat = ', iostat,' iomsg = ',trim(iomsg) close(solUnit) iomsg = 'OK' open(newunit=solUnit, file='test.sol', form='unformatted', status='old', action='read') read(solUnit, iostat=iostat, iomsg=iomsg) sol2 write(*,'(a,i4,2a)') 'On Read: iostat = ', iostat,' iomsg = ',trim(iomsg) deallocate( sol1%vec ) close(solUnit) stop end program testUDDTIO
The file produced during the write appears to be the correct size. Also, when sol1%n is large enough to cause the read error, only the first 1022 elements are read into dtv%vec.
Thanks Again!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hopefully your last code posting will reproduce the error for an Intel software support person. They should be able to investigate the issue with a reproducer. Please provide all the particulars: Compiler version, options used, 32/64-bit build, O/S.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You need to allocate sol2 before the read or have the compiler flag /standard-semantics for it to auto-allocate on read.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Andrew,
I believe the auto-allocate only applies to assignment (=) not reads. The option enabling this is realloc_lhs. For READ, the buffer argument is not an LHS entity.
Jim Dempsey
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Even if you allocate sol2%vec prior to reading (which would defeat the usefulness of UDDTIO it would seem) the problem still occurs when the size exceeds ~16390 elements. I did not try changing compiler options.
Using ifort 16.0.3.207 (build 20160415), x64 compiler
ifort /debug:full /Od /warn:interfaces /traceback /check:bounds /check:stack /libs:static /threads /dbglibs /Qmkl:parallel derivedTypeWriteRead.f90
Build and run on Windows 10.
On a Linux box running version 16.0.2 20160204 of ifort, compiled with just "ifort derivedTypeWriteRead.f90" the exact same problem occurs.
For now, I've dropped trying to use UDDTIO and just went the non object route.
Thanks for everyone's help!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your example works with /standard-semantics for 18000 which is what I tested.on an x32 build.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Actually I take that back, it only reads the first 1022 elements....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
OK, cause I just tried standard-semantics on both win and linux boxes and it did not work, but thanks for trying
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It is a compiler runtime bug. You can make it go away for the specific example if you increase things like the block size used for input/output (e.g. set FORT_BLOCKSIZE=256000 before running the program).
(Reallocation on assignment only applies when assigning to allocatables. There are no allocatables in the program.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thank Joe, Ian. I escalated the issues to Development.
(Internal tracking id: DPD200412514 - not diagnosing body-text requirement for defined input/output of an object of derived type with pointer components)
(Internal tracking id: DPD200412516 - Run-time iostat=67 reading > ~16390 elements w/UDDTIO)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
DPD200412514, the missed diagnosis, will be fixed in a future major release (not the one later this year).
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page