Files
rustytorch/crates/specialized/rtx-fea/src/solvers/time_integration.rs
T
2026-03-04 00:08:42 +00:00

124 lines
3.6 KiB
Rust

// 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<f64>,
displacement: &mut DVector<f64>,
velocity: &mut DVector<f64>,
acceleration: &mut DVector<f64>,
) -> 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<f64>) -> FeaResult<DVector<f64>> {
// 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<f64>,
displacement_prev: &DVector<f64>,
displacement_curr: &DVector<f64>,
) -> FeaResult<DVector<f64>> {
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)
}
}