Obtaining approximate derivatives with variable x spacing in MATLAB?

时间:2015-07-29 00:25:06

标签: arrays matlab

I have two arrays: IF NOT "%BatteryStatus%"=="2" and x. In practice, y is dependent on y, but both arrays are measured values. I would like to obtain the derivative of x with respect to y. If x were uniformly spaced (i.e. x), I could do something with x=[1 2 3 4 5] like this:

diff

However, x is not uniformly spaced (i.e. h = 0.001; x = -pi:h:pi; f = sin(X); y = diff(f)/h; ). How can I obtain the partial derivative of this data set?

1 个答案:

答案 0 :(得分:1)

这样做的好方法是gradient

dydx = gradient(y, x);

我喜欢它,因为它返回一个与xy长度相同的向量。但缺点是,它的第一个订单是准确的。这有时可能是一个问题,修复可能是自己编写,

x = unique([linspace(0, 2*pi, 50), logspace(0, log10(2*pi), 50)]);
y = cos(x) ;
subplot(2,1,1) ;
plot(x, Gradient(y, x), x, gradient(y,x), x, -sin(x));
legend('2^{nd} order', '1^{st} order', 'exact') ;
subplot(2,1,2) ;
plot(x, Gradient(y, x) + sin(x), x, gradient(y,x) + sin(x));
legend('2^{nd} order - exact', '1^{st} order - exact')

http://phpmyadmin.app:8000

Gradient

function dydx = Gradient(y,x)
    y = y(:);

    p = x(3:end) - x(2:end-1);
    p = p(:);

    m = x(2:end-1) - x(1:end-2);
    m = m(:);

    p1 = x(2) - x(1);
    p2 = x(3) - x(1);

    m1 = x(end) - x(end-1);
    m2 = x(end) - x(end-2);

    dydx = reshape([ ((-p1^2 + p2^2)*y(1) - p2^2*y(2) + p1^2*y(3))/(p1*(p1 - p2)*p2); 
                    ((-m.^2 + p.^2).*y(2:end-1) - p.^2.*y(1:end-2) + m.^2.*y(3:end))./(m.*p.*(m + p));
                    ((m1^2 - m2^2)*y(end) + m2^2*y(end-1) - m1^2*y(end-2))/(m1^2*m2 - m1*m2^2) ...
                    ], size(x));
end

编辑:

改进了多维数组和恒定间距支持

function dydx = Gradient(y,x)
    if length(y) < 3
        dydx = gradient(y,x);
        return
    end

    [~, n] = max(size(y));
    N = ndims(y);

    i = repmat({':'},1,N-1);

    y = permute(y, [n, 1:n-1, n+1:N]);

    if isscalar(x)
        %"x" is actually a spacing value
        p = x;
        m = x;
        p1 = x;
        p2 = x;
        m1 = x;
        m2 = x;
    else
        if isvector(x)
            x = repmat(x(:), size(y(1, i{:})));
        else
            x = permute(x, [n, 1:n-1, n+1:N]);
        end

        if all(size(x) ~= size(y))
            error('Sizes of arrays must be the same.')
        end

        p = x(3:end, i{:}) - x(2:end-1, i{:});

        m = x(2:end-1, i{:}) - x(1:end-2, i{:});

        p1 = x(2, i{:}) - x(1, i{:});
        p2 = x(3, i{:}) - x(1, i{:});

        m1 = x(end, i{:}) - x(end-1, i{:});
        m2 = x(end, i{:}) - x(end-2, i{:});
    end

    dydx = ipermute([ ((-p1.^2 + p2.^2).*y(1,i{:}) - p2.^2.*y(2,i{:}) + p1.^2.*y(3,i{:}))./(p1.*(p1 - p2).*p2); 
                    ((-m.^2 + p.^2).*y(2:end-1,i{:}) - p.^2.*y(1:end-2,i{:}) + m.^2.*y(3:end,i{:}))./(m.*p.*(m + p));
                    ((m1.^2 - m2.^2).*y(end,i{:}) + m2.^2.*y(end-1,i{:}) - m1.^2.*y(end-2,i{:}))./(m1.^2.*m2 - m1.*m2.^2) ...
                    ], [n, 1:n-1, n+1:N]);
end