forked from 1b-agent/fieldcraft-upstream
fem, solver: thermal strain in nonlinear static steps
Temperatures now strain the material in nonlinear steps instead of being refused. At finite strain the deformation gradient splits multiplicatively, F = F_m F_theta with F_theta = diag(1 + alpha_i dT) at each point: the material sees F_m and the loops run on the thermally expanded volume J_theta dV0 (mixed elements project det F_m), so the tangent stays consistent. At small strain the split is additive, and elements on their linear stiffness take the equivalent nodal forces as a dead load. The step's temperatures are its temperature loads, or the steady conduction of its temperature conditions and heat loads (one-way coupling, as the linear coupled step); both at once are refused. They ramp with the load factor from each material's reference temperature. Johnson-Cook plasticity softens at the point's temperature. Verified: free expansion and a fully constrained neo-Hookean block at 20 % thermal stretch, full and hybrid (exact); a bar held at its ends heated past yield (exact); the linear limit and the conducted temperatures against the linear solvers; tangents by central differences with a temperature field. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NmAttHhUZTokgPeEJia8sm
This commit is contained in:
1 parent
53adab54c2
commit
3f9e9e30d8
8 files changed
+492
-94
No files matched your search
@@ -353,9 +353,9 @@ pub fn solve_static(model: &Model, step: Option<&str>, limits: &Limits) -> Resul
|
||||
// loads.
|
||||
let (field, temperature) = match step.procedure {
|
||||
Procedure::CoupledTemperatureDisplacement {} => {
|
||||
let (labels, t) = crate::heat::temperatures(model, &resolved, step, limits)?;
|
||||
let at = |l: &u32| labels.binary_search(l).ok().and_then(|i| t.get(i)).copied();
|
||||
(Some(mesh.labels.iter().map(at).collect::<Vec<_>>()), Some(mesh.labels.iter().map(|l| at(l).unwrap_or(0.0)).collect()))
|
||||
let field = crate::heat::temperatures_at(model, &resolved, step, limits, &mesh.labels)?;
|
||||
let temperature = field.iter().map(|t| t.unwrap_or(0.0)).collect();
|
||||
(Some(field), Some(temperature))
|
||||
}
|
||||
_ => (temperature_loads(model, &resolved, &mesh, step)?, None),
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user