|
1 | 1 | # Physics (SiteType) System Examples
|
2 | 2 |
|
| 3 | +## Making a Custom op Definition |
| 4 | + |
| 5 | +The function `op` is used to obtain operators defined for a |
| 6 | +given "site type". ITensor includes pre-defined site types such |
| 7 | +as "S=1/2", "S=1", "Electron" and others. Or you can define your own site type |
| 8 | +as discussed in detail in the code examples further below. |
| 9 | + |
| 10 | +**Extending op Function Definitions** |
| 11 | + |
| 12 | +Perhaps the most common part of the site type system one wishes to extend |
| 13 | +are the various `op` or `op!` function overloads which allow code like |
| 14 | + |
| 15 | +```julia |
| 16 | +s = siteind("S=1/2") |
| 17 | +Sz = op("Sz",s) |
| 18 | +``` |
| 19 | + |
| 20 | +to automatically create the ``S^z`` operator for an Index `s` based on the |
| 21 | +`"S=1/2"` tag it carries. A major reason to define such `op` overloads |
| 22 | +is to allow the OpSum system to recognize new operator names, as |
| 23 | +discussed more below. |
| 24 | + |
| 25 | +Let's see how to introduce a new operator name into the ITensor site type |
| 26 | +system for this existing site type of `"S=1/2"`. The operator we will |
| 27 | +introduce is the projector onto the up spin state ``P_\uparrow`` which |
| 28 | +we will denote with the string `"Pup"`. |
| 29 | + |
| 30 | +As a matrix acting on the space ``\{ |\!\uparrow\rangle, |\!\downarrow\rangle \}``, |
| 31 | +the ``P_\uparrow`` operator is given by |
| 32 | + |
| 33 | +```math |
| 34 | +\begin{aligned} |
| 35 | +
|
| 36 | +P_\uparrow &= |
| 37 | +\begin{bmatrix} |
| 38 | + 1 & 0 \\ |
| 39 | + 0 & 0 \\ |
| 40 | +\end{bmatrix} |
| 41 | +
|
| 42 | +\end{aligned} |
| 43 | +``` |
| 44 | + |
| 45 | +To add this operator to the ITensor `op` system, we just need to introduce the following |
| 46 | +code |
| 47 | + |
| 48 | +```julia |
| 49 | +using ITensors |
| 50 | + |
| 51 | +ITensors.op(::OpName"Pup",::SiteType"S=1/2") = |
| 52 | + [1 0 |
| 53 | + 0 0] |
| 54 | +``` |
| 55 | + |
| 56 | +This code can be defined anywhere, such as in your own personal application code and does |
| 57 | +not have to be put into the ITensor library source code. |
| 58 | + |
| 59 | +Note that we have to name the function `ITensors.op` and not just `op` so that it overloads |
| 60 | +other functions of the name `op` inside the ITensors module. |
| 61 | + |
| 62 | +Having defined the above code, we can now do things like |
| 63 | + |
| 64 | +```julia |
| 65 | +s = siteind("S=1/2") |
| 66 | +Pup = op("Pup",s) |
| 67 | +``` |
| 68 | + |
| 69 | +to obtain the `"Pup"` operator for our `"S=1/2"` Index `s`. Or we can do a similar |
| 70 | +thing for an array of site indices: |
| 71 | + |
| 72 | +```julia |
| 73 | +N = 40 |
| 74 | +s = siteinds("S=1/2",N) |
| 75 | +Pup1 = op("Pup",s[1]) |
| 76 | +Pup3 = op("Pup",s[3]) |
| 77 | +``` |
| 78 | + |
| 79 | +Note that for the `"Qudit"`/`"Boson"` site types, you have to define your overload |
| 80 | +of `op` with the dimension of the local Hilbert space, for example: |
| 81 | +```julia |
| 82 | +using ITensors |
| 83 | + |
| 84 | +function ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) |
| 85 | + o = zeros(d, d) |
| 86 | + o[1, 1] = 1 |
| 87 | + return o |
| 88 | +end |
| 89 | +``` |
| 90 | +Alternatively you could use Julia's [array comprehension](https://docs.julialang.org/en/v1/manual/arrays/#man-comprehensions) syntax: |
| 91 | +```julia |
| 92 | +ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) = |
| 93 | + [(i == j == 1) ? 1.0 : 0.0 for i in 1:d, j in 1:d] |
| 94 | +``` |
| 95 | + |
| 96 | +**Using Custom Operators in OpSum** |
| 97 | + |
| 98 | +A key use of these `op` system extensions is allowing additional operator names to |
| 99 | +be recognized by the OpSum system for constructing matrix product operator (MPO) |
| 100 | +tensor networks. With the code above defining the `"Pup"` operator, we are now |
| 101 | +allowed to use this operator name in any OpSum code involving `"S=1/2"` site |
| 102 | +indices. |
| 103 | + |
| 104 | +For example, we could now make an OpSum involving our custom operator such as: |
| 105 | + |
| 106 | +```julia |
| 107 | +N = 100 |
| 108 | +sites = siteinds("S=1/2",N) |
| 109 | +os = OpSum() |
| 110 | +for n=1:N |
| 111 | + os += "Pup",n |
| 112 | +end |
| 113 | +P = MPO(os,sites) |
| 114 | +``` |
| 115 | + |
| 116 | +This code makes an MPO `P` which is just the sum of a spin-up projection operator |
| 117 | +acting on every site. |
| 118 | + |
| 119 | + |
| 120 | +## Making a Custom state Definition |
| 121 | + |
| 122 | +The function `state` is used to define states (single-site wavefunctions) |
| 123 | +that sites can be in. For example, the "Qubit" site type includes |
| 124 | +definitions for the "0" and "1" states as well as the "+" (eigenstate of X operator) |
| 125 | +state. The "S=1/2" site type includes definitions for the "Up" and "Dn" (down) states. |
| 126 | + |
| 127 | +Say we want to define a new state for the "Electron" site type called "+", which has |
| 128 | +the meaning of one electron with its spin in the +X direction. First let's review |
| 129 | +the existing state definitions: |
| 130 | +```julia |
| 131 | +ITensors.state(::StateName"Emp", ::SiteType"Electron") = [1.0, 0, 0, 0] |
| 132 | +ITensors.state(::StateName"Up", ::SiteType"Electron") = [0.0, 1, 0, 0] |
| 133 | +ITensors.state(::StateName"Dn", ::SiteType"Electron") = [0.0, 0, 1, 0] |
| 134 | +ITensors.state(::StateName"UpDn", ::SiteType"Electron") = [0.0, 0, 0, 1] |
| 135 | +``` |
| 136 | +As we can see, the four settings of an "Electron" index correspond to the states |
| 137 | +``|0\rangle, |\uparrow\rangle, |\downarrow\rangle, |\uparrow\downarrow\rangle``. |
| 138 | + |
| 139 | +So we can define our new state "+" as follows: |
| 140 | +```julia |
| 141 | +ITensors.state(::StateName"+", ::SiteType"Electron") = [0, 1/sqrt(2), 1/sqrt(2), 0] |
| 142 | +``` |
| 143 | +which makes the state |
| 144 | +```math |
| 145 | +|+\rangle = \frac{1}{\sqrt{2}} |\uparrow\rangle + \frac{1}{\sqrt{2}} |\downarrow\rangle |
| 146 | +``` |
| 147 | + |
| 148 | +Having defined this overload of `state`, if we have an Index of type "Electron" |
| 149 | +we can obtain our new state for it by doing |
| 150 | +```julia |
| 151 | +s = siteind("Electron") |
| 152 | +plus = state("+",s) |
| 153 | +``` |
| 154 | +We can also use this new state definition in other ITensor features such as |
| 155 | +the MPS constructor taking an array of state names. |
| 156 | + |
| 157 | + |
3 | 158 | ## Make a Custom Local Hilbert Space / Physical Degree of Freedom
|
4 | 159 |
|
5 | 160 | ITensor provides support for a range of common local Hilbert space types,
|
@@ -336,126 +491,3 @@ on, thus it does not have a well-defined QN flux. But it is perfectly fine to de
|
336 | 491 | non-QN-conserving ITensors or when ``S^z`` is not conserved.
|
337 | 492 |
|
338 | 493 |
|
339 |
| -## Extending an Existing Local Hilbert Space |
340 |
| - |
341 |
| -In the two previous examples above, we discussed the basics |
342 |
| -of how custom local Hilbert spaces a.k.a. site types can be defined from |
343 |
| -scratch in ITensor. However, there are cases where a custom site type is |
344 |
| -already designed for you, such as the site types `"S=1/2"`, `"S=1"`, |
345 |
| -`"Fermion"`, `"Electron"` and others included with ITensor. |
346 |
| - |
347 |
| -A nice feature of the ITensor `SiteType` system is that you can arbitrarily |
348 |
| -extend operator and other definitions, even of existing `SiteTypes` created |
349 |
| -in other code or by someone else. |
350 |
| - |
351 |
| -**Extending op Function Definitions** |
352 |
| - |
353 |
| -Perhaps the most common part of the `SiteType` system one wishes to extend |
354 |
| -are the various `op` or `op!` function overloads which allow code like |
355 |
| - |
356 |
| -```julia |
357 |
| -s = siteind("S=1/2") |
358 |
| -Sz = op("Sz",s) |
359 |
| -``` |
360 |
| - |
361 |
| -to automatically create the ``S^z`` operator for an Index `s` based on the |
362 |
| -`"S=1/2"` tag it carries. A major reason to define such `op` overloads |
363 |
| -is to allow the OpSum (formerly AutoMPO) system to recognize new operator names, as |
364 |
| -discussed more below. |
365 |
| - |
366 |
| -Let's see how to introduce a new operator name into the ITensor `SiteType` |
367 |
| -system for this existing site type of `"S=1/2"`. The operator we will |
368 |
| -introduce is the projector onto the up spin state ``P_\uparrow`` which |
369 |
| -we will denote with the string `"Pup"`. |
370 |
| - |
371 |
| -As a matrix acting on the space ``\{ |\!\uparrow\rangle, |\!\downarrow\rangle \}``, |
372 |
| -the ``P_\uparrow`` operator is given by |
373 |
| - |
374 |
| -```math |
375 |
| -\begin{aligned} |
376 |
| -
|
377 |
| -P_\uparrow &= |
378 |
| -\begin{bmatrix} |
379 |
| - 1 & 0 \\ |
380 |
| - 0 & 0 \\ |
381 |
| -\end{bmatrix} |
382 |
| -
|
383 |
| -\end{aligned} |
384 |
| -``` |
385 |
| - |
386 |
| -To add this operator to the ITensor `op` system, we just need to introduce the following |
387 |
| -code |
388 |
| - |
389 |
| -```julia |
390 |
| -using ITensors |
391 |
| - |
392 |
| -ITensors.op(::OpName"Pup",::SiteType"S=1/2") = |
393 |
| - [1 0 |
394 |
| - 0 0] |
395 |
| -``` |
396 |
| - |
397 |
| -This code can be defined anywhere, such as in your own personal application code and does |
398 |
| -not have to be put into the ITensor library source code. |
399 |
| - |
400 |
| -Note that we have to name the function `ITensors.op!` and not just `op!` so that it overloads |
401 |
| -other functions of the name `op!` inside the ITensors module. |
402 |
| - |
403 |
| -Having defined the above code, we can now do things like |
404 |
| - |
405 |
| -```julia |
406 |
| -s = siteind("S=1/2") |
407 |
| -Pup = op("Pup",s) |
408 |
| -``` |
409 |
| - |
410 |
| -to obtain the `"Pup"` operator for our `"S=1/2"` Index `s`. Or we can do a similar |
411 |
| -thing for an array of site indices: |
412 |
| - |
413 |
| -```julia |
414 |
| -N = 40 |
415 |
| -s = siteinds("S=1/2",N) |
416 |
| -Pup1 = op("Pup",s[1]) |
417 |
| -Pup3 = op("Pup",s[3]) |
418 |
| -``` |
419 |
| - |
420 |
| -Note that for the `"Qudit"`/`"Boson"` site types, you have to define your overload |
421 |
| -of `op` with the dimension of the local Hilbert space, for example: |
422 |
| -```julia |
423 |
| -using ITensors |
424 |
| - |
425 |
| -function ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) |
426 |
| - o = zeros(d, d) |
427 |
| - o[1, 1] = 1 |
428 |
| - return o |
429 |
| -end |
430 |
| -``` |
431 |
| -Alternatively you could use Julia's [array comprehension](https://docs.julialang.org/en/v1/manual/arrays/#man-comprehensions) syntax: |
432 |
| -```julia |
433 |
| -ITensors.op(::OpName"P1", ::SiteType"Boson", d::Int) = |
434 |
| - [(i == j == 1) ? 1.0 : 0.0 for i in 1:d, j in 1:d] |
435 |
| -``` |
436 |
| - |
437 |
| -**Using Custom Operators in OpSum (AutoMPO)** |
438 |
| - |
439 |
| -A key use of these `op` system extensions is allowing additional operator names to |
440 |
| -be recognized by the OpSum (formerly AutoMPO) system for constructing matrix product operator (MPO) |
441 |
| -tensor networks. With the code above defining the `"Pup"` operator, we are now |
442 |
| -allowed to use this operator name in any OpSum code involving `"S=1/2"` site |
443 |
| -indices. |
444 |
| - |
445 |
| -For example, we could now make an OpSum involving our custom operator such as: |
446 |
| - |
447 |
| -```julia |
448 |
| -N = 100 |
449 |
| -sites = siteinds("S=1/2",N) |
450 |
| -ampo = OpSum() |
451 |
| -for n=1:N |
452 |
| - ampo += "Pup",n |
453 |
| -end |
454 |
| -P = MPO(ampo,sites) |
455 |
| -``` |
456 |
| - |
457 |
| -This code makes an MPO `P` which is just the sum of a spin-up projection operator |
458 |
| -acting on every site. |
459 |
| - |
460 |
| - |
461 |
| - |
|
0 commit comments