foamlib 0.6.13__tar.gz → 0.6.15__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.6.13 → foamlib-0.6.15}/PKG-INFO +5 -6
- {foamlib-0.6.13 → foamlib-0.6.15}/README.md +4 -5
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/__init__.py +1 -1
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/_files.py +6 -2
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/_parsing.py +101 -71
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/_serialization.py +32 -12
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib.egg-info/PKG-INFO +5 -6
- {foamlib-0.6.13 → foamlib-0.6.15}/LICENSE.txt +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/__init__.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_async.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_base.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_run.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_slurm.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_subprocess.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_sync.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_cases/_util.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/__init__.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/_base.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/_io.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/_files/_util.py +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib/py.typed +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib.egg-info/SOURCES.txt +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib.egg-info/dependency_links.txt +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib.egg-info/requires.txt +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/foamlib.egg-info/top_level.txt +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/pyproject.toml +0 -0
- {foamlib-0.6.13 → foamlib-0.6.15}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.15
|
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
|
@@ -169,21 +169,20 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
169
169
|
print(U.internal_field)
|
170
170
|
```
|
171
171
|
|
172
|
-
### 🔁 Run an optimization loop
|
172
|
+
### 🔁 Run an optimization loop on a Slurm-based cluster
|
173
173
|
|
174
174
|
```python
|
175
175
|
import os
|
176
176
|
from pathlib import Path
|
177
|
-
from foamlib import
|
177
|
+
from foamlib import AsyncSlurmFoamCase
|
178
178
|
from scipy.optimize import differential_evolution
|
179
179
|
|
180
|
-
base =
|
181
|
-
# Replace with `AsyncSlurmFoamCase` if on a cluster and you want cases to be run as Slurm jobs
|
180
|
+
base = AsyncSlurmFoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
|
182
181
|
|
183
182
|
async def cost(x):
|
184
183
|
async with base.clone() as clone:
|
185
184
|
clone[0]["U"].boundary_field["inlet"].value = [x[0], 0, 0]
|
186
|
-
await clone.run()
|
185
|
+
await clone.run(fallback=True) # Run locally if Slurm is not available
|
187
186
|
return abs(clone[-1]["U"].internal_field[0][0])
|
188
187
|
|
189
188
|
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
@@ -114,21 +114,20 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
114
114
|
print(U.internal_field)
|
115
115
|
```
|
116
116
|
|
117
|
-
### 🔁 Run an optimization loop
|
117
|
+
### 🔁 Run an optimization loop on a Slurm-based cluster
|
118
118
|
|
119
119
|
```python
|
120
120
|
import os
|
121
121
|
from pathlib import Path
|
122
|
-
from foamlib import
|
122
|
+
from foamlib import AsyncSlurmFoamCase
|
123
123
|
from scipy.optimize import differential_evolution
|
124
124
|
|
125
|
-
base =
|
126
|
-
# Replace with `AsyncSlurmFoamCase` if on a cluster and you want cases to be run as Slurm jobs
|
125
|
+
base = AsyncSlurmFoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
|
127
126
|
|
128
127
|
async def cost(x):
|
129
128
|
async with base.clone() as clone:
|
130
129
|
clone[0]["U"].boundary_field["inlet"].value = [x[0], 0, 0]
|
131
|
-
await clone.run()
|
130
|
+
await clone.run(fallback=True) # Run locally if Slurm is not available
|
132
131
|
return abs(clone[-1]["U"].internal_field[0][0])
|
133
132
|
|
134
133
|
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
@@ -189,6 +189,10 @@ class FoamFile(
|
|
189
189
|
elif not isinstance(keywords, tuple):
|
190
190
|
keywords = (keywords,)
|
191
191
|
|
192
|
+
if keywords and not isinstance(normalize(keywords[-1], kind=Kind.KEYWORD), str):
|
193
|
+
msg = f"Invalid keyword: {keywords[-1]}"
|
194
|
+
raise ValueError(msg)
|
195
|
+
|
192
196
|
with self:
|
193
197
|
try:
|
194
198
|
write_header = (
|
@@ -293,7 +297,7 @@ class FoamFile(
|
|
293
297
|
...,
|
294
298
|
before
|
295
299
|
+ indentation
|
296
|
-
+ dumps(keywords[-1])
|
300
|
+
+ dumps(keywords[-1], kind=Kind.KEYWORD)
|
297
301
|
+ b"\n"
|
298
302
|
+ indentation
|
299
303
|
+ b"{\n"
|
@@ -311,7 +315,7 @@ class FoamFile(
|
|
311
315
|
normalize(data, kind=kind),
|
312
316
|
before
|
313
317
|
+ indentation
|
314
|
-
+ dumps(keywords[-1])
|
318
|
+
+ dumps(keywords[-1], kind=Kind.KEYWORD)
|
315
319
|
+ b" "
|
316
320
|
+ dumps(data, kind=kind)
|
317
321
|
+ b";"
|
@@ -29,7 +29,6 @@ from pyparsing import (
|
|
29
29
|
ParseResults,
|
30
30
|
QuotedString,
|
31
31
|
Word,
|
32
|
-
c_style_comment,
|
33
32
|
common,
|
34
33
|
counted_array,
|
35
34
|
cpp_style_comment,
|
@@ -41,9 +40,7 @@ from ._base import FoamFileBase
|
|
41
40
|
|
42
41
|
|
43
42
|
def _list_of(entry: ParserElement) -> ParserElement:
|
44
|
-
return
|
45
|
-
Literal("List") + Literal("<") + common.identifier + Literal(">")
|
46
|
-
).suppress() + (
|
43
|
+
return (
|
47
44
|
(
|
48
45
|
counted_array(entry, common.integer + Literal("(").suppress())
|
49
46
|
+ Literal(")").suppress()
|
@@ -124,7 +121,13 @@ _SWITCH = (
|
|
124
121
|
_DIMENSIONS = (
|
125
122
|
Literal("[").suppress() + common.number[0, 7] + Literal("]").suppress()
|
126
123
|
).set_parse_action(lambda tks: FoamFileBase.DimensionSet(*tks))
|
127
|
-
_TENSOR =
|
124
|
+
_TENSOR = common.ieee_float | (
|
125
|
+
Literal("(").suppress()
|
126
|
+
+ Group(
|
127
|
+
common.ieee_float[9] | common.ieee_float[6] | common.ieee_float[3], aslist=True
|
128
|
+
)
|
129
|
+
+ Literal(")").suppress()
|
130
|
+
)
|
128
131
|
_IDENTIFIER = Combine(
|
129
132
|
Word(_IDENTCHARS, _IDENTBODYCHARS, exclude_chars="()")
|
130
133
|
+ Opt(Literal("(") + Word(_IDENTBODYCHARS, exclude_chars="()") + Literal(")"))
|
@@ -135,87 +138,116 @@ _DIMENSIONED = (Opt(_IDENTIFIER) + _DIMENSIONS + _TENSOR).set_parse_action(
|
|
135
138
|
_FIELD = (Keyword("uniform", _IDENTBODYCHARS).suppress() + _TENSOR) | (
|
136
139
|
Keyword("nonuniform", _IDENTBODYCHARS).suppress()
|
137
140
|
+ (
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
(
|
144
|
-
|
145
|
-
|
146
|
-
|
141
|
+
Literal("List").suppress()
|
142
|
+
+ Literal("<").suppress()
|
143
|
+
+ (
|
144
|
+
(
|
145
|
+
Literal("scalar").suppress()
|
146
|
+
+ Literal(">").suppress()
|
147
|
+
+ (
|
148
|
+
_list_of(common.ieee_float)
|
149
|
+
| (
|
147
150
|
(
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
+
(
|
152
|
+
counted_array(
|
153
|
+
CharsNotIn(exact=8),
|
154
|
+
common.integer + Literal("(").suppress(),
|
155
|
+
)
|
151
156
|
)
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
+
| (
|
158
|
+
counted_array(
|
159
|
+
CharsNotIn(exact=4),
|
160
|
+
common.integer + Literal("(").suppress(),
|
161
|
+
)
|
157
162
|
)
|
158
163
|
)
|
164
|
+
+ Literal(")").suppress()
|
165
|
+
).set_parse_action(_unpack_binary_field)
|
166
|
+
)
|
167
|
+
)
|
168
|
+
| (
|
169
|
+
Literal("vector").suppress()
|
170
|
+
+ Literal(">").suppress()
|
171
|
+
+ (
|
172
|
+
_list_of(
|
173
|
+
Literal("(").suppress()
|
174
|
+
+ Group(common.ieee_float[3], aslist=True)
|
175
|
+
+ Literal(")").suppress()
|
159
176
|
)
|
160
|
-
|
161
|
-
).set_parse_action(_unpack_binary_field)
|
162
|
-
| (
|
163
|
-
Literal("vector").suppress()
|
164
|
-
+ Literal(">").suppress()
|
165
|
-
+ (
|
177
|
+
| (
|
166
178
|
(
|
167
|
-
|
168
|
-
|
169
|
-
|
179
|
+
(
|
180
|
+
counted_array(
|
181
|
+
CharsNotIn(exact=8 * 3),
|
182
|
+
common.integer + Literal("(").suppress(),
|
183
|
+
)
|
170
184
|
)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
185
|
+
| (
|
186
|
+
counted_array(
|
187
|
+
CharsNotIn(exact=4 * 3),
|
188
|
+
common.integer + Literal("(").suppress(),
|
189
|
+
)
|
176
190
|
)
|
177
191
|
)
|
192
|
+
+ Literal(")").suppress()
|
193
|
+
).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=3))
|
194
|
+
)
|
195
|
+
)
|
196
|
+
| (
|
197
|
+
Literal("vector").suppress()
|
198
|
+
+ Literal(">").suppress()
|
199
|
+
+ (
|
200
|
+
_list_of(
|
201
|
+
Literal("(").suppress()
|
202
|
+
+ Group(common.ieee_float[6], aslist=True)
|
203
|
+
+ Literal(")").suppress()
|
178
204
|
)
|
179
|
-
|
180
|
-
).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=3))
|
181
|
-
| (
|
182
|
-
Literal("symmTensor").suppress()
|
183
|
-
+ Literal(">").suppress()
|
184
|
-
+ (
|
205
|
+
| (
|
185
206
|
(
|
186
|
-
|
187
|
-
|
188
|
-
|
207
|
+
(
|
208
|
+
counted_array(
|
209
|
+
CharsNotIn(exact=8 * 6),
|
210
|
+
common.integer + Literal("(").suppress(),
|
211
|
+
)
|
189
212
|
)
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
213
|
+
| (
|
214
|
+
counted_array(
|
215
|
+
CharsNotIn(exact=4 * 6),
|
216
|
+
common.integer + Literal("(").suppress(),
|
217
|
+
)
|
195
218
|
)
|
196
219
|
)
|
220
|
+
+ Literal(")").suppress()
|
221
|
+
).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=6))
|
222
|
+
)
|
223
|
+
)
|
224
|
+
| (
|
225
|
+
Literal("tensor").suppress()
|
226
|
+
+ Literal(">").suppress()
|
227
|
+
+ (
|
228
|
+
_list_of(
|
229
|
+
Literal("(").suppress()
|
230
|
+
+ Group(common.ieee_float[9], aslist=True)
|
231
|
+
+ Literal(")").suppress()
|
197
232
|
)
|
198
|
-
|
199
|
-
).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=6))
|
200
|
-
| (
|
201
|
-
Literal("tensor").suppress()
|
202
|
-
+ Literal(">").suppress()
|
203
|
-
+ (
|
233
|
+
| (
|
204
234
|
(
|
205
|
-
|
206
|
-
|
207
|
-
|
235
|
+
(
|
236
|
+
counted_array(
|
237
|
+
CharsNotIn(exact=8 * 9),
|
238
|
+
common.integer + Literal("(").suppress(),
|
239
|
+
)
|
208
240
|
)
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
241
|
+
| (
|
242
|
+
counted_array(
|
243
|
+
CharsNotIn(exact=4 * 9),
|
244
|
+
common.integer + Literal("(").suppress(),
|
245
|
+
)
|
214
246
|
)
|
215
247
|
)
|
216
|
-
|
217
|
-
|
218
|
-
)
|
248
|
+
+ Literal(")").suppress()
|
249
|
+
).set_parse_action(lambda tks: _unpack_binary_field(tks, elsize=9))
|
250
|
+
)
|
219
251
|
)
|
220
252
|
)
|
221
253
|
)
|
@@ -229,9 +261,8 @@ _KEYWORD_ENTRY = Dict(Group(_keyword_entry_of(_KEYWORD, _DATA)), asdict=True)
|
|
229
261
|
_DATA_ENTRY = Forward()
|
230
262
|
_LIST_ENTRY = _KEYWORD_ENTRY | _DATA_ENTRY
|
231
263
|
_LIST = _list_of(_LIST_ENTRY)
|
232
|
-
|
233
|
-
|
234
|
-
)
|
264
|
+
_NUMBER = common.signed_integer ^ common.ieee_float
|
265
|
+
_DATA_ENTRY <<= _FIELD | _LIST | _DIMENSIONED | _DIMENSIONS | _NUMBER | _SWITCH | _TOKEN
|
235
266
|
|
236
267
|
_DATA <<= _DATA_ENTRY[1, ...].set_parse_action(
|
237
268
|
lambda tks: tuple(tks) if len(tks) > 1 else [tks[0]]
|
@@ -251,7 +282,6 @@ _FILE = (
|
|
251
282
|
)
|
252
283
|
+ Group(_keyword_entry_of(_KEYWORD, Opt(_DATA, default=""), located=True))[...]
|
253
284
|
)
|
254
|
-
.ignore(c_style_comment)
|
255
285
|
.ignore(cpp_style_comment)
|
256
286
|
.ignore(Literal("#include") + ... + LineEnd()) # type: ignore [no-untyped-call]
|
257
287
|
.parse_with_tabs()
|
@@ -26,6 +26,7 @@ except ModuleNotFoundError:
|
|
26
26
|
|
27
27
|
class Kind(Enum):
|
28
28
|
DEFAULT = auto()
|
29
|
+
KEYWORD = auto()
|
29
30
|
SINGLE_ENTRY = auto()
|
30
31
|
ASCII_FIELD = auto()
|
31
32
|
DOUBLE_PRECISION_BINARY_FIELD = auto()
|
@@ -56,11 +57,6 @@ def normalize(
|
|
56
57
|
assert isinstance(ret, list)
|
57
58
|
return ret
|
58
59
|
|
59
|
-
if kind == Kind.SINGLE_ENTRY and isinstance(data, tuple):
|
60
|
-
ret = normalize(list(data))
|
61
|
-
assert isinstance(ret, list)
|
62
|
-
return ret
|
63
|
-
|
64
60
|
if isinstance(data, Mapping):
|
65
61
|
return {k: normalize(v, kind=kind) for k, v in data.items()}
|
66
62
|
|
@@ -73,22 +69,43 @@ def normalize(
|
|
73
69
|
data = cast(Sequence[float], data)
|
74
70
|
return FoamFileBase.DimensionSet(*data)
|
75
71
|
|
76
|
-
if is_sequence(data) and not isinstance(data, tuple):
|
72
|
+
if is_sequence(data) and (kind == Kind.SINGLE_ENTRY or not isinstance(data, tuple)):
|
77
73
|
return [normalize(d, kind=Kind.SINGLE_ENTRY) for d in data]
|
78
74
|
|
79
75
|
if isinstance(data, str):
|
76
|
+
data = data.strip()
|
77
|
+
|
78
|
+
if data.startswith("(") and data.endswith(")"):
|
79
|
+
data = data[1:-1].split()
|
80
|
+
if kind == Kind.KEYWORD:
|
81
|
+
return "(" + " ".join(data) + ")"
|
82
|
+
return [normalize(d, kind=Kind.SINGLE_ENTRY) for d in data]
|
83
|
+
|
84
|
+
if data.startswith("[") and data.endswith("]"):
|
85
|
+
data = data[1:-1].split()
|
86
|
+
return normalize(data, kind=Kind.DIMENSIONS)
|
87
|
+
|
80
88
|
with contextlib.suppress(ValueError):
|
81
89
|
return int(data)
|
82
90
|
|
83
91
|
with contextlib.suppress(ValueError):
|
84
92
|
return float(data)
|
85
93
|
|
94
|
+
if kind != Kind.KEYWORD:
|
95
|
+
if data in ("yes", "true", "on", "y", "t"):
|
96
|
+
return True
|
97
|
+
if data in ("no", "false", "off", "n", "f"):
|
98
|
+
return False
|
99
|
+
|
86
100
|
tokens: list[str] = re.findall(_TOKENS, data)
|
87
101
|
|
88
102
|
if len(tokens) == 1:
|
89
103
|
return tokens[0]
|
90
104
|
|
91
|
-
|
105
|
+
if kind == Kind.KEYWORD:
|
106
|
+
return " ".join(tokens)
|
107
|
+
|
108
|
+
return tuple(tokens)
|
92
109
|
|
93
110
|
if isinstance(data, FoamFileBase.Dimensioned):
|
94
111
|
value = normalize(data.value, kind=Kind.SINGLE_ENTRY)
|
@@ -115,12 +132,15 @@ def dumps(
|
|
115
132
|
if isinstance(data, Mapping):
|
116
133
|
entries = []
|
117
134
|
for k, v in data.items():
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
135
|
+
value = normalize(v)
|
136
|
+
if isinstance(value, Mapping):
|
137
|
+
entries.append(
|
138
|
+
dumps(k, kind=Kind.KEYWORD) + b" {" + dumps(value) + b"}"
|
139
|
+
)
|
140
|
+
elif not value:
|
141
|
+
entries.append(dumps(k, kind=Kind.KEYWORD) + b";")
|
122
142
|
else:
|
123
|
-
entries.append(dumps(k) + b" " + dumps(
|
143
|
+
entries.append(dumps(k, kind=Kind.KEYWORD) + b" " + dumps(value) + b";")
|
124
144
|
|
125
145
|
return b" ".join(entries)
|
126
146
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.15
|
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
|
@@ -169,21 +169,20 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
169
169
|
print(U.internal_field)
|
170
170
|
```
|
171
171
|
|
172
|
-
### 🔁 Run an optimization loop
|
172
|
+
### 🔁 Run an optimization loop on a Slurm-based cluster
|
173
173
|
|
174
174
|
```python
|
175
175
|
import os
|
176
176
|
from pathlib import Path
|
177
|
-
from foamlib import
|
177
|
+
from foamlib import AsyncSlurmFoamCase
|
178
178
|
from scipy.optimize import differential_evolution
|
179
179
|
|
180
|
-
base =
|
181
|
-
# Replace with `AsyncSlurmFoamCase` if on a cluster and you want cases to be run as Slurm jobs
|
180
|
+
base = AsyncSlurmFoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
|
182
181
|
|
183
182
|
async def cost(x):
|
184
183
|
async with base.clone() as clone:
|
185
184
|
clone[0]["U"].boundary_field["inlet"].value = [x[0], 0, 0]
|
186
|
-
await clone.run()
|
185
|
+
await clone.run(fallback=True) # Run locally if Slurm is not available
|
187
186
|
return abs(clone[-1]["U"].internal_field[0][0])
|
188
187
|
|
189
188
|
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
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
|