Chapter 26 — Key Takeaways (Visualization Output)

A one-page reference for writing data that ParaView, VisIt, gnuplot, and matplotlib can read.


The legacy VTK STRUCTURED_POINTS file — the five parts, in order

# vtk DataFile Version 3.0     <- line 1, EXACT (lowercase "vtk", case-sensitive)
<title / comment>               <- line 2, any text ≤ 256 chars (put provenance here)
ASCII                           <- storage: ASCII or BINARY
DATASET STRUCTURED_POINTS       <- grid type
DIMENSIONS nx ny nz             <-   number of POINTS per axis (nz=1 for 2-D)
ORIGIN  x0 y0 z0                <-   physical position of point (1,1,1)
SPACING dx dy dz                <-   physical gap between adjacent points
POINT_DATA (nx*ny*nz)           <- values live AT points; count MUST match
SCALARS temperature double 1    <-   array: name, type, components-per-point
LOOKUP_TABLE default            <-   color table (default = viewer chooses)
<one value per point>           <- x (i) fastest, then y (j), then z (k)

Rules worth memorizing

Rule Why
Line 1 is exact and case-sensitive: # vtk DataFile Version 3.0 # VTK or #vtk → ParaView rejects the file
POINT_DATA = nx*ny*nz, computed from the loop's own variables a mismatched count errors (too many) or silently shifts the field (too few)
Value order: do k; do j; do i; write u(i,j,k)i innermost VTK stores x-fastest; with i→x this is also Fortran column-major (contiguous)
DIMENSIONS counts points, not cells an nx×ny field has nx*ny points, not (nx-1)*(ny-1)
Finite-difference values are nodal → use POINT_DATA, not CELL_DATA the stencil approximates the Laplacian at a point
Zero-pad frame names (heat_000100.vtk) ParaView orders frames by lexical sort; padding makes it match numeric order

The writer (canonical signature — lives in heat_io)

subroutine write_vtk(field, filename, step)
  type(field_t),    intent(in) :: field        ! nx, ny, dx, dy, u(:,:)
  character(len=*), intent(in) :: filename      ! from frame_name(step)
  integer,          intent(in) :: step          ! recorded in the title line
  ! ... 10 header writes, then  do j; do i; write(iu,'(f0.6)') field%u(i,j)

The output loop in the solver's time march

do step = 0, n_steps
  if (mod(step, save_every) == 0) call write_vtk(field, frame_name(step), step)
  call step_field(field, alpha, dt)
end do

Which format, when

Want Write Read with
An animation of a field over time legacy .vtk per step (zero-padded) ParaView / VisIt (group → play)
Physical time on the ParaView slider a .pvd collection listing files + timestep ParaView (open the .pvd)
Compression / parallel per-rank pieces XML .vti (ImageData) / .pvti ParaView / VisIt
A quick heat map or line plot 3-column x y v, blank line per scan gnuplot splot … with pm3d
A NumPy array for a figure whitespace matrix, top row first numpy.loadtxtimshow
A publication figure the matrix, plus plot_heat.py matplotlib (savefig(dpi=300))

VTK dataset ladder (write the least you can)

STRUCTURED_POINTS / ImageData  regular box: origin+spacing+dims → values only   ← the heat plate
RECTILINEAR_GRID  / .vtr       axis-aligned, unequal spacing → coordinate arrays
STRUCTURED_GRID   / .vts       logical box, curved → every point's (x,y,z)
UNSTRUCTURED_GRID / .vtu       arbitrary mesh → every point AND every cell

Edit descriptors used (from Chapter 7)

Descriptor Produces Note
i0 integer, minimum width never overflows to *; right for point counts
i6.6 integer, 6 digits, zero-padded sortable frame numbers (frame_name)
f0.6 real, self-sizing, 6 decimals clean VTK values; leading zero for |x|<1 (gfortran 10+/F2018)
*(f8.3,1x) unlimited-repeat row one write emits a whole matrix row

Pitfalls

  • Case/spelling of # vtk DataFile Version 3.0 — exact, or rejected.
  • POINT_DATA count off by one — the field silently shifts; compute it, never hard-code it.
  • Transposed picture — you looped i outer; VTK needs i inner.
  • Frames play out of order — filenames not zero-padded.
  • gnuplot draws nonsense — missing the blank line between scans.
  • jet/rainbow colormap — invents false edges; use viridis/inferno/magma/plasma.
  • Autoscaled movie frames — colors mean different temperatures per frame; fix vmin/vmax.

Heat-solver piece added this chapter

write_vtk(field, filename, step) in heat_io, called every save_every steps with frame_name(step) → a zero-padded VTK time series you open in ParaView. Optional: a .pvd collection for physical time. This is the visualization the Chapter 38 capstone presents.