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.