PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
petsc_binary.py
Go to the documentation of this file.
1"""!
2@file petsc_binary.py
3@brief Reader for the PETSc binary Vec files PICurv checkpoints hold, shared by the generators.
4
5Not a command. `profile.gen` and `spectra.gen` import it from beside themselves, as
6`spectra.gen` and `ic.gen` import `periodic_spectral.py`.
7"""
8
9import os
10import struct
11
12#: PETSc's class id for a Vec, the first header word of a VecView binary file.
13PETSC_VEC_CLASS_ID = 1211214
14
15
16def read_petsc_vec_binary(path: str, numpy, index_bytes: int = 4, label: str = "field file"):
17 """!
18 @brief Read a real64 PETSc binary VecView payload.
19 @details The header's class id and count are PetscInt of `index_bytes`, the width of the
20 PETSc that wrote the file, which the file does not record. Either byte order is
21 accepted, with or without the class id; the file length must match exactly.
22 @param[in] path PETSc binary vector path.
23 @param[in] numpy The caller's numpy module.
24 @param[in] index_bytes Bytes of a PetscInt in the writing PETSc, 4 or 8.
25 @param[in] label How the caller names the file in errors.
26 @return NumPy array of scalar values.
27 """
28 if not os.path.isfile(path):
29 raise ValueError(f"{label} not found: {path}")
30 data = open(path, "rb").read()
31 word, code = index_bytes, "i" if index_bytes == 4 else "q"
32 if len(data) < 2 * word:
33 raise ValueError(f"{label} '{path}' is too short to be a PETSc Vec binary.")
34 candidates = []
35 for endian in (">", "<"):
36 _class_id, vec_size = struct.unpack(endian + 2 * code, data[:2 * word])
37 if vec_size > 0 and len(data) == 2 * word + vec_size * 8:
38 candidates.append((endian, vec_size, 2 * word))
39 (vec_size_no_class,) = struct.unpack(endian + code, data[:word])
40 if vec_size_no_class > 0 and len(data) == word + vec_size_no_class * 8:
41 candidates.append((endian, vec_size_no_class, word))
42 if not candidates:
43 raise ValueError(
44 f"{label} '{path}' does not match a PETSc real64 Vec binary with "
45 f"{index_bytes}-byte indices; a file from the other index width does not fit."
46 )
47 endian, vec_size, offset = candidates[0]
48 values = numpy.frombuffer(data, dtype=numpy.dtype(endian + "f8"), count=vec_size, offset=offset)
49 return values.astype(float, copy=False)
read_petsc_vec_binary(str path, numpy, int index_bytes=4, str label="field file")
Read a real64 PETSc binary VecView payload.