Напишите файл .vtu (paraview) с необработанными двоичными данными на Фортране. - PullRequest
1 голос
/ 03 мая 2020

Я пытаюсь написать подпрограмму Fortran, которая выводит файл .vtu с необработанными двоичными данными. Я написал с успехом двоичный файл .vtk и .vtu ascii, но в этом виде файла я не знаю, в чем проблема. Моя подпрограмма, сгенерированный файл .vtu и сообщение об ошибке paraview приведены ниже.

MODULE OUTPUT
IMPLICIT NONE
CONTAINS
function itoa(i) result(res)
  character(:),ALLOCATABLE :: res
  INTEGER,intent(in) :: i
  character(range(i)+2) :: tmp
  write(tmp,'(i0)') i
  res = trim(tmp)
end function
SUBROUTINE print_vtu_binary_appended(step,number_of_particles,system_name,position,velocity,radius)
use iso_fortran_env
implicit none
real(kind=real64), intent(in), dimension(number_of_particles,3) :: position, velocity
real(kind=real64), intent(in), dimension(number_of_particles) :: radius
integer(kind=int32), intent(in) :: step, number_of_particles
integer(kind=int32), dimension(6) :: offset
integer(kind=int32) :: vtu, print_number=0
character(len=*), intent(in) :: system_name

offset(1) = 0
offset(2) = offset(1) + 4 + SIZEOF(position)
offset(3) = offset(2) + 4 + SIZEOF(velocity)
offset(4) = offset(3) + 4 + SIZEOF(radius)
offset(5) = offset(4) + 4
offset(6) = offset(5) + 4
OPEN(newunit=vtu, action='write', access='stream', STATUS='new', form='unformatted', FILE='./'//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),position
WRITE(vtu)offset(2),velocity
WRITE(vtu)offset(3),radius
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
END MODULE OUTPUT
program test
use iso_fortran_env
use output
implicit none
integer(kind=int32) :: step=1, number_of_particles=2
real(kind=real64), dimension(2,3) :: position, velocity
real(kind=real64), dimension(2) :: radius
character(len=14) :: system_name='random_numbers'
position = reshape((/ 1.0754_real64, 2.0683_real64, 3.2479_real64, 4.08642_real64, 5.46906_real64, 6.36974_real64 /), shape(position))
velocity = reshape((/ 3.0754_real64, 7.0683_real64, 10.2479_real64, 72.08642_real64, 83.46906_real64, 22.36974_real64 /), shape(velocity))
radius = reshape((/ 0.0000754_real64, 0.00083_real64 /), shape(radius))
CALL print_vtu_binary_appended(step,number_of_particles,system_name,position,velocity,radius)
end program test

Пример сгенерированного xml файла:

<?xml version="1.0"?>
<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">
<UnstructuredGrid>
<Piece NumberOfPoints="8" NumberOfCells="0">
<Points>
<DataArray name="Position" type="Float64" NumberOfComponents="3" format="appended" offset="0">
</DataArray>
</Points>
<PointData>
<DataArray type="Float64" Name="Velocity" NumberOfComponents="3" format="appended" offset="196">
</DataArray>
<DataArray type="Float64" Name="Radius" format="appended" offset="392" >
</DataArray>
</PointData>
<Cells>
<DataArray type="Int32" Name="connectivity" format="appended" offset="460">
</DataArray>
<DataArray type="Int32" Name="offsets" format="appended" offset="464">
</DataArray>
<DataArray type="UInt8" Name="types" format="appended" offset="468">
</DataArray>
</Cells>
</Piece>
</UnstructuredGrid>
<AppendedData encoding="raw">
...
</AppendedData>
</VTKFile>

Ошибка в Paraview:

ОШИБКА: в C: \ bbd \ ecd3383f \ build \ superbuild \ paraview \ src \ VTK \ IO \ XML \ vtkXMLUnstructuredDataReader.cxx, строка 466 vtkXMLUnstructuredGridReader (000001DDC1DD5090): точки в массиве 0 не могут прочитать точки . Массив данных в элементе может быть слишком коротким.

1 Ответ

0 голосов
/ 04 мая 2020

Я думаю, что, вероятно, проблема вызвана конечной записью, я предлагаю использовать "char (10)" вместо intrinsi c "new_line".

В моей библиотеке ( https://github.com/szaghi/VTKFortran) Я использую

character(1), parameter :: end_rec = char(10) !< End-character for binary-record finalize.

РЕДАКТИРОВАТЬ

Извините за неправильное предположение, я предположил, что "char (10)" был более безопасным, потому что с «new_line» вы можете выбрать тип, и, таким образом, я предположил, что разное количество байтов завершится, мой плохой.

Читая ваш код, вы использовали «смещение» для отслеживания смещения добавленных данных и количества байтов каждого. dataarray в добавленном разделе. Я думаю, что это небезопасно: если вы измените определение смещения с типа int64 на тип int32, ваш тест будет работать в моей текущей архитектуре (GNU Fortran 9.3.0, Linux 4.19.0-6-amd64, paraview 5.8.0).

Обратите внимание, что ваша функция itao не имеет определения вида переданного аргумента "i", но вы передаете как int64, так и int32.

Я предлагаю разделить определение смещения и число байтов, но для небольшого файла определение смещения, так как int32, кажется, работает для меня.

...