mphkit 0.1.0__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.
mphkit-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 elgar328
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
mphkit-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,174 @@
1
+ Metadata-Version: 2.4
2
+ Name: mphkit
3
+ Version: 0.1.0
4
+ Summary: Helpers on top of MPh for building COMSOL geometries and geometry-based selections in Python.
5
+ Keywords: comsol,mph,multiphysics,geometry,selection,simulation,fem
6
+ Author: elgar328
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Operating System :: MacOS
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering
20
+ Classifier: Topic :: Scientific/Engineering :: Physics
21
+ Classifier: Typing :: Typed
22
+ Requires-Dist: mph>=1.4
23
+ Requires-Dist: numpy
24
+ Requires-Python: >=3.10
25
+ Project-URL: Homepage, https://github.com/elgar328/mphkit
26
+ Project-URL: Repository, https://github.com/elgar328/mphkit
27
+ Project-URL: Changelog, https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md
28
+ Project-URL: Issues, https://github.com/elgar328/mphkit/issues
29
+ Description-Content-Type: text/markdown
30
+
31
+ # mphkit
32
+
33
+ Helpers on top of [MPh](https://github.com/MPh-py/MPh) for building COMSOL
34
+ geometries and geometry-based selections in Python. Select boundaries by
35
+ location instead of by entity number, so selections keep working when the
36
+ geometry changes.
37
+
38
+ > [!WARNING]
39
+ > **Early stage.** mphkit is at an early stage of development. The API may
40
+ > change at any time, without deprecation warnings.
41
+
42
+ Not affiliated with COMSOL AB.
43
+
44
+ ## Example
45
+
46
+ ```python
47
+ import mph
48
+ import mphkit as mk
49
+
50
+ client = mph.start()
51
+ model = client.create('demo')
52
+ geom = mk.geometry(model, 3, length_unit='mm')
53
+
54
+ plate = mk.block(geom, (100, 100, 10), name='plate')
55
+ hole = mk.cylinder(geom, 5, 10, (50, 50, 0))
56
+ mk.difference(geom, plate, [hole])
57
+ model.build(geom)
58
+
59
+ bottom = mk.sel.box(geom, 'boundary', z=0) # faces on the plane z = 0
60
+
61
+ # plain MPh from here on
62
+ physics = (model/'physics').create('HeatTransfer', geom)
63
+ physics.create('TemperatureBoundary', 2).select(bottom)
64
+ model.save('demo.mph')
65
+ ```
66
+
67
+ Every helper takes MPh `Node`s, and those that create something return
68
+ one, so mphkit and MPh mix freely. Physics, mesh, study and results stay
69
+ plain MPh (or the COMSOL Java API through `node.java`).
70
+
71
+ ## Requirements
72
+
73
+ - COMSOL Multiphysics with a license, installed where MPh can find it
74
+ (see the [MPh documentation](https://mph.readthedocs.io)).
75
+ - Python 3.10 or newer, MPh 1.4 or newer.
76
+ - Importing CAD files (`mk.import_` with STEP, IGES, ...) needs a license
77
+ for CAD import (CAD Import Module, Design Module or a LiveLink).
78
+ Everything else needs COMSOL only.
79
+
80
+ Tested with COMSOL 6.4 and MPh 1.4.0, on macOS (Apple silicon) with
81
+ Python 3.10 and 3.13 and on Windows with Python 3.13. Linux is not tested
82
+ yet; since mphkit only goes through MPh, it is expected to work the same
83
+ way.
84
+
85
+ ## Installation
86
+
87
+ ```
88
+ pip install mphkit
89
+ ```
90
+
91
+ or `uv add mphkit` in a uv project.
92
+
93
+ What changed between versions is listed in
94
+ [CHANGELOG.md](https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md).
95
+
96
+ ## What it covers
97
+
98
+ Geometry, in 3D, 2D and in work planes:
99
+
100
+ ```python
101
+ mk.block(geom, (10, 10, 5)); mk.cylinder(geom, r, h, pos); mk.sphere(geom, r)
102
+ mk.union(geom, [a, b]); mk.difference(geom, a, [b]); mk.intersection(geom, [a, b])
103
+ mk.move(geom, part, (10, 0, 0)); mk.rotate(geom, part, 90, axis='z')
104
+ mk.mirror(geom, part, (1, 0, 0)); mk.array(geom, part, size=(5, 5, 1), displ=(10, 10, 0))
105
+ mk.fillet(geom, block, 0.5); mk.chamfer(geom, block, 0.5) # all edges, or a selection
106
+ mk.partition(geom, part, tool); mk.delete(geom, part)
107
+ plane = mk.workplane(geom, quickz=0)
108
+ mk.circle(plane, 2); mk.extrude(geom, plane, 5); mk.revolve(geom, plane)
109
+ mk.import_(geom, 'part.step')
110
+ mk.feature(geom, 'AnyType', ...) # any other geometry feature
111
+ ```
112
+
113
+ Selections by location (`mk.sel`), usable in physics, materials and mesh:
114
+
115
+ ```python
116
+ mk.sel.box(geom, 'boundary', z=0) # a range per axis, or a value
117
+ mk.sel.ball(geom, 'domain', center, r); mk.sel.cylinder(...); mk.sel.disk(...)
118
+ mk.sel.union(geom, 'boundary', [a, b]) # also intersection, difference, complement
119
+ mk.sel.adjacent(geom, domains) # boundaries around a domain selection
120
+ mk.sel.result(geom, feature, 'domain') # what a feature produced
121
+ holes = mk.sel.cumulative(geom, 'holes', 'domain', create=True)
122
+ mk.cylinder(geom, 1, 5, pos, contributeto=holes) # collect from several features
123
+ ```
124
+
125
+ `where='geometry'` makes a selection inside the geometry sequence instead,
126
+ for use as input of a later operation, e.g. `mk.sel.box(geom, 'object',
127
+ x=(20, 40), where='geometry')` to pick whole objects for `mk.delete`. In a
128
+ work plane, selections pick single corners or edges:
129
+ `mk.fillet(plane, mk.sel.box(plane, 'point', x=1, y=1), 0.3)`.
130
+
131
+ Queries return plain Python values and leave nothing in the model:
132
+
133
+ ```python
134
+ mk.sel.entities(geom, bottom) # [3]
135
+ mk.sel.find(geom, 'domain', x=(0, 10)) # entity numbers inside a box
136
+ mk.measure(geom, 'domain') # volume (area, length for other levels)
137
+ mk.bounding_box(geom, 'boundary', 3) # {'x': (0, 10), 'y': ..., 'z': ...}
138
+ ```
139
+
140
+ And a few helpers outside geometry:
141
+
142
+ ```python
143
+ mk.coordinate_system(geom, 'PML', selection=layer) # e.g. perfectly matched layers
144
+ mk.set(mesh_size, hmax=0.5, hgrad=2) # any node or Java object; converts ints and lists
145
+ ```
146
+
147
+ Arguments are COMSOL property names, so the COMSOL documentation of each
148
+ feature applies. The docstrings describe each helper in detail.
149
+
150
+ [`examples/plate_with_holes.py`](https://github.com/elgar328/mphkit/blob/main/examples/plate_with_holes.py)
151
+ is a complete script, from geometry to solved results: heat conduction in
152
+ a plate with a row of cooling holes, for any number of holes.
153
+
154
+ ## Limitations
155
+
156
+ - mphkit covers geometry and selections only. Physics, mesh, studies and
157
+ results are left to MPh.
158
+ - No named helpers yet for geometry parts (`PartInstance`), sweeps, cones
159
+ and the other remaining primitives, virtual operations or repair. They
160
+ work through `mk.feature(geom, 'Sweep', ...)` with the same conversions
161
+ and input handling.
162
+
163
+ ## Development
164
+
165
+ ```
166
+ uv run pytest
167
+ ```
168
+
169
+ The tests start COMSOL and build real models. Without a CAD import
170
+ license, the CAD import test is skipped.
171
+
172
+ ## License
173
+
174
+ MIT, see [LICENSE](https://github.com/elgar328/mphkit/blob/main/LICENSE).
mphkit-0.1.0/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # mphkit
2
+
3
+ Helpers on top of [MPh](https://github.com/MPh-py/MPh) for building COMSOL
4
+ geometries and geometry-based selections in Python. Select boundaries by
5
+ location instead of by entity number, so selections keep working when the
6
+ geometry changes.
7
+
8
+ > [!WARNING]
9
+ > **Early stage.** mphkit is at an early stage of development. The API may
10
+ > change at any time, without deprecation warnings.
11
+
12
+ Not affiliated with COMSOL AB.
13
+
14
+ ## Example
15
+
16
+ ```python
17
+ import mph
18
+ import mphkit as mk
19
+
20
+ client = mph.start()
21
+ model = client.create('demo')
22
+ geom = mk.geometry(model, 3, length_unit='mm')
23
+
24
+ plate = mk.block(geom, (100, 100, 10), name='plate')
25
+ hole = mk.cylinder(geom, 5, 10, (50, 50, 0))
26
+ mk.difference(geom, plate, [hole])
27
+ model.build(geom)
28
+
29
+ bottom = mk.sel.box(geom, 'boundary', z=0) # faces on the plane z = 0
30
+
31
+ # plain MPh from here on
32
+ physics = (model/'physics').create('HeatTransfer', geom)
33
+ physics.create('TemperatureBoundary', 2).select(bottom)
34
+ model.save('demo.mph')
35
+ ```
36
+
37
+ Every helper takes MPh `Node`s, and those that create something return
38
+ one, so mphkit and MPh mix freely. Physics, mesh, study and results stay
39
+ plain MPh (or the COMSOL Java API through `node.java`).
40
+
41
+ ## Requirements
42
+
43
+ - COMSOL Multiphysics with a license, installed where MPh can find it
44
+ (see the [MPh documentation](https://mph.readthedocs.io)).
45
+ - Python 3.10 or newer, MPh 1.4 or newer.
46
+ - Importing CAD files (`mk.import_` with STEP, IGES, ...) needs a license
47
+ for CAD import (CAD Import Module, Design Module or a LiveLink).
48
+ Everything else needs COMSOL only.
49
+
50
+ Tested with COMSOL 6.4 and MPh 1.4.0, on macOS (Apple silicon) with
51
+ Python 3.10 and 3.13 and on Windows with Python 3.13. Linux is not tested
52
+ yet; since mphkit only goes through MPh, it is expected to work the same
53
+ way.
54
+
55
+ ## Installation
56
+
57
+ ```
58
+ pip install mphkit
59
+ ```
60
+
61
+ or `uv add mphkit` in a uv project.
62
+
63
+ What changed between versions is listed in
64
+ [CHANGELOG.md](https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md).
65
+
66
+ ## What it covers
67
+
68
+ Geometry, in 3D, 2D and in work planes:
69
+
70
+ ```python
71
+ mk.block(geom, (10, 10, 5)); mk.cylinder(geom, r, h, pos); mk.sphere(geom, r)
72
+ mk.union(geom, [a, b]); mk.difference(geom, a, [b]); mk.intersection(geom, [a, b])
73
+ mk.move(geom, part, (10, 0, 0)); mk.rotate(geom, part, 90, axis='z')
74
+ mk.mirror(geom, part, (1, 0, 0)); mk.array(geom, part, size=(5, 5, 1), displ=(10, 10, 0))
75
+ mk.fillet(geom, block, 0.5); mk.chamfer(geom, block, 0.5) # all edges, or a selection
76
+ mk.partition(geom, part, tool); mk.delete(geom, part)
77
+ plane = mk.workplane(geom, quickz=0)
78
+ mk.circle(plane, 2); mk.extrude(geom, plane, 5); mk.revolve(geom, plane)
79
+ mk.import_(geom, 'part.step')
80
+ mk.feature(geom, 'AnyType', ...) # any other geometry feature
81
+ ```
82
+
83
+ Selections by location (`mk.sel`), usable in physics, materials and mesh:
84
+
85
+ ```python
86
+ mk.sel.box(geom, 'boundary', z=0) # a range per axis, or a value
87
+ mk.sel.ball(geom, 'domain', center, r); mk.sel.cylinder(...); mk.sel.disk(...)
88
+ mk.sel.union(geom, 'boundary', [a, b]) # also intersection, difference, complement
89
+ mk.sel.adjacent(geom, domains) # boundaries around a domain selection
90
+ mk.sel.result(geom, feature, 'domain') # what a feature produced
91
+ holes = mk.sel.cumulative(geom, 'holes', 'domain', create=True)
92
+ mk.cylinder(geom, 1, 5, pos, contributeto=holes) # collect from several features
93
+ ```
94
+
95
+ `where='geometry'` makes a selection inside the geometry sequence instead,
96
+ for use as input of a later operation, e.g. `mk.sel.box(geom, 'object',
97
+ x=(20, 40), where='geometry')` to pick whole objects for `mk.delete`. In a
98
+ work plane, selections pick single corners or edges:
99
+ `mk.fillet(plane, mk.sel.box(plane, 'point', x=1, y=1), 0.3)`.
100
+
101
+ Queries return plain Python values and leave nothing in the model:
102
+
103
+ ```python
104
+ mk.sel.entities(geom, bottom) # [3]
105
+ mk.sel.find(geom, 'domain', x=(0, 10)) # entity numbers inside a box
106
+ mk.measure(geom, 'domain') # volume (area, length for other levels)
107
+ mk.bounding_box(geom, 'boundary', 3) # {'x': (0, 10), 'y': ..., 'z': ...}
108
+ ```
109
+
110
+ And a few helpers outside geometry:
111
+
112
+ ```python
113
+ mk.coordinate_system(geom, 'PML', selection=layer) # e.g. perfectly matched layers
114
+ mk.set(mesh_size, hmax=0.5, hgrad=2) # any node or Java object; converts ints and lists
115
+ ```
116
+
117
+ Arguments are COMSOL property names, so the COMSOL documentation of each
118
+ feature applies. The docstrings describe each helper in detail.
119
+
120
+ [`examples/plate_with_holes.py`](https://github.com/elgar328/mphkit/blob/main/examples/plate_with_holes.py)
121
+ is a complete script, from geometry to solved results: heat conduction in
122
+ a plate with a row of cooling holes, for any number of holes.
123
+
124
+ ## Limitations
125
+
126
+ - mphkit covers geometry and selections only. Physics, mesh, studies and
127
+ results are left to MPh.
128
+ - No named helpers yet for geometry parts (`PartInstance`), sweeps, cones
129
+ and the other remaining primitives, virtual operations or repair. They
130
+ work through `mk.feature(geom, 'Sweep', ...)` with the same conversions
131
+ and input handling.
132
+
133
+ ## Development
134
+
135
+ ```
136
+ uv run pytest
137
+ ```
138
+
139
+ The tests start COMSOL and build real models. Without a CAD import
140
+ license, the CAD import test is skipped.
141
+
142
+ ## License
143
+
144
+ MIT, see [LICENSE](https://github.com/elgar328/mphkit/blob/main/LICENSE).
@@ -0,0 +1,55 @@
1
+ [project]
2
+ name = "mphkit"
3
+ version = "0.1.0"
4
+ description = "Helpers on top of MPh for building COMSOL geometries and geometry-based selections in Python."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ keywords = [
9
+ "comsol",
10
+ "mph",
11
+ "multiphysics",
12
+ "geometry",
13
+ "selection",
14
+ "simulation",
15
+ "fem",
16
+ ]
17
+ requires-python = ">=3.10"
18
+ dependencies = [
19
+ "mph>=1.4",
20
+ "numpy",
21
+ ]
22
+ classifiers = [
23
+ "Development Status :: 3 - Alpha",
24
+ "Intended Audience :: Science/Research",
25
+ "Operating System :: MacOS",
26
+ "Operating System :: Microsoft :: Windows",
27
+ "Programming Language :: Python :: 3",
28
+ "Programming Language :: Python :: 3 :: Only",
29
+ "Programming Language :: Python :: 3.10",
30
+ "Programming Language :: Python :: 3.11",
31
+ "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Topic :: Scientific/Engineering",
34
+ "Topic :: Scientific/Engineering :: Physics",
35
+ "Typing :: Typed",
36
+ ]
37
+
38
+ [[project.authors]]
39
+ name = "elgar328"
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/elgar328/mphkit"
43
+ Repository = "https://github.com/elgar328/mphkit"
44
+ Changelog = "https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md"
45
+ Issues = "https://github.com/elgar328/mphkit/issues"
46
+
47
+ [dependency-groups]
48
+ dev = ["pytest>=8"]
49
+
50
+ [build-system]
51
+ requires = ["uv_build>=0.9.9,<0.13"]
52
+ build-backend = "uv_build"
53
+
54
+ [tool.pytest.ini_options]
55
+ testpaths = ["tests"]
@@ -0,0 +1,43 @@
1
+ [project]
2
+ name = "mphkit"
3
+ version = "0.1.0"
4
+ description = "Helpers on top of MPh for building COMSOL geometries and geometry-based selections in Python."
5
+ readme = "README.md"
6
+ authors = [{ name = "elgar328" }]
7
+ license = "MIT"
8
+ license-files = ["LICENSE"]
9
+ keywords = ["comsol", "mph", "multiphysics", "geometry", "selection",
10
+ "simulation", "fem"]
11
+ requires-python = ">=3.10"
12
+ dependencies = ["mph>=1.4", "numpy"]
13
+ classifiers = [
14
+ "Development Status :: 3 - Alpha",
15
+ "Intended Audience :: Science/Research",
16
+ "Operating System :: MacOS",
17
+ "Operating System :: Microsoft :: Windows",
18
+ "Programming Language :: Python :: 3",
19
+ "Programming Language :: Python :: 3 :: Only",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ "Topic :: Scientific/Engineering",
25
+ "Topic :: Scientific/Engineering :: Physics",
26
+ "Typing :: Typed",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/elgar328/mphkit"
31
+ Repository = "https://github.com/elgar328/mphkit"
32
+ Changelog = "https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md"
33
+ Issues = "https://github.com/elgar328/mphkit/issues"
34
+
35
+ [dependency-groups]
36
+ dev = ["pytest>=8"]
37
+
38
+ [build-system]
39
+ requires = ["uv_build>=0.9.9,<0.13"]
40
+ build-backend = "uv_build"
41
+
42
+ [tool.pytest.ini_options]
43
+ testpaths = ["tests"]
@@ -0,0 +1,23 @@
1
+ """Helpers on top of MPh for building COMSOL geometries and selections."""
2
+
3
+ from . import sel
4
+ from ._measure import bounding_box, measure
5
+ from ._props import set_ as set # not in __all__: keeps builtin set
6
+ from .errors import LicenseError
7
+ from .geometry import (array, block, chamfer, circle, component_of,
8
+ coordinate_system, cylinder, delete, difference,
9
+ extrude, feature, fillet, geometry, import_,
10
+ intersection, interval, line_segment, mirror, move,
11
+ partition, point, polygon, rectangle, revolve,
12
+ rigid_transform, rotate, sphere, square, union,
13
+ workplane)
14
+
15
+ __version__ = '0.1.0'
16
+
17
+ __all__ = ['LicenseError', 'array', 'block', 'bounding_box', 'chamfer',
18
+ 'circle', 'component_of', 'coordinate_system', 'cylinder',
19
+ 'delete', 'difference', 'extrude', 'feature', 'fillet',
20
+ 'geometry', 'import_', 'intersection', 'interval',
21
+ 'line_segment', 'measure', 'mirror', 'move', 'partition', 'point',
22
+ 'polygon', 'rectangle', 'revolve', 'rigid_transform', 'rotate',
23
+ 'sel', 'sphere', 'square', 'union', 'workplane']