Typed Tensors (Tensor2 / Tensor4)
simcoon.Tensor2 and simcoon.Tensor4 are unified typed wrappers for 2nd-
and 4th-order tensors. A single object transparently represents either one tensor
or a batch (scipy Rotation style): shape (6,) / (6,6) is a single
tensor, (N,6) / (N,6,6) a batch. Tensor4 stores its data internally
in the Kelvin-Mandel convention, so the double contraction, inverse and
composition of 4th-order tensors become ordinary 6x6 linear algebra; the
engineering Voigt form is recovered on demand via .mat / .voigt.
Objects are built through typed factories, e.g. Tensor2.stress(v),
Tensor2.strain(v), Tensor4.stiffness(m), Tensor4.compliance(m),
Tensor4.from_voigt(v, type_str).
Batch operations
Batch contract, rotate, push_forward, pull_back and inverse
dispatch to vectorised kernels over the (N, ...) data.
Tip
Shared-tangent contraction is ~20x faster — pass a single Tensor4.
When the same 4th-order tensor is contracted against many 2nd-order tensors
(a shared elastic tangent applied at every integration point), pass a
single Tensor4 and contract it with a batch Tensor2:
L = Tensor4.stiffness(L6x6) # single (6,6)
eps = Tensor2.strain(eps_Nx6) # batch (N,6)
sig = L.contract(eps) # one BLAS GEMM -> ~20x
This collapses to a single L @ X matrix-matrix product (BLAS dgemm):
measured ~3.7 ns/point vs ~74 ns/point for the per-point path (N = 1e5).
The C++ batch_contract implements the same fast path when the tensor4
cube has a single slice (N4 == 1).
Anti-pattern: materialising the shared tangent as a tiled (N,6,6)
batch of identical slices — that forces N independent 6x6 matrix-vector
products and the GEMM speed-up is lost. Tile the tangent only when it
genuinely differs per point (a distinct consistent tangent, e.g. plasticity);
there a GEMM collapse is not possible and per-point evaluation is correct.
Note
A dedicated symmetric symtensor2 (Kelvin-Mandel 6-vector storage)
was benchmarked as a way to speed the general contraction path and
rejected: it yields only ~1.1x on a single contraction and ~1.07x on
realistic distinct-tangent batch work, and Armadillo fixed-size containers
negate the 6-vs-9-double storage saving. The real ~20x lever is the
shared-tangent GEMM path above, which needs no new type; Tensor2 stays
the general 3x3 type (it remains the only one able to hold a non-symmetric
tensor such as F, L, R).
API reference
- class simcoon.Tensor2(data)
A 2nd-order tensor with a type tag driving the Voigt convention and rotation dispatch.
A single object transparently represents either one tensor or a batch (scipy
Rotationstyle): the stored numpy array is(6,)for a single tensor and(N, 6)for a batch. The type is a string:"stress","strain","generic", or"none"; it selects the shear factors of the Voigt vector (2*e_ijfor strain,s_ijfor stress) and the rotation/transport rules.Construct through the typed factories (stress, strain, from_mat, from_voigt, from_mandel), never through
Tensor2(array).Examples
import numpy as np import simcoon as sim sigma = sim.Tensor2.stress(np.array([100., 50., 75., 0., 0., 0.])) sigma.mises() # von Mises equivalent stress eps = sim.Tensor2.strain(np.random.randn(1000, 6) * 0.01) # batch len(eps), eps[0] # 1000, single Tensor2
- classmethod concatenate(batches)
Join multiple batches and/or singles (all of the same type) into one batch.
- count(item)
Count occurrences of a single tensor in batch.
- dev()
Deviatoric part
t - tr(t)/3 I.- Returns:
Deviatoric tensor(s), same type tag.
- Return type:
- classmethod from_columns(arr, type_str)
Create a batch from a column-major array (C++ interop).
- Parameters:
arr (array_like) –
(6, N)array, one Voigt vector per column (the simcoon C++ batch convention).type_str (str) – One of
"stress","strain","generic","none".
- Returns:
Batch of N tensors.
- Return type:
- classmethod from_list(tensors)
Stack a list of single tensors (all of the same type) into a batch.
- classmethod from_mandel(v, type_str)
Create from a Kelvin-Mandel 6-vector (inverse of the mandel property).
- Parameters:
v (array_like) –
(6,)Kelvin-Mandel vector (sqrt(2)factor on shear terms, identical for stress and strain) or(N,6)batch.type_str (str) – One of
"stress","strain","generic","none".
- Returns:
Tensor(s) of the requested type.
- Return type:
- classmethod from_mat(m, type_str)
Create from a 3x3 matrix representation with an explicit type.
- Parameters:
m (array_like) –
(3,3)matrix or(N,3,3)batch of matrices.type_str (str) – One of
"stress","strain","generic","none".
- Returns:
Tensor(s) of the requested type.
- Return type:
- classmethod from_tensor(t, n)
Broadcast a single tensor to a batch of size
n(copies the data).
- classmethod from_voigt(v, type_str)
Create from a Voigt 6-vector with an explicit type.
- Parameters:
v (array_like) –
(6,)Voigt vector or(N,6)batch. Shear components follow the type convention (2*e_ijfor strain,s_ijfor stress).type_str (str) – One of
"stress","strain","generic","none".
- Returns:
Tensor(s) of the requested type.
- Return type:
- classmethod identity(type_str='stress')
Create the single identity tensor (Voigt
[1,1,1,0,0,0]) of the given type.
- is_symmetric(tol=1e-12)
Check symmetry of the 3x3 matrix representation (single only).
- Parameters:
tol (float, optional) – Absolute tolerance on the off-diagonal differences (default 1e-12).
- Return type:
bool
- property mandel
Kelvin-Mandel vector (sqrt2 on shear, identical for stress/strain): (6,) for single, (N,6) for batch. Returns a copy.
- property mat
(3,3) for single, (N,3,3) for batch.
- Type:
Matrix
- mises()
Von Mises equivalent (type-aware).
Uses the stress definition
sqrt(3/2 s_dev:s_dev)for stress/generic and the strain definitionsqrt(2/3 e_dev:e_dev)for strain.- Returns:
Scalar for a single tensor,
(N,)for a batch.- Return type:
float or numpy.ndarray
- norm()
Frobenius norm
sqrt(t_ij t_ij)(type-aware shear factors).- Returns:
Scalar for a single tensor,
(N,)for a batch.- Return type:
float or numpy.ndarray
- pull_back(F, metric=True)
Pull-back (current to reference configuration) via the deformation gradient.
Inverse of push_forward; same type-dependent transport and
metricsemantics.- Parameters:
F (array_like) –
(3,3)deformation gradient, or(N,3,3)batch.metric (bool, optional) –
True(default) includes theJ = det(F)factor.
- Returns:
Transported tensor(s), same type tag.
- Return type:
- push_forward(F, metric=True)
Push-forward (reference to current configuration) via the deformation gradient.
Type-dependent transport: stress is fully contravariant (
F s F^T, Piola with1/J), strain fully covariant (F^-T e F^-1).- Parameters:
F (array_like) –
(3,3)deformation gradient, or(N,3,3)batch (a single F is broadcast over a tensor batch).metric (bool, optional) –
True(default) includes theJ = det(F)factor (proper Piola transformation);Falseis pure transport.
- Returns:
Transported tensor(s), same type tag.
- Return type:
- rotate(R, active=True)
Rotate the tensor(s) by a rotation.
- Parameters:
R (simcoon.Rotation or scipy.spatial.transform.Rotation) – Rotation(s) to apply. On a batch, a single rotation is broadcast to all N tensors; a batch of N rotations is applied slice-wise.
active (bool, optional) –
True(default) rotates the tensor (active conventionQ A Q^T);Falserotates the frame (passive).
- Returns:
Rotated tensor(s), same type tag.
- Return type:
Examples
import numpy as np import simcoon as sim from scipy.spatial.transform import Rotation sigma = sim.Tensor2.stress(np.array([100., 0., 0., 0., 0., 0.])) R = Rotation.from_euler('z', 45, degrees=True) sigma_rot = sigma.rotate(R)
- property single
True if this is a single tensor, False if batch.
- classmethod strain(data)
Create strain tensor(s).
- Parameters:
data (array_like) –
(6,)Voigt vector (with2*e_ijshear terms),(3,3)matrix,(N,6)Voigt batch, or(N,3,3)matrix batch.- Returns:
Strain-typed tensor (single or batch, matching the input shape).
- Return type:
- classmethod stress(data)
Create stress tensor(s).
- Parameters:
data (array_like) –
(6,)Voigt vector,(3,3)matrix,(N,6)Voigt batch, or(N,3,3)matrix batch.- Returns:
Stress-typed tensor (single or batch, matching the input shape).
- Return type:
- trace()
Trace
t_kk.- Returns:
Scalar for a single tensor,
(N,)for a batch.- Return type:
float or numpy.ndarray
- property type
Type string.
- property voigt
(6,) for single, (N,6) for batch. Returns a copy.
- Type:
Voigt vector
- property voigt_T
(6, N) transposed Voigt array (batch only, for C++ interop).
- property vtype
Alias for type (backward compatibility).
- classmethod zeros(type_str='stress')
Create a single zero tensor of the given type (default
"stress").
- class simcoon.Tensor4(data)
A 4th-order tensor with a type tag driving rotation dispatch and Voigt factors.
A single object transparently represents either one tensor or a batch: the stored numpy array is
(6,6)(engineering Voigt) for a single tensor and(N,6,6)for a batch. The type is a string:"stiffness","compliance","strain_concentration","stress_concentration", or"generic"; it selects the Kelvin-Mandel congruence factors and the rotation/transport rules, and is propagated through operations (e.g.stiffness.inverse()is a compliance).The C++ backend works internally in the Kelvin-Mandel convention, so contraction, inverse and composition are plain 6x6 linear algebra; the engineering Voigt form is what mat / voigt expose.
Construct through the typed factories (stiffness, compliance, strain_concentration, stress_concentration, from_mat, from_mandel), never through
Tensor4(array).Examples
import numpy as np import simcoon as sim L = sim.Tensor4.stiffness(sim.L_iso([70000, 0.3], 'Enu')) eps = sim.Tensor2.strain(np.array([0.01, -0.003, -0.003, 0.005, 0., 0.])) sigma = L @ eps # contraction -> stress Tensor2 M = L.inverse() # compliance Tensor4
Note
The underlying C++
tensor4class uses a lazy mutable Fastor cache that is not thread-safe. However, the PythonTensor4class creates fresh C++ objects for each operation (via_to_cpp()), so Python-levelTensor4instances are safe to use from multiple threads (subject to the GIL).- classmethod compliance(data)
Create compliance tensor(s) from an engineering Voigt 6x6.
- Parameters:
data (array_like) –
(6,6)matrix (e.g. fromsim.M_iso) or(N,6,6)batch.- Return type:
- classmethod concatenate(batches)
Join multiple batches and/or singles (all of the same type) into one batch.
- contract(t)
Double contraction with a Tensor2 (also available as
L @ t).The output type follows the tensor4 type: stiffness and stress_concentration produce a stress, compliance and strain_concentration produce a strain.
- count(item)
Count occurrences of a single tensor in batch.
- classmethod deviatoric(type_str='stiffness')
Create the deviatoric projector
K = I - Jof the given type.
- classmethod from_list(tensors)
Stack a list of single tensors (all of the same type) into a batch.
- classmethod from_mandel(m, type_str)
Create from a Kelvin-Mandel 6x6 (inverse of the mandel property).
- Parameters:
m (array_like) –
(6,6)Kelvin-Mandel matrix (per-typesqrt(2)congruence factors) or(N,6,6)batch.type_str (str) – One of
"stiffness","compliance","strain_concentration","stress_concentration","generic".
- Return type:
- classmethod from_mat(m, type_str)
Create from an engineering Voigt 6x6 with an explicit type.
- Parameters:
m (array_like) –
(6,6)matrix or(N,6,6)batch.type_str (str) – One of
"stiffness","compliance","strain_concentration","stress_concentration","generic".
- Return type:
- classmethod from_tensor(t, n)
Broadcast a single tensor to a batch of size
n(copies the data).
- classmethod from_voigt(v, type_str)
Alias for from_mat (explicit counterpart of from_mandel).
- classmethod identity(type_str='stiffness')
Create the identity tensor of the given type (default
"stiffness").For every type the identity contracts to the unchanged field (
I : t == t); in Kelvin-Mandel it iseye(6).
- inverse()
Invert the tensor (plain 6x6 inverse in Kelvin-Mandel).
The type follows the algebra: stiffness ↔ compliance, concentration types keep their type, generic stays generic.
- Returns:
Inverse tensor(s) with the inferred type.
- Return type:
- property mandel
Kelvin-Mandel 6x6 (per-type sqrt2 congruence; identity = eye(6) for every type): (6,6) single, (N,6,6) batch. Returns a copy.
- property mat
(6,6) single, (N,6,6) batch. Returns a copy.
- Type:
6x6 matrix
- pull_back(F, metric=True)
Pull-back (current to reference configuration) via the deformation gradient.
Inverse of push_forward; same type-dependent transport and
metricsemantics.- Parameters:
F (array_like) –
(3,3)deformation gradient, or(N,3,3)batch.metric (bool, optional) –
True(default) includes theJ = det(F)factor.
- Returns:
Transported tensor(s), same type tag.
- Return type:
- push_forward(F, metric=True)
Push-forward (reference to current configuration) via the deformation gradient.
Type-dependent transport: stiffness is fully contravariant (
F⊗F : L : F^T⊗F^Twith1/J), compliance fully covariant. Concentration types raise (mixed variance, no pure transport).- Parameters:
F (array_like) –
(3,3)deformation gradient, or(N,3,3)batch (a single F is broadcast over a tensor batch).metric (bool, optional) –
True(default) includes theJ = det(F)factor;Falseis pure transport.
- Returns:
Transported tensor(s), same type tag.
- Return type:
- rotate(R, active=True)
Rotate the tensor(s) by a rotation (type-dependent Voigt congruence).
- Parameters:
R (simcoon.Rotation or scipy.spatial.transform.Rotation) – Rotation(s) to apply. On a batch, a single rotation is broadcast; a batch of N rotations is applied slice-wise.
active (bool, optional) –
True(default) rotates the tensor,Falsethe frame.
- Returns:
Rotated tensor(s), same type tag.
- Return type:
- property single
True if this is a single tensor, False if batch.
- classmethod stiffness(data)
Create stiffness tensor(s) from an engineering Voigt 6x6.
- Parameters:
data (array_like) –
(6,6)matrix (e.g. fromsim.L_iso) or(N,6,6)batch.- Return type:
- classmethod strain_concentration(data)
Create strain concentration tensor(s) (
De = A : Dmaps, e.g.sim.A_R(F)).Uses the engineering Voigt convention: the identity concentration is
eye(6)andA.contract(strain)returns a strain.- Parameters:
data (array_like) –
(6,6)matrix or(N,6,6)batch.- Return type:
- classmethod stress_concentration(data)
Create stress concentration tensor(s) (
s_local = B : smaps).- Parameters:
data (array_like) –
(6,6)matrix or(N,6,6)batch.- Return type:
- property type
Type string.
- property voigt
Alias for mat.
- classmethod volumetric(type_str='stiffness')
Create the volumetric (spherical) projector
J = 1/3 I⊗Iof the given type.
- classmethod zeros(type_str='stiffness')
Create a single zero tensor of the given type (default
"stiffness").
- simcoon.dyadic(a, b)
Dyadic (outer) product
C_ijkl = a_ij b_klof two single Tensor2.
- simcoon.auto_dyadic(a)
Dyadic product of a single Tensor2 with itself:
C_ijkl = a_ij a_kl-> stiffness Tensor4.
- simcoon.sym_dyadic(a, b)
Symmetric Voigt dyadic product
C = v(a) v(b)^Tof two single Tensor2 -> stiffness Tensor4.
- simcoon.auto_sym_dyadic(a)
Symmetric Voigt dyadic product of a single Tensor2 with itself -> stiffness Tensor4.
- simcoon.double_contract(a, b)
Double contraction
A_ij B_ijof two Tensor2 (single or batch).