简体   繁体   中英

Generating Position Vectors from Numpy Meshgrid

I'll try to explain my issue here without going into too much detail on the actual application so that we can stay grounded in the code. Basically, I need to do operations to a vector field. My first step is to generate the field as

x,y,z = np.meshgrid(np.linspace(-5,5,10),np.linspace(-5,5,10),np.linspace(-5,5,10))

Keep in mind that this is a generalized case, in the program, the bounds of the vector field are not all the same. In the general run of things, I would expect to say something along the lines of

u,v,w = f(x,y,z) .

Unfortunately, this case requires so more difficult operations. I need to use a formula similar to

Biot Savart 方程的简化版本 where the vector r is defined in the program as np.array([xgrid-x,ygrid-y,zgrid-z]) divided by its own norm. Basically, this is a vector pointing from every point in space to the position (x,y,z)

Now Numpy has implemented a cross product function using np.cross() , but I can't seem to create a "meshgrid of vectors" like I need. I have a lambda function that is essentially

xgrid,ygrid,zgrid=np.meshgrid(np.linspace(-5,5,10),np.linspace(-5,5,10),np.linspace(-5,5,10)) B(x,y,z) = lambda x,y,z: np.cross(v,np.array([xgrid-x,ygrid-y,zgrid-z]))

Now the array v is imported from another class and seems to work just fine, but the second array, np.array([xgrid-x,ygrid-y,zgrid-z]) is not a proper shape because it is a "vector of meshgrids" instead of a "meshgrid of vectors". My big issue is that I cannot seem to find a method by which to format the meshgrid in such a way that the np.cross() function can use the position vector. Is there a way to do this?

Originally I thought that I could do something along the lines of:

x,y,z = np.meshgrid(np.linspace(-2,2,5),np.linspace(-2,2,5),np.linspace(-2,2,5)) A = np.array([x,y,z]) cross_result = np.cross(np.array(v),A)

This, however, returns the following error, which I cannot seem to circumvent:

Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Python27\lib\site-packages\numpy\core\numeric.py", line 1682, in cross raise ValueError(msg) ValueError: incompatible dimensions for cross product (dimension must be 2 or 3)

There's a work around with reshape and broadcasting:

A = np.array([x_grid, y_grid, z_grid])
# A.shape == (3,5,5,5)

def B(v, p):
    '''
    v.shape = (3,)
    p.shape = (3,) 
    '''
    shape = A.shape

    Ap = A.reshape(3,-1) - p[:,None]

    return np.cross(v[None,:], Ap.reshape(3,-1).T).reshape(shape)

print(B(v,p).shape)
# (3, 5, 5, 5)

I think your original attempt only lacks the specification of the axis along which the cross product should be executed.

x, y, z = np.meshgrid(np.linspace(-2, 2, 5),np.linspace(-2, 2, 5), np.linspace(-2, 2, 5))
A = np.array([x, y, z])
cross_result = np.cross(np.array(v), A, axis=0)

I tested this with the code below. As an alternative to np.array([x, y, z]) , you can also use np.stack(x, y, z, axis=0) , which clearly shows along which axis the meshgrids are stacked to form a meshgrid of vectors, the vectors being aligned with axis 0. I also printed the shape each time and used random input for testing. In the test, the output of the formula is compared at a random index to the cross product of the input-vector at the same index with vector v.

import numpy as np 

x, y, z = np.meshgrid(np.linspace(-5, 5, 10), np.linspace(-5, 5, 10), np.linspace(-5, 5, 10))
p = np.random.rand(3) # random reference point
A = np.array([x-p[0], y-p[1], z-p[2]]) # vectors from positions to reference
A_bis = np.stack((x-p[0], y-p[1], z-p[2]), axis=0) 
print(f"A equals A_bis? {np.allclose(A, A_bis)}") # the two methods of stacking yield the same

v = -1 + 2*np.random.rand(3) # random vector v

B = np.cross(v, A, axis=0) # cross-product for all points along correct axis
print(f"Shape of v: {v.shape}")
print(f"Shape of A: {A.shape}")
print(f"Shape of B: {B.shape}")


print("\nComparison for random locations: ")
point = np.random.randint(0, 9, 3) # generate random multi-index
a = A[:, point[0], point[1], point[2]] # look up input-vector corresponding to index
b = B[:, point[0], point[1], point[2]] # look up output-vector corresponding to index
print(f"A[:, {point[0]}, {point[1]}, {point[2]}] = {a}")
print(f"v = {v}")
print(f"Cross-product as v x a:         {np.cross(v, a)}")
print(f"Cross-product from B (= v x A): {b}")

The resulting output looks like:

A equals A_bis? True
Shape of v: (3,)
Shape of A: (3, 10, 10, 10)
Shape of B: (3, 10, 10, 10)

Comparison for random locations: 
A[:, 8, 1, 1] = [-4.03607312  3.72661831 -4.87453077]
v = [-0.90817859  0.10110274 -0.17848181]
Cross-product as v x a:         [ 0.17230515 -3.70657882 -2.97637688]
Cross-product from B (= v x A): [ 0.17230515 -3.70657882 -2.97637688]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM