foamlib 0.6.7__tar.gz → 0.6.9__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.7 → foamlib-0.6.9}/PKG-INFO +20 -16
- {foamlib-0.6.7 → foamlib-0.6.9}/README.md +19 -15
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/__init__.py +1 -1
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_async.py +9 -4
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_base.py +8 -7
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_run.py +31 -9
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_slurm.py +4 -2
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_subprocess.py +5 -3
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_sync.py +9 -6
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/_base.py +4 -6
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/_files.py +13 -12
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/_io.py +5 -3
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/_serialization.py +31 -33
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib.egg-info/PKG-INFO +20 -16
- {foamlib-0.6.7 → foamlib-0.6.9}/pyproject.toml +30 -1
- {foamlib-0.6.7 → foamlib-0.6.9}/LICENSE.txt +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/__init__.py +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_cases/_util.py +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/__init__.py +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/_parsing.py +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/_files/_util.py +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib/py.typed +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib.egg-info/SOURCES.txt +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib.egg-info/dependency_links.txt +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib.egg-info/requires.txt +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/foamlib.egg-info/top_level.txt +0 -0
- {foamlib-0.6.7 → foamlib-0.6.9}/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.9
|
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
|
@@ -53,7 +53,7 @@ Requires-Dist: foamlib[test]; extra == "dev"
|
|
53
53
|
Requires-Dist: foamlib[typing]; extra == "dev"
|
54
54
|
Requires-Dist: foamlib[docs]; extra == "dev"
|
55
55
|
|
56
|
-
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="
|
56
|
+
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="65">](https://github.com/gerlero/foamlib)
|
57
57
|
|
58
58
|
[](https://foamlib.readthedocs.io/)
|
59
59
|
[](https://github.com/gerlero/foamlib/actions/workflows/ci.yml)
|
@@ -61,24 +61,28 @@ Requires-Dist: foamlib[docs]; extra == "dev"
|
|
61
61
|
[](http://mypy-lang.org/)
|
62
62
|
[](https://github.com/astral-sh/ruff)
|
63
63
|
[](https://github.com/astral-sh/uv)
|
64
|
+
[](https://github.com/gerlero/foamlib/actions/workflows/pypi-publish.yml)
|
64
65
|
[](https://pypi.org/project/foamlib/)
|
65
66
|
[](https://anaconda.org/conda-forge/foamlib)
|
66
67
|
[](https://pypi.org/project/foamlib/)
|
67
68
|

|
69
|
+
[](https://github.com/gerlero/foamlib/actions/workflows/docker.yml)
|
68
70
|
[](https://hub.docker.com/r/microfluidica/foamlib/)
|
69
71
|
|
72
|
+
## 👋 Basics
|
73
|
+
|
70
74
|
**foamlib** provides a simple, modern and ergonomic Python interface for interacting with [OpenFOAM](https://www.openfoam.com).
|
71
75
|
|
72
|
-
It offers the following classes:
|
76
|
+
It offers the following Python classes:
|
73
77
|
|
74
78
|
* [`FoamFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFile) (and [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFieldFile)): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s, using `foamlib`'s own parser. Supports ASCII and binary field formats (with or without compression).
|
75
79
|
* [`FoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.FoamCase): a class for configuring, running, and accessing the results of OpenFOAM cases.
|
76
80
|
* [`AsyncFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncFoamCase): variant of `FoamCase` with asynchronous methods for running multiple cases at once.
|
77
81
|
* [`AsyncSlurmFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncSlurmFoamCase): subclass of `AsyncFoamCase` used for running cases on a Slurm cluster.
|
78
82
|
|
79
|
-
## Get started
|
83
|
+
## ☑️ Get started
|
80
84
|
|
81
|
-
### Install
|
85
|
+
### 📦 Install
|
82
86
|
|
83
87
|
* With [pip](https://pypi.org/project/pip/):
|
84
88
|
|
@@ -92,7 +96,7 @@ It offers the following classes:
|
|
92
96
|
conda install -c conda-forge foamlib
|
93
97
|
```
|
94
98
|
|
95
|
-
### Clone a case
|
99
|
+
### 🐑 Clone a case
|
96
100
|
|
97
101
|
```python
|
98
102
|
import os
|
@@ -104,13 +108,13 @@ pitz_tutorial = FoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/si
|
|
104
108
|
my_pitz = pitz_tutorial.clone("myPitz")
|
105
109
|
```
|
106
110
|
|
107
|
-
### Run the case
|
111
|
+
### 🏃 Run the case
|
108
112
|
|
109
113
|
```python
|
110
114
|
my_pitz.run()
|
111
115
|
```
|
112
116
|
|
113
|
-
### Access the results
|
117
|
+
### 🔎 Access the results
|
114
118
|
|
115
119
|
```python
|
116
120
|
latest_time = my_pitz[-1]
|
@@ -122,19 +126,19 @@ print(p.internal_field)
|
|
122
126
|
print(U.internal_field)
|
123
127
|
```
|
124
128
|
|
125
|
-
### Clean the case
|
129
|
+
### 🧹 Clean the case
|
126
130
|
|
127
131
|
```python
|
128
132
|
my_pitz.clean()
|
129
133
|
```
|
130
134
|
|
131
|
-
### Edit the `controlDict` file
|
135
|
+
### ⚙️ Edit the `controlDict` file
|
132
136
|
|
133
137
|
```python
|
134
138
|
my_pitz.control_dict["writeInterval"] = 10
|
135
139
|
```
|
136
140
|
|
137
|
-
### Make multiple file reads and writes in a single go
|
141
|
+
### 📝 Make multiple file reads and writes in a single go
|
138
142
|
|
139
143
|
```python
|
140
144
|
with my_pitz.fv_schemes as f:
|
@@ -142,7 +146,7 @@ with my_pitz.fv_schemes as f:
|
|
142
146
|
f["snGradSchemes"]["default"] = "uncorrected"
|
143
147
|
```
|
144
148
|
|
145
|
-
### Run a case asynchronously
|
149
|
+
### ⏳ Run a case asynchronously
|
146
150
|
|
147
151
|
```python
|
148
152
|
import asyncio
|
@@ -155,7 +159,7 @@ async def run_case():
|
|
155
159
|
asyncio.run(run_case())
|
156
160
|
```
|
157
161
|
|
158
|
-
### Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
162
|
+
### 🔢 Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
159
163
|
|
160
164
|
```python
|
161
165
|
from foamlib import FoamFieldFile
|
@@ -165,7 +169,7 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
165
169
|
print(U.internal_field)
|
166
170
|
```
|
167
171
|
|
168
|
-
### Run an optimization loop in parallel
|
172
|
+
### 🔁 Run an optimization loop in parallel
|
169
173
|
|
170
174
|
```python
|
171
175
|
import os
|
@@ -185,7 +189,7 @@ async def cost(x):
|
|
185
189
|
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
186
190
|
```
|
187
191
|
|
188
|
-
### Use it to create a `run` (or `clean`) script
|
192
|
+
### 📄 Use it to create a `run` (or `clean`) script
|
189
193
|
|
190
194
|
```python
|
191
195
|
#!/usr/bin/env python3
|
@@ -197,6 +201,6 @@ case = FoamCase(Path(__file__).parent)
|
|
197
201
|
case.run()
|
198
202
|
```
|
199
203
|
|
200
|
-
## Documentation
|
204
|
+
## 📘 Documentation
|
201
205
|
|
202
206
|
For more information, check out the [documentation](https://foamlib.readthedocs.io/).
|
@@ -1,4 +1,4 @@
|
|
1
|
-
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="
|
1
|
+
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="65">](https://github.com/gerlero/foamlib)
|
2
2
|
|
3
3
|
[](https://foamlib.readthedocs.io/)
|
4
4
|
[](https://github.com/gerlero/foamlib/actions/workflows/ci.yml)
|
@@ -6,24 +6,28 @@
|
|
6
6
|
[](http://mypy-lang.org/)
|
7
7
|
[](https://github.com/astral-sh/ruff)
|
8
8
|
[](https://github.com/astral-sh/uv)
|
9
|
+
[](https://github.com/gerlero/foamlib/actions/workflows/pypi-publish.yml)
|
9
10
|
[](https://pypi.org/project/foamlib/)
|
10
11
|
[](https://anaconda.org/conda-forge/foamlib)
|
11
12
|
[](https://pypi.org/project/foamlib/)
|
12
13
|

|
14
|
+
[](https://github.com/gerlero/foamlib/actions/workflows/docker.yml)
|
13
15
|
[](https://hub.docker.com/r/microfluidica/foamlib/)
|
14
16
|
|
17
|
+
## 👋 Basics
|
18
|
+
|
15
19
|
**foamlib** provides a simple, modern and ergonomic Python interface for interacting with [OpenFOAM](https://www.openfoam.com).
|
16
20
|
|
17
|
-
It offers the following classes:
|
21
|
+
It offers the following Python classes:
|
18
22
|
|
19
23
|
* [`FoamFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFile) (and [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFieldFile)): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s, using `foamlib`'s own parser. Supports ASCII and binary field formats (with or without compression).
|
20
24
|
* [`FoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.FoamCase): a class for configuring, running, and accessing the results of OpenFOAM cases.
|
21
25
|
* [`AsyncFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncFoamCase): variant of `FoamCase` with asynchronous methods for running multiple cases at once.
|
22
26
|
* [`AsyncSlurmFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncSlurmFoamCase): subclass of `AsyncFoamCase` used for running cases on a Slurm cluster.
|
23
27
|
|
24
|
-
## Get started
|
28
|
+
## ☑️ Get started
|
25
29
|
|
26
|
-
### Install
|
30
|
+
### 📦 Install
|
27
31
|
|
28
32
|
* With [pip](https://pypi.org/project/pip/):
|
29
33
|
|
@@ -37,7 +41,7 @@ It offers the following classes:
|
|
37
41
|
conda install -c conda-forge foamlib
|
38
42
|
```
|
39
43
|
|
40
|
-
### Clone a case
|
44
|
+
### 🐑 Clone a case
|
41
45
|
|
42
46
|
```python
|
43
47
|
import os
|
@@ -49,13 +53,13 @@ pitz_tutorial = FoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/si
|
|
49
53
|
my_pitz = pitz_tutorial.clone("myPitz")
|
50
54
|
```
|
51
55
|
|
52
|
-
### Run the case
|
56
|
+
### 🏃 Run the case
|
53
57
|
|
54
58
|
```python
|
55
59
|
my_pitz.run()
|
56
60
|
```
|
57
61
|
|
58
|
-
### Access the results
|
62
|
+
### 🔎 Access the results
|
59
63
|
|
60
64
|
```python
|
61
65
|
latest_time = my_pitz[-1]
|
@@ -67,19 +71,19 @@ print(p.internal_field)
|
|
67
71
|
print(U.internal_field)
|
68
72
|
```
|
69
73
|
|
70
|
-
### Clean the case
|
74
|
+
### 🧹 Clean the case
|
71
75
|
|
72
76
|
```python
|
73
77
|
my_pitz.clean()
|
74
78
|
```
|
75
79
|
|
76
|
-
### Edit the `controlDict` file
|
80
|
+
### ⚙️ Edit the `controlDict` file
|
77
81
|
|
78
82
|
```python
|
79
83
|
my_pitz.control_dict["writeInterval"] = 10
|
80
84
|
```
|
81
85
|
|
82
|
-
### Make multiple file reads and writes in a single go
|
86
|
+
### 📝 Make multiple file reads and writes in a single go
|
83
87
|
|
84
88
|
```python
|
85
89
|
with my_pitz.fv_schemes as f:
|
@@ -87,7 +91,7 @@ with my_pitz.fv_schemes as f:
|
|
87
91
|
f["snGradSchemes"]["default"] = "uncorrected"
|
88
92
|
```
|
89
93
|
|
90
|
-
### Run a case asynchronously
|
94
|
+
### ⏳ Run a case asynchronously
|
91
95
|
|
92
96
|
```python
|
93
97
|
import asyncio
|
@@ -100,7 +104,7 @@ async def run_case():
|
|
100
104
|
asyncio.run(run_case())
|
101
105
|
```
|
102
106
|
|
103
|
-
### Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
107
|
+
### 🔢 Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
104
108
|
|
105
109
|
```python
|
106
110
|
from foamlib import FoamFieldFile
|
@@ -110,7 +114,7 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
110
114
|
print(U.internal_field)
|
111
115
|
```
|
112
116
|
|
113
|
-
### Run an optimization loop in parallel
|
117
|
+
### 🔁 Run an optimization loop in parallel
|
114
118
|
|
115
119
|
```python
|
116
120
|
import os
|
@@ -130,7 +134,7 @@ async def cost(x):
|
|
130
134
|
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
131
135
|
```
|
132
136
|
|
133
|
-
### Use it to create a `run` (or `clean`) script
|
137
|
+
### 📄 Use it to create a `run` (or `clean`) script
|
134
138
|
|
135
139
|
```python
|
136
140
|
#!/usr/bin/env python3
|
@@ -142,6 +146,6 @@ case = FoamCase(Path(__file__).parent)
|
|
142
146
|
case.run()
|
143
147
|
```
|
144
148
|
|
145
|
-
## Documentation
|
149
|
+
## 📘 Documentation
|
146
150
|
|
147
151
|
For more information, check out the [documentation](https://foamlib.readthedocs.io/).
|
@@ -1,9 +1,8 @@
|
|
1
1
|
import asyncio
|
2
2
|
import multiprocessing
|
3
|
-
import os
|
4
3
|
import sys
|
5
4
|
from contextlib import asynccontextmanager
|
6
|
-
from typing import Any, Callable, Optional, TypeVar, Union, overload
|
5
|
+
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union, overload
|
7
6
|
|
8
7
|
if sys.version_info >= (3, 9):
|
9
8
|
from collections.abc import (
|
@@ -29,6 +28,9 @@ from ._run import FoamCaseRunBase
|
|
29
28
|
from ._subprocess import run_async
|
30
29
|
from ._util import ValuedGenerator, awaitableasynccontextmanager
|
31
30
|
|
31
|
+
if TYPE_CHECKING:
|
32
|
+
import os
|
33
|
+
|
32
34
|
X = TypeVar("X")
|
33
35
|
Y = TypeVar("Y")
|
34
36
|
|
@@ -138,8 +140,11 @@ class AsyncFoamCase(FoamCaseRunBase):
|
|
138
140
|
ret = super().__getitem__(index)
|
139
141
|
if isinstance(ret, FoamCaseBase.TimeDirectory):
|
140
142
|
return AsyncFoamCase.TimeDirectory(ret)
|
141
|
-
|
142
|
-
|
143
|
+
return [AsyncFoamCase.TimeDirectory(r) for r in ret]
|
144
|
+
|
145
|
+
async def _prepare(self, *, check: bool = True, log: bool = True) -> None:
|
146
|
+
for coro in self._prepare_calls(check=check, log=log):
|
147
|
+
await coro
|
143
148
|
|
144
149
|
async def run(
|
145
150
|
self,
|
@@ -1,8 +1,8 @@
|
|
1
|
-
import os
|
2
1
|
import shutil
|
3
2
|
import sys
|
4
3
|
from pathlib import Path
|
5
4
|
from typing import (
|
5
|
+
TYPE_CHECKING,
|
6
6
|
Optional,
|
7
7
|
Union,
|
8
8
|
overload,
|
@@ -23,6 +23,9 @@ else:
|
|
23
23
|
|
24
24
|
from .._files import FoamFieldFile, FoamFile
|
25
25
|
|
26
|
+
if TYPE_CHECKING:
|
27
|
+
import os
|
28
|
+
|
26
29
|
|
27
30
|
class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
28
31
|
def __init__(self, path: Union["os.PathLike[str]", str] = Path()):
|
@@ -57,18 +60,16 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
57
60
|
def __getitem__(self, key: str) -> FoamFieldFile:
|
58
61
|
if (self.path / f"{key}.gz").is_file() and not (self.path / key).is_file():
|
59
62
|
return FoamFieldFile(self.path / f"{key}.gz")
|
60
|
-
|
61
|
-
return FoamFieldFile(self.path / key)
|
63
|
+
return FoamFieldFile(self.path / key)
|
62
64
|
|
63
65
|
def __contains__(self, obj: object) -> bool:
|
64
66
|
if isinstance(obj, FoamFieldFile):
|
65
67
|
return obj.path.parent == self.path and obj.path.is_file()
|
66
|
-
|
68
|
+
if isinstance(obj, str):
|
67
69
|
return (self.path / obj).is_file() or (
|
68
70
|
self.path / f"{obj}.gz"
|
69
71
|
).is_file()
|
70
|
-
|
71
|
-
return False
|
72
|
+
return False
|
72
73
|
|
73
74
|
def __iter__(self) -> Iterator[FoamFieldFile]:
|
74
75
|
for p in self.path.iterdir():
|
@@ -124,7 +125,7 @@ class FoamCaseBase(Sequence["FoamCaseBase.TimeDirectory"]):
|
|
124
125
|
) -> Union["FoamCaseBase.TimeDirectory", Sequence["FoamCaseBase.TimeDirectory"]]:
|
125
126
|
if isinstance(index, str):
|
126
127
|
return FoamCaseBase.TimeDirectory(self.path / index)
|
127
|
-
|
128
|
+
if isinstance(index, float):
|
128
129
|
for time in self._times:
|
129
130
|
if time.time == index:
|
130
131
|
return time
|
@@ -115,6 +115,12 @@ class FoamCaseRunBase(FoamCaseBase):
|
|
115
115
|
def clone(self, dst: Optional[Union["os.PathLike[str]", str]] = None) -> Any:
|
116
116
|
raise NotImplementedError
|
117
117
|
|
118
|
+
@abstractmethod
|
119
|
+
def _prepare(
|
120
|
+
self, *, check: bool = True, log: bool = True
|
121
|
+
) -> Union[None, Coroutine[None, None, None]]:
|
122
|
+
raise NotImplementedError
|
123
|
+
|
118
124
|
@abstractmethod
|
119
125
|
def run(
|
120
126
|
self,
|
@@ -208,6 +214,18 @@ class FoamCaseRunBase(FoamCaseBase):
|
|
208
214
|
|
209
215
|
return script
|
210
216
|
|
217
|
+
def __prepare_script(self) -> Optional[Path]:
|
218
|
+
"""Return the path to the Allrun.pre script, or None if no prepare script is found."""
|
219
|
+
script = self.path / "Allrun.pre"
|
220
|
+
|
221
|
+
if not script.is_file():
|
222
|
+
return None
|
223
|
+
|
224
|
+
if sys.argv and Path(sys.argv[0]).absolute() == script.absolute():
|
225
|
+
return None
|
226
|
+
|
227
|
+
return script
|
228
|
+
|
211
229
|
def __run_script(self, *, parallel: Optional[bool]) -> Optional[Path]:
|
212
230
|
"""Return the path to the (All)run script, or None if no run script is found."""
|
213
231
|
run = self.path / "run"
|
@@ -256,8 +274,7 @@ class FoamCaseRunBase(FoamCaseBase):
|
|
256
274
|
env["DYLD_LIBRARY_PATH"] = env["FOAM_LD_LIBRARY_PATH"]
|
257
275
|
|
258
276
|
return env
|
259
|
-
|
260
|
-
return None
|
277
|
+
return None
|
261
278
|
|
262
279
|
@contextmanager
|
263
280
|
def __output(
|
@@ -267,10 +284,7 @@ class FoamCaseRunBase(FoamCaseBase):
|
|
267
284
|
if isinstance(cmd, str):
|
268
285
|
name = shlex.split(cmd)[0]
|
269
286
|
else:
|
270
|
-
if isinstance(cmd[0], os.PathLike)
|
271
|
-
name = Path(cmd[0]).name
|
272
|
-
else:
|
273
|
-
name = cmd[0]
|
287
|
+
name = Path(cmd[0]).name if isinstance(cmd[0], os.PathLike) else cmd[0]
|
274
288
|
|
275
289
|
with (self.path / f"log.{name}").open("ab") as stdout:
|
276
290
|
yield stdout, STDOUT
|
@@ -341,6 +355,15 @@ class FoamCaseRunBase(FoamCaseBase):
|
|
341
355
|
) -> Generator[Any, None, None]:
|
342
356
|
yield self.run(["reconstructPar"], cpus=0, check=check, log=log)
|
343
357
|
|
358
|
+
def _prepare_calls(self, *, check: bool, log: bool) -> Generator[Any, None, None]:
|
359
|
+
script_path = self.__prepare_script()
|
360
|
+
|
361
|
+
if script_path is not None:
|
362
|
+
yield self.run([script_path], log=log, check=check)
|
363
|
+
|
364
|
+
elif (self.path / "system" / "blockMeshDict").is_file():
|
365
|
+
yield self.block_mesh(check=check, log=log)
|
366
|
+
|
344
367
|
def _run_calls(
|
345
368
|
self,
|
346
369
|
cmd: Optional[Union[Sequence[Union[str, "os.PathLike[str]"]], str]] = None,
|
@@ -406,12 +429,11 @@ class FoamCaseRunBase(FoamCaseBase):
|
|
406
429
|
)
|
407
430
|
|
408
431
|
else:
|
432
|
+
yield self._prepare(check=check, log=log)
|
433
|
+
|
409
434
|
if not self and (self.path / "0.orig").is_dir():
|
410
435
|
yield self.restore_0_dir()
|
411
436
|
|
412
|
-
if (self.path / "system" / "blockMeshDict").is_file():
|
413
|
-
yield self.block_mesh(check=check)
|
414
|
-
|
415
437
|
if parallel is None:
|
416
438
|
parallel = (
|
417
439
|
(cpus is not None and cpus > 1)
|
@@ -1,7 +1,6 @@
|
|
1
|
-
import os
|
2
1
|
import shutil
|
3
2
|
import sys
|
4
|
-
from typing import Any, Optional, Union
|
3
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
5
4
|
|
6
5
|
if sys.version_info >= (3, 9):
|
7
6
|
from collections.abc import Sequence
|
@@ -11,6 +10,9 @@ else:
|
|
11
10
|
from ._async import AsyncFoamCase
|
12
11
|
from ._subprocess import run_async
|
13
12
|
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
import os
|
15
|
+
|
14
16
|
|
15
17
|
class AsyncSlurmFoamCase(AsyncFoamCase):
|
16
18
|
"""An asynchronous OpenFOAM case that launches jobs on a Slurm cluster."""
|
@@ -1,9 +1,11 @@
|
|
1
1
|
import asyncio
|
2
|
-
import os
|
3
2
|
import subprocess
|
4
3
|
import sys
|
5
4
|
from io import BytesIO
|
6
|
-
from typing import IO, Optional, Union
|
5
|
+
from typing import IO, TYPE_CHECKING, Optional, Union
|
6
|
+
|
7
|
+
if TYPE_CHECKING:
|
8
|
+
import os
|
7
9
|
|
8
10
|
if sys.version_info >= (3, 9):
|
9
11
|
from collections.abc import Mapping, Sequence
|
@@ -18,7 +20,7 @@ class CalledProcessError(subprocess.CalledProcessError):
|
|
18
20
|
if self.stderr:
|
19
21
|
if isinstance(self.stderr, bytes):
|
20
22
|
return super().__str__() + "\n" + self.stderr.decode()
|
21
|
-
|
23
|
+
if isinstance(self.stderr, str):
|
22
24
|
return super().__str__() + "\n" + self.stderr
|
23
25
|
return super().__str__()
|
24
26
|
|
@@ -1,8 +1,7 @@
|
|
1
|
-
import os
|
2
1
|
import shutil
|
3
2
|
import sys
|
4
3
|
from types import TracebackType
|
5
|
-
from typing import Any, Callable, Optional, Type, Union, overload
|
4
|
+
from typing import TYPE_CHECKING, Any, Callable, Optional, Type, Union, overload
|
6
5
|
|
7
6
|
if sys.version_info >= (3, 9):
|
8
7
|
from collections.abc import Collection, Sequence
|
@@ -20,6 +19,9 @@ from ._run import FoamCaseRunBase
|
|
20
19
|
from ._subprocess import run_sync
|
21
20
|
from ._util import ValuedGenerator
|
22
21
|
|
22
|
+
if TYPE_CHECKING:
|
23
|
+
import os
|
24
|
+
|
23
25
|
|
24
26
|
class FoamCase(FoamCaseRunBase):
|
25
27
|
"""
|
@@ -44,8 +46,6 @@ class FoamCase(FoamCaseRunBase):
|
|
44
46
|
for _ in calls:
|
45
47
|
pass
|
46
48
|
|
47
|
-
print(calls.value)
|
48
|
-
|
49
49
|
return calls.value
|
50
50
|
|
51
51
|
@staticmethod
|
@@ -89,8 +89,7 @@ class FoamCase(FoamCaseRunBase):
|
|
89
89
|
ret = super().__getitem__(index)
|
90
90
|
if isinstance(ret, FoamCaseBase.TimeDirectory):
|
91
91
|
return FoamCase.TimeDirectory(ret)
|
92
|
-
|
93
|
-
return [FoamCase.TimeDirectory(r) for r in ret]
|
92
|
+
return [FoamCase.TimeDirectory(r) for r in ret]
|
94
93
|
|
95
94
|
def __enter__(self) -> Self:
|
96
95
|
return self
|
@@ -112,6 +111,10 @@ class FoamCase(FoamCaseRunBase):
|
|
112
111
|
for _ in self._clean_calls(check=check):
|
113
112
|
pass
|
114
113
|
|
114
|
+
def _prepare(self, *, check: bool = True, log: bool = True) -> None:
|
115
|
+
for _ in self._prepare_calls(check=check, log=log):
|
116
|
+
pass
|
117
|
+
|
115
118
|
def run(
|
116
119
|
self,
|
117
120
|
cmd: Optional[Union[Sequence[Union[str, "os.PathLike[str]"]], str]] = None,
|
@@ -1,17 +1,15 @@
|
|
1
1
|
import sys
|
2
2
|
from dataclasses import dataclass
|
3
|
-
from typing import Dict, NamedTuple, Optional, Tuple, Union
|
3
|
+
from typing import TYPE_CHECKING, Dict, NamedTuple, Optional, Tuple, Union
|
4
|
+
|
5
|
+
if TYPE_CHECKING:
|
6
|
+
import numpy as np
|
4
7
|
|
5
8
|
if sys.version_info >= (3, 9):
|
6
9
|
from collections.abc import Mapping, Sequence
|
7
10
|
else:
|
8
11
|
from typing import Mapping, Sequence
|
9
12
|
|
10
|
-
try:
|
11
|
-
import numpy as np
|
12
|
-
except ModuleNotFoundError:
|
13
|
-
pass
|
14
|
-
|
15
13
|
|
16
14
|
class FoamFileBase:
|
17
15
|
class DimensionSet(NamedTuple):
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import sys
|
2
|
-
from typing import Any, Optional, Tuple, Union, cast
|
2
|
+
from typing import TYPE_CHECKING, Any, Optional, Tuple, Union, cast
|
3
3
|
|
4
4
|
if sys.version_info >= (3, 8):
|
5
5
|
from typing import Literal
|
@@ -13,13 +13,11 @@ else:
|
|
13
13
|
|
14
14
|
from ._base import FoamFileBase
|
15
15
|
from ._io import FoamFileIO
|
16
|
-
from ._serialization import Kind,
|
16
|
+
from ._serialization import Kind, dumps
|
17
17
|
from ._util import is_sequence
|
18
18
|
|
19
|
-
|
19
|
+
if TYPE_CHECKING:
|
20
20
|
import numpy as np
|
21
|
-
except ModuleNotFoundError:
|
22
|
-
pass
|
23
21
|
|
24
22
|
|
25
23
|
class FoamFile(
|
@@ -172,8 +170,7 @@ class FoamFile(
|
|
172
170
|
|
173
171
|
if value is ...:
|
174
172
|
return FoamFile.SubDict(self, keywords)
|
175
|
-
|
176
|
-
return value
|
173
|
+
return value
|
177
174
|
|
178
175
|
def __setitem__(
|
179
176
|
self, keywords: Optional[Union[str, Tuple[str, ...]]], data: "FoamFile._SetData"
|
@@ -205,7 +202,11 @@ class FoamFile(
|
|
205
202
|
if keywords == ("internalField",) or (
|
206
203
|
len(keywords) == 3
|
207
204
|
and keywords[0] == "boundaryField"
|
208
|
-
and
|
205
|
+
and (
|
206
|
+
keywords[2] in ("value", "gradient")
|
207
|
+
or keywords[2].endswith("Value")
|
208
|
+
or keywords[2].endswith("Gradient")
|
209
|
+
)
|
209
210
|
):
|
210
211
|
kind = Kind.BINARY_FIELD if self.format == "binary" else Kind.FIELD
|
211
212
|
elif keywords == ("dimensions",):
|
@@ -254,7 +255,7 @@ class FoamFile(
|
|
254
255
|
self._write(
|
255
256
|
before
|
256
257
|
+ indentation
|
257
|
-
+
|
258
|
+
+ dumps(keywords[-1])
|
258
259
|
+ b"\n"
|
259
260
|
+ indentation
|
260
261
|
+ b"{\n"
|
@@ -270,15 +271,15 @@ class FoamFile(
|
|
270
271
|
self._write(
|
271
272
|
before
|
272
273
|
+ indentation
|
273
|
-
+
|
274
|
+
+ dumps(keywords[-1])
|
274
275
|
+ b" "
|
275
|
-
+
|
276
|
+
+ dumps(data, kind=kind)
|
276
277
|
+ b";"
|
277
278
|
+ after
|
278
279
|
)
|
279
280
|
|
280
281
|
else:
|
281
|
-
self._write(before +
|
282
|
+
self._write(before + dumps(data, kind=kind) + after)
|
282
283
|
|
283
284
|
def __delitem__(self, keywords: Optional[Union[str, Tuple[str, ...]]]) -> None:
|
284
285
|
if not keywords:
|
@@ -1,10 +1,10 @@
|
|
1
1
|
import gzip
|
2
|
-
import os
|
3
2
|
import sys
|
4
3
|
from copy import deepcopy
|
5
4
|
from pathlib import Path
|
6
5
|
from types import TracebackType
|
7
6
|
from typing import (
|
7
|
+
TYPE_CHECKING,
|
8
8
|
Optional,
|
9
9
|
Tuple,
|
10
10
|
Type,
|
@@ -18,6 +18,9 @@ else:
|
|
18
18
|
|
19
19
|
from ._parsing import Parsed
|
20
20
|
|
21
|
+
if TYPE_CHECKING:
|
22
|
+
import os
|
23
|
+
|
21
24
|
|
22
25
|
class FoamFileIO:
|
23
26
|
def __init__(self, path: Union["os.PathLike[str]", str]) -> None:
|
@@ -63,8 +66,7 @@ class FoamFileIO:
|
|
63
66
|
if self.__contents is None:
|
64
67
|
if missing_ok:
|
65
68
|
return b"", Parsed(b"")
|
66
|
-
|
67
|
-
raise FileNotFoundError(self.path)
|
69
|
+
raise FileNotFoundError(self.path)
|
68
70
|
|
69
71
|
if self.__parsed is None:
|
70
72
|
parsed = Parsed(self.__contents)
|
@@ -27,42 +27,42 @@ class Kind(Enum):
|
|
27
27
|
DIMENSIONS = auto()
|
28
28
|
|
29
29
|
|
30
|
-
def
|
30
|
+
def dumps(
|
31
31
|
data: FoamFileBase._SetData,
|
32
32
|
*,
|
33
33
|
kind: Kind = Kind.DEFAULT,
|
34
34
|
) -> bytes:
|
35
35
|
if numpy and isinstance(data, np.ndarray):
|
36
|
-
return
|
36
|
+
return dumps(data.tolist(), kind=kind)
|
37
37
|
|
38
|
-
|
38
|
+
if isinstance(data, Mapping):
|
39
39
|
entries = []
|
40
40
|
for k, v in data.items():
|
41
|
-
b =
|
41
|
+
b = dumps(v, kind=kind)
|
42
42
|
if isinstance(v, Mapping):
|
43
|
-
entries.append(
|
43
|
+
entries.append(dumps(k) + b" {" + b + b"}")
|
44
44
|
elif not b:
|
45
|
-
entries.append(
|
45
|
+
entries.append(dumps(k) + b";")
|
46
46
|
else:
|
47
|
-
entries.append(
|
47
|
+
entries.append(dumps(k) + b" " + b + b";")
|
48
48
|
|
49
49
|
return b" ".join(entries)
|
50
50
|
|
51
|
-
|
51
|
+
if isinstance(data, FoamFileBase.DimensionSet) or (
|
52
52
|
kind == Kind.DIMENSIONS and is_sequence(data) and len(data) == 7
|
53
53
|
):
|
54
|
-
return b"[" + b" ".join(
|
54
|
+
return b"[" + b" ".join(dumps(v) for v in data) + b"]"
|
55
55
|
|
56
|
-
|
56
|
+
if (kind == Kind.FIELD or kind == Kind.BINARY_FIELD) and (
|
57
57
|
isinstance(data, (int, float))
|
58
58
|
or is_sequence(data)
|
59
59
|
and data
|
60
60
|
and isinstance(data[0], (int, float))
|
61
61
|
and len(data) in (3, 6, 9)
|
62
62
|
):
|
63
|
-
return b"uniform " +
|
63
|
+
return b"uniform " + dumps(data, kind=Kind.SINGLE_ENTRY)
|
64
64
|
|
65
|
-
|
65
|
+
if (kind == Kind.FIELD or kind == Kind.BINARY_FIELD) and is_sequence(data):
|
66
66
|
if isinstance(data[0], (int, float)):
|
67
67
|
tensor_kind = b"scalar"
|
68
68
|
elif len(data[0]) == 3:
|
@@ -72,7 +72,7 @@ def dumpb(
|
|
72
72
|
elif len(data[0]) == 9:
|
73
73
|
tensor_kind = b"tensor"
|
74
74
|
else:
|
75
|
-
return
|
75
|
+
return dumps(data)
|
76
76
|
|
77
77
|
if kind == Kind.BINARY_FIELD:
|
78
78
|
if tensor_kind == b"scalar":
|
@@ -84,36 +84,34 @@ def dumpb(
|
|
84
84
|
+ b")"
|
85
85
|
)
|
86
86
|
else:
|
87
|
-
contents =
|
87
|
+
contents = dumps(data, kind=Kind.SINGLE_ENTRY)
|
88
88
|
|
89
|
-
return b"nonuniform List<" + tensor_kind + b"> " +
|
89
|
+
return b"nonuniform List<" + tensor_kind + b"> " + dumps(len(data)) + contents
|
90
90
|
|
91
|
-
|
92
|
-
return b" ".join(
|
91
|
+
if kind != Kind.SINGLE_ENTRY and isinstance(data, tuple):
|
92
|
+
return b" ".join(dumps(v) for v in data)
|
93
93
|
|
94
|
-
|
94
|
+
if isinstance(data, FoamFileBase.Dimensioned):
|
95
95
|
if data.name is not None:
|
96
96
|
return (
|
97
|
-
|
97
|
+
dumps(data.name)
|
98
98
|
+ b" "
|
99
|
-
+
|
99
|
+
+ dumps(data.dimensions, kind=Kind.DIMENSIONS)
|
100
100
|
+ b" "
|
101
|
-
+
|
102
|
-
)
|
103
|
-
else:
|
104
|
-
return (
|
105
|
-
dumpb(data.dimensions, kind=Kind.DIMENSIONS)
|
106
|
-
+ b" "
|
107
|
-
+ dumpb(data.value, kind=Kind.SINGLE_ENTRY)
|
101
|
+
+ dumps(data.value, kind=Kind.SINGLE_ENTRY)
|
108
102
|
)
|
103
|
+
return (
|
104
|
+
dumps(data.dimensions, kind=Kind.DIMENSIONS)
|
105
|
+
+ b" "
|
106
|
+
+ dumps(data.value, kind=Kind.SINGLE_ENTRY)
|
107
|
+
)
|
109
108
|
|
110
|
-
|
111
|
-
return b"(" + b" ".join(
|
109
|
+
if is_sequence(data):
|
110
|
+
return b"(" + b" ".join(dumps(v, kind=Kind.SINGLE_ENTRY) for v in data) + b")"
|
112
111
|
|
113
|
-
|
112
|
+
if data is True:
|
114
113
|
return b"yes"
|
115
|
-
|
114
|
+
if data is False:
|
116
115
|
return b"no"
|
117
116
|
|
118
|
-
|
119
|
-
return str(data).encode("latin-1")
|
117
|
+
return str(data).encode("latin-1")
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: foamlib
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.9
|
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
|
@@ -53,7 +53,7 @@ Requires-Dist: foamlib[test]; extra == "dev"
|
|
53
53
|
Requires-Dist: foamlib[typing]; extra == "dev"
|
54
54
|
Requires-Dist: foamlib[docs]; extra == "dev"
|
55
55
|
|
56
|
-
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="
|
56
|
+
[<img alt="foamlib" src="https://github.com/gerlero/foamlib/raw/main/logo.png" height="65">](https://github.com/gerlero/foamlib)
|
57
57
|
|
58
58
|
[](https://foamlib.readthedocs.io/)
|
59
59
|
[](https://github.com/gerlero/foamlib/actions/workflows/ci.yml)
|
@@ -61,24 +61,28 @@ Requires-Dist: foamlib[docs]; extra == "dev"
|
|
61
61
|
[](http://mypy-lang.org/)
|
62
62
|
[](https://github.com/astral-sh/ruff)
|
63
63
|
[](https://github.com/astral-sh/uv)
|
64
|
+
[](https://github.com/gerlero/foamlib/actions/workflows/pypi-publish.yml)
|
64
65
|
[](https://pypi.org/project/foamlib/)
|
65
66
|
[](https://anaconda.org/conda-forge/foamlib)
|
66
67
|
[](https://pypi.org/project/foamlib/)
|
67
68
|

|
69
|
+
[](https://github.com/gerlero/foamlib/actions/workflows/docker.yml)
|
68
70
|
[](https://hub.docker.com/r/microfluidica/foamlib/)
|
69
71
|
|
72
|
+
## 👋 Basics
|
73
|
+
|
70
74
|
**foamlib** provides a simple, modern and ergonomic Python interface for interacting with [OpenFOAM](https://www.openfoam.com).
|
71
75
|
|
72
|
-
It offers the following classes:
|
76
|
+
It offers the following Python classes:
|
73
77
|
|
74
78
|
* [`FoamFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFile) (and [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/files.html#foamlib.FoamFieldFile)): read-write access to OpenFOAM configuration and field files as if they were Python `dict`s, using `foamlib`'s own parser. Supports ASCII and binary field formats (with or without compression).
|
75
79
|
* [`FoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.FoamCase): a class for configuring, running, and accessing the results of OpenFOAM cases.
|
76
80
|
* [`AsyncFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncFoamCase): variant of `FoamCase` with asynchronous methods for running multiple cases at once.
|
77
81
|
* [`AsyncSlurmFoamCase`](https://foamlib.readthedocs.io/en/stable/cases.html#foamlib.AsyncSlurmFoamCase): subclass of `AsyncFoamCase` used for running cases on a Slurm cluster.
|
78
82
|
|
79
|
-
## Get started
|
83
|
+
## ☑️ Get started
|
80
84
|
|
81
|
-
### Install
|
85
|
+
### 📦 Install
|
82
86
|
|
83
87
|
* With [pip](https://pypi.org/project/pip/):
|
84
88
|
|
@@ -92,7 +96,7 @@ It offers the following classes:
|
|
92
96
|
conda install -c conda-forge foamlib
|
93
97
|
```
|
94
98
|
|
95
|
-
### Clone a case
|
99
|
+
### 🐑 Clone a case
|
96
100
|
|
97
101
|
```python
|
98
102
|
import os
|
@@ -104,13 +108,13 @@ pitz_tutorial = FoamCase(Path(os.environ["FOAM_TUTORIALS"]) / "incompressible/si
|
|
104
108
|
my_pitz = pitz_tutorial.clone("myPitz")
|
105
109
|
```
|
106
110
|
|
107
|
-
### Run the case
|
111
|
+
### 🏃 Run the case
|
108
112
|
|
109
113
|
```python
|
110
114
|
my_pitz.run()
|
111
115
|
```
|
112
116
|
|
113
|
-
### Access the results
|
117
|
+
### 🔎 Access the results
|
114
118
|
|
115
119
|
```python
|
116
120
|
latest_time = my_pitz[-1]
|
@@ -122,19 +126,19 @@ print(p.internal_field)
|
|
122
126
|
print(U.internal_field)
|
123
127
|
```
|
124
128
|
|
125
|
-
### Clean the case
|
129
|
+
### 🧹 Clean the case
|
126
130
|
|
127
131
|
```python
|
128
132
|
my_pitz.clean()
|
129
133
|
```
|
130
134
|
|
131
|
-
### Edit the `controlDict` file
|
135
|
+
### ⚙️ Edit the `controlDict` file
|
132
136
|
|
133
137
|
```python
|
134
138
|
my_pitz.control_dict["writeInterval"] = 10
|
135
139
|
```
|
136
140
|
|
137
|
-
### Make multiple file reads and writes in a single go
|
141
|
+
### 📝 Make multiple file reads and writes in a single go
|
138
142
|
|
139
143
|
```python
|
140
144
|
with my_pitz.fv_schemes as f:
|
@@ -142,7 +146,7 @@ with my_pitz.fv_schemes as f:
|
|
142
146
|
f["snGradSchemes"]["default"] = "uncorrected"
|
143
147
|
```
|
144
148
|
|
145
|
-
### Run a case asynchronously
|
149
|
+
### ⏳ Run a case asynchronously
|
146
150
|
|
147
151
|
```python
|
148
152
|
import asyncio
|
@@ -155,7 +159,7 @@ async def run_case():
|
|
155
159
|
asyncio.run(run_case())
|
156
160
|
```
|
157
161
|
|
158
|
-
### Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
162
|
+
### 🔢 Parse a field using the [`FoamFieldFile`](https://foamlib.readthedocs.io/en/stable/#foamlib.FoamFieldFile) class directly
|
159
163
|
|
160
164
|
```python
|
161
165
|
from foamlib import FoamFieldFile
|
@@ -165,7 +169,7 @@ U = FoamFieldFile(Path(my_pitz) / "0/U")
|
|
165
169
|
print(U.internal_field)
|
166
170
|
```
|
167
171
|
|
168
|
-
### Run an optimization loop in parallel
|
172
|
+
### 🔁 Run an optimization loop in parallel
|
169
173
|
|
170
174
|
```python
|
171
175
|
import os
|
@@ -185,7 +189,7 @@ async def cost(x):
|
|
185
189
|
result = differential_evolution(cost, bounds=[(-1, 1)], workers=AsyncFoamCase.map, polish=False)
|
186
190
|
```
|
187
191
|
|
188
|
-
### Use it to create a `run` (or `clean`) script
|
192
|
+
### 📄 Use it to create a `run` (or `clean`) script
|
189
193
|
|
190
194
|
```python
|
191
195
|
#!/usr/bin/env python3
|
@@ -197,6 +201,6 @@ case = FoamCase(Path(__file__).parent)
|
|
197
201
|
case.run()
|
198
202
|
```
|
199
203
|
|
200
|
-
## Documentation
|
204
|
+
## 📘 Documentation
|
201
205
|
|
202
206
|
For more information, check out the [documentation](https://foamlib.readthedocs.io/).
|
@@ -87,7 +87,36 @@ packages = [
|
|
87
87
|
strict = true
|
88
88
|
|
89
89
|
[tool.ruff.lint]
|
90
|
-
extend-select = [
|
90
|
+
extend-select = [
|
91
|
+
"ASYNC",
|
92
|
+
"B",
|
93
|
+
"C4",
|
94
|
+
"D",
|
95
|
+
"ERA",
|
96
|
+
"F",
|
97
|
+
"FLY",
|
98
|
+
"FURB",
|
99
|
+
"I",
|
100
|
+
"ICN",
|
101
|
+
"INT",
|
102
|
+
"NPY",
|
103
|
+
"PERF",
|
104
|
+
"PIE",
|
105
|
+
"PLC",
|
106
|
+
"PLE",
|
107
|
+
"PLW",
|
108
|
+
"PT",
|
109
|
+
"PTH",
|
110
|
+
"Q",
|
111
|
+
"RET",
|
112
|
+
"RSE",
|
113
|
+
"RUF",
|
114
|
+
"SIM",
|
115
|
+
"T20",
|
116
|
+
"TCH",
|
117
|
+
"UP",
|
118
|
+
"YTT",
|
119
|
+
]
|
91
120
|
|
92
121
|
[tool.ruff.lint.pydocstyle]
|
93
122
|
convention = "pep257"
|
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
|