Damage TC, SiC/SiC et Gurson
En bref
Trois lois où un matériau perd sa raideur en se dégradant :
| opérateurs | pyrucast.model.damage_tc(fespace, kinematics, strain_measure="linear"), pyrucast.model.damage_sic_sic(fespace, kinematics, strain_measure="linear"), pyrucast.model.gurson(fespace, kinematics, strain_measure="linear") |
| tag | mechanical |
| type | domaine avec comportement (label() : "Damage" ; "Plasticity" pour Gurson) |
| éléments | 2-D, en plan ou en axisymétrie : TRI3, QUA4, TRI6, QUA8, QUA9 ; 3-D : TET4, PYRA5, PENTA6, HEX8, TET10, PENTA15, HEX20, HEX27 |
| cinématiques | plane_stress, plane_strain, axisymmetric, full_3d |
| loi | variables d’endommagement | ce qu’elle décrit |
|---|---|---|
damage_tc | \(d^+\), \(d^-\) | béton, traction et compression séparées |
damage_sic_sic | \(d_1\), \(d_2\), \(d_3\) | composite tissé, un endommagement par direction |
gurson | la porosité \(f\) | métal ductile, rupture par croissance de cavités |
Damage TC et SiC/SiC sont des lois d’endommagement, comme Mazars ; Gurson est une loi plastique.
Théorie
Le cadre de l’endommagement. La contrainte effective \(\tilde\sigma = D_\text{el} : \varepsilon\) est celle du matériau sain sous la même déformation ; la contrainte est sa version dégradée. Un moteur scalaire \(\tau\), construit sur \(\varepsilon\) ou \(\tilde\sigma\), alimente une variable d’histoire \(r = \max(r_0, \max_t \tau)\), qui ne décroît jamais, et l’endommagement est une fonction croissante de \(r\). Il n’y a pas de déformation permanente, et la mise à jour se fait en un pas, sans itérer.
Damage TC
Les parts positive et négative de la contrainte effective, découpées sur ses valeurs principales, sont dégradées chacune par sa variable :
\[ \sigma = (1 - d^+)\,\tilde\sigma^+ + (1 - d^-)\,\tilde\sigma^- . \]
Une fissure ouverte en traction qui se referme reprend donc toute la raideur en compression : c’est l’effet unilatéral, que le scalaire de Mazars ne peut pas rendre. Chaque variable a son moteur et son histoire :
\[ \tau^+ = \sqrt{\tilde\sigma^+ : \varepsilon}, \qquad \tau^- = \sqrt{\sqrt3\,\big|K\,\tilde\sigma^-_\text{oct} + \tilde\tau^-_\text{oct}\big|}, \qquad r_0^+ = \frac{f_t}{\sqrt E}, \quad r_0^- = \frac{f_c}{\sqrt E}, \]
l’énergie élastique de la part positive en traction, une mesure octaédrique (contrainte normale \(\tfrac13\operatorname{tr}\tilde\sigma^-\) et cisaillement) sensible au confinement en compression, avec \(K = 0{,}171\). L’adoucissement est exponentiel en traction, durcissant puis adoucissant en compression :
\[ d^+ = 1 - \frac{r_0^+}{r^+}\,e^{A_t(1 - r^+/r_0^+)}, \qquad d^- = 1 - \frac{r_0^-}{r^-}(1 - A_c) - A_c\,e^{2(1 - r^-/r_0^-)} . \]
SiC/SiC
Dans un composite tissé, la matrice fissure dans des plans normaux aux torons, et les fibres continuent de porter la charge : la raideur chute par direction. Chaque direction matériau \(i\) a son endommagement, piloté par la déformation dans les axes matériau \(\varepsilon^\text{mat} = R^{\mathsf T}\varepsilon R\) :
\[ \kappa_i = \max_t \langle\varepsilon^\text{mat}_{ii}\rangle_+, \qquad d_i = d_{\max,i}\Big(1 - e^{-(\kappa_i - \varepsilon_{0,i})/\varepsilon_{c,i}}\Big) \ \text{si } \kappa_i > \varepsilon_{0,i} . \]
Une direction comprimée n’est pas dégradée. La dégradation s’applique terme à
terme dans les axes matériau,
\(\sigma^\text{mat}_{ij} = \sqrt{1-d_i}\sqrt{1-d_j}\;\tilde\sigma^\text{mat}_{ij}\),
ce qui garde l’opérateur symétrique. Chaque \(d_i\) sature à \(d_{\max,i}\)
au lieu d’atteindre 1 : les fibres restent. Les axes sont ceux de
l’orthotropie, les vecteurs V1 (et V2 en 3-D) du
matériau ; l’élasticité, elle, est isotrope.
Gurson
La porosité \(f\) rétrécit la surface de charge :
\[ \Phi = \Big(\frac{q}{\sigma_y}\Big)^2 + 2\,q_1 f^* \cosh\!\Big(\frac{3\,q_2\,\sigma_m}{2\,\sigma_y}\Big) - \big(1 + q_3\,f^{*2}\big), \]
qui redonne von Mises à \(f = 0\). Le cosh rend la surface sensible à la
pression : les cavités croissent en traction triaxiale. Au-delà d’une porosité
critique \(f_c\), une porosité effective \(f^*\), bilinéaire en \(f\),
accélère la coalescence et atteint \(1/q_1\) à la porosité de rupture
\(f_f\). La porosité croît par conservation de la masse,
\(\dot f = (1 - f)\,\operatorname{tr}\dot\varepsilon^p\), à partir de sa valeur
initiale \(f_0\) ; la germination n’est pas modélisée. L’écoulement n’est
donc pas isochore. Le retour se fait par plan sécant à normale numérique,
comme celui d’Ottosen, et la tangente par
perturbation.
Variables
Selon la cinématique :
plane_stress, plane_strain | axisymmetric | full_3d | |
|---|---|---|---|
| primales | u_x, u_y | u_x, u_y | u_x, u_y, u_z |
| duales | f_x, f_y | f_x, f_y | f_x, f_y, f_z |
| entrée du comportement | eps_xx, eps_yy, eps_xy | eps_xx, eps_yy, eps_zz, eps_xy | eps_xx, eps_yy, eps_zz, eps_yz, eps_xz, eps_xy |
| contrainte | sigma_xx, sigma_yy, sigma_xy | sigma_xx, sigma_yy, sigma_zz, sigma_xy | sigma_xx, sigma_yy, sigma_zz, sigma_yz, sigma_xz, sigma_xy |
En axisymétrie, eps_zz et sigma_zz sont les composantes orthoradiales.
La sortie du comportement est la contrainte, suivie de l’état. Matériau
facultatif pour les trois lois : rho, alpha.
| loi | matériau requis | état, écrit après la contrainte | état relu (prev) |
|---|---|---|---|
damage_tc | E, nu, f_t, f_c, A_t, A_c | damage, r_plus, r_minus, d_plus, d_minus | r_plus, r_minus, d_plus, d_minus |
damage_sic_sic | E, nu, eps_0_1, eps_c_1, d_max_1, eps_0_2, eps_c_2, d_max_2, eps_0_3, eps_c_3, d_max_3, et les axes : V1X, V1Y en plan et en axisymétrie ; V1X, V1Y, V1Z, V2X, V2Y, V2Z en 3-D | damage, kappa_1, kappa_2, kappa_3, d_1, d_2, d_3 | kappa_1, kappa_2, kappa_3, d_1, d_2, d_3 |
gurson | E, nu, sigma_y, q_1, q_2, q_3, f_0, f_c, f_f | la déformation plastique eps_p_xx, eps_p_yy, eps_p_zz, eps_p_yz, eps_p_xz, eps_p_xy ; la déformation plastique cumulée p ; la déformation totale eps_xx, eps_yy, eps_zz, eps_yz, eps_xz, eps_xy ; et, en plane_stress et plane_strain, sigma_zz ; puis porosity | toute la sortie du pas précédent |
Ce qu’elles produisent
| raideur | élastique, non endommagée |
| masse | exige rho |
| géométrique | sous la contrainte sigma_* |
| tangente | aucune pour Damage TC et SiC/SiC (matrix.tangent lève une erreur) ; par perturbation pour Gurson |
| forces internes | \(\int B^{\mathsf T}\sigma\) |
Exemple
Une maille en traction sous Damage TC : seule la variable de traction croît.
modele = pyrucast.model.damage_tc(fes, "plane_stress")
materiaux = pyrucast.element_field.material_field(
modele,
[("E", 30e3), ("nu", 0.2), ("f_t", 3.0), ("f_c", 30.0), ("A_t", 0.9), ("A_c", 0.5)],
)
eps = pyrucast.element_field.strain(modele, u, materiaux)
etat = pyrucast.element_field.integrate_behavior(
modele, eps, materiaux, pyrucast.element_field.initial_state(modele, materiaux)
)
print(
etat[0].value(0, 0, "d_plus") > 0, etat[0].value(0, 0, "d_minus")
) # True 0.0 : traction seule
Côté Rust
Damage TC et SiC/SiC vivent dans src/models/damage/, Gurson dans
src/models/plasticity/gurson.rs. Une loi déclare l’état qu’elle relit.
L’état de repos que rend initial_state est nul, sauf la porosité de Gurson :
la loi déclare qu’elle part de f_0 (initial_internal_sources), et l’état
de repos la lit dans le matériau.
tests/damage_laws.rs vérifie qu’une fissure refermée reprend la charge en
compression, que l’écrasement laisse l’endommagement de traction intact,
qu’étirer un axe de tissage n’endommage que lui et sature à son plafond, que
la porosité de Gurson croît en traction triaxiale et qu’un métal poreux
plastifie avant un métal dense.
use pyrucast::aggregate::Aggregate;
use pyrucast::atoms::{ElementType, Node};
use pyrucast::containers::element_field::ElementField;
use pyrucast::containers::finite_element_space::FiniteElementSpace;
use pyrucast::containers::mesh::{Mesh, SubMesh};
use pyrucast::containers::model::Model;
use pyrucast::containers::node_field::{NodeField, SubNodeField};
use pyrucast::coords::Coords;
use pyrucast::handle::Handle;
use pyrucast::models::damage::law::DamageLaw;
use pyrucast::models::plasticity::law::PlasticLaw;
use pyrucast::models::tensor::Kinematics;
use pyrucast::ops::element_field::{
behavior::{initial_state, integrate},
deformation, material_field, StrainMeasure,
};
use pyrucast::ops::model;
use pyrucast::Result;
const AXES: [&str; 3] = ["x", "y", "z"];
const TC: &[(&str, f64)] = &[
("E", 30_000.0),
("nu", 0.2),
("f_t", 3.0),
("f_c", 30.0),
("A_t", 0.9),
("A_c", 0.5),
];
#[test]
fn a_closed_crack_carries_load_again() -> Result<()> {
let cube = Cube::damage(DamageLaw::DamageTc, TC)?;
// Stretch far enough to damage in tension…
let damaged = cube.step(&uniaxial(1.5e-3), &cube.rest()?)?;
let d_plus = damaged.var("d_plus")?;
let d_minus = damaged.var("d_minus")?;
assert!(d_plus > 0.1, "tension must damage (d⁺ = {d_plus})");
// …and the **compressive** damage is untouched: the crack has not crushed
// anything. That separation is the whole point of two variables.
assert!(
d_minus < 1e-12,
"compression must stay intact (d⁻ = {d_minus})"
);
// Now close the crack. The compressive stiffness is the undamaged one.
let closed = cube.step(&uniaxial(-1e-4), &damaged.field)?;
let intact = cube.step(&uniaxial(-1e-4), &cube.rest()?)?;
assert!(
(closed.sigma[0] - intact.sigma[0]).abs() < 1e-9 * intact.sigma[0].abs(),
"a closed crack must carry the full compressive stress: {} vs {}",
closed.sigma[0],
intact.sigma[0]
);
Ok(())
}