在fortran中编写一个原始二进制无符号32位整数



我有一个四字节整数,我想将其转换为无符号的32位整数,并作为原始二进制数据(little-endian(写入。根据此模式,此值将用作要在paraview中读取的.vtu文件中的偏移量https://www.paraview.org/pipermail/paraview/2007-October/006064.html我已经尝试过ZEXT和IAND函数,但没有成功,可能是因为我对C语言和C-fortran接口的了解非常基础。下面是我尝试做的草稿

use ISO_C_BINDING
...
INTEGER(kind=4), dimension(8):: offset=0
...
OPEN(newunit=vtu, action='write', access='stream', STATUS='new', form='unformatted', FILE=filename)
....
WRITE(vtu)char(95),ZEXT(offset(1),C_INT32_T),...
WRITE(vtu)ZEXT(offset(2),C_INT32_T),...
...

--编辑(01/05/2020(

SUBROUTINE print_vtu_binary_appended
USE DECLARE
use iso_fortran_env
IMPLICIT NONE
INTEGER(kind=int32) :: i, vtu, print_number=0
INTEGER(kind=int32), dimension(6) :: offset
character (len=24) :: folder
IF (step==0) then
call new_folder(folder)
END IF
offset(1) = 0
offset(2) = offset(1) + 4 + SIZEOF(preceding_position)
offset(3) = offset(2) + 4 + SIZEOF(preceding_velocity)
offset(4) = offset(3) + 4 + SIZEOF(radius)
offset(5) = offset(4) + 4
offset(6) = offset(5) + 4
!or
!offset(1) = 0
!offset(2) = offset(1) + 4 + 8*number_of_particles*3 !(double precision*no_particles*no_components)
!offset(3) = offset(2) + 4 + 8*number_of_particles*3
!offset(4) = offset(3) + 4 + 8*number_of_particles
!offset(5) = offset(4) + 4
!offset(6) = offset(5) + 4
OPEN(newunit=vtu, action='write', access='stream', STATUS='new', form='unformatted', FILE='./'//folder//'/'//TRIM(system_name)//itoa(print_number)//'.vtu')
WRITE(vtu)'<?xml version="1.0"?>'//NEW_LINE('A')
WRITE(vtu)'<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">'//NEW_LINE('A')
WRITE(vtu)'<UnstructuredGrid>'//NEW_LINE('A')
WRITE(vtu)'<Piece NumberOfPoints="'//itoa(number_of_particles)//'" NumberOfCells="0">'//NEW_LINE('A')
WRITE(vtu)'<Points>'//NEW_LINE('A')
WRITE(vtu)'<DataArray name="Position" type="Float64" NumberOfComponents="3" format="appended" offset="'//itoa(offset(1))//'">'//NEW_LINE('A')
WRITE(vtu)'</DataArray>'//NEW_LINE('A')
WRITE(vtu)'</Points>'//NEW_LINE('A')
WRITE(vtu)'<PointData>'//NEW_LINE('A')
WRITE(vtu)'<DataArray type="Float64" Name="Velocity" NumberOfComponents="3" format="appended" offset="'//itoa(offset(2))//'">'//NEW_LINE('A')
WRITE(vtu)'</DataArray>'//NEW_LINE('A')
WRITE(vtu)'<DataArray type="Float64" Name="Radius" format="appended" offset="'//itoa(offset(3))//'" >'//NEW_LINE('A')
WRITE(vtu)'</DataArray>'//NEW_LINE('A')
WRITE(vtu)'</PointData>'//NEW_LINE('A')
WRITE(vtu)'<Cells>'//NEW_LINE('A')
WRITE(vtu)'<DataArray type="Int32" Name="connectivity" format="appended" offset="'//itoa(offset(4))//'">'//NEW_LINE('A')
WRITE(vtu)'</DataArray>'//NEW_LINE('A')
WRITE(vtu)'<DataArray type="Int32" Name="offsets" format="appended" offset="'//itoa(offset(5))//'">'//NEW_LINE('A')
WRITE(vtu)'</DataArray>'//NEW_LINE('A')
WRITE(vtu)'<DataArray type="UInt8" Name="types" format="appended" offset="'//itoa(offset(6))//'">'//NEW_LINE('A')
WRITE(vtu)'</DataArray>'//NEW_LINE('A')
WRITE(vtu)'</Cells>'//NEW_LINE('A')
WRITE(vtu)'</Piece>'//NEW_LINE('A')
WRITE(vtu)'</UnstructuredGrid>'//NEW_LINE('A')
WRITE(vtu)'<AppendedData encoding="raw">'//NEW_LINE('A')
WRITE(vtu)char(95),offset(1),preceding_position
WRITE(vtu)offset(2),preceding_velocity
WRITE(vtu)offset(3),radius
WRITE(vtu)offset(4),offset(5),offset(6)
!a different way to write
!WRITE(vtu)char(95),offset(1),(preceding_position,i=1,number_of_particles)
!WRITE(vtu)offset(2),(preceding_velocity,i=1,number_of_particles)
!WRITE(vtu)offset(3),(radius,i=1,number_of_particles)
!WRITE(vtu)offset(4),offset(5),offset(6)
!another different way
!WRITE(vtu)char(95),offset(1),(preceding_position(i,1),preceding_position(i,2),preceding_position(i,3),i=1,number_of_particles)
!WRITE(vtu)offset(2),(preceding_velocity(i,1),preceding_velocity(i,2),preceding_velocity(i,3),i=1,number_of_particles)
!WRITE(vtu)offset(3),(radius,i=1,number_of_particles)
!WRITE(vtu)offset(4),offset(5),offset(6)
WRITE(vtu)NEW_LINE('A')//'</AppendedData>'//NEW_LINE('A')
WRITE(vtu)'</VTKFile>'
CLOSE(unit=vtu)
print_number = print_number + 1
END SUBROUTINE print_vtu_binary_appended

感谢Vladimir F的回答。然而,我仍然收到这个错误消息:

错误:在C:\bbd\ecd3383f\build\supuild\paraview\src\VTK\IO\XML\vtkXMLUnstructuredDataReader.cxx中,第466行vtkXMLUnstructuredGridReader(00000244BF849310(:无法从片段0中的点读取点数组。元素中的数据数组可能太短。

我认为问题出在我写偏移量的方式上(换句话说,Paraview无法识别有符号整数(。我测试了三种编写方法和两种计算偏移量的方法(如您在代码中所见(。我不知道出了什么问题。我做了一个类似的子程序来打印.vtu ASCII文件,一个.vtk二进制文件,我在这两方面都很成功。

Fortran整数是有符号的。但是,正整数在有符号和无符号中是相同的。所以,如果你的数字是正数,就没有理由使用任何函数。如果你有一个未格式化的流文件,并且你想写一个四字节的整数,你只需要做

use iso_fortran_inv
INTEGER(kind=int32):: number
open(newunit=vtu, action='write', access='stream', STATUS='new', form='unformatted', FILE=filename)
WRITE(vtu) number

仅此而已。如果您的数字足够小,则不涉及转换函数。

如果您的数字大于最大有符号32位值,这实际上取决于在此之前您在Fortran中所做的操作。你实际如何使用这个数字。

  • 如果它是一个负32位整数,并且您想将其写为无符号-同样,不涉及转换。只需写入有符号的数字,Paraview就会将其读取为无符号。

  • 如果您的Fortran代码使用较大的整数种类来表示Fortran中的正数,则必须进行转换。在这种情况下,您需要复制位模式,最好使用transfer()函数或旧的equivalence

这里有一个转换示例。我只是强调,只有当你使用一个更大的整数种类来将整数值表示为正数(即Fortran为正数(时,它才是必要的:

use iso_fortran_env
integer(int64) :: large
integer(int32) :: unsigned
integer(int32) :: tmp(2)    
large = 3000000000_int64
print '(z0)', large
tmp = transfer(large, tmp)     
unsigned = tmp(1)
print '(z0)', unsigned
end

输出是(在小端序机器上(:

> ./a.out 
B2D05E00
B2D05E00

不要使用int(kind=4),它不是可移植的Fortran:integer*4 vs integer(4(vs integer

相关内容

最新更新