pub mod bond_based;
pub mod integration;
pub mod neighbor_list;
pub mod state_based;
pub use bond_based::{BondBasedConfig, BondBasedSolver, IsotropicMaterial};
pub use integration::{BodyForce, DirichletBC, PdIntegrator};
pub use neighbor_list::{BucketGrid, NeighborList};
pub use state_based::{StateBasedConfig, StateBasedSolver};
pub trait PeridynamicMaterial: Send + Sync {
fn bond_force(&self, stretch: f64, xi: [f64; 3]) -> f64;
fn critical_stretch(&self) -> f64;
}
#[derive(Debug, Clone)]
pub struct PeridynamicState {
pub positions: Vec<[f64; 3]>,
pub displacements: Vec<[f64; 3]>,
pub velocities: Vec<[f64; 3]>,
pub damage: Vec<f64>,
pub n_particles: usize,
}
impl PeridynamicState {
pub fn new(positions: Vec<[f64; 3]>) -> Self {
let n = positions.len();
Self {
displacements: vec![[0.0, 0.0, 0.0]; n],
velocities: vec![[0.0, 0.0, 0.0]; n],
damage: vec![0.0; n],
n_particles: n,
positions,
}
}
#[inline]
pub fn current_position(&self, i: usize) -> [f64; 3] {
[
self.positions[i][0] + self.displacements[i][0],
self.positions[i][1] + self.displacements[i][1],
self.positions[i][2] + self.displacements[i][2],
]
}
}
#[derive(Debug, Clone, Copy)]
pub struct Bond {
pub i: usize,
pub j: usize,
pub xi: [f64; 3],
pub active: bool,
}
impl Bond {
#[inline]
pub fn reference_length(&self) -> f64 {
(self.xi[0] * self.xi[0] + self.xi[1] * self.xi[1] + self.xi[2] * self.xi[2]).sqrt()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum FailureMode {
NoBond,
StretchExceeded,
EnergyExceeded,
}