use crate::{
constitutive::{
ConstitutiveError,
fluid::viscoplastic::{
Viscoplastic, ViscoplasticStateVariables, ViscoplasticStateVariablesHistory,
},
},
math::{
Matrix, Rank2, Tensor, TensorArray, Vector,
integrate::{ExplicitDaeFirstOrderRoot, ExplicitDaeZerothOrderRoot},
optimize::{EqualityConstraint, FirstOrderRootFinding, ZerothOrderRootFinding},
},
mechanics::{
DeformationGradient, DeformationGradients, FirstPiolaKirchhoffStress,
FirstPiolaKirchhoffTangentStiffness, Scalar, Times,
},
};
pub use crate::constitutive::solid::elastic_plastic::{AppliedLoad, ElasticPlasticOrViscoplastic};
pub trait ElasticViscoplastic<Y>
where
Self: ElasticPlasticOrViscoplastic + Viscoplastic<Y>,
Y: Tensor,
{
fn state_variables_evolution(
&self,
deformation_gradient: &DeformationGradient,
state_variables: &ViscoplasticStateVariables<Y>,
) -> Result<ViscoplasticStateVariables<Y>, ConstitutiveError> {
let deformation_gradient_p = &state_variables.0;
let jacobian = self.jacobian(deformation_gradient)?;
let deformation_gradient_e = deformation_gradient * deformation_gradient_p.inverse();
let cauchy_stress = self.cauchy_stress(deformation_gradient, deformation_gradient_p)?;
let mandel_stress = (deformation_gradient_e.transpose()
* cauchy_stress
* deformation_gradient_e.inverse_transpose())
* jacobian;
self.plastic_evolution(mandel_stress, state_variables)
}
}
pub trait ZerothOrderRoot<Y>
where
Y: Tensor,
{
fn root(
&self,
applied_load: AppliedLoad,
integrator: impl ExplicitDaeZerothOrderRoot<
ViscoplasticStateVariables<Y>,
DeformationGradient,
ViscoplasticStateVariablesHistory<Y>,
DeformationGradients,
>,
solver: impl ZerothOrderRootFinding<DeformationGradient>,
) -> Result<
(
Times,
DeformationGradients,
ViscoplasticStateVariablesHistory<Y>,
),
ConstitutiveError,
>;
}
pub trait FirstOrderRoot<Y>
where
Y: Tensor,
{
fn root(
&self,
applied_load: AppliedLoad,
integrator: impl ExplicitDaeFirstOrderRoot<
FirstPiolaKirchhoffStress,
FirstPiolaKirchhoffTangentStiffness,
ViscoplasticStateVariables<Y>,
DeformationGradient,
ViscoplasticStateVariablesHistory<Y>,
DeformationGradients,
>,
solver: impl FirstOrderRootFinding<
FirstPiolaKirchhoffStress,
FirstPiolaKirchhoffTangentStiffness,
DeformationGradient,
>,
) -> Result<
(
Times,
DeformationGradients,
ViscoplasticStateVariablesHistory<Y>,
),
ConstitutiveError,
>;
}
impl<C, Y> ZerothOrderRoot<Y> for C
where
C: ElasticViscoplastic<Y>,
Y: Tensor,
{
fn root(
&self,
applied_load: AppliedLoad,
integrator: impl ExplicitDaeZerothOrderRoot<
ViscoplasticStateVariables<Y>,
DeformationGradient,
ViscoplasticStateVariablesHistory<Y>,
DeformationGradients,
>,
solver: impl ZerothOrderRootFinding<DeformationGradient>,
) -> Result<
(
Times,
DeformationGradients,
ViscoplasticStateVariablesHistory<Y>,
),
ConstitutiveError,
> {
match match applied_load {
AppliedLoad::UniaxialStress(deformation_gradient_11, time) => {
let mut matrix = Matrix::zero(4, 9);
let mut vector = Vector::zero(4);
matrix[0][0] = 1.0;
matrix[1][1] = 1.0;
matrix[2][2] = 1.0;
matrix[3][5] = 1.0;
integrator.integrate(
|_: Scalar,
state_variables: &ViscoplasticStateVariables<Y>,
deformation_gradient: &DeformationGradient| {
Ok(self.state_variables_evolution(deformation_gradient, state_variables)?)
},
|_: Scalar,
state_variables: &ViscoplasticStateVariables<Y>,
deformation_gradient: &DeformationGradient| {
let deformation_gradient_p = &state_variables.0;
Ok(self.first_piola_kirchhoff_stress(
deformation_gradient,
deformation_gradient_p,
)?)
},
solver,
time,
(self.initial_state(), DeformationGradient::identity()),
|t: Scalar| {
vector[0] = deformation_gradient_11(t);
EqualityConstraint::Linear(matrix.clone(), vector.clone())
},
)
}
} {
Ok((times, state_variables, _, deformation_gradients)) => {
Ok((times, deformation_gradients, state_variables))
}
Err(error) => Err(ConstitutiveError::Upstream(
format!("{error}"),
format!("{self:?}"),
)),
}
}
}
impl<C, Y> FirstOrderRoot<Y> for C
where
C: ElasticViscoplastic<Y>,
Y: Tensor,
{
fn root(
&self,
applied_load: AppliedLoad,
integrator: impl ExplicitDaeFirstOrderRoot<
FirstPiolaKirchhoffStress,
FirstPiolaKirchhoffTangentStiffness,
ViscoplasticStateVariables<Y>,
DeformationGradient,
ViscoplasticStateVariablesHistory<Y>,
DeformationGradients,
>,
solver: impl FirstOrderRootFinding<
FirstPiolaKirchhoffStress,
FirstPiolaKirchhoffTangentStiffness,
DeformationGradient,
>,
) -> Result<
(
Times,
DeformationGradients,
ViscoplasticStateVariablesHistory<Y>,
),
ConstitutiveError,
> {
match match applied_load {
AppliedLoad::UniaxialStress(deformation_gradient_11, time) => {
let mut matrix = Matrix::zero(4, 9);
let mut vector = Vector::zero(4);
matrix[0][0] = 1.0;
matrix[1][1] = 1.0;
matrix[2][2] = 1.0;
matrix[3][5] = 1.0;
integrator.integrate(
|_: Scalar,
state_variables: &ViscoplasticStateVariables<Y>,
deformation_gradient: &DeformationGradient| {
Ok(self.state_variables_evolution(deformation_gradient, state_variables)?)
},
|_: Scalar,
state_variables: &ViscoplasticStateVariables<Y>,
deformation_gradient: &DeformationGradient| {
let deformation_gradient_p = &state_variables.0;
Ok(self.first_piola_kirchhoff_stress(
deformation_gradient,
deformation_gradient_p,
)?)
},
|_: Scalar,
state_variables: &ViscoplasticStateVariables<Y>,
deformation_gradient: &DeformationGradient| {
let deformation_gradient_p = &state_variables.0;
Ok(self.first_piola_kirchhoff_tangent_stiffness(
deformation_gradient,
deformation_gradient_p,
)?)
},
solver,
time,
(self.initial_state(), DeformationGradient::identity()),
|t: Scalar| {
vector[0] = deformation_gradient_11(t);
EqualityConstraint::Linear(matrix.clone(), vector.clone())
},
)
}
} {
Ok((times, state_variables, _, deformation_gradients)) => {
Ok((times, deformation_gradients, state_variables))
}
Err(error) => Err(ConstitutiveError::Upstream(
format!("{error}"),
format!("{self:?}"),
)),
}
}
}