Minor update

This commit is contained in:
2022-06-19 15:09:53 +09:00
parent 7394a43d1f
commit 0d4f188c3b
7 changed files with 248 additions and 163 deletions

View File

@@ -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

View File

@@ -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
View 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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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]);
}
}

View 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");
}
}