SkillAgentSearch skills...

OptiFax

OptiFaχ - Nonlinear Optical Facsimile

Install / Use

/learn @SCRobarts/OptiFax
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Optifax_named_logo_simplified_narrowed

OptiFaχ - Optical Facsimilie Toolkit - Introduction

An object-oriented digital optical bench for MATLAB

https://github.com/McCrackenLab/OptiFax

clear; close all; devFlag = 0;

1. What is an object (in this context)?

figure
fig_handle = gcf
fig_handle = 
  Figure (1) with properties:

      Number: 1
        Name: ''
       Color: [0.9400 0.9400 0.9400]
    Position: [817 612 560 420]
       Units: 'pixels'

  Show all properties
fig_handle.Position(3:4) = [400 200];
ax_handle = axes(fig_handle);
pl_handle = plot(ax_handle,1:10,'r-o');

image_0.png

Unlike with other classes, variables assigned to an existing object handle still point to the original instance of the object:

new_handle = pl_handle;	
pl_handle == new_handle %#ok<EQEFF>
ans =    1

This ensures object permanence, just as we would expect from physical objects!

new_handle.Color = [0 1 0];	% Changing the property in the newly assigned variable

figure_0.png

pl_handle.Color		% Changes that property for all variables referencing the same object
ans = 1x3    
     0     1     0

Here we changed the value of a property in this instance of a line object.

The methods required to redraw the line on screen are also part of the line object's class.

We can use these principles to create digital versions of the elements in a real optical system!

2. Creating an optical source object with OptiFaχ

Let's use the 'Laser' object class to create an optical source for our system. The following code is taken from a script which is included in the toolbox: laser_setup_Taccor800

open("laser_setup_Taccor800.m")

Initialise physical parameters:

name = "Taccor800";	% Used as filename and also stored with the object as an identifier
lambdaC = 800e-9;	% Central wavelength, used when generating idealised pulses [m]
waistR = 5e-6;		% Beam waist radius, used for default area outside of waveguides [m]
fRep = 1e9;			% Repetition rate [Hz]
power = 2.1;		% Average power [W]
spectralString = "Sech";	% For now, model as idealised Sech^2 temporal pulse shape
dtau = 31.5e-15;	% FWHM pulse duration exiting the laser [s]
dlam = 23e-9;		% Spectral FWHM used with idealised pulse shapes [m]

Create the laser object:

laser = Laser(lambdaC,waistR,fRep,power,spectralString,dtau,dlam);

Object methods are called using the'object.method(args)'syntax, allowing the same function to be implemented differently for different objects.

Many OptiFaχ objects implement'.store'for saving in a format compatible with the rest of the toolkit.

laser.store(name,devFlag)

To test our new laser, we need to give it a coordinate system to exist in, and there's an object for that too! The 'SimWindow' object class.

load("simWin.mat")
nPoints = 2^15;		% Always a power of two for efficient Fourier transforms
tRange = 12e-12;	% Temporal window size [s]
simWin = SimWindow(lambdaC,nPoints,tRange);

The '.simulate(window)' command brings the laser into the space, allowing it to produce OpticalPulse objects.

laser.simulate(simWin);

A convenience plot function, contained in the OpticalPulse class, shows the result:

laser.Pulse.plot;

figure_1.png

If we have an experimentally retrieved spectrum, we can use that file to generate a more representative pulse. If the file is the result of a full pulse retrieval, then we can incorporate real phase data too. A live script is included to aid in formatting spectral data for use with OptiFaχ.

load Chromacity1040.mat
laser.simulate(simWin);
laser.Pulse.plot([1000 1060]);

image_1.png

Crucially, the laser object exists independently of the choice of window, allowing it to be used in any simulation.

This also means that the saved laser doesn't have to store any bulky arrays:

image_2.png

3. Adding components of an optical system

Most linear optical components can be implemented by direct use of the 'Optic' class.

The simplest example is a mirror with a theoretically uniform transmission across all wavelengths:

% First argument defines the regime as transmissive ("T") or reflective ("R")
% Second argument defines the transmissive properties of the first optical coating
% This can be a single value, wavelength dependent data from file, or
% Fresnel when set to "None" (input angle can be varied accordingly) 
mirror = Optic("R",0.05);
mirror.simulate(simWin);
mirror.plot;

figure_2.png

A more interesting example is implementation of a real focus lens:

% Third argument gives the material as a string and an external reference
% table finds the relevant sellmeier coefficients and transmission file
lens_surface_coating_str = 'NIR2CoatingDataLens.xlsx';
lens_thickness = 3.8E-3;
lens = Optic("T",lens_surface_coating_str,"N-BK7",lens_thickness);
lens.simulate(simWin);
lens.plot;

figure_3.png

Optics with geometric dispersion can be implemented by replacing the fixed material length argument with a function handle for generating path lengths as a function of refractive index. For these Pellin-Broca prisms, we also add a non-zero angle of incidence.

theta = 57;	% angle of incidence in degrees
prismPB = Optic("T",'None',"N-BK7",@prismfn_PB,57);
prismPB.simulate(simWin);
prismPB.plot;

figure_4.png

A fused silica, low-pass filter:

FS_LPF = Optic("T",'950_longpass_dichroic_transmission.csv',"FS",1.2e-3);

An uncoated sapphire window used for output coupling in the Fresnel regime:

SapphireOC = Optic("T","None","Sapphire",2e-3,5);

3.2 Waveguides / Nonlinear optical components

Optic class inheritance:

image_3.png

classdef Waveguide < Optic
	%WAVEGUIDE Abstract optical waveguide class
	%   Provides an interface to extend the Optic class to nonlinear media, where individual waveguide types
	%   are implemented in their own classes, extending this one.
	%
	%	Sebastian C. Robarts 2024 - sebrobarts@gmail.com
	properties
		Chi2	% Second order optical nonlinearity [V/m]
		Chi3	% Todo: Implement conversion of gamma [W/m] to Chi3 [V/m]
		RamanFraction
		ResponseTimes	% [Inverse average phonon frequency, Characteristic phonon dampening time] [s]
		ModeFieldDiameter	% Waveguide confinement [m]
	end
	properties (Abstract)
		StepSize	% Default smallest step implemented separately in each subclass [m]
	end
	properties (Dependent)
		RamanResponse	% Calculated Raman response function
	end

Periodically poled lithium niobate (PPLN) implementation:

%% General Optic arguments
T_str = 'ppln_ar_combined.csv';
theta_in = 0;
temp_C = 70;	% Crystal temperature in Celsius - can be adjusted later for different systems
L = 1e-3;
opticArgs = {T_str,"PPLN",L,theta_in,T_str,temp_C};
name = "PPLN_Fanout_1mm";

%% Crystal specific arguments
grating_m = 21.3e-06;	% Grating period [m]
uncertainty_m = 0.2e-6;	% Small perturbation in domain wall locations [m]
dutyOff = 0.1;	% Systematic offset of duty cycle within each period %
xtalArgs = {grating_m, uncertainty_m, dutyOff};

PPLN = NonlinearCrystal(xtalArgs{:},opticArgs{:});
PPLN.store(name,devFlag); PPLN.simulate(simWin); 
PPLN.plot; PPLN.xtalplot;

figure_5.png

figure_6.png

Chirped domain engineering:

Passing a function handle, f(z), as the grating period allows complete control over crystal polarisation.

%% General Optic arguments
T_str = 'AR';	% Idealised 100% anti-reflection coating across all wavelengths
theta_in = 0;
temp_C = 20;
L = 5e-3;
opticArgs = {T_str,"PPLN",L,theta_in,T_str,temp_C};
name = "ChirpedWaveguideLN";

%% Crystal specific arguments
% Chirped grating function arguments:
P1 = 6.3*1e-6;	% Starting grating period [m]
P2 = 2.2*1e-6;	% Finishing grating period [m]
a = 0.48;		% Exponent for rate of chirp
uncertainty_m = 0.1e-6;	% Small perturbation in domain wall locations [m]
dutyOff = 0;	% Systematic offset of duty cycle within each period (not currently implemented for chirped)
grating_m = @(z) chirpedgrating(z,P1,P2,a,uncertainty_m);
xtalArgs = {grating_m, uncertainty_m, dutyOff};
mfd = 5e-6;	% Mode Field Diameter [m]

CPLN = NonlinearCrystal(xtalArgs{:},opticArgs{:});
CPLN.ModeFieldDiameter = mfd;
CPLN.store(name,devFlag); CPLN.simulate(simWin);
CPLN.plot; CPLN.xtalplot;

figure_7.png

figure_8.png

4. Combining optical components with 'Cavity' objects

Cavity class dependency:

image_4.png

Optics are composed of a combination of optical surfaces and bulk dielectric. Cavities are, in turn, composed of a combination of optics.

Pre-cavity optics:

We can define additional optics to account for pump pulse dispersion prior to the cavity itself. In this example we streamline the process by only considering the total bulk material that the pump passes throug

View on GitHub
GitHub Stars4
CategoryDevelopment
Updated9mo ago
Forks1

Languages

MATLAB

Security Score

82/100

Audited on Jul 9, 2025

No findings