{"id":1220,"date":"2018-11-07T10:49:12","date_gmt":"2018-11-07T10:49:12","guid":{"rendered":"http:\/\/second-tech.com\/wordpress\/?p=1220"},"modified":"2020-01-10T14:04:24","modified_gmt":"2020-01-10T14:04:24","slug":"dynamically-adjustable-hoppingamplitudes-using-callback-functions-in-tbtk","status":"publish","type":"post","link":"http:\/\/second-tech.com\/wordpress\/index.php\/2018\/11\/07\/dynamically-adjustable-hoppingamplitudes-using-callback-functions-in-tbtk\/","title":{"rendered":"Dynamically adjustable HoppingAmplitudes using callbacks in TBTK"},"content":{"rendered":"<p><i>Most recent TBTK release at the time of writing: v1.0.3<\/i><br \/>\n<i>Updated to work with: v2.0.0<\/i><\/p>\n<p>In this blog post we will take a look at how to specify models without necessarily knowing all the model parameters at the point of specification. This can be very useful when the Hamiltonian is time dependent or depends on some parameter that is to be solved for self-consistently.<\/p>\n<p>We will here consider a third situation in which adjustable HoppingAmplitudes can be utilized by setting up a model with a variable potential. We will use this to repeatedly calculate the probability density and eigenvalues for the lowest energy states for seven different types of one-dimensional potentials. Namely, the infinite square well, square well, double square well, harmonic oscillator, double well, and step potential, as well as a potential with two regions with different potential separated by a barrier.<\/p>\n<div class=\"a-single a-4\"><script async src=\"\/\/pagead2.googlesyndication.com\/pagead\/js\/adsbygoogle.js\"><\/script>\r\n<ins class=\"adsbygoogle\"\r\n     style=\"display:block; text-align:center;\"\r\n     data-ad-layout=\"in-article\"\r\n     data-ad-format=\"fluid\"\r\n     data-ad-client=\"ca-pub-3756520172792312\"\r\n     data-ad-slot=\"9656949358\"><\/ins>\r\n<script>\r\n     (adsbygoogle = window.adsbygoogle || []).push({});\r\n<\/script><\/div>\n<h2>Parameters<\/h2>\n<p>The parameters that are needed are the number of sites to use for the discretized Schr\u00f6dinger equation, the number of states for which we are going to calculate the probability density, and the nearest neighbor hopping amplitude <img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/ql-cache\/quicklatex.com-6b97bb0f65c75b6cc0fba1868749478d_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;\" title=\"Rendered by QuickLaTeX.com\" height=\"12\" width=\"6\" style=\"vertical-align: 0px;\"\/>. We define these as follows.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Number of sites and states to extract the\r\n\/\/probability density for.\r\nconst int SIZE_X = 500;\r\nconst int NUM_STATES = 7;\r\ndouble t = 1;\r\n<\/pre>\n<p>We further create an enum that will be used to specify the type of the potential.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Enum type for specifying the type of the\r\n\/\/potential.\r\nenum PotentialType{\r\n\tInfiniteSquareWell,\r\n\tSquareWell,\r\n\tDoubleSquareWell,\r\n\tHarmonicOscillator,\r\n\tDoubleWell,\r\n\tStep,\r\n\tBarrier\r\n};\r\n\r\n\/\/The type of the potential.\r\nPotentialType potentialType;\r\n<\/pre>\n<h2>Potential function<\/h2>\n<p>We also define a potential function that will be responsible for returning the potential at any given point.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Function that dynamically returns the current potential on a given site.\r\ncomplex&lt;double&gt; potential(int x){\r\n\tswitch(potentialType){\r\n\tcase InfiniteSquareWell:\r\n\t\treturn infiniteSquareWell(x);\r\n\tcase SquareWell:\r\n\t\treturn squareWell(x);\r\n\tcase DoubleSquareWell:\r\n\t\treturn doubleSquareWell(x);\r\n\tcase HarmonicOscillator:\r\n\t\treturn harmonicOscillator(x);\r\n\tcase DoubleWell:\r\n\t\treturn doubleWell(x);\r\n\tcase Step:\r\n\t\treturn step(x);\r\n\tcase Barrier:\r\n\t\treturn barrier(x);\r\n\tdefault:\r\n\t\tStreams::out &lt;&lt; &quot;Error. This should never happen.&quot;;\r\n\t\texit(1);\r\n\t}\r\n}\r\n<\/pre>\n<p>Depending on the current potential type, this function calls one of several specific potential functions. The definition of these can be seen in the full source code linked at the end of this post.<\/p>\n<h2>Callback function<\/h2>\n<p>Normally a HoppingAmplitude is specified as<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nHoppingAmplitude(value, toIndex, formIndex);\r\n<\/pre>\n<p>However, it is also possible to pass a callback instead of a value as the first argument. This callback will later be called by the HoppingAmplitude to determine the value, passing the toIndex and fromIndex as arguments. That is, the HoppingAmplitude will &#8220;call back&#8221; later to determine the value.<\/p>\n<p>For a class to classify as a valid callback function, it needs to inherit from HoppingAmplitude::AmplitudeCallback and provide a function that takes two indices as arguments and returns a complex value. In addition, it needs to be able to handle every pair of indices that it will be called with. That is, every pair of indices which it is packed together with into a HoppingAmplitude when the model is specified.<\/p>\n<p>In this example, the position can be read off from either of the indices. In the following implementation, we read it off from the *from* Index and pass it to the potential function defined above to get the value for the potential.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Callback that dynamically returns the current\r\n\/\/value on a given site.\r\nclass PotentialCallback : public HoppingAmplitude::AmplitudeCallback{\r\npublic:\r\n\tcomplex&lt;double&gt; getHoppingAmplitude(\r\n\t\tconst Index &amp;to,\r\n\t\tconst Index &amp;from\r\n\t){\r\n\t\treturn potential(from&#x5B;0]);\r\n\t}\r\n} potentialCallback;\r\n<\/pre>\n<p>In the last line, we instantiate an object of the *PotentialCallback* called *potentialCallback*. It is this object that will be used as callback when specifying the model.<\/p>\n<h2>Model<\/h2>\n<p>The model that we will consider is the discretized one-dimensional Schr\u00f6dinger equation which we specify as follows.<span id='easy-footnote-1-1220' class='easy-footnote-margin-adjust'><\/span><span class='easy-footnote'><a href='http:\/\/second-tech.com\/wordpress\/index.php\/2018\/11\/07\/dynamically-adjustable-hoppingamplitudes-using-callback-functions-in-tbtk\/#easy-footnote-bottom-1-1220' title='For more details see for example &lt;a href=&quot;http:\/\/second-tech.com\/wordpress\/index.php\/2018\/10\/23\/using-tbtk-to-calculate-the-density-of-states-dos-of-a-1d-2d-and-3d-square-lattice\/&quot;&gt;Using TBTK to calculate the density of states (DOS) of a 1D, 2D, and 3D square lattice&lt;\/a&gt; and &lt;a href=&quot;http:\/\/second-tech.com\/wordpress\/index.php\/2018\/10\/27\/direct-access-to-wave-function-amplitudes-and-eigenvalues-in-tbtk\/&quot;&gt;Direct access to wave function amplitudes and eigenvalues in TBTK&lt;\/a&gt;'><sup>1<\/sup><\/a><\/span><\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Create the Model.\r\nModel model;\r\nfor(unsigned int x = 0; x &lt; SIZE_X; x++){\r\n\t\/\/Kinetic terms.\r\n\tmodel &lt;&lt; HoppingAmplitude(\r\n\t\t2*t,\r\n\t\t{x},\r\n\t\t{x}\r\n\t);\r\n\tif(x + 1 &lt; SIZE_X){\r\n\t\tmodel &lt;&lt; HoppingAmplitude(\r\n\t\t\t-t,\r\n\t\t\t{x + 1},\r\n\t\t\t{x}\r\n\t\t) + HC;\r\n\t}\r\n\r\n\t\/\/Potential term.\r\n\tmodel &lt;&lt; HoppingAmplitude(\r\n\t\tpotentialCallback,\r\n\t\t{x},\r\n\t\t{x}\r\n\t);\r\n}\r\nmodel.construct();\r\n<\/pre>\n<p>The kinetic terms result from discretizing the Laplace operator and letting <img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/ql-cache\/quicklatex.com-76b383bdf4379b321651d43151a1783c_l3.png\" class=\"ql-img-inline-formula quicklatex-auto-format\" alt=\"&#116;&#32;&#61;&#32;&#92;&#104;&#98;&#97;&#114;&#94;&#50;&#47;&#50;&#109;&#100;&#120;&#94;&#50;\" title=\"Rendered by QuickLaTeX.com\" height=\"20\" width=\"107\" style=\"vertical-align: -5px;\"\/>, while the potential term has been added by passing the callback *potentialCallback* as the first parameter to the HoppingAmplitude.<\/p>\n<h2>Set up the Solver and PropertyExtractor<\/h2>\n<p>We next set up the Solver and PropertyExtractor as follows.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Setup the Solver and PropertyExtractor.\r\nSolver::Diagonalizer solver;\r\nsolver.setModel(model);\r\nPropertyExtractor::Diagonalizer\r\n\tpropertyExtractor(solver);\r\n<\/pre>\n<h2>The main loop<\/h2>\n<p>In the main loop, we will carry out the same calculation for each potential. We therefore begin by creating a list of potential types to perform the calculations for, and a list of filenames to which to save the results.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/List of potentials to run the calculation\r\n\/\/for.\r\nvector&lt;PotentialType&gt; potentialTypes = {\r\n\tInfiniteSquareWell,\r\n\tSquareWell,\r\n\tDoubleSquareWell,\r\n\tHarmonicOscillator,\r\n\tDoubleWell,\r\n\tStep,\r\n\tBarrier\r\n};\r\n\r\n\/\/List of filenames to save the results to.\r\nvector&lt;string&gt; filenames = {\r\n\t&quot;figures\/InfiniteSquareWell.png&quot;,\r\n\t&quot;figures\/SquareWell.png&quot;,\r\n\t&quot;figures\/DoubleSquareWell.png&quot;,\r\n\t&quot;figures\/HarmonicOscillator.png&quot;,\r\n\t&quot;figures\/DoubleWell.png&quot;,\r\n\t&quot;figures\/Step.png&quot;,\r\n\t&quot;figures\/Barrier.png&quot;\r\n};\r\n<\/pre>\n<p>The main loop itself is as follows.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/\/Run the calculation and plot the result for\r\n\/\/each potential.\r\nfor(\r\n\tunsigned int n = 0;\r\n\tn &lt; potentialTypes.size();\r\n\tn++\r\n){\r\n\t\/\/Set the current potential.\r\n\tpotentialType = potentialTypes&#x5B;n];\r\n\r\n\t\/\/Run the solver.\r\n\tsolver.run();\r\n\r\n\t\/\/Calculate the probability density\r\n\t\/\/for the first NUM_STATES.\r\n\tArray&lt;double&gt; probabilityDensities(\r\n\t\t{NUM_STATES, SIZE_X}\r\n\t);\r\n\tfor(\r\n\t\tunsigned int state = 0;\r\n\t\tstate &lt; NUM_STATES;\r\n\t\tstate++\r\n\t){\r\n\t\tfor(\r\n\t\t\tunsigned int x = 0;\r\n\t\t\tx &lt; (unsigned int)SIZE_X;\r\n\t\t\tx++\r\n\t\t){\r\n\t\t\tcomplex&lt;double&gt; amplitude\r\n\t\t\t\t= propertyExtractor.getAmplitude(\r\n\t\t\t\t\tstate,\r\n\t\t\t\t\t{x}\r\n\t\t\t\t);\r\n\t\t\tprobabilityDensities&#x5B;{state, x}]\r\n\t\t\t\t= pow(abs(amplitude), 2);\r\n\t\t}\r\n\t}\r\n\r\n\t\/\/Calculate the eigenvalues.\r\n\tProperty::EigenValues eigenValues\r\n\t\t= propertyExtractor.getEigenValues();\r\n\r\n\t\/\/Plot the results.\r\n\tplot(\r\n\t\tprobabilityDensities,\r\n\t\teigenValues,\r\n\t\tfilenames&#x5B;n]\r\n\t);\r\n}\r\n<\/pre>\n<p>Here we loop over each type of potential and set the global parameter potentialType to the current potential in line 9. The solver is then executed, which results in the HoppingAmplitudes being requested internally, which triggers the callback functions to be called and return the values for the current potential. Next, the probability density is calculated<span id='easy-footnote-2-1220' class='easy-footnote-margin-adjust'><\/span><span class='easy-footnote'><a href='http:\/\/second-tech.com\/wordpress\/index.php\/2018\/11\/07\/dynamically-adjustable-hoppingamplitudes-using-callback-functions-in-tbtk\/#easy-footnote-bottom-2-1220' title='See &lt;a href=&quot;http:\/\/second-tech.com\/wordpress\/index.php\/2018\/10\/27\/direct-access-to-wave-function-amplitudes-and-eigenvalues-in-tbtk\/&quot;&gt;Direct access to wave function amplitudes and eigenvalues in TBTK&lt;\/a&gt; for a more detailed description of the calculation of the probability density.'><sup>2<\/sup><\/a><\/span>, followed by the calculation of the eigenvalues.<\/p>\n<p>Finally, the results are plotted and saved to file. The plotting routine involves significant post processing of the data and the full code for achieving this can be found in the code linked below. In particular, the probability densities are first rescaled such that NUM_STATES probability densities can be stacked evenly on top of each other without overlapping or extending beyond the plotting window. Then the probability densities are shifted by the respective eigenvalue of the corresponding state to simultaneously convey information about the probability density and the eigenvalues in relation to the potential.<\/p>\n<h2>Results<\/h2>\n<p>Below the results are presented. The thick red line indicates the potential, while the black lines are the probability densities. Each probability density has been offset by the corresponding states eigenvalue to put its energy in relation to the potential. The eigenvalues are also plotted with thin red lines. In agreement with the basic principles of quantum mechanics, we see how the states are oscillating in the regions where the potential is smaller than the energy of the state, while they decay exponentially into the regions where the potential is larger.<\/p>\n<h3>Infinite square well<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1874 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/InfiniteSquareWell-2.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/InfiniteSquareWell-2.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/InfiniteSquareWell-2-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/InfiniteSquareWell-2-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h3>Square well<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1875 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/SquareWell-2.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/SquareWell-2.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/SquareWell-2-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/SquareWell-2-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h3>Double square well<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1871 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleSquareWell-1.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleSquareWell-1.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleSquareWell-1-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleSquareWell-1-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h3>Harmonic oscillator<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1873 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/HarmonicOscillator-2.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/HarmonicOscillator-2.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/HarmonicOscillator-2-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/HarmonicOscillator-2-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h3>Double well<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1872 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleWell-2.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleWell-2.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleWell-2-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/DoubleWell-2-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h3>Step<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1876 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Step-2.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Step-2.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Step-2-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Step-2-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h3>Barrier<\/h3>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-1870 size-full\" src=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Barrier-2.png\" alt=\"\" width=\"800\" height=\"600\" srcset=\"http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Barrier-2.png 800w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Barrier-2-300x225.png 300w, http:\/\/second-tech.com\/wordpress\/wp-content\/uploads\/2018\/11\/Barrier-2-768x576.png 768w\" sizes=\"(max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/p>\n<h2>Full code<\/h2>\n<p>Full code is available in <a href=\"https:\/\/github.com\/dafer45\/SecondTechCode\/blob\/master\/2018_11_07\/src\/main.cpp\">src\/main.cpp<\/a> in the project <a href=\"https:\/\/github.com\/dafer45\/SecondTechCode\/tree\/master\/2018_11_07\">2018_11_07<\/a> of the <a href=\"https:\/\/github.com\/dafer45\/SecondTechCode\">Second Tech code package<\/a>. See the README for instructions on how to build and run.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Most recent TBTK release at the time of writing: v1.0.3 Updated to work with: v2.0.0 In this blog post we will take a look at how to specify models without necessarily knowing all the model parameters at the point of specification. This can be very useful when the Hamiltonian is time dependent or depends on &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/second-tech.com\/wordpress\/index.php\/2018\/11\/07\/dynamically-adjustable-hoppingamplitudes-using-callback-functions-in-tbtk\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Dynamically adjustable HoppingAmplitudes using callbacks in TBTK&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"_links":{"self":[{"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/1220"}],"collection":[{"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/comments?post=1220"}],"version-history":[{"count":78,"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/1220\/revisions"}],"predecessor-version":[{"id":1879,"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/posts\/1220\/revisions\/1879"}],"wp:attachment":[{"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/media?parent=1220"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/categories?post=1220"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/second-tech.com\/wordpress\/index.php\/wp-json\/wp\/v2\/tags?post=1220"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}