foamlib 0.8.11__tar.gz → 0.9.1__tar.gz
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-0.8.11 → foamlib-0.9.1}/PKG-INFO +1 -1
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/__init__.py +1 -1
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_files/_parsing.py +206 -110
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_files/_types.py +0 -34
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_files.py +5 -6
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_advanced.py +22 -14
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_basic.py +41 -18
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_decompose_par.py +2 -1
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_intermediate.py +125 -100
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_poly_mesh.py +12 -11
- {foamlib-0.8.11 → foamlib-0.9.1}/.devcontainer.json +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.dockerignore +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.git-blame-ignore-revs +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.github/dependabot.yml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.github/workflows/ci.yml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.github/workflows/docker.yml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.github/workflows/dockerhub-description.yml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.github/workflows/pypi-publish.yml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.gitignore +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/.readthedocs.yaml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/CONTRIBUTING.md +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/Dockerfile +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/LICENSE.txt +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/README.md +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/benchmark/benchmark.png +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/benchmark/benchmark.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/benchmark/requirements.txt +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/benchmark/ruff.toml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/Makefile +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/cases.rst +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/conf.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/files.rst +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/index.rst +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/make.bat +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/docs/ruff.toml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/__init__.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_async.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_base.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_run.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_slurm.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_subprocess.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_sync.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_cases/_util.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_files/__init__.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_files/_files.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_files/_io.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/_files/_serialization.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/foamlib/py.typed +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/logo.png +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/pyproject.toml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/__init__.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/ruff.toml +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_cases/__init__.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_cases/test_cavity.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_cases/test_cavity_async.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_cases/test_flange.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_cases/test_flange_async.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_example.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/__init__.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_dumps.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/__init__.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_fields.py +0 -0
- {foamlib-0.8.11 → foamlib-0.9.1}/tests/test_files/test_parsing/test_fv_schemes.py +0 -0
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
2
2
|
|
3
3
|
import re
|
4
4
|
import sys
|
5
|
-
from typing import Tuple, Union, cast
|
5
|
+
from typing import TYPE_CHECKING, Tuple, Union, cast
|
6
6
|
|
7
7
|
if sys.version_info >= (3, 9):
|
8
8
|
from collections.abc import Iterator, Mapping, MutableMapping, Sequence
|
@@ -25,6 +25,7 @@ from pyparsing import (
|
|
25
25
|
LineEnd,
|
26
26
|
Literal,
|
27
27
|
Located,
|
28
|
+
NoMatch,
|
28
29
|
Opt,
|
29
30
|
ParserElement,
|
30
31
|
ParseResults,
|
@@ -37,131 +38,172 @@ from pyparsing import (
|
|
37
38
|
printables,
|
38
39
|
)
|
39
40
|
|
40
|
-
from ._types import Data, Dimensioned, DimensionSet, File
|
41
|
+
from ._types import Data, Dimensioned, DimensionSet, File
|
41
42
|
|
43
|
+
if TYPE_CHECKING:
|
44
|
+
from numpy.typing import DTypeLike
|
42
45
|
|
43
|
-
def _tensor(tensor_kind: TensorKind, *, ignore: Regex | None = None) -> Regex:
|
44
|
-
float_pattern = r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))"
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
def _ascii_numeric_list(
|
48
|
+
dtype: DTypeLike,
|
49
|
+
*,
|
50
|
+
nested: int | None = None,
|
51
|
+
ignore: Regex | None = None,
|
52
|
+
empty_ok: bool = False,
|
53
|
+
) -> ParserElement:
|
54
|
+
dtype = np.dtype(dtype)
|
55
|
+
|
56
|
+
if np.issubdtype(dtype, np.floating):
|
57
|
+
element = common.ieee_float
|
58
|
+
element_pattern = r"(?i:[+-]?(?:(?:\d+\.?\d*(?:e[+-]?\d+)?)|nan|inf(?:inity)?))"
|
59
|
+
elif np.issubdtype(dtype, np.integer):
|
60
|
+
element = common.integer
|
61
|
+
element_pattern = r"(?:-?\d+)"
|
62
|
+
else:
|
63
|
+
msg = f"Unsupported dtype: {dtype}"
|
64
|
+
raise TypeError(msg)
|
52
65
|
|
53
|
-
|
54
|
-
rf"
|
66
|
+
spacing_pattern = (
|
67
|
+
rf"(?:(?:\s|{ignore.re.pattern})+)" if ignore is not None else r"(?:\s+)"
|
55
68
|
)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
else tks[0][1:-1],
|
61
|
-
sep=" ",
|
69
|
+
|
70
|
+
if nested is not None:
|
71
|
+
element = (
|
72
|
+
Literal("(").suppress() + Group(element[nested]) + Literal(")").suppress()
|
62
73
|
)
|
63
|
-
|
64
|
-
return ret
|
74
|
+
element_pattern = rf"(?:{spacing_pattern}?\({element_pattern}?(?:{element_pattern}{spacing_pattern}){{{nested - 1}}}{element_pattern}{spacing_pattern}?\))"
|
65
75
|
|
76
|
+
list_ = Forward()
|
66
77
|
|
67
|
-
def
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
78
|
+
def process_count(tks: ParseResults) -> None:
|
79
|
+
nonlocal list_
|
80
|
+
|
81
|
+
if not tks:
|
82
|
+
count = None
|
83
|
+
else:
|
84
|
+
(count,) = tks
|
85
|
+
assert isinstance(count, int)
|
86
|
+
|
87
|
+
if count is None:
|
88
|
+
if not empty_ok:
|
89
|
+
list_pattern = rf"\({spacing_pattern}?(?:{element_pattern}{spacing_pattern})*{element_pattern}{spacing_pattern}?\)"
|
90
|
+
else:
|
91
|
+
list_pattern = rf"\({spacing_pattern}?(?:{element_pattern}{spacing_pattern})*{element_pattern}?{spacing_pattern}?\)"
|
92
|
+
|
93
|
+
elif count == 0:
|
94
|
+
if not empty_ok:
|
95
|
+
list_ <<= NoMatch()
|
96
|
+
else:
|
97
|
+
list_ <<= (Literal("(") + Literal(")")).add_parse_action(
|
98
|
+
lambda: np.empty((0, nested) if nested else 0, dtype=dtype)
|
99
|
+
)
|
100
|
+
return
|
101
|
+
|
102
|
+
else:
|
103
|
+
list_pattern = rf"\({spacing_pattern}?(?:{element_pattern}{spacing_pattern}){{{count - 1}}}{element_pattern}{spacing_pattern}?\)"
|
104
|
+
|
105
|
+
list_ <<= Regex(list_pattern).add_parse_action(
|
106
|
+
lambda tks: to_array(tks, dtype=dtype)
|
79
107
|
)
|
80
|
-
| (
|
81
|
-
common.integer + Literal("{").suppress() + entry + Literal("}").suppress()
|
82
|
-
).set_parse_action(lambda tks: [[tks[1]] * tks[0]])
|
83
|
-
)
|
84
108
|
|
109
|
+
def to_array(
|
110
|
+
tks: ParseResults, *, dtype: DTypeLike
|
111
|
+
) -> np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.integer | np.floating]]:
|
112
|
+
(s,) = tks
|
113
|
+
assert s.startswith("(")
|
114
|
+
assert s.endswith(")")
|
115
|
+
s = s[1:-1]
|
116
|
+
if ignore is not None:
|
117
|
+
s = re.sub(ignore.re, " ", s)
|
118
|
+
if nested is not None:
|
119
|
+
s = s.replace("(", " ").replace(")", " ")
|
120
|
+
|
121
|
+
ret: np.ndarray[
|
122
|
+
tuple[int] | tuple[int, int], np.dtype[np.integer | np.floating]
|
123
|
+
] = np.fromstring(s, sep=" ", dtype=dtype) # type: ignore[assignment]
|
124
|
+
|
125
|
+
if nested is not None:
|
126
|
+
ret = ret.reshape(-1, nested)
|
85
127
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
128
|
+
return ret
|
129
|
+
|
130
|
+
def to_full_array(
|
131
|
+
tks: ParseResults, *, dtype: type
|
132
|
+
) -> np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.integer | np.floating]]:
|
133
|
+
count, lst = tks
|
134
|
+
assert isinstance(count, int)
|
92
135
|
|
93
|
-
|
136
|
+
if nested is None:
|
137
|
+
return np.full(count, lst, dtype=dtype)
|
94
138
|
|
139
|
+
return np.full((count, nested), lst, dtype=dtype) # type: ignore[return-value]
|
95
140
|
|
96
|
-
|
97
|
-
|
98
|
-
)
|
99
|
-
|
100
|
-
|
141
|
+
ret = ((Opt(common.integer).add_parse_action(process_count)).suppress() + list_) | (
|
142
|
+
common.integer + Literal("{").suppress() + element + Literal("}").suppress()
|
143
|
+
).add_parse_action(lambda tks: to_full_array(tks, dtype=float))
|
144
|
+
|
145
|
+
if ignore is not None:
|
146
|
+
ret.ignore(ignore)
|
101
147
|
|
102
|
-
|
103
|
-
return np.frombuffer(b, dtype=dtype).reshape(-1, *tensor_kind.shape) # type: ignore [return-value]
|
148
|
+
return ret
|
104
149
|
|
105
150
|
|
106
|
-
def
|
107
|
-
|
151
|
+
def _binary_numeric_list(
|
152
|
+
dtype: DTypeLike, *, nested: int | None = None, empty_ok: bool = False
|
108
153
|
) -> ParserElement:
|
109
|
-
|
110
|
-
ignore_pattern = rf"(?:\s|{ignore.re.pattern})+" if ignore is not None else r"\s+"
|
154
|
+
dtype = np.dtype(dtype)
|
111
155
|
|
112
|
-
|
156
|
+
elsize = nested if nested is not None else 1
|
113
157
|
|
114
|
-
list_
|
115
|
-
rf"\((?:{ignore_pattern})?(?:{tensor.re.pattern}{ignore_pattern})*{tensor.re.pattern}(?:{ignore_pattern})?\)"
|
116
|
-
).add_parse_action(
|
117
|
-
lambda tks: [_parse_ascii_field(tks[0], tensor_kind, ignore=ignore)]
|
118
|
-
) | (
|
119
|
-
(Literal("(") + Literal(")"))
|
120
|
-
.suppress()
|
121
|
-
.add_parse_action(lambda: np.array([]).reshape(0, *tensor_kind.shape))
|
122
|
-
)
|
158
|
+
list_ = Forward()
|
123
159
|
|
124
|
-
def
|
160
|
+
def process_count(tks: ParseResults) -> None:
|
125
161
|
nonlocal list_
|
126
|
-
|
127
|
-
assert isinstance(
|
128
|
-
|
129
|
-
if not
|
130
|
-
list_ <<= (
|
131
|
-
((Literal("(") + Literal(")")) | (Literal("{") + Literal("}")))
|
132
|
-
.suppress()
|
133
|
-
.add_parse_action(lambda: np.array([]).reshape(0, *tensor_kind.shape))
|
134
|
-
)
|
162
|
+
(size,) = tks
|
163
|
+
assert isinstance(size, int)
|
164
|
+
|
165
|
+
if size == 0 and not empty_ok:
|
166
|
+
list_ <<= NoMatch()
|
135
167
|
return
|
136
168
|
|
137
|
-
list_ <<= (
|
138
|
-
Regex(
|
139
|
-
rf"\((?:{ignore_pattern})?(?:{tensor.re.pattern}{ignore_pattern}){{{length - 1}}}{tensor.re.pattern}(?:{ignore_pattern})?\)"
|
140
|
-
).add_parse_action(
|
141
|
-
lambda tks: [_parse_ascii_field(tks[0], tensor_kind, ignore=ignore)]
|
142
|
-
)
|
143
|
-
| Regex(
|
144
|
-
rf"\((?s:({'.' * 8 * tensor_kind.size}|{'.' * 4 * tensor_kind.size}){{{length}}})\)"
|
145
|
-
).add_parse_action(
|
146
|
-
lambda tks: [
|
147
|
-
_unpack_binary_field(
|
148
|
-
tks[0][1:-1].encode("latin-1"), tensor_kind, length=length
|
149
|
-
)
|
150
|
-
]
|
151
|
-
)
|
152
|
-
| (
|
153
|
-
Literal("{").suppress() + tensor + Literal("}").suppress()
|
154
|
-
).add_parse_action(
|
155
|
-
lambda tks: [np.full((length, *tensor_kind.shape), tks[0], dtype=float)]
|
156
|
-
)
|
157
|
-
)
|
169
|
+
list_ <<= Regex(rf"\((?s:{'.' * dtype.itemsize * elsize}){{{size}}}\)")
|
158
170
|
|
159
|
-
|
171
|
+
def to_array(
|
172
|
+
tks: ParseResults,
|
173
|
+
) -> np.ndarray[tuple[int] | tuple[int, int], np.dtype[np.integer | np.floating]]:
|
174
|
+
size, s = tks
|
175
|
+
assert isinstance(size, int)
|
176
|
+
assert isinstance(s, str)
|
177
|
+
assert s[0] == "("
|
178
|
+
assert s[-1] == ")"
|
179
|
+
s = s[1:-1]
|
180
|
+
|
181
|
+
ret = np.frombuffer(s.encode("latin-1"), dtype=dtype)
|
182
|
+
|
183
|
+
if nested is not None:
|
184
|
+
ret = ret.reshape(-1, nested)
|
185
|
+
|
186
|
+
return ret # type: ignore[return-value]
|
160
187
|
|
161
188
|
return (
|
162
|
-
|
163
|
-
|
164
|
-
|
189
|
+
common.integer.copy().add_parse_action(process_count) + list_
|
190
|
+
).add_parse_action(to_array)
|
191
|
+
|
192
|
+
|
193
|
+
def _list_of(entry: ParserElement) -> ParserElement:
|
194
|
+
return (
|
195
|
+
(
|
196
|
+
counted_array(entry, common.integer + Literal("(").suppress())
|
197
|
+
+ Literal(")").suppress()
|
198
|
+
).set_parse_action(lambda tks: [tks.as_list()])
|
199
|
+
| (
|
200
|
+
Literal("(").suppress()
|
201
|
+
+ Group((entry)[...], aslist=True)
|
202
|
+
+ Literal(")").suppress()
|
203
|
+
)
|
204
|
+
| (
|
205
|
+
common.integer + Literal("{").suppress() + entry + Literal("}").suppress()
|
206
|
+
).set_parse_action(lambda tks: [[tks[1]] * tks[0]])
|
165
207
|
)
|
166
208
|
|
167
209
|
|
@@ -250,12 +292,11 @@ _SWITCH = (
|
|
250
292
|
_DIMENSIONS = (
|
251
293
|
Literal("[").suppress() + common.number[0, 7] + Literal("]").suppress()
|
252
294
|
).set_parse_action(lambda tks: DimensionSet(*tks))
|
253
|
-
_TENSOR = (
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
)
|
295
|
+
_TENSOR = common.ieee_float | (
|
296
|
+
Literal("(").suppress()
|
297
|
+
+ Group(common.ieee_float[3] | common.ieee_float[6] | common.ieee_float[9])
|
298
|
+
+ Literal(")").suppress()
|
299
|
+
).add_parse_action(lambda tks: np.array(tks[0], dtype=float))
|
259
300
|
_PARENTHESIZED = Forward()
|
260
301
|
_IDENTIFIER = Combine(Word(_IDENTCHARS, _IDENTBODYCHARS) + Opt(_PARENTHESIZED))
|
261
302
|
_PARENTHESIZED <<= Combine(
|
@@ -270,12 +311,55 @@ _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
|
|
270
311
|
_FIELD = (Keyword("uniform", _IDENTBODYCHARS).suppress() + _TENSOR) | (
|
271
312
|
Keyword("nonuniform", _IDENTBODYCHARS).suppress()
|
272
313
|
+ (
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
314
|
+
(
|
315
|
+
Opt(
|
316
|
+
Literal("List") + Literal("<") + Literal("scalar") + Literal(">")
|
317
|
+
).suppress()
|
318
|
+
+ (
|
319
|
+
_ascii_numeric_list(dtype=float, ignore=_COMMENT, empty_ok=True)
|
320
|
+
| _binary_numeric_list(dtype=np.float64, empty_ok=True)
|
321
|
+
| _binary_numeric_list(dtype=np.float32, empty_ok=True)
|
322
|
+
)
|
323
|
+
)
|
324
|
+
| (
|
325
|
+
Opt(
|
326
|
+
Literal("List") + Literal("<") + Literal("vector") + Literal(">")
|
327
|
+
).suppress()
|
328
|
+
+ (
|
329
|
+
_ascii_numeric_list(
|
330
|
+
dtype=float, nested=3, ignore=_COMMENT, empty_ok=True
|
331
|
+
)
|
332
|
+
| _binary_numeric_list(np.float64, nested=3, empty_ok=True)
|
333
|
+
| _binary_numeric_list(np.float32, nested=3, empty_ok=True)
|
334
|
+
)
|
335
|
+
)
|
336
|
+
| (
|
337
|
+
Opt(
|
338
|
+
Literal("List") + Literal("<") + Literal("symmTensor") + Literal(">")
|
339
|
+
).suppress()
|
340
|
+
+ (
|
341
|
+
_ascii_numeric_list(
|
342
|
+
dtype=float, nested=6, ignore=_COMMENT, empty_ok=True
|
343
|
+
)
|
344
|
+
| _binary_numeric_list(np.float64, nested=6, empty_ok=True)
|
345
|
+
| _binary_numeric_list(np.float32, nested=6, empty_ok=True)
|
346
|
+
)
|
347
|
+
)
|
348
|
+
| (
|
349
|
+
Opt(
|
350
|
+
Literal("List") + Literal("<") + Literal("tensor") + Literal(">")
|
351
|
+
).suppress()
|
352
|
+
+ (
|
353
|
+
_ascii_numeric_list(
|
354
|
+
dtype=float, nested=9, ignore=_COMMENT, empty_ok=True
|
355
|
+
)
|
356
|
+
| _binary_numeric_list(np.float64, nested=9, empty_ok=True)
|
357
|
+
| _binary_numeric_list(np.float32, nested=9, empty_ok=True)
|
358
|
+
)
|
359
|
+
)
|
277
360
|
)
|
278
361
|
)
|
362
|
+
|
279
363
|
_DIRECTIVE = Word("#", _IDENTBODYCHARS)
|
280
364
|
_TOKEN = dbl_quoted_string | _DIRECTIVE | _IDENTIFIER
|
281
365
|
_DATA = Forward()
|
@@ -319,7 +403,19 @@ _LOCATED_DICTIONARY = Group(
|
|
319
403
|
located=True,
|
320
404
|
)
|
321
405
|
)[...]
|
322
|
-
_LOCATED_DATA = Group(
|
406
|
+
_LOCATED_DATA = Group(
|
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
|
+
)
|
323
419
|
|
324
420
|
_FILE = (
|
325
421
|
Dict(_LOCATED_DICTIONARY + Opt(_LOCATED_DATA) + _LOCATED_DICTIONARY)
|
@@ -1,7 +1,6 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
3
|
import sys
|
4
|
-
from enum import Enum
|
5
4
|
from typing import Dict, NamedTuple, Optional, Union
|
6
5
|
|
7
6
|
import numpy as np
|
@@ -42,39 +41,6 @@ TensorLike = Union[
|
|
42
41
|
]
|
43
42
|
|
44
43
|
|
45
|
-
class TensorKind(Enum):
|
46
|
-
SCALAR = ()
|
47
|
-
VECTOR = (3,)
|
48
|
-
SYMM_TENSOR = (6,)
|
49
|
-
TENSOR = (9,)
|
50
|
-
|
51
|
-
@property
|
52
|
-
def shape(self) -> tuple[()] | tuple[int]:
|
53
|
-
shape: tuple[()] | tuple[int] = self.value
|
54
|
-
return shape
|
55
|
-
|
56
|
-
@property
|
57
|
-
def size(self) -> int:
|
58
|
-
return int(np.prod(self.shape))
|
59
|
-
|
60
|
-
def __str__(self) -> str:
|
61
|
-
return {
|
62
|
-
TensorKind.SCALAR: "scalar",
|
63
|
-
TensorKind.VECTOR: "vector",
|
64
|
-
TensorKind.SYMM_TENSOR: "symmTensor",
|
65
|
-
TensorKind.TENSOR: "tensor",
|
66
|
-
}[self]
|
67
|
-
|
68
|
-
@staticmethod
|
69
|
-
def from_shape(shape: tuple[int, ...]) -> TensorKind:
|
70
|
-
for kind in TensorKind:
|
71
|
-
if kind.shape == shape:
|
72
|
-
return kind
|
73
|
-
|
74
|
-
msg = f"No tensor kind for shape {shape!r}"
|
75
|
-
raise ValueError(msg)
|
76
|
-
|
77
|
-
|
78
44
|
class Dimensioned:
|
79
45
|
def __init__(
|
80
46
|
self,
|
@@ -3,9 +3,9 @@ import sys
|
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
5
|
if sys.version_info >= (3, 9):
|
6
|
-
from collections.abc import Generator
|
6
|
+
from collections.abc import Generator
|
7
7
|
else:
|
8
|
-
from typing import Generator
|
8
|
+
from typing import Generator
|
9
9
|
|
10
10
|
import numpy as np
|
11
11
|
import pytest
|
@@ -153,16 +153,15 @@ def test_mesh(cavity: FoamCase) -> None:
|
|
153
153
|
|
154
154
|
points = file[None]
|
155
155
|
|
156
|
-
assert isinstance(points,
|
157
|
-
assert
|
158
|
-
assert
|
156
|
+
assert isinstance(points, np.ndarray)
|
157
|
+
assert points.ndim == 2
|
158
|
+
assert points.shape[-1] == 3
|
159
159
|
|
160
160
|
|
161
161
|
def test_internal_field(cavity: FoamCase) -> None:
|
162
162
|
blocks = cavity.block_mesh_dict["blocks"]
|
163
163
|
assert isinstance(blocks, list)
|
164
164
|
sizes = blocks[2]
|
165
|
-
assert isinstance(sizes, list)
|
166
165
|
size = np.prod(sizes)
|
167
166
|
|
168
167
|
p_arr = np.zeros(size)
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# Based on https://foss.heptapod.net/fluiddyn/fluidsimfoam/-/blob/branch/default/tests/test_parser_advanced.py
|
2
2
|
|
3
|
+
import numpy as np
|
3
4
|
import pytest
|
4
5
|
from foamlib._files._parsing import Parsed
|
5
6
|
|
@@ -276,9 +277,10 @@ def test_assignment_strange_name() -> None:
|
|
276
277
|
"""
|
277
278
|
)
|
278
279
|
assert parsed[("equations", '"(U|e|k).*"')] == 0.7
|
279
|
-
assert parsed[("equations", '"(U|e|k|epsilon).*"')]
|
280
|
-
|
281
|
-
|
280
|
+
assert isinstance(parsed[("equations", '"(U|e|k|epsilon).*"')], tuple)
|
281
|
+
assert parsed[("equations", '"(U|e|k|epsilon).*"')][0] == "table"
|
282
|
+
assert np.array_equal(
|
283
|
+
parsed[("equations", '"(U|e|k|epsilon).*"')][1], [[0, 0.4], [0.5, 0.7]]
|
282
284
|
)
|
283
285
|
|
284
286
|
|
@@ -331,17 +333,23 @@ def test_list_u() -> None:
|
|
331
333
|
)
|
332
334
|
"""
|
333
335
|
)
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
[
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
336
|
+
data = parsed[()]
|
337
|
+
assert isinstance(data, np.ndarray)
|
338
|
+
assert data.shape == (9, 3)
|
339
|
+
assert np.array_equal(
|
340
|
+
data,
|
341
|
+
[
|
342
|
+
[4.507730000e00, 1.799630000e00, 0.000000000e00],
|
343
|
+
[6.062080000e00, 2.408310000e00, 0.000000000e00],
|
344
|
+
[6.874000000e00, 2.720790000e00, 0.000000000e00],
|
345
|
+
[7.429290000e00, 2.931000000e00, 0.000000000e00],
|
346
|
+
[7.850950000e00, 3.088050000e00, 0.000000000e00],
|
347
|
+
[8.192020000e00, 3.213060000e00, 0.000000000e00],
|
348
|
+
[1.750000000e01, 1.925590000e-09, 0.000000000e00],
|
349
|
+
[1.750000000e01, 6.810450000e-12, 0.000000000e00],
|
350
|
+
[1.750000000e01, 6.810450000e-12, 0.000000000e00],
|
351
|
+
],
|
352
|
+
)
|
345
353
|
|
346
354
|
|
347
355
|
def test_list_as_write_cell_centers() -> None:
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import numpy as np
|
2
2
|
from foamlib import FoamFile
|
3
3
|
from foamlib._files._parsing import Parsed
|
4
|
+
from foamlib._files._types import is_sequence
|
4
5
|
|
5
6
|
|
6
7
|
def test_parse_value() -> None:
|
@@ -16,7 +17,12 @@ def test_parse_value() -> None:
|
|
16
17
|
assert Parsed(b"uniform 1")[()] == 1
|
17
18
|
assert Parsed(b"uniform 1.0")[()] == 1.0
|
18
19
|
assert Parsed(b"uniform 1.0e-3")[()] == 1.0e-3
|
19
|
-
assert Parsed(b"(
|
20
|
+
assert Parsed(b"(word word)")[()] == ["word", "word"]
|
21
|
+
lst = Parsed(b"(1 2 3)")[()]
|
22
|
+
assert np.array_equal(lst, [1, 2, 3]) # type: ignore[arg-type]
|
23
|
+
lst = Parsed(b"(1.0 2 3)")[()]
|
24
|
+
assert np.array_equal(lst, [1.0, 2.0, 3.0]) # type: ignore[arg-type]
|
25
|
+
assert Parsed(b"()")[()] == []
|
20
26
|
field = Parsed(b"uniform (1 2 3)")[()]
|
21
27
|
assert isinstance(field, np.ndarray)
|
22
28
|
assert np.array_equal(field, [1, 2, 3])
|
@@ -32,15 +38,28 @@ def test_parse_value() -> None:
|
|
32
38
|
field = Parsed(b"nonuniform List<tensor> ()")[()]
|
33
39
|
assert isinstance(field, np.ndarray)
|
34
40
|
assert field.shape == (0, 9)
|
35
|
-
|
36
|
-
assert
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
assert
|
41
|
-
|
42
|
-
[
|
43
|
-
|
41
|
+
lst = Parsed(b"3(1 2 3)")[()]
|
42
|
+
assert isinstance(lst, np.ndarray)
|
43
|
+
assert np.array_equal(lst, [1, 2, 3])
|
44
|
+
lst = Parsed(b"2((1 2 3) (4 5 6))")[()]
|
45
|
+
assert isinstance(lst, np.ndarray)
|
46
|
+
assert np.array_equal(
|
47
|
+
lst,
|
48
|
+
[
|
49
|
+
[1, 2, 3],
|
50
|
+
[4, 5, 6],
|
51
|
+
],
|
52
|
+
)
|
53
|
+
lst = Parsed(b"2{(1 2 3)}")[()]
|
54
|
+
assert isinstance(lst, np.ndarray)
|
55
|
+
assert np.array_equal(
|
56
|
+
lst,
|
57
|
+
[
|
58
|
+
[1, 2, 3],
|
59
|
+
[1, 2, 3],
|
60
|
+
],
|
61
|
+
)
|
62
|
+
assert Parsed(b"0()")[()] == []
|
44
63
|
field = Parsed(b"nonuniform List<vector> 2((1 2 3) (4 5 6))")[()]
|
45
64
|
assert isinstance(field, np.ndarray)
|
46
65
|
assert np.array_equal(
|
@@ -83,19 +102,23 @@ def test_parse_value() -> None:
|
|
83
102
|
assert Parsed(b"[1 1 -2 0 0 0 0] 9.81")[()] == FoamFile.Dimensioned(
|
84
103
|
dimensions=FoamFile.DimensionSet(mass=1, length=1, time=-2), value=9.81
|
85
104
|
)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
)
|
105
|
+
tpl = Parsed(b"hex (0 1 2 3 4 5 6 7) (1 1 1) simpleGrading (1 1 1)")[()]
|
106
|
+
assert isinstance(tpl, tuple)
|
107
|
+
assert len(tpl) == 5
|
108
|
+
assert tpl[0] == "hex"
|
109
|
+
assert is_sequence(tpl[1])
|
110
|
+
assert np.array_equal(tpl[1], [0, 1, 2, 3, 4, 5, 6, 7]) # type: ignore[arg-type]
|
111
|
+
assert is_sequence(tpl[2])
|
112
|
+
assert np.array_equal(tpl[2], [1, 1, 1]) # type: ignore[arg-type]
|
113
|
+
assert tpl[3] == "simpleGrading"
|
114
|
+
assert is_sequence(tpl[4])
|
115
|
+
assert np.array_equal(tpl[4], [1, 1, 1]) # type: ignore[arg-type]
|
93
116
|
assert Parsed(b"(a b; c d;)")[()] == [("a", "b"), ("c", "d")]
|
94
117
|
assert Parsed(b"(a {b c;} d {e g;})")[()] == [
|
95
118
|
("a", {"b": "c"}),
|
96
119
|
("d", {"e": "g"}),
|
97
120
|
]
|
98
|
-
assert Parsed(b"(a (
|
121
|
+
assert Parsed(b"(a (b c d); e {})")[()] == [("a", ["b", "c", "d"]), ("e", {})]
|
99
122
|
assert Parsed(b"({a b; c d;} {e g;})")[()] == [{"a": "b", "c": "d"}, {"e": "g"}]
|
100
123
|
assert Parsed(b"(water oil mercury air)")[()] == ["water", "oil", "mercury", "air"]
|
101
124
|
assert Parsed(b"div(phi,U)")[()] == "div(phi,U)"
|
@@ -3,6 +3,7 @@
|
|
3
3
|
from pathlib import Path
|
4
4
|
from textwrap import dedent
|
5
5
|
|
6
|
+
import numpy as np
|
6
7
|
from foamlib import FoamFile
|
7
8
|
|
8
9
|
|
@@ -43,7 +44,7 @@ def test_simple(tmp_path: Path) -> None:
|
|
43
44
|
|
44
45
|
assert decompose_par_dict["numberOfSubdomains"] == 8
|
45
46
|
assert decompose_par_dict["method"] == "simple"
|
46
|
-
assert decompose_par_dict["coeffs", "n"]
|
47
|
+
assert np.array_equal(decompose_par_dict["coeffs", "n"], [4, 2, 1]) # type: ignore[arg-type]
|
47
48
|
assert decompose_par_dict["coeffs", "order"] == "xyz"
|
48
49
|
assert decompose_par_dict["coeffs", "delta"] == 0.001
|
49
50
|
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# Based on https://foss.heptapod.net/fluiddyn/fluidsimfoam/-/blob/branch/default/tests/test_parser.py
|
2
2
|
|
3
|
+
import numpy as np
|
3
4
|
import pytest
|
4
5
|
from foamlib import FoamFile
|
5
6
|
from foamlib._files._parsing import Parsed
|
@@ -61,20 +62,18 @@ def test_strange_names() -> None:
|
|
61
62
|
|
62
63
|
|
63
64
|
def test_list_simple() -> None:
|
64
|
-
|
65
|
+
faces = Parsed(b"""
|
65
66
|
faces
|
66
67
|
(
|
67
68
|
(1 5 4 0)
|
68
69
|
(2 3 4 5)
|
69
70
|
);
|
70
|
-
""")[("faces",)]
|
71
|
-
|
72
|
-
[2, 3, 4, 5],
|
73
|
-
]
|
71
|
+
""")[("faces",)]
|
72
|
+
assert np.array_equal(faces, [[1, 5, 4, 0], [2, 3, 4, 5]]) # type: ignore[arg-type]
|
74
73
|
|
75
74
|
|
76
75
|
def test_list_assignment() -> None:
|
77
|
-
|
76
|
+
faces = Parsed(b"""
|
78
77
|
faces
|
79
78
|
(
|
80
79
|
1
|
@@ -82,7 +81,8 @@ def test_list_assignment() -> None:
|
|
82
81
|
4
|
83
82
|
0
|
84
83
|
);
|
85
|
-
""")[("faces",)]
|
84
|
+
""")[("faces",)]
|
85
|
+
assert np.array_equal(faces, [1, 5, 4, 0]) # type: ignore[arg-type]
|
86
86
|
|
87
87
|
|
88
88
|
def test_dict_simple() -> None:
|
@@ -135,11 +135,11 @@ def test_dict_with_list() -> None:
|
|
135
135
|
pRefValue 0;
|
136
136
|
}
|
137
137
|
""")
|
138
|
-
assert parsed[("PISO", "pRefPoint")]
|
138
|
+
assert np.array_equal(parsed[("PISO", "pRefPoint")], [0, 0, 0]) # type: ignore[arg-type]
|
139
139
|
|
140
140
|
|
141
141
|
def test_list_with_dict() -> None:
|
142
|
-
|
142
|
+
boundary = Parsed(b"""
|
143
143
|
boundary
|
144
144
|
(
|
145
145
|
upperBoundary
|
@@ -152,33 +152,32 @@ def test_list_with_dict() -> None:
|
|
152
152
|
);
|
153
153
|
}
|
154
154
|
);
|
155
|
-
""")[("boundary",)]
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
},
|
165
|
-
),
|
166
|
-
]
|
155
|
+
""")[("boundary",)]
|
156
|
+
assert isinstance(boundary, list)
|
157
|
+
assert len(boundary) == 1
|
158
|
+
|
159
|
+
upper_boundary = boundary[0]
|
160
|
+
assert upper_boundary[0] == "upperBoundary"
|
161
|
+
assert upper_boundary[1]["type"] == "cyclic"
|
162
|
+
assert upper_boundary[1]["neighbourPatch"] == "lowerBoundary"
|
163
|
+
assert np.array_equal(upper_boundary[1]["faces"], [[3, 7, 6, 2]])
|
167
164
|
|
168
165
|
|
169
166
|
def test_list_with_str() -> None:
|
170
|
-
|
167
|
+
blocks = Parsed(b"""
|
171
168
|
blocks
|
172
169
|
(
|
173
170
|
hex (0 1 2 3 4 5 6 7) (40 40 40) simpleGrading (1 1 1)
|
174
171
|
);
|
175
|
-
""")[("blocks",)]
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
]
|
172
|
+
""")[("blocks",)]
|
173
|
+
assert isinstance(blocks, list)
|
174
|
+
assert len(blocks) == 5
|
175
|
+
|
176
|
+
assert blocks[0] == "hex"
|
177
|
+
assert np.array_equal(blocks[1], [0, 1, 2, 3, 4, 5, 6, 7])
|
178
|
+
assert np.array_equal(blocks[2], [40, 40, 40])
|
179
|
+
assert blocks[3] == "simpleGrading"
|
180
|
+
assert np.array_equal(blocks[4], [1, 1, 1])
|
182
181
|
|
183
182
|
|
184
183
|
def test_file_simple() -> None:
|
@@ -230,10 +229,8 @@ def test_file() -> None:
|
|
230
229
|
""")
|
231
230
|
assert parsed[("a",)] == 1
|
232
231
|
assert parsed[("b",)] == 2
|
233
|
-
|
234
|
-
|
235
|
-
[2, 3, 4, 5],
|
236
|
-
]
|
232
|
+
faces = parsed[("faces",)]
|
233
|
+
assert np.array_equal(faces, [[1, 5, 4, 0], [2, 3, 4, 5]]) # type: ignore[arg-type]
|
237
234
|
assert parsed[("my_dict", "a")] == 1
|
238
235
|
|
239
236
|
|
@@ -455,12 +452,14 @@ def test_for_blockmesh() -> None:
|
|
455
452
|
);
|
456
453
|
""")
|
457
454
|
assert parsed[("negHalfWidth",)] == ("#neg", "$halfWidth")
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
]
|
455
|
+
blocks = parsed[("blocks",)]
|
456
|
+
assert isinstance(blocks, list)
|
457
|
+
assert len(blocks) == 4
|
458
|
+
|
459
|
+
assert blocks[0] == "hex"
|
460
|
+
assert np.array_equal(blocks[1], [4, 6, 14, 12, 0, 2, 10, 8])
|
461
|
+
assert blocks[2] == [1, "$upstreamCells", "$cylinderBoxCells"]
|
462
|
+
assert blocks[3] == "$expandBlock"
|
464
463
|
|
465
464
|
|
466
465
|
def test_for_u() -> None:
|
@@ -483,30 +482,32 @@ def test_blocks() -> None:
|
|
483
482
|
hex (16 17 18 19 20 21 22 23) (96 1 72) simpleGrading (1 1 1)
|
484
483
|
);
|
485
484
|
""")
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
]
|
485
|
+
blocks = parsed[("blocks",)]
|
486
|
+
assert isinstance(blocks, list)
|
487
|
+
assert len(blocks) == 22
|
488
|
+
|
489
|
+
assert blocks[0] == "hex"
|
490
|
+
assert np.array_equal(blocks[1], [0, 1, 2, 3, 4, 5, 6, 7])
|
491
|
+
assert blocks[2] == "inletChannel"
|
492
|
+
assert np.array_equal(blocks[3], [40, 1, 64])
|
493
|
+
assert blocks[4] == "simpleGrading"
|
494
|
+
assert np.array_equal(blocks[5], [1, 1, 1])
|
495
|
+
assert blocks[6] == "hex"
|
496
|
+
assert np.array_equal(blocks[7], [4, 5, 6, 7, 8, 9, 10, 11, 12])
|
497
|
+
assert blocks[8] == "inletChannel"
|
498
|
+
assert np.array_equal(blocks[9], [40, 1, 16])
|
499
|
+
assert blocks[10] == "simpleGrading"
|
500
|
+
assert np.array_equal(blocks[11], [1, 1, 1])
|
501
|
+
assert blocks[12] == "hex"
|
502
|
+
assert np.array_equal(blocks[13], [12, 13, 14, 15, 16, 17, 18, 19])
|
503
|
+
assert np.array_equal(blocks[14], [96, 1, 8])
|
504
|
+
assert blocks[15] == "simpleGrading"
|
505
|
+
assert np.array_equal(blocks[16], [1, 1, 1])
|
506
|
+
assert blocks[17] == "hex"
|
507
|
+
assert np.array_equal(blocks[18], [16, 17, 18, 19, 20, 21, 22, 23])
|
508
|
+
assert np.array_equal(blocks[19], [96, 1, 72])
|
509
|
+
assert blocks[20] == "simpleGrading"
|
510
|
+
assert np.array_equal(blocks[21], [1, 1, 1])
|
510
511
|
|
511
512
|
|
512
513
|
@pytest.mark.xfail(reason="Not currently supported")
|
@@ -586,10 +587,15 @@ def test_list_edges() -> None:
|
|
586
587
|
spline 6 5 ((0.6 0.0124 0.05) (0.7 0.0395 0.05) (0.8 0.0724 0.05) (0.9 0.132 0.05) (1 0.172 0.05) (1.1 0.132 0.05) (1.2 0.0724 0.05) (1.3 0.0395 0.05) (1.4 0.0124 0.05))
|
587
588
|
);
|
588
589
|
""")
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
590
|
+
edges = parsed[("edges",)]
|
591
|
+
assert isinstance(edges, list)
|
592
|
+
assert len(edges) == 8
|
593
|
+
|
594
|
+
assert edges[0] == "spline"
|
595
|
+
assert edges[1] == 1
|
596
|
+
assert edges[2] == 2
|
597
|
+
assert np.array_equal(
|
598
|
+
edges[3],
|
593
599
|
[
|
594
600
|
[0.6, 0.0124, 0.0],
|
595
601
|
[0.7, 0.0395, 0.0],
|
@@ -601,9 +607,12 @@ def test_list_edges() -> None:
|
|
601
607
|
[1.3, 0.0395, 0.0],
|
602
608
|
[1.4, 0.0124, 0.0],
|
603
609
|
],
|
604
|
-
|
605
|
-
|
606
|
-
|
610
|
+
)
|
611
|
+
assert edges[4] == "spline"
|
612
|
+
assert edges[5] == 6
|
613
|
+
assert edges[6] == 5
|
614
|
+
assert np.array_equal(
|
615
|
+
edges[7],
|
607
616
|
[
|
608
617
|
[0.6, 0.0124, 0.05],
|
609
618
|
[0.7, 0.0395, 0.05],
|
@@ -615,7 +624,7 @@ def test_list_edges() -> None:
|
|
615
624
|
[1.3, 0.0395, 0.05],
|
616
625
|
[1.4, 0.0124, 0.05],
|
617
626
|
],
|
618
|
-
|
627
|
+
)
|
619
628
|
|
620
629
|
|
621
630
|
def test_list_edges_arcs() -> None:
|
@@ -626,18 +635,19 @@ def test_list_edges_arcs() -> None:
|
|
626
635
|
arc 5 10 origin (0 0 0)
|
627
636
|
);
|
628
637
|
""")
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
]
|
638
|
+
edges = parsed[("edges",)]
|
639
|
+
assert isinstance(edges, list)
|
640
|
+
assert len(edges) == 10
|
641
|
+
assert edges[0] == "arc"
|
642
|
+
assert edges[1] == 0
|
643
|
+
assert edges[2] == 5
|
644
|
+
assert edges[3] == "origin"
|
645
|
+
assert np.array_equal(edges[4], [0, 0, 0])
|
646
|
+
assert edges[5] == "arc"
|
647
|
+
assert edges[6] == 5
|
648
|
+
assert edges[7] == 10
|
649
|
+
assert edges[8] == "origin"
|
650
|
+
assert np.array_equal(edges[9], [0, 0, 0])
|
641
651
|
|
642
652
|
|
643
653
|
def test_list_blocks() -> None:
|
@@ -649,23 +659,38 @@ def test_list_blocks() -> None:
|
|
649
659
|
hex (2 3 11 10 5 4 12 13) (225 100 1) simpleGrading (1 ((0.1 0.25 41.9) (0.9 0.75 1)) 1)
|
650
660
|
);
|
651
661
|
""")
|
652
|
-
|
653
|
-
|
654
|
-
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
]
|
662
|
+
blocks = parsed[("blocks",)]
|
663
|
+
|
664
|
+
assert isinstance(blocks, list)
|
665
|
+
assert len(blocks) == 15
|
666
|
+
|
667
|
+
assert blocks[0] == "hex"
|
668
|
+
assert np.array_equal(blocks[1], [0, 1, 9, 8, 7, 6, 14, 15])
|
669
|
+
assert np.array_equal(blocks[2], [50, 100, 1])
|
670
|
+
assert blocks[3] == "simpleGrading"
|
671
|
+
assert isinstance(blocks[4], list)
|
672
|
+
assert len(blocks[4]) == 3
|
673
|
+
assert blocks[4][0] == 1
|
674
|
+
assert np.array_equal(blocks[4][1], [[0.1, 0.25, 41.9], [0.9, 0.75, 1]])
|
675
|
+
assert blocks[4][2] == 1
|
676
|
+
assert blocks[5] == "hex"
|
677
|
+
assert np.array_equal(blocks[6], [1, 2, 10, 9, 6, 5, 13, 14])
|
678
|
+
assert np.array_equal(blocks[7], [50, 100, 1])
|
679
|
+
assert blocks[8] == "simpleGrading"
|
680
|
+
assert isinstance(blocks[9], list)
|
681
|
+
assert len(blocks[9]) == 3
|
682
|
+
assert blocks[9][0] == 1
|
683
|
+
assert np.array_equal(blocks[9][1], [[0.1, 0.25, 41.9], [0.9, 0.75, 1]])
|
684
|
+
assert blocks[9][2] == 1
|
685
|
+
assert blocks[10] == "hex"
|
686
|
+
assert np.array_equal(blocks[11], [2, 3, 11, 10, 5, 4, 12, 13])
|
687
|
+
assert np.array_equal(blocks[12], [225, 100, 1])
|
688
|
+
assert blocks[13] == "simpleGrading"
|
689
|
+
assert isinstance(blocks[14], list)
|
690
|
+
assert len(blocks[14]) == 3
|
691
|
+
assert blocks[14][0] == 1
|
692
|
+
assert np.array_equal(blocks[14][1], [[0.1, 0.25, 41.9], [0.9, 0.75, 1]])
|
693
|
+
assert blocks[14][2] == 1
|
669
694
|
|
670
695
|
|
671
696
|
@pytest.mark.xfail(reason="Not currently supported")
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
from pathlib import Path
|
4
4
|
|
5
|
+
import numpy as np
|
5
6
|
from foamlib import FoamFile
|
6
7
|
|
7
8
|
contents = r"""
|
@@ -49,18 +50,18 @@ def test_get_cells_coords(tmp_path: Path) -> None:
|
|
49
50
|
file = FoamFile(path)
|
50
51
|
|
51
52
|
points = file[None]
|
52
|
-
assert isinstance(points,
|
53
|
+
assert isinstance(points, np.ndarray)
|
53
54
|
|
54
|
-
assert points[0]
|
55
|
-
assert points[1]
|
56
|
-
assert points[2]
|
57
|
-
assert points[3]
|
58
|
-
assert points[4]
|
59
|
-
assert points[5]
|
60
|
-
assert points[6]
|
61
|
-
assert points[7]
|
62
|
-
assert points[8]
|
63
|
-
assert points[9]
|
55
|
+
assert np.array_equal(points[0], [0, 0, 0])
|
56
|
+
assert np.array_equal(points[1], [0.15707963268, 0, 0])
|
57
|
+
assert np.array_equal(points[2], [0.314159265359, 0, 0])
|
58
|
+
assert np.array_equal(points[3], [0.471238898038, 0, 0])
|
59
|
+
assert np.array_equal(points[4], [0.628318530718, 0, 0])
|
60
|
+
assert np.array_equal(points[5], [0, 0, 0])
|
61
|
+
assert np.array_equal(points[6], [0.15707963268, 0, 0])
|
62
|
+
assert np.array_equal(points[7], [0.314159265359, 0, 0])
|
63
|
+
assert np.array_equal(points[8], [0.471238898038, 0, 0])
|
64
|
+
assert np.array_equal(points[9], [0.628318530718, 0, 0])
|
64
65
|
|
65
66
|
assert len(points) == 10
|
66
67
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|