finiteelement_macros/
lib.rs

1//! This library is used to define types that implement the trait  `FiniteElement`
2//!  
3//! The types are defined by procedural macros. To create a new type, one must first define an
4//! unit-like Structure and implement the trait `AutoImplementable` for it. Once the trait
5//! `AutoImplementable` has been implemented it is possible to define a proc macro that will
6//! generate the deffinition of a new type and an implementation of the trait `FiniteElement` for
7//! it.
8//!
9//! # Creation of a new macro
10//!
11//! To create a new macro, one must first define a Zero-Sized `struct`, and implement the trait
12//! `AutoImplementable` for it. For example if we want to create an element representing a spring,
13//! we first create a zero-sized `struct`: `pub struct _Spring{}` and the implement the trait
14//! `Autotimplementable` for it.
15//!
16//! The types that implement the trait `AutoImplementable` can be passed as type argument to the
17//! function `macro_def<F: Float, T: AutoImplementable<F>>() -> TokenStream`. This function
18//! can be used to define a procedural macro that will generate the code defining the
19//! corresponding structure and its implementation of the trait `FiniteElement`. 
20//! Complete example
21//! (copied-pasted from `spring.rs`)
22//! ```
23//!
24//!use crate::formal::{Formal, FormalVector, FormalPoint, Float};
25//!use crate::autoimplementable::AutoImplementable;
26//!
27//!use std::collections::HashMap;
28//!
29//!// A `Spring` likes it when `a` and `b` are at distance `l`, and
30//!// exerts a force of `k.(|ab| - l)` to achieve this.
31//!pub struct _Spring{}
32//!
33//!impl<F: Float> AutoImplementable<F> for _Spring {
34//!    fn struct_name() -> String {
35//!        String::from("Spring")
36//!    }
37//!
38//!    fn elt_list() -> Vec<String> {
39//!        vec![String::from("a"), String::from("b")]
40//!    }
41//!
42//!    fn cst_list() -> Vec<String> {
43//!        vec![String::from("l"), String::from("k")]
44//!    }
45//!
46//!    fn formal_map() -> HashMap<String, FormalVector<F>> {
47//!    //Create a `Formal` for each element coordiate and each constants
48//!        let point_a = FormalPoint {
49//!            x: Formal::new_var(0),
50//!            y: Formal::new_var(1),
51//!            z: Formal::new_var(2)
52//!        };
53//!
54//!        let point_b = FormalPoint {
55//!            x: Formal::new_var(3),
56//!            y: Formal::new_var(4),
57//!            z: Formal::new_var(5)
58//!        };
59//!
60//!        let cst_l = Formal::new_var(6);
61//!        let cst_k = Formal::new_var(7);
62//!
63//!        // The force applied on point a is k(|ab| - l) * ab/|ab|
64//!        let ab = point_b - point_a;
65//!        let force_a: FormalVector<F> = (ab.clone().norm() - cst_l.clone()) * ab.clone()/ab.clone().norm() * cst_k.clone();
66//!
67//!        // The force applied on point b is k(|ba| - l) * ba/|ba|
68//!        let force_b = (ab.clone().norm() - cst_l.clone()) * ab.clone()/ab.clone().norm() * cst_k.clone() * Formal::new_cst(F::one().neg());
69//!        let mut ret = HashMap::new();
70//!        ret.insert(String::from("a"), force_a);
71//!        ret.insert(String::from("b"), force_b);
72//!        ret
73//!    }
74//!
75//!}
76//!
77//!// Once the trait is implemented, we can write a procedural macro
78//!#[proc_macro]
79//!pub fn auto_impl_spring(_item: TokenStream) -> TokenStream {
80//!    macro_def::<f32, _Spring>()
81//!}
82//! ```
83//!
84//!
85//!
86
87extern crate proc_macro;
88
89
90
91/// Defines the trait `AutoImplementable`
92mod autoimplementable;
93/// Defines a type to represent mathematical formulas whose derivatives can be computed
94/// automatically
95mod formal;
96#[doc(hidden)]
97mod spring;
98#[doc(hidden)]
99mod stack;
100
101pub (crate) use autoimplementable::*;
102use proc_macro::TokenStream;
103use spring::_Spring;
104use stack::_Stack;
105
106/// A `Spring` likes it when `a` and `b` are at distance `l`, and
107/// exerts a force of `k.(|ab| - l)` to achieve this.
108#[proc_macro]
109pub fn auto_impl_spring(_item: TokenStream) -> TokenStream {
110    macro_def::<f32, _Spring>()
111}
112
113/// A `Stack` likes it when the angle between `ab` and `cd` is equal to `theta0`, and
114/// exerts a torque of `k.(theta - theta0)` to achieve this.
115#[proc_macro]
116pub fn auto_impl_stack(_item: TokenStream) -> TokenStream {
117    macro_def::<f32, _Stack<f32>>()
118}