foamlib 0.5.0__py3-none-any.whl → 0.5.1__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/_async.py +19 -7
- foamlib/_cases/_sync.py +31 -3
- foamlib/_cases/_util.py +31 -9
- {foamlib-0.5.0.dist-info → foamlib-0.5.1.dist-info}/METADATA +20 -1
- {foamlib-0.5.0.dist-info → foamlib-0.5.1.dist-info}/RECORD +9 -9
- {foamlib-0.5.0.dist-info → foamlib-0.5.1.dist-info}/LICENSE.txt +0 -0
- {foamlib-0.5.0.dist-info → foamlib-0.5.1.dist-info}/WHEEL +0 -0
- {foamlib-0.5.0.dist-info → foamlib-0.5.1.dist-info}/top_level.txt +0 -0
foamlib/__init__.py
CHANGED
foamlib/_cases/_async.py
CHANGED
@@ -5,16 +5,18 @@ import sys
|
|
5
5
|
import tempfile
|
6
6
|
from contextlib import asynccontextmanager
|
7
7
|
from pathlib import Path
|
8
|
-
from typing import
|
9
|
-
Callable,
|
10
|
-
Optional,
|
11
|
-
Union,
|
12
|
-
)
|
8
|
+
from typing import Callable, Optional, TypeVar, Union
|
13
9
|
|
14
10
|
if sys.version_info >= (3, 9):
|
15
|
-
from collections.abc import
|
11
|
+
from collections.abc import (
|
12
|
+
AsyncGenerator,
|
13
|
+
Awaitable,
|
14
|
+
Collection,
|
15
|
+
Iterable,
|
16
|
+
Sequence,
|
17
|
+
)
|
16
18
|
else:
|
17
|
-
from typing import AsyncGenerator, Collection, Sequence
|
19
|
+
from typing import AsyncGenerator, Awaitable, Collection, Iterable, Sequence
|
18
20
|
|
19
21
|
if sys.version_info >= (3, 11):
|
20
22
|
from typing import Self
|
@@ -27,6 +29,9 @@ from ._recipes import _FoamCaseRecipes
|
|
27
29
|
from ._subprocess import run_async
|
28
30
|
from ._util import awaitableasynccontextmanager
|
29
31
|
|
32
|
+
X = TypeVar("X")
|
33
|
+
Y = TypeVar("Y")
|
34
|
+
|
30
35
|
|
31
36
|
class AsyncFoamCase(_FoamCaseRecipes):
|
32
37
|
"""
|
@@ -231,3 +236,10 @@ class AsyncFoamCase(_FoamCaseRecipes):
|
|
231
236
|
await self._rmtree(dst.parent)
|
232
237
|
else:
|
233
238
|
await self._rmtree(dst)
|
239
|
+
|
240
|
+
@staticmethod
|
241
|
+
def map(coro: Callable[[X], Awaitable[Y]], iterable: Iterable[X]) -> Iterable[Y]:
|
242
|
+
"""Run an async function on each element of an iterable concurrently."""
|
243
|
+
return asyncio.get_event_loop().run_until_complete(
|
244
|
+
asyncio.gather(*(coro(arg) for arg in iterable))
|
245
|
+
)
|
foamlib/_cases/_sync.py
CHANGED
@@ -36,6 +36,10 @@ class FoamCase(_FoamCaseRecipes):
|
|
36
36
|
:param path: The path to the case directory.
|
37
37
|
"""
|
38
38
|
|
39
|
+
def __init__(self, path: Union["os.PathLike[str]", str] = Path()):
|
40
|
+
super().__init__(path)
|
41
|
+
self._tmp: Optional[bool] = None
|
42
|
+
|
39
43
|
@staticmethod
|
40
44
|
def _rmtree(
|
41
45
|
path: Union["os.PathLike[str]", str], *, ignore_errors: bool = False
|
@@ -55,6 +59,10 @@ class FoamCase(_FoamCaseRecipes):
|
|
55
59
|
shutil.copytree(src, dest, symlinks=symlinks, ignore=ignore)
|
56
60
|
|
57
61
|
def __enter__(self) -> "FoamCase":
|
62
|
+
if self._tmp is None:
|
63
|
+
raise RuntimeError(
|
64
|
+
"Cannot use a non-copied/cloned case as a context manager"
|
65
|
+
)
|
58
66
|
return self
|
59
67
|
|
60
68
|
def __exit__(
|
@@ -63,7 +71,15 @@ class FoamCase(_FoamCaseRecipes):
|
|
63
71
|
exc_val: Optional[BaseException],
|
64
72
|
exc_tb: Optional[TracebackType],
|
65
73
|
) -> None:
|
66
|
-
self.
|
74
|
+
if self._tmp is not None:
|
75
|
+
if self._tmp:
|
76
|
+
self._rmtree(self.path.parent)
|
77
|
+
else:
|
78
|
+
self._rmtree(self.path)
|
79
|
+
else:
|
80
|
+
raise RuntimeError(
|
81
|
+
"Cannot use a non-copied/cloned case as a context manager"
|
82
|
+
)
|
67
83
|
|
68
84
|
def clean(
|
69
85
|
self,
|
@@ -160,11 +176,17 @@ class FoamCase(_FoamCaseRecipes):
|
|
160
176
|
"""
|
161
177
|
if dst is None:
|
162
178
|
dst = Path(tempfile.mkdtemp(), self.name)
|
179
|
+
tmp = True
|
180
|
+
else:
|
181
|
+
tmp = False
|
163
182
|
|
164
183
|
for name, args, kwargs in self._copy_cmds(dst):
|
165
184
|
getattr(self, name)(*args, **kwargs)
|
166
185
|
|
167
|
-
|
186
|
+
ret = type(self)(dst)
|
187
|
+
ret._tmp = tmp
|
188
|
+
|
189
|
+
return ret
|
168
190
|
|
169
191
|
def clone(self, dst: Optional[Union["os.PathLike[str]", str]] = None) -> "Self":
|
170
192
|
"""
|
@@ -176,8 +198,14 @@ class FoamCase(_FoamCaseRecipes):
|
|
176
198
|
"""
|
177
199
|
if dst is None:
|
178
200
|
dst = Path(tempfile.mkdtemp(), self.name)
|
201
|
+
tmp = True
|
202
|
+
else:
|
203
|
+
tmp = False
|
179
204
|
|
180
205
|
for name, args, kwargs in self._clone_cmds(dst):
|
181
206
|
getattr(self, name)(*args, **kwargs)
|
182
207
|
|
183
|
-
|
208
|
+
ret = type(self)(dst)
|
209
|
+
ret._tmp = tmp
|
210
|
+
|
211
|
+
return ret
|
foamlib/_cases/_util.py
CHANGED
@@ -1,15 +1,33 @@
|
|
1
|
+
import functools
|
2
|
+
import sys
|
1
3
|
from types import TracebackType
|
2
|
-
from typing import
|
4
|
+
from typing import (
|
5
|
+
Any,
|
6
|
+
AsyncContextManager,
|
7
|
+
Callable,
|
8
|
+
Generic,
|
9
|
+
Optional,
|
10
|
+
Type,
|
11
|
+
TypeVar,
|
12
|
+
)
|
3
13
|
|
14
|
+
if sys.version_info >= (3, 9):
|
15
|
+
from collections.abc import Generator
|
16
|
+
else:
|
17
|
+
from typing import Generator
|
4
18
|
|
5
|
-
|
6
|
-
|
19
|
+
|
20
|
+
R = TypeVar("R")
|
21
|
+
|
22
|
+
|
23
|
+
class _AwaitableAsyncContextManager(Generic[R]):
|
24
|
+
def __init__(self, cm: "AsyncContextManager[R]"):
|
7
25
|
self._cm = cm
|
8
26
|
|
9
|
-
def __await__(self) -> Any:
|
27
|
+
def __await__(self) -> Generator[Any, Any, R]:
|
10
28
|
return self._cm.__aenter__().__await__()
|
11
29
|
|
12
|
-
async def __aenter__(self) ->
|
30
|
+
async def __aenter__(self) -> R:
|
13
31
|
return await self._cm.__aenter__()
|
14
32
|
|
15
33
|
async def __aexit__(
|
@@ -17,11 +35,15 @@ class _AwaitableAsyncContextManager:
|
|
17
35
|
exc_type: Optional[Type[BaseException]],
|
18
36
|
exc_val: Optional[BaseException],
|
19
37
|
exc_tb: Optional[TracebackType],
|
20
|
-
) ->
|
38
|
+
) -> Optional[bool]:
|
21
39
|
return await self._cm.__aexit__(exc_type, exc_val, exc_tb)
|
22
40
|
|
23
41
|
|
24
42
|
def awaitableasynccontextmanager(
|
25
|
-
cm: Callable[..., "AsyncContextManager[
|
26
|
-
) -> Callable[..., _AwaitableAsyncContextManager]:
|
27
|
-
|
43
|
+
cm: Callable[..., "AsyncContextManager[R]"],
|
44
|
+
) -> Callable[..., _AwaitableAsyncContextManager[R]]:
|
45
|
+
@functools.wraps(cm)
|
46
|
+
def f(*args: Any, **kwargs: Any) -> _AwaitableAsyncContextManager[R]:
|
47
|
+
return _AwaitableAsyncContextManager(cm(*args, **kwargs))
|
48
|
+
|
49
|
+
return f
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.1
|
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
|
@@ -155,6 +155,25 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
155
155
|
print(U.internal_field)
|
156
156
|
```
|
157
157
|
|
158
|
+
### Run an optimization loop in parallel
|
159
|
+
|
160
|
+
```python
|
161
|
+
import os
|
162
|
+
from pathlib import Path
|
163
|
+
from foamlib import AsyncFoamCase
|
164
|
+
from scipy.optimize import differential_evolution
|
165
|
+
|
166
|
+
base = AsyncFoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/simpleFoam/pitzDaily")
|
167
|
+
|
168
|
+
async def cost(x):
|
169
|
+
async with base.clone() as clone:
|
170
|
+
clone[0]["U"].boundary_field["inlet"].value = [x[0], 0, 0]
|
171
|
+
await clone.run()
|
172
|
+
return abs(clone[-1]["U"].internal_field[0][0])
|
173
|
+
|
174
|
+
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
175
|
+
```
|
176
|
+
|
158
177
|
## Documentation
|
159
178
|
|
160
179
|
For more information, check out the [documentation](https://foamlib.readthedocs.io/).
|
@@ -1,12 +1,12 @@
|
|
1
|
-
foamlib/__init__.py,sha256=
|
1
|
+
foamlib/__init__.py,sha256=bRzkPtbKy1RniCL9eYinI6Yc8g8utDoXrPV6hFimMZY,392
|
2
2
|
foamlib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
foamlib/_cases/__init__.py,sha256=C0mpRu7c-X-4uVMKmVrZhwIyhBNyvUoCv0o-BQ72RC0,236
|
4
|
-
foamlib/_cases/_async.py,sha256=
|
4
|
+
foamlib/_cases/_async.py,sha256=um1nrAjGcT8Vp1hz8XvC_87xVBjfeU3MrpnuzAHN5GY,8251
|
5
5
|
foamlib/_cases/_base.py,sha256=1CUkkK4afBxDgP79dmho97WJdj-GLgYhnrCSf_52Eao,6604
|
6
6
|
foamlib/_cases/_recipes.py,sha256=UTFnVuTvEf-9wn-Fr30a9wOOmyOxvWeDhbqBhdtbhzA,9692
|
7
7
|
foamlib/_cases/_subprocess.py,sha256=CfUy_LrqLnMLR9FHINqInCd3soN6eYvonwZ30epiLu8,2234
|
8
|
-
foamlib/_cases/_sync.py,sha256=
|
9
|
-
foamlib/_cases/_util.py,sha256=
|
8
|
+
foamlib/_cases/_sync.py,sha256=R32Ea4BTOPq-x9OIndObcYZACF8e0RnzB4TywNvDxbA,6733
|
9
|
+
foamlib/_cases/_util.py,sha256=BpPW_91bFLzV3b4r50u-2pGMR3tfQQfY2xqToOHCUBk,1204
|
10
10
|
foamlib/_files/__init__.py,sha256=-UqB9YTH6mrJfXCX00kPTAAY20XG64u1MGPw_1ewLVs,148
|
11
11
|
foamlib/_files/_base.py,sha256=zaFDjLE6jB7WtGWk8hfKusjLtlGu6CZV16AHJpRUibs,1929
|
12
12
|
foamlib/_files/_files.py,sha256=6Fdrc0lksFK99i1a6wEsBi-BtYgSQnUc5s10h2LQ9ew,16091
|
@@ -14,8 +14,8 @@ foamlib/_files/_io.py,sha256=f_tYI7AqaFsQ8mtK__fEoIUqpYb3YmrI8X5D8updmNM,2084
|
|
14
14
|
foamlib/_files/_parsing.py,sha256=8V2CKZ45mKE3f9fP8lAfexIdhPGrq7elIZkpBkkGB6Q,8773
|
15
15
|
foamlib/_files/_serialization.py,sha256=pb8_cIVgRhGS_ZV2p3x8p5_lK1SS6xzQHscAYYuOgFY,3407
|
16
16
|
foamlib/_files/_util.py,sha256=UMzXmTFgvbp46w6k3oEZJoYC98pFgEK6LN5uLOwrlCg,397
|
17
|
-
foamlib-0.5.
|
18
|
-
foamlib-0.5.
|
19
|
-
foamlib-0.5.
|
20
|
-
foamlib-0.5.
|
21
|
-
foamlib-0.5.
|
17
|
+
foamlib-0.5.1.dist-info/LICENSE.txt,sha256=5Dte9TUnLZzPRs4NQzl-Jc2-Ljd-t_v0ZR5Ng5r0UsY,35131
|
18
|
+
foamlib-0.5.1.dist-info/METADATA,sha256=4Fq_okfGu-zY0IGrcUCD5IuuJxAESwNtr0EgXD0NzF8,6338
|
19
|
+
foamlib-0.5.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
20
|
+
foamlib-0.5.1.dist-info/top_level.txt,sha256=ZdVYtetXGwPwyfL-WhlhbTFQGAwKX5P_gXxtH9JYFPI,8
|
21
|
+
foamlib-0.5.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|