io4dolfinx 1.1.0__py3-none-any.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.
io4dolfinx/__init__.py ADDED
@@ -0,0 +1,65 @@
1
+ # Copyright (C) 2023 Jørgen Schartum Dokken
2
+ #
3
+ # This file is part of io4dolfinx
4
+ #
5
+ # SPDX-License-Identifier: MIT
6
+
7
+ """Top-level package for ADIOS2Wrappers."""
8
+
9
+ from importlib.metadata import metadata
10
+
11
+ from .backends import FileMode, get_backend
12
+ from .checkpointing import (
13
+ read_attributes,
14
+ read_function,
15
+ read_function_names,
16
+ read_mesh,
17
+ read_meshtags,
18
+ read_timestamps,
19
+ write_attributes,
20
+ write_cell_data,
21
+ write_function,
22
+ write_mesh,
23
+ write_meshtags,
24
+ write_point_data,
25
+ )
26
+ from .original_checkpoint import write_function_on_input_mesh, write_mesh_input_order
27
+ from .readers import (
28
+ read_cell_data,
29
+ read_function_from_legacy_h5,
30
+ read_mesh_from_legacy_h5,
31
+ read_point_data,
32
+ )
33
+ from .snapshot import snapshot_checkpoint
34
+
35
+ meta = metadata("io4dolfinx")
36
+ __version__ = meta["Version"]
37
+ __author__ = meta.get("Author", "")
38
+ __license__ = meta["License"]
39
+ __email__ = meta["Author-email"]
40
+ __program_name__ = meta["Name"]
41
+
42
+ __all__ = [
43
+ "FileMode",
44
+ "write_meshtags",
45
+ "read_meshtags",
46
+ "read_cell_data",
47
+ "read_mesh",
48
+ "write_mesh",
49
+ "read_function_from_legacy_h5",
50
+ "read_mesh_from_legacy_h5",
51
+ "write_function",
52
+ "read_function",
53
+ "snapshot_checkpoint",
54
+ "write_function_on_input_mesh",
55
+ "write_mesh_input_order",
56
+ "write_attributes",
57
+ "write_data",
58
+ "read_attributes",
59
+ "read_function_names",
60
+ "read_point_data",
61
+ "read_timestamps",
62
+ "get_backend",
63
+ "write_cell_data",
64
+ "write_point_data",
65
+ ]
@@ -0,0 +1,437 @@
1
+ from enum import Enum
2
+ from importlib import import_module
3
+ from pathlib import Path
4
+ from typing import Any, Protocol
5
+
6
+ from mpi4py import MPI
7
+
8
+ import dolfinx
9
+ import numpy as np
10
+ import numpy.typing as npt
11
+
12
+ from ..structures import ArrayData, FunctionData, MeshData, MeshTagsData, ReadMeshData
13
+
14
+ __all__ = ["FileMode", "IOBackend", "get_backend"]
15
+
16
+
17
+ class ReadMode(Enum):
18
+ serial = 10 # This means that all data is read in on root rank
19
+
20
+ # Total number of data P, num processes = i + 1.
21
+ # All processes reads at least `P // (i+1)` items
22
+ # The first j=P%(i+1) processes reads `P // (i+1) + 1` items
23
+ # ```python
24
+ # def compute_partitioning(P, J):
25
+ # min_num = P // J
26
+ # num_per_proc = np.full(J, min_num)
27
+ # rem = P % J
28
+ # num_per_proc[:int(rem)] += 1
29
+ # assert(sum(num_per_proc)) == P
30
+ # return num_per_proc
31
+ # ```
32
+ parallel = 20
33
+
34
+
35
+ class FileMode(Enum):
36
+ """Filen mode used for opening files."""
37
+
38
+ append = 10 #: Append data to file
39
+ write = 20 #: Write data to file
40
+ read = 30 #: Read data from file
41
+
42
+
43
+ # See https://peps.python.org/pep-0544/#modules-as-implementations-of-protocols
44
+ class IOBackend(Protocol):
45
+ read_mode: ReadMode
46
+
47
+ def get_default_backend_args(self, arguments: dict[str, Any] | None) -> dict[str, Any]:
48
+ """Get default backend arguments given a set of input arguments.
49
+
50
+ Args:
51
+ arguments: Input backend arguments
52
+
53
+ Returns:
54
+ Updated backend arguments
55
+ """
56
+
57
+ def write_attributes(
58
+ self,
59
+ filename: Path | str,
60
+ comm: MPI.Intracomm,
61
+ name: str,
62
+ attributes: dict[str, np.ndarray],
63
+ backend_args: dict[str, Any] | None,
64
+ ):
65
+ """Write attributes to file.
66
+
67
+ Args:
68
+ filename: Path to file to write to
69
+ comm: MPI communicator used in storage
70
+ name: Name of the attribute group
71
+ attributes: Dictionary of attributes to write
72
+ backend_args: Arguments to backend
73
+ """
74
+
75
+ def read_attributes(
76
+ self,
77
+ filename: Path | str,
78
+ comm: MPI.Intracomm,
79
+ name: str,
80
+ backend_args: dict[str, Any] | None,
81
+ ) -> dict[str, Any]:
82
+ """Read attributes from file.
83
+
84
+ Args:
85
+ filename: Path to file to read from
86
+ comm: MPI communicator used in storage
87
+ name: Name of the attribute group
88
+ backend_args: Arguments to backend
89
+
90
+ Returns:
91
+ Dictionary of attributes read from file
92
+ """
93
+
94
+ def read_timestamps(
95
+ self,
96
+ filename: Path | str,
97
+ comm: MPI.Intracomm,
98
+ function_name: str,
99
+ backend_args: dict[str, Any] | None,
100
+ ) -> npt.NDArray[np.float64 | str]: # type: ignore[type-var]
101
+ """Read timestamps from file.
102
+
103
+ Args:
104
+ filename: Path to file to read from
105
+ comm: MPI communicator used in storage
106
+ function_name: Name of the function to read timestamps for
107
+ backend_args: Arguments to backend
108
+
109
+ Returns:
110
+ Numpy array of timestamps read from file
111
+ """
112
+
113
+ def write_mesh(
114
+ self,
115
+ filename: Path | str,
116
+ comm: MPI.Intracomm,
117
+ mesh: MeshData,
118
+ backend_args: dict[str, Any] | None,
119
+ mode: FileMode,
120
+ time: float,
121
+ ):
122
+ """
123
+ Write a mesh to file.
124
+
125
+ Args:
126
+ comm: MPI communicator used in storage
127
+ mesh: Internal data structure for the mesh data to save to file
128
+ filename: Path to file to write to
129
+ backend_args: Arguments to backend
130
+ mode: File-mode to store the mesh
131
+ time: Time stamp associated with the mesh
132
+ """
133
+
134
+ def write_meshtags(
135
+ self,
136
+ filename: str | Path,
137
+ comm: MPI.Intracomm,
138
+ data: MeshTagsData,
139
+ backend_args: dict[str, Any] | None,
140
+ ):
141
+ """Write mesh tags to file.
142
+
143
+ Args:
144
+ filename: Path to file to write to
145
+ comm: MPI communicator used in storage
146
+ data: Internal data structure for the mesh tags to save to file
147
+ backend_args: Arguments to backend
148
+ """
149
+
150
+ def read_mesh_data(
151
+ self,
152
+ filename: Path | str,
153
+ comm: MPI.Intracomm,
154
+ time: str | float | None,
155
+ read_from_partition: bool,
156
+ backend_args: dict[str, Any] | None,
157
+ ) -> ReadMeshData:
158
+ """Read mesh data from file.
159
+
160
+ Args:
161
+ filename: Path to file to read from
162
+ comm: MPI communicator used in storage
163
+ time: Time stamp associated with the mesh to read
164
+ read_from_partition: Whether to read partition information
165
+ backend_args: Arguments to backend
166
+
167
+ Returns:
168
+ Internal data structure for the mesh data read from file
169
+ """
170
+
171
+ def read_meshtags_data(
172
+ self,
173
+ filename: str | Path,
174
+ comm: MPI.Intracomm,
175
+ name: str,
176
+ backend_args: dict[str, Any] | None,
177
+ ) -> MeshTagsData:
178
+ """Read mesh tags from file.
179
+
180
+ Args:
181
+ filename: Path to file to read from
182
+ comm: MPI communicator used in storage
183
+ name: Name of the mesh tags to read
184
+ backend_args: Arguments to backend
185
+
186
+ Returns:
187
+ Internal data structure for the mesh tags read from file
188
+ """
189
+
190
+ def read_dofmap(
191
+ self,
192
+ filename: str | Path,
193
+ comm: MPI.Intracomm,
194
+ name: str,
195
+ backend_args: dict[str, Any] | None,
196
+ ) -> dolfinx.graph.AdjacencyList:
197
+ """Read the dofmap of a function with a given name.
198
+
199
+ Args:
200
+ filename: Path to file to read from
201
+ comm: MPI communicator used in storage
202
+ name: Name of the function to read the dofmap for
203
+ backend_args: Arguments to backend
204
+
205
+ Returns:
206
+ Dofmap as an {py:class}`dolfinx.graph.AdjacencyList`
207
+ """
208
+
209
+ def read_dofs(
210
+ self,
211
+ filename: str | Path,
212
+ comm: MPI.Intracomm,
213
+ name: str,
214
+ time: float,
215
+ backend_args: dict[str, Any] | None,
216
+ ) -> tuple[npt.NDArray[np.float32 | np.float64 | np.complex64 | np.complex128], int]:
217
+ """Read the dofs (values) of a function with a given name from a given timestep.
218
+
219
+ Args:
220
+ filename: Path to file to read from
221
+ comm: MPI communicator used in storage
222
+ name: Name of the function to read the dofs for
223
+ time: Time stamp associated with the function to read
224
+ backend_args: Arguments to backend
225
+
226
+ Returns:
227
+ Contiguous sequence of degrees of freedom (with respect to input data)
228
+ and the global starting point on the process.
229
+ Process 0 has [0, M), process 1 [M, N), process 2 [N, O) etc.
230
+ """
231
+
232
+ def read_cell_perms(
233
+ self, comm: MPI.Intracomm, filename: Path | str, backend_args: dict[str, Any] | None
234
+ ) -> npt.NDArray[np.uint32]:
235
+ """
236
+ Read cell permutation from file with given communicator,
237
+ Split in continuous chunks based on number of cells in the input data.
238
+
239
+ Args:
240
+ comm: MPI communicator used in storage
241
+ filename: Path to file to read from
242
+ backend_args: Arguments to backend
243
+
244
+ Returns:
245
+ Contiguous sequence of permutations (with respect to input data)
246
+ Process 0 has [0, M), process 1 [M, N), process 2 [N, O) etc.
247
+ """
248
+
249
+ def write_function(
250
+ self,
251
+ filename: Path,
252
+ comm: MPI.Intracomm,
253
+ u: FunctionData,
254
+ time: float,
255
+ mode: FileMode,
256
+ backend_args: dict[str, Any] | None,
257
+ ):
258
+ """Write a function to file.
259
+
260
+ Args:
261
+ comm: MPI communicator used in storage
262
+ u: Internal data structure for the function data to save to file
263
+ filename: Path to file to write to
264
+ time: Time stamp associated with function
265
+ mode: File-mode to store the function
266
+ backend_args: Arguments to backend
267
+ """
268
+
269
+ def read_legacy_mesh(
270
+ self, filename: Path | str, comm: MPI.Intracomm, group: str
271
+ ) -> tuple[npt.NDArray[np.int64], npt.NDArray[np.floating], str | None]:
272
+ """Read in the mesh topology, geometry and (optionally) cell type from a
273
+ legacy DOLFIN HDF5-file.
274
+
275
+ Args:
276
+ filename: Path to file to read from
277
+ comm: MPI communicator used in storage
278
+ group: Group in HDF5 file where mesh is stored
279
+
280
+ Returns:
281
+ Tuple containing:
282
+ - Topology as a (num_cells, num_vertices_per_cell) array of global vertex indices
283
+ - Geometry as a (num_vertices, geometric_dimension) array of vertex coordinates
284
+ - Cell type as a string (e.g. "tetrahedron") or None if not found
285
+ """
286
+
287
+ def snapshot_checkpoint(
288
+ self,
289
+ filename: Path | str,
290
+ mode: FileMode,
291
+ u: dolfinx.fem.Function,
292
+ backend_args: dict[str, Any] | None,
293
+ ):
294
+ """Create a snapshot checkpoint of a dolfinx function.
295
+
296
+ Args:
297
+ filename: Path to file to read from
298
+ mode: File-mode to store the function
299
+ u: dolfinx function to create a snapshot checkpoint for
300
+ backend_args: Arguments to backend
301
+ """
302
+
303
+ def read_hdf5_array(
304
+ self,
305
+ comm: MPI.Intracomm,
306
+ filename: Path | str,
307
+ group: str,
308
+ backend_args: dict[str, Any] | None,
309
+ ) -> tuple[np.ndarray, int]:
310
+ """Read an array from an HDF5 file.
311
+
312
+ Args:
313
+ comm: MPI communicator used in storage
314
+ filename: Path to file to read from
315
+ group: Group in HDF5 file where array is stored
316
+ backend_args: Arguments to backend
317
+
318
+ Returns:
319
+ Tuple containing:
320
+ - Numpy array read from file
321
+ - Global starting point on the process.
322
+ Process 0 has [0, M), process 1 [M, N), process 2 [N, O) etc.
323
+ """
324
+
325
+ def read_point_data(
326
+ self,
327
+ filename: Path | str,
328
+ name: str,
329
+ comm: MPI.Intracomm,
330
+ time: str | float | None,
331
+ backend_args: dict[str, Any] | None,
332
+ ) -> tuple[np.ndarray, int]:
333
+ """Read data from the nodes of a mesh.
334
+
335
+ Args:
336
+ filename: Path to file
337
+ name: Name of point data
338
+ comm: Communicator to launch IO on.
339
+ time: The time stamp
340
+ backend_args: The backend arguments
341
+ Returns:
342
+ Data local to process (contiguous, no mpi comm) and local start range
343
+ """
344
+ ...
345
+
346
+ def read_function_names(
347
+ self, filename: Path | str, comm: MPI.Intracomm, backend_args: dict[str, Any] | None
348
+ ) -> list[str]:
349
+ """Read all function names from a file.
350
+
351
+ Args:
352
+ filename: Path to file
353
+ comm: MPI communicator to launch IO on.
354
+ backend_args: Arguments to backend
355
+
356
+ Returns:
357
+ A list of function names.
358
+ """
359
+ ...
360
+
361
+ def read_cell_data(
362
+ self,
363
+ filename: Path | str,
364
+ name: str,
365
+ comm: MPI.Intracomm,
366
+ time: str | float | None,
367
+ backend_args: dict[str, Any] | None,
368
+ ) -> tuple[npt.NDArray[np.int64], np.ndarray]:
369
+ """Read data from the cells of a mesh.
370
+
371
+ Args:
372
+ filename: Path to file
373
+ name: Name of point data
374
+ comm: Communicator to launch IO on.
375
+ time: The time stamp
376
+ backend_args: The backend arguments
377
+ Returns:
378
+ A tuple (topology, dofs) where topology contains the
379
+ vertex indices of the cells, dofs the degrees of
380
+ freedom within that cell.
381
+ """
382
+ ...
383
+
384
+ def write_data(
385
+ self,
386
+ filename: Path | str,
387
+ array_data: ArrayData,
388
+ comm: MPI.Intracomm,
389
+ time: str | float | None,
390
+ mode: FileMode,
391
+ backend_args: dict[str, Any] | None,
392
+ ):
393
+ """Write a 2D-array to file.
394
+
395
+
396
+ Args:
397
+ filename: Path to file
398
+ array_data: Data to write to file.
399
+ comm: The MPI communicator to open the writer with.
400
+ time: The time stamp
401
+ mode: Append or write
402
+ backend_args: The backend arguments
403
+ """
404
+ ...
405
+
406
+
407
+ def get_backend(backend: str) -> IOBackend:
408
+ """Get backend class from backend name.
409
+
410
+ Args:
411
+ backend: Name of the backend to get
412
+
413
+ Returns:
414
+ Backend class
415
+ """
416
+ if backend == "h5py":
417
+ from .h5py import backend as H5PYInterface
418
+
419
+ return H5PYInterface
420
+ elif backend == "adios2":
421
+ from .adios2 import backend as ADIOS2Interface
422
+
423
+ return ADIOS2Interface
424
+ elif backend == "pyvista":
425
+ from .pyvista import backend as PYVISTAInterface
426
+
427
+ return PYVISTAInterface
428
+ elif backend == "xdmf":
429
+ from .xdmf import backend as XDMFInterface
430
+
431
+ return XDMFInterface
432
+ elif backend == "vtkhdf":
433
+ from .vtkhdf import backend as VTKDHFInterface
434
+
435
+ return VTKDHFInterface
436
+ else:
437
+ return import_module(backend)
@@ -0,0 +1,3 @@
1
+ from . import backend, helpers
2
+
3
+ __all__ = ["backend", "helpers"]