1 unstable release
0.1.0 | Jul 15, 2019 |
---|
#16 in #formal
28 downloads per month
Used in finiteelement
34KB
746 lines
This library is used to define types that implement the trait FiniteElement
The types are defined by procedural macros. To create a new type, one must first define an
unit-like Structure and implement the trait AutoImplementable
for it. Once the trait
AutoImplementable
has been implemented it is possible to define a proc macro that will
generate the deffinition of a new type and an implementation of the trait FiniteElement
for
it.
Creation of a new macro
To create a new macro, one must first define a Zero-Sized struct
, and implement the trait
AutoImplementable
for it. For example if we want to create an element representing a spring,
we first create a zero-sized struct
: pub struct _Spring{}
and the implement the trait
Autotimplementable
for it.
The types that implement the trait AutoImplementable
can be passed as type argument to the
function macro_def<F: Float, T: AutoImplementable<F>>() -> TokenStream
. This function
can be used to define a procedural macro that will generate the code defining the
corresponding structure and its implementation of the trait FiniteElement
.
Complete example
(copied-pasted from spring.rs
)
use crate::formal::{Formal, FormalVector, FormalPoint, Float};
use crate::autoimplementable::AutoImplementable;
use std::collections::HashMap;
// A `Spring` likes it when `a` and `b` are at distance `l`, and
// exerts a force of `k.(|ab| - l)` to achieve this.
pub struct _Spring{}
impl<F: Float> AutoImplementable<F> for _Spring {
fn struct_name() -> String {
String::from("Spring")
}
fn elt_list() -> Vec<String> {
vec![String::from("a"), String::from("b")]
}
fn cst_list() -> Vec<String> {
vec![String::from("l"), String::from("k")]
}
fn formal_map() -> HashMap<String, FormalVector<F>> {
//Create a `Formal` for each element coordiate and each constants
let point_a = FormalPoint {
x: Formal::new_var(0),
y: Formal::new_var(1),
z: Formal::new_var(2)
};
let point_b = FormalPoint {
x: Formal::new_var(3),
y: Formal::new_var(4),
z: Formal::new_var(5)
};
let cst_l = Formal::new_var(6);
let cst_k = Formal::new_var(7);
// The force applied on point a is k(|ab| - l) * ab/|ab|
let ab = point_b - point_a;
let force_a: FormalVector<F> = (ab.clone().norm() - cst_l.clone()) * ab.clone()/ab.clone().norm() * cst_k.clone();
// The force applied on point b is k(|ba| - l) * ba/|ba|
let force_b = (ab.clone().norm() - cst_l.clone()) * ab.clone()/ab.clone().norm() * cst_k.clone() * Formal::new_cst(F::one().neg());
let mut ret = HashMap::new();
ret.insert(String::from("a"), force_a);
ret.insert(String::from("b"), force_b);
ret
}
}
// Once the trait is implemented, we can write a procedural macro
#[proc_macro]
pub fn auto_impl_spring(_item: TokenStream) -> TokenStream {
macro_def::<f32, _Spring>()
}
Dependencies
~1–1.4MB
~29K SLoC