diff --git a/docs/source/tutorials/index.rst b/docs/source/tutorials/index.rst index 51818828..9ff53d8c 100644 --- a/docs/source/tutorials/index.rst +++ b/docs/source/tutorials/index.rst @@ -19,4 +19,5 @@ Additionally, a set of static (automatically tested) examples can be found below 1d_temporal_laser.ipynb 2d_spatial_laser.ipynb nonlinear_propagation_split_step.ipynb + user_defined_longitudinal_profile.ipynb collins_propagator.ipynb diff --git a/docs/source/tutorials/user_defined_longitudinal_profile.ipynb b/docs/source/tutorials/user_defined_longitudinal_profile.ipynb new file mode 100644 index 00000000..26d8a17c --- /dev/null +++ b/docs/source/tutorials/user_defined_longitudinal_profile.ipynb @@ -0,0 +1,168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e1ed0812-0917-4bb6-b872-3fda185ceb7c", + "metadata": {}, + "source": [ + "# Laser Pulse with user-defined longitudinal profile\n", + "\n", + "In this example we show how to define a custom longitudinal profile based on an analytical expression (in this case a \"flat-top\" profile that rises smoothly from zero to one as a squared cosine, stays constant for some time, and then goes smoothly to zero as a squared cosine)." + ] + }, + { + "cell_type": "markdown", + "id": "f6a4ee6a-1135-412a-9317-1f5dd3edcb66", + "metadata": {}, + "source": [ + "## Define a derived class of LongitudinalProfile: MyOwnLongitudinalProfile\n", + "First, we define a new class `MyOwnLongitudinalProfile`, inheriting the `LongitudinalProfile` class. We need to implement the `__init__` method to record the parameters of the custom profile, and the `evaluate` method that should return the envelope as a function of the time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb439136-ebc4-4c90-a363-322b224120d0", + "metadata": {}, + "outputs": [], + "source": [ + "from lasy.profiles.longitudinal import LongitudinalProfile\n", + "\n", + "\n", + "# User-defined profile\n", + "class MyOwnLongitudinalProfile(LongitudinalProfile):\n", + " r\"\"\"\n", + " Derived class for the analytic longitudinal flat-top profile of a laser pulse.\n", + "\n", + " Derived class for the analytic longitudinal flat-top profile of a laser pulse,\n", + " i.e., a longitudinal profile that rises smoothly from zero to one (as a squared cosine),\n", + " stays constant for some time and then goes down smoothly to zero (as a squared cosine).\n", + "\n", + " Parameters\n", + " ----------\n", + " wavelength : float (in meter)\n", + " The main laser wavelength :math:`\\lambda_0` of the laser.\n", + " t_start : float (in seconds)\n", + " The starting time of the pulse,\n", + " t_rise : float (in seconds)\n", + " The rise time of the pulse envelope,\n", + " t_flat : float (in seconds)\n", + " The duration of the flat part of the pulse envelope,\n", + " t_down : float (in seconds)\n", + " The duration of the decreasing part of the pulse envelope,\n", + " cep_phase : float (in radian), optional\n", + " The Carrier Enveloppe Phase (CEP)\n", + "\n", + " \"\"\"\n", + "\n", + " def __init__(self, wavelength, t_start, t_rise, t_flat, t_down, cep_phase):\n", + " super().__init__(wavelength)\n", + " self.t_start = t_start\n", + " self.t_rise = t_rise\n", + " self.t_flat = t_flat\n", + " self.t_down = t_down\n", + " self.cep_phase = cep_phase\n", + "\n", + " def evaluate(self, t):\n", + " \"\"\"\n", + " Return the longitudinal envelope.\n", + "\n", + " Parameters\n", + " ----------\n", + " t : ndarrays of floats\n", + " Define points on which to evaluate the envelope\n", + "\n", + " Returns\n", + " -------\n", + " envelope : ndarray of complex numbers\n", + " Contains the value of the longitudinal envelope at the\n", + " specified points. This array has the same shape as the array t.\n", + " \"\"\"\n", + " t1 = self.t_start\n", + " t2 = t1 + self.t_rise\n", + " t3 = t2 + self.t_flat\n", + " t4 = t3 + self.t_down\n", + " tcep = 0.5 * (t3 + t2)\n", + "\n", + " envelope = (\n", + " (t >= t1) * (t < t2) * np.cos(0.5 * np.pi * (t - t2) / (t2 - t1)) ** 2\n", + " + (t >= t2) * (t < t3)\n", + " + (t >= t3) * (t < t4) * np.cos(0.5 * np.pi * (t - t3) / (t3 - t4)) ** 2\n", + " ) * np.exp(+1.0j * (self.cep_phase + self.omega0 * tcep))\n", + "\n", + " return envelope" + ] + }, + { + "cell_type": "markdown", + "id": "dace1e17-5f9a-4a8b-b424-f6c26badc706", + "metadata": {}, + "source": [ + "## Use MyOwnLongitudinalProfile as a regular longitudinal profile\n", + "The new class `MyOwnLongitudinalProfile` can be used just like any other longitudinal profile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d1fb72e-b052-4ab0-95de-af974bc7fe54", + "metadata": {}, + "outputs": [], + "source": [ + "wavelength = 800e-6\n", + "t_start = 0\n", + "t_rise = 20e-15\n", + "t_flat = 20e-15\n", + "t_down = 10e-15\n", + "cep_phase = 0\n", + "longitudinal_profile = MyOwnLongitudinalProfile(\n", + " wavelength, t_start, t_rise, t_flat, t_down, cep_phase\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38f2ee28-2d60-488d-8e42-7f3444e41e93", + "metadata": {}, + "outputs": [], + "source": [ + "# test the custom longitudinal profile\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "times = np.linspace(0.0, 55e-15, 300)\n", + "plt.plot(times, np.abs(longitudinal_profile.evaluate(times)))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "60f9d7b6-dd76-4041-9edf-aec39132646f", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.13.3" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}