In this tutorial, we solve a 1D beam bending problem using the Euler-Bernoulli beam theory. The beam is clamped at one end, supported by a roller at midspan, and connected to a linear elastic spring at the free end, while carrying a distributed load, a concentrated moment, and a point load.
The Euler-Bernoulli beam theory describes the bending of slender beams under transverse loading. The governing equation for the transverse deflection \(w(x)\) is the fourth-order equation:
\(\frac{d^2}{dx^2}\left(EI(x)\frac{d^2w}{dx^2}\right) = q(x)\)
Where \(EI(x)\) is the bending stiffness (product of the Young's modulus and the second moment of area of the cross-section) and \(q(x)\) is the distributed transverse load. This example reproduces the "Bending of a Beam" problem from J.N. Reddy, An Introduction to the Finite Element Method, 3rd ed., McGraw-Hill, 2006. A 10 m beam is clamped at \(x=0\), supported by a roller at midspan (\(x=5\)), and connected to a linear elastic spring at the free end (\(x=10\)). The bending stiffness is \(EI = 2.0\times10^6\), and the beam carries a uniformly distributed load \(q=-1000\) over the clamped span (\(0 \le x \le 5\)), a concentrated moment of \(1250\) applied at the roller, and a point load of \(-2500\) applied at the free end. The spring at the free end has a stiffness of \(200\).
Since the governing equation is fourth-order, both the deflection \(w\) and the rotation \(\theta = dw/dx\) must be continuous across element boundaries. FEAScript uses cubic Hermite shape functions for the beam field, so each node carries 2 degrees of freedom, ordered as \([w_0, \theta_0, w_1, \theta_1, \ldots]\) in the solution vector.
Below is a demonstration of how to use the FEAScript library to solve this beam bending problem in your web browser. You only need a simple HTML page to run this example where the following code snippets should be included. First, load the required external libraries:
<head> <!-- ...head region... --> <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/11.12.0/math.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/plotly.js/2.35.3/plotly.min.js"></script> <!-- ...rest of head region... --> </head>
We should then define the problem parameters, such as the solver type, the mesh configuration, and the boundary conditions. This is performed using JavaScript objects directly in the HTML file:
<body>
<!-- ...body region... -->
<script type="module">
// Import FEAScript library
import { FEAScriptModel, plotSolution, printVersion } from "https://core.feascript.com/dist/feascript.esm.js";
window.addEventListener("DOMContentLoaded", (event) => {
// Print FEAScript version in the console
printVersion();
// Create and configure model
const model = new FEAScriptModel();
model.setModelConfig("eulerBernoulliBeamScript", {
coefficientFunctions: {
EI: (x) => 2.0e6, // Bending stiffness
q: (x) => (x <= 5 ? -1000 : 0), // Distributed load over the clamped span
},
});
// Define mesh configuration
model.setMeshConfig({
meshDimension: "1D",
elementOrder: "linear",
numElementsX: 2,
maxX: 10,
});
// Define boundary conditions
model.addBoundaryCondition("1", [["fixed"]]); // Clamped support
model.addBoundaryCondition("2", [["pinned"], ["moment", 1250]]); // Roller + applied moment
model.addBoundaryCondition("3", [["spring", 200], ["force", -2500]]); // Spring support + point load
// Solve
model.setSolverMethod("lusolve");
const result = model.solve();
// Extract the deflection field from the solution vector
// DOF layout per node: [w, theta]
const totalNodesX = model._eulerBernoulliBeamMetadata.totalNodesX;
const flatSolution = result.solutionVector.map((entry) => (Array.isArray(entry) ? entry[0] : entry));
const deflection = [];
for (let i = 0; i < totalNodesX; i++) {
deflection.push(flatSolution[2 * i]);
}
// Plot the deflection as a line plot
plotSolution(model, { solutionVector: deflection, nodesCoordinates: result.nodesCoordinates },
"line", "resultsCanvas");
});
</script>
<!-- ...rest of body region... -->
</body>
In the boundary condition definition, the numbers at the left side ("1" to
"3") refer to the 1-based global node number, since beam problems commonly need conditions
at interior nodes as well (e.g. the midspan roller). Each key maps to an array of condition tuples,
since a node can carry more than one condition at once (e.g. a spring support plus a point load).
Since the beam solver packs \(w\) and \(\theta\) together at each node, the deflection field is
extracted from the solution vector by taking every other entry before passing it to
plotSolution.
After solving the case, the results appear as a line plot. To visualize it, include an HTML container where the plot will render:
<body> <!-- ...body region... --> <div id="resultsCanvas"></div> <!-- ...rest of body region... --> </body>
The "resultsCanvas" is the id of the div where the plot will be rendered. This id is passed
as an argument to the plotSolution function to specify the target div for the plot.
Below is the 1D line plot of the computed beam deflection \(w(x)\). This plot is generated in real time using FEAScript. You can find a Node.js implementation of this tutorial in the example directory.
The plot shows the beam deflection dropping to zero at the clamped end and at the midspan roller, while the free end deflects under the combined effect of the spring support and the applied point load.