foamlib 0.9.1__py3-none-any.whl → 0.9.2__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.
- foamlib/__init__.py +1 -1
- foamlib/_files/_files.py +143 -48
- foamlib/_files/_parsing.py +37 -26
- foamlib/_files/_serialization.py +117 -78
- {foamlib-0.9.1.dist-info → foamlib-0.9.2.dist-info}/METADATA +1 -1
- {foamlib-0.9.1.dist-info → foamlib-0.9.2.dist-info}/RECORD +8 -8
- {foamlib-0.9.1.dist-info → foamlib-0.9.2.dist-info}/WHEEL +0 -0
- {foamlib-0.9.1.dist-info → foamlib-0.9.2.dist-info}/licenses/LICENSE.txt +0 -0
foamlib/__init__.py
CHANGED
foamlib/_files/_files.py
CHANGED
@@ -17,9 +17,11 @@ else:
|
|
17
17
|
import numpy as np
|
18
18
|
|
19
19
|
from ._io import FoamFileIO
|
20
|
-
from .
|
20
|
+
from ._parsing import loads
|
21
|
+
from ._serialization import dumps, normalize_data, normalize_keyword
|
21
22
|
from ._types import (
|
22
23
|
Data,
|
24
|
+
DataLike,
|
23
25
|
Dict_,
|
24
26
|
Dimensioned,
|
25
27
|
DimensionSet,
|
@@ -31,6 +33,32 @@ from ._types import (
|
|
31
33
|
)
|
32
34
|
|
33
35
|
|
36
|
+
def _tensor_kind_for_field(
|
37
|
+
field: FieldLike,
|
38
|
+
) -> str:
|
39
|
+
shape = np.shape(field) # type: ignore [arg-type]
|
40
|
+
if not shape:
|
41
|
+
return "scalar"
|
42
|
+
if shape == (3,):
|
43
|
+
return "vector"
|
44
|
+
if shape == (6,):
|
45
|
+
return "symmTensor"
|
46
|
+
if shape == (9,):
|
47
|
+
return "tensor"
|
48
|
+
if len(shape) == 1:
|
49
|
+
return "scalar"
|
50
|
+
if len(shape) == 2:
|
51
|
+
if shape[1] == 3:
|
52
|
+
return "vector"
|
53
|
+
if shape[1] == 6:
|
54
|
+
return "symmTensor"
|
55
|
+
if shape[1] == 9:
|
56
|
+
return "tensor"
|
57
|
+
|
58
|
+
msg = f"Invalid field shape: {shape}"
|
59
|
+
raise ValueError(msg)
|
60
|
+
|
61
|
+
|
34
62
|
class FoamFile(
|
35
63
|
MutableMapping[
|
36
64
|
Optional[Union[str, Tuple[str, ...]]],
|
@@ -261,7 +289,7 @@ class FoamFile(
|
|
261
289
|
elif not isinstance(keywords, tuple):
|
262
290
|
keywords = (keywords,)
|
263
291
|
|
264
|
-
if keywords and not isinstance(
|
292
|
+
if keywords and not isinstance(normalize_keyword(keywords[-1]), str):
|
265
293
|
msg = f"Invalid keyword: {keywords[-1]}"
|
266
294
|
raise ValueError(msg)
|
267
295
|
|
@@ -283,52 +311,26 @@ class FoamFile(
|
|
283
311
|
self.path.stem if self.path.suffix == ".gz" else self.path.name
|
284
312
|
)
|
285
313
|
|
286
|
-
kind = Kind.DEFAULT
|
287
|
-
if keywords == ("internalField",) or (
|
288
|
-
len(keywords) == 3
|
289
|
-
and keywords[0] == "boundaryField"
|
290
|
-
and (
|
291
|
-
keywords[2] in ("value", "gradient")
|
292
|
-
or keywords[2].endswith("Value")
|
293
|
-
or keywords[2].endswith("Gradient")
|
294
|
-
)
|
295
|
-
):
|
296
|
-
kind = (
|
297
|
-
Kind.BINARY_FIELD if self.format == "binary" else Kind.ASCII_FIELD
|
298
|
-
)
|
299
|
-
elif keywords == ("dimensions",):
|
300
|
-
kind = Kind.DIMENSIONS
|
301
|
-
|
302
314
|
if (
|
303
|
-
|
315
|
+
keywords == ("internalField",)
|
316
|
+
or (
|
317
|
+
len(keywords) == 3
|
318
|
+
and keywords[0] == "boundaryField"
|
319
|
+
and (
|
320
|
+
keywords[2] == "value"
|
321
|
+
or keywords[2] == "gradient"
|
322
|
+
or keywords[2].endswith(("Value", "Gradient"))
|
323
|
+
)
|
324
|
+
)
|
304
325
|
) and self.class_ == "dictionary":
|
305
326
|
try:
|
306
|
-
|
327
|
+
tensor_kind = _tensor_kind_for_field(data) # type: ignore [arg-type]
|
307
328
|
except ValueError:
|
308
329
|
pass
|
309
330
|
else:
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
self.class_ = "volVectorField"
|
314
|
-
elif shape == (6,):
|
315
|
-
self.class_ = "volSymmTensorField"
|
316
|
-
elif shape == (9,):
|
317
|
-
self.class_ = "volTensorField"
|
318
|
-
elif len(shape) == 1:
|
319
|
-
self.class_ = "volScalarField"
|
320
|
-
elif len(shape) == 2:
|
321
|
-
if shape[1] == 3:
|
322
|
-
self.class_ = "volVectorField"
|
323
|
-
elif shape[1] == 6:
|
324
|
-
self.class_ = "volSymmTensorField"
|
325
|
-
elif shape[1] == 9:
|
326
|
-
self.class_ = "volTensorField"
|
327
|
-
|
328
|
-
if kind == Kind.ASCII_FIELD and self.class_.endswith("scalarField"):
|
329
|
-
kind = Kind.SCALAR_ASCII_FIELD
|
330
|
-
elif kind == Kind.BINARY_FIELD and self.class_.endswith("scalarField"):
|
331
|
-
kind = Kind.SCALAR_BINARY_FIELD
|
331
|
+
self.class_ = (
|
332
|
+
"vol" + tensor_kind[0].upper() + tensor_kind[1:] + "Field"
|
333
|
+
)
|
332
334
|
|
333
335
|
parsed = self._get_parsed(missing_ok=True)
|
334
336
|
|
@@ -360,7 +362,7 @@ class FoamFile(
|
|
360
362
|
...,
|
361
363
|
before
|
362
364
|
+ indentation
|
363
|
-
+ dumps(keywords[-1])
|
365
|
+
+ dumps(normalize_keyword(keywords[-1]))
|
364
366
|
+ b"\n"
|
365
367
|
+ indentation
|
366
368
|
+ b"{\n"
|
@@ -373,23 +375,37 @@ class FoamFile(
|
|
373
375
|
self[(*keywords, k)] = v
|
374
376
|
|
375
377
|
elif keywords:
|
376
|
-
|
378
|
+
header = self.get("FoamFile", None)
|
379
|
+
assert header is None or isinstance(header, FoamFile.SubDict)
|
380
|
+
val = dumps(
|
381
|
+
data,
|
382
|
+
keywords=keywords,
|
383
|
+
header=header,
|
384
|
+
)
|
377
385
|
parsed.put(
|
378
386
|
keywords,
|
379
|
-
|
387
|
+
normalize_data(data, keywords=keywords),
|
380
388
|
before
|
381
389
|
+ indentation
|
382
|
-
+ dumps(keywords[-1])
|
390
|
+
+ dumps(normalize_keyword(keywords[-1]))
|
383
391
|
+ ((b" " + val) if val else b"")
|
384
392
|
+ (b";" if not keywords[-1].startswith("#") else b"")
|
385
393
|
+ after,
|
386
394
|
)
|
387
395
|
|
388
396
|
else:
|
397
|
+
header = self.get("FoamFile", None)
|
398
|
+
assert header is None or isinstance(header, FoamFile.SubDict)
|
389
399
|
parsed.put(
|
390
400
|
(),
|
391
|
-
|
392
|
-
before
|
401
|
+
normalize_data(data, keywords=keywords),
|
402
|
+
before
|
403
|
+
+ dumps(
|
404
|
+
data,
|
405
|
+
keywords=(),
|
406
|
+
header=header,
|
407
|
+
)
|
408
|
+
+ after,
|
393
409
|
)
|
394
410
|
|
395
411
|
def __delitem__(self, keywords: str | tuple[str, ...] | None) -> None:
|
@@ -442,6 +458,85 @@ class FoamFile(
|
|
442
458
|
d.pop("FoamFile", None)
|
443
459
|
return deepcopy(d)
|
444
460
|
|
461
|
+
@staticmethod
|
462
|
+
def loads(
|
463
|
+
s: bytes | str,
|
464
|
+
*,
|
465
|
+
include_header: bool = False,
|
466
|
+
) -> File | Data:
|
467
|
+
"""
|
468
|
+
Standalone deserializing function.
|
469
|
+
|
470
|
+
Deserialize the OpenFOAM FoamFile format to Python objects.
|
471
|
+
|
472
|
+
:param s: The string to deserialize. This can be a dictionary, list, or any
|
473
|
+
other object that can be serialized to the OpenFOAM format.
|
474
|
+
:param include_header: Whether to include the "FoamFile" header in the output.
|
475
|
+
If `True`, the header will be included if it is present in the input object.
|
476
|
+
"""
|
477
|
+
ret = loads(s)
|
478
|
+
|
479
|
+
if not include_header and isinstance(ret, Mapping) and "FoamFile" in ret:
|
480
|
+
del ret["FoamFile"]
|
481
|
+
if len(ret) == 1 and None in ret:
|
482
|
+
val = ret[None]
|
483
|
+
assert not isinstance(val, Mapping)
|
484
|
+
return val
|
485
|
+
|
486
|
+
return ret
|
487
|
+
|
488
|
+
@staticmethod
|
489
|
+
def dumps(file: File | DataLike, *, ensure_header: bool = True) -> bytes:
|
490
|
+
"""
|
491
|
+
Standalone serializing function.
|
492
|
+
|
493
|
+
Serialize Python objects to the OpenFOAM FoamFile format.
|
494
|
+
|
495
|
+
:param file: The Python object to serialize. This can be a dictionary, list,
|
496
|
+
or any other object that can be serialized to the OpenFOAM format.
|
497
|
+
:param ensure_header: Whether to include the "FoamFile" header in the output.
|
498
|
+
If `True`, a header will be included if it is not already present in the
|
499
|
+
input object.
|
500
|
+
"""
|
501
|
+
if isinstance(file, Mapping):
|
502
|
+
header = file.get("FoamFile", None)
|
503
|
+
assert isinstance(header, FoamFile.SubDict) or header is None
|
504
|
+
entries: list[bytes] = []
|
505
|
+
for k, v in file.items():
|
506
|
+
if k is not None:
|
507
|
+
entries.append(
|
508
|
+
dumps((k, v), keywords=(), header=header, tuple_is_entry=True)
|
509
|
+
)
|
510
|
+
else:
|
511
|
+
entries.append(dumps(v, keywords=(), header=header))
|
512
|
+
ret = b" ".join(entries)
|
513
|
+
else:
|
514
|
+
header = None
|
515
|
+
ret = dumps(file)
|
516
|
+
|
517
|
+
if header is None and ensure_header:
|
518
|
+
class_ = "dictionary"
|
519
|
+
if isinstance(file, Mapping) and "internalField" in file:
|
520
|
+
try:
|
521
|
+
tensor_kind = _tensor_kind_for_field(file["internalField"]) # type: ignore [arg-type]
|
522
|
+
except (ValueError, TypeError):
|
523
|
+
pass
|
524
|
+
else:
|
525
|
+
class_ = "vol" + tensor_kind[0].upper() + tensor_kind[1:] + "Field"
|
526
|
+
|
527
|
+
header = {"version": 2.0, "format": "ascii", "class": class_}
|
528
|
+
|
529
|
+
ret = (
|
530
|
+
dumps(
|
531
|
+
{"FoamFile": header},
|
532
|
+
keywords=(),
|
533
|
+
)
|
534
|
+
+ b" "
|
535
|
+
+ ret
|
536
|
+
)
|
537
|
+
|
538
|
+
return ret
|
539
|
+
|
445
540
|
|
446
541
|
class FoamFieldFile(FoamFile):
|
447
542
|
"""
|
foamlib/_files/_parsing.py
CHANGED
@@ -380,21 +380,41 @@ _NUMBER = (
|
|
380
380
|
)
|
381
381
|
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | _TOKEN
|
382
382
|
|
383
|
-
_DATA <<= (
|
384
|
-
|
385
|
-
|
383
|
+
_DATA <<= _DATA_ENTRY[1, ...].set_parse_action(
|
384
|
+
lambda tks: [tuple(tks)] if len(tks) > 1 else [tks[0]]
|
385
|
+
)
|
386
|
+
|
387
|
+
_STANDALONE_DATA = (
|
388
|
+
_ascii_numeric_list(dtype=int, ignore=_COMMENT)
|
389
|
+
| _binary_numeric_list(dtype=np.int64)
|
390
|
+
| _binary_numeric_list(dtype=np.int32)
|
391
|
+
| _ascii_numeric_list(dtype=float, nested=3, ignore=_COMMENT)
|
392
|
+
| _binary_numeric_list(dtype=np.float64, nested=3)
|
393
|
+
| _binary_numeric_list(dtype=np.float32, nested=3)
|
394
|
+
| _DATA
|
395
|
+
).add_parse_action(lambda tks: [None, tks[0]])
|
396
|
+
|
397
|
+
|
398
|
+
_FILE = (
|
399
|
+
Dict(_KEYWORD_ENTRY[...] + Opt(Group(_STANDALONE_DATA)) + _KEYWORD_ENTRY[...])
|
386
400
|
.ignore(_COMMENT)
|
387
401
|
.parse_with_tabs()
|
388
402
|
)
|
389
403
|
|
390
404
|
|
391
|
-
def
|
392
|
-
if
|
393
|
-
|
394
|
-
|
405
|
+
def loads(s: bytes | str) -> File | Data:
|
406
|
+
if isinstance(s, bytes):
|
407
|
+
s = s.decode("latin-1")
|
408
|
+
|
409
|
+
file = _FILE.parse_string(s, parse_all=True).as_dict()
|
410
|
+
|
411
|
+
if len(file) == 1 and None in file:
|
412
|
+
return file[None] # type: ignore[no-any-return]
|
395
413
|
|
414
|
+
return file
|
396
415
|
|
397
|
-
|
416
|
+
|
417
|
+
_LOCATED_KEYWORD_ENTRIES = Group(
|
398
418
|
_keyword_entry_of(
|
399
419
|
_TOKEN,
|
400
420
|
Opt(_DATA, default=""),
|
@@ -403,22 +423,14 @@ _LOCATED_DICTIONARY = Group(
|
|
403
423
|
located=True,
|
404
424
|
)
|
405
425
|
)[...]
|
406
|
-
|
407
|
-
Located(
|
408
|
-
(
|
409
|
-
_ascii_numeric_list(dtype=int, ignore=_COMMENT)
|
410
|
-
| _binary_numeric_list(dtype=np.int64)
|
411
|
-
| _binary_numeric_list(dtype=np.int32)
|
412
|
-
| _ascii_numeric_list(dtype=float, nested=3, ignore=_COMMENT)
|
413
|
-
| _binary_numeric_list(dtype=np.float64, nested=3)
|
414
|
-
| _binary_numeric_list(dtype=np.float32, nested=3)
|
415
|
-
| _DATA
|
416
|
-
).add_parse_action(lambda tks: ["", tks[0]])
|
417
|
-
)
|
418
|
-
)
|
426
|
+
_LOCATED_STANDALONE_DATA = Group(Located(_STANDALONE_DATA))
|
419
427
|
|
420
|
-
|
421
|
-
Dict(
|
428
|
+
_LOCATED_FILE = (
|
429
|
+
Dict(
|
430
|
+
_LOCATED_KEYWORD_ENTRIES
|
431
|
+
+ Opt(_LOCATED_STANDALONE_DATA)
|
432
|
+
+ _LOCATED_KEYWORD_ENTRIES
|
433
|
+
)
|
422
434
|
.ignore(_COMMENT)
|
423
435
|
.parse_with_tabs()
|
424
436
|
)
|
@@ -430,7 +442,7 @@ class Parsed(Mapping[Tuple[str, ...], Union[Data, EllipsisType]]):
|
|
430
442
|
tuple[str, ...],
|
431
443
|
tuple[int, Data | EllipsisType, int],
|
432
444
|
] = {}
|
433
|
-
for parse_result in
|
445
|
+
for parse_result in _LOCATED_FILE.parse_string(
|
434
446
|
contents.decode("latin-1"), parse_all=True
|
435
447
|
):
|
436
448
|
self._parsed.update(self._flatten_result(parse_result))
|
@@ -453,8 +465,7 @@ class Parsed(Mapping[Tuple[str, ...], Union[Data, EllipsisType]]):
|
|
453
465
|
end = parse_result.locn_end
|
454
466
|
assert isinstance(end, int)
|
455
467
|
keyword, *data = item
|
456
|
-
|
457
|
-
if not keyword:
|
468
|
+
if keyword is None:
|
458
469
|
assert not _keywords
|
459
470
|
assert len(data) == 1
|
460
471
|
assert not isinstance(data[0], ParseResults)
|
foamlib/_files/_serialization.py
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import sys
|
4
|
-
from enum import Enum, auto
|
5
4
|
from typing import overload
|
6
5
|
|
7
6
|
if sys.version_info >= (3, 9):
|
@@ -11,7 +10,7 @@ else:
|
|
11
10
|
|
12
11
|
import numpy as np
|
13
12
|
|
14
|
-
from ._parsing import
|
13
|
+
from ._parsing import loads
|
15
14
|
from ._types import (
|
16
15
|
Data,
|
17
16
|
DataLike,
|
@@ -23,31 +22,32 @@ from ._types import (
|
|
23
22
|
)
|
24
23
|
|
25
24
|
|
26
|
-
class Kind(Enum):
|
27
|
-
DEFAULT = auto()
|
28
|
-
SINGLE_ENTRY = auto()
|
29
|
-
ASCII_FIELD = auto()
|
30
|
-
SCALAR_ASCII_FIELD = auto()
|
31
|
-
BINARY_FIELD = auto()
|
32
|
-
SCALAR_BINARY_FIELD = auto()
|
33
|
-
DIMENSIONS = auto()
|
34
|
-
KEYWORD = auto()
|
35
|
-
|
36
|
-
|
37
25
|
@overload
|
38
|
-
def
|
26
|
+
def normalize_data(
|
27
|
+
data: DataLike, *, keywords: tuple[str, ...] | None = None
|
28
|
+
) -> Data: ...
|
39
29
|
|
40
30
|
|
41
31
|
@overload
|
42
|
-
def
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
32
|
+
def normalize_data(
|
33
|
+
data: EntryLike, *, keywords: tuple[str, ...] | None = None
|
34
|
+
) -> Entry: ...
|
35
|
+
|
36
|
+
|
37
|
+
def normalize_data(
|
38
|
+
data: EntryLike, *, keywords: tuple[str, ...] | None = None
|
39
|
+
) -> Entry:
|
40
|
+
if keywords is not None and (
|
41
|
+
keywords == ("internalField",)
|
42
|
+
or (
|
43
|
+
len(keywords) == 3
|
44
|
+
and keywords[0] == "boundaryField"
|
45
|
+
and (
|
46
|
+
keywords[2] == "value"
|
47
|
+
or keywords[2] == "gradient"
|
48
|
+
or keywords[2].endswith(("Value", "Gradient"))
|
49
|
+
)
|
50
|
+
)
|
51
51
|
):
|
52
52
|
if is_sequence(data):
|
53
53
|
try:
|
@@ -61,41 +61,50 @@ def normalize(data: EntryLike, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
|
61
61
|
if arr.ndim == 1 or (arr.ndim == 2 and arr.shape[1] in (3, 6, 9)):
|
62
62
|
return arr # type: ignore [return-value]
|
63
63
|
|
64
|
-
return [
|
64
|
+
return [normalize_data(d) for d in data]
|
65
65
|
|
66
66
|
if isinstance(data, int):
|
67
67
|
return float(data)
|
68
68
|
|
69
|
-
return
|
69
|
+
return normalize_data(data)
|
70
|
+
|
71
|
+
if isinstance(data, Mapping):
|
72
|
+
return {normalize_keyword(k): normalize_data(v) for k, v in data.items()} # type: ignore [misc]
|
70
73
|
|
71
74
|
if isinstance(data, np.ndarray):
|
72
75
|
ret = data.tolist()
|
73
76
|
assert isinstance(ret, (int, float, list))
|
74
77
|
return ret
|
75
78
|
|
76
|
-
if isinstance(data, Mapping):
|
77
|
-
return {k: normalize(v, kind=kind) for k, v in data.items()}
|
78
|
-
|
79
79
|
if (
|
80
|
-
|
80
|
+
not isinstance(data, DimensionSet)
|
81
|
+
and keywords is not None
|
82
|
+
and keywords == ("dimensions",)
|
81
83
|
and is_sequence(data)
|
82
84
|
and len(data) <= 7
|
83
85
|
and all(isinstance(d, (int, float)) for d in data)
|
84
86
|
):
|
85
87
|
return DimensionSet(*data)
|
86
88
|
|
87
|
-
if isinstance(data, tuple) and
|
89
|
+
if keywords is None and isinstance(data, tuple) and len(data) == 2:
|
88
90
|
k, v = data
|
89
|
-
|
91
|
+
assert not isinstance(k, Mapping)
|
92
|
+
return (
|
93
|
+
normalize_keyword(k),
|
94
|
+
normalize_data(v) if not isinstance(v, Mapping) else v,
|
95
|
+
) # type: ignore [return-value]
|
90
96
|
|
91
|
-
if
|
92
|
-
|
97
|
+
if (
|
98
|
+
is_sequence(data)
|
99
|
+
and not isinstance(data, DimensionSet)
|
100
|
+
and (keywords is None or not isinstance(data, tuple))
|
101
|
+
):
|
102
|
+
return [normalize_data(d) for d in data]
|
93
103
|
|
94
104
|
if isinstance(data, str):
|
95
|
-
|
96
|
-
if
|
97
|
-
return
|
98
|
-
return parsed_data
|
105
|
+
s = loads(data)
|
106
|
+
if isinstance(s, (str, tuple, bool)):
|
107
|
+
return s
|
99
108
|
|
100
109
|
if isinstance(
|
101
110
|
data,
|
@@ -107,52 +116,70 @@ def normalize(data: EntryLike, *, kind: Kind = Kind.DEFAULT) -> Entry:
|
|
107
116
|
raise TypeError(msg)
|
108
117
|
|
109
118
|
|
119
|
+
def normalize_keyword(data: DataLike) -> Data:
|
120
|
+
ret = normalize_data(data)
|
121
|
+
|
122
|
+
if isinstance(data, str) and isinstance(ret, bool):
|
123
|
+
return data
|
124
|
+
|
125
|
+
return ret
|
126
|
+
|
127
|
+
|
110
128
|
def dumps(
|
111
129
|
data: EntryLike,
|
112
130
|
*,
|
113
|
-
|
131
|
+
keywords: tuple[str, ...] | None = None,
|
132
|
+
header: Mapping[str, Entry] | None = None,
|
133
|
+
tuple_is_entry: bool = False,
|
114
134
|
) -> bytes:
|
115
|
-
data =
|
135
|
+
data = normalize_data(data, keywords=keywords)
|
116
136
|
|
117
137
|
if isinstance(data, Mapping):
|
118
138
|
return (
|
119
139
|
b"{"
|
120
|
-
+ b" ".join(
|
140
|
+
+ b" ".join(
|
141
|
+
dumps(
|
142
|
+
(k, v),
|
143
|
+
keywords=keywords,
|
144
|
+
tuple_is_entry=True,
|
145
|
+
)
|
146
|
+
for k, v in data.items()
|
147
|
+
)
|
121
148
|
+ b"}"
|
122
149
|
)
|
123
150
|
|
124
|
-
if
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
151
|
+
if (
|
152
|
+
keywords is not None
|
153
|
+
and (
|
154
|
+
keywords == ("internalField",)
|
155
|
+
or (
|
156
|
+
len(keywords) == 3
|
157
|
+
and keywords[0] == "boundaryField"
|
158
|
+
and (
|
159
|
+
keywords[2] == "value"
|
160
|
+
or keywords[2] == "gradient"
|
161
|
+
or keywords[2].endswith(("Value", "Gradient"))
|
162
|
+
)
|
163
|
+
)
|
164
|
+
)
|
165
|
+
and isinstance(data, (int, float, np.ndarray))
|
166
|
+
):
|
167
|
+
data = np.asarray(data) # type: ignore [assignment]
|
168
|
+
class_ = header.get("class", "") if header else ""
|
169
|
+
assert isinstance(class_, str)
|
170
|
+
scalar = "Scalar" in class_
|
136
171
|
|
137
|
-
if kind in (
|
138
|
-
Kind.ASCII_FIELD,
|
139
|
-
Kind.SCALAR_ASCII_FIELD,
|
140
|
-
Kind.BINARY_FIELD,
|
141
|
-
Kind.SCALAR_BINARY_FIELD,
|
142
|
-
) and (isinstance(data, (int, float, np.ndarray))):
|
143
172
|
shape = np.shape(data)
|
144
|
-
if not shape or (
|
145
|
-
|
146
|
-
and shape in ((3,), (6,), (9,))
|
147
|
-
):
|
148
|
-
return b"uniform " + dumps(data, kind=Kind.SINGLE_ENTRY)
|
173
|
+
if not shape or (not scalar and shape in ((3,), (6,), (9,))):
|
174
|
+
return b"uniform " + dumps(data)
|
149
175
|
|
150
176
|
assert isinstance(data, np.ndarray)
|
151
|
-
ndim =
|
177
|
+
ndim = np.ndim(data)
|
152
178
|
if ndim == 1:
|
153
179
|
tensor_kind = b"scalar"
|
154
180
|
|
155
181
|
elif ndim == 2:
|
182
|
+
assert len(shape) == 2
|
156
183
|
if shape[1] == 3:
|
157
184
|
tensor_kind = b"vector"
|
158
185
|
elif shape[1] == 6:
|
@@ -165,34 +192,46 @@ def dumps(
|
|
165
192
|
else:
|
166
193
|
return dumps(data)
|
167
194
|
|
168
|
-
|
169
|
-
|
170
|
-
else
|
171
|
-
assert kind in (Kind.ASCII_FIELD, Kind.SCALAR_ASCII_FIELD)
|
172
|
-
contents = dumps(data, kind=Kind.SINGLE_ENTRY)
|
195
|
+
binary = (header.get("format", "") if header else "") == "binary"
|
196
|
+
|
197
|
+
contents = b"(" + data.tobytes() + b")" if binary else dumps(data)
|
173
198
|
|
174
199
|
return b"nonuniform List<" + tensor_kind + b"> " + dumps(len(data)) + contents
|
175
200
|
|
201
|
+
if isinstance(data, DimensionSet):
|
202
|
+
return b"[" + b" ".join(dumps(v) for v in data) + b"]"
|
203
|
+
|
176
204
|
if isinstance(data, Dimensioned):
|
177
205
|
if data.name is not None:
|
178
206
|
return (
|
179
207
|
dumps(data.name)
|
180
208
|
+ b" "
|
181
|
-
+ dumps(data.dimensions
|
209
|
+
+ dumps(data.dimensions)
|
182
210
|
+ b" "
|
183
|
-
+ dumps(data.value
|
211
|
+
+ dumps(data.value)
|
184
212
|
)
|
185
|
-
return (
|
186
|
-
dumps(data.dimensions, kind=Kind.DIMENSIONS)
|
187
|
-
+ b" "
|
188
|
-
+ dumps(data.value, kind=Kind.SINGLE_ENTRY)
|
189
|
-
)
|
213
|
+
return dumps(data.dimensions) + b" " + dumps(data.value)
|
190
214
|
|
191
215
|
if isinstance(data, tuple):
|
216
|
+
if tuple_is_entry:
|
217
|
+
k, v = data
|
218
|
+
ret = dumps(k)
|
219
|
+
val = dumps(
|
220
|
+
v,
|
221
|
+
keywords=(*keywords, k)
|
222
|
+
if keywords is not None and isinstance(k, str)
|
223
|
+
else None,
|
224
|
+
)
|
225
|
+
if val:
|
226
|
+
ret += b" " + val
|
227
|
+
if not isinstance(v, Mapping):
|
228
|
+
ret += b";"
|
229
|
+
return ret
|
230
|
+
|
192
231
|
return b" ".join(dumps(v) for v in data)
|
193
232
|
|
194
|
-
if is_sequence(data)
|
195
|
-
return b"(" + b" ".join(dumps(v,
|
233
|
+
if is_sequence(data):
|
234
|
+
return b"(" + b" ".join(dumps(v, tuple_is_entry=True) for v in data) + b")"
|
196
235
|
|
197
236
|
if data is True:
|
198
237
|
return b"yes"
|
@@ -1,4 +1,4 @@
|
|
1
|
-
foamlib/__init__.py,sha256=
|
1
|
+
foamlib/__init__.py,sha256=75bXvyciN5IbxNdsJ4XEBETcI5ojrnjWQhQco2Xmqy4,452
|
2
2
|
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
foamlib/_cases/__init__.py,sha256=_A1TTHuQfS9FH2_33lSEyLtOJZGFHZBco1tWJCVOHks,358
|
4
4
|
foamlib/_cases/_async.py,sha256=e4lGTcQBbFGwfG6SmJks5aa5LWd_0dy01kgKZWAgTGQ,11655
|
@@ -9,12 +9,12 @@ foamlib/_cases/_subprocess.py,sha256=VHV2SuOLqa711an6kCuvN6UlIkeh4qqFfdrpNoKzQps
|
|
9
9
|
foamlib/_cases/_sync.py,sha256=yhrkwStKri7u41YImYCGBH4REcKn8Ar-32VW_WPa40c,9641
|
10
10
|
foamlib/_cases/_util.py,sha256=QCizfbuJdOCeF9ogU2R-y-iWX5kfaOA4U2W68t6QlOM,2544
|
11
11
|
foamlib/_files/__init__.py,sha256=q1vkjXnjnSZvo45jPAICpWeF2LZv5V6xfzAR6S8fS5A,96
|
12
|
-
foamlib/_files/_files.py,sha256=
|
12
|
+
foamlib/_files/_files.py,sha256=7Si-C-2O0h27Ga4bC0W-i6_PKq7B4K2Gg1tDGh8AZFo,22416
|
13
13
|
foamlib/_files/_io.py,sha256=BGbbm6HKxL2ka0YMCmHqZQZ1R4PPQlkvWWb4FHMAS8k,2217
|
14
|
-
foamlib/_files/_parsing.py,sha256=
|
15
|
-
foamlib/_files/_serialization.py,sha256=
|
14
|
+
foamlib/_files/_parsing.py,sha256=ftaAh8WJ816Y6ej9ntoUzBOn6hC22qHLgN00568Hc2w,17636
|
15
|
+
foamlib/_files/_serialization.py,sha256=R9-oXYywZubevuPkYaTIAyM0_BfF9rC819j9AXOCcg8,6451
|
16
16
|
foamlib/_files/_types.py,sha256=q5O_x680XhGfvPHCNF_3objK1imUG2kgQYNRF2Z4qJ0,2918
|
17
|
-
foamlib-0.9.
|
18
|
-
foamlib-0.9.
|
19
|
-
foamlib-0.9.
|
20
|
-
foamlib-0.9.
|
17
|
+
foamlib-0.9.2.dist-info/METADATA,sha256=c1itaOTpgA5-3jV5ADxqg02_th-qPhry2mA4M7fR9rk,12906
|
18
|
+
foamlib-0.9.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
19
|
+
foamlib-0.9.2.dist-info/licenses/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
20
|
+
foamlib-0.9.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|