UNPKG

awatif-fem

Version:

Awatif Finite Element Method (FEM) Solver

116 lines (97 loc) 2.98 kB
import { flatten, lusolve, multiply, subset, index, lup, sparse } from "mathjs"; import { Node, Element, NodeInputs, ElementInputs, DeformOutputs, } from "./data-model"; import { getGlobalStiffnessMatrix } from "./utils/getGlobalStiffnessMatrix"; export function deform( nodes: Node[], elements: Element[], nodeInputs: NodeInputs, elementInputs: ElementInputs ): DeformOutputs { if (nodes.length === 0 || elements.length === 0) return; const dof = nodes.length * 6; const freeInd = getFreeIndices(nodeInputs.supports, dof); const appliedForces = getAppliedForces(nodeInputs.loads, dof); const stiffnesses = getGlobalStiffnessMatrix( nodes, elements, elementInputs, dof ); const forcesFree = subset(appliedForces, index(freeInd)); const stiffnessesFree = subset(stiffnesses, index(freeInd, freeInd)); const stiffnessesFreeSparse = sparse(stiffnessesFree); const lu = lup(stiffnessesFreeSparse); const deformationFree = lusolve(lu, forcesFree); const deformationsArray: number[] = subset( Array(dof).fill(0), index(freeInd), flatten(deformationFree) ); const reactionsArray = multiply(stiffnesses, deformationsArray); const deformations: DeformOutputs["deformations"] = new Map(); const reactions: DeformOutputs["reactions"] = new Map(); nodes.forEach((_, i) => { const hasReaction = nodeInputs.supports?.get(i); deformations.set(i, [ deformationsArray[i * 6], deformationsArray[i * 6 + 1], deformationsArray[i * 6 + 2], deformationsArray[i * 6 + 3], deformationsArray[i * 6 + 4], deformationsArray[i * 6 + 5], ]); if (hasReaction) { reactions.set(i, [ reactionsArray[i * 6], reactionsArray[i * 6 + 1], reactionsArray[i * 6 + 2], reactionsArray[i * 6 + 3], reactionsArray[i * 6 + 4], reactionsArray[i * 6 + 5], ]); } }); return { deformations, reactions, }; } function getFreeIndices( supports: NodeInputs["supports"], dof: number ): number[] { const toRemove: number[] = []; supports?.forEach((support, index) => { if (support[0]) toRemove.push(index * 6); if (support[1]) toRemove.push(index * 6 + 1); if (support[2]) toRemove.push(index * 6 + 2); if (support[3]) toRemove.push(index * 6 + 3); if (support[4]) toRemove.push(index * 6 + 4); if (support[5]) toRemove.push(index * 6 + 5); }); return Array(dof) .fill(0) .map((_, i) => i) .filter((v) => !toRemove.includes(v)); } function getAppliedForces( forcesInputs: NodeInputs["loads"], dof: number ): number[] { const forces: number[] = Array(dof).fill(0); forcesInputs?.forEach((force, index) => { forces[index * 6] = force[0]; forces[index * 6 + 1] = force[1]; forces[index * 6 + 2] = force[2]; forces[index * 6 + 3] = force[3]; forces[index * 6 + 4] = force[4]; forces[index * 6 + 5] = force[5]; }); return forces; }