sdfr 1.4.8__py3-none-win_amd64.whl → 1.4.10__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
sdfr/SDF.py CHANGED
@@ -15,11 +15,21 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- import ctypes as ct
19
- import numpy as np
20
- import struct
21
- from enum import IntEnum
22
- from .loadlib import sdf_lib
18
+ """Constants and types for representing the blocks contained in an SDF file."""
19
+
20
+ import ctypes as _c
21
+ import numpy as _np
22
+ import struct as _struct
23
+ import re as _re
24
+ import io as _io
25
+ import hashlib as _hashlib
26
+ import tarfile as _tarfile
27
+ import gzip as _gzip
28
+ import os as _os
29
+ from enum import IntEnum as _IntEnum
30
+ from ._loadlib import sdf_lib as _sdf_lib
31
+ from typing import Dict as _Dict
32
+ from typing import Any as _Any
23
33
 
24
34
  # try:
25
35
  # import xarray as xr
@@ -30,92 +40,99 @@ from .loadlib import sdf_lib
30
40
  # got_xarray = False
31
41
 
32
42
 
33
- # Enum representation using ct
34
- class SdfBlockType(IntEnum):
35
- SDF_BLOCKTYPE_SCRUBBED = -1
36
- SDF_BLOCKTYPE_NULL = 0
37
- SDF_BLOCKTYPE_PLAIN_MESH = 1
38
- SDF_BLOCKTYPE_POINT_MESH = 2
39
- SDF_BLOCKTYPE_PLAIN_VARIABLE = 3
40
- SDF_BLOCKTYPE_POINT_VARIABLE = 4
41
- SDF_BLOCKTYPE_CONSTANT = 5
42
- SDF_BLOCKTYPE_ARRAY = 6
43
- SDF_BLOCKTYPE_RUN_INFO = 7
44
- SDF_BLOCKTYPE_SOURCE = 8
45
- SDF_BLOCKTYPE_STITCHED_TENSOR = 9
46
- SDF_BLOCKTYPE_STITCHED_MATERIAL = 10
47
- SDF_BLOCKTYPE_STITCHED_MATVAR = 11
48
- SDF_BLOCKTYPE_STITCHED_SPECIES = 12
49
- SDF_BLOCKTYPE_SPECIES = 13
50
- SDF_BLOCKTYPE_PLAIN_DERIVED = 14
51
- SDF_BLOCKTYPE_POINT_DERIVED = 15
52
- SDF_BLOCKTYPE_CONTIGUOUS_TENSOR = 16
53
- SDF_BLOCKTYPE_CONTIGUOUS_MATERIAL = 17
54
- SDF_BLOCKTYPE_CONTIGUOUS_MATVAR = 18
55
- SDF_BLOCKTYPE_CONTIGUOUS_SPECIES = 19
56
- SDF_BLOCKTYPE_CPU_SPLIT = 20
57
- SDF_BLOCKTYPE_STITCHED_OBSTACLE_GROUP = 21
58
- SDF_BLOCKTYPE_UNSTRUCTURED_MESH = 22
59
- SDF_BLOCKTYPE_STITCHED = 23
60
- SDF_BLOCKTYPE_CONTIGUOUS = 24
61
- SDF_BLOCKTYPE_LAGRANGIAN_MESH = 25
62
- SDF_BLOCKTYPE_STATION = 26
63
- SDF_BLOCKTYPE_STATION_DERIVED = 27
64
- SDF_BLOCKTYPE_DATABLOCK = 28
65
- SDF_BLOCKTYPE_NAMEVALUE = 29
66
-
67
-
68
- class SdfGeometry(IntEnum):
69
- SDF_GEOMETRY_NULL = 0
70
- SDF_GEOMETRY_CARTESIAN = 1
71
- SDF_GEOMETRY_CYLINDRICAL = 2
72
- SDF_GEOMETRY_SPHERICAL = 3
73
-
74
-
75
- class SdfStagger(IntEnum):
76
- SDF_STAGGER_CELL_CENTRE = 0
77
- SDF_STAGGER_FACE_X = 1
78
- SDF_STAGGER_FACE_Y = 2
79
- SDF_STAGGER_FACE_Z = 3
80
- SDF_STAGGER_EDGE_X = 4
81
- SDF_STAGGER_EDGE_Y = 5
82
- SDF_STAGGER_EDGE_Z = 6
83
- SDF_STAGGER_VERTEX = 7
84
-
85
-
86
- class SdfDataType(IntEnum):
87
- SDF_DATATYPE_NULL = 0
88
- SDF_DATATYPE_INTEGER4 = 1
89
- SDF_DATATYPE_INTEGER8 = 2
90
- SDF_DATATYPE_REAL4 = 3
91
- SDF_DATATYPE_REAL8 = 4
92
- SDF_DATATYPE_REAL16 = 5
93
- SDF_DATATYPE_CHARACTER = 6
94
- SDF_DATATYPE_LOGICAL = 7
95
- SDF_DATATYPE_OTHER = 8
43
+ # Enum representation using _c
44
+ class SdfBlockType(_IntEnum):
45
+ SCRUBBED = -1
46
+ NULL = 0
47
+ PLAIN_MESH = 1
48
+ POINT_MESH = 2
49
+ PLAIN_VARIABLE = 3
50
+ POINT_VARIABLE = 4
51
+ CONSTANT = 5
52
+ ARRAY = 6
53
+ RUN_INFO = 7
54
+ SOURCE = 8
55
+ STITCHED_TENSOR = 9
56
+ STITCHED_MATERIAL = 10
57
+ STITCHED_MATVAR = 11
58
+ STITCHED_SPECIES = 12
59
+ SPECIES = 13
60
+ PLAIN_DERIVED = 14
61
+ POINT_DERIVED = 15
62
+ CONTIGUOUS_TENSOR = 16
63
+ CONTIGUOUS_MATERIAL = 17
64
+ CONTIGUOUS_MATVAR = 18
65
+ CONTIGUOUS_SPECIES = 19
66
+ CPU_SPLIT = 20
67
+ STITCHED_OBSTACLE_GROUP = 21
68
+ UNSTRUCTURED_MESH = 22
69
+ STITCHED = 23
70
+ CONTIGUOUS = 24
71
+ LAGRANGIAN_MESH = 25
72
+ STATION = 26
73
+ STATION_DERIVED = 27
74
+ DATABLOCK = 28
75
+ NAMEVALUE = 29
76
+
77
+
78
+ class SdfGeometry(_IntEnum):
79
+ NULL = 0
80
+ CARTESIAN = 1
81
+ CYLINDRICAL = 2
82
+ SPHERICAL = 3
83
+
84
+
85
+ class SdfStagger(_IntEnum):
86
+ CELL_CENTRE = 0
87
+ FACE_X = 1
88
+ FACE_Y = 2
89
+ FACE_Z = 3
90
+ EDGE_X = 4
91
+ EDGE_Y = 5
92
+ EDGE_Z = 6
93
+ VERTEX = 7
94
+ HIDDEN0 = 10
95
+ HIDDEN1 = 11
96
+ HIDDEN2 = 12
97
+
98
+
99
+ class SdfDataType(_IntEnum):
100
+ NULL = 0
101
+ INTEGER4 = 1
102
+ INTEGER8 = 2
103
+ REAL4 = 3
104
+ REAL8 = 4
105
+ REAL16 = 5
106
+ CHARACTER = 6
107
+ LOGICAL = 7
108
+ OTHER = 8
109
+
110
+
111
+ class SdfMode(_IntEnum):
112
+ READ = 1
113
+ WRITE = 2
96
114
 
97
115
 
98
116
  _np_datatypes = [
99
117
  0,
100
- np.int32,
101
- np.int64,
102
- np.float32,
103
- np.float64,
104
- np.longdouble,
105
- np.byte,
106
- np.int32,
118
+ _np.int32,
119
+ _np.int64,
120
+ _np.float32,
121
+ _np.float64,
122
+ _np.longdouble,
123
+ _np.byte,
107
124
  bool,
108
125
  0,
109
126
  ]
110
127
  _ct_datatypes = [
111
128
  0,
112
- ct.c_int32,
113
- ct.c_int64,
114
- ct.c_float,
115
- ct.c_double,
116
- ct.c_longdouble,
117
- ct.c_char,
118
- ct.c_bool,
129
+ _c.c_int32,
130
+ _c.c_int64,
131
+ _c.c_float,
132
+ _c.c_double,
133
+ _c.c_longdouble,
134
+ _c.c_char,
135
+ _c.c_bool,
119
136
  0,
120
137
  ]
121
138
  _st_datatypes = [
@@ -131,223 +148,247 @@ _st_datatypes = [
131
148
  ]
132
149
 
133
150
  # Constants
134
- SDF_READ = 1
135
- SDF_WRITE = 2
136
- SDF_MAXDIMS = 4
151
+ _SDF_MAXDIMS = 4
137
152
 
138
153
 
139
- class SdfBlock(ct.Structure):
154
+ class SdfBlock(_c.Structure):
140
155
  pass # Forward declaration for self-referencing structure
141
156
 
142
157
 
143
- class SdfFile(ct.Structure):
158
+ class SdfFile(_c.Structure):
144
159
  pass # Forward declaration for function pointer compatibility
145
160
 
146
161
 
147
162
  SdfBlock._fields_ = [
148
- ("extents", ct.POINTER(ct.c_double)),
149
- ("dim_mults", ct.POINTER(ct.c_double)),
150
- ("station_x", ct.POINTER(ct.c_double)),
151
- ("station_y", ct.POINTER(ct.c_double)),
152
- ("station_z", ct.POINTER(ct.c_double)),
153
- ("mult", ct.c_double),
154
- ("time", ct.c_double),
155
- ("time_increment", ct.c_double),
156
- ("dims", ct.c_int64 * SDF_MAXDIMS),
157
- ("local_dims", ct.c_int64 * SDF_MAXDIMS),
158
- ("block_start", ct.c_int64),
159
- ("next_block_location", ct.c_int64),
160
- ("data_location", ct.c_int64),
161
- ("inline_block_start", ct.c_int64),
162
- ("inline_next_block_location", ct.c_int64),
163
- ("summary_block_start", ct.c_int64),
164
- ("summary_next_block_location", ct.c_int64),
165
- ("nelements", ct.c_int64),
166
- ("nelements_local", ct.c_int64),
167
- ("data_length", ct.c_int64),
168
- ("nelements_blocks", ct.POINTER(ct.c_int64)),
169
- ("data_length_blocks", ct.POINTER(ct.c_int64)),
170
- ("array_starts", ct.POINTER(ct.c_int64)),
171
- ("array_ends", ct.POINTER(ct.c_int64)),
172
- ("array_strides", ct.POINTER(ct.c_int64)),
173
- ("global_array_starts", ct.POINTER(ct.c_int64)),
174
- ("global_array_ends", ct.POINTER(ct.c_int64)),
175
- ("global_array_strides", ct.POINTER(ct.c_int64)),
176
- ("ndims", ct.c_int32),
177
- ("geometry", ct.c_int32),
178
- ("datatype", ct.c_int32),
179
- ("blocktype", ct.c_int32),
180
- ("info_length", ct.c_int32),
181
- ("type_size", ct.c_int32),
182
- ("stagger", ct.c_int32),
183
- ("datatype_out", ct.c_int32),
184
- ("type_size_out", ct.c_int32),
185
- ("nstations", ct.c_int32),
186
- ("nvariables", ct.c_int32),
187
- ("step", ct.c_int32),
188
- ("step_increment", ct.c_int32),
189
- ("dims_in", ct.POINTER(ct.c_int32)),
190
- ("station_nvars", ct.POINTER(ct.c_int32)),
191
- ("variable_types", ct.POINTER(ct.c_int32)),
192
- ("station_index", ct.POINTER(ct.c_int32)),
193
- ("station_move", ct.POINTER(ct.c_int32)),
194
- ("nm", ct.c_int),
195
- ("n_ids", ct.c_int),
196
- ("opt", ct.c_int),
197
- ("ng", ct.c_int),
198
- ("nfaces", ct.c_int),
199
- ("ngrids", ct.c_int),
200
- ("offset", ct.c_int),
201
- ("ngb", ct.c_int * 6),
202
- ("const_value", ct.c_byte * 16),
203
- ("id", ct.c_char_p),
204
- ("units", ct.c_char_p),
205
- ("mesh_id", ct.c_char_p),
206
- ("material_id", ct.c_char_p),
207
- ("vfm_id", ct.c_char_p),
208
- ("obstacle_id", ct.c_char_p),
209
- ("station_id", ct.c_char_p),
210
- ("name", ct.c_char_p),
211
- ("material_name", ct.c_char_p),
212
- ("must_read", ct.c_char_p),
213
- ("dim_labels", ct.POINTER(ct.c_char_p)),
214
- ("dim_units", ct.POINTER(ct.c_char_p)),
215
- ("station_ids", ct.POINTER(ct.c_char_p)),
216
- ("variable_ids", ct.POINTER(ct.c_char_p)),
217
- ("station_names", ct.POINTER(ct.c_char_p)),
218
- ("material_names", ct.POINTER(ct.c_char_p)),
219
- ("node_list", ct.POINTER(ct.c_int)),
220
- ("boundary_cells", ct.POINTER(ct.c_int)),
221
- ("grids", ct.POINTER(ct.c_void_p)),
222
- ("data", ct.c_void_p),
223
- ("done_header", ct.c_bool),
224
- ("done_info", ct.c_bool),
225
- ("done_data", ct.c_bool),
226
- ("dont_allocate", ct.c_bool),
227
- ("dont_display", ct.c_bool),
228
- ("dont_own_data", ct.c_bool),
229
- ("use_mult", ct.c_bool),
230
- ("next_block_modified", ct.c_bool),
231
- ("rewrite_metadata", ct.c_bool),
232
- ("in_file", ct.c_bool),
233
- ("ng_any", ct.c_bool),
234
- ("no_internal_ghost", ct.c_bool),
235
- ("next", ct.POINTER(SdfBlock)),
236
- ("prev", ct.POINTER(SdfBlock)),
237
- ("subblock", ct.POINTER(SdfBlock)),
238
- ("subblock2", ct.POINTER(SdfBlock)),
163
+ ("extents", _c.POINTER(_c.c_double)),
164
+ ("dim_mults", _c.POINTER(_c.c_double)),
165
+ ("station_x", _c.POINTER(_c.c_double)),
166
+ ("station_y", _c.POINTER(_c.c_double)),
167
+ ("station_z", _c.POINTER(_c.c_double)),
168
+ ("mult", _c.c_double),
169
+ ("time", _c.c_double),
170
+ ("time_increment", _c.c_double),
171
+ ("dims", _c.c_int64 * _SDF_MAXDIMS),
172
+ ("local_dims", _c.c_int64 * _SDF_MAXDIMS),
173
+ ("block_start", _c.c_int64),
174
+ ("next_block_location", _c.c_int64),
175
+ ("data_location", _c.c_int64),
176
+ ("inline_block_start", _c.c_int64),
177
+ ("inline_next_block_location", _c.c_int64),
178
+ ("summary_block_start", _c.c_int64),
179
+ ("summary_next_block_location", _c.c_int64),
180
+ ("nelements", _c.c_int64),
181
+ ("nelements_local", _c.c_int64),
182
+ ("data_length", _c.c_int64),
183
+ ("nelements_blocks", _c.POINTER(_c.c_int64)),
184
+ ("data_length_blocks", _c.POINTER(_c.c_int64)),
185
+ ("array_starts", _c.POINTER(_c.c_int64)),
186
+ ("array_ends", _c.POINTER(_c.c_int64)),
187
+ ("array_strides", _c.POINTER(_c.c_int64)),
188
+ ("global_array_starts", _c.POINTER(_c.c_int64)),
189
+ ("global_array_ends", _c.POINTER(_c.c_int64)),
190
+ ("global_array_strides", _c.POINTER(_c.c_int64)),
191
+ ("ndims", _c.c_int32),
192
+ ("geometry", _c.c_int32),
193
+ ("datatype", _c.c_int32),
194
+ ("blocktype", _c.c_int32),
195
+ ("info_length", _c.c_int32),
196
+ ("type_size", _c.c_int32),
197
+ ("stagger", _c.c_int32),
198
+ ("datatype_out", _c.c_int32),
199
+ ("type_size_out", _c.c_int32),
200
+ ("nstations", _c.c_int32),
201
+ ("nvariables", _c.c_int32),
202
+ ("step", _c.c_int32),
203
+ ("step_increment", _c.c_int32),
204
+ ("dims_in", _c.POINTER(_c.c_int32)),
205
+ ("station_nvars", _c.POINTER(_c.c_int32)),
206
+ ("variable_types", _c.POINTER(_c.c_int32)),
207
+ ("station_index", _c.POINTER(_c.c_int32)),
208
+ ("station_move", _c.POINTER(_c.c_int32)),
209
+ ("nm", _c.c_int),
210
+ ("n_ids", _c.c_int),
211
+ ("opt", _c.c_int),
212
+ ("ng", _c.c_int),
213
+ ("nfaces", _c.c_int),
214
+ ("ngrids", _c.c_int),
215
+ ("offset", _c.c_int),
216
+ ("ngb", _c.c_int * 6),
217
+ ("const_value", _c.c_byte * 16),
218
+ ("id", _c.c_char_p),
219
+ ("units", _c.c_char_p),
220
+ ("mesh_id", _c.c_char_p),
221
+ ("material_id", _c.c_char_p),
222
+ ("vfm_id", _c.c_char_p),
223
+ ("obstacle_id", _c.c_char_p),
224
+ ("station_id", _c.c_char_p),
225
+ ("name", _c.c_char_p),
226
+ ("material_name", _c.c_char_p),
227
+ ("must_read", _c.c_char_p),
228
+ ("dim_labels", _c.POINTER(_c.c_char_p)),
229
+ ("dim_units", _c.POINTER(_c.c_char_p)),
230
+ ("station_ids", _c.POINTER(_c.c_char_p)),
231
+ ("variable_ids", _c.POINTER(_c.c_char_p)),
232
+ ("station_names", _c.POINTER(_c.c_char_p)),
233
+ ("material_names", _c.POINTER(_c.c_char_p)),
234
+ ("node_list", _c.POINTER(_c.c_int)),
235
+ ("boundary_cells", _c.POINTER(_c.c_int)),
236
+ ("grids", _c.POINTER(_c.c_void_p)),
237
+ ("data", _c.c_void_p),
238
+ ("done_header", _c.c_bool),
239
+ ("done_info", _c.c_bool),
240
+ ("done_data", _c.c_bool),
241
+ ("dont_allocate", _c.c_bool),
242
+ ("dont_display", _c.c_bool),
243
+ ("dont_own_data", _c.c_bool),
244
+ ("use_mult", _c.c_bool),
245
+ ("next_block_modified", _c.c_bool),
246
+ ("rewrite_metadata", _c.c_bool),
247
+ ("in_file", _c.c_bool),
248
+ ("ng_any", _c.c_bool),
249
+ ("no_internal_ghost", _c.c_bool),
250
+ ("next", _c.POINTER(SdfBlock)),
251
+ ("prev", _c.POINTER(SdfBlock)),
252
+ ("subblock", _c.POINTER(SdfBlock)),
253
+ ("subblock2", _c.POINTER(SdfBlock)),
239
254
  (
240
255
  "populate_data",
241
- ct.CFUNCTYPE(
242
- ct.POINTER(SdfBlock), ct.POINTER(SdfFile), ct.POINTER(SdfBlock)
256
+ _c.CFUNCTYPE(
257
+ _c.POINTER(SdfBlock), _c.POINTER(SdfFile), _c.POINTER(SdfBlock)
243
258
  ),
244
259
  ),
245
- ("cpu_split", ct.c_int * SDF_MAXDIMS),
246
- ("starts", ct.c_int * SDF_MAXDIMS),
247
- ("proc_min", ct.c_int * 3),
248
- ("proc_max", ct.c_int * 3),
249
- ("ndim_labels", ct.c_int),
250
- ("ndim_units", ct.c_int),
251
- ("nstation_ids", ct.c_int),
252
- ("nvariable_ids", ct.c_int),
253
- ("nstation_names", ct.c_int),
254
- ("nmaterial_names", ct.c_int),
255
- ("option", ct.c_int),
256
- ("mimetype", ct.c_char_p),
257
- ("checksum_type", ct.c_char_p),
258
- ("checksum", ct.c_char_p),
259
- ("mmap", ct.c_char_p),
260
- ("mmap_len", ct.c_int64),
261
- ("derived", ct.c_bool),
260
+ ("cpu_split", _c.c_int * _SDF_MAXDIMS),
261
+ ("starts", _c.c_int * _SDF_MAXDIMS),
262
+ ("proc_min", _c.c_int * 3),
263
+ ("proc_max", _c.c_int * 3),
264
+ ("ndim_labels", _c.c_int),
265
+ ("ndim_units", _c.c_int),
266
+ ("nstation_ids", _c.c_int),
267
+ ("nvariable_ids", _c.c_int),
268
+ ("nstation_names", _c.c_int),
269
+ ("nmaterial_names", _c.c_int),
270
+ ("option", _c.c_int),
271
+ ("mimetype", _c.c_char_p),
272
+ ("checksum_type", _c.c_char_p),
273
+ ("checksum", _c.c_char_p),
274
+ ("mmap", _c.c_char_p),
275
+ ("mmap_len", _c.c_int64),
276
+ ("derived", _c.c_bool),
277
+ ("id_orig", _c.c_char_p),
278
+ ("name_orig", _c.c_char_p),
262
279
  ]
263
280
 
264
281
  SdfFile._fields_ = [
265
- ("dbg_count", ct.c_int64),
266
- ("sdf_lib_version", ct.c_int32),
267
- ("sdf_lib_revision", ct.c_int32),
268
- ("sdf_extension_version", ct.c_int32),
269
- ("sdf_extension_revision", ct.c_int32),
270
- ("file_version", ct.c_int32),
271
- ("file_revision", ct.c_int32),
272
- ("dbg", ct.c_char_p),
273
- ("dbg_buf", ct.c_char_p),
274
- ("extension_names", ct.POINTER(ct.c_char_p)),
275
- ("time", ct.c_double),
276
- ("first_block_location", ct.c_int64),
277
- ("summary_location", ct.c_int64),
278
- ("start_location", ct.c_int64),
279
- ("soi", ct.c_int64),
280
- ("sof", ct.c_int64),
281
- ("current_location", ct.c_int64),
282
- ("jobid1", ct.c_int32),
283
- ("jobid2", ct.c_int32),
284
- ("endianness", ct.c_int32),
285
- ("summary_size", ct.c_int32),
286
- ("block_header_length", ct.c_int32),
287
- ("string_length", ct.c_int32),
288
- ("id_length", ct.c_int32),
289
- ("code_io_version", ct.c_int32),
290
- ("step", ct.c_int32),
291
- ("nblocks", ct.c_int32),
292
- ("nblocks_file", ct.c_int32),
293
- ("error_code", ct.c_int32),
294
- ("rank", ct.c_int),
295
- ("ncpus", ct.c_int),
296
- ("ndomains", ct.c_int),
297
- ("rank_master", ct.c_int),
298
- ("indent", ct.c_int),
299
- ("print", ct.c_int),
300
- ("buffer", ct.c_char_p),
301
- ("filename", ct.c_char_p),
302
- ("done_header", ct.c_bool),
303
- ("restart_flag", ct.c_bool),
304
- ("other_domains", ct.c_bool),
305
- ("use_float", ct.c_bool),
306
- ("use_summary", ct.c_bool),
307
- ("use_random", ct.c_bool),
308
- ("station_file", ct.c_bool),
309
- ("swap", ct.c_bool),
310
- ("inline_metadata_read", ct.c_bool),
311
- ("summary_metadata_read", ct.c_bool),
312
- ("inline_metadata_invalid", ct.c_bool),
313
- ("summary_metadata_invalid", ct.c_bool),
314
- ("tmp_flag", ct.c_bool),
315
- ("metadata_modified", ct.c_bool),
316
- ("can_truncate", ct.c_bool),
317
- ("first_block_modified", ct.c_bool),
318
- ("code_name", ct.c_char_p),
319
- ("error_message", ct.c_char_p),
320
- ("blocklist", ct.POINTER(SdfBlock)),
321
- ("tail", ct.POINTER(SdfBlock)),
322
- ("current_block", ct.POINTER(SdfBlock)),
323
- ("last_block_in_file", ct.POINTER(SdfBlock)),
324
- ("mmap", ct.c_char_p),
325
- ("ext_data", ct.c_void_p),
326
- ("stack_handle", ct.c_void_p),
327
- ("array_count", ct.c_int),
328
- ("fd", ct.c_int),
329
- ("purge_duplicated_ids", ct.c_int),
330
- ("internal_ghost_cells", ct.c_int),
331
- ("ignore_nblocks", ct.c_int),
282
+ ("dbg_count", _c.c_int64),
283
+ ("sdf_lib_version", _c.c_int32),
284
+ ("sdf_lib_revision", _c.c_int32),
285
+ ("sdf_extension_version", _c.c_int32),
286
+ ("sdf_extension_revision", _c.c_int32),
287
+ ("file_version", _c.c_int32),
288
+ ("file_revision", _c.c_int32),
289
+ ("dbg", _c.c_char_p),
290
+ ("dbg_buf", _c.c_char_p),
291
+ ("extension_names", _c.POINTER(_c.c_char_p)),
292
+ ("time", _c.c_double),
293
+ ("first_block_location", _c.c_int64),
294
+ ("summary_location", _c.c_int64),
295
+ ("start_location", _c.c_int64),
296
+ ("soi", _c.c_int64),
297
+ ("sof", _c.c_int64),
298
+ ("current_location", _c.c_int64),
299
+ ("jobid1", _c.c_int32),
300
+ ("jobid2", _c.c_int32),
301
+ ("endianness", _c.c_int32),
302
+ ("summary_size", _c.c_int32),
303
+ ("block_header_length", _c.c_int32),
304
+ ("string_length", _c.c_int32),
305
+ ("id_length", _c.c_int32),
306
+ ("code_io_version", _c.c_int32),
307
+ ("step", _c.c_int32),
308
+ ("nblocks", _c.c_int32),
309
+ ("nblocks_file", _c.c_int32),
310
+ ("error_code", _c.c_int32),
311
+ ("rank", _c.c_int),
312
+ ("ncpus", _c.c_int),
313
+ ("ndomains", _c.c_int),
314
+ ("rank_master", _c.c_int),
315
+ ("indent", _c.c_int),
316
+ ("print", _c.c_int),
317
+ ("buffer", _c.c_char_p),
318
+ ("filename", _c.c_char_p),
319
+ ("done_header", _c.c_bool),
320
+ ("restart_flag", _c.c_bool),
321
+ ("other_domains", _c.c_bool),
322
+ ("use_float", _c.c_bool),
323
+ ("use_summary", _c.c_bool),
324
+ ("use_random", _c.c_bool),
325
+ ("station_file", _c.c_bool),
326
+ ("swap", _c.c_bool),
327
+ ("inline_metadata_read", _c.c_bool),
328
+ ("summary_metadata_read", _c.c_bool),
329
+ ("inline_metadata_invalid", _c.c_bool),
330
+ ("summary_metadata_invalid", _c.c_bool),
331
+ ("tmp_flag", _c.c_bool),
332
+ ("metadata_modified", _c.c_bool),
333
+ ("can_truncate", _c.c_bool),
334
+ ("first_block_modified", _c.c_bool),
335
+ ("code_name", _c.c_char_p),
336
+ ("error_message", _c.c_char_p),
337
+ ("blocklist", _c.POINTER(SdfBlock)),
338
+ ("tail", _c.POINTER(SdfBlock)),
339
+ ("current_block", _c.POINTER(SdfBlock)),
340
+ ("last_block_in_file", _c.POINTER(SdfBlock)),
341
+ ("mmap", _c.c_char_p),
342
+ ("ext_data", _c.c_void_p),
343
+ ("stack_handle", _c.c_void_p),
344
+ ("array_count", _c.c_int),
345
+ ("fd", _c.c_int),
346
+ ("purge_duplicated_ids", _c.c_int),
347
+ ("internal_ghost_cells", _c.c_int),
348
+ ("ignore_nblocks", _c.c_int),
332
349
  ]
333
350
 
334
351
 
335
- class RunInfo(ct.Structure):
352
+ class RunInfo(_c.Structure):
336
353
  _fields_ = [
337
- ("defines", ct.c_int64),
338
- ("version", ct.c_int32),
339
- ("revision", ct.c_int32),
340
- ("compile_date", ct.c_int32),
341
- ("run_date", ct.c_int32),
342
- ("io_date", ct.c_int32),
343
- ("minor_rev", ct.c_int32),
344
- ("commit_id", ct.c_char_p),
345
- ("sha1sum", ct.c_char_p),
346
- ("compile_machine", ct.c_char_p),
347
- ("compile_flags", ct.c_char_p),
354
+ ("defines", _c.c_int64),
355
+ ("version", _c.c_int32),
356
+ ("revision", _c.c_int32),
357
+ ("compile_date", _c.c_int32),
358
+ ("run_date", _c.c_int32),
359
+ ("io_date", _c.c_int32),
360
+ ("minor_rev", _c.c_int32),
361
+ ("commit_id", _c.c_char_p),
362
+ ("sha1sum", _c.c_char_p),
363
+ ("compile_machine", _c.c_char_p),
364
+ ("compile_flags", _c.c_char_p),
348
365
  ]
349
366
 
350
367
 
368
+ class BlockDict(dict):
369
+ def __init__(self, _dict, block):
370
+ self.handle = block._handle
371
+ super().__init__(_dict)
372
+
373
+ def __setitem__(self, key, value):
374
+ h = self.handle
375
+ if key in (
376
+ "step",
377
+ "time",
378
+ "code_io_version",
379
+ "string_length",
380
+ "jobid1",
381
+ "jobid2",
382
+ ):
383
+ setattr(h.contents, key, value)
384
+ elif key == "code_name":
385
+ h._clib.sdf_set_code_name(h, value.encode("utf-8"))
386
+ else:
387
+ print(f'WARNING: unable to set header key "{key}"')
388
+ return
389
+ super().__setitem__(key, value)
390
+
391
+
351
392
  class BlockList:
352
393
  """Contains all the blocks"""
353
394
 
@@ -356,52 +397,63 @@ class BlockList:
356
397
  filename=None,
357
398
  convert=False,
358
399
  derived=True,
359
- mode=SDF_READ,
400
+ mode=SdfMode.READ,
360
401
  code_name="sdfr",
361
402
  restart=False,
362
403
  ):
363
404
  self._handle = None
364
- clib = sdf_lib
405
+ clib = _sdf_lib
365
406
  self._clib = clib
366
- clib.sdf_open.restype = ct.POINTER(SdfFile)
367
- clib.sdf_open.argtypes = [ct.c_char_p, ct.c_int, ct.c_int, ct.c_int]
368
- clib.sdf_new.restype = ct.POINTER(SdfFile)
369
- clib.sdf_new.argtypes = [ct.c_int, ct.c_int]
370
- clib.sdf_stack_init.argtypes = [ct.c_void_p]
371
- clib.sdf_read_blocklist.argtypes = [ct.c_void_p]
372
- clib.sdf_read_blocklist_all.argtypes = [ct.c_void_p]
373
- clib.sdf_helper_read_data.argtypes = [ct.c_void_p, ct.POINTER(SdfBlock)]
374
- clib.sdf_free_block_data.argtypes = [ct.c_void_p, ct.POINTER(SdfBlock)]
375
- clib.sdf_stack_destroy.argtypes = [ct.c_void_p]
376
- clib.sdf_close.argtypes = [ct.c_void_p]
377
- clib.sdf_write.argtypes = [ct.c_void_p, ct.c_char_p]
378
- clib.sdf_get_next_block.argtypes = [ct.c_void_p]
407
+ clib.sdf_open.restype = _c.POINTER(SdfFile)
408
+ clib.sdf_open.argtypes = [_c.c_char_p, _c.c_int, _c.c_int, _c.c_int]
409
+ clib.sdf_new.restype = _c.POINTER(SdfFile)
410
+ clib.sdf_new.argtypes = [_c.c_int, _c.c_int]
411
+ clib.sdf_stack_init.argtypes = [_c.c_void_p]
412
+ clib.sdf_read_blocklist.argtypes = [_c.c_void_p]
413
+ clib.sdf_read_blocklist_all.argtypes = [_c.c_void_p]
414
+ clib.sdf_helper_read_data.argtypes = [_c.c_void_p, _c.POINTER(SdfBlock)]
415
+ clib.sdf_free_block_data.argtypes = [_c.c_void_p, _c.POINTER(SdfBlock)]
416
+ clib.sdf_stack_destroy.argtypes = [_c.c_void_p]
417
+ clib.sdf_close.argtypes = [_c.c_void_p]
418
+ clib.sdf_write.argtypes = [_c.c_void_p, _c.c_char_p]
419
+ clib.sdf_get_next_block.argtypes = [_c.c_void_p]
379
420
  clib.sdf_set_namevalue.argtypes = [
380
- ct.POINTER(SdfBlock),
381
- ct.POINTER(ct.c_char_p),
382
- ct.POINTER(ct.c_void_p),
421
+ _c.POINTER(SdfBlock),
422
+ _c.POINTER(_c.c_char_p),
423
+ _c.POINTER(_c.c_void_p),
383
424
  ]
384
- clib.sdf_set_code_name.argtypes = [ct.c_void_p, ct.c_char_p]
425
+ clib.sdf_set_code_name.argtypes = [_c.c_void_p, _c.c_char_p]
385
426
  clib.sdf_set_block_name.argtypes = [
386
- ct.c_void_p,
387
- ct.c_char_p,
388
- ct.c_char_p,
427
+ _c.c_void_p,
428
+ _c.c_char_p,
429
+ _c.c_char_p,
389
430
  ]
390
431
  clib.sdf_set_defaults.argtypes = [
391
- ct.c_void_p,
392
- ct.POINTER(SdfBlock),
432
+ _c.c_void_p,
433
+ _c.POINTER(SdfBlock),
393
434
  ]
394
435
  clib.sdf_create_id.argtypes = [
395
- ct.c_void_p,
396
- ct.c_char_p,
436
+ _c.c_void_p,
437
+ _c.c_char_p,
397
438
  ]
398
- clib.sdf_create_id.restype = ct.POINTER(ct.c_char_p)
439
+ clib.sdf_create_id.restype = _c.POINTER(_c.c_char_p)
399
440
  clib.sdf_create_id_array.argtypes = [
400
- ct.c_void_p,
401
- ct.c_int,
402
- ct.POINTER(ct.c_char_p),
441
+ _c.c_void_p,
442
+ _c.c_int,
443
+ _c.POINTER(_c.c_char_p),
444
+ ]
445
+ clib.sdf_create_id_array.restype = _c.POINTER(_c.c_char_p)
446
+ clib.sdf_create_string.argtypes = [
447
+ _c.c_void_p,
448
+ _c.c_char_p,
449
+ ]
450
+ clib.sdf_create_string.restype = _c.POINTER(_c.c_char_p)
451
+ clib.sdf_create_string_array.argtypes = [
452
+ _c.c_void_p,
453
+ _c.c_int,
454
+ _c.POINTER(_c.c_char_p),
403
455
  ]
404
- clib.sdf_create_id_array.restype = ct.POINTER(ct.c_char_p)
456
+ clib.sdf_create_string_array.restype = _c.POINTER(_c.c_char_p)
405
457
 
406
458
  comm = 0
407
459
  use_mmap = 0
@@ -418,7 +470,7 @@ class BlockList:
418
470
  h._clib = clib
419
471
  self._handle = h
420
472
  clib.sdf_stack_init(h)
421
- if mode == SDF_READ:
473
+ if mode == SdfMode.READ:
422
474
  if derived:
423
475
  clib.sdf_read_blocklist_all(h)
424
476
  else:
@@ -428,7 +480,7 @@ class BlockList:
428
480
 
429
481
  block = h.contents.blocklist
430
482
  h.contents.restart_flag = restart
431
- self.Header = get_header(h.contents)
483
+ self._header = self._get_header(h.contents)
432
484
  mesh_id_map = {}
433
485
  mesh_vars = []
434
486
  self._block_ids = {"Header": self.Header}
@@ -440,77 +492,88 @@ class BlockList:
440
492
  blocktype = block.blocktype
441
493
  newblock = None
442
494
  newblock_mid = None
443
- name = get_member_name(block.name)
444
- if blocktype == SdfBlockType.SDF_BLOCKTYPE_ARRAY:
495
+ if block.name_orig:
496
+ name = _get_member_name(block.name_orig)
497
+ else:
498
+ name = _get_member_name(block.name)
499
+ if blocktype == SdfBlockType.ARRAY:
445
500
  newblock = BlockArray(block)
446
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_CONSTANT:
501
+ elif blocktype == SdfBlockType.CONSTANT:
447
502
  newblock = BlockConstant(block)
448
503
  elif (
449
- blocktype == SdfBlockType.SDF_BLOCKTYPE_CONTIGUOUS
450
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_STITCHED
504
+ blocktype == SdfBlockType.CONTIGUOUS
505
+ or blocktype == SdfBlockType.STITCHED
451
506
  ):
452
- if block.stagger == 10 or block.stagger == 12:
507
+ if block.stagger in (SdfStagger.HIDDEN0, SdfStagger.HIDDEN2):
453
508
  newblock = BlockStitchedPath(block)
454
509
  else:
455
510
  newblock = BlockStitched(block)
511
+ mesh_vars.append(newblock)
456
512
  elif (
457
- blocktype == SdfBlockType.SDF_BLOCKTYPE_CONTIGUOUS_MATERIAL
458
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_STITCHED_MATERIAL
513
+ blocktype == SdfBlockType.CONTIGUOUS_MATERIAL
514
+ or blocktype == SdfBlockType.STITCHED_MATERIAL
459
515
  ):
460
516
  newblock = BlockStitchedMaterial(block)
517
+ mesh_vars.append(newblock)
461
518
  elif (
462
- blocktype == SdfBlockType.SDF_BLOCKTYPE_CONTIGUOUS_MATVAR
463
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_STITCHED_MATVAR
519
+ blocktype == SdfBlockType.CONTIGUOUS_MATVAR
520
+ or blocktype == SdfBlockType.STITCHED_MATVAR
464
521
  ):
465
522
  newblock = BlockStitchedMatvar(block)
523
+ mesh_vars.append(newblock)
466
524
  elif (
467
- blocktype == SdfBlockType.SDF_BLOCKTYPE_CONTIGUOUS_SPECIES
468
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_STITCHED_SPECIES
525
+ blocktype == SdfBlockType.CONTIGUOUS_SPECIES
526
+ or blocktype == SdfBlockType.STITCHED_SPECIES
469
527
  ):
470
528
  newblock = BlockStitchedSpecies(block)
529
+ mesh_vars.append(newblock)
471
530
  elif (
472
- blocktype == SdfBlockType.SDF_BLOCKTYPE_CONTIGUOUS_TENSOR
473
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_STITCHED_TENSOR
531
+ blocktype == SdfBlockType.CONTIGUOUS_TENSOR
532
+ or blocktype == SdfBlockType.STITCHED_TENSOR
474
533
  ):
475
534
  newblock = BlockStitchedTensor(block)
476
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_DATABLOCK:
535
+ mesh_vars.append(newblock)
536
+ elif blocktype == SdfBlockType.DATABLOCK:
477
537
  newblock = BlockData(block)
478
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_LAGRANGIAN_MESH:
538
+ elif blocktype == SdfBlockType.LAGRANGIAN_MESH:
479
539
  if block.datatype_out != 0:
480
540
  newblock = BlockLagrangianMesh(block)
481
541
  newblock_mid = block
482
542
  newblock_mid._grid_block = newblock
483
543
  mesh_id_map[newblock.id] = newblock
484
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_NAMEVALUE:
544
+ elif blocktype == SdfBlockType.NAMEVALUE:
485
545
  newblock = BlockNameValue(block)
486
546
  elif (
487
- blocktype == SdfBlockType.SDF_BLOCKTYPE_PLAIN_DERIVED
488
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_PLAIN_VARIABLE
547
+ blocktype == SdfBlockType.PLAIN_DERIVED
548
+ or blocktype == SdfBlockType.PLAIN_VARIABLE
489
549
  ):
490
550
  newblock = BlockPlainVariable(block)
491
551
  mesh_vars.append(newblock)
492
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_PLAIN_MESH:
552
+ elif blocktype == SdfBlockType.PLAIN_MESH:
493
553
  if block.datatype_out != 0:
494
554
  newblock = BlockPlainMesh(block)
495
555
  newblock_mid = block
496
556
  newblock_mid._grid_block = newblock
497
557
  mesh_id_map[newblock.id] = newblock
498
558
  elif (
499
- blocktype == SdfBlockType.SDF_BLOCKTYPE_POINT_DERIVED
500
- or blocktype == SdfBlockType.SDF_BLOCKTYPE_POINT_VARIABLE
559
+ blocktype == SdfBlockType.POINT_DERIVED
560
+ or blocktype == SdfBlockType.POINT_VARIABLE
501
561
  ):
502
562
  newblock = BlockPointVariable(block)
503
563
  mesh_vars.append(newblock)
504
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_POINT_MESH:
564
+ elif blocktype == SdfBlockType.POINT_MESH:
505
565
  newblock = BlockPointMesh(block)
506
566
  mesh_id_map[newblock.id] = newblock
507
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_RUN_INFO:
508
- self.Run_info = get_run_info(block)
509
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_STATION:
510
- sdict = BlockStation(block, name)
567
+ elif blocktype == SdfBlockType.RUN_INFO:
568
+ newblock = BlockRunInfo(block)
569
+ elif blocktype == SdfBlockType.STATION:
570
+ sdict = _BlockStation(block, name)
511
571
  self.__dict__.update({"StationBlocks": sdict})
512
572
  self._block_ids.update({block.id.decode(): sdict})
513
573
  self._block_names.update({block.name.decode(): sdict})
574
+ elif blocktype == SdfBlockType.CPU_SPLIT:
575
+ newblock = BlockCpuSplit(block)
576
+ name = "_" + name
514
577
  else:
515
578
  # Block not supported
516
579
  # print(name,SdfBlockType(blocktype).name)
@@ -527,10 +590,10 @@ class BlockList:
527
590
  block_mid._handle = h
528
591
  block_mid._blocklist = self
529
592
  blocktype = block_mid.blocktype
530
- name = get_member_name(block_mid.name) + "_mid"
531
- if blocktype == SdfBlockType.SDF_BLOCKTYPE_LAGRANGIAN_MESH:
593
+ name = _get_member_name(block_mid.name) + "_mid"
594
+ if blocktype == SdfBlockType.LAGRANGIAN_MESH:
532
595
  newblock = BlockLagrangianMesh(block_mid, mid=True)
533
- elif blocktype == SdfBlockType.SDF_BLOCKTYPE_PLAIN_MESH:
596
+ elif blocktype == SdfBlockType.PLAIN_MESH:
534
597
  newblock = BlockPlainMesh(block_mid, mid=True)
535
598
  if not newblock_mid.dont_display:
536
599
  self.__dict__[name] = newblock
@@ -551,10 +614,41 @@ class BlockList:
551
614
  self._clib.sdf_close(self._handle)
552
615
  self._handle = None
553
616
 
554
- def write(self, filename):
555
- if not self._handle:
556
- return
557
- self._clib.sdf_write(self._handle, filename.encode())
617
+ @property
618
+ def Header(self) -> _Dict[str, _Any]:
619
+ """SDF file header"""
620
+ return self._header
621
+
622
+ @Header.setter
623
+ def Header(self, value):
624
+ try:
625
+ for k, v in value.items():
626
+ self.Header[k] = v
627
+ except Exception:
628
+ print("failed")
629
+
630
+ def _get_header(self, h):
631
+ d = {}
632
+ for k in [
633
+ "filename",
634
+ "file_version",
635
+ "file_revision",
636
+ "code_name",
637
+ "step",
638
+ "time",
639
+ "jobid1",
640
+ "jobid2",
641
+ "code_io_version",
642
+ "restart_flag",
643
+ "other_domains",
644
+ "station_file",
645
+ ]:
646
+ attr = getattr(h, k)
647
+ if isinstance(attr, bytes):
648
+ d[k] = attr.decode()
649
+ else:
650
+ d[k] = attr
651
+ return BlockDict(d, self)
558
652
 
559
653
  def _set_block_name(self, id, name):
560
654
  self._clib.sdf_set_block_name(
@@ -563,13 +657,17 @@ class BlockList:
563
657
 
564
658
  def _create_id(self, values):
565
659
  tmp = self._clib.sdf_create_id(self._handle, values.encode("utf-8"))
566
- return ct.cast(tmp, ct.c_char_p)
660
+ return _c.cast(tmp, _c.c_char_p)
661
+
662
+ def _create_string(self, values):
663
+ tmp = self._clib.sdf_create_string(self._handle, values.encode("utf-8"))
664
+ return _c.cast(tmp, _c.c_char_p)
567
665
 
568
666
  def _string_array_ctype(self, values):
569
667
  strings = [s.encode("utf-8") for s in values]
570
- strings = [ct.create_string_buffer(s) for s in strings]
571
- strings = [ct.cast(s, ct.c_char_p) for s in strings]
572
- strings = (ct.c_char_p * len(values))(*strings)
668
+ strings = [_c.create_string_buffer(s) for s in strings]
669
+ strings = [_c.cast(s, _c.c_char_p) for s in strings]
670
+ strings = (_c.c_char_p * len(values))(*strings)
573
671
  return strings
574
672
 
575
673
  def _create_id_array(self, values):
@@ -577,240 +675,12 @@ class BlockList:
577
675
  res = self._clib.sdf_create_id_array(self._handle, len(values), values)
578
676
  return res
579
677
 
580
- def _add_preamble(self, id, name, datatype):
581
- self._clib.sdf_get_next_block(self._handle)
582
- h = self._handle.contents
583
- h.nblocks += 1
584
- h.nblocks_file += 1
585
- block = h.current_block.contents
586
- block._handle = self._handle
587
- block._blocklist = h.blocklist
588
- block._data = None
589
- block.datatype = datatype
590
- block.in_file = 1
591
- block.AddBlock = None
592
- self._set_block_name(id, name)
593
- return h, block
594
-
595
- def _add_post(self, block):
596
- if block.AddBlock:
597
- newblock = block.AddBlock(block)
598
- else:
599
- return
600
-
601
- id = block.id.decode()
602
- name = block.name.decode()
603
- if not block.dont_display:
604
- self.__dict__[name] = newblock
605
- if block._data is not None:
606
- newblock._data = block._data
607
- self._block_ids.update({id: newblock})
608
- self._block_names.update({name: newblock})
609
-
610
- def _add_constant(self, name, value=0, datatype=None, id=None):
611
- if datatype == SdfDataType.SDF_DATATYPE_CHARACTER:
612
- print(f'Block "{id}", unsupported datatype: {type(value)}')
613
- return
614
-
615
- h, block = self._add_preamble(id, name, datatype)
616
- block.blocktype = SdfBlockType.SDF_BLOCKTYPE_CONSTANT
617
- block.AddBlock = BlockConstant
618
-
619
- const_value = struct.pack(_st_datatypes[block.datatype], value)
620
- ct.memmove(block.const_value, const_value, 16)
621
-
622
- self._add_post(block)
623
-
624
- def _add_namevalue(self, name, value={}, datatype=None, id=None):
625
- h, block = self._add_preamble(id, name, datatype)
626
- block.blocktype = SdfBlockType.SDF_BLOCKTYPE_NAMEVALUE
627
- block.AddBlock = BlockNameValue
628
-
629
- nvalue = len(value)
630
- block.ndims = nvalue
631
- ctype = _ct_datatypes[block.datatype]
632
- if block.datatype == SdfDataType.SDF_DATATYPE_CHARACTER:
633
- vals = self._string_array_ctype(value.values())
634
- else:
635
- vals = (ctype * nvalue)(*value.values())
636
- names = self._string_array_ctype(value.keys())
637
- vals = ct.cast(vals, ct.POINTER(ct.c_void_p))
638
- self._clib.sdf_set_namevalue(block, names, vals)
639
-
640
- self._add_post(block)
641
-
642
- def _add_array(self, name, value=(), datatype=None, id=None):
643
- if datatype == SdfDataType.SDF_DATATYPE_CHARACTER:
644
- print(f'Block "{id}", unsupported datatype: {type(value[0])}')
645
- return
646
-
647
- h, block = self._add_preamble(id, name, datatype)
648
- block.blocktype = SdfBlockType.SDF_BLOCKTYPE_ARRAY
649
- block.AddBlock = BlockArray
650
-
651
- block._data = np.array(value)
652
- block.ndims = block._data.ndim
653
- for i in range(block.ndims):
654
- block.dims[i] = block._data.shape[i]
655
- block.data = block._data.ctypes.data_as(ct.c_void_p)
656
-
657
- self._add_post(block)
658
-
659
- def _add_plainvar(
660
- self,
661
- name,
662
- value=(),
663
- datatype=None,
664
- id=None,
665
- mult=None,
666
- units=None,
667
- mesh_id=None,
668
- stagger=None,
669
- ):
670
- if datatype == SdfDataType.SDF_DATATYPE_CHARACTER:
671
- print(f'Block "{id}", unsupported datatype: {type(value[0])}')
672
- return
673
- try:
674
- mult = float(mult)
675
- except Exception:
676
- if mult is not None:
677
- print(f"ERROR: unable to use mult parameter, {mult}")
678
- return
679
- try:
680
- stagger = SdfStagger(stagger)
681
- except Exception:
682
- if stagger is not None:
683
- print(f"ERROR: unable to use stagger parameter, {stagger}")
684
- return
685
- if units is not None and not isinstance(units, str):
686
- print(f"ERROR: unable to use units parameter, {units}")
687
- return
688
- if mesh_id is not None and not isinstance(mesh_id, str):
689
- print(f"ERROR: unable to use mesh_id parameter, {mesh_id}")
690
- return
691
-
692
- h, block = self._add_preamble(id, name, datatype)
693
- block.blocktype = SdfBlockType.SDF_BLOCKTYPE_PLAIN_VARIABLE
694
- block.AddBlock = BlockPlainVariable
695
-
696
- block._data = np.array(value, order="F")
697
- block.ndims = block._data.ndim
698
- for i in range(block.ndims):
699
- block.dims[i] = block._data.shape[i]
700
- block.data = block._data.ctypes.data_as(ct.c_void_p)
701
- if mult is not None:
702
- block.mult = mult
703
- if isinstance(units, str):
704
- block.units = self._create_id(units)
705
- if isinstance(mesh_id, str):
706
- block.mesh_id = self._create_id(mesh_id)
707
- if stagger:
708
- block.stagger = stagger
709
-
710
- self._clib.sdf_set_defaults(self._handle, block)
711
- self._add_post(block)
712
-
713
- def _add_mesh(
714
- self,
715
- name,
716
- value=None,
717
- datatype=None,
718
- id=None,
719
- units=None,
720
- labels=None,
721
- geometry=None,
722
- **kwargs,
723
- ):
724
- if datatype == SdfDataType.SDF_DATATYPE_CHARACTER:
725
- print(f'Block "{id}", unsupported datatype: {type(value[0])}')
726
- return
727
-
728
- h, block = self._add_preamble(id, name, datatype)
729
-
730
- keys = ["x", "y", "z"]
731
- keys = [k for k in keys if k in kwargs and kwargs[k] is not None]
732
- val = np.concatenate([kwargs[k] for k in keys]).flatten()[0]
733
-
734
- block._data = [np.array(kwargs[k], dtype=val.dtype) for k in keys]
735
- block._data = [np.array(row, order="F") for row in block._data]
736
- block._data = tuple(block._data)
737
- block.ndims = len(block._data)
738
- block.ngrids = block.ndims
739
- grids = [row.ctypes.data_as(ct.c_void_p) for row in block._data]
740
- block.grids = (ct.c_void_p * block.ngrids)(*grids)
741
- if block._data[0].ndim == 1:
742
- block.blocktype = SdfBlockType.SDF_BLOCKTYPE_PLAIN_MESH
743
- block.AddBlock = BlockPlainMesh
744
- for i in range(block.ndims):
745
- block.dims[i] = block._data[i].shape[0]
746
- else:
747
- block.blocktype = SdfBlockType.SDF_BLOCKTYPE_LAGRANGIAN_MESH
748
- block.AddBlock = BlockLagrangianMesh
749
- for i in range(block.ndims):
750
- block.dims[i] = block._data[0].shape[i]
751
- if isinstance(units, (list, tuple)):
752
- block.dim_units = self._create_id_array(units)
753
- if isinstance(labels, (list, tuple)):
754
- block.dim_labels = self._create_id_array(labels)
755
- if isinstance(geometry, str):
756
- if geometry == "rz":
757
- geometry = SdfGeometry.SDF_GEOMETRY_CYLINDRICAL
758
- if isinstance(geometry, int):
759
- block.geometry = geometry
760
-
761
- self._clib.sdf_set_defaults(self._handle, block)
762
- self._add_post(block)
763
-
764
- def add_block(self, name, value=None, id=None, **kwargs):
765
- if isinstance(value, dict):
766
- val = next(iter(value.values()), None)
767
- add_func = self._add_namevalue
768
- elif isinstance(value, (tuple, list, np.ndarray)):
769
- arr = np.array(value)
770
- if arr.ndim == 1:
771
- val = value[0]
772
- add_func = self._add_array
773
- else:
774
- val = arr.flatten()[0]
775
- add_func = self._add_plainvar
776
- elif value is not None:
777
- val = value
778
- add_func = self._add_constant
779
- else:
780
- keys = ["x", "y", "z"]
781
- keys = [k for k in keys if k in kwargs and kwargs[k] is not None]
782
- val = np.concatenate([kwargs[k] for k in keys]).flatten()[0]
783
- add_func = self._add_mesh
784
- if id is None:
785
- id = "grid"
786
-
787
- if id is None:
788
- id = name
789
- if id in self._block_ids:
790
- print(f'Unable to create block. ID duplicated: "{id}"')
791
- return
792
-
793
- datatype = None
794
- if isinstance(val, bool):
795
- datatype = SdfDataType.SDF_DATATYPE_LOGICAL
796
- elif isinstance(val, np.int32):
797
- datatype = SdfDataType.SDF_DATATYPE_INTEGER4
798
- elif isinstance(val, (int, np.int64)):
799
- datatype = SdfDataType.SDF_DATATYPE_INTEGER8
800
- elif isinstance(val, np.float32):
801
- datatype = SdfDataType.SDF_DATATYPE_REAL4
802
- elif isinstance(val, float):
803
- datatype = SdfDataType.SDF_DATATYPE_REAL8
804
- elif isinstance(val, str):
805
- datatype = SdfDataType.SDF_DATATYPE_CHARACTER
806
- else:
807
- add_func = None
808
-
809
- if add_func:
810
- add_func(name, value=value, id=id, datatype=datatype, **kwargs)
811
- else:
812
- print(f'Block "{id}", unsupported datatype: {type(value)}')
813
- return
678
+ def _create_string_array(self, values):
679
+ values = self._string_array_ctype(values)
680
+ res = self._clib.sdf_create_string_array(
681
+ self._handle, len(values), values
682
+ )
683
+ return res
814
684
 
815
685
  @property
816
686
  def name_dict(self):
@@ -831,25 +701,31 @@ class Block:
831
701
 
832
702
  def __init__(self, block):
833
703
  self._handle = block._handle
834
- self._id = block.id.decode()
835
- self._name = block.name.decode()
704
+ if block.id_orig:
705
+ self._id = block.id_orig.decode()
706
+ self._name = block.name_orig.decode()
707
+ else:
708
+ self._id = block.id.decode()
709
+ self._name = block.name.decode()
836
710
  self._datatype = _np_datatypes[block.datatype_out]
837
711
  self._data_length = block.data_length
838
712
  self._dims = tuple(block.dims[: block.ndims])
839
713
  self._contents = block
840
714
  self._blocklist = block._blocklist
715
+ self._in_file = block.in_file
841
716
  self._data = None
717
+ self._grid = None
842
718
 
843
719
  def _numpy_from_buffer(self, data, blen):
844
- buffer_from_memory = ct.pythonapi.PyMemoryView_FromMemory
845
- buffer_from_memory.restype = ct.py_object
720
+ buffer_from_memory = _c.pythonapi.PyMemoryView_FromMemory
721
+ buffer_from_memory.restype = _c.py_object
846
722
  dtype = self._datatype
847
- if dtype == np.byte:
848
- dtype = np.dtype("|S1")
723
+ if dtype == _np.byte:
724
+ dtype = _np.dtype("|S1")
849
725
  totype = _ct_datatypes[self._contents.datatype_out]
850
- cast = ct.cast(data, ct.POINTER(totype))
726
+ cast = _c.cast(data, _c.POINTER(totype))
851
727
  buf = buffer_from_memory(cast, blen)
852
- return np.frombuffer(buf, dtype)
728
+ return _np.frombuffer(buf, dtype)
853
729
 
854
730
  @property
855
731
  def blocklist(self):
@@ -887,6 +763,73 @@ class Block:
887
763
  return self._name
888
764
 
889
765
 
766
+ class BlockRunInfo(Block, dict):
767
+ """Run info block"""
768
+
769
+ def __init__(self, block, info=None):
770
+ import datetime
771
+ from datetime import datetime as dtm
772
+
773
+ if isinstance(block, Block):
774
+ block = block._contents
775
+
776
+ Block.__init__(self, block)
777
+
778
+ if info is not None:
779
+ self._run_info = self._build_info(info)
780
+ block.data = _c.cast(_c.byref(self._run_info), _c.c_void_p)
781
+
782
+ utc = datetime.timezone.utc
783
+
784
+ h = _c.cast(block.data, _c.POINTER(RunInfo)).contents
785
+
786
+ self._dict = {
787
+ "version": f"{h.version}.{h.revision}.{h.minor_rev}",
788
+ "commit_id": h.commit_id.decode(),
789
+ "sha1sum": h.sha1sum.decode(),
790
+ "compile_machine": h.compile_machine.decode(),
791
+ "compile_flags": h.compile_flags.decode(),
792
+ "compile_date": dtm.fromtimestamp(h.compile_date, utc).strftime(
793
+ "%c"
794
+ ),
795
+ "run_date": dtm.fromtimestamp(h.run_date, utc).strftime("%c"),
796
+ "io_date": dtm.fromtimestamp(h.io_date, utc).strftime("%c"),
797
+ }
798
+
799
+ dict.__init__(self, self._dict)
800
+
801
+ def _build_info(self, info):
802
+ import datetime as dtm
803
+ import dateutil.parser as dtp
804
+
805
+ run_info = RunInfo()
806
+ fields = [f[0] for f in run_info._fields_]
807
+ for f in run_info._fields_:
808
+ if f[1] == _c.c_char_p:
809
+ setattr(run_info, f[0], "".encode())
810
+ else:
811
+ setattr(run_info, f[0], 0)
812
+ k = "version"
813
+ if k in info and isinstance(info[k], str):
814
+ ver = [int(s) for s in info[k].split(".")]
815
+ info[k] = ver[0]
816
+ if len(ver) > 1:
817
+ info["revision"] = ver[1]
818
+ if len(ver) > 2:
819
+ info["minor_rev"] = ver[2]
820
+ for k, v in info.items():
821
+ if k.endswith("_date"):
822
+ if isinstance(v, str):
823
+ date = dtp.parse(v)
824
+ date = date.replace(tzinfo=dtm.timezone.utc)
825
+ v = int(date.timestamp())
826
+ elif isinstance(v, dtm.datetime):
827
+ v = int(v.timestamp())
828
+ if k in fields:
829
+ setattr(run_info, k, v)
830
+ return run_info
831
+
832
+
890
833
  class BlockConstant(Block):
891
834
  """Constant block"""
892
835
 
@@ -907,7 +850,7 @@ class BlockPlainVariable(Block):
907
850
  if self._data is None:
908
851
  clib = self._handle._clib
909
852
  clib.sdf_helper_read_data(self._handle, self._contents)
910
- blen = np.dtype(self._datatype).itemsize
853
+ blen = _np.dtype(self._datatype).itemsize
911
854
  for d in self.dims:
912
855
  blen *= d
913
856
  array = self._numpy_from_buffer(self._contents.data, blen)
@@ -964,6 +907,7 @@ class BlockPlainMesh(Block):
964
907
  self._id += "_mid"
965
908
  self._name += "_mid"
966
909
  self._dims = tuple([i - 1 for i in self._dims])
910
+ self._in_file = False
967
911
  if bool(block.dim_mults):
968
912
  self._mult = tuple(block.dim_mults[: block.ndims])
969
913
  if bool(block.extents):
@@ -977,7 +921,7 @@ class BlockPlainMesh(Block):
977
921
  clib.sdf_helper_read_data(self._handle, self._contents)
978
922
  grids = []
979
923
  for i, d in enumerate(self._bdims):
980
- blen = np.dtype(self._datatype).itemsize * d
924
+ blen = _np.dtype(self._datatype).itemsize * d
981
925
  array = self._numpy_from_buffer(self._contents.grids[i], blen)
982
926
  if self._mid:
983
927
  array = 0.5 * (array[1:] + array[:-1])
@@ -1020,7 +964,7 @@ class BlockLagrangianMesh(BlockPlainMesh):
1020
964
  if self._data is None:
1021
965
  clib = self._handle._clib
1022
966
  clib.sdf_helper_read_data(self._handle, self._contents)
1023
- blen = np.dtype(self._datatype).itemsize
967
+ blen = _np.dtype(self._datatype).itemsize
1024
968
  for d in self._bdims:
1025
969
  blen *= d
1026
970
  grids = []
@@ -1067,13 +1011,13 @@ class BlockNameValue(Block):
1067
1011
  vals = {}
1068
1012
  for n in range(block.ndims):
1069
1013
  val = None
1070
- if block.datatype == SdfDataType.SDF_DATATYPE_CHARACTER:
1071
- p = ct.cast(block.data, ct.POINTER(ct.c_char_p))
1014
+ if block.datatype == SdfDataType.CHARACTER:
1015
+ p = _c.cast(block.data, _c.POINTER(_c.c_char_p))
1072
1016
  val = p[n].decode()
1073
1017
  else:
1074
1018
  dt = _ct_datatypes[block.datatype]
1075
- val = ct.cast(block.data, ct.POINTER(dt))[n]
1076
- nid = get_member_name(block.material_names[n])
1019
+ val = _c.cast(block.data, _c.POINTER(dt))[n]
1020
+ nid = _get_member_name(block.material_names[n])
1077
1021
  vals[nid] = val
1078
1022
  self.__dict__[nid] = val
1079
1023
  self._data = vals
@@ -1088,7 +1032,7 @@ class BlockArray(Block):
1088
1032
  if self._data is None:
1089
1033
  clib = self._handle._clib
1090
1034
  clib.sdf_helper_read_data(self._handle, self._contents)
1091
- blen = np.dtype(self._datatype).itemsize
1035
+ blen = _np.dtype(self._datatype).itemsize
1092
1036
  for d in self.dims:
1093
1037
  blen *= d
1094
1038
  array = self._numpy_from_buffer(self._contents.data, blen)
@@ -1112,7 +1056,7 @@ class BlockData(Block):
1112
1056
  clib = self._handle._clib
1113
1057
  clib.sdf_helper_read_data(self._handle, self._contents)
1114
1058
  blen = self._contents.data_length
1115
- _data = ct.cast(self._contents.data, ct.POINTER(ct.c_char * blen))
1059
+ _data = _c.cast(self._contents.data, _c.POINTER(_c.c_char * blen))
1116
1060
  self._data = _data.contents[:]
1117
1061
  return self._data
1118
1062
 
@@ -1132,7 +1076,7 @@ class BlockData(Block):
1132
1076
  return self._mimetype
1133
1077
 
1134
1078
 
1135
- def BlockStation(block, name):
1079
+ def _BlockStation(block, name):
1136
1080
  """Station block"""
1137
1081
  sdict = dict(
1138
1082
  stations=None,
@@ -1173,9 +1117,24 @@ class BlockStitched(Block):
1173
1117
  vid = self._contents.variable_ids[i]
1174
1118
  if len(vid) > 0:
1175
1119
  vid = vid.decode()
1176
- self._data.append(self._blocklist._block_ids[vid])
1120
+ if vid in self._blocklist._block_ids:
1121
+ self._data.append(self._blocklist._block_ids[vid])
1122
+ else:
1123
+ self._data.append(None)
1124
+ else:
1125
+ self._data.append(None)
1177
1126
  return self._data
1178
1127
 
1128
+ @property
1129
+ def grid(self):
1130
+ """Associated mesh"""
1131
+ return self._grid
1132
+
1133
+ @property
1134
+ def grid_id(self):
1135
+ """Associated mesh id"""
1136
+ return self._contents.mesh_id.decode()
1137
+
1179
1138
 
1180
1139
  class BlockStitchedPath(BlockStitched):
1181
1140
  """Stitched path block"""
@@ -1186,19 +1145,40 @@ class BlockStitchedPath(BlockStitched):
1186
1145
  class BlockStitchedMaterial(BlockStitched):
1187
1146
  """Stitched material block"""
1188
1147
 
1189
- pass
1148
+ @property
1149
+ def material_names(self):
1150
+ """Material names"""
1151
+ b = self._contents
1152
+ return [b.material_names[i].decode() for i in range(b.ndims)]
1190
1153
 
1191
1154
 
1192
1155
  class BlockStitchedMatvar(BlockStitched):
1193
1156
  """Stitched material variable block"""
1194
1157
 
1195
- pass
1158
+ @property
1159
+ def material_id(self):
1160
+ """Material ID"""
1161
+ return self._contents.material_id.decode()
1196
1162
 
1197
1163
 
1198
1164
  class BlockStitchedSpecies(BlockStitched):
1199
1165
  """Stitched species block"""
1200
1166
 
1201
- pass
1167
+ @property
1168
+ def material_id(self):
1169
+ """Material ID"""
1170
+ return self._contents.material_id.decode()
1171
+
1172
+ @property
1173
+ def material_name(self):
1174
+ """Material name"""
1175
+ return self._contents.material_name.decode()
1176
+
1177
+ @property
1178
+ def material_names(self):
1179
+ """Species names"""
1180
+ b = self._contents
1181
+ return [b.material_names[i].decode() for i in range(b.ndims)]
1202
1182
 
1203
1183
 
1204
1184
  class BlockStitchedTensor(BlockStitched):
@@ -1207,63 +1187,63 @@ class BlockStitchedTensor(BlockStitched):
1207
1187
  pass
1208
1188
 
1209
1189
 
1210
- def get_header(h):
1211
- d = {}
1212
- if h.filename:
1213
- d["filename"] = h.filename.decode()
1214
- d["file_version"] = h.file_version
1215
- d["file_revision"] = h.file_revision
1216
- if h.code_name:
1217
- d["code_name"] = h.code_name.decode()
1218
- d["step"] = h.step
1219
- d["time"] = h.time
1220
- d["jobid1"] = h.jobid1
1221
- d["jobid2"] = h.jobid2
1222
- d["code_io_version"] = h.code_io_version
1223
- d["restart_flag"] = h.restart_flag
1224
- d["other_domains"] = h.other_domains
1225
- d["station_file"] = h.station_file
1226
- return d
1227
-
1228
-
1229
- def get_run_info(block):
1230
- import datetime
1231
- from datetime import datetime as dtm
1232
-
1233
- utc = datetime.timezone.utc
1234
-
1235
- h = ct.cast(block.data, ct.POINTER(RunInfo)).contents
1236
- d = {}
1237
- d["version"] = f"{h.version}.{h.revision}.{h.minor_rev}"
1238
- d["commit_id"] = h.commit_id.decode()
1239
- d["sha1sum"] = h.sha1sum.decode()
1240
- d["compile_machine"] = h.compile_machine.decode()
1241
- d["compile_flags"] = h.compile_flags.decode()
1242
- d["compile_date"] = dtm.fromtimestamp(h.compile_date, utc).strftime("%c")
1243
- d["run_date"] = dtm.fromtimestamp(h.run_date, utc).strftime("%c")
1244
- d["io_data"] = dtm.fromtimestamp(h.io_date, utc).strftime("%c")
1245
- return d
1246
-
1247
-
1248
- def get_member_name(name):
1190
+ class BlockCpuSplit(Block):
1191
+ """CPU split block"""
1192
+
1193
+ def __init__(self, block):
1194
+ super().__init__(block)
1195
+ nelements = 0
1196
+ if self._contents.geometry in (1, 4):
1197
+ nelements = sum(self.dims)
1198
+ elif self._contents.geometry == 2:
1199
+ nelements, adim = 0, []
1200
+ for dim in self.dims:
1201
+ adim.append(dim)
1202
+ nelements += _np.prod(adim)
1203
+ elif self._contents.geometry == 3:
1204
+ nelements = _np.prod(self.dims)
1205
+ else:
1206
+ raise Exception("CPU split geometry not supported")
1207
+ self._contents.nelements = nelements
1208
+
1209
+ @property
1210
+ def data(self):
1211
+ """Block data contents"""
1212
+ if self._data is None:
1213
+ clib = self._handle._clib
1214
+ clib.sdf_helper_read_data(self._handle, self._contents)
1215
+ nelements = self._contents.nelements
1216
+ blen = _np.dtype(self._datatype).itemsize * nelements
1217
+ array = self._numpy_from_buffer(self._contents.data, blen)
1218
+ if self._contents.geometry in (1, 4):
1219
+ d0, data = 0, []
1220
+ for dim in self.dims:
1221
+ d1 = d0 + dim
1222
+ data.append(array[d0:d1])
1223
+ d0 = d1
1224
+ self._data = tuple(data)
1225
+ elif self._contents.geometry == 2:
1226
+ d0, data, adim = 0, [], []
1227
+ for dim in self.dims:
1228
+ adim.append(dim)
1229
+ d1 = d0 + _np.prod(adim)
1230
+ data.append(array[d0:d1].reshape(adim, order="F"))
1231
+ d0 = d1
1232
+ self._data = tuple(data)
1233
+ elif self._contents.geometry == 3:
1234
+ self._data = array.reshape(self.dims, order="F")
1235
+ return self._data
1236
+
1237
+
1238
+ _re_pattern = _re.compile(r"[^a-zA-Z0-9]")
1239
+
1240
+
1241
+ def _get_member_name(name):
1249
1242
  sname = name.decode()
1250
- return "".join(
1251
- [
1252
- (
1253
- i
1254
- if (
1255
- (i >= "a" and i <= "z")
1256
- or (i >= "A" and i <= "Z")
1257
- or (i >= "0" and i <= "9")
1258
- )
1259
- else "_"
1260
- )
1261
- for i in sname
1262
- ]
1263
- )
1243
+ return _re_pattern.sub("_", sname)
1264
1244
 
1265
1245
 
1266
- def read(file=None, convert=False, mmap=0, dict=False, derived=True):
1246
+ def _read(file=None, convert=False, mmap=0, dict=False, derived=True):
1267
1247
  """Reads the SDF data and returns a dictionary of NumPy arrays.
1268
1248
 
1269
1249
  Parameters
@@ -1297,7 +1277,7 @@ def read(file=None, convert=False, mmap=0, dict=False, derived=True):
1297
1277
  return blocklist
1298
1278
 
1299
1279
 
1300
- def new(dict=False, code_name="sdfr", restart=False):
1280
+ def _new(dict=False, code_name="sdfr", restart=False):
1301
1281
  """Creates a new SDF blocklist and returns a dictionary of NumPy arrays.
1302
1282
 
1303
1283
  Parameters
@@ -1306,7 +1286,9 @@ def new(dict=False, code_name="sdfr", restart=False):
1306
1286
  Return file contents as a dictionary rather than member names.
1307
1287
  """
1308
1288
 
1309
- blocklist = BlockList(mode=SDF_WRITE, code_name=code_name, restart=restart)
1289
+ blocklist = BlockList(
1290
+ mode=SdfMode.WRITE, code_name=code_name, restart=restart
1291
+ )
1310
1292
 
1311
1293
  if isinstance(dict, str):
1312
1294
  if dict == "id" or dict == "ids":
@@ -1315,3 +1297,701 @@ def new(dict=False, code_name="sdfr", restart=False):
1315
1297
  return blocklist._block_names
1316
1298
 
1317
1299
  return blocklist
1300
+
1301
+
1302
+ def _get_md5(data):
1303
+ return _hashlib.md5(data).hexdigest()
1304
+
1305
+
1306
+ def _get_sha(data):
1307
+ sha = _hashlib.sha256()
1308
+ try:
1309
+ with _io.BytesIO(data) as buf:
1310
+ with _tarfile.open(mode="r:*", fileobj=buf) as file:
1311
+ for name in sorted(file.getnames()):
1312
+ fd = file.extractfile(name)
1313
+ if fd:
1314
+ sha.update(fd.read())
1315
+ fd.close()
1316
+ except Exception:
1317
+ try:
1318
+ sha.update(_gzip.decompress(data))
1319
+ except Exception:
1320
+ sha.update(data)
1321
+ return sha.hexdigest()
1322
+
1323
+
1324
+ def _get_tarfile_data(source=None):
1325
+ if not source or not _os.path.exists(source):
1326
+ return source
1327
+ if _os.path.isdir(source):
1328
+ buf = _io.BytesIO()
1329
+ with _tarfile.open("out", "w:gz", fileobj=buf) as tar:
1330
+ tar.add(source)
1331
+ buf.seek(0)
1332
+ return buf.read()
1333
+ else:
1334
+ with open(source, "rb") as fd:
1335
+ return fd.read()
1336
+
1337
+
1338
+ def _get_mimetype(data):
1339
+ try:
1340
+ _ = _gzip.decompress(data)
1341
+ return "application/gzip"
1342
+ except Exception:
1343
+ pass
1344
+ try:
1345
+ buf = _io.BytesIO(data)
1346
+ _ = _tarfile.open(mode="r:*", fileobj=buf)
1347
+ return "application/tar"
1348
+ except Exception:
1349
+ return "text/plain"
1350
+
1351
+
1352
+ def _get_checksum_info(value=None, checksum_type=None):
1353
+ if not value:
1354
+ return None, None, None, value
1355
+ data = _get_tarfile_data(value)
1356
+ mimetype = _get_mimetype(data)
1357
+ if checksum_type is None:
1358
+ if mimetype == "text/plain":
1359
+ checksum_type = "md5"
1360
+ else:
1361
+ checksum_type = "sha256"
1362
+ if checksum_type == "md5":
1363
+ checksum = _get_md5(data)
1364
+ else:
1365
+ checksum = _get_sha(data)
1366
+
1367
+ return checksum, checksum_type, mimetype, data
1368
+
1369
+
1370
+ def _add_preamble(blocklist, id, name, datatype):
1371
+ blocklist._clib.sdf_get_next_block(blocklist._handle)
1372
+ h = blocklist._handle.contents
1373
+ h.nblocks += 1
1374
+ h.nblocks_file += 1
1375
+ block = h.current_block.contents
1376
+ block._handle = blocklist._handle
1377
+ block._blocklist = h.blocklist
1378
+ block._data = None
1379
+ block.datatype = datatype
1380
+ block.in_file = 1
1381
+ block.AddBlock = None
1382
+ blocklist._set_block_name(id, name)
1383
+ return h, block
1384
+
1385
+
1386
+ def _add_post(blocklist, block, extra=None):
1387
+ if block.AddBlock:
1388
+ if extra is None:
1389
+ newblock = block.AddBlock(block)
1390
+ else:
1391
+ newblock = block.AddBlock(block, extra)
1392
+ else:
1393
+ return
1394
+
1395
+ id = block.id.decode()
1396
+ name = block.name.decode()
1397
+ if not block.dont_display:
1398
+ blocklist.__dict__[name] = newblock
1399
+ if block._data is not None:
1400
+ newblock._data = block._data
1401
+ blocklist._block_ids.update({id: newblock})
1402
+ blocklist._block_names.update({name: newblock})
1403
+
1404
+
1405
+ def _add_constant(blocklist, name, value=0, datatype=None, id=None):
1406
+ h, block = _add_preamble(blocklist, id, name, datatype)
1407
+ block.blocktype = SdfBlockType.CONSTANT
1408
+ block.AddBlock = BlockConstant
1409
+
1410
+ const_value = _struct.pack(_st_datatypes[block.datatype], value)
1411
+ _c.memmove(block.const_value, const_value, 16)
1412
+
1413
+ _add_post(blocklist, block)
1414
+
1415
+
1416
+ def _add_namevalue(blocklist, name, value={}, datatype=None, id=None):
1417
+ h, block = _add_preamble(blocklist, id, name, datatype)
1418
+ block.blocktype = SdfBlockType.NAMEVALUE
1419
+ block.AddBlock = BlockNameValue
1420
+
1421
+ nvalue = len(value)
1422
+ block.ndims = nvalue
1423
+ ctype = _ct_datatypes[block.datatype]
1424
+ if block.datatype == SdfDataType.CHARACTER:
1425
+ vals = blocklist._string_array_ctype(value.values())
1426
+ else:
1427
+ vals = (ctype * nvalue)(*value.values())
1428
+ names = blocklist._string_array_ctype(value.keys())
1429
+ vals = _c.cast(vals, _c.POINTER(_c.c_void_p))
1430
+ blocklist._clib.sdf_set_namevalue(block, names, vals)
1431
+
1432
+ _add_post(blocklist, block)
1433
+
1434
+
1435
+ def _add_array(blocklist, name, value=(), datatype=None, id=None):
1436
+ h, block = _add_preamble(blocklist, id, name, datatype)
1437
+ block.blocktype = SdfBlockType.ARRAY
1438
+ block.AddBlock = BlockArray
1439
+
1440
+ block._data = _np.array(value)
1441
+ block.ndims = block._data.ndim
1442
+ for i in range(block.ndims):
1443
+ block.dims[i] = block._data.shape[i]
1444
+ block.data = block._data.ctypes.data_as(_c.c_void_p)
1445
+
1446
+ _add_post(blocklist, block)
1447
+
1448
+
1449
+ def _add_cpu_split(
1450
+ blocklist, name, value=(), id=None, datatype=None, geometry=1
1451
+ ):
1452
+ from itertools import chain
1453
+
1454
+ if not isinstance(blocklist, BlockList):
1455
+ print("ERROR: first argument must be of type BlockList")
1456
+ return
1457
+ if id is None:
1458
+ id = name
1459
+ if datatype is None:
1460
+ if geometry == 4:
1461
+ datatype = SdfDataType.INTEGER8
1462
+ else:
1463
+ datatype = SdfDataType.INTEGER4
1464
+ h, block = _add_preamble(blocklist, id, name, datatype)
1465
+ block.blocktype = SdfBlockType.CPU_SPLIT
1466
+ block.AddBlock = BlockCpuSplit
1467
+
1468
+ dtype = _np_datatypes[datatype]
1469
+ block._data = _np.asarray(list(chain.from_iterable(value)), dtype=dtype)
1470
+ block.ndims = len(value)
1471
+ block.geometry = geometry
1472
+ dims = []
1473
+ for i in range(block.ndims):
1474
+ dims.append(len(value[i]))
1475
+ block.dims[i] = len(value[i])
1476
+
1477
+ block.data = block._data.ctypes.data_as(_c.c_void_p)
1478
+
1479
+ _add_post(blocklist, block)
1480
+
1481
+
1482
+ def _add_datablock(
1483
+ blocklist,
1484
+ name,
1485
+ value=(),
1486
+ id=None,
1487
+ checksum=None,
1488
+ checksum_type=None,
1489
+ mimetype=None,
1490
+ datatype=None,
1491
+ ):
1492
+ datatype = SdfDataType.CHARACTER
1493
+ h, block = _add_preamble(blocklist, id, name, datatype)
1494
+ block.blocktype = SdfBlockType.DATABLOCK
1495
+ block.AddBlock = BlockData
1496
+
1497
+ if not checksum:
1498
+ checksum, checksum_type, mimetype, value = _get_checksum_info(
1499
+ value, checksum_type
1500
+ )
1501
+
1502
+ if isinstance(checksum, str):
1503
+ block.checksum = blocklist._create_string(checksum)
1504
+ if isinstance(checksum_type, str):
1505
+ block.checksum_type = blocklist._create_id(checksum_type)
1506
+ if isinstance(mimetype, str):
1507
+ block.mimetype = blocklist._create_id(mimetype)
1508
+
1509
+ block._data = _np.array(value)
1510
+ block.ndims = 0
1511
+ block.nelements = len(value)
1512
+ block.data = block._data.ctypes.data_as(_c.c_void_p)
1513
+
1514
+ _add_post(blocklist, block)
1515
+
1516
+
1517
+ def _add_plainvar(
1518
+ blocklist,
1519
+ name,
1520
+ value=(),
1521
+ datatype=None,
1522
+ id=None,
1523
+ mult=None,
1524
+ units=None,
1525
+ mesh_id=None,
1526
+ stagger=None,
1527
+ species=None,
1528
+ ):
1529
+ try:
1530
+ mult = float(mult)
1531
+ except Exception:
1532
+ if mult is not None:
1533
+ print(f"ERROR: unable to use mult parameter, {mult}")
1534
+ return
1535
+ try:
1536
+ stagger = SdfStagger(stagger)
1537
+ except Exception:
1538
+ if stagger is not None:
1539
+ print(f"ERROR: unable to use stagger parameter, {stagger}")
1540
+ return
1541
+ if units is not None and not isinstance(units, str):
1542
+ print(f"ERROR: unable to use units parameter, {units}")
1543
+ return
1544
+ if mesh_id is not None and not isinstance(mesh_id, str):
1545
+ print(f"ERROR: unable to use mesh_id parameter, {mesh_id}")
1546
+ return
1547
+
1548
+ h, block = _add_preamble(blocklist, id, name, datatype)
1549
+
1550
+ block._data = _np.array(value, order="F")
1551
+ block.ndims = block._data.ndim
1552
+
1553
+ if block.ndims == 1 and isinstance(species, str):
1554
+ block.blocktype = SdfBlockType.POINT_VARIABLE
1555
+ block.AddBlock = BlockPointVariable
1556
+ block.material_id = blocklist._create_id(species)
1557
+ else:
1558
+ block.blocktype = SdfBlockType.PLAIN_VARIABLE
1559
+ block.AddBlock = BlockPlainVariable
1560
+
1561
+ for i in range(block.ndims):
1562
+ block.dims[i] = block._data.shape[i]
1563
+ block.data = block._data.ctypes.data_as(_c.c_void_p)
1564
+ if mult is not None:
1565
+ block.mult = mult
1566
+ if isinstance(units, str):
1567
+ block.units = blocklist._create_id(units)
1568
+ if isinstance(mesh_id, str):
1569
+ block.mesh_id = blocklist._create_id(mesh_id)
1570
+ if stagger:
1571
+ block.stagger = stagger
1572
+
1573
+ blocklist._clib.sdf_set_defaults(blocklist._handle, block)
1574
+ _add_post(blocklist, block)
1575
+
1576
+
1577
+ def _add_mesh(
1578
+ blocklist,
1579
+ name,
1580
+ value=None,
1581
+ datatype=None,
1582
+ id=None,
1583
+ units=None,
1584
+ labels=None,
1585
+ geometry=None,
1586
+ species=None,
1587
+ **kwargs,
1588
+ ):
1589
+ h, block = _add_preamble(blocklist, id, name, datatype)
1590
+
1591
+ keys = ["x", "y", "z"]
1592
+ keys = [k for k in keys if k in kwargs and kwargs[k] is not None]
1593
+ val = _np.concatenate([kwargs[k] for k in keys]).flatten()[0]
1594
+
1595
+ block._data = [_np.array(kwargs[k], dtype=val.dtype) for k in keys]
1596
+ block._data = [_np.array(row, order="F") for row in block._data]
1597
+ block._data = tuple(block._data)
1598
+ block.ndims = len(block._data)
1599
+ block.ngrids = block.ndims
1600
+ grids = [row.ctypes.data_as(_c.c_void_p) for row in block._data]
1601
+ block.grids = (_c.c_void_p * block.ngrids)(*grids)
1602
+ if block._data[0].ndim == 1:
1603
+ block.blocktype = SdfBlockType.PLAIN_MESH
1604
+ block.AddBlock = BlockPlainMesh
1605
+ for i in range(block.ndims):
1606
+ block.dims[i] = block._data[i].shape[0]
1607
+ if isinstance(species, str):
1608
+ block.blocktype = SdfBlockType.POINT_MESH
1609
+ block.AddBlock = BlockPointMesh
1610
+ block.material_id = blocklist._create_id(species)
1611
+ else:
1612
+ block.blocktype = SdfBlockType.LAGRANGIAN_MESH
1613
+ block.AddBlock = BlockLagrangianMesh
1614
+ for i in range(block.ndims):
1615
+ block.dims[i] = block._data[0].shape[i]
1616
+ if isinstance(units, str):
1617
+ units = (units,)
1618
+ if isinstance(units, (list, tuple)):
1619
+ block.dim_units = blocklist._create_id_array(units)
1620
+ if isinstance(labels, str):
1621
+ labels = (labels,)
1622
+ if isinstance(labels, (list, tuple)):
1623
+ block.dim_labels = blocklist._create_id_array(labels)
1624
+ if isinstance(geometry, str):
1625
+ if geometry == "rz":
1626
+ geometry = SdfGeometry.CYLINDRICAL
1627
+ if isinstance(geometry, int):
1628
+ block.geometry = geometry
1629
+
1630
+ blocklist._clib.sdf_set_defaults(blocklist._handle, block)
1631
+ _add_post(blocklist, block)
1632
+
1633
+
1634
+ def _add_stitched(
1635
+ blocklist,
1636
+ name,
1637
+ value={},
1638
+ id=None,
1639
+ mesh_id=None,
1640
+ btype=None,
1641
+ datatype=None,
1642
+ stagger=SdfStagger.HIDDEN0,
1643
+ material_id=None,
1644
+ material_name=None,
1645
+ material_names=None,
1646
+ ):
1647
+ if not isinstance(blocklist, BlockList):
1648
+ print("ERROR: first argument must be of type BlockList")
1649
+ return
1650
+ if not isinstance(value, (list, tuple)):
1651
+ print("ERROR: invalid value supplied for stitched block")
1652
+ return
1653
+ if not isinstance(mesh_id, str):
1654
+ found_mesh = None
1655
+ warn = True
1656
+ for val in value:
1657
+ if val in blocklist._block_ids:
1658
+ tmp = blocklist._block_ids[val]._contents.mesh_id
1659
+ if isinstance(tmp, bytes):
1660
+ tmp = tmp.decode()
1661
+ if warn and found_mesh is not None and found_mesh != tmp:
1662
+ print("WARNING: stitched blocks on different meshes")
1663
+ warn = False
1664
+ found_mesh = tmp
1665
+ else:
1666
+ print(f'WARNING: stitched id "{val}" not found in blocklist')
1667
+ if found_mesh is not None:
1668
+ mesh_id = found_mesh
1669
+ else:
1670
+ print("ERROR: no mesh_id supplied for stitched block")
1671
+ return
1672
+ if id is None:
1673
+ id = name
1674
+ if datatype is None:
1675
+ datatype = SdfDataType.NULL
1676
+ h, block = _add_preamble(blocklist, id, name, datatype)
1677
+
1678
+ if btype is None:
1679
+ btype = SdfBlockType.STITCHED
1680
+ block.blocktype = btype
1681
+
1682
+ if btype in (
1683
+ SdfBlockType.CONTIGUOUS_TENSOR,
1684
+ SdfBlockType.STITCHED_TENSOR,
1685
+ ):
1686
+ block.AddBlock = BlockStitchedTensor
1687
+ elif btype in (
1688
+ SdfBlockType.CONTIGUOUS_MATERIAL,
1689
+ SdfBlockType.STITCHED_MATERIAL,
1690
+ ):
1691
+ block.AddBlock = BlockStitchedMaterial
1692
+ block.material_names = blocklist._create_string_array(material_names)
1693
+ elif btype in (
1694
+ SdfBlockType.CONTIGUOUS_MATVAR,
1695
+ SdfBlockType.STITCHED_MATVAR,
1696
+ ):
1697
+ block.AddBlock = BlockStitchedMatvar
1698
+ block.material_id = blocklist._create_id(material_id)
1699
+ elif btype in (
1700
+ SdfBlockType.CONTIGUOUS_SPECIES,
1701
+ SdfBlockType.STITCHED_SPECIES,
1702
+ ):
1703
+ block.AddBlock = BlockStitchedSpecies
1704
+ block.material_id = blocklist._create_id(material_id)
1705
+ block.material_name = blocklist._create_string(material_name)
1706
+ block.material_names = blocklist._create_id_array(material_names)
1707
+ else:
1708
+ if stagger in (SdfStagger.HIDDEN0, SdfStagger.HIDDEN2):
1709
+ block.AddBlock = BlockStitchedPath
1710
+ else:
1711
+ block.AddBlock = BlockStitched
1712
+
1713
+ block.stagger = stagger
1714
+ nvalue = len(value)
1715
+ block.ndims = nvalue
1716
+ block.mesh_id = blocklist._create_id(mesh_id)
1717
+ block.variable_ids = blocklist._create_id_array(value)
1718
+ block._blocklist._block_ids = blocklist._block_ids
1719
+
1720
+ _add_post(blocklist, block)
1721
+
1722
+
1723
+ def _add_stitched_vector(blocklist, name, value={}, id=None, mesh_id=None):
1724
+ return _add_stitched(
1725
+ blocklist,
1726
+ name,
1727
+ value,
1728
+ id,
1729
+ mesh_id,
1730
+ btype=SdfBlockType.STITCHED_TENSOR,
1731
+ )
1732
+
1733
+
1734
+ def _add_stitched_material(
1735
+ blocklist, name, value={}, id=None, mesh_id=None, material_names=None
1736
+ ):
1737
+ return _add_stitched(
1738
+ blocklist,
1739
+ name,
1740
+ value,
1741
+ id,
1742
+ mesh_id,
1743
+ material_names=material_names,
1744
+ btype=SdfBlockType.STITCHED_MATERIAL,
1745
+ )
1746
+
1747
+
1748
+ def _add_stitched_matvar(
1749
+ blocklist, name, value={}, id=None, mesh_id=None, material_id=None
1750
+ ):
1751
+ return _add_stitched(
1752
+ blocklist,
1753
+ name,
1754
+ value,
1755
+ id,
1756
+ mesh_id,
1757
+ material_id=material_id,
1758
+ btype=SdfBlockType.STITCHED_MATVAR,
1759
+ )
1760
+
1761
+
1762
+ def _add_stitched_species(
1763
+ blocklist,
1764
+ name,
1765
+ value={},
1766
+ id=None,
1767
+ mesh_id=None,
1768
+ material_id=None,
1769
+ material_name=None,
1770
+ material_names=None,
1771
+ ):
1772
+ return _add_stitched(
1773
+ blocklist,
1774
+ name,
1775
+ value,
1776
+ id,
1777
+ mesh_id,
1778
+ material_id=material_id,
1779
+ material_name=material_name,
1780
+ material_names=material_names,
1781
+ btype=SdfBlockType.STITCHED_SPECIES,
1782
+ )
1783
+
1784
+
1785
+ def _add_runinfo(blocklist, name, value=None, **kwargs):
1786
+ if not isinstance(blocklist, BlockList):
1787
+ print("ERROR: first argument must be of type BlockList")
1788
+ return
1789
+ id = None
1790
+ args = None
1791
+ data = None
1792
+ if isinstance(value, Block):
1793
+ id = value.id
1794
+ name = value.name
1795
+ data = value._contents.data
1796
+ elif isinstance(name, dict) and value is None:
1797
+ args = name
1798
+ name = None
1799
+ else:
1800
+ args = value
1801
+
1802
+ if "id" in kwargs:
1803
+ id = kwargs["id"]
1804
+
1805
+ if name is None:
1806
+ name = "Run_info"
1807
+ if id is None:
1808
+ id = name.lower()
1809
+
1810
+ datatype = SdfDataType.CHARACTER
1811
+ h, block = _add_preamble(blocklist, id, name, datatype)
1812
+ block.blocktype = SdfBlockType.RUN_INFO
1813
+ block.AddBlock = BlockRunInfo
1814
+
1815
+ block.data = data
1816
+
1817
+ _add_post(blocklist, block, args)
1818
+
1819
+
1820
+ def _copy_block(blocklist, block=None, **kwargs):
1821
+ if not block._in_file:
1822
+ return
1823
+
1824
+ _ = block.data
1825
+ kwargs["value"] = block.data
1826
+ kwargs["id"] = block.id
1827
+ kwargs["name"] = block.name
1828
+ kwargs["datatype"] = SdfDataType(block._contents.datatype)
1829
+
1830
+ if isinstance(block, BlockConstant):
1831
+ _add_constant(blocklist, **kwargs)
1832
+ elif isinstance(block, BlockNameValue):
1833
+ _add_namevalue(blocklist, **kwargs)
1834
+ elif isinstance(block, BlockArray):
1835
+ _add_array(blocklist, **kwargs)
1836
+ elif isinstance(block, BlockRunInfo):
1837
+ kwargs["value"] = block
1838
+ _add_runinfo(blocklist, **kwargs)
1839
+ elif isinstance(block, BlockData):
1840
+ kwargs["checksum"] = block.checksum
1841
+ kwargs["checksum_type"] = block.checksum_type
1842
+ kwargs["mimetype"] = block.mimetype
1843
+ del kwargs["datatype"]
1844
+ _add_datablock(blocklist, **kwargs)
1845
+ elif isinstance(block, BlockPlainVariable):
1846
+ kwargs["mult"] = block.mult
1847
+ kwargs["units"] = block.units
1848
+ kwargs["mesh_id"] = block.grid_id
1849
+ kwargs["stagger"] = block.stagger
1850
+ if hasattr(block, "species_id"):
1851
+ kwargs["species"] = block.species_id
1852
+ _add_plainvar(blocklist, **kwargs)
1853
+ elif isinstance(block, BlockPlainMesh):
1854
+ if len(block.data) > 0:
1855
+ kwargs["x"] = block.data[0]
1856
+ if len(block.data) > 1:
1857
+ kwargs["y"] = block.data[1]
1858
+ if len(block.data) > 2:
1859
+ kwargs["z"] = block.data[2]
1860
+ if hasattr(block, "species_id"):
1861
+ kwargs["species"] = block.species_id
1862
+ kwargs["units"] = block.units
1863
+ kwargs["labels"] = block.labels
1864
+ kwargs["geometry"] = block.geometry
1865
+ _add_mesh(blocklist, **kwargs)
1866
+ elif isinstance(block, BlockStitched):
1867
+ b = block._contents
1868
+ btype = b.blocktype
1869
+ kwargs["mesh_id"] = b.mesh_id.decode()
1870
+ kwargs["value"] = [d.id if d else "" for d in block.data]
1871
+ kwargs["stagger"] = b.stagger
1872
+ kwargs["btype"] = btype
1873
+
1874
+ if btype in (
1875
+ SdfBlockType.CONTIGUOUS_MATERIAL,
1876
+ SdfBlockType.STITCHED_MATERIAL,
1877
+ ):
1878
+ kwargs["material_names"] = [
1879
+ b.material_names[i].decode() for i in range(b.ndims)
1880
+ ]
1881
+ elif btype in (
1882
+ SdfBlockType.CONTIGUOUS_MATVAR,
1883
+ SdfBlockType.STITCHED_MATVAR,
1884
+ ):
1885
+ kwargs["material_id"] = b.material_id.decode()
1886
+ elif btype in (
1887
+ SdfBlockType.CONTIGUOUS_SPECIES,
1888
+ SdfBlockType.STITCHED_SPECIES,
1889
+ ):
1890
+ kwargs["material_id"] = b.material_id.decode()
1891
+ kwargs["material_name"] = b.material_name.decode()
1892
+ kwargs["material_names"] = [
1893
+ b.material_names[i].decode() for i in range(b.ndims)
1894
+ ]
1895
+
1896
+ _add_stitched(blocklist, **kwargs)
1897
+ elif isinstance(block, BlockCpuSplit):
1898
+ kwargs["geometry"] = block._contents.geometry
1899
+ _add_cpu_split(blocklist, **kwargs)
1900
+ else:
1901
+ print(
1902
+ f'WARNING: block id "{block.id}" of type '
1903
+ f'"{type(block).__name__}" not supported'
1904
+ )
1905
+ return
1906
+
1907
+
1908
+ def _add_block(blocklist, name=None, value=None, id=None, **kwargs):
1909
+ if not isinstance(blocklist, BlockList):
1910
+ print("ERROR: first argument must be of type BlockList")
1911
+ return
1912
+ if isinstance(name, Block):
1913
+ return _copy_block(blocklist, block=name, value=value, id=id, **kwargs)
1914
+
1915
+ add_func = None
1916
+ if isinstance(value, dict):
1917
+ val = next(iter(value.values()), None)
1918
+ add_func = _add_namevalue
1919
+ elif isinstance(value, (tuple, list, _np.ndarray)):
1920
+ arr = _np.array(value)
1921
+ if arr.ndim == 1:
1922
+ val = value[0]
1923
+ if isinstance(arr[0], str):
1924
+ add_func = _add_stitched
1925
+ elif "species" in kwargs or "mesh_id" in kwargs:
1926
+ add_func = _add_plainvar
1927
+ else:
1928
+ add_func = _add_array
1929
+ else:
1930
+ val = arr.flatten()[0]
1931
+ add_func = _add_plainvar
1932
+ elif isinstance(value, (str, bytes)):
1933
+ val = value
1934
+ add_func = _add_datablock
1935
+ elif value is not None:
1936
+ val = value
1937
+ add_func = _add_constant
1938
+ else:
1939
+ keys = ["x", "y", "z"]
1940
+ keys = [k for k in keys if k in kwargs and kwargs[k] is not None]
1941
+ if len(keys) > 0:
1942
+ val = _np.concatenate([kwargs[k] for k in keys]).flatten()[0]
1943
+ add_func = _add_mesh
1944
+ if id is None:
1945
+ k = "species"
1946
+ if k in kwargs:
1947
+ id = f"grid/{kwargs[k]}"
1948
+ else:
1949
+ id = "grid"
1950
+
1951
+ if id is None:
1952
+ id = name
1953
+ if id in blocklist._block_ids:
1954
+ print(f'Unable to create block. ID duplicated: "{id}"')
1955
+ return
1956
+
1957
+ datatype = None
1958
+ if isinstance(val, (bool, _np.bool)):
1959
+ datatype = SdfDataType.LOGICAL
1960
+ elif isinstance(val, _np.int32):
1961
+ datatype = SdfDataType.INTEGER4
1962
+ elif isinstance(val, (int, _np.int64)):
1963
+ datatype = SdfDataType.INTEGER8
1964
+ elif isinstance(val, _np.float32):
1965
+ datatype = SdfDataType.REAL4
1966
+ elif isinstance(val, float):
1967
+ datatype = SdfDataType.REAL8
1968
+ elif isinstance(val, str) or isinstance(val, bytes):
1969
+ datatype = SdfDataType.CHARACTER
1970
+ if add_func not in (
1971
+ _add_namevalue,
1972
+ _add_datablock,
1973
+ _add_stitched,
1974
+ ):
1975
+ add_func = None
1976
+ else:
1977
+ add_func = None
1978
+
1979
+ if add_func:
1980
+ add_func(
1981
+ blocklist, name, value=value, id=id, datatype=datatype, **kwargs
1982
+ )
1983
+ else:
1984
+ print(f'Block "{id}", unsupported datatype: {type(value)}')
1985
+ return
1986
+
1987
+
1988
+ def _write(blocklist, filename):
1989
+ if not isinstance(blocklist, BlockList):
1990
+ print("ERROR: first argument must be of type BlockList")
1991
+ return
1992
+ if not blocklist._handle:
1993
+ return
1994
+ for k, b in blocklist._block_ids.items():
1995
+ if isinstance(b, Block) and b._contents.in_file:
1996
+ _ = b.data
1997
+ blocklist._clib.sdf_write(blocklist._handle, filename.encode())