foamlib 0.3.4__py3-none-any.whl → 0.3.5__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/_cases.py +3 -13
- foamlib/_files/__init__.py +1 -2
- foamlib/_files/_files.py +159 -36
- foamlib/_files/_io.py +1 -1
- foamlib/_files/_serialization.py +28 -49
- foamlib/_util.py +14 -6
- {foamlib-0.3.4.dist-info → foamlib-0.3.5.dist-info}/METADATA +13 -3
- foamlib-0.3.5.dist-info/RECORD +15 -0
- foamlib/_files/_fields.py +0 -170
- foamlib-0.3.4.dist-info/RECORD +0 -16
- {foamlib-0.3.4.dist-info → foamlib-0.3.5.dist-info}/LICENSE.txt +0 -0
- {foamlib-0.3.4.dist-info → foamlib-0.3.5.dist-info}/WHEEL +0 -0
- {foamlib-0.3.4.dist-info → foamlib-0.3.5.dist-info}/top_level.txt +0 -0
foamlib/__init__.py
CHANGED
foamlib/_cases.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
import asyncio
|
2
2
|
import multiprocessing
|
3
|
-
import os
|
4
3
|
import shutil
|
5
4
|
import sys
|
6
5
|
from contextlib import asynccontextmanager
|
@@ -17,13 +16,12 @@ if sys.version_info >= (3, 9):
|
|
17
16
|
Callable,
|
18
17
|
Collection,
|
19
18
|
Iterator,
|
20
|
-
Mapping,
|
21
19
|
Sequence,
|
22
20
|
Set,
|
23
21
|
)
|
24
22
|
else:
|
25
23
|
from typing import AbstractSet as Set
|
26
|
-
from typing import AsyncGenerator, Callable, Collection, Iterator,
|
24
|
+
from typing import AsyncGenerator, Callable, Collection, Iterator, Sequence
|
27
25
|
|
28
26
|
import aioshutil
|
29
27
|
|
@@ -87,7 +85,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
87
85
|
return str(self.path)
|
88
86
|
|
89
87
|
def __repr__(self) -> str:
|
90
|
-
return f"{type(self).
|
88
|
+
return f"{type(self).__qualname__}('{self.path}')"
|
91
89
|
|
92
90
|
def __str__(self) -> str:
|
93
91
|
return str(self.path)
|
@@ -203,12 +201,6 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
203
201
|
else:
|
204
202
|
return None
|
205
203
|
|
206
|
-
def _env(self) -> Mapping[str, str]:
|
207
|
-
"""Return the environment variables for this case."""
|
208
|
-
env = os.environ.copy()
|
209
|
-
env["PWD"] = str(self.path)
|
210
|
-
return env
|
211
|
-
|
212
204
|
def _parallel_cmd(
|
213
205
|
self, cmd: Union[Sequence[Union[str, Path]], str, Path]
|
214
206
|
) -> Union[Sequence[Union[str, Path]], str]:
|
@@ -298,7 +290,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
298
290
|
return str(self.path)
|
299
291
|
|
300
292
|
def __repr__(self) -> str:
|
301
|
-
return f"{type(self).
|
293
|
+
return f"{type(self).__qualname__}('{self.path}')"
|
302
294
|
|
303
295
|
def __str__(self) -> str:
|
304
296
|
return str(self.path)
|
@@ -359,7 +351,6 @@ class FoamCase(FoamCaseBase):
|
|
359
351
|
cmd,
|
360
352
|
check=check,
|
361
353
|
cwd=self.path,
|
362
|
-
env=self._env(),
|
363
354
|
)
|
364
355
|
else:
|
365
356
|
script_path = self._run_script(parallel=parallel) if script else None
|
@@ -522,7 +513,6 @@ class AsyncFoamCase(FoamCaseBase):
|
|
522
513
|
cmd,
|
523
514
|
check=check,
|
524
515
|
cwd=self.path,
|
525
|
-
env=self._env(),
|
526
516
|
)
|
527
517
|
else:
|
528
518
|
script_path = self._run_script(parallel=parallel) if script else None
|
foamlib/_files/__init__.py
CHANGED
foamlib/_files/_files.py
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
import sys
|
2
|
-
from typing import
|
3
|
-
Any,
|
4
|
-
Tuple,
|
5
|
-
Union,
|
6
|
-
)
|
2
|
+
from typing import Any, Tuple, Union, cast
|
7
3
|
|
8
4
|
if sys.version_info >= (3, 9):
|
9
|
-
from collections.abc import Iterator, Mapping, MutableMapping
|
5
|
+
from collections.abc import Iterator, Mapping, MutableMapping, Sequence
|
10
6
|
else:
|
11
|
-
from typing import Iterator, Mapping, MutableMapping
|
7
|
+
from typing import Iterator, Mapping, MutableMapping, Sequence
|
12
8
|
|
13
9
|
from ._base import FoamDict
|
14
10
|
from ._io import FoamFileIO
|
15
|
-
from ._serialization import dumpb
|
11
|
+
from ._serialization import Kind, dumpb
|
12
|
+
|
13
|
+
try:
|
14
|
+
import numpy as np
|
15
|
+
except ModuleNotFoundError:
|
16
|
+
pass
|
16
17
|
|
17
18
|
|
18
19
|
class FoamFile(
|
@@ -45,23 +46,12 @@ class FoamFile(
|
|
45
46
|
) -> Union["FoamFile.Data", "FoamFile.SubDict"]:
|
46
47
|
return self._file[(*self._keywords, keyword)]
|
47
48
|
|
48
|
-
def
|
49
|
+
def __setitem__(
|
49
50
|
self,
|
50
51
|
keyword: str,
|
51
|
-
data:
|
52
|
-
*,
|
53
|
-
assume_field: bool = False,
|
54
|
-
assume_dimensions: bool = False,
|
52
|
+
data: "FoamFile._SetData",
|
55
53
|
) -> None:
|
56
|
-
self._file.
|
57
|
-
(*self._keywords, keyword),
|
58
|
-
data,
|
59
|
-
assume_field=assume_field,
|
60
|
-
assume_dimensions=assume_dimensions,
|
61
|
-
)
|
62
|
-
|
63
|
-
def __setitem__(self, keyword: str, value: "FoamFile._SetData") -> None:
|
64
|
-
self._setitem(keyword, value)
|
54
|
+
self._file[(*self._keywords, keyword)] = data
|
65
55
|
|
66
56
|
def __delitem__(self, keyword: str) -> None:
|
67
57
|
del self._file[(*self._keywords, keyword)]
|
@@ -117,7 +107,7 @@ class FoamFile(
|
|
117
107
|
def _binary(self) -> bool:
|
118
108
|
return self.get(("FoamFile", "format"), None) == "binary"
|
119
109
|
|
120
|
-
def
|
110
|
+
def __setitem__(
|
121
111
|
self,
|
122
112
|
keywords: Union[str, Tuple[str, ...]],
|
123
113
|
data: "FoamFile._SetData",
|
@@ -128,6 +118,16 @@ class FoamFile(
|
|
128
118
|
if not isinstance(keywords, tuple):
|
129
119
|
keywords = (keywords,)
|
130
120
|
|
121
|
+
kind = Kind.DEFAULT
|
122
|
+
if keywords == ("internalField",) or (
|
123
|
+
len(keywords) == 3
|
124
|
+
and keywords[0] == "boundaryField"
|
125
|
+
and keywords[2] == "value"
|
126
|
+
):
|
127
|
+
kind = Kind.BINARY_FIELD if self._binary else Kind.FIELD
|
128
|
+
elif keywords == ("dimensions",):
|
129
|
+
kind = Kind.DIMENSIONS
|
130
|
+
|
131
131
|
contents, parsed = self._read()
|
132
132
|
|
133
133
|
if isinstance(data, Mapping):
|
@@ -153,23 +153,11 @@ class FoamFile(
|
|
153
153
|
self._write(
|
154
154
|
contents[:start]
|
155
155
|
+ b"\n"
|
156
|
-
+ dumpb(
|
157
|
-
{keywords[-1]: data},
|
158
|
-
assume_field=assume_field,
|
159
|
-
assume_dimensions=assume_dimensions,
|
160
|
-
binary_fields=self._binary,
|
161
|
-
)
|
156
|
+
+ dumpb({keywords[-1]: data}, kind=kind)
|
162
157
|
+ b"\n"
|
163
158
|
+ contents[end:]
|
164
159
|
)
|
165
160
|
|
166
|
-
def __setitem__(
|
167
|
-
self,
|
168
|
-
keywords: Union[str, Tuple[str, ...]],
|
169
|
-
data: "FoamFile._SetData",
|
170
|
-
) -> None:
|
171
|
-
self._setitem(keywords, data)
|
172
|
-
|
173
161
|
def __delitem__(self, keywords: Union[str, Tuple[str, ...]]) -> None:
|
174
162
|
if not isinstance(keywords, tuple):
|
175
163
|
keywords = (keywords,)
|
@@ -215,3 +203,138 @@ class FoamFile(
|
|
215
203
|
"""Return a nested dict representation of the file."""
|
216
204
|
_, parsed = self._read()
|
217
205
|
return parsed.as_dict()
|
206
|
+
|
207
|
+
|
208
|
+
class FoamFieldFile(FoamFile):
|
209
|
+
"""An OpenFOAM dictionary file representing a field as a mutable mapping."""
|
210
|
+
|
211
|
+
class BoundariesSubDict(FoamFile.SubDict):
|
212
|
+
def __getitem__(self, keyword: str) -> "FoamFieldFile.BoundarySubDict":
|
213
|
+
value = super().__getitem__(keyword)
|
214
|
+
if not isinstance(value, FoamFieldFile.BoundarySubDict):
|
215
|
+
assert not isinstance(value, FoamFile.SubDict)
|
216
|
+
raise TypeError(f"boundary {keyword} is not a dictionary")
|
217
|
+
return value
|
218
|
+
|
219
|
+
class BoundarySubDict(FoamFile.SubDict):
|
220
|
+
"""An OpenFOAM dictionary representing a boundary condition as a mutable mapping."""
|
221
|
+
|
222
|
+
@property
|
223
|
+
def type(self) -> str:
|
224
|
+
"""Alias of `self["type"]`."""
|
225
|
+
ret = self["type"]
|
226
|
+
if not isinstance(ret, str):
|
227
|
+
raise TypeError("type is not a string")
|
228
|
+
return ret
|
229
|
+
|
230
|
+
@type.setter
|
231
|
+
def type(self, data: str) -> None:
|
232
|
+
self["type"] = data
|
233
|
+
|
234
|
+
@property
|
235
|
+
def value(
|
236
|
+
self,
|
237
|
+
) -> Union[
|
238
|
+
int,
|
239
|
+
float,
|
240
|
+
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
241
|
+
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
242
|
+
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
243
|
+
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
244
|
+
]:
|
245
|
+
"""Alias of `self["value"]`."""
|
246
|
+
ret = self["value"]
|
247
|
+
if not isinstance(ret, (int, float, Sequence)):
|
248
|
+
raise TypeError("value is not a field")
|
249
|
+
return cast(
|
250
|
+
Union[
|
251
|
+
int, float, Sequence[Union[int, float, Sequence[Union[int, float]]]]
|
252
|
+
],
|
253
|
+
ret,
|
254
|
+
)
|
255
|
+
|
256
|
+
@value.setter
|
257
|
+
def value(
|
258
|
+
self,
|
259
|
+
value: Union[
|
260
|
+
int,
|
261
|
+
float,
|
262
|
+
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
263
|
+
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
264
|
+
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
265
|
+
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
266
|
+
],
|
267
|
+
) -> None:
|
268
|
+
self["value"] = value
|
269
|
+
|
270
|
+
@value.deleter
|
271
|
+
def value(self) -> None:
|
272
|
+
del self["value"]
|
273
|
+
|
274
|
+
def __getitem__(
|
275
|
+
self, keywords: Union[str, Tuple[str, ...]]
|
276
|
+
) -> Union[FoamFile.Data, FoamFile.SubDict]:
|
277
|
+
if not isinstance(keywords, tuple):
|
278
|
+
keywords = (keywords,)
|
279
|
+
|
280
|
+
ret = super().__getitem__(keywords)
|
281
|
+
if keywords[0] == "boundaryField" and isinstance(ret, FoamFile.SubDict):
|
282
|
+
if len(keywords) == 1:
|
283
|
+
ret = FoamFieldFile.BoundariesSubDict(self, keywords)
|
284
|
+
elif len(keywords) == 2:
|
285
|
+
ret = FoamFieldFile.BoundarySubDict(self, keywords)
|
286
|
+
return ret
|
287
|
+
|
288
|
+
@property
|
289
|
+
def dimensions(self) -> Union[FoamFile.DimensionSet, Sequence[Union[int, float]]]:
|
290
|
+
"""Alias of `self["dimensions"]`."""
|
291
|
+
ret = self["dimensions"]
|
292
|
+
if not isinstance(ret, FoamFile.DimensionSet):
|
293
|
+
raise TypeError("dimensions is not a DimensionSet")
|
294
|
+
return ret
|
295
|
+
|
296
|
+
@dimensions.setter
|
297
|
+
def dimensions(
|
298
|
+
self, value: Union[FoamFile.DimensionSet, Sequence[Union[int, float]]]
|
299
|
+
) -> None:
|
300
|
+
self["dimensions"] = value
|
301
|
+
|
302
|
+
@property
|
303
|
+
def internal_field(
|
304
|
+
self,
|
305
|
+
) -> Union[
|
306
|
+
int,
|
307
|
+
float,
|
308
|
+
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
309
|
+
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
310
|
+
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
311
|
+
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
312
|
+
]:
|
313
|
+
"""Alias of `self["internalField"]`."""
|
314
|
+
ret = self["internalField"]
|
315
|
+
if not isinstance(ret, (int, float, Sequence)):
|
316
|
+
raise TypeError("internalField is not a field")
|
317
|
+
return cast(Union[int, float, Sequence[Union[int, float]]], ret)
|
318
|
+
|
319
|
+
@internal_field.setter
|
320
|
+
def internal_field(
|
321
|
+
self,
|
322
|
+
value: Union[
|
323
|
+
int,
|
324
|
+
float,
|
325
|
+
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
326
|
+
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
327
|
+
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
328
|
+
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
329
|
+
],
|
330
|
+
) -> None:
|
331
|
+
self["internalField"] = value
|
332
|
+
|
333
|
+
@property
|
334
|
+
def boundary_field(self) -> "FoamFieldFile.BoundariesSubDict":
|
335
|
+
"""Alias of `self["boundaryField"]`."""
|
336
|
+
ret = self["boundaryField"]
|
337
|
+
if not isinstance(ret, FoamFieldFile.BoundariesSubDict):
|
338
|
+
assert not isinstance(ret, FoamFile.SubDict)
|
339
|
+
raise TypeError("boundaryField is not a dictionary")
|
340
|
+
return ret
|
foamlib/_files/_io.py
CHANGED
foamlib/_files/_serialization.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import array
|
2
2
|
import itertools
|
3
3
|
import sys
|
4
|
+
from enum import Enum, auto
|
4
5
|
|
5
6
|
if sys.version_info >= (3, 9):
|
6
7
|
from collections.abc import Mapping
|
@@ -18,33 +19,26 @@ except ModuleNotFoundError:
|
|
18
19
|
numpy = False
|
19
20
|
|
20
21
|
|
22
|
+
class Kind(Enum):
|
23
|
+
DEFAULT = auto()
|
24
|
+
LIST_ENTRY = auto()
|
25
|
+
FIELD = auto()
|
26
|
+
BINARY_FIELD = auto()
|
27
|
+
DIMENSIONS = auto()
|
28
|
+
|
29
|
+
|
21
30
|
def dumpb(
|
22
31
|
data: FoamDict._SetData,
|
23
32
|
*,
|
24
|
-
|
25
|
-
assume_dimensions: bool = False,
|
26
|
-
assume_data_entries: bool = False,
|
27
|
-
binary_fields: bool = False,
|
33
|
+
kind: Kind = Kind.DEFAULT,
|
28
34
|
) -> bytes:
|
29
35
|
if numpy and isinstance(data, np.ndarray):
|
30
|
-
return dumpb(
|
31
|
-
data.tolist(),
|
32
|
-
assume_field=assume_field,
|
33
|
-
assume_dimensions=assume_dimensions,
|
34
|
-
assume_data_entries=assume_data_entries,
|
35
|
-
binary_fields=binary_fields,
|
36
|
-
)
|
36
|
+
return dumpb(data.tolist(), kind=kind)
|
37
37
|
|
38
38
|
elif isinstance(data, Mapping):
|
39
39
|
entries = []
|
40
40
|
for k, v in data.items():
|
41
|
-
b = dumpb(
|
42
|
-
v,
|
43
|
-
assume_field=assume_field,
|
44
|
-
assume_dimensions=assume_dimensions,
|
45
|
-
assume_data_entries=True,
|
46
|
-
binary_fields=binary_fields,
|
47
|
-
)
|
41
|
+
b = dumpb(v, kind=kind)
|
48
42
|
if isinstance(v, Mapping):
|
49
43
|
entries.append(dumpb(k) + b"\n" + b"{\n" + b + b"\n}")
|
50
44
|
elif b:
|
@@ -55,11 +49,11 @@ def dumpb(
|
|
55
49
|
return b"\n".join(entries)
|
56
50
|
|
57
51
|
elif isinstance(data, FoamDict.DimensionSet) or (
|
58
|
-
|
52
|
+
kind == Kind.DIMENSIONS and is_sequence(data) and len(data) == 7
|
59
53
|
):
|
60
54
|
return b"[" + b" ".join(dumpb(v) for v in data) + b"]"
|
61
55
|
|
62
|
-
elif
|
56
|
+
elif (kind == Kind.FIELD or kind == Kind.BINARY_FIELD) and (
|
63
57
|
isinstance(data, (int, float))
|
64
58
|
or is_sequence(data)
|
65
59
|
and data
|
@@ -68,25 +62,20 @@ def dumpb(
|
|
68
62
|
):
|
69
63
|
return b"uniform " + dumpb(data)
|
70
64
|
|
71
|
-
elif
|
65
|
+
elif (kind == Kind.FIELD or kind == Kind.BINARY_FIELD) and is_sequence(data):
|
72
66
|
if isinstance(data[0], (int, float)):
|
73
|
-
|
67
|
+
tensor_kind = b"scalar"
|
74
68
|
elif len(data[0]) == 3:
|
75
|
-
|
69
|
+
tensor_kind = b"vector"
|
76
70
|
elif len(data[0]) == 6:
|
77
|
-
|
71
|
+
tensor_kind = b"symmTensor"
|
78
72
|
elif len(data[0]) == 9:
|
79
|
-
|
73
|
+
tensor_kind = b"tensor"
|
80
74
|
else:
|
81
|
-
return dumpb(
|
82
|
-
data,
|
83
|
-
assume_dimensions=assume_dimensions,
|
84
|
-
assume_data_entries=assume_data_entries,
|
85
|
-
binary_fields=binary_fields,
|
86
|
-
)
|
75
|
+
return dumpb(data)
|
87
76
|
|
88
|
-
if
|
89
|
-
if
|
77
|
+
if kind == Kind.BINARY_FIELD:
|
78
|
+
if tensor_kind == b"scalar":
|
90
79
|
contents = b"(" + array.array("d", data).tobytes() + b")"
|
91
80
|
else:
|
92
81
|
contents = (
|
@@ -97,37 +86,27 @@ def dumpb(
|
|
97
86
|
else:
|
98
87
|
contents = dumpb(data)
|
99
88
|
|
100
|
-
return b"nonuniform List<" +
|
89
|
+
return b"nonuniform List<" + tensor_kind + b"> " + dumpb(len(data)) + contents
|
101
90
|
|
102
|
-
elif
|
103
|
-
return b" ".join(
|
104
|
-
dumpb(
|
105
|
-
v,
|
106
|
-
assume_field=assume_field,
|
107
|
-
assume_dimensions=assume_dimensions,
|
108
|
-
binary_fields=binary_fields,
|
109
|
-
)
|
110
|
-
for v in data
|
111
|
-
)
|
91
|
+
elif kind != Kind.LIST_ENTRY and isinstance(data, tuple):
|
92
|
+
return b" ".join(dumpb(v) for v in data)
|
112
93
|
|
113
94
|
elif isinstance(data, FoamDict.Dimensioned):
|
114
95
|
if data.name is not None:
|
115
96
|
return (
|
116
97
|
dumpb(data.name)
|
117
98
|
+ b" "
|
118
|
-
+ dumpb(data.dimensions,
|
99
|
+
+ dumpb(data.dimensions, kind=Kind.DIMENSIONS)
|
119
100
|
+ b" "
|
120
101
|
+ dumpb(data.value)
|
121
102
|
)
|
122
103
|
else:
|
123
104
|
return (
|
124
|
-
dumpb(data.dimensions,
|
125
|
-
+ b" "
|
126
|
-
+ dumpb(data.value)
|
105
|
+
dumpb(data.dimensions, kind=Kind.DIMENSIONS) + b" " + dumpb(data.value)
|
127
106
|
)
|
128
107
|
|
129
108
|
elif is_sequence(data):
|
130
|
-
return b"(" + b" ".join(dumpb(v) for v in data) + b")"
|
109
|
+
return b"(" + b" ".join(dumpb(v, kind=Kind.LIST_ENTRY) for v in data) + b")"
|
131
110
|
|
132
111
|
elif data is True:
|
133
112
|
return b"yes"
|
foamlib/_util.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import asyncio
|
2
|
+
import os
|
2
3
|
import subprocess
|
3
4
|
import sys
|
4
5
|
from pathlib import Path
|
@@ -47,12 +48,20 @@ def _check(
|
|
47
48
|
warn(f"Command {cmd} printed to stderr.\n{stderr}", CalledProcessWarning)
|
48
49
|
|
49
50
|
|
51
|
+
def _env(cwd: Optional[Union[str, Path]] = None) -> Optional[Mapping[str, str]]:
|
52
|
+
if cwd is not None:
|
53
|
+
env = os.environ.copy()
|
54
|
+
env["PWD"] = str(cwd)
|
55
|
+
return env
|
56
|
+
else:
|
57
|
+
return None
|
58
|
+
|
59
|
+
|
50
60
|
def run_process(
|
51
61
|
cmd: Union[Sequence[Union[str, Path]], str, Path],
|
52
62
|
*,
|
53
63
|
check: bool = True,
|
54
64
|
cwd: Union[None, str, Path] = None,
|
55
|
-
env: Union[None, Mapping[str, str]] = None,
|
56
65
|
) -> None:
|
57
66
|
shell = not is_sequence(cmd)
|
58
67
|
|
@@ -65,8 +74,8 @@ def run_process(
|
|
65
74
|
proc = subprocess.run(
|
66
75
|
cmd,
|
67
76
|
cwd=cwd,
|
68
|
-
env=
|
69
|
-
stdout=
|
77
|
+
env=_env(cwd),
|
78
|
+
stdout=None,
|
70
79
|
stderr=subprocess.PIPE if check else subprocess.DEVNULL,
|
71
80
|
text=True,
|
72
81
|
shell=shell,
|
@@ -81,13 +90,12 @@ async def run_process_async(
|
|
81
90
|
*,
|
82
91
|
check: bool = True,
|
83
92
|
cwd: Union[None, str, Path] = None,
|
84
|
-
env: Union[None, Mapping[str, str]] = None,
|
85
93
|
) -> None:
|
86
94
|
if not is_sequence(cmd):
|
87
95
|
proc = await asyncio.create_subprocess_shell(
|
88
96
|
str(cmd),
|
89
97
|
cwd=cwd,
|
90
|
-
env=
|
98
|
+
env=_env(cwd),
|
91
99
|
stdout=asyncio.subprocess.DEVNULL,
|
92
100
|
stderr=asyncio.subprocess.PIPE if check else asyncio.subprocess.DEVNULL,
|
93
101
|
)
|
@@ -98,7 +106,7 @@ async def run_process_async(
|
|
98
106
|
proc = await asyncio.create_subprocess_exec(
|
99
107
|
*cmd,
|
100
108
|
cwd=cwd,
|
101
|
-
env=
|
109
|
+
env=_env(cwd),
|
102
110
|
stdout=asyncio.subprocess.DEVNULL,
|
103
111
|
stderr=asyncio.subprocess.PIPE if check else asyncio.subprocess.DEVNULL,
|
104
112
|
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.5
|
4
4
|
Summary: A Python interface for interacting with OpenFOAM
|
5
5
|
Author-email: "Gabriel S. Gerlero" <ggerlero@cimec.unl.edu.ar>
|
6
6
|
Project-URL: Homepage, https://github.com/gerlero/foamlib
|
@@ -58,11 +58,11 @@ Requires-Dist: numpy <2,>=1 ; extra == 'typing'
|
|
58
58
|
|
59
59
|
**foamlib** provides a simple, modern and ergonomic Python interface for interacting with [OpenFOAM](https://www.openfoam.com).
|
60
60
|
|
61
|
-
It offers the following classes
|
61
|
+
It offers the following classes:
|
62
62
|
|
63
|
+
* [`FoamFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFile) (and [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile)): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s, using `foamlib`'s own parser. Supports both ASCII and binary field formats.
|
63
64
|
* [`FoamCase`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamCase): a class for manipulating, executing and accessing the results of OpenFOAM cases.
|
64
65
|
* [`AsyncFoamCase`](https://foamlib.readthedocs.io/en/stable/#foamlib.AsyncFoamCase): variant of `FoamCase` with asynchronous methods for running multiple cases at once.
|
65
|
-
* [`FoamFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFile): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s.
|
66
66
|
|
67
67
|
## Get started
|
68
68
|
|
@@ -130,6 +130,16 @@ async def run_case():
|
|
130
130
|
asyncio.run(run_case())
|
131
131
|
```
|
132
132
|
|
133
|
+
### Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
134
|
+
|
135
|
+
```python
|
136
|
+
from foamlib import FoamFieldFile
|
137
|
+
|
138
|
+
U = FoamFieldFile(Path(my_pitz) / "0/U")
|
139
|
+
|
140
|
+
print(U.internal_field)
|
141
|
+
```
|
142
|
+
|
133
143
|
## Documentation
|
134
144
|
|
135
145
|
For more information, check out the [documentation](https://foamlib.readthedocs.io/).
|
@@ -0,0 +1,15 @@
|
|
1
|
+
foamlib/__init__.py,sha256=Zvz69We30bHHGeRvmwmUvLTCPDoYxSHNsMGfJm8NTro,431
|
2
|
+
foamlib/_cases.py,sha256=ELwX-Gr3ZB11axG6coHqXDyGh9Xb7kgAfYkhCsEGZy4,20278
|
3
|
+
foamlib/_util.py,sha256=hh5gTJqEvQcqbt0_tA2xMceyqtAIaqNd78jvePdAQ7w,3037
|
4
|
+
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
+
foamlib/_files/__init__.py,sha256=vDkPj8u8bX_I_m2YfeKvXBgwg8D1ufyFCfHGHKN3JPQ,140
|
6
|
+
foamlib/_files/_base.py,sha256=YA5a-i5HZuA3JslCD6r-DwZzpSA8r42dqSXef286Ako,2050
|
7
|
+
foamlib/_files/_files.py,sha256=JcOVP3eu9QYCOPt_DfobigKsd0VqgJRfEVytMOwES_g,10815
|
8
|
+
foamlib/_files/_io.py,sha256=So9rG6iW77sRK2xFz5KHX6AFtYc2L19voAwn-_NmQow,2075
|
9
|
+
foamlib/_files/_parsing.py,sha256=-zSpEDjuPxzOdsLWaeQl7j6FZHyw2-jXNgOCXkcGskU,7308
|
10
|
+
foamlib/_files/_serialization.py,sha256=bGit_qcQvbGd20yuPdAXfx7d9ArmHa_tSAPYPPecgCg,3266
|
11
|
+
foamlib-0.3.5.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
12
|
+
foamlib-0.3.5.dist-info/METADATA,sha256=5NbPf_3gASyHvck8fOHMawq0W70o0GqEtO6tL42se-o,5037
|
13
|
+
foamlib-0.3.5.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
14
|
+
foamlib-0.3.5.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
15
|
+
foamlib-0.3.5.dist-info/RECORD,,
|
foamlib/_files/_fields.py
DELETED
@@ -1,170 +0,0 @@
|
|
1
|
-
import sys
|
2
|
-
from typing import Any, Tuple, Union, cast
|
3
|
-
|
4
|
-
if sys.version_info >= (3, 9):
|
5
|
-
from collections.abc import Sequence
|
6
|
-
else:
|
7
|
-
from typing import Sequence
|
8
|
-
|
9
|
-
from ._files import FoamFile
|
10
|
-
|
11
|
-
try:
|
12
|
-
import numpy as np
|
13
|
-
except ModuleNotFoundError:
|
14
|
-
pass
|
15
|
-
|
16
|
-
|
17
|
-
class FoamFieldFile(FoamFile):
|
18
|
-
"""An OpenFOAM dictionary file representing a field as a mutable mapping."""
|
19
|
-
|
20
|
-
class BoundariesSubDict(FoamFile.SubDict):
|
21
|
-
def __getitem__(self, keyword: str) -> "FoamFieldFile.BoundarySubDict":
|
22
|
-
value = super().__getitem__(keyword)
|
23
|
-
if not isinstance(value, FoamFieldFile.BoundarySubDict):
|
24
|
-
assert not isinstance(value, FoamFile.SubDict)
|
25
|
-
raise TypeError(f"boundary {keyword} is not a dictionary")
|
26
|
-
return value
|
27
|
-
|
28
|
-
class BoundarySubDict(FoamFile.SubDict):
|
29
|
-
"""An OpenFOAM dictionary representing a boundary condition as a mutable mapping."""
|
30
|
-
|
31
|
-
def __setitem__(
|
32
|
-
self,
|
33
|
-
keyword: str,
|
34
|
-
data: FoamFile._SetData,
|
35
|
-
) -> None:
|
36
|
-
if keyword == "value":
|
37
|
-
self._setitem(keyword, data, assume_field=True)
|
38
|
-
else:
|
39
|
-
self._setitem(keyword, data)
|
40
|
-
|
41
|
-
@property
|
42
|
-
def type(self) -> str:
|
43
|
-
"""Alias of `self["type"]`."""
|
44
|
-
ret = self["type"]
|
45
|
-
if not isinstance(ret, str):
|
46
|
-
raise TypeError("type is not a string")
|
47
|
-
return ret
|
48
|
-
|
49
|
-
@type.setter
|
50
|
-
def type(self, data: str) -> None:
|
51
|
-
self["type"] = data
|
52
|
-
|
53
|
-
@property
|
54
|
-
def value(
|
55
|
-
self,
|
56
|
-
) -> Union[
|
57
|
-
int,
|
58
|
-
float,
|
59
|
-
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
60
|
-
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
61
|
-
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
62
|
-
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
63
|
-
]:
|
64
|
-
"""Alias of `self["value"]`."""
|
65
|
-
ret = self["value"]
|
66
|
-
if not isinstance(ret, (int, float, Sequence)):
|
67
|
-
raise TypeError("value is not a field")
|
68
|
-
return cast(
|
69
|
-
Union[
|
70
|
-
int, float, Sequence[Union[int, float, Sequence[Union[int, float]]]]
|
71
|
-
],
|
72
|
-
ret,
|
73
|
-
)
|
74
|
-
|
75
|
-
@value.setter
|
76
|
-
def value(
|
77
|
-
self,
|
78
|
-
value: Union[
|
79
|
-
int,
|
80
|
-
float,
|
81
|
-
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
82
|
-
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
83
|
-
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
84
|
-
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
85
|
-
],
|
86
|
-
) -> None:
|
87
|
-
self["value"] = value
|
88
|
-
|
89
|
-
@value.deleter
|
90
|
-
def value(self) -> None:
|
91
|
-
del self["value"]
|
92
|
-
|
93
|
-
def __getitem__(
|
94
|
-
self, keywords: Union[str, Tuple[str, ...]]
|
95
|
-
) -> Union[FoamFile.Data, FoamFile.SubDict]:
|
96
|
-
if not isinstance(keywords, tuple):
|
97
|
-
keywords = (keywords,)
|
98
|
-
|
99
|
-
ret = super().__getitem__(keywords)
|
100
|
-
if keywords[0] == "boundaryField" and isinstance(ret, FoamFile.SubDict):
|
101
|
-
if len(keywords) == 1:
|
102
|
-
ret = FoamFieldFile.BoundariesSubDict(self, keywords)
|
103
|
-
elif len(keywords) == 2:
|
104
|
-
ret = FoamFieldFile.BoundarySubDict(self, keywords)
|
105
|
-
return ret
|
106
|
-
|
107
|
-
def __setitem__(self, keywords: Union[str, Tuple[str, ...]], value: Any) -> None:
|
108
|
-
if not isinstance(keywords, tuple):
|
109
|
-
keywords = (keywords,)
|
110
|
-
|
111
|
-
if keywords == ("internalField",):
|
112
|
-
self._setitem(keywords, value, assume_field=True)
|
113
|
-
elif keywords == ("dimensions",):
|
114
|
-
self._setitem(keywords, value, assume_dimensions=True)
|
115
|
-
else:
|
116
|
-
self._setitem(keywords, value)
|
117
|
-
|
118
|
-
@property
|
119
|
-
def dimensions(self) -> Union[FoamFile.DimensionSet, Sequence[Union[int, float]]]:
|
120
|
-
"""Alias of `self["dimensions"]`."""
|
121
|
-
ret = self["dimensions"]
|
122
|
-
if not isinstance(ret, FoamFile.DimensionSet):
|
123
|
-
raise TypeError("dimensions is not a DimensionSet")
|
124
|
-
return ret
|
125
|
-
|
126
|
-
@dimensions.setter
|
127
|
-
def dimensions(
|
128
|
-
self, value: Union[FoamFile.DimensionSet, Sequence[Union[int, float]]]
|
129
|
-
) -> None:
|
130
|
-
self["dimensions"] = value
|
131
|
-
|
132
|
-
@property
|
133
|
-
def internal_field(
|
134
|
-
self,
|
135
|
-
) -> Union[
|
136
|
-
int,
|
137
|
-
float,
|
138
|
-
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
139
|
-
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
140
|
-
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
141
|
-
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
142
|
-
]:
|
143
|
-
"""Alias of `self["internalField"]`."""
|
144
|
-
ret = self["internalField"]
|
145
|
-
if not isinstance(ret, (int, float, Sequence)):
|
146
|
-
raise TypeError("internalField is not a field")
|
147
|
-
return cast(Union[int, float, Sequence[Union[int, float]]], ret)
|
148
|
-
|
149
|
-
@internal_field.setter
|
150
|
-
def internal_field(
|
151
|
-
self,
|
152
|
-
value: Union[
|
153
|
-
int,
|
154
|
-
float,
|
155
|
-
Sequence[Union[int, float, Sequence[Union[int, float]]]],
|
156
|
-
"np.ndarray[Tuple[()], np.dtype[np.generic]]",
|
157
|
-
"np.ndarray[Tuple[int], np.dtype[np.generic]]",
|
158
|
-
"np.ndarray[Tuple[int, int], np.dtype[np.generic]]",
|
159
|
-
],
|
160
|
-
) -> None:
|
161
|
-
self["internalField"] = value
|
162
|
-
|
163
|
-
@property
|
164
|
-
def boundary_field(self) -> "FoamFieldFile.BoundariesSubDict":
|
165
|
-
"""Alias of `self["boundaryField"]`."""
|
166
|
-
ret = self["boundaryField"]
|
167
|
-
if not isinstance(ret, FoamFieldFile.BoundariesSubDict):
|
168
|
-
assert not isinstance(ret, FoamFile.SubDict)
|
169
|
-
raise TypeError("boundaryField is not a dictionary")
|
170
|
-
return ret
|
foamlib-0.3.4.dist-info/RECORD
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
foamlib/__init__.py,sha256=1kmwoS1I2xRIk3KC9kFbsnLNljDVG3TOtdq0l9bnKE4,431
|
2
|
-
foamlib/_cases.py,sha256=xR_m_4-YJbYfbIwhw17F6ieHw6BLCRgneDa4-xOoEf8,20567
|
3
|
-
foamlib/_util.py,sha256=0HJ9n8QG9K7jC_xUDzOJo_NA2DBCJKJRLpmd5Yu42kU,2901
|
4
|
-
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
5
|
-
foamlib/_files/__init__.py,sha256=m4y_7wFV2Voly1aJrTYALjT3S1Aq7EbaijxdGFbJrmU,160
|
6
|
-
foamlib/_files/_base.py,sha256=YA5a-i5HZuA3JslCD6r-DwZzpSA8r42dqSXef286Ako,2050
|
7
|
-
foamlib/_files/_fields.py,sha256=kY8EKNYp89asDOQjr-U9UmCqC2_Tt11zMfTQSWTvoms,5782
|
8
|
-
foamlib/_files/_files.py,sha256=0xQ7Y-TEOgnbCq0X781gtX2RMxw7Xu024RXbQshmt6I,6293
|
9
|
-
foamlib/_files/_io.py,sha256=GaOrwJt_upUyNPgeRXXrooppto82dUwAK2C9jNFqSNc,2071
|
10
|
-
foamlib/_files/_parsing.py,sha256=-zSpEDjuPxzOdsLWaeQl7j6FZHyw2-jXNgOCXkcGskU,7308
|
11
|
-
foamlib/_files/_serialization.py,sha256=WBDGt_P0FJ6X2uzav2JGvUHDhhyoRQ40cSF4kOK9qhw,3879
|
12
|
-
foamlib-0.3.4.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
13
|
-
foamlib-0.3.4.dist-info/METADATA,sha256=IVi0yNXJRfXYBxNur8KU46Jg6EOOXvfZtEf8g4O_C3w,4650
|
14
|
-
foamlib-0.3.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
15
|
-
foamlib-0.3.4.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
16
|
-
foamlib-0.3.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|