Binary Read/Write of Data Types with Allocatable Components in Fortran90+

后端 未结 1 517
醉话见心
醉话见心 2020-12-06 22:17

What is the best way to save a binary snapshot of the variable save which is made out of sample data type below?

program save_it

          


        
1条回答
  •  -上瘾入骨i
    2020-12-06 23:06

    If by Fortran90+ you mean you are happy with Fortran 2003, then there is the option of user-defined derived type IO. This allows you to wrap the extra bookkeeping required for the allocation in the write statement. I'll put example code at the bottom.

    If you don't want to use this feature, which is possibly because you don't have a compiler which supports it (I've tested with ifort 14), then you can mimic the bookkeeping easily enough.

    The crucial part is just sending out and reading back in the sizes and allocating the variables before the read.

    The code:

    module types
    
       type core
          integer, dimension(8) :: indx
       end type core 
    
       type sample
          integer :: a
          real*8, dimension(:), allocatable :: b
          type(core), dimension(:), allocatable :: c
        contains
          procedure write_sample
          procedure read_sample
          generic :: write(unformatted) => write_sample
          generic :: read(unformatted) => read_sample
       end type sample
    
       contains
    
         ! Unformatted writing for the sample derived type
         subroutine write_sample(dtv, unit, iostat, iomsg)
           class(sample), intent(in) :: dtv
           integer, intent(in) :: unit
           integer, intent(out) :: iostat
           character(*), intent(inout) :: iomsg
    
           integer i
    
           ! Write a record giving sizes for the allocation
           write(unit, iostat=iostat, iomsg=iomsg) SIZE(dtv%b), SIZE(dtv%c)
           write(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
                                                   (dtv%c(i)%indx, i=1,SIZE(dtv%c))
    
         end subroutine write_sample
    
         ! Unformatted reading for the sample derived type
         subroutine read_sample(dtv, unit, iostat, iomsg)
           class(sample), intent(inout) :: dtv
           integer, intent(in) :: unit
           integer, intent(out) :: iostat
           character(*), intent(inout) :: iomsg
    
           integer i
           integer sizeb, sizec
    
           ! We first have a record telling us the sizes of components
           read(unit, iostat=iostat, iomsg=iomsg) sizeb, sizec
           ! So we do the allocation
           allocate(dtv%b(sizeb), dtv%c(sizec))
           ! And then finally the reading.
           read(unit, iostat=iostat, iomsg=iomsg) dtv%a, dtv%b, &
                                                 (dtv%c(i)%indx, i=1,SIZE(dtv%c))
    
         end subroutine read_sample
    
    end module types
    
    program save_it
       use types
    
       implicit none
    
       integer i, unit_in, unit_out
    
       ! here it comes
       type(sample) :: save
       type(sample) :: save_test
    
       ! Define some values - using ifort don't forget to set the compile flag
       save%a = 14
       save%b = [(i*1., i=1, 10)]
       save%c = [core([(i, i=1,8)]), core([(i, i=11, 18)])]
    
       ! Write out the derived type
       open(newunit=unit_out, file='serial', form='unformatted', &
            status='replace', action='write')
       write(unit_out) save
       close(unit_out)
    
       ! Read in the derived type to a new one
       open(newunit=unit_in, file='serial', form='unformatted', &
            status='old', action='read')
       read(unit_in) save_test
       close(unit_in)
    
       ! Test, if we want to be certain
    
    end program save_it
    

    There's certainly a lot of work to be done on making it robust.

    0 讨论(0)
提交回复
热议问题