|
9 | 9 |
|
10 | 10 | // Import Math.js |
11 | 11 | import * as math from "mathjs"; |
12 | | -global.math = math; |
| 12 | +globalThis.math = math; |
13 | 13 |
|
14 | 14 | // Import FEAScript library |
15 | | -import { FEAScriptModel, printVersion } from "feascript"; |
| 15 | +import { |
| 16 | + FEAScriptModel, |
| 17 | + createColorScale, |
| 18 | + createContourLineOptions, |
| 19 | + plotInterpolatedSolution, |
| 20 | + printVersion, |
| 21 | +} from "feascript"; |
16 | 22 |
|
17 | 23 | console.log("FEAScript Version:", printVersion); |
18 | 24 |
|
19 | | -// Create a new FEAScript model |
20 | | -const model = new FEAScriptModel(); |
21 | | - |
22 | | -// Select physics/PDE |
23 | | -model.setModelConfig("heatConductionScript"); |
24 | | - |
25 | | -// Define mesh configuration |
26 | | -model.setMeshConfig({ |
27 | | - meshDimension: "2D", |
28 | | - elementOrder: "quadratic", |
29 | | - numElementsX: 8, |
30 | | - numElementsY: 4, |
31 | | - maxX: 4, |
32 | | - maxY: 2, |
33 | | -}); |
34 | | - |
35 | | -// Define boundary conditions |
36 | | -model.addBoundaryCondition("0", ["constantTemp", 200]); // Bottom boundary |
37 | | -model.addBoundaryCondition("1", ["symmetry"]); // Left boundary |
38 | | -model.addBoundaryCondition("2", ["convection", 1, 20]); // Top boundary |
39 | | -model.addBoundaryCondition("3", ["constantTemp", 200]); // Right boundary |
40 | | - |
41 | | -// Set solver method (optional) |
42 | | -model.setSolverMethod("lusolve"); |
43 | | - |
44 | | -// Solve the problem |
45 | | -const { solutionVector, nodesCoordinates } = model.solve(); |
46 | | - |
47 | | -// Print results |
48 | | -console.log(`Number of nodes in mesh: ${nodesCoordinates.nodesXCoordinates.length}`); |
49 | | -console.log("Node coordinates:", nodesCoordinates); |
50 | | -console.log("Solution vector:", solutionVector); |
| 25 | +function createPlotSection(title, plotDivId) { |
| 26 | + const section = document.createElement("section"); |
| 27 | + section.style.margin = "1rem 0 2rem"; |
| 28 | + |
| 29 | + const heading = document.createElement("h2"); |
| 30 | + heading.textContent = title; |
| 31 | + heading.style.fontFamily = "sans-serif"; |
| 32 | + heading.style.fontSize = "1rem"; |
| 33 | + heading.style.margin = "0 0 0.5rem"; |
| 34 | + |
| 35 | + const plotDiv = document.createElement("div"); |
| 36 | + plotDiv.id = plotDivId; |
| 37 | + plotDiv.style.width = "100%"; |
| 38 | + plotDiv.style.height = "420px"; |
| 39 | + plotDiv.style.border = "1px solid #d0d7de"; |
| 40 | + plotDiv.style.borderRadius = "8px"; |
| 41 | + plotDiv.style.overflow = "hidden"; |
| 42 | + |
| 43 | + section.append(heading, plotDiv); |
| 44 | + return { section, plotDivId }; |
| 45 | +} |
| 46 | + |
| 47 | +function ensurePlotRoot() { |
| 48 | + const existingRoot = document.getElementById("feascript-fin-plots"); |
| 49 | + if (existingRoot) { |
| 50 | + existingRoot.innerHTML = ""; |
| 51 | + return existingRoot; |
| 52 | + } |
| 53 | + |
| 54 | + const root = document.createElement("div"); |
| 55 | + root.id = "feascript-fin-plots"; |
| 56 | + root.style.maxWidth = "1100px"; |
| 57 | + root.style.margin = "1.5rem auto"; |
| 58 | + root.style.padding = "0 1rem 2rem"; |
| 59 | + document.body.appendChild(root); |
| 60 | + return root; |
| 61 | +} |
| 62 | + |
| 63 | +async function renderVisualizations(model, result) { |
| 64 | + if (typeof document === "undefined") { |
| 65 | + return; |
| 66 | + } |
| 67 | + |
| 68 | + const plotRoot = ensurePlotRoot(); |
| 69 | + const vtkPlot = createPlotSection("VTK.js contour visualization", "heat-fin-vtk-plot"); |
| 70 | + const plotlyPlot = createPlotSection("Plotly contour visualization", "heat-fin-plotly-plot"); |
| 71 | + plotRoot.append(vtkPlot.section, plotlyPlot.section); |
| 72 | + |
| 73 | + const renderOptions = { |
| 74 | + colorScale: createColorScale({ |
| 75 | + presetName: "Cool to Warm", |
| 76 | + scalarBarTitle: "Temperature", |
| 77 | + }), |
| 78 | + contourLines: createContourLineOptions({ |
| 79 | + enabled: true, |
| 80 | + numberOfContours: 14, |
| 81 | + lineWidth: 1.25, |
| 82 | + }), |
| 83 | + }; |
| 84 | + |
| 85 | + await plotInterpolatedSolution(model, result, "contour", vtkPlot.plotDivId, { |
| 86 | + ...renderOptions, |
| 87 | + backend: "vtk", |
| 88 | + }); |
| 89 | + |
| 90 | + await plotInterpolatedSolution(model, result, "contour", plotlyPlot.plotDivId, { |
| 91 | + ...renderOptions, |
| 92 | + backend: "plotly", |
| 93 | + }); |
| 94 | +} |
| 95 | + |
| 96 | +async function runExample() { |
| 97 | + // Create a new FEAScript model |
| 98 | + const model = new FEAScriptModel(); |
| 99 | + |
| 100 | + // Select physics/PDE |
| 101 | + model.setModelConfig("heatConductionScript"); |
| 102 | + |
| 103 | + // Define mesh configuration |
| 104 | + model.setMeshConfig({ |
| 105 | + meshDimension: "2D", |
| 106 | + elementOrder: "quadratic", |
| 107 | + numElementsX: 8, |
| 108 | + numElementsY: 4, |
| 109 | + maxX: 4, |
| 110 | + maxY: 2, |
| 111 | + }); |
| 112 | + |
| 113 | + // Define boundary conditions |
| 114 | + model.addBoundaryCondition("0", ["constantTemp", 200]); // Bottom boundary |
| 115 | + model.addBoundaryCondition("1", ["symmetry"]); // Left boundary |
| 116 | + model.addBoundaryCondition("2", ["convection", 1, 20]); // Top boundary |
| 117 | + model.addBoundaryCondition("3", ["constantTemp", 200]); // Right boundary |
| 118 | + |
| 119 | + // Set solver method (optional) |
| 120 | + model.setSolverMethod("lusolve"); |
| 121 | + |
| 122 | + // Solve the problem |
| 123 | + const result = model.solve(); |
| 124 | + const { solutionVector, nodesCoordinates } = result; |
| 125 | + |
| 126 | + // Print results |
| 127 | + console.log(`Number of nodes in mesh: ${nodesCoordinates.nodesXCoordinates.length}`); |
| 128 | + console.log("Node coordinates:", nodesCoordinates); |
| 129 | + console.log("Solution vector:", solutionVector); |
| 130 | + |
| 131 | + await renderVisualizations(model, result); |
| 132 | +} |
| 133 | + |
| 134 | +if (typeof document !== "undefined" && document.readyState === "loading") { |
| 135 | + document.addEventListener("DOMContentLoaded", () => { |
| 136 | + runExample().catch((error) => { |
| 137 | + console.error("Failed to run heat conduction fin example:", error); |
| 138 | + }); |
| 139 | + }, { once: true }); |
| 140 | +} else { |
| 141 | + runExample().catch((error) => { |
| 142 | + console.error("Failed to run heat conduction fin example:", error); |
| 143 | + }); |
| 144 | +} |
0 commit comments