%% Approximating Perturbed Systems
%% The Circuit and Test Frequency
% A ladder circuit is used in this example showing how the changes in
% branch currents and node voltages can be approximated.
%
% <<r2rLadder 001.JPG>>
%
%%
% The circuit and tableau objects are created and the test frequency
% defined below.
ckt=circuit('test circuits\r2rLadder.cir');
T=tableau(ckt);
f=1000;
%% Nominal Values of Branch Currents and Node Voltages
% Nominal branch currents and node voltages (IVn) can be calculated from
% the tableau matrix. The nominal values will be used to compare to the
% perturbed values, first by exact calculations and second by an
% approximate method.
Tmat_n=tableau_matrix(T,f);
IVn=Tmat_n\T.S;
disp(full(IVn))
%% Perturbed Values of Branch Currents and Node Voltages
% The exact solution for the perturbed values is obtained by changing the
% randomly selected values in varyKi and varyKv. For this example, the
% values are changed to the maximum tolerance value of the resistors. This
% process is begun by obtaining a random value for varyKi and varyKv.
[varyKi,varyKv]=monteCarlo(T);
%%
% Having obtained a random value for varyKi and varyKv, tolerance and
% component values are obtained via the deltaComp_vector. The deltaComp
% variable is a structure containing the negative and positive fractional
% limits and the value of the components.
deltaComp=deltaComp_vector(T);
%%
% The random selection is removed and the maximum tolerance value
% substituted in varyKi and varyKv. These substitutions are completed
% below.
[row,~]=find(T.deltaKi);
varyKi(logical(T.deltaKi))=1+deltaComp.pTol(row);
[row,~]=find(T.deltaKv);
varyKv(logical(T.deltaKv))=1+deltaComp.pTol(row);
%%
% The perturbed matrix is generated and the branch currents and node
% voltages computed. This operation finds the exact solution for perturbed
% branch currents and node voltages.
Tmat=tableau_matrix(T,f,varyKi,varyKv);
IV=Tmat\T.S;
disp(full(IV))
%% Exact Value of deltaIV
% The exact value of deltaIV is obtained by subtracting the nonimal value
% from the perturbed value.
deltaIVexact=IV-IVn;
disp(full(deltaIVexact))
%%
% At first glance, the value of deltaIVexact may not appear correct as the
% changes in branch currents are zero and only the node voltages change.
% The first row in the deltaIVexact vector is zero because the value of the
% constant current source is not changed. The values of the second, third,
% and fourth rows are also zero, indicating that branch currents have not
% changed. This appears to be anomalous. In the nominal condition R1 = R2 +
% R3. Since the resistor tolerances are all 5%, the relationship R1 = R2 +
% R3 still holds at maximum tolerance. When the current is constant, the
% relative current split between R1 and R2 + R3 is the same. The change in
% current is therefore zero in all three resistors. The result that appears
% incorrect is actually correct.
%% Approximating deltaIV From a Recursion Relationship
% A circuit with its components at their nominal values can be represented
% in tableau format as
%
% Tn*IVn = S
%
% where Tn is the tableau matrix, IVn is the vector of branch currents and
% node voltages, and S is the vector of independent sources. The variation
% of branch currents and node voltages can be explored by letting the
% components vary from their nominal value. (Here we will assume that the
% independent sources remain constant since variation would simply be a
% linear response to the stimulus.) In this situation, the perturbed
% circuit represented in tableau format is
%
% (Tn+deltaT)*(IVn+deltaIV)=S
%
% When the first equation is subtracted from the second equation, the
% result is
%
% (Tn+deltaT)*(IVn+deltaIV)-Tn*IVn=0
%
% This equation can be simplified to
%
% Tn*deltaIV=-deltaT*(IVn+deltaIV)
%
% Since the tableau matrix has an inverse, then
%
% deltaIV=-inv(Tn)*deltaT*(IVn+deltaIV)
%
% The tableau system of equations has a property not shared by all methods
% of formulating circuit equations; a component value appears in one and
% only one row of the tableau format at a single location within the row.
% Each location in a row of deltaT has a number representing the
% change-in-value for that component. For each row, the change in component
% value can be extracted from deltaT and replaced by the appropriate value
% of (IVn+delatIV) because there is only one matrix element in a row. The
% equation becomes
%
% deltaIV=-inv(Tn)*deltaT_IV*deltaComp
%
% The variable deltaT_IV is the matrix where the change in component value
% has been interchanged with (IVn+delatIV). The variable deltaComp is the
% vector of changes in component values.
%
% In this form, the matrix
%
% -inv(Tn)*deltaT_IV
%
% directly maps the change-in-component-value space to the
% change-in-current-and-voltage space.
%
% Note that deltaT_IV forms a recursion relation that can be iterated to
% find deltaIV. To begin the iteration, the values which do not change are
% pre-calculated. As part of the assumptions, deltaIV is assumed to be
% zero initially.
invTmat_n=inv(Tmat_n);
deltaIV=0;
deltaComp=deltaComp_vector(T);
deltaPosTol=deltaComp.pTol.*deltaComp.compVal;
%% Performing an Iteration
% To begin the iteration IV is just IVn, since deltaIV was assumed to be
% zero initially.
IV=IVn+deltaIV;
deltaT_IV=deltaTableau_matrix(T,f,IV);
deltaIV=-invTmat_n*deltaT_IV*deltaPosTol;
%%
% After one iteration, the approximate and exact values of deltaIV are:
disp([full(deltaIV) full(deltaIVexact)])
%%
% The difference between the approximate and the exact values are:
full(deltaIV-deltaIVexact)
%%
% Typically, the recursion relation converges quite quickly as can be seen
% above.
%% Mapping the Component Space to the Node Voltage Space
% To begin the mapping, a logical variable is defined whose columns are all
% logical combinations of three things.
x=logical([1 1 1 1 0 0 0 0;1 1 0 0 1 1 0 0 ;1 0 1 0 1 0 1 0]);
disp(x)
%%
% The logical variable "x" is now used to create all possible combinations
% of tolerance extremes.
index=find(deltaComp.pTol);
tolExtremes=x.*repmat(deltaComp.pTol(index),1,8)-~x.*repmat(deltaComp.nTol(index),1,8);
disp(tolExtremes)
%%
% Having created the extremes in tolerance (fractional) values, the
% extremes in change-in-component values is computed.
compExtremeValues=repmat(deltaComp.compVal,1,8);
compExtremeValues(index,:)=tolExtremes.*compExtremeValues(index,:);
disp(compExtremeValues)
%%
% The values of deltaIV for each extreme in component values is created.
% The recursion relation is iterated twice and the difference between the
% current iteration and the last iteration tested to determine if the
% difference is less than 1e-15. When the test shows that the difference is
% less than 1e-15, iteration is terminated and the value deltaIV copied to
% the matrix of extreme points.
[row,col]=size(compExtremeValues);
extremePoints=zeros(row,col);
for I=1:length(x)
% Initialize values
deltaIV=zeros(row,1);
deltaIVlist=zeros(row,4); % Make room for up to four iterations
% First iteration
count=1;
IV=IVn+deltaIV;
deltaT_IV=deltaTableau_matrix(T,f,IV);
deltaIV=-invTmat_n*deltaT_IV*compExtremeValues(:,I);
deltaIVlist(:,count)=deltaIV;
% Second iteration
count=count+1;
IV=IVn+deltaIV;
deltaT_IV=deltaTableau_matrix(T,f,IV);
deltaIV=-invTmat_n*deltaT_IV*compExtremeValues(:,I);
deltaIVlist(:,count)=deltaIV;
% Subsequent iterations (must have two iterations to compare first)
while all((deltaIVlist(:,count)-deltaIVlist(:,count-1)>1e-15))
count=count+1;
IV=IVn+deltaIV;
deltaT_IV=deltaTableau_matrix(T,f,IV);
deltaIV=-invTmat_n*deltaT_IV*compExtremeValues(:,I);
deltaIVlist(:,count)=deltaIV;
end
extremePoints(:,I)=deltaIVlist(:,count);
end
%% Plotting the Node Voltage Space
% Since the stimulus is a constant current, the node voltages are a more
% more interesting space. The space formed by the change in node voltages
% is:
voltageExtremePoints=extremePoints(T.nodeVoltIndx,:)';
pointOrder=convhull(voltageExtremePoints(:,1),voltageExtremePoints(:,2));
%%
% The node voltage space, a two dimensional space, is plotted. The number
% of edges in the space matches the number of faces in the component space.
fill(voltageExtremePoints(pointOrder,1),voltageExtremePoints(pointOrder,2),'g')
xlabel('Change in Voltage at N1');
ylabel('Change in Voltage at N2');
title('Node Voltage Space');
%% Plotting the Component Value Space
% The component space is plotted next. It is a three dimensional space
% since there are three components. The component space is a rectangular
% solid.
xyz=compExtremeValues(index,:)';
pointOrder=convhulln(xyz);
trisurf(pointOrder,xyz(:,1),xyz(:,2),xyz(:,3),'FaceColor','green')
xlabel('Change in R1 (Ohms)')
ylabel('Change in R2 (Ohms)')
zlabel('Change in R3 (Ohms)')
title('Component Value Space')
%% Summary and Conclusions
% The recursion relation provides a means of mapping the component space
% into a branch current and node voltage space. This example demonstrates
% that the recursion relation converges quite quickly. (None of the extreme
% points took more that two iterations to converge to an acceptably small
% number.)
%%
% Each point within the green area of the component space represents an
% instance of a circuit where all of the components are within the stated
% tolerance. Each of the points in the green area of the node voltage space
% also represents an instance of a circuit where all of the components are
% within tolerance. In a practical application, verifying that all the
% components are in tolerance will usually require removing them from the
% circuit and measuring each one. Removing components is usually not
% practical and replacing them afterward opens up the possibility of a
% loading error or part damage. In contrast, measuring the node voltages
% and determining if they fall within the node voltage space is much less
% expensive and without the downside risk of a loading error or part damage.