Compute divergence of vector field using python

前端 未结 10 2613
甜味超标
甜味超标 2020-12-03 21:58

Is there a function that could be used for calculation of the divergence of the vectorial field? (in matlab) I would expect it exists in numpy/scipy but I can not find it us

相关标签:
10条回答
  • 2020-12-03 22:11

    What Daniel had modified is the right answer, let me explain self defined func divergence further in more detail :

    Function np.gradient() defined as : np.gradient( f) = df/dx, df/dy, df/dz +...

    but we need define func divergence as : divergence ( f) = dfx/dx + dfy/dy + dfz/dz +... = np.gradient( fx) + np.gradient(fy) + np.gradient(fz) + ...

    Let's test, compare with example of divergence in matlab

    import numpy as np
    import matplotlib.pyplot as plt
    
    NY = 50
    ymin = -2.
    ymax = 2.
    dy = (ymax -ymin )/(NY-1.)
    
    NX = NY
    xmin = -2.
    xmax = 2.
    dx = (xmax -xmin)/(NX-1.)
    
    def divergence(f):
        num_dims = len(f)
        return np.ufunc.reduce(np.add, [np.gradient(f[i], axis=i) for i in range(num_dims)])
    
    y = np.array([ ymin + float(i)*dy for i in range(NY)])
    x = np.array([ xmin + float(i)*dx for i in range(NX)])
    
    x, y = np.meshgrid( x, y, indexing = 'ij', sparse = False)
    
    Fx  = np.cos(x + 2*y)
    Fy  = np.sin(x - 2*y)
    
    F = [Fx, Fy]
    g = divergence(F)
    
    plt.pcolormesh(x, y, g)
    plt.colorbar()
    plt.savefig( 'Div' + str(NY) +'.png', format = 'png')
    plt.show()
    

    0 讨论(0)
  • 2020-12-03 22:12

    Based on @paul_chen answer, and with some additions for Matplotlib 3.3.0 (a shading param needs to be passed, and default colormap I guess has changed)

    import numpy as np
    import matplotlib.pyplot as plt
    
    NY = 20; ymin = -2.; ymax = 2.
    dy = (ymax -ymin )/(NY-1.)
    NX = NY
    xmin = -2.; xmax = 2.
    dx = (xmax -xmin)/(NX-1.)
    
    def divergence(f):
        num_dims = len(f)
        return np.ufunc.reduce(np.add, [np.gradient(f[i], axis=i) for i in range(num_dims)])
    
    y = np.array([ ymin + float(i)*dy for i in range(NY)])
    x = np.array([ xmin + float(i)*dx for i in range(NX)])
    
    x, y = np.meshgrid( x, y, indexing = 'ij', sparse = False)
    
    Fx  = np.cos(x + 2*y)
    Fy  = np.sin(x - 2*y)
    
    
    F = [Fx, Fy]
    g = divergence(F)
    
    plt.pcolormesh(x, y, g, shading='nearest', cmap=plt.cm.get_cmap('coolwarm'))
    plt.colorbar()
    plt.quiver(x,y,Fx,Fy)
    plt.savefig( 'Div.png', format = 'png')
    

    0 讨论(0)
  • 2020-12-03 22:15

    Just a hint for everybody reading that:

    the functions above do not compute the divergence of a vector field. they sum the derivatives of a scalar field A:

    result = dA/dx + dA/dy

    in contrast to a vector field (with three dimensional example):

    result = sum dAi/dxi = dAx/dx + dAy/dy + dAz/dz

    Vote down for all! It is mathematically simply wrong.

    Cheers!

    0 讨论(0)
  • 2020-12-03 22:16

    Based on Juh_'s answer, but modified for the correct divergence of a vector field formula

    def divergence(f):
        """
        Computes the divergence of the vector field f, corresponding to dFx/dx + dFy/dy + ...
        :param f: List of ndarrays, where every item of the list is one dimension of the vector field
        :return: Single ndarray of the same shape as each of the items in f, which corresponds to a scalar field
        """
        num_dims = len(f)
        return np.ufunc.reduce(np.add, [np.gradient(f[i], axis=i) for i in range(num_dims)])
    

    Matlab's documentation uses this exact formula (scroll down to Divergence of a Vector Field)

    0 讨论(0)
  • 2020-12-03 22:18

    The divergence as a built-in function is included in matlab, but not numpy. This is the sort of thing that it may perhaps be worthwhile to contribute to pylab, an effort to create a viable open-source alternative to matlab.

    http://wiki.scipy.org/PyLab

    Edit: Now called http://www.scipy.org/stackspec.html

    0 讨论(0)
  • 2020-12-03 22:19

    I don't think the answer by @Daniel is correct, especially when the input is in order [Fx, Fy, Fz, ...].

    A simple test case

    See the MATLAB code:

    a = [1 2 3;1 2 3; 1 2 3];
    b = [[7 8 9] ;[1 5 8] ;[2 4 7]];
    divergence(a,b)
    

    which gives the result:

    ans =
    
       -5.0000   -2.0000         0
       -1.5000   -1.0000         0
        2.0000         0         0
    

    and Daniel's solution:

    def divergence(f):
        """
        Daniel's solution
        Computes the divergence of the vector field f, corresponding to dFx/dx + dFy/dy + ...
        :param f: List of ndarrays, where every item of the list is one dimension of the vector field
        :return: Single ndarray of the same shape as each of the items in f, which corresponds to a scalar field
        """
        num_dims = len(f)
        return np.ufunc.reduce(np.add, [np.gradient(f[i], axis=i) for i in range(num_dims)])
    
    
    if __name__ == '__main__':
        a = np.array([[1, 2, 3]] * 3)
        b = np.array([[7, 8, 9], [1, 5, 8], [2, 4, 7]])
        div = divergence([a, b])
        print(div)
        pass
    

    which gives:

    [[1.  1.  1. ]
     [4.  3.5 3. ]
     [2.  2.5 3. ]]
    

    Explanation

    The mistake of Daniel's solution is, in Numpy, the x axis is the last axis instead of the first axis. When using np.gradient(x, axis=0), Numpy actually gives the gradient of y direction (when x is a 2d array).

    My solution

    There is my solution based on Daniel's answer.

    def divergence(f):
        """
        Computes the divergence of the vector field f, corresponding to dFx/dx + dFy/dy + ...
        :param f: List of ndarrays, where every item of the list is one dimension of the vector field
        :return: Single ndarray of the same shape as each of the items in f, which corresponds to a scalar field
        """
        num_dims = len(f)
        return np.ufunc.reduce(np.add, [np.gradient(f[num_dims - i - 1], axis=i) for i in range(num_dims)])
    

    which gives the same result as MATLAB divergence in my test case.

    0 讨论(0)
提交回复
热议问题