More efficient loop method?

I have a small piece of code from a much larger script. I realized that when a function is called t_area, it is responsible for most of the execution time. I tested this function myself, and it is not slow, it takes a lot of time due to how many times it needs to be run. I believe. Here is the code where the function is called:

tri_area = np.zeros((numx,numy),dtype=float)
for jj in range(0,numy-1):
    for ii in range(0,numx-1):
      xp = x[ii,jj]
      yp = y[ii,jj]
      zp = surface[ii,jj]
      ap = np.array((xp,yp,zp))

      xp = xp+dx
      zp = surface[ii+1,jj]
      bp = np.array((xp,yp,zp))

      yp = yp+dx
      zp = surface[ii+1,jj+1]
      dp = np.array((xp,yp,zp))

      xp = xp-dx
      zp = surface[ii,jj+1]
      cp = np.array((xp,yp,zp))

      tri_area[ii,jj] = t_area(ap,bp,cp,dp)

The size of the arrays used is 216 x 217, as well as the xand values y. I am new to python coding, I have used MATLAB in the past. So my question is, is there a way around two for-loops or a more efficient way to run this block of code as a whole? Seek any help to speed it up! Thank you

EDIT:

, . t_area, , :

def t_area(a,b,c,d):
ab=b-a
ac=c-a
tri_area_a = 0.5*linalg.norm(np.cross(ab,ac))

db=b-d
dc=c-d
tri_area_d = 0.5*linalg.norm(np.cross(db,dc))

ba=a-b
bd=d-b
tri_area_b = 0.5*linalg.norm(np.cross(ba,bd))

ca=a-c
cd=d-c
tri_area_c = 0.5*linalg.norm(np.cross(ca,cd))

av_area = (tri_area_a + tri_area_b + tri_area_c + tri_area_d)*0.5
return(av_area)

, , , , , , . !

+4
1

, . range(0, numy-1), range(numy-1), 0 numy-2, numy-1. , numy-1 0 numy-2. MATLAB 1, Python 0-, . , tri_area = np.zeros((numx, numy), dtype=float), tri_area[ii,jj] , . , range(numy).

fuction t_area() , . , numpy , , .

ap (i, j) a (m, n, 3), (m, n) - x. (m, n, 3) , . , np.cross(a, b) (i, j) a[i,j] b[i,j]. , np.linalg.norm(a, axis=2) (i, j) a[i,j]. (m, n). , , , 2- .

, . , , surface x y.

import numpy as np

def _t_area(a, b, c):
    ab = b - a
    ac = c - a
    return 0.5 * np.linalg.norm(np.cross(ab, ac), axis=2)

def t_area(x, y, surface, dx):
    a = np.zeros((x.shape[0], y.shape[0], 3), dtype=float)
    b = np.zeros_like(a)
    c = np.zeros_like(a)
    d = np.zeros_like(a)

    a[...,0] = x
    a[...,1] = y
    a[...,2] = surface[:-1,:-1]

    b[...,0] = x + dx
    b[...,1] = y
    b[...,2] = surface[1:,:-1]

    c[...,0] = x
    c[...,1] = y + dx
    c[...,2] = surface[:-1,1:]

    d[...,0] = bp[...,0]
    d[...,1] = cp[...,1]
    d[...,2] = surface[1:,1:]

    # are you sure you didn't mean 0.25???
    return 0.5 * (_t_area(a, b, c) + _t_area(d, b, c) + _t_area(b, a, d) + _t_area(c, a, d))

nx, ny = 250, 250

dx = np.random.random()
x = np.random.random((nx, ny))
y = np.random.random((nx, ny))
surface = np.random.random((nx+1, ny+1))

tri_area = t_area(x, y, surface, dx)

x 0-249, surface 0-250. surface[:-1], surface[0:-1], , 0 , . -1 end MATLAB. , surface[:-1] 0-249. , surface[1:] 1-250, , surface[ii+1].


. , , t_area() . , , , , , , .

, , , x, y,, surface dx . .

, ap, bp, cp dp , . .

. - ( MATLAB ), ii , . , , ?

, .

def t_area(x, y, surface, dx):
    # I assume numx == x.shape[0]. If not, pass it as an extra argument.
    tri_area = np.zeros(x.shape, dtype=float)

    ap = np.zeros((3,), dtype=float)
    bp = np.zeros_like(ap)
    cp = np.zeros_like(ap)
    dp = np.zeros_like(ap)

    for ii in range(x.shape[0]-1): # do you really want range(numx-1) or just range(numx)?
        for jj in range(x.shape[1]-1):
            xp = x[ii,jj]
            yp = y[ii,jj]
            zp = surface[ii,jj]
            ap[:] = (xp, yp, zp)

            # get `bp`, `cp` and `dp` in a similar manner and compute `tri_area[ii,jj]`
+2

Source: https://habr.com/ru/post/1623618/


All Articles