29 releases (12 breaking)
0.13.0 | Oct 29, 2023 |
---|---|
0.11.0 | Oct 23, 2023 |
#912 in Algorithms
239 downloads per month
200KB
942 lines
QTruss
A simple finite-element solver for 2D trusses.
Getting Started
Importing maria-linalg
You must import the latest version of the Rust crate maria-linalg
in order to use this package.
Creating a List of Nodes
First, you must construct a list of nodes. Each node must have a location and a constraint type. There are four types of constraints.
Constraint::Pin
. 0 degrees of freedom. An immobile pin joint.Constraint::Free (force)
. 2 degrees of freedom. A free joint with an appliedforce
of typemaria_linalg::Vector<2>
. Note that this applied force may be zero.Constraint::HorizontalSlide (force)
. 1 degree of freedom. A horizontal slider joint with an appliedforce
of typemaria_linalg::Vector<2>
. Note that this applied force may be zero. This joint is free to move in the X direction but cannot move in the Y direction.Constraint::VerticalSlide (force)
. 1 degree of freedom. A vertical slider joint with an appliedforce
of typemaria_linalg::Vector<2>
. Note that this applied force may be zero. This joint is free to move in the X direction but cannot move in the Y direction.
Construct nodes according to the following method.
use maria_linalg::Vector;
use qtruss::{Constraint, Node};
// Note that From<[f64; N]> is implemented for Vector<N>
let n0 = Node::new(
[0.0, 1.0].into(),
Constraint::Pin,
);
// Note that From<[f64; N]> is implemented for Vector<N>
let n1 = Node::new(
[0.0, 1.0].into(),
Constraint::HorizontalSlide ([-1.0, 0.0].into()),
);
Constructing a Truss
Once nodes are constructed, place these in an array like so.
let nodes = [
n0,
n1,
// All the nodes
];
You are now ready to construct your truss. Note that the truss should be mut
able, as you will add elements later. Additionally, the Truss::solve
function stores its results inside of the Truss
structure.
Note that there are three generic constants that must be defined.
N: usize
. The number of nodes in this truss.K: usize
. The number of elements in this truss.F: usize
. The number of degrees of freedom in this truss. As of the latest version ofqopt
, you must compute this manually. Compute this by summing the number of degrees of freedom for each node (see above aboutenum Constraint
).
let mut truss = Truss::<N, K, F>::new(nodes);
Creating Elements
Create elements according to the following pattern.
truss.add(n0, n1);
This function has two arguments.
n0: usize
. The index innodes
of the first node to which this element connects.n1: usize
. The index innodes
of the second node to which this element connects.
Note that the area and material of this element will be passed at evaluation time. This allows improved run-time on specific optimization problems.
Call Truss::add
for every element in your truss.
This function returns Option<usize>
. If the provided node numbers are valid, it returns variant Some
with the index of this element. The first call to Truss::add
will have index 0
, the second call index 1
, and so on. If the provided node numbers are invalid (beyond the range of nodes
), this function returns variant None
.
Solving the Truss
let (forces, displacements) = truss.solve(areas, materials).unwrap();
This function has two arguments.
areas: [f64; K]
. The areas of each element in the truss.materials: [Material; K]
. The materials of each element in the truss.
Determining Member Forces
let force: Option<f64> = truss.internal_force(areas, materials, k);
This function has three arguments.
areas: [f64; K]
. The areas of each element in the truss.materials: [Material; K]
. The materials of each element in the truss.k: usize
. The index of the desired element. This is determined by the number of calls toTruss::add
. The first call corresponds tok = 0
, the second callk = 1
, and so on.
This function is positive when the element is in tension and negative when the element is in compression.
If force
is of variant None
, there is something preventing qtruss
from solving your truss. Check your N
, K
, and F
values, and ensure that your truss is fully constrained.
Determining Node Displacements
let displacement: Option<Vector<2>> = truss.displacement(areas, materials, n);
This function has three arguments.
areas: [f64; K]
. The areas of each element in the truss.materials: [Material; K]
. The materials of each element in the truss.n: usize
. The index of the desired node innodes
.
If displacement
is of variant None
, there is something preventing qtruss
from solving your truss. Check your N
, K
, and F
values, and ensure that your truss is fully constrained.
Determining Total Truss Compliance
let compliance: Option<f64> = truss.compliance(areas, materials);
This function has two arguments.
areas: [f64; K]
. The areas of each element in the truss.materials: [Material; K]
. The materials of each element in the truss.
If compliance
is of variant None
, there is something preventing qtruss
from solving your truss. Check your N
, K
, and F
values, and ensure that your truss is fully constrained.
Determining Truss Volume
let volume: f64 = truss.volume(areas);
This function has one argument.
areas: [f64; K]
. The areas of each element in the truss.
Determining Truss Fabrication Complexity
let complexity: f64 = truss.volume(areas, maxarea, beta);
This function has three arguments.
areas: [f64; K]
. The areas of each element in the truss.maxarea: f64
. An area standardization term of each element. This should be close to the maximum allowable area.beta: f64
. A term to adjust the regularized Heaviside distribution.
Dependencies
~5–14MB
~197K SLoC