3 unstable releases

0.2.0 Oct 2, 2024
0.1.1 Jan 30, 2024
0.1.0 Jan 30, 2024

#519 in Math

MIT/Apache

245KB
3.5K SLoC

dexterior

Documentation Crates.io

dexterior provides building blocks for the discretization of partial differential equations using the mathematical framework of Discrete Exterior Calculus (DEC). These building blocks are sparse matrix operators (exterior derivative, Hodge star) and vector operands (cochains) associated with a simplicial mesh of any dimension. An effort is made to provide as many compile-time checks and type inference opportunities as possible to produce concise and correct code.

Additionally, dexterior provides some batteries-included tools for real-time visualization with wgpu in the optional visuals module.

Current state

This library is being built to facilitate the author's PhD studies and as such is developed with their use cases as first priority. The main library is already fairly far along in development, implementing most of PyDEC's functionality relevant to PDEs, but it hasn't been tested with many cases yet. Some known rough edges remain. The visuals crate is quite limited at the moment, supporting only a handful of 2D use cases, but built with an eventual extension to 3D in mind.

Example

To give you a taste of the basic features available, the following code implements a simple acoustic wave simulation:

use dexterior as dex;
use nalgebra::Vector2;

// type aliases for simulation variables ease readability
type Pressure = dex::Cochain<0, dex::Primal>;
type Velocity = dex::Cochain<1, dex::Primal>;

// meshes can be loaded from files generated with `gmsh`
let msh_bytes = include_bytes!("./examples/meshes/2d_square_pi_x_pi.msh");
let mesh = dex::gmsh::load_trimesh_2d(msh_bytes).expect("Failed to load mesh");

let dt = 0.1;
// generic operator expressed with its input and output type.
// type inference figures out which dimensions of `star` and `d` we need
// to make this expression match the type
let p_step: dex::Op<Velocity, Pressure> =
    -dt * mesh.star() * mesh.d() * mesh.star();
// type inference also knows which `d` we mean here
// because we multiply `p` by this operator later
let v_step = dt * mesh.d();

// integrate an initial state function into discrete cochains
let mut p: Pressure = mesh.integrate_cochain(dex::quadrature::Pointwise(
    |v: Vector2<f64>| f64::sin(3.0 * v.x) * f64::sin(2.0 * v.y)
));
let mut v: Velocity = mesh.new_zero_cochain();

// step the simulation forward in time
for _step in 0..10 {
    p += &p_step * &v;
    v += &v_step * &p;
}

A more complete version of this with visuals is in crates/dexterior/examples/membrane.rs. If you run it, it should look like this (but animated):

Simulation of a standing wave in a vibrating membrane with colors representing pressure and arrows pointing in the direction of velocity.

Note that the examples require the visuals feature, which isn't on by default, so you'll need to enable it with a flag:

cargo run --features visuals --example membrane
# or:
cargo run --all-features --example membrane

dexterior is largely inspired by the PyDEC library for Python, the most comprehensive implementation of DEC I know of. The accompanying paper PyDEC: Software and Algorithms for Discretization of Exterior Calculus by Hirani and Bell (2012) has been an invaluable aid in development.

More articles I wish to credit:

For a tutorial on the basics of DEC and in-depth explanations of the acoustics examples in this repo, see my master's thesis:

Additional recommendations for readers new to the topic or in need of a refresher:

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

Dependencies

~5–41MB
~669K SLoC