Is there a silver bullet? At some point you arrive at indirect addresing using arrays of integers.
If you don’t want to manage the complexity yourself you write/use a finite-element form compiler (e.g. FreeFEM, FEniCSx, FireDrake, libCEED).
The classic approach you see in Fortran codes is to have essentially a linked-list, with the pointers stored in a separate offset array:
Example
program main
implicit none
integer, parameter :: TRI03 = 5 !> Linear triangle
integer, parameter :: QUA04 = 9 !> Linear quad
integer :: npoin, nelem
integer, allocatable :: lconn(:), lcoff(:), ltype(:)
real, allocatable :: x(:), y(:)
npoin = 6
nelem = 3
! 2-----3-----5
! | v | |
! | v | |
! 0-----1-----4
x = [0.0, 1.0, 0.0, 1.0, 2.0, 2.0]
y = [0.0, 0.0, 1.0, 1.0, 0.0, 1.0]
! Connectivity
lconn = [0, 1, 2, 1, 3, 2, 1, 4, 5, 3] !> Connectivity
lcoff = [3, 6, 10] !> Offset
ltype = [TRI03, TRI03, QUA04] !> Element type
call dumpvtk(npoin,x,y,nelem,lconn,lcoff,ltype)
contains
subroutine dumpvtk(npoin,x,y,nelem,lconn,lcoff,ltype)
use, intrinsic :: iso_fortran_env, only: int8
integer, intent(in) :: npoin
real, intent(in) :: x(:), y(:)
integer, intent(in) :: nelem
integer, intent(in) :: lconn(:), lcoff(:), ltype(:)
character(len=512) :: buffer
character(len=1), parameter :: nl = new_line('a')
integer :: ivtu, i
open(newunit=ivtu,file="dump.vtu")
write(ivtu,'(A)') '<?xml version="1.0"?>'
write(ivtu,'(A)') '<VTKFile type="UnstructuredGrid" version="0.1" byte_order="LittleEndian">'
write(ivtu,'(A)') '<UnstructuredGrid>'
write(buffer,"('<Piece NumberOfPoints=',A,' NumberOfCells=',A,'>')") dq(npoin), dq(nelem)
write(ivtu,'(A)') trim(buffer)
write(ivtu,'(A)') '<Points>'
write(ivtu,'(A)') '<DataArray type="Float32" NumberOfComponents="3" format="ascii">'
write(ivtu,'(*(E12.5,1X))') [(x(i),y(i),0.0, i=1,npoin)]
write(ivtu,'(A)') '</DataArray>'
write(ivtu,'(A)') '</Points>'
write(ivtu,'(A)') '<Cells>'
write(ivtu,'(A)') '<DataArray type="Int32" Name="connectivity" format="ascii">'
write(ivtu,'(*(I0,1X))') lconn
write(ivtu,'(A)') '</DataArray>'
write(ivtu,'(A)') '<DataArray type="Int32" Name="offsets" format="ascii">'
write(ivtu,'(*(I0,1X))') lcoff
write(ivtu,'(A)') '</DataArray>'
write(ivtu,'(A)') '<DataArray type="UInt8" Name="types" format="ascii">'
write(ivtu,'(*(I0,1X))') int(ltype,int8)
write(ivtu,'(A)') '</DataArray>'
write(ivtu,'(A)') '</Cells>'
write(ivtu,'(A)') '</Piece>'
write(ivtu,'(A)') '</UnstructuredGrid>'
write(ivtu,'(A)') '</VTKFile>'
close(ivtu)
end subroutine
function dq(i)
integer, intent(in) :: i
character(len=:), allocatable :: dq
dq = '"'//itoa(i)//'"'
end function
function itoa(i)
integer, intent(in) :: i
character(len=:), allocatable :: itoa
character(len=32) :: tmp
write(tmp,'(I0)') i
itoa = trim(tmp)
end function
end program