A 2D Rust-Based Finite Element Simulator

Overview

Magnetite Cover Image

Magnetite

A 2D linear-elastic FEA program for isotropic materials, built in Rust.

Overview

Magnetite is a simple linear-elastic mechanical solver for isotropic 2D models. Here's how it works:

  1. First, we give Magnetite two things: an input json and a geometry file

    • The input json is explained in greater detail below; it lays out boundary conditions and other parameters for the simulation, including part-thickness and material elasticity.
    • The geometry is provided via an svg file. There's some limitations to what Magnetite supports, and this is covered below too. Optionally, you can provide CSV files of vertices, but this method tends to be convoluted.
  2. Next, Magnetite rebuilds your geometry into a .geo file. This allows us to use Gmesh—an open source meshing program—to create a mesh of the geometry using Delaunay triangulation.

    Gmesh is a vastly equipped piece of software. The algorithm Magnetite uses is Delaunay-based, but many mesh conflicts are resolved by other Gmesh algorithms.

  3. After parsing the geometry into a .geo file, Magnetite runs Gmesh to create a .msh mesh.

  4. After the meshing has finished, Magnetite parses the mesh output into a list of Nodes and Vertices. At this time, it will apply boundary conditions listed in the input json.

  5. Once the mesh has been parsed, it's onto solving. A lot happens under the hood, and the process is documented in detail here.

  6. After solving the system, we post-process the system to solve for stresses, then we output the results as a nodes.csv and elements.csv.

  7. Finally, Magnetite triggers a Python script to plot these elements in matplotlib.

Example Output

Here's a fun example I did with the LinedIn logo. This mesh is pretty fine, but it only took Magnetite 0.286 seconds to solve on my not-so-special MacBook Air.

A screenshot of a simulation output

Installation and Running

It's important to build this crate in release mode. The underlying linear algebra accelerators don't seem to trigger in dev mode, meaning that everything will work in dev—just very slowly.

To install Magnetite, run:

git clone https://github.com/kyle-tennison/Magnetite.git; cd Magnetite
cargo build --release

Then, optionally, you can alias the binary:

alias magnetite=target/release/magnetite

You will also need Gmsh installed on your machine.

Running Example

Try running the example above! Go to examples/cover-example and run the following:

magnetite input.json geom.svg --cmap gist_heat

The cmap flag is optional; it tells us to use the gist_heat colormap when plotting our results in matplotlib. All matplotlib colormaps are supported.

Magnetite has some other options. Run the following to display the help page:

magnetite -h

Geometry Files

Geometry can be provided in two ways:

  • As an .svg file
  • As a series of .csv files

In both cases, geometry is limited to simple regions, meaning that regions can have holes, but they must contribute to the same "part." To facilitate this requirement, Magnetite needs one external region and any number of internal regions (including none).

SVG Files

The easiest way to generate a .svg file for Magnetite is through Adobe Illustrator; however, this product is far-from free. If you don't have access to Illustrator, another vector art program should suffice.

Currently, Magnetite supports the following SVG elements:

  • rect
  • polyline
  • polygons

Unfortunately, this means that other common elements are not currently supported. This includes, but is not limited to:

Eventually, I hope to support these elements, but my priorities with this project are elsewhere.

In illustrator, if you exclusively use the rectangle and pen tool (without splines), your geometry should be parsed correctly.

The example above was created in illustrator:

Again, Magnetite needs one external region and any number of internal regions. The green in the image above shows the external region, which wraps the yellow internal regions. These interal regions will be "cut" out of the final geometry.

To tell Magnetite what's internal versus external, we simply name the layers INNER or OUTER—respectively:

It's not pretty, but it works. Eventually, Magnetite might support .dxf drawings.

Notice how there's a few leftover layers? That's perfectly fine. Any layers that aren't named INNER or OUTER will be ignored.

We can export this document as a .svg, then we're ready to run a simulation on it!

If two vertices are closer than the minimum element length specified in the input json, one will be removed. If something ends up looking jagged, try refining the mesh.

CSV Files

CSV files are simpler to use, but they are cumbersome to create. These CSV files only have two fields, x & y, which detail the vertices in the model. The ordering of these vertices defines the connections between them.

x,y
-11,4.5
-10,4.5
-9,4.5
-8,4.5
-7,4.5
...

CSV Files follow the same OUTER-INNER requirements defined above. Magnetite will always require one external geometry, and any number of additional internal geometries.

For instance, say we have an external.csv for our outer region, then internal_1.csv and internal_2.csv. To tell Magnetite which geometry is which, we need to pass the external geometry first. In this scenario, that would look like:

magnetite input.json external.csv interal_1.csv internal_2.csv

Input Json

The actual simulation is defined in an input json. Let's break down the following example:

{
  "metadata": {
    "part_thickness": 0.5,
    "material_elasticity": 69e9,
    "poisson_ratio": 0.33,
    "characteristic_length_min": 0,
    "characteristic_length_max": 0.9
  },
  "boundary_conditions": {
    "restraint": {
      "region": {
        "x_target_min": -12,
        "x_target_max": -10
      },
      "targets": {
        "ux": 0,
        "uy": 0,
        "fx": null,
        "fy": null
      }
    },
    "load": {
      "region": {
        "x_target_min": 10,
        "x_target_max": 12
      },
      "targets": {
        "ux": null,
        "uy": null,
        "fx": -6e8,
        "fy": 0
      }
    }
  }
}

Metadata

The metadata field defines the properties of the simulation. All the fields shown (i.e., part_thickness, material_elasticity, etc.) are required for each simulation.

These fields describe:

  • part_thickness – The thickness of the part
  • material_elasticity – The Young's Modulus of the part
  • characteristic_length_min – (Effectively) The minimum mesh element size
  • characteristic_length_max – (Effectively) The maximum mesh element size

Boundary Conditions

Here, we specify boundary conditions for the simulation. In the example above, we define two boundary conditions, restraint and load. We can name these whatever we like.

Each boundary condition must have two fields: region and targets

Region

Boundary conditions are applied by rectangular-region; if a node falls within this region, the targets will be applied to it. By default, the region is $\mathbb{R}^2$ ; we restrict it with:

  • x_target_min
  • x_target_max
  • y_target_min
  • y_target_max

We are effectively saying: $R=\{(x,y)\in{\mathbb{R}^2|x_{target-min} ≤x≤ x_{target-max}, y_{target-min} ≤y≤ y_{target-max}}\}$

Values left undefined will default to $\infty$ .

Target

If a node falls within the region, the parameters defined here will be applied to that node. As with the metadata section, all fields in the target section must be defined.

To create a properly constrained model, there must be one unknown in each axis. For instance, in this example, the external forces fx and fy are known in the $x$ and $y$ axes; therefore, we must leave ux and uy as null. If we over- or under-define our model, Magnetite will error.

Citations

The equations used to obtain stiffness matrices were derived in this University of New Mexico Paper.

Other references are made to this Indian Institute of Science Paper.

More information is found on this Wikipedia page

More

Magnetite is a Rust-adapdation of my Python-based solver Pyrite. Eventually, I hope to build a 3D solver, and Magnetite will be the starting-place for that.

These isotropic linear-elastic solvers are stepping stones, and eventually, I hope to use them for some pretty ambitious projects.

A lot more of how this solver works is documented in "under the hood." If you're interested, check it out!

You might also like...
Terminal based GUI for eAsistent written in Rust

Terminal based GUI for eAsistent written in Rust This project is currently work in progress. I will update this readme with features that I'm currentl

A Rust-based Garry's Mod module for fetching environment variables.

gm_environ Using Environment Variables in Garry's Mod. Installation Download a copy of the module from the releases (or compile from source) Move the

A CLI-based pride flag generator written in Rust
A CLI-based pride flag generator written in Rust

🌈 prideful (in development) A CLI-based pride flag generator written in Rust. How to run Build the project using cargo. Install cargo by following th

A native screenshot tool for wlroots based compositors such as sway and river written in Rust
A native screenshot tool for wlroots based compositors such as sway and river written in Rust

A native screenshot tool for wlroots based compositors such as sway and river written in Rust. X11 support coming soon.

A simple lexer which creates over 75 various tokens based on the rust programming language.

Documentation. This complete Lexer/Lexical Scanner produces tokens for a string or a file path entry. The output is a Vector for the user to handle ac

An easy-to-use TUI crate for Rust, based off of the Elm architecture.

Rustea An easy-to-use TUI crate for Rust, based off of the Elm architecture. This is a re-implementation of Go's Tea, created by TJ Holowaychuk. Featu

Rust derive-based argument parsing optimized for code size

Argh Argh is an opinionated Derive-based argument parser optimized for code size Derive-based argument parsing optimized for code size and conformance

A text renderer for Rust's embedded-graphics crate, based on U8g2
A text renderer for Rust's embedded-graphics crate, based on U8g2

u8g2-fonts This crate is a pure Rust reimplementation of the font subsystem of U8g2. It is intended for the embedded-graphics ecosystem. Licensing Whi

Rust-based language and runtime for cross-platform app development
Rust-based language and runtime for cross-platform app development

Pax Pax is a cross-platform rendering engine & Rust framework for interactive graphics, animations, and GUIs. Pax extends the Rust programming languag

Owner
Kyle Tennison
Student. Intern at Ansys
Kyle Tennison
Like HashSet but retaining INSERTION order and without `Hash` requirement on the Element type.

identified_vec A collection of unique identifiable elements which retains insertion order, inspired by Pointfree's Swift Identified Collections. Simil

Alexander Cyon 4 Dec 11, 2023
Simulator for Analogue's CHIP32 VM on Analogue Pocket

Simulator for Analogue's CHIP32 VM This is a simulator for Analogue's CHIP32 virtual 32-bit CPU used as a data preprocessor for openFPGA. It allows yo

Adam Gastineau 6 Nov 14, 2022
Ethereum transaction simulator leveraging Foundry's codebase

Enso Transaction ?? Simulator ?? A simple API which simulates a given transaction request. ?? API ?? POST /api/v1/simulate Simulates a single transact

null 162 Jun 4, 2023
A simulator for Street Fighter 6 battle data.

sf6_sim A simulator for Street Fighter 6 battle data. Very early in development. It can currently simulate boxes, cancel lists, and movement. Online v

null 4 Jun 18, 2023
Fast Symbol Ranking based compressor. Based on the idea of Matt Mahoney's SR2

Fast Symbol Ranking based compressor. Based on the idea of Matt Mahoney's SR2

Mai Thanh Minh 3 Apr 29, 2023
A Rust-based shell script to create a folder structure to use for a single class every semester. Mostly an excuse to use Rust.

A Rust Course Folder Shell Script PROJECT IN PROGRESS (Spring 2022) When completed, script will create a folder structure of the following schema: [ro

Sebastián Romero Cruz 1 Apr 10, 2022
Another TUI based system monitor, this time in Rust!

Another TUI based system monitor, this time in Rust!

Caleb Bassi 2.1k Jan 3, 2023
Warp is a blazingly fast, Rust-based terminal that makes you and your team more productive at running, debugging, and deploying code and infrastructure.

Warp is a blazingly fast, Rust-based terminal that makes you and your team more productive at running, debugging, and deploying code and infrastructure.

Warp 10.4k Jan 4, 2023
Simple test app based on rust-psp

PSP Test App Simple test app based on rust-psp. Demonstrating the usage of C libs. Build Download and unzip the prebuilt PSPSDK (built from clang-psp)

Yifeng Wang 4 Nov 28, 2022
A cli based pastebin in Rust, but very insecure

pasta A cli based pastebin in Rust, but very insecure Use nightly toolchain to build rustup override set nightly When this program is running, you can

Snehit Sah 3 Mar 25, 2022