hermit.outputs

Postprocess a hermit.ShellState into scalar and field outputs.

Every function here takes the solved state and nothing else – the state back-references its domain, geometry, material, loads and boundary conditions. Scalar outputs return csdl.Variables; field outputs return hermit.Fields. All of them are differentiable in reverse mode, including with respect to the mesh coordinates when the solve was given a live geometry.

Functions

aggregated_stress(state, *[, rho, m, region, surface, ...])

Smooth aggregate of isotropic von Mises stress, (1/m) * pnorm**(1/rho).

center_of_gravity(state)

Mass-weighted centre of gravity, in global Cartesian coordinates.

compliance(state)

Work done by the applied loads on the solution.

displacement_field(state)

Mid-surface displacement as a field.

elastic_energy(state)

Stored shell strain energy.

failure_field(state, *[, sampling])

Per-cell, per-ply-face Tsai-Wu failure indices.

failure_index(state, *[, rho, sampling])

KS-aggregated Tsai-Wu failure index over the whole laminate.

mass(state)

Structural mass, int density * thickness dx.

nodal_displacement(state)

Displacements at the mesh vertices.

nodal_rotation(state)

Director rotations at the mesh vertices.

pnorm_stress(state, *[, rho, m, region, surface, ...])

Area-normalized p-norm stress integral, (1/A) int (m*vm)**rho dx.

rotation_field(state)

Director rotation as a field.

strain_fields(state, *[, space, method, frame])

Membrane strain, bending curvature and transverse shear.

stress_field(state, *[, space, method, surface])

Isotropic von Mises stress field.

stress_scaling(state, *[, surface, space, method])

Suggest the stress scaling m = 1 / max|von Mises| for the aggregates.

Module Contents

hermit.outputs.aggregated_stress(state, *, rho=100, m=1e-06, region=None, surface='top', quadrature_degree=None)

Smooth aggregate of isotropic von Mises stress, (1/m) * pnorm**(1/rho).

A differentiable stand-in for the peak stress, suitable as an optimizer constraint.

Parameters:
stateShellState
rhofloat, optional

Aggregation exponent. Default 100.

mfloat, optional

Stress scaling; see pnorm_stress(). Default 1e-6.

regionstr or int, optional

Restrict to a mesh-tagged region.

surface{‘top’, ‘bottom’, ‘mid’}, optional

Through-thickness station. Default 'top'.

quadrature_degreeint, optional

Overrides the domain’s degree for this integral.

Returns:
csdl.Variable

Scalar, in stress units.

Warns:
UserWarning

If m is degenerate for this problem, which would otherwise return a number that barely depends on the solution.

Notes

Approaches max(vm) from below as rho grows: this is the area-averaged integral p-norm, bounded above by the pointwise maximum, unlike the discrete log-sum-exp aggregate failure_index() uses.

Examples

>>> m = hm.stress_scaling(state)
>>> peak = hm.aggregated_stress(state, m=m)
hermit.outputs.center_of_gravity(state)

Mass-weighted centre of gravity, in global Cartesian coordinates.

Parameters:
stateShellState
Returns:
csdl.Variable

Shape (3,).

hermit.outputs.compliance(state)

Work done by the applied loads on the solution.

Parameters:
stateShellState
Returns:
csdl.Variable

Scalar. Conjugate to the exact Loads object that was solved, including edge and point terms.

hermit.outputs.displacement_field(state)

Mid-surface displacement as a field.

Parameters:
stateShellState
Returns:
Field

(3,) vector field on the displacement subspace of the element, in global Cartesian components.

See also

nodal_displacement

the same quantity at mesh vertices, in file order.

hermit.outputs.elastic_energy(state)

Stored shell strain energy.

Parameters:
stateShellState
Returns:
csdl.Variable

Scalar. For a linear solve this is half the compliance, up to the round-off of the direct solve.

Raises:
ValueError

If the material carries no A/B/D/As (a thickness_only() material).

hermit.outputs.failure_field(state, *, sampling='average')

Per-cell, per-ply-face Tsai-Wu failure indices.

Parameters:
stateShellState
sampling{‘average’, ‘midpoint’}, optional

How the DG0 strain measures are sampled per cell. Default 'average'.

Returns:
Field

DG0 field with one component per ply face.

Raises:
ValueError

If the material carries no layup. Only laminate() sets one.

hermit.outputs.failure_index(state, *, rho=100, sampling='average')

KS-aggregated Tsai-Wu failure index over the whole laminate.

Parameters:
stateShellState
rhofloat, optional

KS aggregation exponent. Default 100.

sampling{‘average’, ‘midpoint’}, optional

How the DG0 strain measures are sampled per cell. Default 'average'.

Returns:
csdl.Variable

Scalar. Below 1 means no ply face has failed; the log-sum-exp KS aggregate bounds the true maximum from above.

Raises:
ValueError

If the material carries no layup. Only laminate() sets one.

hermit.outputs.mass(state)

Structural mass, int density * thickness dx.

Parameters:
stateShellState
Returns:
csdl.Variable

Scalar.

hermit.outputs.nodal_displacement(state)

Displacements at the mesh vertices.

Parameters:
stateShellState
Returns:
csdl.Variable

Shape (n_nodes, 3), in file vertex order – the ordering an external geometry pipeline uses.

hermit.outputs.nodal_rotation(state)

Director rotations at the mesh vertices.

Parameters:
stateShellState
Returns:
csdl.Variable

Shape (n_nodes, 3), in file vertex order.

hermit.outputs.pnorm_stress(state, *, rho=100, m=1e-06, region=None, surface='top', quadrature_degree=None)

Area-normalized p-norm stress integral, (1/A) int (m*vm)**rho dx.

Parameters:
stateShellState
rhofloat, optional

Aggregation exponent. Default 100.

mfloat, optional

Stress scaling; see Notes. Default 1e-6.

regionstr or int, optional

Restrict the integral to a mesh-tagged region. Needs a domain built with cell_tags= and regions=.

surface{‘top’, ‘bottom’, ‘mid’}, optional

Through-thickness station the stress is recovered at. Default 'top'.

quadrature_degreeint, optional

Overrides the domain’s degree for this integral.

Returns:
csdl.Variable

Scalar.

Raises:
ValueError

If the material carries no E and nu (stress recovery is isotropic-only – use failure_index() for laminates), or if region= is given without mesh tags.

KeyError

If region is not among the mesh tags.

See also

aggregated_stress

the same quantity reduced back to stress units.

Notes

m is a problem-specific scaling, not a smoothing knob. It enters as (m*vm)**rho, so it must put m*max(vm) near 1 or the integrand runs off the end of double precision: with the default m and a peak von Mises of 1.4e4, (m*vm)**100 is 1e-186. Use stress_scaling() to compute one.

m must also be constant with respect to the design variables. It is not differentiated and cancels out of the aggregate exactly; recomputing it inside the recorded graph each optimizer iteration silently makes the reported derivative wrong.

hermit.outputs.rotation_field(state)

Director rotation as a field.

Parameters:
stateShellState
Returns:
Field

(3,) vector field on the rotation subspace of the element, in global Cartesian components.

hermit.outputs.strain_fields(state, *, space=('DG', 2), method='project', frame=None)

Membrane strain, bending curvature and transverse shear.

Parameters:
stateShellState
spacetuple, optional

Target space for all three fields. Default ("DG", 2).

method{‘project’, ‘interpolate’, ‘average’}, optional

Recovery method. 'average' is the DG0 cell average. Default 'project'.

frame{‘local’, ‘global’}, optional

Component frame. Defaults to the element-local in-plane frame on a DG space, and to global Cartesian on a CG space, where per-cell frames would be ambiguous at shared nodes.

Returns:
tuple of Field

(mid_strain, curvature, shear_strain). The component layout follows the frame: in the element-local frame the first two are in-plane engineering Voigt [xx, yy, 2xy] and the third is [xz, yz]; in the global frame they become full symmetric tensors, [xx, yy, zz, 2yz, 2xz, 2xy] and a 3-vector.

Raises:
ValueError

If method or frame is not one of the accepted values, or if a local frame is requested on a continuous (CG) space.

See also

hermit.Field.to_frame, hermit.Field.to_global

re-express the components.

Examples

>>> eps, kappa, gamma = hm.strain_fields(state)
>>> kappa_global = kappa.to_global().values
hermit.outputs.stress_field(state, *, space=('DG', 2), method='project', surface='top')

Isotropic von Mises stress field.

Parameters:
stateShellState
spacetuple, optional

Target space. Default ("DG", 2).

method{‘project’, ‘interpolate’, ‘average’}, optional

Recovery method. Default 'project'.

surface{‘top’, ‘bottom’, ‘mid’}, optional

Through-thickness station. Default 'top'.

Returns:
Field

Scalar field.

Raises:
ValueError

If the material carries no E and nu; von Mises recovery is isotropic-only. composite() accepts E= / nu= for this.

hermit.outputs.stress_scaling(state, *, surface='top', space=('DG', 2), method='project')

Suggest the stress scaling m = 1 / max|von Mises| for the aggregates.

Parameters:
stateShellState
surface{‘top’, ‘bottom’, ‘mid’}, optional

Through-thickness station. Default 'top'.

spacetuple, optional

Space the stress field is recovered on. Default ("DG", 2).

method{‘project’, ‘interpolate’, ‘average’}, optional

Field recovery method. Default 'project'.

Returns:
float

A plain Python float, deliberately: it is a snapshot taken outside the differentiated path, so it cannot contaminate the derivative of aggregated_stress().

Raises:
ValueError

If the stress field has no value (run under an inline csdl.Recorder), or if the peak is not finite and positive.

Notes

Costs one extra stress-field assembly. Call it once when setting a problem up, not inside an optimizer loop – a design-dependent m makes the reported gradient wrong even though the value looks better scaled.