.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_tutorials/tests/g_performance_CQE.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_tutorials_tests_g_performance_CQE.py: Stepsize adaption in the CQE method =================================== This example demonstrates the ability of the conservation quantity error (CQE) method [H2009]_ to locally decrease the stepsize when higher accuracy is needed. As test case, the interaction dynamics of two colliding fundamental soliton governed by the standard nonlinear Schrödinger equation is considered. In contrast to the LEM, which uses a local error derived by means of step-doubling and extrapolation, the CQE uses a conservation quantity of the underlying propagation equation to drive stepsize adaption. .. codeauthor:: Oliver Melchert .. GENERATED FROM PYTHON SOURCE LINES 18-20 We first import the functionality needed to perform the sequence of numerical experiments: .. GENERATED FROM PYTHON SOURCE LINES 20-30 .. code-block:: default import sys import numpy as np from fmas.models import ModelBaseClass from fmas.config import FTFREQ, FT, IFT, C0 from fmas.grid import Grid from fmas.solver import CQE from fmas.data_io import save_h5 from fmas.tools import plot_evolution .. GENERATED FROM PYTHON SOURCE LINES 31-41 Next, we implement a model for the nonlinear Schrödinger equation. In particular, we here consider the standard nonlinear Schrödinger equation, given by .. math:: \partial_z u = -i \frac{\beta_2}{2}\partial_t^2 u + i\gamma |u|^2 u, wherein :math:`u = u(z, t)` represents the slowly varying pulse envelope, :math:`\beta_2=-1` is the second order dispersion parameter, and :math:`\gamma=1` is the nonlinear parameter: .. GENERATED FROM PYTHON SOURCE LINES 41-57 .. code-block:: default class NSE(ModelBaseClass): def __init__(self, w, beta, gamma): super().__init__(w, beta_w=beta) self.gamma = gamma @property def Lw(self): return 1j*self.beta_w def N(self, uw): ut = IFT(uw) return 1j*self.gamma*FT(np.abs(ut)**2*ut) .. GENERATED FROM PYTHON SOURCE LINES 58-79 Next, we set up the computational domain, the model, and the LEM solver and prepare an initial condition with two fundamental solitons. The velocity of the solitons is adjusted so that they collide after approximately half a soliton period. To construct the initial condition, we use the exact single-soliton solution of the nonlinar Schrödinger equation, given by .. math:: u_{\rm{exact}}(z,t) = \sqrt{P_0} {\rm{sech}}(t/t_0)\,e^{-i\gamma P_0 z/2}, with :math:`P_0=|\beta_2|/(\gamma t_0^2)`. We here consider two fundamental solitons of duration :math:`t_0=1` and frequency detunings :math:`\omega_0=25` to construct the initial condition .. math: u_0(t) = u{\rm{exact}}(0, t+t_{\rm{off}})\,e^{i \omega_0 t}+ u{\rm{exact}}(0, t-t_{\rm{off}})\,e^{- i \omega_0 t}. The propagation is performed up to :math:`z_{\rm{max}}=\pi/2`, i.e. for one soliton period. .. GENERATED FROM PYTHON SOURCE LINES 79-107 .. code-block:: default # -- SET MODEL PARAMETERS t_max = -50. Nt = 2**12 # ... PROPAGATION CONSTANT (POLYNOMIAL MODEL) beta = np.poly1d([-0.5, 0.0, 0.0]) beta1 = np.polyder(beta, m=1) beta2 = np.polyder(beta, m=2) # ... NONLINEAR PARAMETER gamma = 1. # ... SOLITON PARAMTERS t0 = 1. # duration t_off = 20. # temporal offset w0 = 25. # detuning P0 = np.abs(beta2(0))/t0/t0/gamma # peak-intensity LD = t0*t0/np.abs(beta2(0)) # dispersion length # ... EXACT SOLUTION u_exact = lambda z, t: np.sqrt(P0)*np.exp(0.5j*gamma*P0*z)/np.cosh(t/t0) # -- INITIALIZATION STAGE # ... COMPUTATIONAL DOMAIN grid = Grid(t_max=t_max, t_num=Nt) t, w = grid.t, grid.w # ... NONLINEAR SCHROEDINGER EQUATION model = NSE(w, beta(w), gamma) # ... PROPAGATION ALGORITHM .. GENERATED FROM PYTHON SOURCE LINES 108-116 In order to drive stepsize adaption, the CQE method monitors a conservation law exhibited by the underlying propagation equation. Here, for the standard nonlinear Schrödinger equation, we opt to use the conserved quantity .. math: C_E = \int |u(z,t)|^2 ~ {\rm{d}}t, implemented by the function: .. GENERATED FROM PYTHON SOURCE LINES 116-120 .. code-block:: default def my_CQE_fun(i, zi, w, uw): return np.sum(np.abs(uw)**2) .. GENERATED FROM PYTHON SOURCE LINES 121-122 The function can be set when an instance of the solver is initialized: .. GENERATED FROM PYTHON SOURCE LINES 122-136 .. code-block:: default solver = CQE(model.Lw, model.N, del_G = 1e-7, user_action = my_CQE_fun) # ... INITIAL CONDITION u0_t = u_exact(0.0, t+t_off)*np.exp(1j*w0*t) u0_t += u_exact(0.0, t-t_off)*np.exp(-1j*w0*t) solver.set_initial_condition(w, FT(u0_t)) # -- RUN SOLVER solver.propagate( z_range = 0.5*np.pi*LD, # propagation range n_steps = 512, n_skip = 2 ) .. GENERATED FROM PYTHON SOURCE LINES 137-139 The figure below shows the propagation dynamics of the above initial condition: .. GENERATED FROM PYTHON SOURCE LINES 139-142 .. code-block:: default plot_evolution( solver.z, grid.t, solver.utz, t_lim = (-30,30), w_lim = (-50.,50.)) .. image:: /auto_tutorials/tests/images/sphx_glr_g_performance_CQE_001.png :alt: $|u|^2/{\rm{max}}\left(|u|^2\right)$, $|u_\omega|^2/{\rm{max}}\left(|u_\omega|^2\right)$ :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 143-149 Below we prepare a figure showing the variation of the local relative error upon propagation (top figure), and the decrease of the local stepsize in the vicinity of the soliton-soliton collision (bottom subfigure). In the top figure, the shaded region indicates the local goal error range. Aim of the CQE method is to keep the conservation quantity error within that range. .. GENERATED FROM PYTHON SOURCE LINES 149-168 .. code-block:: default # sphinx_gallery_thumbnail_number = 2 import matplotlib as mpl import matplotlib.pyplot as plt import matplotlib.colors as col f, (ax1,ax2) = plt.subplots(2, 1, figsize=(8,6)) ax1.plot(range(len(solver._del_rle)), solver._del_rle) ax1.axhspan(0.1e-7,1e-7,color='lightgray') ax1.set_ylabel(r"$\delta_{\rm{CQE}}$") ax2.plot(range(len(solver._dz_a)), solver._dz_a) ax2.set_ylabel(r"$h~{(\mathrm{\mu m})}$") ax2.set_xlabel(r"$z$-slice number $n$") plt.show() .. image:: /auto_tutorials/tests/images/sphx_glr_g_performance_CQE_002.png :alt: g performance CQE :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 169-176 **References:** .. [H2009] A. M. Heidt, Efficient Adaptive Step Size Method for the Simulation of Supercontinuum Generation in Optical Fibers, IEEE J. Lightwave Tech. 27 (2009) 3984, https://doi.org/10.1109/JLT.2009.2021538 .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 1.784 seconds) .. _sphx_glr_download_auto_tutorials_tests_g_performance_CQE.py: .. only :: html .. container:: sphx-glr-footer :class: sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: g_performance_CQE.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: g_performance_CQE.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_