Tensor Network Theory Library  Beta release 1.2.1
A library of routines for performing TNT-based operations
 All Data Structures Functions Variables Groups Pages
tntMpsCreateSpinOp.c
1 /*
2 Authors: Sarah Al-Assam, Stephen Clark and Dieter Jaksch
3 $LastChangedDate$
4 (c) University of Oxford 2014
5 */
6 
7 /* Include the internal header for the TNT library */
8 #include "tntMpsInternal.h"
9 
24 void tntMpsCreateSpinOp(unsigned TwoS,
25  tntNode *Sx,
26  tntNode *Sy,
27  tntNode *Sz,
28  tntNode *Sp,
29  tntNode *Sm,
30  tntNode *eye)
31 {
32 
33  tntComplexArray Szarr, Sparr, Smarr; /* Arrays to hold the tensor elements */
34  tntNode Spl = NULL, Sml = NULL; /* Local spin raising and lowering operators used to create Sx and Sy */
35  double m; /* z component of the spin */
36  double S = (double) TwoS*0.5; /* Spin of the system */
37  unsigned physdim = TwoS + 1; /* Physical dimension for the spin system */
38  unsigned j; /* index for arrays */
39  tntComplex ScaleSy = {0, 0.5}; /* tntComplex value to scale Sy by */
40  tntIntArray qninf; /* Quantum number information for the physical legs */
41 
42  /* Quantum number information to set for invariant operators only */
43  if (TNT_SYMM_U1 == tntSymmTypeGet()) {
44  qninf = tntIntArrayAlloc(physdim);
45  for (j = 0; j < physdim; j++) {
46  qninf.vals[j] = -2*j-1+physdim;
47  }
48  }
49 
50  /* Check whether each node pointer is NULL, before creating each node */
51 
52  /* Sz = [ S 0 ... 0 0]
53  [ 0 S-1 ... 0 0]
54  [ : ]
55  [ 0 0 ... -S+1 0]
56  [ 0 0 ... 0 -S]
57  */
58  if (NULL != Sz) {
59 
60  /* Make array of values */
61  Szarr = tntComplexArrayAlloc(physdim*physdim);
62  for (j = 0; j < physdim; j++) {
63  /* Calculate the value of the z componenet of the spin for each element */
64  m = S - j;
65  /* Put the value of the spin on the diagonal elements */
66  Szarr.vals[j*(physdim+1)].re = m;
67  }
68  *Sz = tntNodeCreate(&Szarr, "DU", physdim, physdim);
69 
70  /* Free the array - it is no longer needed */
71  tntComplexArrayFree(&Szarr);
72 
73  if (TNT_SYMM_U1 == tntSymmTypeGet()) {
74  tntNodeSetQN(*Sz,"D",&qninf,TNT_QN_IN);
75  tntNodeSetQN(*Sz,"U",&qninf,TNT_QN_OUT);
76  }
77  }
78 
79  /* Sp = [ 0 c_{S} 0 0 0 ...]
80  [ 0 0 c_{S-1} 0 0 ...]
81  [ 0 0 0 c_{-S+3} 0 ...]
82  [ 0 0 0 0 c_{-S+4} ...]
83  [ 0 0 0 0 0 ...]
84  [ ..... ]
85  with c_m = sqrt((S-m)(S-m+1))*/
86 
87  if ((NULL != Sp)||(NULL != Sx)||(NULL != Sy)) {
88 
89  /* Make array of values */
90  Sparr = tntComplexArrayAlloc(physdim*physdim);
91  for (j = 1; j < physdim; j++) {
92  /* Calculate the value of the z componenet of the spin for each element */
93  m = S - j;
94  /* Put the value of coefficient for spin j on row j-1, column j */
95  Sparr.vals[(j-1) + j*physdim].re = sqrt((S-m)*(S+m+1.0));
96  }
97  Spl = tntNodeCreate(&Sparr, "DU", physdim, physdim);
98 
99  /* Free the array - it is no longer needed */
100  tntComplexArrayFree(&Sparr);
101  }
102 
103 
104  if ((NULL != Sm)||(NULL != Sx)||(NULL != Sy)) {
105 
106  /* Make array of values */
107  Smarr = tntComplexArrayAlloc(physdim*physdim);
108  for (j = 0; j < (physdim-1); j++) {
109  /* Calculate the value of the z componenet of the spin for each element */
110  m = S - j;
111  /* Put the value of coefficient for spin j on row j+1, column j */
112  Smarr.vals[(j+1) + j*physdim].re = sqrt((S+m)*(S-m+1.0));
113  }
114  Sml = tntNodeCreate(&Smarr, "DU", physdim, physdim);
115 
116  /* Free the array - it is no longer needed */
117  tntComplexArrayFree(&Smarr);
118  }
119 
120  /* \sigma^x = 1/2*(Sp + Sm)*/
121  if (NULL != Sx) {
122  /* Make Sx a copy of the local version of Sp */
123  *Sx = tntNodeCopy(Spl);
124  /* Add the local copy of Sm */
125  tntNodeAdd(*Sx,Sml);
126  /* Scale the total node by 1/2 */
127  tntNodeScaleReal(*Sx,0.5);
128  }
129 
130  /* \sigma^y = -i/2*(Sp - Sm)*/
131  if (NULL != Sy) {
132  /* Make Sy a copy of the local version of Sp */
133  *Sy = tntNodeCopy(Spl);
134  /* Scale by -1 */
135  tntNodeScaleReal(*Sy,-1);
136  /* Add the local copy of Sm */
137  tntNodeAdd(*Sy,Sml);
138  /* Scale the total node by i/2 */
139  tntNodeScaleComplex(*Sy,ScaleSy);
140  }
141 
142  /* eye = [ 1 0 ....]
143  [ 0 1 ....]
144  .....
145  [ .... 0 1] */
146  if (NULL != eye) {
147 
148  *eye = tntNodeCreateEyeOp(Spl);
149 
150  if (TNT_SYMM_U1 == tntSymmTypeGet()) {
151  tntNodeSetQN(*eye,"D",&qninf,TNT_QN_IN);
152  tntNodeSetQN(*eye,"U",&qninf,TNT_QN_OUT);
153  }
154  }
155 
156  /* Free the qn information if it was used */
157  if (TNT_SYMM_U1 == tntSymmTypeGet()) tntIntArrayFree(&qninf);
158 
159  /* Free the nodes for sigma plus or minus if not required, otherwise assign to pointer arguments */
160  if (NULL == Sp) tntNodeFree(&Spl);
161  else *Sp = Spl;
162 
163  if (NULL == Sm) tntNodeFree(&Sml);
164  else *Sm = Sml;
165 
166  return;
167 
168 }
169 
tntNode tntNodeCopy(tntNode A)
Definition: tntNodeUtil.c:304
void tntNodeSetQN(tntNode A, tntLegLabel legA, tntIntArray *qvals, int legdir)
Definition: tntNodeQN.c:37
void tntMpsCreateSpinOp(unsigned TwoS, tntNode *Sx, tntNode *Sy, tntNode *Sz, tntNode *Sp, tntNode *Sm, tntNode *eye)
tntNode tntNodeCreateEyeOp(tntNode A)
Definition: tntNodeUtil.c:195
void tntNodeScaleComplex(tntNode A, tntComplex val)
void tntNodeAdd(tntNode A, tntNode B)
void tntNodeFree(tntNode *A)
Definition: tntNodeUtil.c:275
tntComplexArray tntComplexArrayAlloc(unsigned numrows, unsigned numcols)
Definition: tntArray.c:392
Definition: tnt.h:65
void tntIntArrayFree(tntIntArray *arr)
Definition: tntArray.c:620
tntIntArray tntIntArrayAlloc(unsigned numrows, unsigned numcols)
Definition: tntArray.c:29
tntNode tntNodeCreate(tntComplexArray *nodeVals, tntLegLabel leglabels, unsigned dimleg1, unsigned dim...)
Definition: tntNodeUtil.c:354
void tntComplexArrayFree(tntComplexArray *arr)
Definition: tntArray.c:650
void tntNodeScaleReal(tntNode A, double val)
int tntSymmTypeGet(void)
Definition: tntSys.c:498