// Copyright (c) 2024 RustyTorch++ Team // Licensed under the Apache License, Version 2.0 //! Time integration schemes for dynamic analysis. use crate::assembly::SparseMatrix; use crate::error::FeaResult; use nalgebra::DVector; /// Newmark time integration scheme. #[derive(Debug)] pub struct NewmarkIntegrator { /// Newmark beta parameter pub beta: f64, /// Newmark gamma parameter pub gamma: f64, /// Time step pub dt: f64, } impl NewmarkIntegrator { /// Create average acceleration method (beta=0.25, gamma=0.5) pub fn average_acceleration(dt: f64) -> Self { Self { beta: 0.25, gamma: 0.5, dt, } } /// Create linear acceleration method (beta=1/6, gamma=0.5) pub fn linear_acceleration(dt: f64) -> Self { Self { beta: 1.0 / 6.0, gamma: 0.5, dt, } } /// Perform one time step pub fn step( &self, mass: &SparseMatrix, damping: &SparseMatrix, stiffness: &SparseMatrix, force: &DVector, displacement: &mut DVector, velocity: &mut DVector, acceleration: &mut DVector, ) -> FeaResult<()> { let dt = self.dt; let beta = self.beta; let gamma = self.gamma; // Predictors let disp_pred = &*displacement + dt * &*velocity + (0.5 - beta) * dt * dt * &*acceleration; let vel_pred = &*velocity + (1.0 - gamma) * dt * &*acceleration; // Effective stiffness matrix let k_eff = stiffness.clone() + &(mass.clone() * (1.0 / (beta * dt * dt))) + &(damping.clone() * (gamma / (beta * dt))); // Effective force let f_eff = force + &mass.multiply_vector(&((1.0 / (beta * dt * dt)) * &disp_pred))? + &damping.multiply_vector(&((gamma / (beta * dt)) * &vel_pred))?; // Solve for displacement increment using appropriate solver let delta_disp = self.solve_system(&k_eff, &f_eff)?; // Correctors *displacement = disp_pred + beta * dt * dt * &delta_disp; *velocity = vel_pred + gamma * dt * &delta_disp; *acceleration = (1.0 / (beta * dt * dt)) * (&delta_disp - dt * &*velocity - (0.5 - beta) * dt * dt * &*acceleration); Ok(()) } /// Solve the linear system K*x = f using appropriate method fn solve_system(&self, k: &SparseMatrix, f: &DVector) -> FeaResult> { // Use direct solver for well-conditioned systems k.solve_vector(f) } } /// Central difference time integration. #[derive(Debug)] pub struct CentralDifferenceIntegrator { pub dt: f64, } impl CentralDifferenceIntegrator { pub fn new(dt: f64) -> Self { Self { dt } } pub fn step( &self, mass: &SparseMatrix, damping: &SparseMatrix, stiffness: &SparseMatrix, force: &DVector, displacement_prev: &DVector, displacement_curr: &DVector, ) -> FeaResult> { let dt2 = self.dt * self.dt; // M*a_n = F_n - C*v_n - K*u_n let velocity = (displacement_curr - displacement_prev) / self.dt; let rhs = force - &damping.multiply_vector(&velocity)? - &stiffness.multiply_vector(displacement_curr)?; let acceleration = mass.solve_vector(&rhs)?; // u_{n+1} = 2*u_n - u_{n-1} + dt^2*a_n let displacement_next = 2.0 * displacement_curr - displacement_prev + &(dt2 * &acceleration); Ok(displacement_next) } }