use reader, writer templates
due to the high level of code duplication across array rank (dimension), we use CMake or Meson configure_file() to simply inject this code for each dimension. This makes the program more robust. If we instead used Fortran select rank
we would still need a template, and it wasn't immediately clear there would be a benefit from this vs. the current approach.