1111import { basicLog , debugLog , errorLog } from "../utilities/loggingScript.js" ;
1212
1313/**
14- * Function to import mesh data from Gmsh format containing quadrilateral and triangular elements
15- * @param {File } file - The Gmsh file to be parsed (.msh version 4.1)
16- * @returns {object } The parsed mesh data including node coordinates, element connectivity, and boundary conditions
14+ * Function to import mesh data from Gmsh (.msh v4.1) containing quadrilateral and triangular elements
15+ * @param {File } file
16+ * @returns {object }
1717 */
1818const importGmshQuadTri = async ( file ) => {
1919 let result = {
@@ -25,7 +25,7 @@ const importGmshQuadTri = async (file) => {
2525 } ,
2626 boundaryElements : [ ] ,
2727 boundaryConditions : [ ] ,
28- boundaryNodePairs : { } , // Store boundary node pairs for processing in meshGenerationScript
28+ boundaryNodePairs : { } ,
2929 gmshV : 0 ,
3030 ascii : false ,
3131 fltBytes : "8" ,
@@ -35,175 +35,194 @@ const importGmshQuadTri = async (file) => {
3535 elementTypes : { } ,
3636 } ;
3737
38+ // Entities to physical tags map
39+ const entityPhysicalMap = { curves : { } } ;
40+
3841 let content = await file . text ( ) ;
3942 let lines = content
4043 . split ( "\n" )
41- . map ( ( line ) => line . trim ( ) )
42- . filter ( ( line ) => line !== "" && line !== " ") ;
44+ . map ( ( l ) => l . trim ( ) )
45+ . filter ( ( l ) => l !== "" ) ;
4346
4447 let section = "" ;
4548 let lineIndex = 0 ;
4649
50+ // Nodes
4751 let nodeEntityBlocks = 0 ;
4852 let totalNodes = 0 ;
4953 let nodeBlocksProcessed = 0 ;
5054 let currentNodeBlock = { numNodes : 0 } ;
51- let nodeTagsCollected = 0 ;
5255 let nodeTags = [ ] ;
56+ let nodeTagsCollected = 0 ;
5357 let nodeCoordinatesCollected = 0 ;
5458
59+ // Elements
5560 let elementEntityBlocks = 0 ;
5661 let totalElements = 0 ;
5762 let elementBlocksProcessed = 0 ;
58- let currentElementBlock = {
59- dim : 0 ,
60- tag : 0 ,
61- elementType : 0 ,
62- numElements : 0 ,
63- } ;
63+ let currentElementBlock = { numElements : 0 } ;
6464 let elementsProcessedInBlock = 0 ;
6565
6666 let boundaryElementsByTag = { } ;
6767
68+ // Entities helpers
69+ let entityCounts = null ;
70+ let entitiesPhase = null ;
71+ let processedPoints = 0 ;
72+ let processedCurves = 0 ;
73+ let processedSurfaces = 0 ;
74+ let processedVolumes = 0 ;
75+
6876 while ( lineIndex < lines . length ) {
6977 const line = lines [ lineIndex ] ;
7078
79+ // Section switches
7180 if ( line === "$MeshFormat" ) {
7281 section = "meshFormat" ;
7382 lineIndex ++ ;
7483 continue ;
75- } else if ( line === "$EndMeshFormat" ) {
84+ }
85+ if ( line === "$EndMeshFormat" ) {
7686 section = "" ;
7787 lineIndex ++ ;
7888 continue ;
79- } else if ( line === "$PhysicalNames" ) {
89+ }
90+ if ( line === "$PhysicalNames" ) {
8091 section = "physicalNames" ;
8192 lineIndex ++ ;
8293 continue ;
83- } else if ( line === "$EndPhysicalNames" ) {
94+ }
95+ if ( line === "$EndPhysicalNames" ) {
8496 section = "" ;
8597 lineIndex ++ ;
8698 continue ;
87- } else if ( line === "$Entities" ) {
99+ }
100+ if ( line === "$Entities" ) {
88101 section = "entities" ;
102+ entitiesPhase = "counts" ;
89103 lineIndex ++ ;
90104 continue ;
91- } else if ( line === "$EndEntities" ) {
105+ }
106+ if ( line === "$EndEntities" ) {
92107 section = "" ;
108+ entityCounts = null ;
109+ entitiesPhase = null ;
93110 lineIndex ++ ;
94111 continue ;
95- } else if ( line === "$Nodes" ) {
112+ }
113+ if ( line === "$Nodes" ) {
96114 section = "nodes" ;
97115 lineIndex ++ ;
98116 continue ;
99- } else if ( line === "$EndNodes" ) {
117+ }
118+ if ( line === "$EndNodes" ) {
100119 section = "" ;
101120 lineIndex ++ ;
102121 continue ;
103- } else if ( line === "$Elements" ) {
122+ }
123+ if ( line === "$Elements" ) {
104124 section = "elements" ;
105125 lineIndex ++ ;
106126 continue ;
107- } else if ( line === "$EndElements" ) {
127+ }
128+ if ( line === "$EndElements" ) {
108129 section = "" ;
109130 lineIndex ++ ;
110131 continue ;
111132 }
112133
113- const parts = line . split ( / \s + / ) . filter ( ( part ) => part !== "" ) ;
134+ const parts = line . split ( / \s + / ) ;
114135
136+ // Mesh format
115137 if ( section === "meshFormat" ) {
116138 result . gmshV = parseFloat ( parts [ 0 ] ) ;
117139 result . ascii = parts [ 1 ] === "0" ;
118140 result . fltBytes = parts [ 2 ] ;
119- } else if ( section === "physicalNames" ) {
120- if ( parts . length >= 3 ) {
121- if ( ! / ^ \d + $ / . test ( parts [ 0 ] ) ) {
122- lineIndex ++ ;
123- continue ;
124- }
141+ }
125142
126- const dimension = parseInt ( parts [ 0 ] , 10 ) ;
127- const tag = parseInt ( parts [ 1 ] , 10 ) ;
128- let name = parts . slice ( 2 ) . join ( " " ) ;
129- name = name . replace ( / ^ " | " $ / g, "" ) ;
143+ // Physical names
144+ else if ( section === "physicalNames" ) {
145+ const dimension = parseInt ( parts [ 0 ] , 10 ) ;
146+ const tag = parseInt ( parts [ 1 ] , 10 ) ;
147+ let name = parts . slice ( 2 ) . join ( " " ) . replace ( / ^ " | " $ / g, "" ) ;
130148
131- result . physicalPropMap . push ( {
132- tag,
133- dimension,
134- name,
135- } ) ;
149+ result . physicalPropMap . push ( { tag, dimension, name } ) ;
150+ }
151+
152+ // Entities
153+ else if ( section === "entities" ) {
154+ if ( entitiesPhase === "counts" ) {
155+ entityCounts = {
156+ points : parseInt ( parts [ 0 ] , 10 ) ,
157+ curves : parseInt ( parts [ 1 ] , 10 ) ,
158+ surfaces : parseInt ( parts [ 2 ] , 10 ) ,
159+ volumes : parseInt ( parts [ 3 ] , 10 ) ,
160+ } ;
161+ entitiesPhase = "points" ;
162+ } else if ( entitiesPhase === "points" ) {
163+ processedPoints ++ ;
164+ if ( processedPoints === entityCounts . points ) entitiesPhase = "curves" ;
165+ } else if ( entitiesPhase === "curves" ) {
166+ const tag = parseInt ( parts [ 0 ] , 10 ) ;
167+ const numPhysical = parseInt ( parts [ 7 ] , 10 ) ;
168+ const physTags = parts . slice ( 8 , 8 + numPhysical ) . map ( ( p ) => parseInt ( p , 10 ) ) ;
169+ entityPhysicalMap . curves [ tag ] = physTags ;
170+ processedCurves ++ ;
171+ if ( processedCurves === entityCounts . curves ) entitiesPhase = "surfaces" ;
172+ } else if ( entitiesPhase === "surfaces" ) {
173+ processedSurfaces ++ ;
174+ if ( processedSurfaces === entityCounts . surfaces ) entitiesPhase = "volumes" ;
175+ } else if ( entitiesPhase === "volumes" ) {
176+ processedVolumes ++ ;
136177 }
137- } else if ( section === "nodes" ) {
178+ }
179+
180+ // Nodes
181+ else if ( section === "nodes" ) {
138182 if ( nodeEntityBlocks === 0 ) {
139183 nodeEntityBlocks = parseInt ( parts [ 0 ] , 10 ) ;
140184 totalNodes = parseInt ( parts [ 1 ] , 10 ) ;
141185 result . nodesXCoordinates = new Array ( totalNodes ) . fill ( 0 ) ;
142186 result . nodesYCoordinates = new Array ( totalNodes ) . fill ( 0 ) ;
143- lineIndex ++ ;
144- continue ;
145- }
146-
147- if ( nodeBlocksProcessed < nodeEntityBlocks && currentNodeBlock . numNodes === 0 ) {
187+ } else if ( nodeBlocksProcessed < nodeEntityBlocks && currentNodeBlock . numNodes === 0 ) {
148188 currentNodeBlock = {
149189 dim : parseInt ( parts [ 0 ] , 10 ) ,
150190 tag : parseInt ( parts [ 1 ] , 10 ) ,
151191 parametric : parseInt ( parts [ 2 ] , 10 ) ,
152192 numNodes : parseInt ( parts [ 3 ] , 10 ) ,
153193 } ;
154-
155194 nodeTags = [ ] ;
156195 nodeTagsCollected = 0 ;
157196 nodeCoordinatesCollected = 0 ;
158-
159- lineIndex ++ ;
160- continue ;
161- }
162-
163- if ( nodeTagsCollected < currentNodeBlock . numNodes ) {
164- for ( let i = 0 ; i < parts . length && nodeTagsCollected < currentNodeBlock . numNodes ; i ++ ) {
165- nodeTags . push ( parseInt ( parts [ i ] , 10 ) ) ;
197+ } else if ( nodeTagsCollected < currentNodeBlock . numNodes ) {
198+ for ( let p of parts ) {
199+ nodeTags . push ( parseInt ( p , 10 ) ) ;
166200 nodeTagsCollected ++ ;
201+ if ( nodeTagsCollected === currentNodeBlock . numNodes ) break ;
167202 }
168-
169- if ( nodeTagsCollected < currentNodeBlock . numNodes ) {
170- lineIndex ++ ;
171- continue ;
172- }
173-
174- lineIndex ++ ;
175- continue ;
176- }
177-
178- if ( nodeCoordinatesCollected < currentNodeBlock . numNodes ) {
203+ } else if ( nodeCoordinatesCollected < currentNodeBlock . numNodes ) {
179204 const nodeTag = nodeTags [ nodeCoordinatesCollected ] - 1 ;
180- const x = parseFloat ( parts [ 0 ] ) ;
181- const y = parseFloat ( parts [ 1 ] ) ;
182-
183- result . nodesXCoordinates [ nodeTag ] = x ;
184- result . nodesYCoordinates [ nodeTag ] = y ;
205+ result . nodesXCoordinates [ nodeTag ] = parseFloat ( parts [ 0 ] ) ;
206+ result . nodesYCoordinates [ nodeTag ] = parseFloat ( parts [ 1 ] ) ;
185207 result . totalNodesX ++ ;
186208 result . totalNodesY ++ ;
187-
188209 nodeCoordinatesCollected ++ ;
189-
190210 if ( nodeCoordinatesCollected === currentNodeBlock . numNodes ) {
191211 nodeBlocksProcessed ++ ;
192212 currentNodeBlock = { numNodes : 0 } ;
193213 }
194214 }
195- } else if ( section === "elements" ) {
215+ }
216+
217+ // Elements
218+ else if ( section === "elements" ) {
196219 if ( elementEntityBlocks === 0 ) {
197220 elementEntityBlocks = parseInt ( parts [ 0 ] , 10 ) ;
198221 totalElements = parseInt ( parts [ 1 ] , 10 ) ;
199- lineIndex ++ ;
200- continue ;
201- }
202-
203- if ( elementBlocksProcessed < elementEntityBlocks && currentElementBlock . numElements === 0 ) {
222+ } else if ( elementBlocksProcessed < elementEntityBlocks && currentElementBlock . numElements === 0 ) {
204223 currentElementBlock = {
205224 dim : parseInt ( parts [ 0 ] , 10 ) ,
206- tag : parseInt ( parts [ 1 ] , 10 ) ,
225+ tag : parseInt ( parts [ 1 ] , 10 ) , // entity tag
207226 elementType : parseInt ( parts [ 2 ] , 10 ) ,
208227 numElements : parseInt ( parts [ 3 ] , 10 ) ,
209228 } ;
@@ -212,41 +231,29 @@ const importGmshQuadTri = async (file) => {
212231 ( result . elementTypes [ currentElementBlock . elementType ] || 0 ) + currentElementBlock . numElements ;
213232
214233 elementsProcessedInBlock = 0 ;
215- lineIndex ++ ;
216- continue ;
217- }
218-
219- if ( elementsProcessedInBlock < currentElementBlock . numElements ) {
220- const elementTag = parseInt ( parts [ 0 ] , 10 ) ;
221- const nodeIndices = parts . slice ( 1 ) . map ( ( idx ) => parseInt ( idx , 10 ) ) ;
234+ } else if ( elementsProcessedInBlock < currentElementBlock . numElements ) {
235+ const nodeIndices = parts . slice ( 1 ) . map ( ( n ) => parseInt ( n , 10 ) ) ;
236+
237+ // Resolve physical tag via entity → physical map
238+ let physicalTag = currentElementBlock . tag ;
239+ if ( currentElementBlock . dim === 1 ) {
240+ const mapped = entityPhysicalMap . curves [ currentElementBlock . tag ] ;
241+ if ( mapped && mapped . length > 0 ) physicalTag = mapped [ 0 ] ;
242+ }
222243
223244 if ( currentElementBlock . elementType === 1 || currentElementBlock . elementType === 8 ) {
224- const physicalTag = currentElementBlock . tag ;
225-
226- if ( ! boundaryElementsByTag [ physicalTag ] ) {
227- boundaryElementsByTag [ physicalTag ] = [ ] ;
228- }
229-
245+ if ( ! boundaryElementsByTag [ physicalTag ] ) boundaryElementsByTag [ physicalTag ] = [ ] ;
230246 boundaryElementsByTag [ physicalTag ] . push ( nodeIndices ) ;
231247
232- // Store boundary node pairs for later processing in meshGenerationScript
233- if ( ! result . boundaryNodePairs [ physicalTag ] ) {
234- result . boundaryNodePairs [ physicalTag ] = [ ] ;
235- }
248+ if ( ! result . boundaryNodePairs [ physicalTag ] ) result . boundaryNodePairs [ physicalTag ] = [ ] ;
236249 result . boundaryNodePairs [ physicalTag ] . push ( nodeIndices ) ;
237250 } else if ( currentElementBlock . elementType === 2 ) {
238- // Linear triangle elements (3 nodes)
239251 result . nodalNumbering . triangleElements . push ( nodeIndices ) ;
240- } else if ( currentElementBlock . elementType === 3 ) {
241- // Linear quadrilateral elements (4 nodes)
242- result . nodalNumbering . quadElements . push ( nodeIndices ) ;
243- } else if ( currentElementBlock . elementType === 10 ) {
244- // Quadratic quadrilateral elements (9 nodes)
252+ } else if ( currentElementBlock . elementType === 3 || currentElementBlock . elementType === 10 ) {
245253 result . nodalNumbering . quadElements . push ( nodeIndices ) ;
246254 }
247255
248256 elementsProcessedInBlock ++ ;
249-
250257 if ( elementsProcessedInBlock === currentElementBlock . numElements ) {
251258 elementBlocksProcessed ++ ;
252259 currentElementBlock = { numElements : 0 } ;
@@ -257,26 +264,21 @@ const importGmshQuadTri = async (file) => {
257264 lineIndex ++ ;
258265 }
259266
260- // Store boundary conditions information
267+ // Boundary conditions
261268 result . physicalPropMap . forEach ( ( prop ) => {
262269 if ( prop . dimension === 1 ) {
263- const boundaryNodes = boundaryElementsByTag [ prop . tag ] || [ ] ;
264-
265- if ( boundaryNodes . length > 0 ) {
270+ const nodes = boundaryElementsByTag [ prop . tag ] || [ ] ;
271+ if ( nodes . length > 0 ) {
266272 result . boundaryConditions . push ( {
267273 name : prop . name ,
268274 tag : prop . tag ,
269- nodes : boundaryNodes ,
275+ nodes,
270276 } ) ;
271277 }
272278 }
273279 } ) ;
274280
275- debugLog (
276- `Parsed boundary node pairs by physical tag: ${ JSON . stringify (
277- result . boundaryNodePairs
278- ) } . These pairs will be used to identify boundary elements in the mesh.`
279- ) ;
281+ debugLog ( `Parsed boundary node pairs by physical tag: ${ JSON . stringify ( result . boundaryNodePairs ) } ` ) ;
280282
281283 return result ;
282284} ;
0 commit comments