Common Interface for Structured VTK Datasets¶
Structured VTK datasets use a logical grid indexed by three integer coordinates. Their point and cell data are written as rectangular regions of that grid. The interface below is shared by the ImageData, RectilinearGrid, and StructuredGrid writers; see those sections for geometry definition, supported modes, and reader requirements.
File Creation and Management¶
The declaration of file and its geometry-writing method depend on the
VTK dataset type: vtkhdf_image_file, vtkhdf_rectilinear_file, or
vtkhdf_structured_file, from the corresponding *_file_type module.
call file%create(filename, [comm,] stat, errmsg [, mode] [, data_chunk_bytes])
Create a new file.
filename: path to the file to create. The recommended extension is.vtkhdf.comm: MPI communicator, omitted in serial builds. WithUSE_MPI_F08=ON(default), eitherintegerortype(MPI_Comm)is accepted. WithUSE_MPI_F08=OFF, onlyintegeris accepted.stat: output status code; zero indicates success.errmsg: allocated error message whenstat /= 0.mode: optional supported writer mode; defaults toVTKHDF_STATIC.data_chunk_bytes: optional positiveint64target chunk size in bytes for point and cell data; defaults to128*1024(128 KiB).
In MPI builds, all input arguments are identical on all ranks, and all
ranks return identical stat and errmsg values.
call file%flush()
Flush the file’s HDF5 buffers.
call file%close()
Finalize any open time step, close the file, and release resources. Users must call this explicitly; automatic Fortran finalization cannot perform collective cleanup.
Geometry Ordering¶
Supply the mesh geometry before writing point or cell data. In temporal files, the initial geometry may be supplied before or during the first time step, but must be supplied before that step is finalized. Complete all geometry writes before the first point/cell data write or the first step’s finalization. Static and fixed-mesh modes permit no subsequent geometry writes. In moving-mesh mode, each new step permits a replacement before that step’s point/cell writes; omitting geometry writes reuses the previous coordinates.
Point and cell data registration requires the logical grid dimensions. Where the geometry interface permits separate coordinate writes, registration may precede those writes.
Grid Indices and Data Layout¶
Global point bounds specify inclusive logical indices in each of three
directions. Point and cell indices, array_origin, and write_bounds
use kind int32. Cells are indexed by their lower-index corner.
For example, point indices 3:8 in one direction give cell indices
3:7 in that direction. In a singleton direction, points and cells use
the same single index.
Point and cell arrays use the following shapes, including all three spatial dimensions even for one- or two-dimensional grids:
Data |
Fortran shape |
|---|---|
Scalar |
|
Multicomponent |
|
The supported numeric kinds are int8, int32, int64, real32,
and real64 from iso_fortran_env. All writes to one dataset must have
the same type, kind, scalar/multicomponent interpretation, and component
count. The component count must be positive.
Unwritten point and cell data values default to quiet NaN for real kinds and zero for integer kinds. NaN makes missing real data distinguishable from a valid zero; it does not mark a location hidden (see below).
Warning
int8 data uses VTK/ParaView-compatible unsigned-byte storage. Use only
nonnegative values; negative int8 values are not a portable interface.
Static Point and Cell Data¶
type(vtkhdf_cell_data_handle) :: cell_var
type(vtkhdf_point_data_handle) :: point_var
call file%write_cell_data(name, array, array_origin [, write_bounds] [, attribute] [, handle])
call file%write_point_data(name, array, array_origin [, write_bounds] [, attribute] [, handle])
Create a static dataset and write one rectangular region per calling rank.
name: character name; see Common Conventions for naming rules.array: rank-3 scalar or rank-4 multicomponent data, as above.array_origin(3): global logical indices of the first spatial element ofarray, independently of its Fortran lower bounds.write_bounds(3,2): optional inclusive global bounds selecting the region to write. Column 1 gives lower bounds and column 2 gives upper bounds. The selection must lie within the global bounds for the association and within the global region represented by the array, fromarray_originthrougharray_origin + spatial_shape - 1, wherespatial_shapegives the array’s three spatial extents. If omitted, the entire array is written.attribute: optional character VTK role; see Common Conventions.handle: optional output handle of the corresponding cell or point data type, for subsequent writes to this dataset.
For example, with an actual array declared a(0:4,1,1),
array_origin=[10,0,0] places a(0,1,1) at global index (10,0,0).
A write_bounds selection from [11,0,0] to [13,0,0] writes
a(1:3,1,1).
Each call by name creates a new dataset. Repeating the name creates another dataset with a disambiguated name.
call file%write_cell_data(cell_var, array, array_origin [, write_bounds])
call file%write_point_data(point_var, array, array_origin [, write_bounds])
Write another region to the dataset identified by a handle. Placement and array arguments have the same meaning as in the calls by name.
Static point and cell data are supported in all structured writer modes. Define the mesh before creating or writing these datasets. In a temporal file, static datasets may also be written after time stepping begins, including after the last step has been finalized and before closing the file. Their values apply to every step, including earlier steps. Further writes through a static handle modify the same dataset for all steps; they do not create temporal replacements.
Region Ownership and Collective Writes¶
Each rank may contribute different rectangular regions, and may contribute multiple regions to one dataset. No Cartesian arrangement of ranks is required. All ranks must make the same sequence of calls for the same datasets, with matching numeric and component characteristics. Ranks with fewer regions must therefore supply empty contributions to complete that sequence.
For each dataset, the caller must supply data for every visible global point or cell index exactly once. Hidden locations may be left unwritten. Overlapping writes are forbidden; shared boundary points must have one writer. This rule also applies to boundary-condition regions included in the global grid. The library does not detect overlaps or incomplete coverage.
For an array containing halos, pass the full contiguous allocation and use
write_bounds to select its owned interior. Passing a noncontiguous array
section may cause a compiler-generated copy.
Empty Regions¶
To contribute an empty region, pass an array with zero extent in any spatial
dimension and omit write_bounds. Alternatively, supply write_bounds
with an upper bound less than its lower bound in any direction; the array
may then be nonempty.
array_origin is still required, but its values are not checked against
the global grid for an empty region. Use [0,0,0], even if zero lies outside
the grid. The array must still have the correct numeric type, kind, and
scalar/multicomponent interpretation, including the component count.
An empty first call still creates the dataset and returns a valid handle
when requested.
Temporal Point and Cell Data¶
type(vtkhdf_cell_data_handle) :: cell_var
type(vtkhdf_point_data_handle) :: point_var
cell_var = file%register_temporal_cell_data(name, mold [, attribute])
point_var = file%register_temporal_point_data(name, mold [, attribute])
Register a time-dependent dataset and return its opaque handle.
name: character name; see Common Conventions.mold: scalar for scalar data, or rank-1 array whose size is the number of components for multicomponent data. Its type, kind, and scalar/component interpretation determine those of later writes; its values are ignored.attribute: optional character VTK role, set at registration.
Define the logical grid before registration. Complete all registration before the first time step starts. Placement is supplied on each write.
call file%start_time_step(time)
Start a new time step with the scalar real32 or real64 time value
time. In MPI builds, only rank zero’s value is used; the call is collective.
call file%write_cell_data(cell_var, array, array_origin [, write_bounds])
call file%write_point_data(point_var, array, array_origin [, write_bounds])
Write a region of the temporal dataset for the current time step. The array and placement arguments have the same meaning as for static datasets, and must match the registered numeric and component characteristics. Multiple calls may assemble one complete dataset.
call file%finalize_time_step()
Complete the current time step after all its temporal writes.
Every registered point or cell dataset must be written in the first time step. In each subsequent step, the caller must either omit all writes to the dataset, reusing its previous complete value, or supply a complete replacement. An unwritten region in a replacement does not inherit values from the previous step. All-empty collective writes still begin a replacement; reuse requires omitting the calls on all ranks.
Region shapes and rank ownership may change between replacements. Every replacement must cover all visible locations exactly once before the step is finalized.
Warning
VTK 9.7.1 can return stale point/cell data when time steps are requested
out of order, including for fixed meshes. This is fixed in VTK 9.7.2
(ParaView 6.2.1). For affected readers, disable caching:
clear Use Cache in the ParaView reader properties and click Apply,
or call reader.SetUseCache(False) when using VTK in Python.
Field Data¶
See Field Data for the shared interface. Field data writes supply a complete value; they have no region-placement arguments and do not use the incremental point/cell writing rules.
Example: Static Data with Halos¶
After creating the file and defining a sufficiently large mesh, the following
calls create a cell dataset and contribute two regions. The first array contains
halos excluded by owned:
real(real64) :: pressure(0:5,0:4,1)
integer(int32) :: owned(3,2)
type(vtkhdf_cell_data_handle) :: pressure_var
! Interior subscripts (1:4,1:3,1) map to global indices (10:13,-2:0,0).
owned(:,1) = [10,-2,0]
owned(:,2) = [13,0,0]
call file%write_cell_data('Pressure',pressure, &
array_origin=[9,-3,0],write_bounds=owned,handle=pressure_var)
call file%write_cell_data(pressure_var,other_pressure, &
array_origin=other_origin,write_bounds=other_owned)