diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c93669c..1f7f766 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: fetch-depth: 2 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: "3.10" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6f1ace1..7bf65bc 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python }} - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python }} @@ -44,18 +44,18 @@ jobs: poetry --version - name: Install System Dependencies (Ubuntu) - if: startsWith(matrix.os, 'ubuntu') && (matrix.session 'tests' | matrix.session == 'pre-commit') + if: startsWith(matrix.os, 'ubuntu') && (matrix.session == 'no') run: | sudo apt-get update sudo apt-get install -y python3-dev python3-setuptools python3-scipy python3-matplotlib python3-pytest python3-sympy g++ build-essential gfortran libopenblas-dev liblapack-dev libmumps-scotch-dev - name: Install Python dependencies (Ubuntu) - if: startsWith(matrix.os, 'ubuntu') && (matrix.session 'tests' | matrix.session == 'pre-commit') + if: startsWith(matrix.os, 'ubuntu') && (matrix.session == 'no') run: | python -m pip install cython tinyarray - name: Clone and Install kwant (Ubuntu) - if: startsWith(matrix.os, 'ubuntu') && (matrix.session 'tests' | matrix.session == 'pre-commit') + if: startsWith(matrix.os, 'ubuntu') && (matrix.session == 'no') run: | git clone https://github.com/kwant-project/kwant.git cd kwant @@ -122,7 +122,7 @@ jobs: uses: actions/checkout@v4 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v4 with: python-version: "3.10" diff --git a/README.md b/README.md index a64d50d..e51718a 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,20 @@ ## Features -- TODO +- KPM expansion of typical spectal functions + - Density of states + - Green's functions + - Kubo conductivity + - Chern marker +- Time evolution +- Tools for system with periodic boundaries + - KPM vector factories that produces tiles + - Velocity operators adapted to periodic boundaries + - Distance operators adapted to periodic boundaries ## Requirements -- TODO +- Python >=3.9 ## Installation @@ -41,9 +50,9 @@ You can install _KPM Tools_ via [pip] from [PyPI]: $ pip install kpm-tools ``` -## Usage +## Python API -Please see the [Command-line Reference] for details. +Please see the [Python API reference] for details. ## Contributing @@ -74,4 +83,4 @@ This project was generated from [@cjolowicz]'s [Hypermodern Python Cookiecutter] [license]: https://github.com/piskunow/kpm-tools/blob/main/LICENSE [contributor guide]: https://github.com/piskunow/kpm-tools/blob/main/CONTRIBUTING.md -[command-line reference]: https://kpm-tools.readthedocs.io/en/latest/usage.html +[python api reference]: https://kpm-tools.readthedocs.io/en/latest/api.html diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..feb1b2b --- /dev/null +++ b/docs/api.md @@ -0,0 +1,81 @@ +# Python API + +```{eval-rst} +.. click:: kpm_tools.__main__:main + :prog: kpm-tools + :nested: full +``` + +Each of the following sections describes the usage of different modules in the `kpm_tools` package. + +## Bloch Module + +```{eval-rst} +.. automodule:: kpm_tools.bloch + :members: + :undoc-members: + :show-inheritance: +``` + +## Common Module + +```{eval-rst} +.. automodule:: kpm_tools.common + :members: + :undoc-members: + :show-inheritance: +``` + +## Evolution Module + +```{eval-rst} +.. automodule:: kpm_tools.evolution + :members: + :undoc-members: + :show-inheritance: +``` + +## Hamiltonians Module + +```{eval-rst} +.. automodule:: kpm_tools.hamiltonians + :members: + :undoc-members: + :show-inheritance: +``` + +## KPM Functions Module + +```{eval-rst} +.. automodule:: kpm_tools.kpm_funcs + :members: + :undoc-members: + :show-inheritance: +``` + +## KPM Generator Module + +```{eval-rst} +.. automodule:: kpm_tools.kpm_generator + :members: + :undoc-members: + :show-inheritance: +``` + +## Plotting Module + +```{eval-rst} +.. automodule:: kpm_tools.plotting + :members: + :undoc-members: + :show-inheritance: +``` + +## Tiles Module + +```{eval-rst} +.. automodule:: kpm_tools.tiles + :members: + :undoc-members: + :show-inheritance: +``` diff --git a/docs/conf.py b/docs/conf.py index 8fd1051..1fcc385 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,10 +1,17 @@ """Sphinx configuration.""" + +import inspect +import os +import sys + + project = "KPM Tools" author = "Pablo Piskunow" copyright = "2023, Pablo Piskunow" extensions = [ "sphinx.ext.autodoc", "sphinx.ext.napoleon", + "sphinx.ext.linkcode", "sphinx_click", "myst_parser", "nbsphinx", @@ -36,3 +43,43 @@ """ # noqa: B950 + + +def linkcode_resolve(domain, info): + """Resolve links to source.""" + if domain != "py": + return None + if not info["module"]: + return None + + # Replace with your project's GitHub repository URL + github_repo = "https://github.com/piskunow/kpm-tools" + + # Get the module object + module = sys.modules.get(info["module"]) + if module is None: + return None + + # Get the source file path of the module + filename = inspect.getsourcefile(module) + if filename is None: + return None + + # Trim the filename to a path relative to the project root + rel_fn = os.path.relpath(filename, start=os.path.dirname(__file__)) + + # Get the line number of the object within the module + obj = module + for part in info["fullname"].split("."): + obj = getattr(obj, part, None) + + if obj is None: + return None + + try: + lines, _ = inspect.getsourcelines(obj) + except Exception: + return None + + line = inspect.getsourcelines(obj)[1] + return f"{github_repo}/blob/main/{rel_fn}#L{line}" diff --git a/docs/index.md b/docs/index.md index bca2b31..5dcbf3b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -6,7 +6,7 @@ end-before: [license]: license [contributor guide]: contributing -[command-line reference]: usage +[python api]: api ```{toctree} --- @@ -15,8 +15,7 @@ maxdepth: 1 --- Tutorials -usage -reference +api contributing Code of Conduct License diff --git a/docs/tutorials.md b/docs/tutorials.md index 37ceb84..66629f9 100644 --- a/docs/tutorials.md +++ b/docs/tutorials.md @@ -6,4 +6,6 @@ maxdepth: 1 --- tutorials/tutorial_bloch +tutorials/tutorial_time_evolution +tutorials/tutorial_evolution_performance ``` diff --git a/docs/tutorials/tutorial_evolution_performance.ipynb b/docs/tutorials/tutorial_evolution_performance.ipynb new file mode 100644 index 0000000..ef00abe --- /dev/null +++ b/docs/tutorials/tutorial_evolution_performance.ipynb @@ -0,0 +1,589 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "afc07c2f-f818-45a3-adc1-4ccc177fb49e", + "metadata": {}, + "source": [ + "# Performance of `evolution`\n", + "## Cutoff in the coefficients\n", + "\n", + "The time evolution operator for a Hamiltonian $H$\n", + "$$ O[H, \\Delta t] = \\text{exp}\\left(-i H \\Delta t\\right) $$\n", + "uses a KPM expansion as a function of time $\\Delta t$, instead of the usual Fermi energy $\\varepsilon$ of spectral functions.\n", + "\n", + "In the expansion \n", + "$$ O[H, \\Delta t] = \\sum_{m=0}^{\\infty} T_m(H) c_m(\\Delta t)$$\n", + "the coefficients $c_m$ are proportional to the Bessel functions of the first kind of order $m$, so they decay exponentially fast after a certain threshold $m^*$.\n", + "\n", + "Thus, is it extremely efficient to cutoff the expansion for a certain target accuracy\n", + "$$ O[H, \\Delta t] \\simeq \\sum_{m=0}^{m^*} T_m(H) c_m(\\Delta t)$$\n", + "\n", + "The exact value of $m^*$ depends on the time step times the bounds of the spectrum $\\Delta t\\times\\Delta E$, and on the desired accuracy.\n", + "To find $m^*$ for all values of $\\Delta t\\times\\Delta E$, we define a few typical target accuracies: $10^{-8}, 10^{-16}, 10^{-32}$, and numerically obtain the answer. \n", + "Then, we will use a numerical estimate of the function that fits $m^*$." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "678ee99d-938d-4560-8008-48eedefd3194", + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n var py_version = '3.3.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n var reloading = false;\n var Bokeh = root.Bokeh;\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n run_callbacks();\n return null;\n }\n if (!reloading) {\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n require([\"jspanel\"], function(jsPanel) {\n\twindow.jsPanel = jsPanel\n\ton_load()\n })\n require([\"jspanel-modal\"], function() {\n\ton_load()\n })\n require([\"jspanel-tooltip\"], function() {\n\ton_load()\n })\n require([\"jspanel-hint\"], function() {\n\ton_load()\n })\n require([\"jspanel-layout\"], function() {\n\ton_load()\n })\n require([\"jspanel-contextmenu\"], function() {\n\ton_load()\n })\n require([\"jspanel-dock\"], function() {\n\ton_load()\n })\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 9;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n var existing_stylesheets = []\n var links = document.getElementsByTagName('link')\n for (var i = 0; i < links.length; i++) {\n var link = links[i]\n if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n }\n }\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } var existing_scripts = []\n var scripts = document.getElementsByTagName('script')\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n\texisting_scripts.push(script.src)\n }\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n var url = js_exports[name];\n if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.3.1.min.js\", \"https://cdn.holoviz.org/panel/1.3.2/dist/panel.min.js\"];\n var js_modules = [];\n var js_exports = {};\n var css_urls = [];\n var inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n\ttry {\n inline_js[i].call(root, root.Bokeh);\n\t} catch(e) {\n\t if (!reloading) {\n\t throw e;\n\t }\n\t}\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n\troot.Bokeh = undefined;\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));", + "application/vnd.holoviews_load.v0+json": "" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n", + "application/vnd.holoviews_load.v0+json": "" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "
\n", + "
\n", + "" + ] + }, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "p1002" + } + }, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + "\n", + "\n", + "
\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "import holoviews as hv\n", + "hv.extension()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "b0c2c1c9-47cd-466e-8f46-fad06283fb36", + "metadata": {}, + "outputs": [], + "source": [ + "import scipy\n", + "import scipy.optimize\n", + "from scipy.special import jv\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "21504e7c-9efb-409a-8a14-d3f86655054a", + "metadata": {}, + "outputs": [], + "source": [ + "from kpm_tools.evolution import coef_evo\n" + ] + }, + { + "cell_type": "markdown", + "id": "ae3eabbb-6c96-4499-9551-acab82c3afd7", + "metadata": {}, + "source": [ + "\n", + "## numerical evaluation of the coefficients\n", + "\n", + "First, we obtain an `ndarray` of the coefficients vs the time delta $\\Delta t$ and the number of moments `num_moments`.\n", + "\n", + "Here, we use $\\Delta E = 1$, such that `dt` is the rescaled time delta $\\Delta t \\times \\Delta E$. " + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "16305d37-d864-4b26-bada-3720a18d41fb", + "metadata": {}, + "outputs": [], + "source": [ + "dt_array = np.logspace(-3,2,1000)\n", + "num_moments = 500\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "e58fe285-fbb2-4c39-b58b-a098e606df11", + "metadata": {}, + "outputs": [], + "source": [ + "coefs_array = np.array([\n", + " coef_evo(num_moments, 0, ab=(2,0), delta_time=dt)\n", + " for dt in dt_array\n", + "])\n", + "coefs_array = coefs_array[:,1:,0]\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "63d2e9dc-13af-4f30-b742-f1c50974647a", + "metadata": {}, + "outputs": [], + "source": [ + "num_moments_array = np.arange(1, num_moments)\n" + ] + }, + { + "cell_type": "markdown", + "id": "bce1b2d9-5c48-4a9a-9818-fde110efeff3", + "metadata": {}, + "source": [ + "## make a fit\n", + "\n", + "### Numerical estimation of the best `num_moments`\n", + "Then we obtain the best `num_moments` for a given `dt` and `accuracy`." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "9c772263-2eb8-4d49-b038-8842972f7872", + "metadata": {}, + "outputs": [], + "source": [ + "accuracy = 1e-16\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "45b5e0fe-4df1-44b5-ae6f-1b17ada7e64b", + "metadata": {}, + "outputs": [], + "source": [ + "# get the transition point in `m` such that coefs are smaller than accuracy\n", + "\n", + "def max_m_array(coefs_array, accuracy):\n", + " return np.count_nonzero(np.abs(coefs_array) > accuracy, axis=1)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "7d89d044-e66d-4298-a437-2bf2e0742af0", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/tmp/ipykernel_21141/785646435.py:5: RuntimeWarning: divide by zero encountered in log\n", + " np.log(np.abs(coefs_array))/np.log(10)\n" + ] + }, + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + ":Overlay\n", + " .QuadMesh.I :QuadMesh [M,$dt$] (z)\n", + " .Curve.I :Curve [x] (y)" + ] + }, + "execution_count": 9, + "metadata": { + "application/vnd.holoviews_exec.v0+json": {} + }, + "output_type": "execute_result" + } + ], + "source": [ + "(\n", + " hv.QuadMesh((\n", + " num_moments_array,\n", + " dt_array,\n", + " np.log(np.abs(coefs_array))/np.log(10)\n", + " ),\n", + " kdims=['M', '$dt$'],\n", + " vdims=hv.Dimension('z', label='${log}_{10}|c_n|$', range=(np.log(accuracy)/np.log(10), 0))\n", + " ).opts(colorbar=True, fig_size=200)\n", + " *\n", + " hv.Curve((\n", + " max_m_array(coefs_array, accuracy),\n", + " dt_array,\n", + " ))\n", + ")[:30,:4]\n" + ] + }, + { + "cell_type": "markdown", + "id": "e60af675-2128-4ec0-812e-7a63bfc2453c", + "metadata": {}, + "source": [ + "We can already see that only a handful of moments is needed for a fairly large vale of the time step `dt`." + ] + }, + { + "cell_type": "markdown", + "id": "8713f990-6eb3-463d-8692-b18acd93725a", + "metadata": {}, + "source": [ + "\n", + "### Analitical fit of the best `num_moments`\n", + "\n", + "Since we don't want to store arrays of best `num_moments`, we make\n", + "an analytical approximation to the best `num_moments` for a given accuray and as a function of `dt`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "bcacfa28-2ef0-4c02-b49a-20f5b5b60835", + "metadata": {}, + "outputs": [], + "source": [ + "def func(dt, A, B, C, D):\n", + " return (A * np.log(1/accuracy) * (dt) ** B) + C * dt + D * np.log(1/accuracy)\n", + "\n", + "p_acc16, _ = scipy.optimize.curve_fit(func,\n", + " dt_array,\n", + " max_m_array(coefs_array, accuracy),\n", + " p0=(0.5, 0.25, 2, 0),\n", + "\n", + "# bounds=([0,0,0,2], [1,1,1,2+1e-8])\n", + " )\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "da947bd6-9ee7-485a-b5c0-1331c07f10ab", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + ":Overlay\n", + " .QuadMesh.I :QuadMesh [M,$dt$] (z)\n", + " .Curve.I :Curve [x] (y)" + ] + }, + "execution_count": 11, + "metadata": { + "application/vnd.holoviews_exec.v0+json": {} + }, + "output_type": "execute_result" + } + ], + "source": [ + "hv.QuadMesh((\n", + " num_moments_array,\n", + " dt_array,\n", + " np.log(np.abs(coefs_array+np.finfo(float).eps))/np.log(10)\n", + "),\n", + " kdims=['M', '$dt$'],\n", + " vdims=hv.Dimension('z', label='$|c_n|$', range=(np.log(accuracy)/np.log(10), 0))\n", + ").opts(logy=True, logz=False, colorbar=True, fig_size=200) * \\\n", + "hv.Curve((np.array([func(dt, *p_acc16) for dt in dt_array]),\n", + " dt_array)).opts(logy=True, logx=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "63ad6320-1f42-4556-a77e-2eb18314fd0e", + "metadata": {}, + "source": [ + "## Result\n", + "\n", + "Finally, these parameters give the best choice of `num_moments`\n", + "as a function of `dt` for\n", + "typical accuracy goals: `1e-8`, `1e-16`, `1e-32`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "'p_acc8 = [0.42464678, 0.33500138, 2.00044861, 0.07265139]'\n", + "'p_acc16 = [0.34310197, 0.33722835, 2.01232381, 0.08868359]'\n", + "'p_acc32 = [0.28132266, 0.32958046, 2.04428473, 0.09146841]'\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "id": "548000c4-04cc-4f1a-8977-aadeef099537", + "metadata": {}, + "source": [ + "From the scaling analysis we can see that large time steps are possible, and require a proportionally larger amount of moments in the KPM expansion.\n", + "\n", + "Smaller timesteps have a slight overhead in the number of moments:\n", + "$m^*=4$ for very small time steps of $10^{-3}$ but only $m^*=6$ for a ten times larger time step $10^{-2}$.\n", + "\n", + "Thus, it is more convenient -in terms of performance- to make one big time step, rather than many subsequent smaller time steps.\n", + "\n", + "Nevertheless, it is still fairly efficient to make many time steps for visualizing the time evolution." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "kt", + "language": "python", + "name": "kt" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/tutorials/tutorial_time_evolution.ipynb b/docs/tutorials/tutorial_time_evolution.ipynb new file mode 100644 index 0000000..4e28587 --- /dev/null +++ b/docs/tutorials/tutorial_time_evolution.ipynb @@ -0,0 +1,1027 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8b9ff2a1-58ba-46b2-87e0-03d8d987fd94", + "metadata": {}, + "source": [ + "# Tutorial `evolution`" + ] + }, + { + "cell_type": "markdown", + "id": "303dcd12-cd29-49a0-81b0-befa68549c86", + "metadata": {}, + "source": [ + "We demonstrate the use of a KPM expansion to handle the evolution in time of set of initial states under a defined Hamiltonian.\n", + "\n", + "Note that this module only addresses the time evolution of closed systems. For time evolution in scattering problems, please refer to [TKwant](https://tkwant.kwant-project.org/)." + ] + }, + { + "cell_type": "markdown", + "id": "9886d7d6-8c51-4dbc-a87b-c3c44035c7b8", + "metadata": {}, + "source": [ + "## Defining the system\n", + "We make some basic imports and define a linear chain." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "eaabebb3-7176-4a8b-bbd9-cd38964f34eb", + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "(function(root) {\n", + " function now() {\n", + " return new Date();\n", + " }\n", + "\n", + " var force = true;\n", + " var py_version = '3.3.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", + " var reloading = false;\n", + " var Bokeh = root.Bokeh;\n", + "\n", + " if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n", + " root._bokeh_timeout = Date.now() + 5000;\n", + " root._bokeh_failed_load = false;\n", + " }\n", + "\n", + " function run_callbacks() {\n", + " try {\n", + " root._bokeh_onload_callbacks.forEach(function(callback) {\n", + " if (callback != null)\n", + " callback();\n", + " });\n", + " } finally {\n", + " delete root._bokeh_onload_callbacks;\n", + " }\n", + " console.debug(\"Bokeh: all callbacks have finished\");\n", + " }\n", + "\n", + " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", + " if (css_urls == null) css_urls = [];\n", + " if (js_urls == null) js_urls = [];\n", + " if (js_modules == null) js_modules = [];\n", + " if (js_exports == null) js_exports = {};\n", + "\n", + " root._bokeh_onload_callbacks.push(callback);\n", + "\n", + " if (root._bokeh_is_loading > 0) {\n", + " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", + " return null;\n", + " }\n", + " if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", + " run_callbacks();\n", + " return null;\n", + " }\n", + " if (!reloading) {\n", + " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", + " }\n", + "\n", + " function on_load() {\n", + " root._bokeh_is_loading--;\n", + " if (root._bokeh_is_loading === 0) {\n", + " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", + " run_callbacks()\n", + " }\n", + " }\n", + " window._bokeh_on_load = on_load\n", + "\n", + " function on_error() {\n", + " console.error(\"failed to load \" + url);\n", + " }\n", + "\n", + " var skip = [];\n", + " if (window.requirejs) {\n", + " window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n", + " require([\"jspanel\"], function(jsPanel) {\n", + "\twindow.jsPanel = jsPanel\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-modal\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-tooltip\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-hint\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-layout\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-contextmenu\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-dock\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"gridstack\"], function(GridStack) {\n", + "\twindow.GridStack = GridStack\n", + "\ton_load()\n", + " })\n", + " require([\"notyf\"], function() {\n", + "\ton_load()\n", + " })\n", + " root._bokeh_is_loading = css_urls.length + 9;\n", + " } else {\n", + " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", + " }\n", + "\n", + " var existing_stylesheets = []\n", + " var links = document.getElementsByTagName('link')\n", + " for (var i = 0; i < links.length; i++) {\n", + " var link = links[i]\n", + " if (link.href != null) {\n", + "\texisting_stylesheets.push(link.href)\n", + " }\n", + " }\n", + " for (var i = 0; i < css_urls.length; i++) {\n", + " var url = css_urls[i];\n", + " if (existing_stylesheets.indexOf(url) !== -1) {\n", + "\ton_load()\n", + "\tcontinue;\n", + " }\n", + " const element = document.createElement(\"link\");\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.rel = \"stylesheet\";\n", + " element.type = \"text/css\";\n", + " element.href = url;\n", + " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", + " document.body.appendChild(element);\n", + " } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } var existing_scripts = []\n", + " var scripts = document.getElementsByTagName('script')\n", + " for (var i = 0; i < scripts.length; i++) {\n", + " var script = scripts[i]\n", + " if (script.src != null) {\n", + "\texisting_scripts.push(script.src)\n", + " }\n", + " }\n", + " for (var i = 0; i < js_urls.length; i++) {\n", + " var url = js_urls[i];\n", + " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.src = url;\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " document.head.appendChild(element);\n", + " }\n", + " for (var i = 0; i < js_modules.length; i++) {\n", + " var url = js_modules[i];\n", + " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.src = url;\n", + " element.type = \"module\";\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " document.head.appendChild(element);\n", + " }\n", + " for (const name in js_exports) {\n", + " var url = js_exports[name];\n", + " if (skip.indexOf(url) >= 0 || root[name] != null) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.type = \"module\";\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " element.textContent = `\n", + " import ${name} from \"${url}\"\n", + " window.${name} = ${name}\n", + " window._bokeh_on_load()\n", + " `\n", + " document.head.appendChild(element);\n", + " }\n", + " if (!js_urls.length && !js_modules.length) {\n", + " on_load()\n", + " }\n", + " };\n", + "\n", + " function inject_raw_css(css) {\n", + " const element = document.createElement(\"style\");\n", + " element.appendChild(document.createTextNode(css));\n", + " document.body.appendChild(element);\n", + " }\n", + "\n", + " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.3.1.min.js\", \"https://cdn.holoviz.org/panel/1.3.2/dist/panel.min.js\"];\n", + " var js_modules = [];\n", + " var js_exports = {};\n", + " var css_urls = [];\n", + " var inline_js = [ function(Bokeh) {\n", + " Bokeh.set_log_level(\"info\");\n", + " },\n", + "function(Bokeh) {} // ensure no trailing comma for IE\n", + " ];\n", + "\n", + " function run_inline_js() {\n", + " if ((root.Bokeh !== undefined) || (force === true)) {\n", + " for (var i = 0; i < inline_js.length; i++) {\n", + "\ttry {\n", + " inline_js[i].call(root, root.Bokeh);\n", + "\t} catch(e) {\n", + "\t if (!reloading) {\n", + "\t throw e;\n", + "\t }\n", + "\t}\n", + " }\n", + " // Cache old bokeh versions\n", + " if (Bokeh != undefined && !reloading) {\n", + "\tvar NewBokeh = root.Bokeh;\n", + "\tif (Bokeh.versions === undefined) {\n", + "\t Bokeh.versions = new Map();\n", + "\t}\n", + "\tif (NewBokeh.version !== Bokeh.version) {\n", + "\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", + "\t}\n", + "\troot.Bokeh = Bokeh;\n", + " }} else if (Date.now() < root._bokeh_timeout) {\n", + " setTimeout(run_inline_js, 100);\n", + " } else if (!root._bokeh_failed_load) {\n", + " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", + " root._bokeh_failed_load = true;\n", + " }\n", + " root._bokeh_is_initializing = false\n", + " }\n", + "\n", + " function load_or_wait() {\n", + " // Implement a backoff loop that tries to ensure we do not load multiple\n", + " // versions of Bokeh and its dependencies at the same time.\n", + " // In recent versions we use the root._bokeh_is_initializing flag\n", + " // to determine whether there is an ongoing attempt to initialize\n", + " // bokeh, however for backward compatibility we also try to ensure\n", + " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", + " // before older versions are fully initialized.\n", + " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", + " root._bokeh_is_initializing = false;\n", + " root._bokeh_onload_callbacks = undefined;\n", + " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", + " load_or_wait();\n", + " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", + " setTimeout(load_or_wait, 100);\n", + " } else {\n", + " root._bokeh_is_initializing = true\n", + " root._bokeh_onload_callbacks = []\n", + " var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n", + " if (!reloading && !bokeh_loaded) {\n", + "\troot.Bokeh = undefined;\n", + " }\n", + " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", + "\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", + "\trun_inline_js();\n", + " });\n", + " }\n", + " }\n", + " // Give older versions of the autoload script a head-start to ensure\n", + " // they initialize before we start loading newer version.\n", + " setTimeout(load_or_wait, 100)\n", + "}(window));" + ], + "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n var py_version = '3.3.1'.replace('rc', '-rc.').replace('.dev', '-dev.');\n var reloading = false;\n var Bokeh = root.Bokeh;\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n run_callbacks();\n return null;\n }\n if (!reloading) {\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n require([\"jspanel\"], function(jsPanel) {\n\twindow.jsPanel = jsPanel\n\ton_load()\n })\n require([\"jspanel-modal\"], function() {\n\ton_load()\n })\n require([\"jspanel-tooltip\"], function() {\n\ton_load()\n })\n require([\"jspanel-hint\"], function() {\n\ton_load()\n })\n require([\"jspanel-layout\"], function() {\n\ton_load()\n })\n require([\"jspanel-contextmenu\"], function() {\n\ton_load()\n })\n require([\"jspanel-dock\"], function() {\n\ton_load()\n })\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 9;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n var existing_stylesheets = []\n var links = document.getElementsByTagName('link')\n for (var i = 0; i < links.length; i++) {\n var link = links[i]\n if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n }\n }\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.3.2/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.2/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } var existing_scripts = []\n var scripts = document.getElementsByTagName('script')\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n\texisting_scripts.push(script.src)\n }\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n var url = js_exports[name];\n if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.3.1.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.3.1.min.js\", \"https://cdn.holoviz.org/panel/1.3.2/dist/panel.min.js\"];\n var js_modules = [];\n var js_exports = {};\n var css_urls = [];\n var inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n\ttry {\n inline_js[i].call(root, root.Bokeh);\n\t} catch(e) {\n\t if (!reloading) {\n\t throw e;\n\t }\n\t}\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n\troot.Bokeh = undefined;\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "\n", + "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", + " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", + "}\n", + "\n", + "\n", + " function JupyterCommManager() {\n", + " }\n", + "\n", + " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", + " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", + " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", + " comm_manager.register_target(comm_id, function(comm) {\n", + " comm.on_msg(msg_handler);\n", + " });\n", + " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", + " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", + " comm.onMsg = msg_handler;\n", + " });\n", + " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", + " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", + " var messages = comm.messages[Symbol.asyncIterator]();\n", + " function processIteratorResult(result) {\n", + " var message = result.value;\n", + " console.log(message)\n", + " var content = {data: message.data, comm_id};\n", + " var buffers = []\n", + " for (var buffer of message.buffers || []) {\n", + " buffers.push(new DataView(buffer))\n", + " }\n", + " var metadata = message.metadata || {};\n", + " var msg = {content, buffers, metadata}\n", + " msg_handler(msg);\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " return messages.next().then(processIteratorResult);\n", + " })\n", + " }\n", + " }\n", + "\n", + " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", + " if (comm_id in window.PyViz.comms) {\n", + " return window.PyViz.comms[comm_id];\n", + " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", + " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", + " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", + " if (msg_handler) {\n", + " comm.on_msg(msg_handler);\n", + " }\n", + " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", + " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", + " comm.open();\n", + " if (msg_handler) {\n", + " comm.onMsg = msg_handler;\n", + " }\n", + " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", + " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", + " comm_promise.then((comm) => {\n", + " window.PyViz.comms[comm_id] = comm;\n", + " if (msg_handler) {\n", + " var messages = comm.messages[Symbol.asyncIterator]();\n", + " function processIteratorResult(result) {\n", + " var message = result.value;\n", + " var content = {data: message.data};\n", + " var metadata = message.metadata || {comm_id};\n", + " var msg = {content, metadata}\n", + " msg_handler(msg);\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " }) \n", + " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", + " return comm_promise.then((comm) => {\n", + " comm.send(data, metadata, buffers, disposeOnDone);\n", + " });\n", + " };\n", + " var comm = {\n", + " send: sendClosure\n", + " };\n", + " }\n", + " window.PyViz.comms[comm_id] = comm;\n", + " return comm;\n", + " }\n", + " window.PyViz.comm_manager = new JupyterCommManager();\n", + " \n", + "\n", + "\n", + "var JS_MIME_TYPE = 'application/javascript';\n", + "var HTML_MIME_TYPE = 'text/html';\n", + "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", + "var CLASS_NAME = 'output';\n", + "\n", + "/**\n", + " * Render data to the DOM node\n", + " */\n", + "function render(props, node) {\n", + " var div = document.createElement(\"div\");\n", + " var script = document.createElement(\"script\");\n", + " node.appendChild(div);\n", + " node.appendChild(script);\n", + "}\n", + "\n", + "/**\n", + " * Handle when a new output is added\n", + " */\n", + "function handle_add_output(event, handle) {\n", + " var output_area = handle.output_area;\n", + " var output = handle.output;\n", + " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", + " return\n", + " }\n", + " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", + " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", + " if (id !== undefined) {\n", + " var nchildren = toinsert.length;\n", + " var html_node = toinsert[nchildren-1].children[0];\n", + " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", + " var scripts = [];\n", + " var nodelist = html_node.querySelectorAll(\"script\");\n", + " for (var i in nodelist) {\n", + " if (nodelist.hasOwnProperty(i)) {\n", + " scripts.push(nodelist[i])\n", + " }\n", + " }\n", + "\n", + " scripts.forEach( function (oldScript) {\n", + " var newScript = document.createElement(\"script\");\n", + " var attrs = [];\n", + " var nodemap = oldScript.attributes;\n", + " for (var j in nodemap) {\n", + " if (nodemap.hasOwnProperty(j)) {\n", + " attrs.push(nodemap[j])\n", + " }\n", + " }\n", + " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", + " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", + " oldScript.parentNode.replaceChild(newScript, oldScript);\n", + " });\n", + " if (JS_MIME_TYPE in output.data) {\n", + " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", + " }\n", + " output_area._hv_plot_id = id;\n", + " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", + " window.PyViz.plot_index[id] = Bokeh.index[id];\n", + " } else {\n", + " window.PyViz.plot_index[id] = null;\n", + " }\n", + " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", + " var bk_div = document.createElement(\"div\");\n", + " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", + " var script_attrs = bk_div.children[0].attributes;\n", + " for (var i = 0; i < script_attrs.length; i++) {\n", + " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", + " }\n", + " // store reference to server id on output_area\n", + " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", + " }\n", + "}\n", + "\n", + "/**\n", + " * Handle when an output is cleared or removed\n", + " */\n", + "function handle_clear_output(event, handle) {\n", + " var id = handle.cell.output_area._hv_plot_id;\n", + " var server_id = handle.cell.output_area._bokeh_server_id;\n", + " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", + " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", + " if (server_id !== null) {\n", + " comm.send({event_type: 'server_delete', 'id': server_id});\n", + " return;\n", + " } else if (comm !== null) {\n", + " comm.send({event_type: 'delete', 'id': id});\n", + " }\n", + " delete PyViz.plot_index[id];\n", + " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", + " var doc = window.Bokeh.index[id].model.document\n", + " doc.clear();\n", + " const i = window.Bokeh.documents.indexOf(doc);\n", + " if (i > -1) {\n", + " window.Bokeh.documents.splice(i, 1);\n", + " }\n", + " }\n", + "}\n", + "\n", + "/**\n", + " * Handle kernel restart event\n", + " */\n", + "function handle_kernel_cleanup(event, handle) {\n", + " delete PyViz.comms[\"hv-extension-comm\"];\n", + " window.PyViz.plot_index = {}\n", + "}\n", + "\n", + "/**\n", + " * Handle update_display_data messages\n", + " */\n", + "function handle_update_output(event, handle) {\n", + " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", + " handle_add_output(event, handle)\n", + "}\n", + "\n", + "function register_renderer(events, OutputArea) {\n", + " function append_mime(data, metadata, element) {\n", + " // create a DOM node to render to\n", + " var toinsert = this.create_output_subarea(\n", + " metadata,\n", + " CLASS_NAME,\n", + " EXEC_MIME_TYPE\n", + " );\n", + " this.keyboard_manager.register_events(toinsert);\n", + " // Render to node\n", + " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", + " render(props, toinsert[0]);\n", + " element.append(toinsert);\n", + " return toinsert\n", + " }\n", + "\n", + " events.on('output_added.OutputArea', handle_add_output);\n", + " events.on('output_updated.OutputArea', handle_update_output);\n", + " events.on('clear_output.CodeCell', handle_clear_output);\n", + " events.on('delete.Cell', handle_clear_output);\n", + " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", + "\n", + " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", + " safe: true,\n", + " index: 0\n", + " });\n", + "}\n", + "\n", + "if (window.Jupyter !== undefined) {\n", + " try {\n", + " var events = require('base/js/events');\n", + " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", + " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", + " register_renderer(events, OutputArea);\n", + " }\n", + " } catch(err) {\n", + " }\n", + "}\n" + ], + "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "
\n", + "
\n", + "
\n", + "" + ] + }, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "p1002" + } + }, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + " \n", + " \n", + "\n", + "\n", + "
\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import numpy as np\n", + "import kwant\n", + "\n", + "import holoviews as hv\n", + "hv.notebook_extension()\n", + "\n", + "from matplotlib import pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "7acf989f-3c7d-4cd9-ade3-803123e3a330", + "metadata": {}, + "outputs": [], + "source": [ + "from kpm_tools.evolution import evolve_vectors, _max_num_moments, evolve_vectors_time_steps" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "7730652d-b5f6-49aa-8bf5-842cb73bee17", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/pablo/.cache/pypoetry/virtualenvs/kpm-tools-1LxsbUd2-py3.10/lib/python3.10/site-packages/kwant-1.5.0a0.dev111+g7790469-py3.10-linux-x86_64.egg/kwant/plotter.py:893: RuntimeWarning:\n", + "\n", + "Kwant's plotting functions have\n", + "the side effect of selecting the matplotlib backend. To avoid this warning,\n", + "import matplotlib.pyplot, matplotlib.backends or call matplotlib.use().\n", + "\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "chain_length = 100\n", + "lat = kwant.lattice.chain(norbs=1)\n", + "syst = kwant.builder.Builder()\n", + "for i in range(chain_length):\n", + " syst[lat(i)] = 0\n", + "syst[lat.neighbors()] = -1\n", + "fsyst = syst.finalized()\n", + "kwant.plot(fsyst);" + ] + }, + { + "cell_type": "markdown", + "id": "243dc269-cccb-46f0-ba2f-54d10093f2e0", + "metadata": {}, + "source": [ + "## Time evolution\n", + "\n", + "We will demonstrate the time evolution using two initial states, one at the center of the chain, and one at the edge." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "31bd051c-8d24-4b23-a5e7-e11c48fff4bc", + "metadata": {}, + "outputs": [], + "source": [ + "vector_factory = kwant.kpm.LocalVectors(fsyst, where=[fsyst.sites[chain_length // 2], fsyst.sites[0]])\n", + "vectors = np.array([v for v in vector_factory])\n", + "\n", + "time_steps, dt = np.linspace(0, 64, 256, retstep=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "22d84ef0-cc31-4b08-8a36-483e124a9562", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 1.69 s, sys: 947 µs, total: 1.69 s\n", + "Wall time: 1.71 s\n" + ] + } + ], + "source": [ + "%%time\n", + "\n", + "accuracy = 0.5e-16\n", + "\n", + "eee = evolve_vectors_time_steps(\n", + " fsyst,\n", + " time_steps=time_steps,\n", + " vectors=vectors,\n", + " accuracy=accuracy\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "1764d818-29dd-4d64-be62-4d48d6a7eb63", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + ":Layout\n", + " .QuadMesh.Start_at_the_center :QuadMesh [$t$,$x[a]$] (LDOS)\n", + " .QuadMesh.Start_at_the_edge :QuadMesh [$t$,$x[a]$] (LDOS)" + ] + }, + "execution_count": 6, + "metadata": { + "application/vnd.holoviews_exec.v0+json": {} + }, + "output_type": "execute_result" + } + ], + "source": [ + "%%opts QuadMesh [aspect=\"square\" colorbar=True]\n", + "(\n", + " hv.QuadMesh(\n", + " (time_steps, np.arange(len(fsyst.sites)), np.abs(eee[:,0].T)),\n", + " kdims=[r'$t$',r'$x[a]$'], vdims=r'LDOS', label=\"start at the center\"\n", + " ) +\n", + " hv.QuadMesh(\n", + " (time_steps, np.arange(len(fsyst.sites)), np.abs(eee[:,1].T)),\n", + " kdims=[r'$t$',r'$x[a]$'], vdims=r'LDOS', label=\"start at the edge\"\n", + " )\n", + ").opts(title=\"Evolution of LDOS over time\")" + ] + }, + { + "cell_type": "markdown", + "id": "2c044872-26e8-4026-9782-2d8d9e543cea", + "metadata": {}, + "source": [ + "### Vector normalization over time\n", + "Like with every evolution method, there is the risk of loosing the normalization of the initial vectors.\n", + "\n", + "Here, we control this by setting the `accuracy` of the time evolution.\n", + "Note that for consecutive applications of the time evolution expansion, the errors can accumulate. Thanks to the KPM stability and the efficiency of the time evolution expansion, the errors do not blow exponentially.\n", + "\n", + "See [Performance of evolution](https://kpm-tools.readthedocs.io/en/latest/tutorials/tutorial_evolution_performance.html) for more details." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "4cb85f92-4b59-4a4b-bea0-c2caaddeacb5", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "" + ], + "text/plain": [ + ":Scatter [x] (y)" + ] + }, + "execution_count": 7, + "metadata": { + "application/vnd.holoviews_exec.v0+json": {} + }, + "output_type": "execute_result" + } + ], + "source": [ + "hv.Scatter((time_steps, abs(np.linalg.norm(eee[:,0], axis=1)-1)),\n", + " vdims=hv.Dimension('y', label=r'$|\\rho(t)-1|$',)\n", + " )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "kt", + "language": "python", + "name": "kt" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.13" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/docs/usage.md b/docs/usage.md deleted file mode 100644 index 7e1d1e1..0000000 --- a/docs/usage.md +++ /dev/null @@ -1,7 +0,0 @@ -# Usage - -```{eval-rst} -.. click:: kpm_tools.__main__:main - :prog: kpm-tools - :nested: full -``` diff --git a/noxfile.py b/noxfile.py index d6726fb..a13536d 100644 --- a/noxfile.py +++ b/noxfile.py @@ -121,8 +121,11 @@ def build_kwant(session: Session): """Build and install kwant from source.""" session.install("cython", "numpy", "scipy", "sympy", "tinyarray") + # Store the original directory + original_dir = Path.cwd() + # temp folder - kwant_dir = os.path.join(session.create_tmp(), "kwant") + kwant_dir = Path(session.create_tmp()) / "kwant" need_to_build = False # Check if kwant directory exists @@ -141,7 +144,7 @@ def build_kwant(session: Session): ) # Navigate to the cloned directory - session.cd(kwant_dir) + session.cd(str(kwant_dir)) # Checkout the master branch session.run("git", "checkout", "master", external=True) @@ -151,6 +154,10 @@ def build_kwant(session: Session): session.run("python", "setup.py", "build") session.run("python", "setup.py", "install") + # Return to the original directory and remove the kwant directory + session.cd(str(original_dir)) + shutil.rmtree(str(kwant_dir)) + @session(name="pre-commit", python=python_versions[0]) def precommit(session: Session) -> None: @@ -175,6 +182,7 @@ def precommit(session: Session) -> None: "pre-commit-hooks", "pyupgrade", ) + session.run("pre-commit", *args) if args and args[0] == "install": activate_virtualenv_in_precommit_hooks(session) @@ -204,6 +212,10 @@ def tests(session: Session) -> None: """Run the test suite.""" session.install(".") session.install("coverage[toml]", "pytest", "pygments") + + # Call the kwant installation functions + build_kwant(session) + try: session.run("coverage", "run", "--parallel", "-m", "pytest", *session.posargs) finally: @@ -229,6 +241,10 @@ def typeguard(session: Session) -> None: """Runtime type checking using Typeguard.""" session.install(".") session.install("pytest", "typeguard", "pygments") + + # Call the kwant installation functions + build_kwant(session) + session.run("pytest", f"--typeguard-packages={package}", *session.posargs) @@ -243,6 +259,7 @@ def xdoctest(session: Session) -> None: args.append("--colored=1") session.install(".") + session.install("xdoctest[colors]") session.run("python", "-m", "xdoctest", *args) @@ -259,6 +276,9 @@ def docs_build(session: Session) -> None: "sphinx", "sphinx-click", "nbsphinx", "pandoc", "furo", "myst-parser" ) + # Call the kwant installation functions + build_kwant(session) + build_dir = Path("docs", "_build") if build_dir.exists(): shutil.rmtree(build_dir) @@ -282,6 +302,9 @@ def docs(session: Session) -> None: "pandoc", ) + # Call the kwant installation functions + build_kwant(session) + build_dir = Path("docs", "_build") if build_dir.exists(): shutil.rmtree(build_dir) diff --git a/poetry.lock b/poetry.lock index c060ef9..ffa6612 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. [[package]] name = "alabaster" @@ -1153,13 +1153,13 @@ license = ["ukkonen"] [[package]] name = "idna" -version = "3.4" +version = "3.5" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.5" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.5-py3-none-any.whl", hash = "sha256:79b8f0ac92d2351be5f6122356c9a592c96d81c9a79e4b488bf2a6a15f88057a"}, + {file = "idna-3.5.tar.gz", hash = "sha256:27009fe2735bf8723353582d48575b23c533cc2c2de7b5a68908d91b5eb18d08"}, ] [[package]] @@ -1256,17 +1256,16 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio" [[package]] name = "ipython" -version = "8.17.2" +version = "8.18.0" description = "IPython: Productive Interactive Computing" optional = false python-versions = ">=3.9" files = [ - {file = "ipython-8.17.2-py3-none-any.whl", hash = "sha256:1e4d1d666a023e3c93585ba0d8e962867f7a111af322efff6b9c58062b3e5444"}, - {file = "ipython-8.17.2.tar.gz", hash = "sha256:126bb57e1895594bb0d91ea3090bbd39384f6fe87c3d57fd558d0670f50339bb"}, + {file = "ipython-8.18.0-py3-none-any.whl", hash = "sha256:d538a7a98ad9b7e018926447a5f35856113a85d08fd68a165d7871ab5175f6e0"}, + {file = "ipython-8.18.0.tar.gz", hash = "sha256:4feb61210160f75e229ce932dbf8b719bff37af123c0b985fd038b14233daa16"}, ] [package.dependencies] -appnope = {version = "*", markers = "sys_platform == \"darwin\""} colorama = {version = "*", markers = "sys_platform == \"win32\""} decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} @@ -2086,38 +2085,38 @@ files = [ [[package]] name = "mypy" -version = "1.7.0" +version = "1.7.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5da84d7bf257fd8f66b4f759a904fd2c5a765f70d8b52dde62b521972a0a2357"}, - {file = "mypy-1.7.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a3637c03f4025f6405737570d6cbfa4f1400eb3c649317634d273687a09ffc2f"}, - {file = "mypy-1.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b633f188fc5ae1b6edca39dae566974d7ef4e9aaaae00bc36efe1f855e5173ac"}, - {file = "mypy-1.7.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d6ed9a3997b90c6f891138e3f83fb8f475c74db4ccaa942a1c7bf99e83a989a1"}, - {file = "mypy-1.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:1fe46e96ae319df21359c8db77e1aecac8e5949da4773c0274c0ef3d8d1268a9"}, - {file = "mypy-1.7.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:df67fbeb666ee8828f675fee724cc2cbd2e4828cc3df56703e02fe6a421b7401"}, - {file = "mypy-1.7.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a79cdc12a02eb526d808a32a934c6fe6df07b05f3573d210e41808020aed8b5d"}, - {file = "mypy-1.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f65f385a6f43211effe8c682e8ec3f55d79391f70a201575def73d08db68ead1"}, - {file = "mypy-1.7.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:0e81ffd120ee24959b449b647c4b2fbfcf8acf3465e082b8d58fd6c4c2b27e46"}, - {file = "mypy-1.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:f29386804c3577c83d76520abf18cfcd7d68264c7e431c5907d250ab502658ee"}, - {file = "mypy-1.7.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:87c076c174e2c7ef8ab416c4e252d94c08cd4980a10967754f91571070bf5fbe"}, - {file = "mypy-1.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6cb8d5f6d0fcd9e708bb190b224089e45902cacef6f6915481806b0c77f7786d"}, - {file = "mypy-1.7.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d93e76c2256aa50d9c82a88e2f569232e9862c9982095f6d54e13509f01222fc"}, - {file = "mypy-1.7.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:cddee95dea7990e2215576fae95f6b78a8c12f4c089d7e4367564704e99118d3"}, - {file = "mypy-1.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:d01921dbd691c4061a3e2ecdbfbfad029410c5c2b1ee88946bf45c62c6c91210"}, - {file = "mypy-1.7.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:185cff9b9a7fec1f9f7d8352dff8a4c713b2e3eea9c6c4b5ff7f0edf46b91e41"}, - {file = "mypy-1.7.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7a7b1e399c47b18feb6f8ad4a3eef3813e28c1e871ea7d4ea5d444b2ac03c418"}, - {file = "mypy-1.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9fe455ad58a20ec68599139ed1113b21f977b536a91b42bef3ffed5cce7391"}, - {file = "mypy-1.7.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d0fa29919d2e720c8dbaf07d5578f93d7b313c3e9954c8ec05b6d83da592e5d9"}, - {file = "mypy-1.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:2b53655a295c1ed1af9e96b462a736bf083adba7b314ae775563e3fb4e6795f5"}, - {file = "mypy-1.7.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1b06b4b109e342f7dccc9efda965fc3970a604db70f8560ddfdee7ef19afb05"}, - {file = "mypy-1.7.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bf7a2f0a6907f231d5e41adba1a82d7d88cf1f61a70335889412dec99feeb0f8"}, - {file = "mypy-1.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:551d4a0cdcbd1d2cccdcc7cb516bb4ae888794929f5b040bb51aae1846062901"}, - {file = "mypy-1.7.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:55d28d7963bef00c330cb6461db80b0b72afe2f3c4e2963c99517cf06454e665"}, - {file = "mypy-1.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:870bd1ffc8a5862e593185a4c169804f2744112b4a7c55b93eb50f48e7a77010"}, - {file = "mypy-1.7.0-py3-none-any.whl", hash = "sha256:96650d9a4c651bc2a4991cf46f100973f656d69edc7faf91844e87fe627f7e96"}, - {file = "mypy-1.7.0.tar.gz", hash = "sha256:1e280b5697202efa698372d2f39e9a6713a0395a756b1c6bd48995f8d72690dc"}, + {file = "mypy-1.7.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:12cce78e329838d70a204293e7b29af9faa3ab14899aec397798a4b41be7f340"}, + {file = "mypy-1.7.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1484b8fa2c10adf4474f016e09d7a159602f3239075c7bf9f1627f5acf40ad49"}, + {file = "mypy-1.7.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31902408f4bf54108bbfb2e35369877c01c95adc6192958684473658c322c8a5"}, + {file = "mypy-1.7.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:f2c2521a8e4d6d769e3234350ba7b65ff5d527137cdcde13ff4d99114b0c8e7d"}, + {file = "mypy-1.7.1-cp310-cp310-win_amd64.whl", hash = "sha256:fcd2572dd4519e8a6642b733cd3a8cfc1ef94bafd0c1ceed9c94fe736cb65b6a"}, + {file = "mypy-1.7.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b901927f16224d0d143b925ce9a4e6b3a758010673eeded9b748f250cf4e8f7"}, + {file = "mypy-1.7.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2f7f6985d05a4e3ce8255396df363046c28bea790e40617654e91ed580ca7c51"}, + {file = "mypy-1.7.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:944bdc21ebd620eafefc090cdf83158393ec2b1391578359776c00de00e8907a"}, + {file = "mypy-1.7.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9c7ac372232c928fff0645d85f273a726970c014749b924ce5710d7d89763a28"}, + {file = "mypy-1.7.1-cp311-cp311-win_amd64.whl", hash = "sha256:f6efc9bd72258f89a3816e3a98c09d36f079c223aa345c659622f056b760ab42"}, + {file = "mypy-1.7.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6dbdec441c60699288adf051f51a5d512b0d818526d1dcfff5a41f8cd8b4aaf1"}, + {file = "mypy-1.7.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:4fc3d14ee80cd22367caaaf6e014494415bf440980a3045bf5045b525680ac33"}, + {file = "mypy-1.7.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c6e4464ed5f01dc44dc9821caf67b60a4e5c3b04278286a85c067010653a0eb"}, + {file = "mypy-1.7.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:d9b338c19fa2412f76e17525c1b4f2c687a55b156320acb588df79f2e6fa9fea"}, + {file = "mypy-1.7.1-cp312-cp312-win_amd64.whl", hash = "sha256:204e0d6de5fd2317394a4eff62065614c4892d5a4d1a7ee55b765d7a3d9e3f82"}, + {file = "mypy-1.7.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:84860e06ba363d9c0eeabd45ac0fde4b903ad7aa4f93cd8b648385a888e23200"}, + {file = "mypy-1.7.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:8c5091ebd294f7628eb25ea554852a52058ac81472c921150e3a61cdd68f75a7"}, + {file = "mypy-1.7.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40716d1f821b89838589e5b3106ebbc23636ffdef5abc31f7cd0266db936067e"}, + {file = "mypy-1.7.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cf3f0c5ac72139797953bd50bc6c95ac13075e62dbfcc923571180bebb662e9"}, + {file = "mypy-1.7.1-cp38-cp38-win_amd64.whl", hash = "sha256:78e25b2fd6cbb55ddfb8058417df193f0129cad5f4ee75d1502248e588d9e0d7"}, + {file = "mypy-1.7.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:75c4d2a6effd015786c87774e04331b6da863fc3fc4e8adfc3b40aa55ab516fe"}, + {file = "mypy-1.7.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:2643d145af5292ee956aa0a83c2ce1038a3bdb26e033dadeb2f7066fb0c9abce"}, + {file = "mypy-1.7.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aa828610b67462ffe3057d4d8a4112105ed211596b750b53cbfe182f44777a"}, + {file = "mypy-1.7.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ee5d62d28b854eb61889cde4e1dbc10fbaa5560cb39780c3995f6737f7e82120"}, + {file = "mypy-1.7.1-cp39-cp39-win_amd64.whl", hash = "sha256:72cf32ce7dd3562373f78bd751f73c96cfb441de147cc2448a92c1a308bd0ca6"}, + {file = "mypy-1.7.1-py3-none-any.whl", hash = "sha256:f7c5d642db47376a0cc130f0de6d055056e010debdaf0707cd2b0fc7e7ef30ea"}, + {file = "mypy-1.7.1.tar.gz", hash = "sha256:fcb6d9afb1b6208b4c712af0dafdc650f518836065df0d4fb1d800f5d6773db2"}, ] [package.dependencies] @@ -4382,4 +4381,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "a4869a711e84f5a81ea008859a2bca5c051404d2f0c1ff3206dd0a0c2998d439" +content-hash = "b1fb5d158546b931f7c0a44f7a0f036b68577ad8e0aabb1723a5679ab825c4dd" diff --git a/pyproject.toml b/pyproject.toml index 6f9d322..14aa962 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "kpm-tools" -version = "0.0.1" +version = "0.0.2" description = "KPM Tools" authors = ["Pablo Piskunow "] license = "BSD 2-Clause" @@ -61,6 +61,7 @@ nbsphinx = "^0.9.3" jupyter = "^1.0.0" plotly = "^5.18.0" pandoc = "^2.3" +isort = "^5.12.0" [tool.coverage.paths] source = ["src", "*/site-packages"] diff --git a/src/kpm_tools/__init__.py b/src/kpm_tools/__init__.py index 6cdb3ea..576b142 100644 --- a/src/kpm_tools/__init__.py +++ b/src/kpm_tools/__init__.py @@ -1 +1,64 @@ """KPM Tools.""" +# flake8: noqa +from .bloch import _hopping_distance +from .bloch import separate_bloch_components +from .bloch import wrap_distance +from .bloch import wrap_velocity +from .bloch import wraparound_by_parts +from .common import expectation_value +from .common import identity_operator +from .common import local_expectation_value +from .common import position_operator +from .common import standard_gaussian +from .common import trace_orbs +from .common import trace_unit_cell +from .common import transparent_cmap +from .common import uniform +from .evolution import _max_num_moments +from .evolution import coef_evo +from .evolution import evolve_observable +from .evolution import evolve_vectors +from .evolution import evolve_vectors_time_steps +from .hamiltonians import haldane_obc +from .hamiltonians import haldane_pbc +from .hamiltonians import qhe_obc +from .hamiltonians import qhe_pbc +from .kpm_funcs import chebysev_polynomial_series +from .kpm_funcs import chern_number +from .kpm_funcs import chern_number_pbc +from .kpm_funcs import coef_delta_function +from .kpm_funcs import coef_greens_function +from .kpm_funcs import coef_greens_function_a +from .kpm_funcs import coef_greens_function_prime +from .kpm_funcs import coef_greens_function_prime_a +from .kpm_funcs import coef_greens_function_prime_r +from .kpm_funcs import coef_greens_function_r +from .kpm_funcs import coef_projector_function +from .kpm_funcs import coef_projector_function_unoccupied +from .kpm_funcs import conductivity +from .kpm_funcs import delta_function +from .kpm_funcs import greens_function +from .kpm_funcs import longitudinal_conductivity +from .kpm_funcs import projector_operator +from .kpm_generator import GeneralVectorExpansion +from .kpm_generator import IteratorKPM +from .kpm_generator import SpectralDensityIterator +from .kpm_generator import _BaseKPM +from .kpm_generator import _dagger +from .kpm_generator import _normalize_num_moments +from .kpm_generator import _normalize_operator +from .kpm_generator import _rescale +from .kpm_generator import concatenator +from .kpm_generator import general_function +from .kpm_generator import multiprocess_update +from .kpm_generator import process_update +from .kpm_generator import thread_update +from .plotting import Arrow3D +from .plotting import plot_arrows3d +from .plotting import plot_kwant +from .plotting import plot_neighbors +from .plotting import plot_vectors +from .tiles import TileKVectors +from .tiles import _TileVectors +from .tiles import momentum_to_ts +from .tiles import tile_random_kvectors diff --git a/src/kpm_tools/bloch.py b/src/kpm_tools/bloch.py index 11cf440..acfa58b 100644 --- a/src/kpm_tools/bloch.py +++ b/src/kpm_tools/bloch.py @@ -9,12 +9,6 @@ import numpy as np import tinyarray as ta - -import kwant - - -if kwant.__version__ < "1.5": - raise ImportError("This module does not work with versions of Kwant " "<= 1.4.2.") from kwant._common import get_parameters from kwant._common import memoize from kwant.builder import Builder diff --git a/src/kpm_tools/common.py b/src/kpm_tools/common.py index 0b6c6bd..32784be 100644 --- a/src/kpm_tools/common.py +++ b/src/kpm_tools/common.py @@ -2,13 +2,12 @@ from collections import OrderedDict +import kwant import numpy as np from matplotlib.colors import ListedColormap from matplotlib.pylab import cm from scipy.sparse import diags -import kwant - def identity_operator(x): """Return argument.""" diff --git a/src/kpm_tools/hamiltonians.py b/src/kpm_tools/hamiltonians.py index 9bb61d4..421ca71 100644 --- a/src/kpm_tools/hamiltonians.py +++ b/src/kpm_tools/hamiltonians.py @@ -4,9 +4,8 @@ """ from itertools import product -import numpy as np - import kwant +import numpy as np from kwant import HoppingKind diff --git a/src/kpm_tools/kpm_generator.py b/src/kpm_tools/kpm_generator.py index a89787c..0a53368 100644 --- a/src/kpm_tools/kpm_generator.py +++ b/src/kpm_tools/kpm_generator.py @@ -6,14 +6,14 @@ from math import ceil from multiprocessing import Pool +import kwant import numpy as np -from common import identity_operator +from kwant.operator import _LocalOperator from scipy.sparse import csr_matrix from scipy.sparse import identity from scipy.sparse.linalg import eigsh -import kwant -from kwant.operator import _LocalOperator +from .common import identity_operator DEFAULT_MOMENTS = 100 @@ -23,20 +23,16 @@ class IteratorKPM: r"""Iterator of KPM vectors. This iterator yields vectors as - .. math:: - T_n(H) \\rvert v \\langle - - for vectors :math:`\\rvert v \\langle` in ``vectors``, - for 'n' in '[0, max_moments]'. - + `T_n(H) | v >` + for vectors `| v >` in `vectors`, + for 'n' in '[0, max_moments]'. Notes ----- - Returns a sequence of expanded vectors of shape ``(M, N)``. - If the input is a vector then ``M=1``. - + Returns a sequence of expanded vectors of shape `(M, N)`. + If the input is a vector then `M=1`. """ def __init__(self, ham, vectors, max_moments=None, operator=None, num_threads=None): @@ -380,11 +376,11 @@ def add_moments(self, num_moments=None, *, energy_resolution=None): ---------- num_moments: positive int The number of Chebyshev moments to add. Mutually - exclusive with ``energy_resolution``. + exclusive with `energy_resolution`. energy_resolution: positive float, optional Features wider than this resolution are visible in the spectral density. Mutually exclusive with - ``num_moments``. + `num_moments`. """ new_moments = _normalize_num_moments(num_moments, energy_resolution, self._a) @@ -488,11 +484,11 @@ def add_moments(self, num_moments=None, *, energy_resolution=None): ---------- num_moments: positive int The number of Chebyshev moments to add. Mutually - exclusive with ``energy_resolution``. + exclusive with `energy_resolution`. energy_resolution: positive float, optional Features wider than this resolution are visible in the spectral density. Mutually exclusive with - ``num_moments``. + `num_moments`. """ new_moments = _normalize_num_moments(num_moments, energy_resolution, self._a) diff --git a/src/kpm_tools/tiles.py b/src/kpm_tools/tiles.py new file mode 100644 index 0000000..57c1d5a --- /dev/null +++ b/src/kpm_tools/tiles.py @@ -0,0 +1,199 @@ +"""Generate tile vectors to compute the effective Bloch spectrum.""" + +from collections import defaultdict + +import kwant +import numpy as np +from kwant._common import ensure_rng + + +def momentum_to_ts(k, ts): + """Transform 'k' to the reciprocal lattice basis.""" + # columns of B are lattice vectors + _b = np.array(ts.periods).T + # columns of A are reciprocal lattice vectors + _a = np.linalg.pinv(_b).T + k, residuals = np.linalg.lstsq(_a, k, rcond=None)[:2] + if np.any(abs(residuals) > 1e-7): + raise RuntimeError( + "Requested momentum doesn't correspond to " + "any lattice momentum or TranslationalSymmetry." + ) + return k + + +class _TileVectors: + def __init__(self, sites, tile, ts, *, check=True): + """Construct an iterator over the sites in 'tile'. + + The iterator returns one vector for every orbital for every site + in the fundamental domain (FD) of 'tile'. + Each vector contains the orbital and its copies on the other + tiles. + + Parameters + ---------- + sites : iterable of `kwant.builder.Site` instances + The sites of the system. Should belong to a lattice that + is commensurate with both 'tile' and 'ts'. + tile : instance of `~kwant.TranslationalSymmetry` + Translational symmetry of the tiles within the supercell. + The tiles should cover the supercell 'ts'. + ts : instance of `~kwant.TranslationalSymmetry` or + Translational symmetry of the supercell. + check : bool, default to 'True' + Check that 'tile' covers the 'ts'. This is done by checking + that the translational symmetry 'tile' has the subgroup 'ts'. + If 'False', do not check anything. + + """ + if check: + # This does not yet checks + # for lattice commensuration with tile nor TS. + # The check is done when calling `tile.to_fd()`. + if not tile.has_subgroup(ts): + raise ValueError(f"The tile {tile} has no subgroup {ts}.") + + self.tile = tile + self.ts = ts + + # assume all norbs are the same + self.norbs = sites[0].family.norbs + self.tot_norbs = self.norbs * len(sites) + + self.site_replicas = defaultdict(list) + for idx, site in enumerate(sites): + base = tile.to_fd(site) + self.site_replicas[base].append(idx) + + self.keys = list(self.site_replicas.keys()) + + # these counters can be reset to default values + self.idx = 0 + self.orb_idx = 0 + + def _reset_count(self): + self.idx = 0 + self.orb_idx = 0 + + def __len__(self): + return self.norbs * len(self.keys) + + def __iter__(self): + return self + + @property + def _norm(self): + return 1 / len(self) + + def __next__(self): + try: + keys = self.keys[self.idx] + except IndexError as err: + raise StopIteration( + "Too many vectors requested " "from this generator." + ) from err + + site_indices = np.array(self.site_replicas[keys], dtype=int) + orbs = site_indices * self.norbs + self.orb_idx + + self.orb_idx += 1 + # bump indices if needed + if self.orb_idx >= self.norbs: + self.idx += 1 + self.orb_idx = 0 + + return site_indices, orbs + + +class TileKVectors(_TileVectors): + """Construct k-vectors over the sites in 'tile'. + + The iterator returns one vector for every orbital for every site + in the fundamental domain (FD) of 'tile'. + Each vector contains the orbital and its copies on the other + tiles, multiplied with the phase given by the position and the + 'k' vector. + + Parameters + ---------- + k : pair or triplet floats + The vector in k-space. Should have the same dimensions as the + positions of the 'syst'. + tile : instance of `~kwant.TranslationalSymmetry` + Translational symmetry of the tiles within the supercell. + The tiles should cover the supercell defined by the wrapped + symmetry of 'syst'. + syst : instance of `~kwant.system.FiniteSystem` + System with wrapped symmetry. + + Note + ---- + 'kwargs' are passed to `_TileVectors`. + + """ + + def __init__(self, k, tile, syst, **kwargs): + """Initialize tiles.""" + self.k = k + self.positions = np.array([s.pos for s in syst.sites]) + + if isinstance(syst.symmetry, kwant.builder.NoSymmetry): + ts = syst._wrapped_symmetry + else: + ts = syst.symmetry + + super().__init__(syst.sites, tile, ts, **kwargs) + + def _get_orbs_and_phase(self): + site_indices, orbs = super().__next__() + pos = self.positions[site_indices] + phase = np.exp(1j * pos.dot(self.k)) + return orbs, phase + + def __next__( + self, + ): + """Get the next vector.""" + orbs, phase = self._get_orbs_and_phase() + + vector = np.zeros(self.tot_norbs, dtype=complex) + vector[orbs] = phase + return vector + + +def tile_random_kvectors(k, tile, syst, *, rng=0, **kwargs): + """Construct an iterator of random phase vectors inside 'tile'. + + The other copies of 'tile' will have a phase relative to the base + tile. That phase is given by 'k' and the positions of the sites in + the 'syst'. Check 'TileKVectors' for details. + + Parameters + ---------- + k : pair or triplet floats + The vector in k-space. Should have the same dimensions as the + positions of the 'syst'. + tile : instance of `~kwant.TranslationalSymmetry` + Translational symmetry of the tiles within the supercell. + The tiles should cover the supercell defined by the wrapped + symmetry of 'syst'. + syst : instance of `~kwant.system.FiniteSystem` + System with wrapped symmetry. + rng : int, float, or string, default to 'int(0)' + Initial seed for the random vectors to ensure reproducibility. + + Note + ---- + 'kwargs' are passed to `_TileVectors`. + """ + rng = ensure_rng(rng) + tile_kvecs = TileKVectors(k, tile, syst, **kwargs) + + while True: + tile_kvecs._reset_count() + vector = np.zeros(tile_kvecs.tot_norbs, dtype=complex) + for _ in range(len(tile_kvecs)): + orbs, phase = tile_kvecs._get_orbs_and_phase() + vector[orbs] = phase * np.exp(2j * np.pi * rng.random_sample()) + yield vector