Skip to content

Commit 2882872

Browse files
authored
Merge pull request #13 from OpenSEMBA/feature/unshielded-multiwires
Changes near vacuum to a rectangle
2 parents 2f7aa7e + 775558c commit 2882872

File tree

7 files changed

+294
-56
lines changed

7 files changed

+294
-56
lines changed

src/BoundingBox.py

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,42 @@
44

55
class BoundingBox():
66
edges: Dict[str, float]
7-
def __init__(self, listOfCoordinates:Tuple[int, int, int, int, int, int]):
7+
def __init__(self, listOfCoordinates:Tuple[float,float,float,float,float,float]):
88
self.edges = {
9-
'xmin': listOfCoordinates[0],
10-
'ymin': listOfCoordinates[1],
11-
'zmin': listOfCoordinates[2],
12-
'xmax': listOfCoordinates[3],
13-
'ymax': listOfCoordinates[4],
14-
'zmax': listOfCoordinates[5],
9+
'XMin': listOfCoordinates[0],
10+
'YMin': listOfCoordinates[1],
11+
'ZMin': listOfCoordinates[2],
12+
'XMax': listOfCoordinates[3],
13+
'YMax': listOfCoordinates[4],
14+
'ZMax': listOfCoordinates[5],
1515
}
1616

17+
def getOrigin(self) -> Tuple[float,float,float]:
18+
return (
19+
self.edges['XMin'],
20+
self.edges['YMin'],
21+
self.edges['ZMin']
22+
)
23+
1724
def getCenter(self) -> Tuple[float,float,float]:
1825
return (
19-
(self.edges['xmax'] + self.edges['xmin']) / 2,
20-
(self.edges['ymax'] + self.edges['ymin']) / 2,
21-
(self.edges['zmax'] + self.edges['zmin']) / 2
26+
(self.edges['XMax'] + self.edges['XMin']) / 2,
27+
(self.edges['YMax'] + self.edges['YMin']) / 2,
28+
(self.edges['ZMax'] + self.edges['ZMin']) / 2
2229
)
2330
def getDiagonal(self) -> float:
24-
dx = self.edges['xmax'] - self.edges['xmin']
25-
dy = self.edges['ymax'] - self.edges['ymin']
26-
dz = self.edges['zmax'] - self.edges['zmin']
31+
dx = self.edges['XMax'] - self.edges['XMin']
32+
dy = self.edges['YMax'] - self.edges['YMin']
33+
dz = self.edges['ZMax'] - self.edges['ZMin']
2734
return (dx**2 + dy**2 + dz**2) ** 0.5
2835

36+
def getLengths(self) -> Tuple[float, float, float]:
37+
return (
38+
self.edges['XMax'] - self.edges['XMin'],
39+
self.edges['YMax'] - self.edges['YMin'],
40+
self.edges['ZMax'] - self.edges['ZMin']
41+
)
42+
2943
@staticmethod
3044
def _getBoundingBox(element:Tuple[int,int]) -> 'BoundingBox':
3145
boundingBox:BoundingBox = BoundingBox(gmsh.model.occ.get_bounding_box(*element))
@@ -39,25 +53,25 @@ def getBoundingBoxFromGroup(elements:List[Tuple[int,int]]) -> 'BoundingBox':
3953

4054
if len(boundingBoxs) != 0:
4155
edges: Dict[str, List[float]] = {
42-
'xmin': [],
43-
'ymin': [],
44-
'zmin': [],
45-
'xmax': [],
46-
'ymax': [],
47-
'zmax': [],
56+
'XMin': [],
57+
'YMin': [],
58+
'ZMin': [],
59+
'XMax': [],
60+
'YMax': [],
61+
'ZMax': [],
4862
}
4963
for boundingBox in boundingBoxs:
5064
for key in edges.keys():
5165
edges[key].append(boundingBox.edges[key])
5266

5367
return BoundingBox(
5468
(
55-
utils.getMinFromList(edges['xmin']),
56-
utils.getMinFromList(edges['ymin']),
57-
utils.getMinFromList(edges['zmin']),
58-
utils.getMaxFromList(edges['xmax']),
59-
utils.getMaxFromList(edges['ymax']),
60-
utils.getMaxFromList(edges['zmax'])
69+
utils.getMinFromList(edges['XMin']),
70+
utils.getMinFromList(edges['YMin']),
71+
utils.getMinFromList(edges['ZMin']),
72+
utils.getMaxFromList(edges['XMax']),
73+
utils.getMaxFromList(edges['YMax']),
74+
utils.getMaxFromList(edges['ZMax'])
6175
)
6276
)
6377
else:

src/ShapesClassification.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import gmsh
44
from .BoundingBox import BoundingBox
55
from itertools import chain
6+
import numpy as np
67

78
class ShapesClassification:
89
isOpenCase:bool
@@ -87,12 +88,12 @@ def buildVacuumDomain(self):
8788
if self.isOpenCase and len(self.open) == 0:
8889
self.vacuum = self._buildDefaultVacuumDomain()
8990
elif self.isOpenCase and len(self.open) > 0:
90-
self.vacuum = self._buildOpenVacuumDomain()
91+
self.vacuum = self._buildVacuumDomainFromOpenBoundary()
9192
else:
9293
self.vacuum = self._buildClosedVacuumDomain()
9394
return self.vacuum
9495

95-
def _buildOpenVacuumDomain(self) -> Dict[int, List[int]]:
96+
def _buildVacuumDomainFromOpenBoundary(self) -> Dict[int, List[int]]:
9697
dom = self.open[0]
9798

9899
surfsToRemove = []
@@ -131,14 +132,18 @@ def _buildDefaultVacuumDomain(self):
131132
nonVacuumSurfaces.extend(surf)
132133

133134
boundingBox = BoundingBox.getBoundingBoxFromGroup(nonVacuumSurfaces)
134-
boundingBoxCenter = boundingBox.getCenter()
135-
boundingBoxDiagonal = boundingBox.getDiagonal()
136135

137-
nearVacuumDiameter = boundingBoxDiagonal
138-
nearVacuum = [(2, gmsh.model.occ.addDisk(*boundingBoxCenter, nearVacuumDiameter, nearVacuumDiameter))]
139-
140-
farVacuumDiameter = 4*boundingBoxDiagonal
141-
farVacuum = [(2, gmsh.model.occ.addDisk(*boundingBoxCenter, farVacuumDiameter, farVacuumDiameter))]
136+
137+
bbMaxLength = np.max(boundingBox.getLengths())
138+
nVOrigin = tuple(
139+
np.subtract(boundingBox.getCenter(),
140+
(bbMaxLength, bbMaxLength, 0.0)))
141+
nearVacuum = [(2, gmsh.model.occ.addRectangle(*nVOrigin, *(bbMaxLength*2.0,)*2))]
142+
143+
farVacuumDiameter = 4.0 * boundingBox.getDiagonal()
144+
farVacuum = [(2, gmsh.model.occ.addDisk(
145+
*boundingBox.getCenter(),
146+
farVacuumDiameter, farVacuumDiameter))]
142147

143148
gmsh.model.occ.synchronize()
144149

@@ -148,8 +153,16 @@ def _buildDefaultVacuumDomain(self):
148153
nearVacuum = gmsh.model.occ.cut(
149154
nearVacuum, nonVacuumSurfaces, removeObject=True, removeTool=False)[0]
150155

151-
self.open = dict([[0, gmsh.model.getBoundary(farVacuum)]])
156+
# -- Set mesh size for near vacuum region
157+
bb = BoundingBox(
158+
gmsh.model.getBoundingBox(2, nearVacuum[0][1]))
159+
minSide = np.min(np.array([bb.getLengths()[0], bb.getLengths()[1]]))
152160

161+
innerRegion = gmsh.model.getBoundary(nearVacuum, recursive=True)
162+
gmsh.model.mesh.setSize(innerRegion, minSide / 20)
163+
164+
165+
self.open = dict([[0, gmsh.model.getBoundary(farVacuum)]])
153166
gmsh.model.occ.synchronize()
154167

155168
return dict([[0, nearVacuum], [1, farVacuum]])

src/mesher.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,18 @@
55

66
from src.AreaExporterService import AreaExporterService
77
from .ShapesClassification import ShapesClassification
8+
from .BoundingBox import BoundingBox
9+
import numpy as np
810

911
class Mesher():
1012
DEFAULT_MESHING_OPTIONS = {
1113

12-
"Mesh.MshFileVersion": 2.2, # Mandatory for MFEM compatibility
14+
"Mesh.MshFileVersion": 2.2, # Required for MFEM compatibility
1315
"Mesh.MeshSizeFromCurvature": 50,
1416
"Mesh.ElementOrder": 3,
1517
"Mesh.ScalingFactor": 1e-3,
1618
"Mesh.SurfaceFaces": 1,
17-
"Mesh.MeshSizeMax": 50,
19+
"Mesh.MeshSizeMax": 40,
1820

1921
"General.DrawBoundingBoxes": 1,
2022
"General.Axes": 1,
@@ -32,7 +34,7 @@ def runFromInput(self, inputFile, runGui=False):
3234
self.meshFromStep(inputFile, caseName, self.DEFAULT_MESHING_OPTIONS)
3335
self.exportGeometryAreas(caseName)
3436
gmsh.write(caseName + '.msh')
35-
gmsh.write(caseName + '.vtk')
37+
gmsh.write(caseName + '.vtk') # vtk export is just for debugging.
3638
if runGui:
3739
gmsh.fltk.run()
3840

@@ -64,6 +66,8 @@ def meshFromStep(self, inputFile: str, caseName: str, meshingOptions=None):
6466
for [opt, val] in meshingOptions.items():
6567
gmsh.option.setNumber(opt, val)
6668

69+
# --- Mesh generation ---
70+
6771
gmsh.model.mesh.generate(2)
6872

6973
def exportGeometryAreas(self, caseName:str):

test/test_BoundingBox.py

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,24 @@ class testBoundingBox(unittest.TestCase):
1010
def testCanDefineBoundingBox(self):
1111
inputExample = (-1, 2.0, 3, 5, 6, 7)
1212
expectedBoundingBoxEdges: Dict[str, float] = {
13-
'xmin': -1,
14-
'ymin': 2.0,
15-
'zmin': 3,
16-
'xmax': 5,
17-
'ymax': 6,
18-
'zmax': 7,
13+
'XMin': -1,
14+
'YMin': 2.0,
15+
'ZMin': 3,
16+
'XMax': 5,
17+
'YMax': 6,
18+
'ZMax': 7,
1919
}
2020
boundingBox = BoundingBox(inputExample)
2121
self.assertDictEqual(boundingBox.edges, expectedBoundingBoxEdges)
2222

2323
def testCanGetBoundingBoxFromSurface(self):
2424
expectedBoundingBoxEdges: Dict[str, float] = {
25-
'xmin': -10,
26-
'ymin': -10,
27-
'zmin': 0,
28-
'xmax': 10,
29-
'ymax': 10,
30-
'zmax': 0,
25+
'XMin': -10,
26+
'YMin': -10,
27+
'ZMin': 0,
28+
'XMax': 10,
29+
'YMax': 10,
30+
'ZMax': 0,
3131
}
3232

3333
gmsh.initialize()
@@ -39,12 +39,12 @@ def testCanGetBoundingBoxFromSurface(self):
3939

4040
def testCanGetBoundingBoxFromListOfSurfaces(self):
4141
expectedBoundingBoxEdges: Dict[str, float] = {
42-
'xmin': -10,
43-
'ymin': -10,
44-
'zmin': 0,
45-
'xmax': 35,
46-
'ymax': 40,
47-
'zmax': 0,
42+
'XMin': -10,
43+
'YMin': -10,
44+
'ZMin': 0,
45+
'XMax': 35,
46+
'YMax': 40,
47+
'ZMax': 0,
4848
}
4949

5050
gmsh.initialize()

test/test_mesher.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,8 @@ def test_unshielded_multiwire(self):
223223
caseName = 'unshielded_multiwire'
224224
Mesher().meshFromStep(self.inputFileFromCaseName(caseName), caseName)
225225

226+
gmsh.write(caseName + '.vtk')
227+
226228
pGs = gmsh.model.getPhysicalGroups()
227229
pGNames = [gmsh.model.getPhysicalName(*pG) for pG in pGs]
228230
expectedNames = ['Conductor_0', 'Conductor_1', 'Dielectric_1',
@@ -236,5 +238,27 @@ def test_unshielded_multiwire(self):
236238
for idx, name in enumerate(expectedNames):
237239
self.assertEqual(self.countEntitiesInPhysicalGroupWithName(name), expectedEntities[idx], name)
238240

241+
def test_lansink2024_single_wire_multipolar(self):
242+
caseName = 'lansink2024_single_wire_multipolar'
243+
Mesher().meshFromStep(self.inputFileFromCaseName(caseName), caseName)
244+
245+
gmsh.write(caseName + '.msh')
246+
gmsh.write(caseName + '.vtk')
247+
248+
pGs = gmsh.model.getPhysicalGroups()
249+
pGNames = [gmsh.model.getPhysicalName(*pG) for pG in pGs]
250+
expectedNames = ['Conductor_0',
251+
'Dielectric_0',
252+
'OpenBoundary_0',
253+
'Vacuum_0', 'Vacuum_1']
254+
expectedEntities = [1, 1, 1,
255+
1,
256+
1, 1]
257+
self.assertEqual(sorted(pGNames), sorted(expectedNames))
258+
259+
for idx, name in enumerate(expectedNames):
260+
self.assertEqual(self.countEntitiesInPhysicalGroupWithName(name), expectedEntities[idx], name)
261+
262+
239263
if __name__ == '__main__':
240264
unittest.main()
Binary file not shown.

0 commit comments

Comments
 (0)