Skip to content

Commit a11d466

Browse files
committed
Fixed a critical bug in thermal boundary conditions application where boundary physical tags (referenced as boundaryKey) were being incorrectly used to directly access boundarySides mapping. Update boundary condition scripts for improved handling of Gmsh meshes.
1 parent 0812dd7 commit a11d466

File tree

5 files changed

+282
-79
lines changed

5 files changed

+282
-79
lines changed

src/mesh/meshGenerationScript.js

Lines changed: 104 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ export class meshGeneration {
6161
const quadElements = this.parsedMesh.nodalNumbering.quadElements || [];
6262
const triangleElements = this.parsedMesh.nodalNumbering.triangleElements || [];
6363

64-
console.log("Parsed mesh nodal numbering:", this.parsedMesh.nodalNumbering);
64+
debugLog(
65+
"Initial parsed mesh nodal numbering from GMSH format: " +
66+
JSON.stringify(this.parsedMesh.nodalNumbering)
67+
);
6568

6669
// Check if it has quadElements or triangleElements structure from gmshReader
6770
if (quadElements && quadElements.length > 0) {
@@ -91,7 +94,10 @@ export class meshGeneration {
9194
this.parsedMesh.nodalNumbering = triangleElements;
9295
}
9396

94-
console.log("Mapped nodal numbering:", this.parsedMesh.nodalNumbering);
97+
debugLog(
98+
"Nodal numbering after mapping from GMSH to FEAScript format: " +
99+
JSON.stringify(this.parsedMesh.nodalNumbering)
100+
);
95101

96102
// Process boundary elements if they exist and if physical property mapping exists
97103
if (this.parsedMesh.physicalPropMap && this.parsedMesh.boundaryElements) {
@@ -113,68 +119,101 @@ export class meshGeneration {
113119

114120
// If boundary node pairs exist but boundary elements haven't been processed
115121
if (this.parsedMesh.boundaryNodePairs && !this.parsedMesh.boundaryElementsProcessed) {
122+
// Reset boundary elements array
116123
this.parsedMesh.boundaryElements = [];
117124

125+
// Process each physical property from the Gmsh file
118126
this.parsedMesh.physicalPropMap.forEach((prop) => {
127+
// Only process 1D physical entities (boundary lines)
119128
if (prop.dimension === 1) {
120-
const boundaryNodes = this.parsedMesh.boundaryNodePairs[prop.tag] || [];
129+
// Get all node pairs for this boundary
130+
const boundaryNodePairs = this.parsedMesh.boundaryNodePairs[prop.tag] || [];
121131

122-
if (boundaryNodes.length > 0) {
123-
// Initialize boundary element array for this tag
132+
if (boundaryNodePairs.length > 0) {
133+
// Initialize array for this boundary tag
124134
if (!this.parsedMesh.boundaryElements[prop.tag]) {
125135
this.parsedMesh.boundaryElements[prop.tag] = [];
126136
}
127137

128-
// For each boundary line segment (2 nodes)
129-
boundaryNodes.forEach((nodesPair) => {
130-
// Find which element contains both nodes of this boundary
138+
// For each boundary line segment (defined by a pair of nodes)
139+
boundaryNodePairs.forEach((nodesPair) => {
140+
const node1 = nodesPair[0]; // First node in the pair
141+
const node2 = nodesPair[1]; // Second node in the pair
142+
143+
debugLog(
144+
`Processing boundary node pair: [${node1}, ${node2}] for boundary ${prop.tag} (${
145+
prop.name || "unnamed"
146+
})`
147+
);
148+
149+
// Search through all elements to find which one contains both nodes
131150
let foundElement = false;
151+
152+
// Loop through all elements in the mesh
132153
for (let elemIdx = 0; elemIdx < this.parsedMesh.nodalNumbering.length; elemIdx++) {
133154
const elemNodes = this.parsedMesh.nodalNumbering[elemIdx];
134155

135-
// Check if both boundary nodes are in this element
136-
if (elemNodes.includes(nodesPair[0]) && elemNodes.includes(nodesPair[1])) {
137-
// Find which side of the element these nodes form
138-
let side;
139-
140-
// Using FEAScript orientation for sides
141-
// Side 0 (Bottom): nodes 0-2
142-
// Side 1 (Left): nodes 0-1
143-
// Side 2 (Top): nodes 1-3
144-
// Side 3 (Right): nodes 2-3
145-
146-
if (
147-
(elemNodes.indexOf(nodesPair[0]) === 0 &&
148-
elemNodes.indexOf(nodesPair[1]) === 2) ||
149-
(elemNodes.indexOf(nodesPair[1]) === 0 && elemNodes.indexOf(nodesPair[0]) === 2)
150-
) {
151-
side = 0; // Bottom side
152-
} else if (
153-
(elemNodes.indexOf(nodesPair[0]) === 0 &&
154-
elemNodes.indexOf(nodesPair[1]) === 1) ||
155-
(elemNodes.indexOf(nodesPair[1]) === 0 && elemNodes.indexOf(nodesPair[0]) === 1)
156-
) {
157-
side = 1; // Left side
158-
} else if (
159-
(elemNodes.indexOf(nodesPair[0]) === 1 &&
160-
elemNodes.indexOf(nodesPair[1]) === 3) ||
161-
(elemNodes.indexOf(nodesPair[1]) === 1 && elemNodes.indexOf(nodesPair[0]) === 3)
162-
) {
163-
side = 2; // Top side
164-
} else if (
165-
(elemNodes.indexOf(nodesPair[0]) === 2 &&
166-
elemNodes.indexOf(nodesPair[1]) === 3) ||
167-
(elemNodes.indexOf(nodesPair[1]) === 2 && elemNodes.indexOf(nodesPair[0]) === 3)
168-
) {
169-
side = 3; // Right side
156+
// For linear quadrilateral elements only (4 nodes)
157+
if (elemNodes.length === 4) {
158+
// Check if both boundary nodes are in this element
159+
if (elemNodes.includes(node1) && elemNodes.includes(node2)) {
160+
// Find which side of the element these nodes form
161+
let side;
162+
163+
const node1Index = elemNodes.indexOf(node1);
164+
const node2Index = elemNodes.indexOf(node2);
165+
166+
debugLog(
167+
` Found element ${elemIdx} containing boundary nodes. Element nodes: [${elemNodes.join(
168+
", "
169+
)}]`
170+
);
171+
debugLog(
172+
` Node ${node1} is at index ${node1Index}, Node ${node2} is at index ${node2Index} in the element`
173+
);
174+
175+
if (
176+
(node1Index === 0 && node2Index === 2) ||
177+
(node1Index === 2 && node2Index === 0)
178+
) {
179+
side = 0; // Bottom side
180+
debugLog(` These nodes form the BOTTOM side (${side}) of element ${elemIdx}`);
181+
} else if (
182+
(node1Index === 0 && node2Index === 1) ||
183+
(node1Index === 1 && node2Index === 0)
184+
) {
185+
side = 1; // Left side
186+
debugLog(` These nodes form the LEFT side (${side}) of element ${elemIdx}`);
187+
} else if (
188+
(node1Index === 1 && node2Index === 3) ||
189+
(node1Index === 3 && node2Index === 1)
190+
) {
191+
side = 2; // Top side
192+
debugLog(` These nodes form the TOP side (${side}) of element ${elemIdx}`);
193+
} else if (
194+
(node1Index === 2 && node2Index === 3) ||
195+
(node1Index === 3 && node2Index === 2)
196+
) {
197+
side = 3; // Right side
198+
debugLog(` These nodes form the RIGHT side (${side}) of element ${elemIdx}`);
199+
}
200+
201+
// Add the element and side to the boundary elements array
202+
this.parsedMesh.boundaryElements[prop.tag].push([elemIdx, side]);
203+
debugLog(
204+
` Added element-side pair [${elemIdx}, ${side}] to boundary tag ${prop.tag}`
205+
);
206+
foundElement = true;
207+
break;
170208
}
171-
172-
// Add to boundary elements
173-
this.parsedMesh.boundaryElements[prop.tag].push([elemIdx, side]);
174-
foundElement = true;
175-
break;
176209
}
177210
}
211+
212+
if (!foundElement) {
213+
errorLog(
214+
`Could not find element containing boundary nodes ${node1} and ${node2}. Boundary may be incomplete.`
215+
);
216+
}
178217
});
179218
}
180219
}
@@ -200,6 +239,9 @@ export class meshGeneration {
200239
}
201240
}
202241
}
242+
243+
debugLog("Processed boundary elements by tag: " + JSON.stringify(this.parsedMesh.boundaryElements));
244+
203245
return this.parsedMesh;
204246
} else {
205247
// Validate required geometry parameters based on mesh dimension
@@ -266,6 +308,8 @@ export class meshGeneration {
266308
// Find boundary elements
267309
const boundaryElements = this.findBoundaryElements();
268310

311+
debugLog("Generated node X coordinates: " + JSON.stringify(nodesXCoordinates));
312+
269313
// Return x coordinates of nodes, total nodes, NOP array, and boundary elements
270314
return {
271315
nodesXCoordinates,
@@ -328,8 +372,8 @@ export class meshGeneration {
328372
// Find boundary elements
329373
const boundaryElements = this.findBoundaryElements();
330374

331-
console.log("x coordinates of nodes:", nodesXCoordinates);
332-
console.log("y coordinates of nodes:", nodesYCoordinates);
375+
debugLog("Generated node X coordinates: " + JSON.stringify(nodesXCoordinates));
376+
debugLog("Generated node Y coordinates: " + JSON.stringify(nodesYCoordinates));
333377

334378
// Return x and y coordinates of nodes, total nodes, NOP array, and boundary elements
335379
return {
@@ -400,6 +444,7 @@ export class meshGeneration {
400444
}
401445
}
402446

447+
debugLog("Identified boundary elements by side: " + JSON.stringify(boundaryElements));
403448
return boundaryElements;
404449
}
405450

@@ -422,7 +467,7 @@ export class meshGeneration {
422467
/**
423468
* Linear 1D elements with the following nodes representation:
424469
*
425-
* 1__ __2
470+
* 1 --- 2
426471
*
427472
*/
428473
for (let elementIndex = 0; elementIndex < numElementsX; elementIndex++) {
@@ -435,7 +480,7 @@ export class meshGeneration {
435480
/**
436481
* Quadratic 1D elements with the following nodes representation:
437482
*
438-
* 1__2__3
483+
* 1 --- 2 --- 3
439484
*
440485
*/
441486
let columnCounter = 0;
@@ -452,10 +497,9 @@ export class meshGeneration {
452497
/**
453498
* Linear rectangular elements with the following nodes representation:
454499
*
455-
* 1__ __3
500+
* 1 --- 3
456501
* | |
457-
* |__ __|
458-
* 0 2
502+
* 0 --- 2
459503
*
460504
*/
461505
let rowCounter = 0;
@@ -476,11 +520,11 @@ export class meshGeneration {
476520
/**
477521
* Quadratic rectangular elements with the following nodes representation:
478522
*
479-
* 2__5__8
480-
* | |
481-
* 1 4 7
482-
* |__ __|
483-
* 0 3 6
523+
* 2 --- 5 --- 8
524+
* | | |
525+
* 1 --- 4 --- 7
526+
* | | |
527+
* 0 --- 3 --- 6
484528
*
485529
*/
486530
for (let elementIndexX = 1; elementIndexX <= numElementsX; elementIndexX++) {

src/readers/gmshReaderScript.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ const importGmshQuadTri = async (file) => {
229229
}
230230

231231
boundaryElementsByTag[physicalTag].push(nodeIndices);
232-
232+
233233
// Store boundary node pairs for later processing in meshGenerationScript
234234
if (!result.boundaryNodePairs[physicalTag]) {
235235
result.boundaryNodePairs[physicalTag] = [];
@@ -268,6 +268,12 @@ const importGmshQuadTri = async (file) => {
268268
}
269269
});
270270

271+
debugLog(
272+
`Parsed boundary node pairs by physical tag: ${JSON.stringify(
273+
result.boundaryNodePairs
274+
)}. These pairs will be used to identify boundary elements in the mesh.`
275+
);
276+
271277
return result;
272278
};
273279

src/solvers/solidHeatTransferScript.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export function assembleSolidHeatTransferMat(meshConfig, boundaryConditions) {
7070
if (isParsedMesh) {
7171
totalElements = nop.length; // Number of elements is the length of the nodal numbering array
7272
totalNodes = nodesXCoordinates.length; // Number of nodes is the length of the coordinates array
73-
73+
7474
// Debug log for mesh size
7575
debugLog(`Using parsed mesh with ${totalElements} elements and ${totalNodes} nodes`);
7676
} else {
@@ -151,8 +151,7 @@ export function assembleSolidHeatTransferMat(meshConfig, boundaryConditions) {
151151

152152
// Isoparametric mapping
153153
for (let localNodeIndex = 0; localNodeIndex < numNodes; localNodeIndex++) {
154-
xCoordinates +=
155-
nodesXCoordinates[localToGlobalMap[localNodeIndex]] * basisFunction[localNodeIndex];
154+
xCoordinates += nodesXCoordinates[localToGlobalMap[localNodeIndex]] * basisFunction[localNodeIndex];
156155
ksiDerivX +=
157156
nodesXCoordinates[localToGlobalMap[localNodeIndex]] * basisFunctionDerivKsi[localNodeIndex];
158157
detJacobian = ksiDerivX;

0 commit comments

Comments
 (0)