mphkit 0.1.0__tar.gz → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mphkit
3
- Version: 0.1.0
3
+ Version: 0.2.0
4
4
  Summary: Helpers on top of MPh for building COMSOL geometries and geometry-based selections in Python.
5
5
  Keywords: comsol,mph,multiphysics,geometry,selection,simulation,fem
6
6
  Author: elgar328
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
18
  Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
19
20
  Classifier: Topic :: Scientific/Engineering
20
21
  Classifier: Topic :: Scientific/Engineering :: Physics
21
22
  Classifier: Typing :: Typed
@@ -30,14 +31,19 @@ Description-Content-Type: text/markdown
30
31
 
31
32
  # mphkit
32
33
 
34
+ [![PyPI](https://img.shields.io/pypi/v/mphkit)](https://pypi.org/project/mphkit/)
35
+ [![Python](https://img.shields.io/python/required-version-toml?tomlFilePath=https://raw.githubusercontent.com/elgar328/mphkit/main/pyproject.toml)](https://pypi.org/project/mphkit/)
36
+ [![License](https://img.shields.io/pypi/l/mphkit)](https://github.com/elgar328/mphkit/blob/main/LICENSE)
37
+ [![COMSOL](https://img.shields.io/badge/COMSOL-6.4-blue)](https://www.comsol.com/)
38
+
33
39
  Helpers on top of [MPh](https://github.com/MPh-py/MPh) for building COMSOL
34
40
  geometries and geometry-based selections in Python. Select boundaries by
35
41
  location instead of by entity number, so selections keep working when the
36
42
  geometry changes.
37
43
 
38
44
  > [!WARNING]
39
- > **Early stage.** mphkit is at an early stage of development. The API may
40
- > change at any time, without deprecation warnings.
45
+ > **Early stage.** The API may change at any time, without deprecation
46
+ > warnings.
41
47
 
42
48
  Not affiliated with COMSOL AB.
43
49
 
@@ -60,13 +66,18 @@ bottom = mk.sel.box(geom, 'boundary', z=0) # faces on the plane z = 0
60
66
 
61
67
  # plain MPh from here on
62
68
  physics = (model/'physics').create('HeatTransfer', geom)
63
- physics.create('TemperatureBoundary', 2).select(bottom)
69
+ physics.create('TemperatureBoundary', 2).select(bottom) # 2: boundaries in 3D
64
70
  model.save('demo.mph')
65
71
  ```
66
72
 
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`).
73
+ Helpers take MPh `Node`s (`mk.geometry` the model, `mk.set` also Java
74
+ objects), and those that create something return one, so mphkit and MPh
75
+ mix freely. Physics, mesh, study and results stay plain MPh (or the
76
+ COMSOL Java API through `node.java`).
77
+
78
+ `help(mphkit)` sums up the workflow, the rules and the common pitfalls,
79
+ and each helper has its own `help()`. Point an AI assistant to
80
+ `help(mphkit)` first.
70
81
 
71
82
  ## Requirements
72
83
 
@@ -77,10 +88,10 @@ plain MPh (or the COMSOL Java API through `node.java`).
77
88
  for CAD import (CAD Import Module, Design Module or a LiveLink).
78
89
  Everything else needs COMSOL only.
79
90
 
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.
91
+ mphkit is developed and tested with COMSOL 6.4 and MPh 1.4. Feature types,
92
+ property names and selection behavior can differ between COMSOL versions,
93
+ so other versions may need adjustments; reports are welcome. Checked on
94
+ macOS and Windows; it should run wherever MPh runs.
84
95
 
85
96
  ## Installation
86
97
 
@@ -102,7 +113,7 @@ mk.block(geom, (10, 10, 5)); mk.cylinder(geom, r, h, pos); mk.sphere(geom, r)
102
113
  mk.union(geom, [a, b]); mk.difference(geom, a, [b]); mk.intersection(geom, [a, b])
103
114
  mk.move(geom, part, (10, 0, 0)); mk.rotate(geom, part, 90, axis='z')
104
115
  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
116
+ mk.fillet(geom, part, 0.5); mk.chamfer(geom, part, 0.5) # all edges, or a selection
106
117
  mk.partition(geom, part, tool); mk.delete(geom, part)
107
118
  plane = mk.workplane(geom, quickz=0)
108
119
  mk.circle(plane, 2); mk.extrude(geom, plane, 5); mk.revolve(geom, plane)
@@ -125,16 +136,27 @@ mk.cylinder(geom, 1, 5, pos, contributeto=holes) # collect from several feature
125
136
  `where='geometry'` makes a selection inside the geometry sequence instead,
126
137
  for use as input of a later operation, e.g. `mk.sel.box(geom, 'object',
127
138
  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)`.
139
+ work plane, selections can pick single corners or edges, e.g. to fillet
140
+ one corner: `mk.fillet(plane, mk.sel.box(plane, 'point', x=1, y=1), 0.3)`.
130
141
 
131
- Queries return plain Python values and leave nothing in the model:
142
+ Queries on the plate from the Example section return plain Python values
143
+ and leave nothing in the model:
132
144
 
133
145
  ```python
134
146
  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': ...}
147
+ mk.sel.find(geom, 'boundary', x=0) # [1]: the face at x = 0
148
+ mk.measure(geom, 'domain') # 99216.5: volume, approximate where curved
149
+ mk.bounding_box(geom, 'boundary', 3) # {'x': (0.0, 100.0), 'y': ..., 'z': (0.0, 0.0)}
150
+ mk.summary(geom) # counts, voids, bounding box, unit
151
+ mk.sel.neighbors(geom, 'domain', boundary=3) # [1]: the domain beside it
152
+ mk.coordinates(geom, 'boundary', 3) # {1: (0.0, 0.0, 0.0), 3: (0.0, 100.0, 0.0), ...}
153
+ ```
154
+
155
+ Pictures, written to a file:
156
+
157
+ ```python
158
+ mk.image(geom, 'geom.png') # the geometry
159
+ mk.image(geom, 'selection.png', selection, labels=True) # with numbers
138
160
  ```
139
161
 
140
162
  And a few helpers outside geometry:
@@ -144,21 +166,18 @@ mk.coordinate_system(geom, 'PML', selection=layer) # e.g. perfectly matched la
144
166
  mk.set(mesh_size, hmax=0.5, hgrad=2) # any node or Java object; converts ints and lists
145
167
  ```
146
168
 
147
- Arguments are COMSOL property names, so the COMSOL documentation of each
148
- feature applies. The docstrings describe each helper in detail.
149
-
150
169
  [`examples/plate_with_holes.py`](https://github.com/elgar328/mphkit/blob/main/examples/plate_with_holes.py)
151
170
  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.
171
+ a plate with a row of cooling holes, for one or more holes.
153
172
 
154
173
  ## Limitations
155
174
 
156
- - mphkit covers geometry and selections only. Physics, mesh, studies and
175
+ - mphkit covers geometry and selections. Physics, mesh, studies and
157
176
  results are left to MPh.
158
177
  - No named helpers yet for geometry parts (`PartInstance`), sweeps, cones
159
178
  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.
179
+ work through `mk.feature(geom, 'Sweep', ...)`, which handles arguments
180
+ like the named helpers (expressions, lists, nodes as inputs).
162
181
 
163
182
  ## Development
164
183
 
@@ -1,13 +1,18 @@
1
1
  # mphkit
2
2
 
3
+ [![PyPI](https://img.shields.io/pypi/v/mphkit)](https://pypi.org/project/mphkit/)
4
+ [![Python](https://img.shields.io/python/required-version-toml?tomlFilePath=https://raw.githubusercontent.com/elgar328/mphkit/main/pyproject.toml)](https://pypi.org/project/mphkit/)
5
+ [![License](https://img.shields.io/pypi/l/mphkit)](https://github.com/elgar328/mphkit/blob/main/LICENSE)
6
+ [![COMSOL](https://img.shields.io/badge/COMSOL-6.4-blue)](https://www.comsol.com/)
7
+
3
8
  Helpers on top of [MPh](https://github.com/MPh-py/MPh) for building COMSOL
4
9
  geometries and geometry-based selections in Python. Select boundaries by
5
10
  location instead of by entity number, so selections keep working when the
6
11
  geometry changes.
7
12
 
8
13
  > [!WARNING]
9
- > **Early stage.** mphkit is at an early stage of development. The API may
10
- > change at any time, without deprecation warnings.
14
+ > **Early stage.** The API may change at any time, without deprecation
15
+ > warnings.
11
16
 
12
17
  Not affiliated with COMSOL AB.
13
18
 
@@ -30,13 +35,18 @@ bottom = mk.sel.box(geom, 'boundary', z=0) # faces on the plane z = 0
30
35
 
31
36
  # plain MPh from here on
32
37
  physics = (model/'physics').create('HeatTransfer', geom)
33
- physics.create('TemperatureBoundary', 2).select(bottom)
38
+ physics.create('TemperatureBoundary', 2).select(bottom) # 2: boundaries in 3D
34
39
  model.save('demo.mph')
35
40
  ```
36
41
 
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`).
42
+ Helpers take MPh `Node`s (`mk.geometry` the model, `mk.set` also Java
43
+ objects), and those that create something return one, so mphkit and MPh
44
+ mix freely. Physics, mesh, study and results stay plain MPh (or the
45
+ COMSOL Java API through `node.java`).
46
+
47
+ `help(mphkit)` sums up the workflow, the rules and the common pitfalls,
48
+ and each helper has its own `help()`. Point an AI assistant to
49
+ `help(mphkit)` first.
40
50
 
41
51
  ## Requirements
42
52
 
@@ -47,10 +57,10 @@ plain MPh (or the COMSOL Java API through `node.java`).
47
57
  for CAD import (CAD Import Module, Design Module or a LiveLink).
48
58
  Everything else needs COMSOL only.
49
59
 
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.
60
+ mphkit is developed and tested with COMSOL 6.4 and MPh 1.4. Feature types,
61
+ property names and selection behavior can differ between COMSOL versions,
62
+ so other versions may need adjustments; reports are welcome. Checked on
63
+ macOS and Windows; it should run wherever MPh runs.
54
64
 
55
65
  ## Installation
56
66
 
@@ -72,7 +82,7 @@ mk.block(geom, (10, 10, 5)); mk.cylinder(geom, r, h, pos); mk.sphere(geom, r)
72
82
  mk.union(geom, [a, b]); mk.difference(geom, a, [b]); mk.intersection(geom, [a, b])
73
83
  mk.move(geom, part, (10, 0, 0)); mk.rotate(geom, part, 90, axis='z')
74
84
  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
85
+ mk.fillet(geom, part, 0.5); mk.chamfer(geom, part, 0.5) # all edges, or a selection
76
86
  mk.partition(geom, part, tool); mk.delete(geom, part)
77
87
  plane = mk.workplane(geom, quickz=0)
78
88
  mk.circle(plane, 2); mk.extrude(geom, plane, 5); mk.revolve(geom, plane)
@@ -95,16 +105,27 @@ mk.cylinder(geom, 1, 5, pos, contributeto=holes) # collect from several feature
95
105
  `where='geometry'` makes a selection inside the geometry sequence instead,
96
106
  for use as input of a later operation, e.g. `mk.sel.box(geom, 'object',
97
107
  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)`.
108
+ work plane, selections can pick single corners or edges, e.g. to fillet
109
+ one corner: `mk.fillet(plane, mk.sel.box(plane, 'point', x=1, y=1), 0.3)`.
100
110
 
101
- Queries return plain Python values and leave nothing in the model:
111
+ Queries on the plate from the Example section return plain Python values
112
+ and leave nothing in the model:
102
113
 
103
114
  ```python
104
115
  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': ...}
116
+ mk.sel.find(geom, 'boundary', x=0) # [1]: the face at x = 0
117
+ mk.measure(geom, 'domain') # 99216.5: volume, approximate where curved
118
+ mk.bounding_box(geom, 'boundary', 3) # {'x': (0.0, 100.0), 'y': ..., 'z': (0.0, 0.0)}
119
+ mk.summary(geom) # counts, voids, bounding box, unit
120
+ mk.sel.neighbors(geom, 'domain', boundary=3) # [1]: the domain beside it
121
+ mk.coordinates(geom, 'boundary', 3) # {1: (0.0, 0.0, 0.0), 3: (0.0, 100.0, 0.0), ...}
122
+ ```
123
+
124
+ Pictures, written to a file:
125
+
126
+ ```python
127
+ mk.image(geom, 'geom.png') # the geometry
128
+ mk.image(geom, 'selection.png', selection, labels=True) # with numbers
108
129
  ```
109
130
 
110
131
  And a few helpers outside geometry:
@@ -114,21 +135,18 @@ mk.coordinate_system(geom, 'PML', selection=layer) # e.g. perfectly matched la
114
135
  mk.set(mesh_size, hmax=0.5, hgrad=2) # any node or Java object; converts ints and lists
115
136
  ```
116
137
 
117
- Arguments are COMSOL property names, so the COMSOL documentation of each
118
- feature applies. The docstrings describe each helper in detail.
119
-
120
138
  [`examples/plate_with_holes.py`](https://github.com/elgar328/mphkit/blob/main/examples/plate_with_holes.py)
121
139
  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.
140
+ a plate with a row of cooling holes, for one or more holes.
123
141
 
124
142
  ## Limitations
125
143
 
126
- - mphkit covers geometry and selections only. Physics, mesh, studies and
144
+ - mphkit covers geometry and selections. Physics, mesh, studies and
127
145
  results are left to MPh.
128
146
  - No named helpers yet for geometry parts (`PartInstance`), sweeps, cones
129
147
  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.
148
+ work through `mk.feature(geom, 'Sweep', ...)`, which handles arguments
149
+ like the named helpers (expressions, lists, nodes as inputs).
132
150
 
133
151
  ## Development
134
152
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mphkit"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "Helpers on top of MPh for building COMSOL geometries and geometry-based selections in Python."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -30,6 +30,7 @@ classifiers = [
30
30
  "Programming Language :: Python :: 3.11",
31
31
  "Programming Language :: Python :: 3.12",
32
32
  "Programming Language :: Python :: 3.13",
33
+ "Programming Language :: Python :: 3.14",
33
34
  "Topic :: Scientific/Engineering",
34
35
  "Topic :: Scientific/Engineering :: Physics",
35
36
  "Typing :: Typed",
@@ -45,7 +46,10 @@ Changelog = "https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md"
45
46
  Issues = "https://github.com/elgar328/mphkit/issues"
46
47
 
47
48
  [dependency-groups]
48
- dev = ["pytest>=8"]
49
+ dev = [
50
+ "mypy>=2.3.1",
51
+ "pytest>=8",
52
+ ]
49
53
 
50
54
  [build-system]
51
55
  requires = ["uv_build>=0.9.9,<0.13"]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mphkit"
3
- version = "0.1.0"
3
+ version = "0.2.0"
4
4
  description = "Helpers on top of MPh for building COMSOL geometries and geometry-based selections in Python."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "elgar328" }]
@@ -21,6 +21,7 @@ classifiers = [
21
21
  "Programming Language :: Python :: 3.11",
22
22
  "Programming Language :: Python :: 3.12",
23
23
  "Programming Language :: Python :: 3.13",
24
+ "Programming Language :: Python :: 3.14",
24
25
  "Topic :: Scientific/Engineering",
25
26
  "Topic :: Scientific/Engineering :: Physics",
26
27
  "Typing :: Typed",
@@ -33,7 +34,10 @@ Changelog = "https://github.com/elgar328/mphkit/blob/main/CHANGELOG.md"
33
34
  Issues = "https://github.com/elgar328/mphkit/issues"
34
35
 
35
36
  [dependency-groups]
36
- dev = ["pytest>=8"]
37
+ dev = [
38
+ "mypy>=2.3.1",
39
+ "pytest>=8",
40
+ ]
37
41
 
38
42
  [build-system]
39
43
  requires = ["uv_build>=0.9.9,<0.13"]
@@ -0,0 +1,117 @@
1
+ """
2
+ Helpers on top of MPh for building COMSOL geometries and selections.
3
+
4
+ mphkit builds geometry and named selections; physics, mesh, studies and
5
+ results stay plain MPh (or the COMSOL Java API through `node.java`).
6
+ Helpers take MPh nodes (`mk.geometry` the model, `mk.set` also Java
7
+ objects), and those that create something return one.
8
+
9
+ import mph
10
+ import mphkit as mk
11
+
12
+ client = mph.start()
13
+ model = client.create('demo')
14
+ geom = mk.geometry(model, 3, length_unit='mm')
15
+ plate = mk.block(geom, (100, 100, 10))
16
+ hole = mk.cylinder(geom, 5, 10, (50, 50, 0))
17
+ mk.difference(geom, plate, [hole])
18
+ model.build(geom)
19
+ bottom = mk.sel.box(geom, 'boundary', z=0) # select by location
20
+ physics = (model/'physics').create('HeatTransfer', geom)
21
+ # 2: boundaries in 3D
22
+ physics.create('TemperatureBoundary', 2).select(bottom)
23
+
24
+ Rules:
25
+
26
+ - Select entities by location with `mk.sel` (box, ball, cylinder, disk,
27
+ adjacent, set operations), never by entity number: numbers change with
28
+ the geometry, selections are re-evaluated by COMSOL.
29
+ - Besides locations, `mk.sel.result` selects what a feature left in the
30
+ geometry and `mk.sel.cumulative` collects groups across operations
31
+ (features join with `contributeto=`).
32
+ - Entity kinds are COMSOL's: 'domain' (volumes in 3D, areas in 2D),
33
+ 'boundary' (faces in 3D, edges in 2D, where 'edge' means the same),
34
+ 'edge', 'point' (vertices). Physics features take the level as a
35
+ number: 3 for domains and 2 for boundaries in 3D, 2 and 1 in 2D.
36
+ - Objects that touch or overlap stay separate domains, even after
37
+ `mk.union`; merge them with `mk.union(geom, [a, b], intbnd=False)`,
38
+ which also removes layers and partition cuts of its inputs. A full
39
+ `mk.revolve` (no `angle`) keeps its cross-section as an interior face
40
+ unless `origfaces=False`.
41
+ - Extra keyword arguments are COMSOL property names (`intbnd`, `keep`,
42
+ `layername`, `base`, ...); an unknown name raises an error that often
43
+ suggests the right one.
44
+ - Sizes, positions, angles and counts may be numbers or COMSOL expressions
45
+ with parameters and units, e.g. `'L-2*t'` or `'5[mm]'`; define
46
+ parameters with `model.parameter('t', '0.3[mm]')`.
47
+ - Sizes and coordinates are in the geometry's length unit.
48
+ - Build the geometry (`model.build(geom)`) before querying it, and again
49
+ after adding a `where='geometry'` selection.
50
+
51
+ Check the result from code:
52
+
53
+ - `mk.sel.entities(geom, selection)`: entity numbers of a selection
54
+ - `mk.sel.find(geom, 'domain', x=...)`: entity numbers inside a box
55
+ - `mk.measure(geom, 'domain')`: volume, area or length
56
+ - `mk.bounding_box(geom, 'boundary', 3)`: extents
57
+ - `mk.summary(geom)`: counts, voids, size
58
+ - `mk.sel.neighbors(geom, 'domain', boundary=3)`: adjacent entities
59
+ - `mk.coordinates(geom, 'boundary', 3)`: vertex coordinates
60
+ - `mk.image(geom, 'geom.png')`: a picture of the geometry
61
+ - `mk.image(geom, 'selection.png', selection, labels=True)`: a selection
62
+ highlighted, with entity numbers
63
+
64
+ Curved entities are measured approximately (see `help(mk.measure)`).
65
+ `mk.measure` and `mk.bounding_box` use single precision, about seven
66
+ digits of the coordinates (`mk.bounding_box` of points excepted);
67
+ `mk.coordinates` and `mk.summary` use double precision. Compare with a
68
+ tolerance either way.
69
+
70
+ Selection tips: `mk.sel.result(geom, feature, 'boundary')` gives the faces
71
+ that an object and its copies leave in the geometry, curved ones
72
+ included, and the faces it cuts into other objects, e.g. the spherical
73
+ faces a subtracted sphere leaves in a block. Curved surfaces are split
74
+ into several faces: the side of a cylinder or cone, the wall of a hole or
75
+ of an extruded circle into four, a sphere into eight. For the side of a
76
+ cylinder that no other object cut, use a thin shell:
77
+ `mk.sel.cylinder(geom, 'boundary', pos, r, rin=0.99*r, bottom=0, top=h,
78
+ name='side')` (`rin` needs about 1 % room, see
79
+ `help(mk.sel.cylinder)`; a name avoids a clash with the cylinder's own
80
+ label).
81
+
82
+ More: `help(mk.sel)` for selections (also in work planes), `help(mk.block)`
83
+ etc. for each helper, `mk.feature(geom, 'Type', ...)` for any other
84
+ geometry feature, `mk.set(node_or_java, **properties)` to set properties
85
+ of anything else (mesh, study, material, probe), and `node.java` for the
86
+ rest of the COMSOL API.
87
+ """
88
+ import sys as _sys
89
+
90
+ from . import sel
91
+ from ._hints import HintModule as _HintModule
92
+ from ._image import image
93
+ from ._measure import bounding_box, coordinates, measure, summary
94
+ from ._props import set_ as set # not in __all__: keeps builtin set
95
+ from .errors import LicenseError
96
+ from .geometry import (array, block, chamfer, circle, component_of,
97
+ coordinate_system, cylinder, delete, difference,
98
+ extrude, feature, fillet, geometry, import_,
99
+ intersection, interval, line_segment, mirror, move,
100
+ partition, point, polygon, rectangle, revolve,
101
+ rigid_transform, rotate, sphere, square, union,
102
+ workplane)
103
+
104
+ __version__ = '0.2.0'
105
+
106
+ __all__ = ['LicenseError', 'array', 'block', 'bounding_box', 'chamfer',
107
+ 'circle', 'component_of', 'coordinate_system', 'coordinates',
108
+ 'cylinder', 'delete', 'difference', 'extrude', 'feature',
109
+ 'fillet', 'geometry', 'image', 'import_', 'intersection',
110
+ 'interval', 'line_segment', 'measure', 'mirror', 'move',
111
+ 'partition', 'point', 'polygon', 'rectangle', 'revolve',
112
+ 'rigid_transform', 'rotate', 'sel', 'sphere', 'square', 'summary',
113
+ 'union', 'workplane']
114
+
115
+ # Unknown names raise errors that name the right helper (see _hints).
116
+ _sys.modules[__name__].__class__ = _HintModule
117
+ del _sys, _HintModule