Skip to content

Commit ac09141

Browse files
committed
Enhance boundary element handling in importGmshQuadTri function and fix nodal numbering remapping for quadrilateral elements
1 parent d5b8c94 commit ac09141

File tree

1 file changed

+93
-24
lines changed

1 file changed

+93
-24
lines changed

src/readers/gmshReaderScript.js

Lines changed: 93 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -261,34 +261,103 @@ const importGmshQuadTri = async (file) => {
261261
if (!result.boundaryElements[prop.tag]) {
262262
result.boundaryElements[prop.tag] = [];
263263
}
264-
// TODO: Calculate the boundaryElements based on boundaryElementsByTag and nodalNumbering
265-
// NEXT TODO: Remap nodalNumbering according to https://gmsh.info/doc/texinfo/gmsh.html#Node-ordering.
266-
// In the case of quadrilaterals, the order is:
267-
/**
268-
* Gmsh quadrilateral node numbering (linear elements):
269-
*
270-
* 3__ __2
271-
* | |
272-
* |__ __|
273-
* 0 1
274-
*
275-
* FEAScript quadrilateral node numbering:
276-
*
277-
* 1__ __3
278-
* | |
279-
* |__ __|
280-
* 0 2
281-
*
282-
* Remapping:
283-
* - 0 (bottom left): stays as 0
284-
* - 3 (top left): becomes 1
285-
* - 1 (bottom right): becomes 2
286-
* - 2 (top right): becomes 3
287-
*/
264+
265+
// For each boundary line segment (2 nodes)
266+
boundaryNodes.forEach((nodesPair) => {
267+
// Find which quad element contains both nodes of this boundary
268+
let foundElement = false;
269+
for (let elemIdx = 0; elemIdx < result.nodalNumbering.quadElements.length; elemIdx++) {
270+
const elemNodes = result.nodalNumbering.quadElements[elemIdx];
271+
272+
// Check if both boundary nodes are in this element
273+
if (elemNodes.includes(nodesPair[0]) && elemNodes.includes(nodesPair[1])) {
274+
// Find which side of the element these nodes form
275+
let side;
276+
277+
// For linear quadrilateral elements, the Gmsh local numbering is:
278+
// 3 --- 2
279+
// | |
280+
// 0 --- 1
281+
282+
// Check which side these nodes belong to
283+
if (
284+
(elemNodes.indexOf(nodesPair[0]) === 0 && elemNodes.indexOf(nodesPair[1]) === 1) ||
285+
(elemNodes.indexOf(nodesPair[1]) === 0 && elemNodes.indexOf(nodesPair[0]) === 1)
286+
) {
287+
side = 0; // Bottom side
288+
} else if (
289+
(elemNodes.indexOf(nodesPair[0]) === 1 && elemNodes.indexOf(nodesPair[1]) === 2) ||
290+
(elemNodes.indexOf(nodesPair[1]) === 1 && elemNodes.indexOf(nodesPair[0]) === 2)
291+
) {
292+
side = 1; // Right side
293+
} else if (
294+
(elemNodes.indexOf(nodesPair[0]) === 2 && elemNodes.indexOf(nodesPair[1]) === 3) ||
295+
(elemNodes.indexOf(nodesPair[1]) === 2 && elemNodes.indexOf(nodesPair[0]) === 3)
296+
) {
297+
side = 2; // Top side
298+
} else if (
299+
(elemNodes.indexOf(nodesPair[0]) === 3 && elemNodes.indexOf(nodesPair[1]) === 0) ||
300+
(elemNodes.indexOf(nodesPair[1]) === 3 && elemNodes.indexOf(nodesPair[0]) === 0)
301+
) {
302+
side = 3; // Left side
303+
}
304+
305+
// Add to boundary elements
306+
result.boundaryElements[prop.tag].push([elemIdx, side]);
307+
foundElement = true;
308+
break;
309+
}
310+
}
311+
});
288312
}
289313
}
290314
});
291315

316+
// Remap nodal numbering from Gmsh format to FEAScript format for quadrilateral elements
317+
if (result.nodalNumbering.quadElements.length > 0) {
318+
/*
319+
* Gmsh quadrilateral node numbering (linear elements):
320+
*
321+
* 3__ __2
322+
* | |
323+
* |__ __|
324+
* 0 1
325+
*
326+
* FEAScript quadrilateral node numbering (linear elements):
327+
*
328+
* 1__ __3
329+
* | |
330+
* |__ __|
331+
* 0 2
332+
*
333+
*/
334+
// Mapping: Gmsh → FEAScript
335+
// 0 → 0 (bottom left)
336+
// 1 → 2 (bottom right)
337+
// 2 → 3 (top right)
338+
// 3 → 1 (top left)
339+
const gmshToFEAMap = [0, 2, 3, 1];
340+
341+
for (let i = 0; i < result.nodalNumbering.quadElements.length; i++) {
342+
const originalNodes = [...result.nodalNumbering.quadElements[i]];
343+
for (let j = 0; j < 4; j++) {
344+
result.nodalNumbering.quadElements[i][gmshToFEAMap[j]] = originalNodes[j];
345+
}
346+
}
347+
}
348+
349+
// Fix boundary elements array - remove the empty first element
350+
if (result.boundaryElements.length > 0 && result.boundaryElements[0] === undefined) {
351+
// Create a new array without the empty first element
352+
const fixedBoundaryElements = [];
353+
for (let i = 1; i < result.boundaryElements.length; i++) {
354+
if (result.boundaryElements[i]) {
355+
fixedBoundaryElements.push(result.boundaryElements[i]);
356+
}
357+
}
358+
result.boundaryElements = fixedBoundaryElements;
359+
}
360+
292361
return result;
293362
};
294363

0 commit comments

Comments
 (0)