From b631f5e793516e210edebe5287d05b3586b574be Mon Sep 17 00:00:00 2001 From: miguelmaso Date: Mon, 10 Aug 2026 17:48:37 +0200 Subject: [PATCH 1/4] Third order contraction --- src/TensorAlgebra/Operations.jl | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/TensorAlgebra/Operations.jl b/src/TensorAlgebra/Operations.jl index 56ad7a1..2a92a82 100644 --- a/src/TensorAlgebra/Operations.jl +++ b/src/TensorAlgebra/Operations.jl @@ -472,7 +472,7 @@ end @inline @generated function ⊙₁₂₃³(H::TensorValue{D,D²}, V::VectorValue{D}) where {D, D²} - @assert D*D == D² "Fourth- and second-order tensors size mismatch" + @assert D*D == D² "Third- and first-order tensors size mismatch" str = "" for j in 1:D for i in 1:D @@ -487,12 +487,30 @@ end end +@inline @generated function ⊙₁¹²³(V::VectorValue{D}, H::TensorValue{D,D²}) where {D, D²} + @assert D*D == D² "Firts- and third-order tensors size mismatch" + str = "" + for k in 1:D + for j in 1:D + for i in 1:D + a = _flat_idx(i,j,k,D) + str *= "+V[$k]*H[$a]" + end + str *= "," + end + end + Meta.parse("TensorValue{$D,$D}($str)") +end + + Gridap.TensorValues.inner(H::TensorValue{4,4}, A::TensorValue{2,2}) = H ⊙₁₂₃₄³⁴ A Gridap.TensorValues.inner(H::TensorValue{9,9}, A::TensorValue{3,3}) = H ⊙₁₂₃₄³⁴ A Gridap.TensorValues.inner(H::TensorValue{2,4}, A::TensorValue{2,2}) = H ⊙₁₂₃²³ A Gridap.TensorValues.inner(H::TensorValue{3,9}, A::TensorValue{3,3}) = H ⊙₁₂₃²³ A Gridap.TensorValues.inner(H::TensorValue{2,4}, V::VectorValue{2}) = H ⊙₁₂₃³ V Gridap.TensorValues.inner(H::TensorValue{3,9}, V::VectorValue{3}) = H ⊙₁₂₃³ V +Gridap.TensorValues.inner(V::VectorValue{2}, H::TensorValue{2,4}) = V ⊙₁¹²³ H +Gridap.TensorValues.inner(V::VectorValue{3}, H::TensorValue{3,9}) = V ⊙₁¹²³ H Gridap.TensorValues.inner(V::VectorValue, H::TensorValue) = TensorValue(V.data) ⊙ H @@ -607,6 +625,10 @@ Gridap.TensorValues.dot(A::TensorValue{2,2}, B::TensorValue{4,4}) = contraction_ Gridap.TensorValues.dot(A::TensorValue{3,3}, B::TensorValue{9,9}) = contraction_IP_PJKL(A,B) Gridap.TensorValues.dot(A::TensorValue{2,4}, B::TensorValue{2,4}) = contraction_IJK_KLP(A,B) Gridap.TensorValues.dot(A::TensorValue{3,9}, B::TensorValue{3,9}) = contraction_IJK_KLP(A,B) +Gridap.TensorValues.dot(H::TensorValue{2,4}, V::VectorValue{2}) = H ⊙₁₂₃³ V +Gridap.TensorValues.dot(H::TensorValue{3,9}, V::VectorValue{3}) = H ⊙₁₂₃³ V +Gridap.TensorValues.dot(V::VectorValue{2}, H::TensorValue{2,4}) = V ⊙₁¹²³ H +Gridap.TensorValues.dot(V::VectorValue{3}, H::TensorValue{3,9}) = V ⊙₁¹²³ H """ From 83a7bdf4d503d2b00ecdf60ee4dfc405d79a1b2d Mon Sep 17 00:00:00 2001 From: miguelmaso Date: Mon, 10 Aug 2026 17:58:17 +0200 Subject: [PATCH 2/4] added tests --- src/TensorAlgebra/Operations.jl | 2 +- test/TestTensorAlgebra/TensorAlgebraTests.jl | 39 ++++++++++++++++++-- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/TensorAlgebra/Operations.jl b/src/TensorAlgebra/Operations.jl index 2a92a82..2369277 100644 --- a/src/TensorAlgebra/Operations.jl +++ b/src/TensorAlgebra/Operations.jl @@ -488,7 +488,7 @@ end @inline @generated function ⊙₁¹²³(V::VectorValue{D}, H::TensorValue{D,D²}) where {D, D²} - @assert D*D == D² "Firts- and third-order tensors size mismatch" + @assert D*D == D² "First- and third-order tensors size mismatch" str = "" for k in 1:D for j in 1:D diff --git a/test/TestTensorAlgebra/TensorAlgebraTests.jl b/test/TestTensorAlgebra/TensorAlgebraTests.jl index 8154c04..60a87a1 100644 --- a/test/TestTensorAlgebra/TensorAlgebraTests.jl +++ b/test/TestTensorAlgebra/TensorAlgebraTests.jl @@ -117,9 +117,10 @@ end @test contraction_IP_PJKL(A,H) == TensorValue(7.0, 10.0, 15.0, 22.0, 23.0, 34.0, 31.0, 46.0, 39.0, 58.0, 47.0, 70.0, 55.0, 82.0, 63.0, 94.0) @test contraction_IP_JPKL(A,H) == TensorValue(10.0, 14.0, 14.0, 20.0, 26.0, 38.0, 30.0, 44.0, 42.0, 62.0, 46.0, 68.0, 58.0, 86.0, 62.0, 92.0) - digits2(D) = [Float64(10i + 1j) for i in 1:D, j in 1:D] - digits3(D) = [Float64(100i + 10j + 1k) for i in 1:D, j in 1:D, k in 1:D] - digits4(D) = [Float64(1000i + 100j + 10k + 1l) for i in 1:D, j in 1:D, k in 1:D, l in 1:D] + digits1(D) = [Float64(i) for i in 1:D] + digits2(D) = [Float64(10i + j) for i in 1:D, j in 1:D] + digits3(D) = [Float64(100i + 10j + k) for i in 1:D, j in 1:D, k in 1:D] + digits4(D) = [Float64(1000i + 100j + 10k + l) for i in 1:D, j in 1:D, k in 1:D, l in 1:D] function reference_IJK_KLP(A::TensorValue{3,9}, B::TensorValue{3,9}) D = size(A, 1) @@ -137,6 +138,38 @@ end A = TensorValue{3,9}(digits3(3)...) B = TensorValue{3,9}(reverse(digits3(3))...) @test A · B == reference_IJK_KLP(A,B) + + function reference_IJK_K(A::TensorValue{3,9}, B::VectorValue{3}) + D = size(A,1) + C = zeros(Float64, D, D) + for i in 1:D, j in 1:D + s = zero(Float64) + for k in 1:D + s += A[_flat_idx(i, j, k, D)] * B[k] + end + C[i, j] = s + end + TensorValue{3,3}(C...) + end + + A = TensorValue{3,9}(digits3(3)...) + V = VectorValue{3}(digits1(3)...) + @test A · V == reference_IJK_K(A,B) + + function reference_I_IJK(A::VectorValue{3}, B::TensorValue{3,9}) + D = size(A,1) + C = zeros(Float64, D, D) + for j in 1:D, k in 1:D + s = zero(Float64) + for i in 1:D + s += A[i] * B[_flat_idx(i, j, k, D)] + end + C[j, k] = s + end + TensorValue{3,3}(C...) + end + + @test V · A == reference_I_IJK(V, A) end From 8668658e6e44d95b017234ff771afe9095651971 Mon Sep 17 00:00:00 2001 From: miguelmaso Date: Mon, 10 Aug 2026 18:31:02 +0200 Subject: [PATCH 3/4] fixed test --- test/TestTensorAlgebra/TensorAlgebraTests.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/TestTensorAlgebra/TensorAlgebraTests.jl b/test/TestTensorAlgebra/TensorAlgebraTests.jl index 60a87a1..5b101c5 100644 --- a/test/TestTensorAlgebra/TensorAlgebraTests.jl +++ b/test/TestTensorAlgebra/TensorAlgebraTests.jl @@ -137,7 +137,7 @@ end A = TensorValue{3,9}(digits3(3)...) B = TensorValue{3,9}(reverse(digits3(3))...) - @test A · B == reference_IJK_KLP(A,B) + @test A · B == reference_IJK_KLP(A, B) function reference_IJK_K(A::TensorValue{3,9}, B::VectorValue{3}) D = size(A,1) @@ -154,7 +154,7 @@ end A = TensorValue{3,9}(digits3(3)...) V = VectorValue{3}(digits1(3)...) - @test A · V == reference_IJK_K(A,B) + @test A · V == reference_IJK_K(A, V) function reference_I_IJK(A::VectorValue{3}, B::TensorValue{3,9}) D = size(A,1) From 7edf5a4fba4b86f652b52f870fd66aa81ba617ba Mon Sep 17 00:00:00 2001 From: miguelmaso Date: Mon, 10 Aug 2026 18:44:23 +0200 Subject: [PATCH 4/4] fixed index in contraction --- src/TensorAlgebra/Operations.jl | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TensorAlgebra/Operations.jl b/src/TensorAlgebra/Operations.jl index 2369277..bafdf12 100644 --- a/src/TensorAlgebra/Operations.jl +++ b/src/TensorAlgebra/Operations.jl @@ -477,13 +477,13 @@ end for j in 1:D for i in 1:D for k in 1:D - a = _flat_idx(j,k,D) - str *= "+H[$i,$a]*V[$k]" + a = _flat_idx(i,j,k,D) + str *= "+H[$a]*V[$k]" end str *= "," end end - Meta.parse("TensorValue{$D}($str)") + Meta.parse("TensorValue{$D,$D}($str)") end @@ -494,7 +494,7 @@ end for j in 1:D for i in 1:D a = _flat_idx(i,j,k,D) - str *= "+V[$k]*H[$a]" + str *= "+V[$i]*H[$a]" end str *= "," end