This page demonstrates solving the 2D lid-driven cavity problem using FEAScript in a web worker for improved browser responsiveness. For the mathematical formulation and theory, see the basic tutorial.
⚠️ Important: Due to security restrictions, this example requires launching the browser with reduced security settings, e.g.:
start chrome --disable-web-security --user-data-dir="C:\tmp\chrome-cors" --disable-site-isolation-trials
These flags temporarily disable CORS restrictions that normally block a web worker from loading scripts or data when running from local files. For production applications, proper CORS headers should be configured on your server.
The code below shows how to use FEAScript with a web worker. The velocity field is decomposed and plotted as contour plots.
<body>
<!-- ...body region... -->
<script type="module">
// Import FEAScript library
import { FEAScriptWorker, plotSolution, printVersion } from "https://core.feascript.com/src/index.js";
window.addEventListener("DOMContentLoaded", async () => {
// Print FEAScript version in the console
printVersion();
// Create a new FEAScriptWorker instance
const model = new FEAScriptWorker();
// Ensure the worker is ready
await model.ping();
// Configure model
await model.setModelConfig("stokesScript");
// Mesh parameters
const numElementsX = 12;
const numElementsY = 6;
await model.setMeshConfig({
meshDimension: "2D",
elementOrder: "quadratic",
numElementsX: numElementsX,
numElementsY: numElementsY,
maxX: 4,
maxY: 2,
});
// Apply boundary conditions
await model.addBoundaryCondition("0", ["constantVelocity", 0, 0]); // Bottom boundary
await model.addBoundaryCondition("1", ["constantVelocity", 0, 0]); // Left boundary
await model.addBoundaryCondition("2", ["constantVelocity", 1, 0]); // Top boundary
await model.addBoundaryCondition("3", ["constantVelocity", 0, 0]); // Right boundary
// Solve
await model.setSolverMethod("lusolve");
const result = await model.solve();
// Calculate total velocity nodes for quadratic elements
const nodesX = 2 * numElementsX + 1;
const nodesY = 2 * numElementsY + 1;
const totalNodesVelocity = nodesX * nodesY;
// Extract solution components
const solutionVector = result.solutionVector;
const uVelocity = solutionVector.slice(0, totalNodesVelocity);
const vVelocity = solutionVector.slice(totalNodesVelocity, 2 * totalNodesVelocity);
const velocityMagnitude = uVelocity.map((u, i) => Math.sqrt(u * u + vVelocity[i] * vVelocity[i]));
// Get model info for plotting
const modelInfo = await model.getModelInfo();
// Plot results
plotSolution(modelInfo, { solutionVector: velocityMagnitude, nodesCoordinates: result.nodesCoordinates },
"contour", "velocityMagnitudeCanvas");
plotSolution(modelInfo, { solutionVector: uVelocity, nodesCoordinates: result.nodesCoordinates },
"contour", "uVelocityCanvas");
plotSolution(modelInfo, { solutionVector: vVelocity, nodesCoordinates: result.nodesCoordinates },
"contour", "vVelocityCanvas");
// Terminate the worker
model.terminate();
});
</script>
<!-- ...rest of body region... -->
</body>
Below are the 2D contour plots of the computed velocity magnitude \(|\mathbf{u}| = \sqrt{u^2+v^2}\), horizontal velocity component \(u\), and vertical velocity component \(v\). These plots are generated in real time using FEAScript.