diff --git a/src/algorithms/optimization/implicit_differentiation.jl b/src/algorithms/optimization/implicit_differentiation.jl index 6c7fd4e5c..f00632504 100644 --- a/src/algorithms/optimization/implicit_differentiation.jl +++ b/src/algorithms/optimization/implicit_differentiation.jl @@ -55,6 +55,10 @@ function GradientAlgorithm(; return alg_type(solver) end +# a `GradientAlgorithm` has no top-level `tol` field (it lives on `solver_alg`), so the +# default `MPSKit.DynamicTols._updatetol` (which sets `alg.tol`) doesn't apply +_updatetol(alg::GradientAlgorithm, tol::Real) = @set alg.solver_alg.tol = tol + # # Fixed-point gradient computation # @@ -95,10 +99,6 @@ end FixedPointGradient(; kwargs...) = GradientAlgorithm(; alg = :FixedPointGradient, kwargs...) GRADIENT_ALGORITHM_SYMBOLS[:FixedPointGradient] = FixedPointGradient -# `FixedPointGradient` has no top-level `tol` field (it lives on `solver_alg`), so the -# default `MPSKit.DynamicTols._updatetol` (which sets `alg.tol`) doesn't apply -_updatetol(alg::FixedPointGradient, tol::Real) = @set alg.solver_alg.tol = tol - const FIXEDPOINT_SOLVER_SYMBOLS = IdDict{Symbol, Type{<:Any}}( :GMRES => GMRES, :BiCGStab => BiCGStab, :Arnoldi => Arnoldi, ) diff --git a/src/environments/ctmrg_environments.jl b/src/environments/ctmrg_environments.jl index cabc0e764..ac1ee525e 100644 --- a/src/environments/ctmrg_environments.jl +++ b/src/environments/ctmrg_environments.jl @@ -328,6 +328,17 @@ function update!(env::CTMRGEnv{C, T}, env´::CTMRGEnv{C, T}) where {C, T} env.edges .= env´.edges return env end +# patch for the case where the corners are of a different type, which happens when running +# variational optimization using an implicit gradient +function update!(env::CTMRGEnv{C, T}, env´::CTMRGEnv{C´, T}) where {C, C´, T} + env.corners .= _convert_cornertype.(C, env´.corners) + env.edges .= env´.edges + return env +end +function _convert_cornertype(::Type{C}, c) where {C <: DiagonalTensorMap} + d = DiagonalTensorMap(c) + return scalartype(C) <: Real ? real(d) : d +end # Rotate corners & edges counter-clockwise function Base.rotl90(env::CTMRGEnv{C, T}) where {C, T} diff --git a/test/examples/heisenberg.jl b/test/examples/heisenberg.jl index 8441998f6..d6fd28e54 100644 --- a/test/examples/heisenberg.jl +++ b/test/examples/heisenberg.jl @@ -52,8 +52,8 @@ end @test all(@. ξ_h > 0 && ξ_v > 0) end -@testset "C4v AD optimization with scalartype T=$T and projector_alg=$projector_alg" for (T, projector_alg) in - Iterators.product([Float64, ComplexF64], [:C4vEighProjector, :C4vQRProjector]) +@testset "C4v AD optimization with scalartype T=$T, projector_alg=$projector_alg and gradient_alg=$gradient_alg" for (T, projector_alg, gradient_alg) in + Iterators.product([Float64, ComplexF64], [:C4vEighProjector, :C4vQRProjector], [:FixedPointGradient, :ImplicitGradient]) # initialize symmetric states Random.seed!(123456789) symm = RotateReflect() @@ -69,6 +69,7 @@ end H, peps₀, env₀; optimizer_alg = (; tol = gradtol, maxiter = 25), boundary_alg = (; alg = :C4vCTMRG, projector_alg, maxiter = 500), + gradient_alg = (; alg = gradient_alg), ) ξ_h, ξ_v, = correlation_length(peps, env) @info "Optimized energy = $E."