Matlab与Numpy矩阵逆之间的差异

时间:2016-09-11 08:39:24

标签: python matlab numpy matrix

我能够找到一些错误报告,但没有找到我所看到的结论性答案或解决方案。我有一个工作的Matlab脚本,它构建一个矩阵并从其逆中提取值。它正在发挥作用,情节与理论一致。

我开始将程序移到Python上尝试其他一些库,但它没有按预期工作。我已经在Matlab和Python中记录了为矩阵找到的所有值,他们同意这一点。但是,它似乎打破了逆的计算。 numpy中的常规,伪或.I反转都没有给出正确的答案。由于在此之前使用的每个值在两个脚本中都是相同的,我认为这必须归结为numpy的linalg.inv()问题。我有一些旧的文件可以找到反转,但不能想象我掀起的任何恐怖都将超越内部实现。有没有人遇到类似的问题,并知道去哪儿?谢谢!

编辑:以下代码。我找到了带通滤波器的反射/透射,其最终目标是插入具有交叉耦合的非无限传输零点并优化它引入的不匹配。

我标记了所有故障的位置。

1)Python代码:

def s_from_m(n, ripple, w0, bw, bw_is_hz, tz_freq):

    # Get cheby low-pass prototype values for resistance matrix.
    g_vals = cheby_g_vals(n, ripple)
    m = np.floor(n/2)

    # Use center frequency and bandwidth to find passband edges
    if bw_is_hz:
        w1 = w0 - bw/2
        w2 = w0 + bw/2
        # Modified center frequency.
        w0 = w1 + w2 - np.sqrt( (w2-w1)**2 + w1*w2 )
    else:
        # Solve for needed w1/w2 using quadratic formula.
        w1 = (-bw*w0 + np.sqrt( (bw*w0)**2 + 4*(w0**2) )) / 2
        w2 = (w0**2)/w1

    # Fractional Bandwidth for cross-coupling calculations.
    fbw = (w2 - w1) / w0

    # Source and load external quality coefficients
    q_source = (g_vals[0]*g_vals[1]) / fbw
    q_load = (g_vals[-1]*g_vals[-2]) / fbw

    # Build resistance, frequency, and coupling matrices.
    R = np.zeros((n,n), dtype=np.complex)
    R[0,0] = 1/q_source
    R[n-1,n-1] = 1/q_load
    S = np.eye(n)
    M = np.zeros((n,n), dtype=np.complex)

    # Calculate direct-coupling coefficients
    for i in range(1, n):
        M[i-1, i] = fbw/np.sqrt(g_vals[i]*g_vals[i+1])
        M[i, i-1] = M[i-1, i]

    # Cross-coupling coeff for given ratio
    m1 = tz_freq/w0 
    M[m-1,m+1] = -m1
    M[m+1,m-1] = -m1

    # Range 8 bandwidths wide in total for visualization.
    w_range = np.arange(w1-4*bw, w2+4*bw, (w2-w1)/10000)
    x = len(w_range)

    # Stores S11 and S21 with current coeffs.
    s11 = np.zeros(x)
    s21 = np.zeros(x)

    A = np.matrix(R + S - 1j*M)

    # Populate s11/s21 based on admittance/impedance matrix
    for j in range(x):
        # A = np.matrix(R + 1j*(w_range[j]/w0 - w0/w_range[j])*S - 1j*M)
        # Only modify the values being changed.
        np.fill_diagonal(A, 1j*(w_range[j]/w0 - w0/w_range[j]))
        A[0,0] += 1/q_source
        A[-1,-1] += 1/q_load
        # EVERYTHING UNTIL THIS POINT AGREES WITH MATLAB
        inv_a = A.I
        s11[j] = 1 - (2/q_load)*inv_a[0,0]
        s21[j] = (2/np.sqrt(q_source*q_load))*inv_a[n-1,0]

    # Convert to dB
    s11 = 20*np.log10(abs(s11))
    s21 = 20*np.log10(abs(s21))

Python日志:

Chebyshev g vals: [ 1.      1.7373  1.2582  2.6383  1.3443 2.6383  1.2582  1.7373  1.    ]

Overall coupling matrix:

[ 0.      0.0271  0.      0.      0.      0.      0.    ] 
[ 0.0271  0.      0.022   0.      0.      0.      0.    ]
[ 0.      0.022   0.      0.0213  0.      0.      0.    ]
[ 0.      0.      0.0213  0.      0.0213  0.      0.    ]
[ 0.      0.      0.      0.0213  0.      0.022   0.    ]
[ 0.      0.      0.      0.      0.022   0.      0.0271] 
[ 0.      0.      0.      0.      0.      0.0271  0.    ]

2)Matlab代码

function [A, M, S21, S11, w] = SfromM(nIn, ripLevel, w0In, BW, bwInHz, tzFreq)
 %% Function to generate S parameters for a bandpass filter.
 % Use a Chebyshev response for prototype values, then create the coupling coefficients. 
 % Overall resistance matrix built up of real resistances, frequency
 % components, and coupling coefficients. This matrix is then inverted, and the appropriate 
 % formulas used to create S11 and S21. 
 % nIn is filter order. 
 % ripLevel is max ripple allowed in Passband.
 % w0In is input center frequency. 
 % BW is bandwidth in Hz or percent
 % bwInHz is flag value to handle both Hz and percent bandwidth inputs.
 % tzFreq is frequency for cross-coupling zero (Hz)

% Chebyshev and filter parameters
g = gVals(nIn, ripLevel);
n = nIn;
m = floor(n/2);

% Center frequency and bandwidth used to find edges of passband.
if bwInHz % BW given in Hz (w2-w1)
    w1 = w0In - BW/2;
    w2 = w0In + BW/2;
    w0 = w1 + w2 - sqrt( (w2-w1)^2 + w1*w2 );
    FBW = (w2-w1)/w0;
else % BW given in percent (w2-w1)/w0
    w0 = w0In;
    w1 = (-(BW*w0In) + sqrt( (BW*w0In)^2 + 4*(w0In^2) )) / 2;
    w2 = w0In^2/w1;
    FBW = (w2 - w1)/w0;
end


% Source and load external quality coefficients.
qSource = (g(1)*g(2))/FBW;
qLoad = (g(n+1)*g(n+2))/FBW;

% Building resistance, frequency, and coupling matrices.
R = zeros(n);
R(1,1) = 1/qSource;
R(n,n) = 1/qLoad;
S = eye(n);
M = zeros(n);

% Calculating direct-coupling coefficients
% display('Coefficients founds as FBW / sqrt(g(i)*g(i+1))');
for i = 2:n
    M(i-1, i) = FBW/sqrt(g(i)*g(i+1));
    M(i, i-1) = M(i-1, i); % Filling lower diagonal with same coupling
end

% Cross coupling coefficients from given ratio
% m1 = (tzFreq)/w0;
% M(m,m+2) = -m1;
% M(m+2,m) = -m1;

% Different frequency values for plotting:
w = 4*10^9:10^6:6*10^9; % for 5 Ghz in Mhz steps.
x = length(w);

% % For storing regular values.
S21 = zeros(1,x);
S11 = zeros(1,x);


% Generate S21 and S11 response from admittance/impendace matrix.
for s = 1:x
    % Definition of overall impedance matrix.
    A = (R + 1i*(w(s)/w0 - w0/w(s))*S - 1i*M);
    # Works fine.
    inva = inv(A);
    % Conversion to S parameters with external quality coefficients.
    S21(s) = (2/sqrt(qSource*qLoad))*inva(n,1);
    S11(s) = 1 - (2/qLoad)*inva(1,1);
end

% Convert to dB again
S11 = 20*log10(abs(S11));
S21 = 20*log10(abs(S21));

Matlab日志:

g values for n = 7, and rip level = 0.5:

g = 

    1.0000   1.7373   1.2582   2.6383   1.3443   2.6383   1.2582   1.7373   1.0000

         0   0.0271        0        0        0        0        0
    0.0271        0   0.0220        0        0        0        0
         0   0.0220        0   0.0213        0        0        0
         0        0   0.0213        0   0.0213        0        0
         0        0        0   0.0213        0   0.0220        0
         0        0        0        0   0.0220        0   0.0271
         0        0        0        0        0   0.0271        0

编辑2:仍在研究这个例子。 虽然我对它进行了测试,但看起来似乎是对s11 / s21和/或20 * log10()操作的计算。对于Python和Matlab,矩阵A和inv_a是相同的。但是,用公式计算s21和s11,然后取20 * log10()幂,答案会发生剧烈变化。任何人都看到我忽视的那个区域的愚蠢错误?谢谢!

0 个答案:

没有答案