用python中的积分法从x和y速度计算流函数

2024-04-26 12:20:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图计算二维流的流函数,给定x和y速度分量。我使用流函数的定义:

enter image description here

我按照建议的here尝试了这个方法,它基本上建议你整合一行v组件,在所有地方集成u组件,并将它们相加(如果我理解正确的话)。在

这是我的代码:

from scipy import integrate
import numpy

# make some data
y=numpy.linspace(0,10,40)
x=numpy.linspace(0,10,50)
X,Y=numpy.meshgrid(x,y)

# a velocity field that is non-divergent
u=3*Y**2-3*X**2
v=6*X*Y

# integrate
intx=integrate.cumtrapz(v,X,axis=1,initial=0)[0]
inty=integrate.cumtrapz(u,Y,axis=0,initial=0)

psi1=-intx+inty

intx2=integrate.cumtrapz(v,X,axis=1,initial=0)
inty2=integrate.cumtrapz(u,Y,axis=0,initial=0)[:,0][:,None]

psi2=-intx2+inty2

psi=(psi1+psi2)/2.

u2=numpy.gradient(psi,axis=0)
v2=-numpy.gradient(psi,axis=1)
dx=numpy.gradient(X,axis=1)
dy=numpy.gradient(Y,axis=0)

u2=u2/dy
v2=v2/dx

我的问题是重新计算的v2和{}非常接近,但是u2和{}总是有一点偏移(在这个设置中是0.09861933)。这个错误与积分的计算方式有关吗?从x流和y流计算流函数的推荐方法是什么?在


Tags: 方法函数importnumpy组件建议initialv2
1条回答
网友
1楼 · 发布于 2024-04-26 12:20:41

回答自己:

我想这可能会变得更复杂,但这里是一个尝试,来解决一个流函数+一个速度势,目的是最小化输入uv与重构的输入之间的差异。在

(匆忙上传,会回来重新格式化公式)。在

'''Solve streamfunction and velocity potential from given u and v.

u and v are given in an even grid (n x m).

streamfunction (psi) and velocity potential (chi) are defined on a dual
grid ((n+1) x (m+1)), where psi and chi are defined on the 4 corners
of u and v.

Define:

    u = u_chi + u_psi
    v = v_chi + v_psi

    u_psi = -dpsi/dy
    v_psi = dpsi/dx
    u_chi = dchi/dx
    v_chi = dchi/dy


Define 2 2x2 kernels:

    k_x = |-0.5 0.5|
          |-0.5 0.5| / dx

    k_y = |-0.5 -0.5|
          |0.5   0.5| / dy

Then u_chi = chi \bigotimes k_x
where \bigotimes is cross-correlation,

Similarly:

    v_chi = chi \bigotimes k_y
    u_psi = psi \bigotimes -k_y
    v_psi = psi \bigotimes k_x

Define cost function J = (uhat - u)**2 + (vhat - v)**2

Gradients of chi and psi:

    dJ/dchi = (uhat - u) du_chi/dchi + (vhat - v) dv_chi/dchi
    dJ/dpsi = (uhat - u) du_psi/dpsi + (vhat - v) dv_psi/dpsi

    du_chi/dchi = (uhat - u) \bigotimes Rot180(k_x) = (uhat - u) \bigotimes -k_x
    dv_chi/dchi = (vhat - v) \bigotimes Rot180(k_y) = (vhat - v) \bigotimes -k_y
    du_psi/dpsi = (uhat - u) \bigotimes k_x
    dv_psi/dpsi = (vhat - v) \bigotimes Rot180(k_x) = (vhat - v) \bigotimes -k_x

Add optional regularization term:

    J = (uhat - u)**2 + (vhat - v)**2 + lambda*(chi**2 + psi**2)
'''

from scipy import integrate
import numpy
from scipy import optimize
from scipy.signal import fftconvolve


def uRecon(sf,vp,kernel_x,kernel_y):
    uchi=fftconvolve(vp,-kernel_x,mode='valid')
    upsi=fftconvolve(sf,kernel_y,mode='valid')
    return upsi+uchi

def vRecon(sf,vp,kernel_x,kernel_y):
    vchi=fftconvolve(vp,-kernel_y,mode='valid')
    vpsi=fftconvolve(sf,-kernel_x,mode='valid')
    return vpsi+vchi

def costFunc(params,u,v,kernel_x,kernel_y,pad_shape,lam):
    pp=params.reshape(pad_shape)
    sf=pp[0]
    vp=pp[1]
    uhat=uRecon(sf,vp,kernel_x,kernel_y)
    vhat=vRecon(sf,vp,kernel_x,kernel_y)
    j=(uhat-u)**2+(vhat-v)**2
    j=j.mean()
    j+=lam*numpy.mean(params**2)

    return j

def jac(params,u,v,kernel_x,kernel_y,pad_shape,lam):
    pp=params.reshape(pad_shape)
    sf=pp[0]
    vp=pp[1]
    uhat=uRecon(sf,vp,kernel_x,kernel_y)
    vhat=vRecon(sf,vp,kernel_x,kernel_y)

    du=uhat-u
    dv=vhat-v

    dvp_u=fftconvolve(du,kernel_x,mode='full')
    dvp_v=fftconvolve(dv,kernel_y,mode='full')

    dsf_u=fftconvolve(du,-kernel_y,mode='full')
    dsf_v=fftconvolve(dv,kernel_x,mode='full')

    dsf=dsf_u+dsf_v
    dvp=dvp_u+dvp_v

    re=numpy.vstack([dsf[None,:,:,],dvp[None,:,:]])
    re=re.reshape(params.shape)
    re=re+lam*params/u.size
    #re=re+lam*params

    return re


# make some data
y=numpy.linspace(0,10,40)
x=numpy.linspace(0,10,50)
X,Y=numpy.meshgrid(x,y)
dx=x[1]-x[0]
dy=y[1]-y[0]

# create convolution kernel
kernel_x=numpy.array([[-0.5, 0.5],[-0.5, 0.5]])/dx
kernel_y=numpy.array([[-0.5, -0.5],[0.5, 0.5]])/dy

# make a velocity field
u=3*Y**2-3*X**2+Y
v=6*X*Y+X

# integrate to make an intial guess
intx=integrate.cumtrapz(v,X,axis=1,initial=0)[0]
inty=integrate.cumtrapz(u,Y,axis=0,initial=0)
psi1=intx-inty

intx=integrate.cumtrapz(v,X,axis=1,initial=0)
inty=integrate.cumtrapz(u,Y,axis=0,initial=0)[:,0][:,None]
psi2=intx-inty

psi=0.5*(psi1+psi2)

intx=integrate.cumtrapz(u,X,axis=1,initial=0)[0]
inty=integrate.cumtrapz(v,Y,axis=0,initial=0)
chi1=intx+inty

intx=integrate.cumtrapz(u,X,axis=1,initial=0)
inty=integrate.cumtrapz(v,Y,axis=0,initial=0)[:,0][:,None]
chi2=intx+inty

chi=0.5*(chi1+chi2)

# pad to add 1 row/column
sf=numpy.pad(psi,(1,0),'edge')
vp=numpy.pad(chi,(1,0),'edge')
params=numpy.vstack([sf[None,:,:], vp[None,:,:]])

# optimize
pad_shape=params.shape
lam=0.001 # regularization parameter

opt=optimize.minimize(costFunc,params,
        args=(u,v,kernel_x,kernel_y,pad_shape,lam),
        method='Newton-CG',
        jac=jac)

params=opt.x.reshape(pad_shape)
sf=params[0]
vp=params[1]
uhat=uRecon(sf,vp,kernel_x,kernel_y)
vhat=vRecon(sf,vp,kernel_x,kernel_y)

其他注意事项:

由于卷积使用的是一个极小的核(2x2),一种特殊形式的卷积可能比fftconvolve快,参见比较here,和{a2}。在

当网格不均匀时(例如高斯网格上的风数据),将不得不处理不均匀的网格大小。我想出了一个脚本,它使用netcdf格式(通过CDAT模块)计算风数据,请参见here。欢迎反馈。在

相关问题 更多 >