The orthogonal rational approximation (ORA) algorithm allows users to fit a rational function to known frequency-dependent data from simulations or measurements. This algorithm is implemented in MATLAB®.

This function works with Touchstone® .SnP files (ex. .s2p, s10p, etc.).

To use these files:

  1. Copy and paste the numfit, denfit, and ORA files and save them in the same folder as numfit.m, denfit.m, and ORA.m
  2. Call the ORA function from a MATLAB® .m file with the Touchstone® file name as an input. For example: ora(“myFileHere.s2p”, [1 1; 1 2; 2 1; 2 2], 30, 30, 20)
  3. Run the MATLAB file.

MATLAB is a registered trademark of The MathWorks, Inc. (http://www.mathworks.com)

Please cite:

Ma, A, Engin, AE. Orthogonal rational approximation of transfer functions for high-frequency circuits. Int J Circ Theor Appl. 2022; 1– 13. doi:10.1002/cta.3488

Creative Commons License:

This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.

Download Files:

ora.zip

mainora
clear all;
close all;
clc;


% Orthogonal Rational Approximation (ORA)
% San Diego State University
% Revision Date: 09-09-2024

% Ma, A, Engin, AE. Orthogonal rational approximation of transfer functions for high-frequency circuits.
% Int J Circ Theor Appl. 2022; 1- 13. doi:10.1002/cta.3488



file = 'st4_01.s2p'; %Touchstone .snp data file
param_indices = [1 1; 1 2]; %ex: S11, S12 = [1 1; 1 2]

% ----------------------------------------------- %
% ----------------------------------------------- %
% ----------------------------------------------- %

touch = sparameters(file);
params = touch.Parameters;
frequency = touch.Frequencies;
p=size(touch.Parameters,1);

params_extracted = [];
for i=1:length(param_indices(:,1))
    params_extracted = [params_extracted squeeze(params(param_indices(i,1),param_indices(i,2),:))];
end


w = frequency .* 2 .* pi; %rad/s
x = 1j .* w;

minPoles = 30;
maxPoles = 50;
numberOfPoles = minPoles:1:maxPoles;
rms_error_ORA_iter = zeros(length(numberOfPoles), 1);
error_ORA_iter = zeros(length(numberOfPoles), length(param_indices));


for i=1:length(numberOfPoles)
    [poles_ora, fit_ora, myss_ora, err_ora] = ora(touch, param_indices, numberOfPoles(i), numberOfPoles(i), 20);
    error_ORA_iter = abs(fit_ora-params_extracted);
    rms_error_ORA_iter(i, 1) = err_ora;
end


% ------------------ Figures ------------------- %


figure
for m=1:length(param_indices(:,1))
   semilogy(frequency, abs(params_extracted(:, m)), 'LineWidth', 1, 'Color', 'b');
   if m == 1
       hold on;
   end
   semilogy(frequency, abs(fit_ora(:, m)), '--', 'LineWidth', 1, 'Color', 'r');
   semilogy(frequency,error_ORA_iter(:,m), '--', 'Color', '#808080', 'LineWidth', 1);
end
hold off;
xlabel('Frequency [Hz]')
ylabel('Magnitude')
legend("Data", "ORA", "Deviation");
title('Data')
axes1 = gca;
set(axes1,'FontSize',14);



figure
semilogy(numberOfPoles, rms_error_ORA_iter);
xlabel('Poles')
ylabel('rms error')
title('Error')
legend('ORA')
axes2 = gca;
set(axes2,'FontSize',14);

mainora