{ "cells": [ { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "# Apply a frequency response function\n", "\n", "Objects from `thztools`: `apply_frf`, `timebase`, `wave`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from matplotlib import pyplot as plt\n", "import numpy as np\n", "\n", "import thztools as thz" ] }, { "cell_type": "markdown", "metadata": { "collapsed": false }, "source": [ "## Set the simulation parameters" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "n = 256 # Number of samples\n", "dt = 0.05 # Sampling time [ps]\n", "a = 0.5 # Scale factor\n", "eta = 1.0 # Delay [ps]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Simulate an input waveform" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "t = thz.timebase(n, dt=dt)\n", "mu = thz.wave(n, dt=dt)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Define the frequency response function\n", "\n", "The frequency response function `frfun` rescales the input waveform by `a` and delays it by `eta`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def frfun(omega, _a, _eta):\n", " return _a * np.exp(-1j * omega * _eta)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Apply the frequency response function\n", "\n", "Generate the time-domain output waveform `psi` by applying `frfun` to `mu` with the `apply_frf` function." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "psi = thz.apply_frf(frfun, mu, dt=dt, args=(a, eta))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Show the input and output waveforms" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_, ax = plt.subplots()\n", "\n", "ax.plot(t, mu, label=r'$\\mu$')\n", "ax.plot(t, psi, label=r'$\\psi$')\n", "\n", "ax.legend()\n", "\n", "ax.set_xlabel('Time (ps)')\n", "ax.set_ylabel(r'Amplitude (units of $\\mu_{p})$')\n", "\n", "ax.set_xticks(np.arange(0, 11, 5))\n", "ax.set_xlim(0, 10)\n", "\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Change sign convention\n", "\n", "The above example uses the $+i\\omega t$ sign convention for representing harmonic waves with complex exponentials. NumPy also uses this convention in its definition of the FFT. Physicists commonly use the $-i\\omega t$ sign convention, which can cause confusion when translating between analytic expressions and computational expressions. The `apply_frf` function supports both sign conventions through the boolean parameter `numpy_sign_convention`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "def frfun_phys(omega, _a, _eta):\n", " return _a * np.exp(1j * omega * _eta)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "psi_phys = thz.apply_frf(frfun_phys, mu, dt=dt, args=(a, eta), numpy_sign_convention=False)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "_, ax = plt.subplots()\n", "\n", "ax.plot(t, mu, label=r'$\\mu$')\n", "ax.plot(t, psi_phys, label=r'$\\psi$')\n", "\n", "ax.legend()\n", "\n", "ax.set_xlabel('Time (ps)')\n", "ax.set_ylabel(r'Amplitude (units of $\\mu_{p})$')\n", "\n", "ax.set_xticks(np.arange(0, 11, 5))\n", "ax.set_xlim(0, 10)\n", "\n", "plt.show()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "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.9.16" } }, "nbformat": 4, "nbformat_minor": 1 }