----------------------------------------------- Plotting, Beam Coupling, Propagation ----------------------------------------------- ^^^^^^^^^^^^^^ Plotting modes ^^^^^^^^^^^^^^ Plotting all the modes is useful both for visualisation, as well as performing numerical integration required for coupling in beams or determining the power in the core. Plotting is easiest to perform using the ``Solution`` class, although low-level functions can also be used directly. Assuming we already have a list of modes stored in ``modes``, obtained from ``lpmodes.find_modes()``, we then need to define the size of the square grid, in pixels, and also in physical units:: grid_size = 150 # pixels max_plot_radius = 15 # microns The ``max_plot_radius`` is half of the width or height of the plot. For a core radius of 10 microns, a max_plot_radius of 15 microns will ensure all the core plus a reasonable extent of the cladding is plotted. We then create an instance of the ``Solution`` class. Creating this instance plots all the modes, and so this line may take several seconds to execute, depending on the number of modes and grid size chosen:: solution = lpmodes.Solution(modes, grid_size, max_plot_radius) If we do not specifiy the max_plot_radius, it will automatically chosen to be 1.5 times the core_radius that the modes in ``modes`` were calculated for. The mode plots are now available as 3D numpy arrays. For example, plots of the amplitude of the cosine orientations are stored in ``solution.mode_cos``. The 3D array is organised as (mode number, x co-ord, y co-ord). To extract the 3rd mode plot, for example, you can use:: mode_3 = solution.mode_cos[2] which will return a 2D numpy array containing a plot of the 3rd mode. The sine orientations are stored in ``mode_sin``, and intensity plots are stored in ``mode_sin_intensity`` and ``mode_cos_intensity``. The mode details are now stored in ``solution.modes``. If the index of a mode with specific l and m values is required, use the ``find_mode_idx()`` function, e.g. to obtain the plot of the l = 1, m = 2 mode:: mode_12 = solution.mode_cos[lpmodes.find_mode_idx(solution.modes, 1, 2)] ^^^^^^^^^^^^^^^^^^^ Coupling Into Modes ^^^^^^^^^^^^^^^^^^^ To simulate couling a beam into the simulated fibre, we require a representation of the electric field as 2D complex numpy array. The array must have the same dimension and physical pixel size as the mode plots were created for. Functions are provided to generate plane waves (with a tilt) or Gaussian shaped beams, which are two common use cases. Assume we have created a ``Solution`` with a ``grid_size`` of 100 and a ``max_plot_radius`` of 15 microns. We can generated a Gaussian beam with a sigma of 5 microns, centred on the fibre, using:: field_size = max_plot_radius * 2 sigma = 5 position = (0,0) g_field = lpmodes.gaussian_field(grid_size, field_size, position, sigma) We have set ``field_size`` to twice ``max_plot_radius`` because the mode plots run from ``-max_plot_radius`` to ``+max_plot_radius``. To produce an offset beam, set ``position`` to a tuple of (x pos, y pos). The position is in microns relative to the centre of the field, and can can be positive or negative. The field can now be coupled in to the fibre using the ``couple_field`` method of the ``Solution`` class. Assuming we have created a solution stored in ``solution``:: solution.couple_field(g_field) The complex amplitude in each mode is now stored in ``solution.cos_amp`` and ``solution.sin_amp``, for the sine and cosine orientations of the modes. Each of these is a 1D complex numpy array. The amplitudes can be obtained using ``np.abs(solution.sin_amp)``. The power in each mode (combined sine and cosine orientations) is stored in ``solution.mode_power``. The total power coupled is stored in ``solution.power_coupled``. If the input field is normalised to have a total power of 1, as the fields generated by ``gaussian_field()`` and ``tilted_field()`` are, this will be the coupling efficiency. ^^^^^^^^^^^^^^^^^^^^^^^^^^ Plotting the Coupled Field ^^^^^^^^^^^^^^^^^^^^^^^^^^ A plot of the coupled field, as a 2D complex numpy array, is obtained using:: field = solution.get_in_field() or the coupled intensity distribution using:: intensity = solution.get_in_intensity() The grid size and pixel size are as defined when the modes and field to couple were plotted. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Propagating the Coupled Field ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The field coupled into the fibre is propagated along a length of the fibre by:: distance = 2000 # microns solution.propagate(distance) The complex amplitudes for each mode are then stored in the 1D arrays in ``solution.prop_cos_amp`` and ``solution.prop_sin_amp``. The amplitudes do not change, only the phases. The total field after propgation is stored in ``solution.prop_field`` as a 2D complex numpy array, and the intensity distribution is in ``solution.prop_intensity``, as a 2D real numpy array. To allow random rotations of the modes during propagation, pass the keyword argument ``rotations = True``.