tebdol

Simulation of ultracold atoms in optical lattices
git clone https://miroslavurbanek.com/git/tebdol.git
Log | Files | Refs | README

commit a425029cc2f8da8b54478f2b3539d8b4926114a3
parent 43e837ff846bd38b7766877c64515bc8fa8efd9e
Author: Miroslav Urbanek <mu@miroslavurbanek.com>
Date:   Wed, 28 Jun 2017 19:43:34 +0200

Add support for two-dimensional models

Two-dimensional states are represented as tree tensor network states
(TTNS). The time-evolution algorithm rearranges the network to apply a
two-site operator to each pair of adjacent sites.

Diffstat:
tebdol/mps.lisp | 10++--------
tebdol/tebd.lisp | 4+++-
tebdol/tebdol.asd | 5+++--
tebdol/tensor.lisp | 31+++++++++++++++++++++++++++++++
tebdol/ttns.lisp | 975+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1014 insertions(+), 11 deletions(-)

diff --git a/tebdol/mps.lisp b/tebdol/mps.lisp @@ -47,12 +47,6 @@ 1 0))))) -(defun val (tensor) - (let ((s (tensor-sectors tensor))) - (if s - (aref (sector-array (first s))) - +blas-0+))) - (defun right-singvals-tensor (index) (functional-tensor (list @@ -112,7 +106,7 @@ #'(lambda (s) (declare (ignore s)) 1))) (setf l (tensor-contract l '(0 1) r '(0 1))))) (if (= rank (1- size)) - (val l) + (tensor-scalar l) (mpi-send-object l (1+ rank))))) (defun mps-expectation-value (size rank length mpo submps) @@ -145,7 +139,7 @@ #'(lambda (s) (declare (ignore s)) 1))) (setf l (tensor-contract l '(0 1 2) r '(0 1 2))))) (if (= rank (1- size)) - (val l) + (tensor-scalar l) (mpi-send-object l (1+ rank))))) (defun save-metadata (dimension length particles pathname) diff --git a/tebdol/tebd.lisp b/tebdol/tebd.lisp @@ -1,6 +1,8 @@ (defpackage :tebd (:use :common-lisp :blas :tensor :mpi :mps) - (:export :make-mph-propagator + (:export :make-single-site-propagator + :make-double-site-propagator + :make-mph-propagator :make-uniform-propagator :tebd-evolve)) diff --git a/tebdol/tebdol.asd b/tebdol/tebdol.asd @@ -4,7 +4,7 @@ :description "TEBDOL is an implementation of the time-evolving block decimation algorithm for simulating evolution of ultracold atoms in optical lattices." - :version "0.2.0" + :version "0.3.0" :author "Miroslav Urbanek <miroslav.urbanek@mff.cuni.cz>" :licence "GPL-3+" :serial t @@ -18,4 +18,5 @@ (:file "mps") (:file "part") (:file "tebd") - (:file "bhm"))) + (:file "bhm") + (:file "ttns"))) diff --git a/tebdol/tensor.lisp b/tebdol/tensor.lisp @@ -24,6 +24,8 @@ :tensor-rank :tensor-dimensions :tensor-total-size + :tensor-scalar + :tensor-normalize :tensor-conjugate :tensor-contract :tensor-permute @@ -142,6 +144,35 @@ (defun tensor-total-size (tensor) (reduce #'+ (tensor-sectors tensor) :key #'(lambda (s) (array-total-size (sector-array s))))) +(defun tensor-scalar (tensor) + (let ((s (tensor-sectors tensor))) + (if s + (aref (sector-array (first s))) + +blas-0+))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; tensor-normalize + +(defun tensor-norm (tensor) + (sqrt + (loop + for s in (tensor-sectors tensor) + sum (expt (array-norm (sector-array s)) 2)))) + +(defun tensor-normalize (tensor) + (let ((n (tensor-norm tensor))) + (make-tensor + :indices + (tensor-indices tensor) + :sectors + (mapcar + #'(lambda (s) + (make-sector + :numbers (sector-numbers s) + :array (array-scalar-/ (sector-array s) n))) + (tensor-sectors tensor))))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; tensor-conjugate diff --git a/tebdol/ttns.lisp b/tebdol/ttns.lisp @@ -0,0 +1,975 @@ +(defpackage :ttns + (:use :common-lisp :tensor :bhm :tebd) + (:export :make-vacuum-ttns + :ttns-create-particle + :ttns-overlap + :compress-ttns + :make-ssps + :make-dsps + :ttns-tebd-evolve + :all-pn-operators + :all-pn + :print-pn)) + +(in-package :ttns) + +(defstruct site + id + subscript + bonds) + +(defstruct ttns + width + height + lattice + tensors) + +(defun site-by-id (ttns id) + (find id (ttns-lattice ttns) :key #'site-id :test #'equal)) + +(defun site-by-bond (ttns site bond) + (let ((i (cdr (assoc bond (site-bonds site))))) + (if i (svref (ttns-lattice ttns) i)))) + +(defun tensor-by-site (ttns site) + (svref (ttns-tensors ttns) (site-subscript site))) + +(defun (setf tensor-by-site) (tensor ttns site) + (setf + (svref (ttns-tensors ttns) (site-subscript site)) + tensor)) + +(defun tensor-at-site (ttns id) + (svref (ttns-tensors ttns) (site-subscript (site-by-id ttns id)))) + +(defun (setf tensor-at-site) (tensor ttns id) + (setf + (svref (ttns-tensors ttns) (site-subscript (site-by-id ttns id))) + tensor)) + +(defun make-rectangular-lattice (width height) + (flet ((subscript (i j) + (if (and (>= i 0) (< i width) (>= j 0) (< j height)) + (+ i (* j width))))) + (let ((a (make-array (* width height)))) + (dotimes (i width a) + (dotimes (j height) + (let ((s (subscript i j))) + (setf (svref a s) + (make-site + :id (list i j) + :subscript s + :bonds (list + (cons :x- (subscript (1- i) j)) + (cons :x+ (subscript (1+ i) j)) + (cons :y- (subscript i (1- j))) + (cons :y+ (subscript i (1+ j)))))))))))) + +(defun make-vacuum-ttns (width height dimension) + (let* ((l (make-rectangular-lattice width height)) + (a (make-array (length l)))) + (dotimes (i (length l) + (make-ttns :width width :height height :lattice l :tensors a)) + (setf (svref a i) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1))) + #'(lambda (s) (declare (ignore s)) 1)))))) + +(defun identity-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) + (declare (ignore s)) 1))) + +(defun xx-connecting-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '(-1) :dimension 1)) + (list (make-segment :numbers '( 1) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) (declare (ignore s)) 1))) + +(defun yy-connecting-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '(-1) :dimension 1)) + (list (make-segment :numbers '( 1) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) (declare (ignore s)) 1))) + +(defun xy-connecting-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '(-1) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 1) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) (declare (ignore s)) 1))) + +(defun x-creation-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '(-1) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) + (let ((n (- (first (subscript-numbers (sixth s)))))) + (sqrt (1+ n)))))) + +(defun y-creation-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (list (make-segment :numbers '(-1) :dimension 1)) + (list (make-segment :numbers '( 0) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) + (let ((n (- (first (subscript-numbers (sixth s)))))) + (sqrt (1+ n)))))) + +(defun pn-site-operator (dimension) + (functional-tensor + (list + (ket-physical-index dimension) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (list (make-segment :numbers '(0) :dimension 1)) + (bra-physical-index dimension)) + #'(lambda (s) + (- (first (subscript-numbers (sixth s))))))) + +(defun identity-operator (width height dimension) + (let* ((l (make-rectangular-lattice width height)) + (a (make-array (length l))) + (o (identity-site-operator dimension))) + (dotimes (i (length l) + (make-ttns + :width width + :height height + :lattice l + :tensors a)) + (setf (svref a i) o)))) + +(defun apply-and-fuse (operator ttns) + (let* ((l (length (ttns-lattice ttns))) + (o (ttns-tensors operator)) + (p (ttns-tensors ttns)) + (a (make-array l))) + (dotimes (i l + (make-ttns + :width (ttns-width ttns) + :height (ttns-height ttns) + :lattice (ttns-lattice ttns) + :tensors a)) + (setf (svref a i) + (tensor-fuse + (tensor-permute + (tensor-contract (svref o i) 5 (svref p i) 0) + '(0 1 3 5 7 2 4 6 8)) + '(1 3 5 7) + '(:normal :reverse :normal :reverse :normal)))))) + +(defun ttns-create-particle (ttns x y dimension) + (flet ((f (i j o) + (let ((s (site-subscript (site-by-id ttns (list i j)))) + (p (ttns-tensors ttns))) + (setf (svref p s) + (tensor-fuse + (tensor-permute + (tensor-contract o 5 (svref p s) 0) + '(0 1 3 5 7 2 4 6 8)) + '(1 3 5 7) + '(:normal :reverse :normal :reverse :normal)))))) + (loop + with o = (xx-connecting-site-operator dimension) + for i below x + do (f i 0 o)) + (loop + with o = (yy-connecting-site-operator dimension) + for i from 1 below y + do (f x i o)) + (if (zerop y) + (f x y (x-creation-site-operator dimension)) + (progn + (f x 0 (xy-connecting-site-operator dimension)) + (f x y (y-creation-site-operator dimension)))))) + +(defun pn-operator (width height x y dimension) + (let ((o (identity-operator width height dimension))) + (setf (tensor-at-site o (list x y)) + (pn-site-operator dimension)) + o)) + +(defun mps-boundary-tensor () + (let ((m (list (make-segment :numbers '(0) :dimension 1)))) + (functional-tensor + (list m m m) + #'(lambda (s) (declare (ignore s)) 1)))) + +(defun mps-overlap-boundary-tensor () + (let ((m (list (make-segment :numbers '(0) :dimension 1)))) + (functional-tensor + (list m m) + #'(lambda (s) (declare (ignore s)) 1)))) + +(defun terminate-dummy-index (tensor index) + (tensor-contract + tensor + index + (functional-tensor + (list (list (make-segment :numbers '(0) :dimension 1))) + #'(lambda (s) (declare (ignore s)) 1)) + 0)) + +(defun terminate-dummy-indices (tensor indices) + (reduce #'terminate-dummy-index indices :initial-value tensor)) + +(defun ttns-overlap-boundary-tensor (tensor1 tensor2) + (functional-tensor + (list (second (tensor-indices tensor2)) + (conjugate-index (second (tensor-indices tensor1)))) + #'(lambda (s) + (if (eql (subscript-subscript (first s)) + (subscript-subscript (second s))) + 1 + 0)))) + +(defun ttns-boundary-tensor (tensor1 tensor2) + (functional-tensor + (list (second (tensor-indices tensor2)) + (list (make-segment :numbers '(0) :dimension 1)) + (conjugate-index (second (tensor-indices tensor1)))) + #'(lambda (s) + (if (eql (subscript-subscript (first s)) + (subscript-subscript (third s))) + 1 + 0)))) + +(defun ttns-overlap (ttns1 ttns2) + (loop + with w = (ttns-width ttns1) + with h = (ttns-height ttns1) + with l = (ttns-overlap-boundary-tensor (tensor-at-site ttns1 '(0 0)) (tensor-at-site ttns2 '(0 0))) + for i below w + for u = (loop + for j from h above 0 + for v = (mps-overlap-boundary-tensor) + then (let ((t1 (terminate-dummy-indices (tensor-at-site ttns1 (list i j)) '(1 1))) + (t2 (terminate-dummy-indices (tensor-at-site ttns2 (list i j)) '(1 1)))) + (tensor-contract + (tensor-conjugate t2) + '(0 2) + (tensor-contract t1 2 v 1) + '(0 2))) + finally (return v)) + do + (let ((t1 (terminate-dummy-indices (tensor-at-site ttns1 (list i 0)) '(3))) + (t2 (terminate-dummy-indices (tensor-at-site ttns2 (list i 0)) '(3)))) + (setf l (tensor-contract + (tensor-conjugate t2) + '(1 3 0) + (tensor-contract l 1 (tensor-contract u 1 t1 3) 2) + '(0 1 2)))) + finally (return (tensor-scalar (tensor-contract l '(0 1) (mps-overlap-boundary-tensor) '(0 1)))))) + +(defun ttns-expectation (ttns1 ttns2 ttno) + (loop + with w = (ttns-width ttns1) + with h = (ttns-height ttns1) + with l = (ttns-boundary-tensor (tensor-at-site ttns1 '(0 0)) (tensor-at-site ttns2 '(0 0))) + for i below w + for u = (loop + for j from h above 0 + for v = (mps-boundary-tensor) + then (let ((t1 (terminate-dummy-indices (tensor-at-site ttns1 (list i j)) '(1 1))) + (t2 (terminate-dummy-indices (tensor-at-site ttns2 (list i j)) '(1 1))) + (to (terminate-dummy-indices (tensor-at-site ttno (list i j)) '(1 1)))) + (tensor-contract + (tensor-conjugate t2) + '(0 2) + (tensor-contract to '(2 3) (tensor-contract t1 2 v 2) '(3 0)) + '(0 3))) + finally (return v)) + do + (let ((t1 (terminate-dummy-indices (tensor-at-site ttns1 (list i 0)) '(3))) + (t2 (terminate-dummy-indices (tensor-at-site ttns2 (list i 0)) '(3))) + (to (terminate-dummy-indices (tensor-at-site ttno (list i 0)) '(3)))) + (setf l (tensor-contract + (tensor-conjugate t2) + '(0 1 3) + (tensor-contract + to + '(1 3 4) + (tensor-contract l 2 (tensor-contract u 2 t1 3) 3) + '(1 3 4)) + '(0 2 3)))) + finally (return (tensor-scalar (tensor-contract l '(0 1 2) (mps-boundary-tensor) '(0 1 2)))))) + +(defun normalize-tensor-by-site (ttns site bond) + (let ((u (site-by-bond ttns site bond))) + (case bond + (:x- (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns site) '(0 2 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns site) + (tensor-permute l '(0 2 3 4 1))) + (setf (tensor-by-site ttns u) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns u) 2) + '(2 0 1 3 4))))) + (:x+ (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns site) '(0 1 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns site) + (tensor-permute l '(0 1 3 4 2))) + (setf (tensor-by-site ttns u) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns u) 1) + '(1 0 2 3 4))))) + (:y- (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns site) '(0 1 2 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns site) + (tensor-permute l '(0 1 2 4 3))) + (setf (tensor-by-site ttns u) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns u) 4) + '(4 0 1 2 3))))) + (:y+ (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns site) '(0 1 2 3) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns site) l) + (setf (tensor-by-site ttns u) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns u) 3) + '(3 0 1 2 4)))))))) + +(defun compress-ttns (ttns dimension) + (let ((w (ttns-width ttns)) + (h (ttns-height ttns))) + ;; vertical top to bottom + (loop for i below w do + (loop for j from (1- h) above 0 do + (let* ((u (site-by-id ttns (list i j))) + (v (site-by-bond ttns u :y-))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns u) '(3) nil :right) + (declare (ignore s)) + (setf (tensor-by-site ttns u) + (tensor-permute r '(3 0 1 2 4))) + (setf (tensor-by-site ttns v) + (tensor-contract (tensor-by-site ttns v) 4 l 0)))))) + ;; horizontal left to right + (loop for i below (1- w) do + (let* ((u (site-by-id ttns (list i 0))) + (v (site-by-bond ttns u :x+))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns u) '(0 1 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns u) + (tensor-permute l '(0 1 3 4 2))) + (setf (tensor-by-site ttns v) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns v) 1) + '(1 0 2 3 4)))))) + ;; horizontal right to left + (loop for i from (1- w) downto 0 do + ;; vertical bottom to top + (loop for j from 0 below (1- h) do + (let* ((u (site-by-id ttns (list i j))) + (v (site-by-bond ttns u :y+))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns u) '(0 1 2 3) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns v) 3) + '(3 0 1 2 4)))))) + ;; vertical top to bottom with truncation + (loop for j from (1- h) above 0 do + (let* ((u (site-by-id ttns (list i j))) + (v (site-by-bond ttns u :y-))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns u) '(3) dimension :right) + (declare (ignore s)) + (setf (tensor-by-site ttns u) + (tensor-permute r '(3 0 1 2 4))) + (setf (tensor-by-site ttns v) + (tensor-contract (tensor-by-site ttns v) 4 l 0))))) + ;; right to left with truncation + unless (zerop i) do + (let* ((u (site-by-id ttns (list i 0))) + (v (site-by-bond ttns u :x-))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns u) '(1) dimension :right) + (declare (ignore s)) + (setf (tensor-by-site ttns u) + (tensor-permute r '(1 0 2 3 4))) + (setf (tensor-by-site ttns v) + (tensor-permute + (tensor-contract (tensor-by-site ttns v) 2 l 0) + '(0 1 3 4 2)))))) + (setf (tensor-by-site ttns (site-by-id ttns '(0 0))) + (tensor-normalize (tensor-by-site ttns (site-by-id ttns '(0 0))))))) + +(defun print-dimensions (ttns) + (let ((w (ttns-width ttns)) + (h (ttns-height ttns))) + (loop + for j from (1- h) downto 0 + do + (loop + for i below w + do (format t " ~3D " (fifth + (tensor-dimensions + (tensor-at-site + ttns + (list i j)))))) + (terpri) + (loop + for i below w + for d = (tensor-dimensions (tensor-at-site ttns (list i j))) + do (format t "~3D * ~3D " (second d) (third d))) + (terpri) + (loop + for i below w + do (format t " ~3D " (fourth + (tensor-dimensions + (tensor-at-site + ttns + (list i j)))))) + (terpri)))) + +(defun split-index-tensor (tensor index) + (let ((i (nth index (tensor-indices tensor)))) + (functional-tensor + (list (conjugate-index i) + i + (list (make-segment :numbers '(0) :dimension 1))) + #'(lambda (s) + (if (eql (subscript-subscript (first s)) + (subscript-subscript (second s))) + 1 + 0))))) + +(defun shift-right-bond-up (ttns site maxdim) + (let* ((u (tensor-by-site ttns site)) + (v (tensor-contract u 2 (split-index-tensor u 2) 0))) + (multiple-value-bind (l s r) (tensor-decompose v '(3 4) maxdim :right) + (declare (ignore s)) + (let ((w (site-by-bond ttns site :y+))) + (setf (tensor-by-site ttns w) + (tensor-fuse + (tensor-permute + (tensor-contract (tensor-by-site ttns w) 3 l 0) + '(0 1 2 5 3 4)) + '(1 2 4 5 6) + '(:normal :normal :normal :normal :normal)))) + (setf (tensor-by-site ttns site) + (tensor-permute + r + '(4 0 1 3 2)))))) + +(defun shift-left-bond-up (ttns site maxdim) + (let* ((u (tensor-by-site ttns site)) + (v (tensor-contract u 1 (split-index-tensor u 1) 0))) + (multiple-value-bind (l s r) (tensor-decompose v '(3 4) maxdim :right) + (declare (ignore s)) + (let ((w (site-by-bond ttns site :y+))) + (setf (tensor-by-site ttns w) + (tensor-fuse + (tensor-permute + (tensor-contract (tensor-by-site ttns w) 3 l 0) + '(0 1 3 5 2 4)) + '(1 3 4 5 6) + '(:normal :reverse :normal :normal :normal)))) + (setf (tensor-by-site ttns site) + (tensor-permute + r + '(4 0 2 3 1)))))) + +(defun shift-right-bond-down (ttns site maxdim) + (let* ((u (tensor-by-site ttns site)) + (v (tensor-contract u 2 (split-index-tensor u 2) 0))) + (multiple-value-bind (l s r) (tensor-decompose v '(0 1 5 3) maxdim :left) + (declare (ignore s)) + (setf (tensor-by-site ttns site) + (tensor-permute + l + '(0 1 2 4 3))) + (let ((w (site-by-bond ttns site :y-))) + (setf (tensor-by-site ttns w) + (tensor-fuse + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns w) 4) + '(5 2 0 1 3 4)) + '(1 2 3 5 6) + '(:normal :normal :normal :normal :normal))))))) + +(defun shift-left-bond-down (ttns site maxdim) + (let* ((u (tensor-by-site ttns site)) + (v (tensor-contract u 1 (split-index-tensor u 1) 0))) + (multiple-value-bind (l s r) (tensor-decompose v '(0 5 1 3) maxdim :left) + (declare (ignore s)) + (setf (tensor-by-site ttns site) + (tensor-permute + l + '(0 1 2 4 3))) + (let ((w (site-by-bond ttns site :y-))) + (setf (tensor-by-site ttns w) + (tensor-fuse + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns w) 4) + '(5 1 0 2 3 4)) + '(1 2 4 5 6) + '(:normal :reverse :normal :normal :normal))))))) + +;; time evolution + +(defun apply-single-site-operator-x (operator tensor) + (tensor-contract operator 1 tensor 0)) + +(defun apply-double-site-operator-x (operator tensor1 tensor2 maxdim normalization) + (multiple-value-bind (l1 s1 r1) (tensor-decompose tensor1 '(1 3 4) nil :left) + (declare (ignore s1)) + (multiple-value-bind (l2 s2 r2) (tensor-decompose tensor2 '(1 0) nil :right) + (declare (ignore s2)) + (let ((u (tensor-contract + operator + '(1 3) + (tensor-contract r1 2 l2 0) + '(1 2)))) + (multiple-value-bind (l s r) + (tensor-decompose u '(2 0) maxdim normalization) + (declare (ignore s)) + (let ((v1 (tensor-permute + (tensor-contract l1 3 l 0) + '(1 3 4 0 2)))) + (let ((v2 (tensor-permute + (tensor-contract r 2 r2 0) + '(1 0 2 3 4)))) + (values v1 v2)))))))) + +(defun apply-double-site-operator-y (operator tensor1 tensor2 maxdim normalization) + (multiple-value-bind (l1 s1 r1) (tensor-decompose tensor1 '(1 2 3) nil :left) + (declare (ignore s1)) + (multiple-value-bind (l2 s2 r2) (tensor-decompose tensor2 '(3 0) nil :right) + (declare (ignore s2)) + (let ((u (tensor-contract + operator + '(1 3) + (tensor-contract r1 2 l2 0) + '(1 2)))) + (multiple-value-bind (l s r) + (tensor-decompose u '(2 0) maxdim normalization) + (declare (ignore s)) + (values + (tensor-permute + (tensor-contract l1 3 l 0) + '(1 2 3 0 4)) + (tensor-permute + (tensor-contract r 2 r2 0) + '(3 0 1 2 4)))))))) + +(defun normalize-line (ttns site direction) + (loop + for u = site then v + for v = (site-by-bond ttns u direction) + while v + do + (normalize-tensor-by-site ttns u direction))) + +(defun apply-single-column-tebd-operators (ssps ttns x) + (loop + for u = (site-by-id ttns (list x 0)) then v + while u + for v = (site-by-bond ttns u :y+) + do + (setf (tensor-by-site ttns u) + (apply-single-site-operator-x (apply #'aref ssps (site-id u)) (tensor-by-site ttns u))))) + +(defun apply-double-column-tebd-operators (dsps ttns x maxdim normalization) + (loop + for u = (site-by-id ttns (list x 0)) then w + while u + for v = (site-by-bond ttns u :x+) + for w = (site-by-bond ttns u :y+) + do + (multiple-value-bind (l r) + (apply-double-site-operator-x + (apply #'aref dsps (site-id u)) + (tensor-by-site ttns u) + (tensor-by-site ttns v) + maxdim + (if w + (case normalization + (:left :right) + (:right :left)) + normalization)) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) r)) + when w + do + (case normalization + (:left + (shift-right-bond-up ttns u maxdim) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns w) '(0 1 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns w) + (tensor-permute l '(0 1 3 4 2))) + (setf (tensor-by-site ttns v) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns v) 1) + '(1 0 2 3 4)))) + (shift-left-bond-up ttns v maxdim)) + (:right + (shift-left-bond-up ttns v maxdim) + (let ((z (site-by-bond ttns w :x+))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns z) '(0 2 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns z) + (tensor-permute l '(0 2 3 4 1))) + (setf (tensor-by-site ttns u) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns u) 2) + '(2 0 1 3 4))))) + (shift-right-bond-up ttns u maxdim))))) + +(defun apply-double-column-tebd-operators-down (dsps ttns x maxdim normalization) + (loop + with h = (ttns-height ttns) + for u = (site-by-id ttns (list x (1- h))) then w + while u + for v = (site-by-bond ttns u :x+) + for w = (site-by-bond ttns u :y-) + do + (multiple-value-bind (l r) + (apply-double-site-operator-x + (apply #'aref dsps (site-id u)) + (tensor-by-site ttns u) + (tensor-by-site ttns v) + maxdim + (if w + (case normalization + (:left :right) + (:right :left)) + normalization)) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) r)) + when w + do + (case normalization + (:left + (shift-right-bond-down ttns u maxdim) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns w) '(0 1 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns w) + (tensor-permute l '(0 1 3 4 2))) + (setf (tensor-by-site ttns v) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns v) 1) + '(1 0 2 3 4)))) + (shift-left-bond-down ttns v maxdim)) + (:right + (shift-left-bond-down ttns v maxdim) + (let ((z (site-by-bond ttns w :x+))) + (multiple-value-bind (l s r) + (tensor-decompose (tensor-by-site ttns z) '(0 2 3 4) nil :left) + (declare (ignore s)) + (setf (tensor-by-site ttns z) + (tensor-permute l '(0 2 3 4 1))) + (setf (tensor-by-site ttns u) + (tensor-permute + (tensor-contract r 1 (tensor-by-site ttns u) 2) + '(2 0 1 3 4))))) + (shift-right-bond-down ttns u maxdim))))) + +(defun apply-even-tebd-operators-x (ssps dsps ttns maxdim) + (let ((w (ttns-width ttns)) + (h (ttns-height ttns))) + (loop + for i below (1- w) by 2 + do + (apply-double-column-tebd-operators dsps ttns i maxdim :left) + (unless (eql i (- w 2)) + (normalize-line ttns (site-by-id ttns (list (1+ i) (1- h))) :y-) + (normalize-tensor-by-site ttns (site-by-id ttns (list (1+ i) 0)) :x+))) + (when (oddp w) + (apply-single-column-tebd-operators ssps ttns (1- w)) + (normalize-line ttns (site-by-id ttns (list (1- w) (1- h))) :y-)))) + +(defun apply-odd-tebd-operators-x (ssps dsps ttns maxdim) + (let ((w (ttns-width ttns)) + (h (ttns-height ttns))) + (when (evenp w) + (apply-single-column-tebd-operators ssps ttns (1- w)) + (normalize-line ttns (site-by-id ttns (list (1- w) 0)) :y+)) + (loop + for i from (if (evenp w) (- w 3) (- w 2)) downto 1 by 2 + do + (unless (eql i (- w 2)) + (normalize-tensor-by-site ttns (site-by-id ttns (list (+ i 2) (1- h))) :x-) + (normalize-line ttns (site-by-id ttns (list (1+ i) (1- h))) :y-)) + (apply-double-column-tebd-operators dsps ttns i maxdim :right) + (normalize-tensor-by-site ttns (site-by-id ttns (list i (1- h))) :x-)))) + +(defun apply-even-tebd-operators-x-down (ssps dsps ttns maxdim) + (let ((w (ttns-width ttns)) + (h (ttns-height ttns))) + (when (oddp w) + (apply-single-column-tebd-operators ssps ttns (1- w)) + (normalize-line ttns (site-by-id ttns (list (1- w) (1- h))) :y-)) + (loop + for i from (if (evenp w) (- w 2) (- w 3)) downto 0 by 2 + do + (unless (eql i (- w 2)) + (normalize-tensor-by-site ttns (site-by-id ttns (list (+ i 2) 0)) :x-) + (normalize-line ttns (site-by-id ttns (list (1+ i) 0)) :y+)) + (apply-double-column-tebd-operators-down dsps ttns i maxdim :right) + (unless (zerop i) + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :x-))))) + +(defun apply-odd-tebd-operators-x-down (ssps dsps ttns maxdim) + (let ((w (ttns-width ttns)) + (h (ttns-height ttns))) + (normalize-tensor-by-site ttns (site-by-id ttns (list 0 (1- h))) :x+) + (loop + for i from 1 below (1- w) by 2 + do + (apply-double-column-tebd-operators-down dsps ttns i maxdim :left) + (unless (eql i (- w 2)) + (normalize-line ttns (site-by-id ttns (list (1+ i) 0)) :y+) + (normalize-tensor-by-site ttns (site-by-id ttns (list (1+ i) (1- h))) :x+))) + (when (evenp w) + (apply-single-column-tebd-operators ssps ttns (1- w)) + (normalize-line ttns (site-by-id ttns (list (1- w) 0)) :y+)))) + +(defun apply-even-tebd-operators-y (double ttns maxdim) + (loop + with w = (ttns-width ttns) + with h = (ttns-height ttns) + for i below w + do + (loop + for j below (1- h) by 2 + for u = (site-by-id ttns (list i j)) + for v = (site-by-bond ttns u :y+) + do + (multiple-value-bind (l r) + (apply-double-site-operator-y + double + (tensor-by-site ttns u) + (tensor-by-site ttns v) + maxdim + :left) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) r)) + (unless (>= j (- h 3)) + (normalize-tensor-by-site ttns v :y+))) + (loop + for j from (1- h) above 0 + do + (normalize-tensor-by-site ttns (site-by-id ttns (list i j)) :y-)) + (unless (eql i (1- w)) + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :x+)))) + +(defun apply-odd-tebd-operators-y (double ttns maxdim) + (loop + with w = (ttns-width ttns) + with h = (ttns-height ttns) + for i from (1- w) downto 0 + do + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :y+) + (loop + for j from 1 below (1- h) by 2 + for u = (site-by-id ttns (list i j)) + for v = (site-by-bond ttns u :y+) + do + (multiple-value-bind (l r) + (apply-double-site-operator-y + double + (tensor-by-site ttns u) + (tensor-by-site ttns v) + maxdim + :left) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) r)) + (unless (>= j (- h 3)) + (normalize-tensor-by-site ttns v :y+))) + (loop + for j from (1- h) above 0 + do + (normalize-tensor-by-site ttns (site-by-id ttns (list i j)) :y-)) + (unless (zerop i) + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :x-)))) + +(defun apply-even-tebd-operators-y-down (double ttns maxdim) + (loop + with w = (ttns-width ttns) + with h = (ttns-height ttns) + for i from (1- w) downto 0 + do + (loop + for j below (1- h) by 2 + for u = (site-by-id ttns (list i j)) + for v = (site-by-bond ttns u :y+) + do + (multiple-value-bind (l r) + (apply-double-site-operator-y + double + (tensor-by-site ttns u) + (tensor-by-site ttns v) + maxdim + :left) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) r)) + (unless (>= j (- h 3)) + (normalize-tensor-by-site ttns v :y+))) + (loop + for j from (1- h) above 0 + do + (normalize-tensor-by-site ttns (site-by-id ttns (list i j)) :y-)) + (unless (zerop i) + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :x-)) + )) + +(defun apply-odd-tebd-operators-y-down (double ttns maxdim) + (loop + with w = (ttns-width ttns) + with h = (ttns-height ttns) + for i below w + do + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :y+) + (loop + for j from 1 below (1- h) by 2 + for u = (site-by-id ttns (list i j)) + for v = (site-by-bond ttns u :y+) + do + (multiple-value-bind (l r) + (apply-double-site-operator-y + double + (tensor-by-site ttns u) + (tensor-by-site ttns v) + maxdim + :left) + (setf (tensor-by-site ttns u) l) + (setf (tensor-by-site ttns v) r)) + (unless (>= j (- h 3)) + (normalize-tensor-by-site ttns v :y+))) + (loop + for j from (1- h) above 0 + do + (normalize-tensor-by-site ttns (site-by-id ttns (list i j)) :y-)) + (unless (eql i (1- w)) + (normalize-tensor-by-site ttns (site-by-id ttns (list i 0)) :x+)))) + +(defun make-ssps (width height dimension interaction potential step) + (loop + with a = (make-array (list width height)) + for i below width + do + (loop + for j below height + for h = (bose-hubbard-site-hamiltonian dimension 1 interaction (aref potential i j)) + do + (setf (aref a i j) (make-single-site-propagator h step))) + finally (return a))) + +(defun make-dsps (width height dimension interaction potential step) + (loop + with a = (make-array (list (1- width) height)) + for i below (1- width) + do + (loop + for j below height + for f = (bose-hubbard-site-hamiltonian dimension 1 interaction (aref potential i j)) + for g = (bose-hubbard-site-hamiltonian dimension 1 interaction (aref potential (1+ i) j)) + do + (setf (aref a i j) (make-double-site-propagator f g step))) + finally (return a))) + +(defun ttns-tebd-evolve (ttns ssps dsps idsp maxdim) + (apply-even-tebd-operators-y idsp ttns maxdim) + (apply-odd-tebd-operators-y idsp ttns maxdim) + (apply-even-tebd-operators-x ssps dsps ttns maxdim) + (apply-odd-tebd-operators-x ssps dsps ttns maxdim) + (apply-odd-tebd-operators-x-down ssps dsps ttns maxdim) + (apply-even-tebd-operators-x-down ssps dsps ttns maxdim) + (apply-odd-tebd-operators-y-down idsp ttns maxdim) + (apply-even-tebd-operators-y-down idsp ttns maxdim)) + +(defun all-pn-operators (width height dimension) + (loop + with a = (make-array (list width height)) + for i below width + do + (loop + for j below height + do + (setf (aref a i j) + (pn-operator width height i j dimension))) + finally + (return a))) + +(defun all-pn (ttns norm pn) + (loop + with w = (array-dimension pn 0) + with h = (array-dimension pn 1) + with a = (make-array (list w h)) + for i below w + do + (loop + for j below h + do + (setf (aref a i j) + (realpart (/ (ttns-expectation + ttns + ttns + (aref pn i j)) + norm)))) + finally + (return a))) + +(defun print-pn (pn) + (loop + with w = (array-dimension pn 0) + with h = (array-dimension pn 1) + for j from (1- h) downto 0 + do + (loop + for i below w + do + (format t + ;; "~,3f~:[ ~;~%~]" + "~F~:[ ~;~%~]" + (aref pn i j) + (eql i (1- w))))))