Minor update
This commit is contained in:
20
Cargo.toml
20
Cargo.toml
@@ -19,9 +19,7 @@ rand = "0.8.4"
|
||||
rand_pcg = "0.3.1"
|
||||
rand_distr = "0.4.1"
|
||||
doc-comment = "0.3.3"
|
||||
moldybrody_proc = {path = "moldybrody_proc"}
|
||||
itertools = "0.10.3"
|
||||
assert_approx_eq = "1.1.0"
|
||||
ndarray = "0.15.2"
|
||||
num-traits = "0.2.0"
|
||||
num-complex = "0.4.0"
|
||||
@@ -29,13 +27,29 @@ approx = {version = "0.5.0", features = ["num-complex"]}
|
||||
ndarray-linalg = {version = "0.14.1", features = ["openblas-system"]}
|
||||
# blas-src = {version = "0.8", features = ["openblas"] }
|
||||
# openblas-src = {version = "0.10.4", features = ["cblas", "system"]}
|
||||
moldybrody_proc = {path = "moldybrody_proc"}
|
||||
clap = { version = "3.1.14", features = ["derive"] }
|
||||
rayon = "1.5.3"
|
||||
crossbeam = "0.8.1"
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
"moldybrody_proc",
|
||||
]
|
||||
exclude = [
|
||||
"examples/reproduce",
|
||||
]
|
||||
|
||||
[features]
|
||||
default = ["parallel"]
|
||||
serial = []
|
||||
parallel = []
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = "0.3.4"
|
||||
|
||||
|
||||
[[bench]]
|
||||
name = "boundary_simple_plane"
|
||||
name = "par_iter_3"
|
||||
harness = false
|
||||
|
||||
|
||||
@@ -5,90 +5,6 @@ use syn::{parse_macro_input, DeriveInput, Data, Fields, Ident, Type};
|
||||
use std::iter;
|
||||
|
||||
|
||||
|
||||
#[proc_macro_derive(Mass)]
|
||||
pub fn derive_mass(item : TokenStream) -> TokenStream{
|
||||
let x = parse_macro_input!(item as DeriveInput);
|
||||
|
||||
let struct_name = x.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = x.generics.split_for_impl();
|
||||
|
||||
let names = match x.data{
|
||||
Data::Struct(ds) => {
|
||||
match ds.fields{
|
||||
Fields::Named(n) => {
|
||||
n.named
|
||||
},
|
||||
_ => {
|
||||
return err(Span::call_site(), "expected named fields, found unnamed or unit");
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return err(Span::call_site(), "expected struct, found enum or union");
|
||||
},
|
||||
};
|
||||
|
||||
let mass_ident = Ident::new("mass", proc_macro2::Span::call_site());
|
||||
for f in names.iter(){
|
||||
let ident = f.ident.clone().unwrap();
|
||||
if ident == mass_ident{
|
||||
let ty = f.ty.clone();
|
||||
let tokens = quote!{
|
||||
impl #impl_generics Mass<#ty> for #struct_name #ty_generics #where_clause {
|
||||
fn mass(&self) -> #ty{
|
||||
self.mass
|
||||
}
|
||||
}
|
||||
};
|
||||
return tokens.into();
|
||||
}
|
||||
}
|
||||
return err(Span::call_site(), "There is no fields of name 'mass' in struct");
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Charge)]
|
||||
pub fn derive_charge(item : TokenStream) -> TokenStream{
|
||||
let x = parse_macro_input!(item as DeriveInput);
|
||||
|
||||
let struct_name = x.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = x.generics.split_for_impl();
|
||||
|
||||
let names = match x.data{
|
||||
Data::Struct(ds) => {
|
||||
match ds.fields{
|
||||
Fields::Named(n) => {
|
||||
n.named
|
||||
},
|
||||
_ => {
|
||||
return err(Span::call_site(), "expected named fields, found unnamed or unit");
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
return err(Span::call_site(), "expected struct, found enum or union");
|
||||
},
|
||||
};
|
||||
|
||||
let mass_ident = Ident::new("charge", proc_macro2::Span::call_site());
|
||||
for f in names.iter(){
|
||||
let ident = f.ident.clone().unwrap();
|
||||
if ident == mass_ident{
|
||||
let ty = f.ty.clone();
|
||||
let tokens = quote!{
|
||||
impl #impl_generics Charge<#ty> for #struct_name #ty_generics #where_clause {
|
||||
fn charge(&self) -> #ty{
|
||||
self.charge
|
||||
}
|
||||
}
|
||||
};
|
||||
return tokens.into();
|
||||
}
|
||||
}
|
||||
return err(Span::call_site(), "There is no fields of name 'charge' in struct");
|
||||
}
|
||||
|
||||
|
||||
#[proc_macro_derive(State)]
|
||||
pub fn derive_state(item : TokenStream) -> TokenStream{
|
||||
fn from_string(name : &str) -> Ident{
|
||||
@@ -125,7 +41,6 @@ pub fn derive_state(item : TokenStream) -> TokenStream{
|
||||
if ident == from_string("mass"){
|
||||
let ty = f.ty.clone();
|
||||
|
||||
|
||||
token = quote!{
|
||||
#token
|
||||
|
||||
@@ -138,7 +53,6 @@ pub fn derive_state(item : TokenStream) -> TokenStream{
|
||||
} else if ident == from_string("charge"){
|
||||
let ty = f.ty.clone();
|
||||
|
||||
|
||||
token = quote!{
|
||||
#token
|
||||
|
||||
@@ -148,6 +62,30 @@ pub fn derive_state(item : TokenStream) -> TokenStream{
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if ident == from_string("diff_const"){
|
||||
let ty = f.ty.clone();
|
||||
|
||||
token = quote!{
|
||||
#token
|
||||
|
||||
impl #impl_generics Diffusion<#ty> for #struct_name #ty_generics #where_clause {
|
||||
fn diff_const(&self) -> #ty{
|
||||
self.diff_const
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if ident == from_string("orientation"){
|
||||
let ty = f.ty.clone();
|
||||
|
||||
token = quote!{
|
||||
#token
|
||||
|
||||
impl #impl_generics Orientation<#ty> for #struct_name #ty_generics #where_clause {
|
||||
fn orientation(&self) -> #ty{
|
||||
self.orientation
|
||||
}
|
||||
}
|
||||
};
|
||||
} else if ident == from_string("pos"){
|
||||
ty_pos = Some(f.ty.clone());
|
||||
} else if ident == from_string("vel"){
|
||||
|
||||
29
src/approx/langevin.rs
Normal file
29
src/approx/langevin.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use crate::approx::ApproxOverdampedLangevin;
|
||||
use crate::approx::State;
|
||||
use crate::approx::Vector;
|
||||
use crate::state::DiffusionFloat;
|
||||
use std::ops::Add;
|
||||
use std::ops::Mul;
|
||||
|
||||
macro_rules! impl_langevin_float {
|
||||
($ty : ident) => {
|
||||
impl<'a, S, P> ApproxOverdampedLangevin<'a, P, $ty> for S
|
||||
where
|
||||
S: State<Movement = P, Position = P> + DiffusionFloat<$ty>,
|
||||
P: Vector<Item = $ty> + Add<Output = P> + 'a,
|
||||
&'a P: Mul<$ty, Output = P>,
|
||||
{
|
||||
/// Pure diffusion
|
||||
fn euler_pure_diffusion(&'a self, random_force: &'a P, dt: $ty) -> P {
|
||||
random_force * (self.diff_const() * dt.sqrt())
|
||||
}
|
||||
|
||||
fn euler_with_drift(&'a self, force: &'a P, random_force: &'a P, dt: $ty) -> P {
|
||||
force * (self.diff_const() * dt) + random_force * (self.diff_const() * dt.sqrt())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_langevin_float!(f32);
|
||||
impl_langevin_float!(f64);
|
||||
51
src/lib.rs
51
src/lib.rs
@@ -13,19 +13,20 @@
|
||||
//! ```
|
||||
|
||||
extern crate doc_comment;
|
||||
extern crate num_traits;
|
||||
extern crate ndarray;
|
||||
extern crate num_traits;
|
||||
|
||||
pub mod vector;
|
||||
pub mod state;
|
||||
pub mod vector;
|
||||
// pub mod system;
|
||||
pub mod approx;
|
||||
pub mod boundary;
|
||||
// pub mod force;
|
||||
// pub mod approx;
|
||||
pub mod force;
|
||||
// pub mod analysis;
|
||||
pub mod format_convert;
|
||||
pub mod iterator;
|
||||
pub mod rng;
|
||||
|
||||
|
||||
pub(crate) mod error;
|
||||
pub mod prelude;
|
||||
|
||||
@@ -33,32 +34,28 @@ pub mod prelude;
|
||||
// Todo
|
||||
//
|
||||
// Common
|
||||
// Argument information auto-complete
|
||||
// Argument parsing
|
||||
// Argument information auto-complete
|
||||
// Argument parsing
|
||||
//
|
||||
// System
|
||||
// Continuous : Rectangular, Circular
|
||||
// Point & Boundary로 정의됨.
|
||||
// Boundary condition check
|
||||
// Periodic
|
||||
// Reflective
|
||||
// Robin
|
||||
// etc
|
||||
// Continuous : Rectangular, Circular
|
||||
// Point & Boundary로 정의됨.
|
||||
// Boundary condition check
|
||||
// Periodic
|
||||
// Reflective
|
||||
// Robin
|
||||
// etc
|
||||
// Point
|
||||
// Associated with System
|
||||
// Vector operation : Add, Scalar Multiplication, Sub, Dot, cross
|
||||
// Associated with System
|
||||
// Vector operation : Add, Scalar Multiplication, Sub, Dot, cross
|
||||
// Boundary
|
||||
// 경계면은 대부분 함수로 정의됨.
|
||||
// 경계면은 대부분 함수로 정의됨.
|
||||
// Agent
|
||||
// Single-ptl : Global Interaction, Brownian, Active motion, Levy walk
|
||||
// Double-ptl : Central forces
|
||||
// Move
|
||||
// Single-ptl : Global Interaction, Brownian, Active motion, Levy walk
|
||||
// Double-ptl : Central forces
|
||||
// Move
|
||||
// Approximation
|
||||
// First order approximation : Newtonian / Stochastic
|
||||
// Second .. : Newtonian / Stochastic
|
||||
// Forces to Displacement
|
||||
// First order approximation : Newtonian / Stochastic
|
||||
// Second .. : Newtonian / Stochastic
|
||||
// Forces to Displacement
|
||||
// Analysis
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
pub use moldybrody_proc::{State};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub use crate::{
|
||||
// system::{Point, Topology},
|
||||
@@ -25,10 +27,6 @@ pub(crate) use crate::{
|
||||
error::{Result, Error, ErrorCode},
|
||||
};
|
||||
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use moldybrody_proc::{Point, Topology, Mass};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use rand_pcg::Pcg64;
|
||||
|
||||
@@ -50,6 +48,5 @@ pub(crate) use std::{
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use std::f64::consts::PI;
|
||||
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use assert_approx_eq::assert_approx_eq;
|
||||
|
||||
|
||||
|
||||
127
src/state.rs
127
src/state.rs
@@ -7,33 +7,46 @@
|
||||
|
||||
use crate::vector::Vector;
|
||||
|
||||
pub trait State{
|
||||
type Movement : Vector;
|
||||
type Position : Vector;
|
||||
pub trait State {
|
||||
type Movement: Vector;
|
||||
type Position: Vector;
|
||||
|
||||
fn pos(&self) -> &Self::Position;
|
||||
fn pos_mut(&mut self) -> &mut Self::Position;
|
||||
|
||||
fn disp<'a>(&self, movement : &'a Self::Movement) -> &'a Self::Position;
|
||||
fn disp<'a>(&self, movement: &'a Self::Movement) -> &'a Self::Position;
|
||||
|
||||
fn renew_state(&mut self, movement : &Self::Movement);
|
||||
fn renew_state(&mut self, movement: &Self::Movement);
|
||||
}
|
||||
|
||||
|
||||
pub trait HasVelocity : State{
|
||||
|
||||
pub trait HasVelocity: State {
|
||||
fn vel(&self) -> &<Self as State>::Position;
|
||||
fn vel_mut(&mut self) -> &mut <Self as State>::Position;
|
||||
}
|
||||
|
||||
pub trait Mass<T>{
|
||||
pub trait Mass<T>: State {
|
||||
fn mass(&self) -> T;
|
||||
}
|
||||
|
||||
pub trait Charge<T>{
|
||||
pub trait Charge<T>: State {
|
||||
fn charge(&self) -> T;
|
||||
}
|
||||
|
||||
pub trait DiffusionFloat<T>: State {
|
||||
fn diff_const(&self) -> T;
|
||||
}
|
||||
|
||||
pub trait DiffusionInt<T>: State {
|
||||
fn diff_time(&self) -> T;
|
||||
}
|
||||
|
||||
pub trait Orientation<P>: State
|
||||
where
|
||||
P: Vector,
|
||||
{
|
||||
fn orientation(&self) -> P;
|
||||
}
|
||||
|
||||
// pub trait GeneralState : State<T, N>{
|
||||
// type Position : Vector;
|
||||
// type Velocity : Vector;
|
||||
@@ -45,7 +58,6 @@ pub trait Charge<T>{
|
||||
// fn vel_mut(&mut self) -> &mut Self::Velocity;
|
||||
// }
|
||||
|
||||
|
||||
// pub trait OverdampedState : State{
|
||||
// type Position : Vector;
|
||||
|
||||
@@ -55,34 +67,42 @@ pub trait Charge<T>{
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::vector::product::Norm;
|
||||
// use approx::assert_abs_diff_eq;
|
||||
|
||||
use super::*;
|
||||
use crate::prelude::{Mass, Charge, State};
|
||||
use crate::vector::{Cartessian2D};
|
||||
use crate::prelude::State;
|
||||
use crate::vector::product::Norm;
|
||||
use crate::vector::Cartessian2D;
|
||||
|
||||
#[test]
|
||||
fn test_derive_macro(){
|
||||
|
||||
#[derive(Mass, Charge)]
|
||||
struct TestState{
|
||||
mass : f64,
|
||||
charge : f64,
|
||||
fn test_derive_macro() {
|
||||
#[derive(State)]
|
||||
struct TestState {
|
||||
mass: f64,
|
||||
charge: f64,
|
||||
#[allow(dead_code)]
|
||||
pos : Cartessian2D<f64>,
|
||||
pos: Cartessian2D<f64>,
|
||||
}
|
||||
|
||||
let test = TestState{mass : 0f64, charge : 0f64, pos : Cartessian2D::new([0f64, 0f64])};
|
||||
let test = TestState {
|
||||
mass: 0f64,
|
||||
charge: 0f64,
|
||||
pos: Cartessian2D::new([0f64, 0f64]),
|
||||
};
|
||||
assert!(test.mass() < 1e-30);
|
||||
assert!(test.charge() < 1e-30);
|
||||
|
||||
|
||||
#[derive(State)]
|
||||
struct TestState2{
|
||||
mass : f64,
|
||||
charge : f64,
|
||||
pos : Cartessian2D<f64>,
|
||||
struct TestState2 {
|
||||
mass: f64,
|
||||
charge: f64,
|
||||
pos: Cartessian2D<f64>,
|
||||
}
|
||||
let mut test = TestState2{mass : 0f64, charge : 0f64, pos : Cartessian2D::new([0f64, 0f64])};
|
||||
let mut test = TestState2 {
|
||||
mass: 0f64,
|
||||
charge: 0f64,
|
||||
pos: Cartessian2D::new([0f64, 0f64]),
|
||||
};
|
||||
assert!(test.mass() < 1e-30);
|
||||
assert!(test.charge() < 1e-30);
|
||||
assert!(test.pos().norm_l2() < 1e-30);
|
||||
@@ -91,26 +111,51 @@ mod test {
|
||||
assert!((test.pos().norm_l2() - 5f64.sqrt()).abs() < 1e-30);
|
||||
|
||||
#[derive(State)]
|
||||
struct TestState3{
|
||||
mass : f64,
|
||||
charge : f64,
|
||||
pos : Cartessian2D<f64>,
|
||||
vel : Cartessian2D<f64>,
|
||||
struct TestState3 {
|
||||
mass: f64,
|
||||
charge: f64,
|
||||
pos: Cartessian2D<f64>,
|
||||
vel: Cartessian2D<f64>,
|
||||
}
|
||||
let mut test = TestState3{mass : 0f64,
|
||||
charge : 0f64,
|
||||
pos : Cartessian2D::new([0f64, 0f64]),
|
||||
vel : Cartessian2D::new([0f64, 0f64])};
|
||||
let mut test = TestState3 {
|
||||
mass: 0f64,
|
||||
charge: 0f64,
|
||||
pos: Cartessian2D::new([0f64, 0f64]),
|
||||
vel: Cartessian2D::new([0f64, 0f64]),
|
||||
};
|
||||
assert!(test.mass() < 1e-30);
|
||||
assert!(test.charge() < 1e-30);
|
||||
assert!(test.pos().norm_l2() < 1e-30);
|
||||
assert!(test.vel().norm_l2() < 1e-30);
|
||||
let movement = (Cartessian2D::new([1f64, 2f64]), Cartessian2D::new([0f64, 1f64]));
|
||||
let movement = (
|
||||
Cartessian2D::new([1f64, 2f64]),
|
||||
Cartessian2D::new([0f64, 1f64]),
|
||||
);
|
||||
test.renew_state(&movement);
|
||||
assert!((test.pos().norm_l2() - 5f64.sqrt()).abs() < 1e-30);
|
||||
assert!((test.vel().norm_l2() - 1f64).abs() < 1e-30);
|
||||
|
||||
// #[derive(State)]
|
||||
// struct TestState4 {
|
||||
// diff_const: f64,
|
||||
// pos: Cartessian2D<f64>,
|
||||
// }
|
||||
// let test = TestState4 {
|
||||
// diff_const: 1f64,
|
||||
// pos: Cartessian2D::new([0f64; 2]),
|
||||
// };
|
||||
// assert_abs_diff_eq!(test.diff_const(), 1f64, epsilon = 1e-3);
|
||||
|
||||
// #[derive(State)]
|
||||
// struct TestState5 {
|
||||
// diff_const: [f64; 3],
|
||||
// pos: Cartessian2D<f64>,
|
||||
// }
|
||||
|
||||
// let test = TestState5 {
|
||||
// diff_const: [1f64, 2f64, 3f64],
|
||||
// pos: Cartessian2D::new([0f64; 2]),
|
||||
// };
|
||||
// assert_eq!(test.diff_const(), [1f64, 2f64, 3f64]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
65
src/vector/vector_serde.rs
Normal file
65
src/vector/vector_serde.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
use serde::{ser::{SerializeStruct, SerializeSeq}, Serialize, Serializer};
|
||||
use super::{Cartessian, CartessianND, arithmetic::Scalar};
|
||||
use std::slice::Iter;
|
||||
|
||||
struct Sequence<'a, T>(Iter<'a, T>);
|
||||
|
||||
impl<'a, T> Serialize for Sequence<'a, T>
|
||||
where T : Serialize{
|
||||
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer {
|
||||
let iter = &self.0;
|
||||
let mut seq = serializer.serialize_seq(Some(iter.len()))?;
|
||||
for elt in iter.clone(){
|
||||
seq.serialize_element(elt)?;
|
||||
}
|
||||
seq.end()
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================================
|
||||
|
||||
impl<T, const N : usize> Serialize for Cartessian<T, N>
|
||||
where T : Scalar + Serialize{
|
||||
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where S: Serializer {
|
||||
|
||||
let mut state = serializer.serialize_struct("Cartessian", 2)?;
|
||||
state.serialize_field("dim", &N)?;
|
||||
state.serialize_field("coord", &Sequence(self.into_iter()))?;
|
||||
state.end()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ========================================================
|
||||
|
||||
// impl<T> Serialize for CartessianND<T>
|
||||
// where T : Scalar + Serialize{
|
||||
|
||||
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
// where S: Serializer {
|
||||
|
||||
// let mut state = serializer.serialize_struct("CartessianND", 2)?;
|
||||
// state.serialize_field("dim", &self.dim())?;
|
||||
// state.serialize_field("coord", &Sequence(self.into_iter()))?;
|
||||
// state.end()
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::vector::CartessianND;
|
||||
|
||||
#[test]
|
||||
fn test_serde_cartessian(){
|
||||
let a = CartessianND::new(vec![0, 3]);
|
||||
println!("{:?}", serde_json::to_string(&a).unwrap());
|
||||
println!("Hello");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user