## qtruss

A simple finite-element solver for trusses

### 29 releases(12 breaking)

 0.13.0 Oct 29, 2023 Oct 23, 2023

#140 in Math

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 applied `force` of type `maria_linalg::Vector<2>`. Note that this applied force may be zero.
• `Constraint::HorizontalSlide (force)`. 1 degree of freedom. A horizontal slider joint with an applied `force` of type `maria_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 applied `force` of type `maria_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 of `qopt`, you must compute this manually. Compute this by summing the number of degrees of freedom for each node (see above about `enum 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 in `nodes` of the first node to which this element connects.
• `n1: usize`. The index in `nodes` 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 to `Truss::add`. The first call corresponds to `k = 0`, the second call `k = 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 in `nodes`.

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.

~5–16MB
~202K SLoC