From 8b0e2001378cee7d0bd830afcffe21a263d3af28 Mon Sep 17 00:00:00 2001 From: Miles Date: Tue, 17 Oct 2023 15:58:28 -0400 Subject: [PATCH 1/2] Fix fermion cases in blocksparse SVD --- NDTensors/src/blocksparse/linearalgebra.jl | 7 +++++-- test/base/test_fermions.jl | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/NDTensors/src/blocksparse/linearalgebra.jl b/NDTensors/src/blocksparse/linearalgebra.jl index 1c8732e05c..3ee0855b0e 100644 --- a/NDTensors/src/blocksparse/linearalgebra.jl +++ b/NDTensors/src/blocksparse/linearalgebra.jl @@ -184,9 +184,12 @@ function LinearAlgebra.svd(T::BlockSparseMatrix{ElT}; kwargs...) where {ElT} # This sign (sVP) accounts for the fact that # V is transposed, i.e. the index connecting to S # is the second index: - sVP = using_auto_fermion() ? -block_parity(vind, blockV[2]) : 1 + sVP = 1 + if using_auto_fermion() + sVP = block_parity(vind, blockV[2]) == 1 ? -1 : +1 + end - if (sV * sV) == -1 + if (sV * sVP) == -1 blockview(V, blockV) .= -Vb else blockview(V, blockV) .= Vb diff --git a/test/base/test_fermions.jl b/test/base/test_fermions.jl index 2a6ecefb2f..fe03c06713 100644 --- a/test/base/test_fermions.jl +++ b/test/base/test_fermions.jl @@ -699,7 +699,7 @@ import ITensors: Out, In T = ITensor(s[1], dag(s[2])) T[2, 2] = 1.0 U, S, V, spec, u, v = svd(T, s[1]) - @test_broken norm(T - U * S * V) ≈ 0 + @test norm(T - U * S * V) ≈ 0 UU = dag(U) * prime(U, u) @test norm(UU - id(u)) ≈ 0 VV = dag(V) * prime(V, v) @@ -711,7 +711,7 @@ import ITensors: Out, In T = ITensor(dag(s[1]), dag(s[2])) T[1, 2] = 1.0 U, S, V, spec, u, v = svd(T, s[1]) - @test_broken norm(T - U * S * V) ≈ 0 + @test norm(T - U * S * V) ≈ 0 UU = dag(U) * prime(U, u) @test norm(UU - id(u)) ≈ 0 VV = dag(V) * prime(V, v) From 350370bed6d9b94ab67cd093aa2ca245654557ca Mon Sep 17 00:00:00 2001 From: Miles Date: Tue, 17 Oct 2023 16:42:12 -0400 Subject: [PATCH 2/2] Define and use block_sign function --- NDTensors/src/blocksparse/fermions.jl | 1 + NDTensors/src/blocksparse/linearalgebra.jl | 2 +- src/physics/fermions.jl | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NDTensors/src/blocksparse/fermions.jl b/NDTensors/src/blocksparse/fermions.jl index 4acc85fe8e..3fdb96fd9c 100644 --- a/NDTensors/src/blocksparse/fermions.jl +++ b/NDTensors/src/blocksparse/fermions.jl @@ -1,4 +1,5 @@ block_parity(i, block) = 0 +block_sign(i, block) = 1 right_arrow_sign(i, block) = 1 left_arrow_sign(i, block) = 1 diff --git a/NDTensors/src/blocksparse/linearalgebra.jl b/NDTensors/src/blocksparse/linearalgebra.jl index 3ee0855b0e..2835d262c7 100644 --- a/NDTensors/src/blocksparse/linearalgebra.jl +++ b/NDTensors/src/blocksparse/linearalgebra.jl @@ -186,7 +186,7 @@ function LinearAlgebra.svd(T::BlockSparseMatrix{ElT}; kwargs...) where {ElT} # is the second index: sVP = 1 if using_auto_fermion() - sVP = block_parity(vind, blockV[2]) == 1 ? -1 : +1 + sVP = -block_sign(vind, blockV[2]) end if (sV * sVP) == -1 diff --git a/src/physics/fermions.jl b/src/physics/fermions.jl index 17270dfb6c..262721746e 100644 --- a/src/physics/fermions.jl +++ b/src/physics/fermions.jl @@ -107,6 +107,8 @@ end NDTensors.block_parity(i::QNIndex, block::Integer) = fparity(qn(i, block)) +NDTensors.block_sign(i::QNIndex, block::Integer) = 2 * NDTensors.block_parity(i, block) - 1 + function NDTensors.right_arrow_sign(i::QNIndex, block::Integer) !using_auto_fermion() && return 1 if dir(i) == Out && NDTensors.block_parity(i, block) == 1