Creeping Flow in a 2D Lid-Driven Cavity Tutorial (Multi-threaded)

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.

Web Worker Implementation

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("creepingFlowScript");
      // 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>

Results

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.

Solving...

Velocity Magnitude

Horizontal Velocity (\(u\))

Vertical Velocity (\(v\))