Summary
trans(F)*F (right Cauchy-Green) and F*trans(F) (left Cauchy-Green / Finger) are symmetric and positive-semidefinite for any F — no assumption on F required. The CAS currently derives neither annotation.
This is the highest-value case: C = FᵀF is the workhorse strain measure in the finite-strain / spectral pipeline, and downstream sym()-projector and eigen simplifications key off the symmetric annotation.
Math
- Symmetric:
(FᵀF)ᵀ = Fᵀ(Fᵀ)ᵀ = FᵀF. Likewise (FFᵀ)ᵀ = FFᵀ.
- PSD:
xᵀ(FᵀF)x = (Fx)ᵀ(Fx) = ‖Fx‖² ≥ 0. (Positive-definite iff F is invertible — not generally known, so only PSD is derivable unconditionally.)
Current behavior (probed)
trans(F)*F -> is_symmetric=0 is_positive_semidefinite=0 (expected: sym, PSD)
F*trans(F) -> is_symmetric=0 is_positive_semidefinite=0 (expected: sym, PSD)
No false positives — the annotation is simply dropped (sound but incomplete).
How to fix
Binary hook in the tensor·tensor mul operator, mirroring the existing orthogonal trans(Q)·Q → I fold. In include/numsim_cas/tensor/tensor_operators.h, tag_invoke(mul_fn, L&&, R&&) (the tensor×tensor overload), right after the orthogonal branch (~lines 164-169) and before returning the generic mul_base result:
// Build the product first (via mul_base visitor), then annotate.
// Gram form: trans(X)·X and X·trans(X) are symmetric PSD for any X.
if (lhs.get().rank() == 2 && rhs.get().rank() == 2 &&
(is_trans_of(lhs, rhs) || is_trans_of(rhs, lhs))) {
// ... obtain `result` from the mul_base visitor ...
if (result.is_valid()) {
result.data()->set_space({Symmetric{}, AnyTraceTag{}});
result.data()->tensor_algebra_assumptions().insert(positive_semidefinite{});
}
return result;
}
is_trans_of(a, b) already exists in this file (matches permute_indices_wrapper with {2,1} over b).
- Post-construction
set_space is hash-safe today because the n_ary hash excludes the space annotation — see the identical note on the existing skew branch (lines 118-124).
- Do not insert
positive_definite — F invertibility is not tracked.
How to test
tests/TensorSpacePropagationTest.h (and/or the #111 matrix in tests/TensorAnnotationMatrixTest.h):
auto F = mk("F", 3); // general, no assumption
EXPECT_TRUE(is_symmetric(trans(F) * F));
EXPECT_TRUE(is_positive_semidefinite(trans(F) * F));
EXPECT_TRUE(is_symmetric(F * trans(F)));
EXPECT_TRUE(is_positive_semidefinite(F * trans(F)));
EXPECT_FALSE(is_skew(trans(F) * F)); // safety: not skew
// Regression guard already present: A·B of two DISTINCT symmetric tensors
// must stay non-symmetric (do not over-generalize the pattern).
Also verify sym(trans(F)*F) now short-circuits to trans(F)*F.
Part of the tensor space-annotation completeness effort (umbrella below). Related: #228 (algebra-property annotations), #111 (annotation matrix).
Summary
trans(F)*F(right Cauchy-Green) andF*trans(F)(left Cauchy-Green / Finger) are symmetric and positive-semidefinite for anyF— no assumption onFrequired. The CAS currently derives neither annotation.This is the highest-value case:
C = FᵀFis the workhorse strain measure in the finite-strain / spectral pipeline, and downstreamsym()-projector and eigen simplifications key off the symmetric annotation.Math
(FᵀF)ᵀ = Fᵀ(Fᵀ)ᵀ = FᵀF. Likewise(FFᵀ)ᵀ = FFᵀ.xᵀ(FᵀF)x = (Fx)ᵀ(Fx) = ‖Fx‖² ≥ 0. (Positive-definite iffFis invertible — not generally known, so only PSD is derivable unconditionally.)Current behavior (probed)
No false positives — the annotation is simply dropped (sound but incomplete).
How to fix
Binary hook in the tensor·tensor
muloperator, mirroring the existing orthogonaltrans(Q)·Q → Ifold. Ininclude/numsim_cas/tensor/tensor_operators.h,tag_invoke(mul_fn, L&&, R&&)(the tensor×tensor overload), right after the orthogonal branch (~lines 164-169) and before returning the genericmul_baseresult:is_trans_of(a, b)already exists in this file (matchespermute_indices_wrapperwith{2,1}overb).set_spaceis hash-safe today because the n_ary hash excludes the space annotation — see the identical note on the existing skew branch (lines 118-124).positive_definite—Finvertibility is not tracked.How to test
tests/TensorSpacePropagationTest.h(and/or the#111matrix intests/TensorAnnotationMatrixTest.h):Also verify
sym(trans(F)*F)now short-circuits totrans(F)*F.Part of the tensor space-annotation completeness effort (umbrella below). Related: #228 (algebra-property annotations), #111 (annotation matrix).