diff --git a/README.md b/README.md index 2b4b8fd..af4e3bc 100644 --- a/README.md +++ b/README.md @@ -16,19 +16,26 @@ Install requirements with ## Usage +Step2gmsh requires two diferent files: +- A json file where material properties are described for each geometry +- A step file with all the geometry info + +Both files must have the same label and share folder path. +An example of those files can be found in [Five wires case](testData/five_wires/) + Launch from command line as ```shell python src/step2gmsh.py <-i path_to_step_file> ``` -The tested input step files have been generated with [FreeCAD](https://www.freecad.org/). The geometrical entities within the step file must be separated in layers. The operations which are performed of the different layers depend on their name. +The tested input step files have been generated with [FreeCAD](https://www.freecad.org/). The geometrical entities within the step file must be separated in layers. The operations performed on the different layers depend on their material asignment registered in the json file. -- A layer named `Conductor_N` with `N` being an integer represents a perfect conductor. `Conductor_0` is a special case of which represents the ground and defines the global domain. For layers named `Conductor_N` with `N` different to zero their areas will be substracted from the computational domain and removed. -- Layers named as `Dielectric_N` are used to identify regions which will have a material assigned. +- A layer with a `PEC material`, represent a perfect conductor. In case one of the layers surrounds the rest of elements, it will be asigned as ground and defines the global domain for the rest of conductors. Internally, this will be represented as Conductor_0. The areas of the rest of conductors different to zero will be substracted from the computational domain and removed. In open cases, Conductor_0 is just another conductor and the domain is defined using the bounding box of the layers. +- Layers registered as `Dielectric` are used to identify regions which will have a material assigned. - Open and semi-open problems can be defined using a single layer called `OpenBoundary`. -Below is shown an example of a closed case with 6 conductors and 5 dielectrics, the external boundary corresponds to `Conductor_0`. The case is modeled with FreeCAD and can be found in the `testData/five_wires` folder together with the exported as a step file. The resulting mesh after applying `step2gmsh` is shown below. +Below is shown an example of a closed case with 6 conductors and 5 dielectrics, the external boundary corresponds to `Conductor_0`. The case is modeled with FreeCAD and can be found in the [testData/five_wires](testData/five_wires/) folder together with the exported as a step file. The resulting mesh after applying `step2gmsh` is shown below. ![Five wires example as modeled with FreeCAD](doc/fig/five_wires_freecad.png) ![Five wires example meshed with gmsh](doc/fig/five_wires_gmsh.png) diff --git a/test/test_mesher.py b/test/test_mesher.py index c371d0d..34d7cd1 100644 --- a/test/test_mesher.py +++ b/test/test_mesher.py @@ -268,13 +268,34 @@ def test_lansink2024_single_wire_multipolar(self): 'OpenBoundary_0', 'Vacuum_0', 'Vacuum_1'] expectedEntities = [1, 1, 1, - 1, 1, 1] self.assertEqual(sorted(pGNames), sorted(expectedNames)) for idx, name in enumerate(expectedNames): self.assertEqual(self.countEntitiesInPhysicalGroupWithName(name), expectedEntities[idx], name) + def test_unshielded_nesting(self): + caseName = 'UnshieldedNested' + Mesher().meshFromStep(self.inputFileFromCaseName(caseName), caseName) + + #gmsh.write(caseName + '.msh') + #gmsh.write(caseName + '.vtk') + + pGs = gmsh.model.getPhysicalGroups() + pGNames = [gmsh.model.getPhysicalName(*pG) for pG in pGs] + expectedNames = ['Conductor_0', + 'Conductor_1', + 'Conductor_2', + 'OpenBoundary_0', + 'Vacuum_0', 'Vacuum_1'] + expectedEntities = [2, 1, 1, + 1, + 2, 1] + self.assertEqual(sorted(pGNames), sorted(expectedNames)) + + for idx, name in enumerate(expectedNames): + self.assertEqual(self.countEntitiesInPhysicalGroupWithName(name), expectedEntities[idx], name) + if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/testData/UnshieldedNested/UnshieldedNested.FCStd b/testData/UnshieldedNested/UnshieldedNested.FCStd new file mode 100644 index 0000000..faae23a Binary files /dev/null and b/testData/UnshieldedNested/UnshieldedNested.FCStd differ diff --git a/testData/UnshieldedNested/UnshieldedNested.json b/testData/UnshieldedNested/UnshieldedNested.json new file mode 100644 index 0000000..8b81c7c --- /dev/null +++ b/testData/UnshieldedNested/UnshieldedNested.json @@ -0,0 +1,22 @@ +{ + "CrossSection":[ + { + "name":"Conductor_2", + "material":{ + "type":"PEC" + } + }, + { + "name":"Conductor_1", + "material":{ + "type":"PEC" + } + }, + { + "name":"ExtraConductor", + "material":{ + "type":"PEC" + } + } + ] +} \ No newline at end of file diff --git a/testData/UnshieldedNested/UnshieldedNested.step b/testData/UnshieldedNested/UnshieldedNested.step new file mode 100644 index 0000000..50b419d --- /dev/null +++ b/testData/UnshieldedNested/UnshieldedNested.step @@ -0,0 +1,230 @@ +ISO-10303-21; +HEADER; +FILE_DESCRIPTION(('FreeCAD Model'),'2;1'); +FILE_NAME('Open CASCADE Shape Model','2025-10-14T12:52:45',(''),(''), + 'Open CASCADE STEP processor 7.8','FreeCAD','Unknown'); +FILE_SCHEMA(('AUTOMOTIVE_DESIGN { 1 0 10303 214 1 1 1 1 }')); +ENDSEC; +DATA; +#1 = APPLICATION_PROTOCOL_DEFINITION('international standard', + 'automotive_design',2000,#2); +#2 = APPLICATION_CONTEXT( + 'core data for automotive mechanical design processes'); +#3 = SHAPE_DEFINITION_REPRESENTATION(#4,#10); +#4 = PRODUCT_DEFINITION_SHAPE('','',#5); +#5 = PRODUCT_DEFINITION('design','',#6,#9); +#6 = PRODUCT_DEFINITION_FORMATION('','',#7); +#7 = PRODUCT('nested_coax','nested_coax','',(#8)); +#8 = PRODUCT_CONTEXT('',#2,'mechanical'); +#9 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design'); +#10 = SHAPE_REPRESENTATION('',(#11,#15,#19,#23),#27); +#11 = AXIS2_PLACEMENT_3D('',#12,#13,#14); +#12 = CARTESIAN_POINT('',(0.,0.,0.)); +#13 = DIRECTION('',(0.,0.,1.)); +#14 = DIRECTION('',(1.,0.,-0.)); +#15 = AXIS2_PLACEMENT_3D('',#16,#17,#18); +#16 = CARTESIAN_POINT('',(0.,0.,0.)); +#17 = DIRECTION('',(0.,0.,1.)); +#18 = DIRECTION('',(1.,0.,0.)); +#19 = AXIS2_PLACEMENT_3D('',#20,#21,#22); +#20 = CARTESIAN_POINT('',(0.,0.,0.)); +#21 = DIRECTION('',(0.,0.,1.)); +#22 = DIRECTION('',(1.,0.,0.)); +#23 = AXIS2_PLACEMENT_3D('',#24,#25,#26); +#24 = CARTESIAN_POINT('',(5.,0.,0.)); +#25 = DIRECTION('',(0.,0.,1.)); +#26 = DIRECTION('',(1.,0.,0.)); +#27 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#31)) GLOBAL_UNIT_ASSIGNED_CONTEXT( +(#28,#29,#30)) REPRESENTATION_CONTEXT('Context #1', + '3D Context with UNIT and UNCERTAINTY') ); +#28 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); +#29 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); +#30 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() ); +#31 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#28, + 'distance_accuracy_value','confusion accuracy'); +#32 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#7)); +#33 = SHAPE_DEFINITION_REPRESENTATION(#34,#40); +#34 = PRODUCT_DEFINITION_SHAPE('','',#35); +#35 = PRODUCT_DEFINITION('design','',#36,#39); +#36 = PRODUCT_DEFINITION_FORMATION('','',#37); +#37 = PRODUCT('Conductor_1','Conductor_1','',(#38)); +#38 = PRODUCT_CONTEXT('',#2,'mechanical'); +#39 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design'); +#40 = MANIFOLD_SURFACE_SHAPE_REPRESENTATION('',(#11,#41),#71); +#41 = SHELL_BASED_SURFACE_MODEL('',(#42)); +#42 = OPEN_SHELL('',(#43)); +#43 = ADVANCED_FACE('',(#44,#55),#66,.T.); +#44 = FACE_BOUND('',#45,.T.); +#45 = EDGE_LOOP('',(#46)); +#46 = ORIENTED_EDGE('',*,*,#47,.T.); +#47 = EDGE_CURVE('',#48,#48,#50,.T.); +#48 = VERTEX_POINT('',#49); +#49 = CARTESIAN_POINT('',(2.8,0.,0.)); +#50 = CIRCLE('',#51,2.8); +#51 = AXIS2_PLACEMENT_3D('',#52,#53,#54); +#52 = CARTESIAN_POINT('',(0.,0.,0.)); +#53 = DIRECTION('',(0.,0.,1.)); +#54 = DIRECTION('',(1.,0.,0.)); +#55 = FACE_BOUND('',#56,.T.); +#56 = EDGE_LOOP('',(#57)); +#57 = ORIENTED_EDGE('',*,*,#58,.F.); +#58 = EDGE_CURVE('',#59,#59,#61,.T.); +#59 = VERTEX_POINT('',#60); +#60 = CARTESIAN_POINT('',(2.4,0.,0.)); +#61 = CIRCLE('',#62,2.4); +#62 = AXIS2_PLACEMENT_3D('',#63,#64,#65); +#63 = CARTESIAN_POINT('',(0.,0.,0.)); +#64 = DIRECTION('',(0.,0.,1.)); +#65 = DIRECTION('',(1.,0.,0.)); +#66 = PLANE('',#67); +#67 = AXIS2_PLACEMENT_3D('',#68,#69,#70); +#68 = CARTESIAN_POINT('',(-2.441857379535E-16,1.29885370033E-16,0.)); +#69 = DIRECTION('',(0.,0.,1.)); +#70 = DIRECTION('',(1.,0.,0.)); +#71 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#75)) GLOBAL_UNIT_ASSIGNED_CONTEXT( +(#72,#73,#74)) REPRESENTATION_CONTEXT('Context #1', + '3D Context with UNIT and UNCERTAINTY') ); +#72 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); +#73 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); +#74 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() ); +#75 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#72, + 'distance_accuracy_value','confusion accuracy'); +#76 = CONTEXT_DEPENDENT_SHAPE_REPRESENTATION(#77,#79); +#77 = ( REPRESENTATION_RELATIONSHIP('','',#40,#10) +REPRESENTATION_RELATIONSHIP_WITH_TRANSFORMATION(#78) +SHAPE_REPRESENTATION_RELATIONSHIP() ); +#78 = ITEM_DEFINED_TRANSFORMATION('','',#11,#15); +#79 = PRODUCT_DEFINITION_SHAPE('Placement','Placement of an item',#80); +#80 = NEXT_ASSEMBLY_USAGE_OCCURRENCE('1','Conductor_1','',#5,#35,$); +#81 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#37)); +#82 = SHAPE_DEFINITION_REPRESENTATION(#83,#89); +#83 = PRODUCT_DEFINITION_SHAPE('','',#84); +#84 = PRODUCT_DEFINITION('design','',#85,#88); +#85 = PRODUCT_DEFINITION_FORMATION('','',#86); +#86 = PRODUCT('Conductor_2','Conductor_2','',(#87)); +#87 = PRODUCT_CONTEXT('',#2,'mechanical'); +#88 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design'); +#89 = MANIFOLD_SURFACE_SHAPE_REPRESENTATION('',(#11,#90),#109); +#90 = SHELL_BASED_SURFACE_MODEL('',(#91)); +#91 = OPEN_SHELL('',(#92)); +#92 = ADVANCED_FACE('',(#93),#104,.T.); +#93 = FACE_BOUND('',#94,.T.); +#94 = EDGE_LOOP('',(#95)); +#95 = ORIENTED_EDGE('',*,*,#96,.T.); +#96 = EDGE_CURVE('',#97,#97,#99,.T.); +#97 = VERTEX_POINT('',#98); +#98 = CARTESIAN_POINT('',(1.,0.,0.)); +#99 = CIRCLE('',#100,1.); +#100 = AXIS2_PLACEMENT_3D('',#101,#102,#103); +#101 = CARTESIAN_POINT('',(0.,0.,0.)); +#102 = DIRECTION('',(0.,0.,1.)); +#103 = DIRECTION('',(1.,0.,-0.)); +#104 = PLANE('',#105); +#105 = AXIS2_PLACEMENT_3D('',#106,#107,#108); +#106 = CARTESIAN_POINT('',(-6.409875621279E-17,1.910944170279E-18,0.)); +#107 = DIRECTION('',(0.,0.,1.)); +#108 = DIRECTION('',(1.,0.,-0.)); +#109 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#113)) GLOBAL_UNIT_ASSIGNED_CONTEXT +((#110,#111,#112)) REPRESENTATION_CONTEXT('Context #1', + '3D Context with UNIT and UNCERTAINTY') ); +#110 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); +#111 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); +#112 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() ); +#113 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#110, + 'distance_accuracy_value','confusion accuracy'); +#114 = CONTEXT_DEPENDENT_SHAPE_REPRESENTATION(#115,#117); +#115 = ( REPRESENTATION_RELATIONSHIP('','',#89,#10) +REPRESENTATION_RELATIONSHIP_WITH_TRANSFORMATION(#116) +SHAPE_REPRESENTATION_RELATIONSHIP() ); +#116 = ITEM_DEFINED_TRANSFORMATION('','',#11,#19); +#117 = PRODUCT_DEFINITION_SHAPE('Placement','Placement of an item',#118 + ); +#118 = NEXT_ASSEMBLY_USAGE_OCCURRENCE('2','Conductor_2','',#5,#84,$); +#119 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#86)); +#120 = SHAPE_DEFINITION_REPRESENTATION(#121,#127); +#121 = PRODUCT_DEFINITION_SHAPE('','',#122); +#122 = PRODUCT_DEFINITION('design','',#123,#126); +#123 = PRODUCT_DEFINITION_FORMATION('','',#124); +#124 = PRODUCT('ExtraConductor','ExtraConductor','',(#125)); +#125 = PRODUCT_CONTEXT('',#2,'mechanical'); +#126 = PRODUCT_DEFINITION_CONTEXT('part definition',#2,'design'); +#127 = MANIFOLD_SURFACE_SHAPE_REPRESENTATION('',(#11,#128),#147); +#128 = SHELL_BASED_SURFACE_MODEL('',(#129)); +#129 = OPEN_SHELL('',(#130)); +#130 = ADVANCED_FACE('',(#131),#142,.T.); +#131 = FACE_BOUND('',#132,.T.); +#132 = EDGE_LOOP('',(#133)); +#133 = ORIENTED_EDGE('',*,*,#134,.T.); +#134 = EDGE_CURVE('',#135,#135,#137,.T.); +#135 = VERTEX_POINT('',#136); +#136 = CARTESIAN_POINT('',(1.,0.,0.)); +#137 = CIRCLE('',#138,1.); +#138 = AXIS2_PLACEMENT_3D('',#139,#140,#141); +#139 = CARTESIAN_POINT('',(0.,0.,0.)); +#140 = DIRECTION('',(0.,0.,1.)); +#141 = DIRECTION('',(1.,0.,0.)); +#142 = PLANE('',#143); +#143 = AXIS2_PLACEMENT_3D('',#144,#145,#146); +#144 = CARTESIAN_POINT('',(-6.409875621279E-17,1.910944170279E-18,0.)); +#145 = DIRECTION('',(0.,0.,1.)); +#146 = DIRECTION('',(1.,0.,0.)); +#147 = ( GEOMETRIC_REPRESENTATION_CONTEXT(3) +GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#151)) GLOBAL_UNIT_ASSIGNED_CONTEXT +((#148,#149,#150)) REPRESENTATION_CONTEXT('Context #1', + '3D Context with UNIT and UNCERTAINTY') ); +#148 = ( LENGTH_UNIT() NAMED_UNIT(*) SI_UNIT(.MILLI.,.METRE.) ); +#149 = ( NAMED_UNIT(*) PLANE_ANGLE_UNIT() SI_UNIT($,.RADIAN.) ); +#150 = ( NAMED_UNIT(*) SI_UNIT($,.STERADIAN.) SOLID_ANGLE_UNIT() ); +#151 = UNCERTAINTY_MEASURE_WITH_UNIT(LENGTH_MEASURE(1.E-07),#148, + 'distance_accuracy_value','confusion accuracy'); +#152 = CONTEXT_DEPENDENT_SHAPE_REPRESENTATION(#153,#155); +#153 = ( REPRESENTATION_RELATIONSHIP('','',#127,#10) +REPRESENTATION_RELATIONSHIP_WITH_TRANSFORMATION(#154) +SHAPE_REPRESENTATION_RELATIONSHIP() ); +#154 = ITEM_DEFINED_TRANSFORMATION('','',#11,#23); +#155 = PRODUCT_DEFINITION_SHAPE('Placement','Placement of an item',#156 + ); +#156 = NEXT_ASSEMBLY_USAGE_OCCURRENCE('3','ExtraConductor','',#5,#122,$ + ); +#157 = PRODUCT_RELATED_PRODUCT_CATEGORY('part',$,(#124)); +#158 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#159) + ,#109); +#159 = STYLED_ITEM('color',(#160),#92); +#160 = PRESENTATION_STYLE_ASSIGNMENT((#161,#167)); +#161 = SURFACE_STYLE_USAGE(.BOTH.,#162); +#162 = SURFACE_SIDE_STYLE('',(#163)); +#163 = SURFACE_STYLE_FILL_AREA(#164); +#164 = FILL_AREA_STYLE('',(#165)); +#165 = FILL_AREA_STYLE_COLOUR('',#166); +#166 = COLOUR_RGB('',0.800000010877,0.800000010877,0.800000010877); +#167 = CURVE_STYLE('',#168,POSITIVE_LENGTH_MEASURE(0.1),#169); +#168 = DRAUGHTING_PRE_DEFINED_CURVE_FONT('continuous'); +#169 = COLOUR_RGB('',9.803921802644E-02,9.803921802644E-02, + 9.803921802644E-02); +#170 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#171) + ,#147); +#171 = STYLED_ITEM('color',(#172),#130); +#172 = PRESENTATION_STYLE_ASSIGNMENT((#173,#178)); +#173 = SURFACE_STYLE_USAGE(.BOTH.,#174); +#174 = SURFACE_SIDE_STYLE('',(#175)); +#175 = SURFACE_STYLE_FILL_AREA(#176); +#176 = FILL_AREA_STYLE('',(#177)); +#177 = FILL_AREA_STYLE_COLOUR('',#166); +#178 = CURVE_STYLE('',#179,POSITIVE_LENGTH_MEASURE(0.1),#169); +#179 = DRAUGHTING_PRE_DEFINED_CURVE_FONT('continuous'); +#180 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION('',(#181) + ,#71); +#181 = STYLED_ITEM('color',(#182),#43); +#182 = PRESENTATION_STYLE_ASSIGNMENT((#183,#188)); +#183 = SURFACE_STYLE_USAGE(.BOTH.,#184); +#184 = SURFACE_SIDE_STYLE('',(#185)); +#185 = SURFACE_STYLE_FILL_AREA(#186); +#186 = FILL_AREA_STYLE('',(#187)); +#187 = FILL_AREA_STYLE_COLOUR('',#166); +#188 = CURVE_STYLE('',#189,POSITIVE_LENGTH_MEASURE(0.1),#169); +#189 = DRAUGHTING_PRE_DEFINED_CURVE_FONT('continuous'); +ENDSEC; +END-ISO-10303-21;