如何在contourf插值中避免使用零,以绘制CFD速度数据。

huangapple go评论149阅读模式
英文:

How to avoid using zeros in interpolation for contourf, for plotting CFD velocity data

问题

从 Ansys Fluent 中的 CFD 模拟中,我有一个包含 4 列的 CSV 数据帧:x、y、z(不规则网格的节点坐标)和 u(流速的大小)。我想要绘制 u 在 x-z 平面上的等高线图。空气流过的实体的 u=0,我希望在插值时对其进行掩码处理,即我想要创建一个带有不规则边界的等高线图。第一张附图大致是我想要使用 Python 获得的结果,是通过 Ansys CFD-Post 获得的,实体的几何形状用黑色轮廓线标出:

这是数据的样子。请注意,列值不是唯一的,也没有排序。

  1. ### 几何参数,单位是米
  2. L = 0.3048
  3. hwall = 0.0095
  4. Lin = L-hwall*2
  5. H = 0.073
  6. Lpad = Lin/10
  7. Hpad = H/10
  8. ### 获取数据帧:x、y、z坐标和瞬时流向速度
  9. df = pd.read_csv('test2.csv', names=['x','y','z','u'])
  10. dfsub = df.loc[(df.x > -Lin/2-Lpad) & (df.x < Lin/2+Lpad) & (df.z < H+Hpad)] # 限制在较小的区域内
  11. dfsub
  12. x y z u
  13. 2 -0.141747 2.106994e-11 0.010645 0.106242
  14. 3 -0.139540 -6.458060e-12 0.010615 0.456511
  15. 5 -0.132303 -1.308423e-12 0.010602 1.138072
  16. 8 0.141747 -2.106730e-11 0.010650 -0.154759
  17. 9 0.139543 1.165080e-11 0.010619 -0.150316
  18. ... ... ... ... ...
  19. 3597 0.159718 -2.567698e-11 0.027614 -0.532316
  20. 3598 0.159934 2.542068e-13 0.027258 -0.544210
  21. 3599 0.159501 1.936669e-12 0.027613 -0.520241
  22. 3600 0.157081 -6.854833e-12 0.035597 -0.392042
  23. 3601 0.156974 1.765435e-11 0.027732 -0.382951

以下是用来展示数据的散点图:

  1. umax = max(np.abs(dfsub.u))
  2. fig, ax = plt.subplots(figsize=(16, 3))
  3. dfsub.plot.scatter('x', 'z', c='u', cmap='seismic', vmin=-umax, vmax=umax, ax=ax)
  4. plt.show()

接下来是用于绘图的基本代码,我不希望它起作用,因为实体区域只是被视为插值的速度 = 0:

  1. ### 等高线图
  2. crange = 4
  3. fig, ax = plt.subplots(figsize=(16, 3))
  4. tcf = ax.tricontourf(dfsub.x, dfsub.z, dfsub.u, levels=np.arange(
  5. crange, crange, 0.1), cmap='seismic', extend='both')
  6. plt.colorbar(tcf, ax=ax, label='$u$ (m/s)')
  7. ax.set_title('basic', size=14)
  8. plt.show()

以下是输出:
如何在contourf插值中避免使用零,以绘制CFD速度数据。

我已经尝试过多种方法来屏蔽这些值,例如将 0 替换为 NaN,但会导致 "ValueError: z array must not contain non-finite values within the triangulation" 错误:

  1. ### 获取数据帧:x、y、z坐标和瞬时流向速度
  2. df = pd.read_csv('test2.csv', names=['x','y','z','u'])
  3. df.replace(0, np.nan, inplace=True)
  4. dfsub = df.loc[(df.x > -Lin/2-Lpad) & (df.x < Lin/2+Lpad) & (df.z < H+Hpad)] # 限制在较小的区域内

或者从数据帧中删除 0:

  1. ### 获取数据帧:x、y、z坐标和瞬时流向速度
  2. df = pd.read_csv('test2.csv', names=['x','y','z','u'])
  3. df = df.loc[df.u != 0]
  4. dfsub = df.loc[(df.x > -Lin/2-Lpad) & (df.x < Lin/2+Lpad) & (df.z < H+Hpad)] # 限制在较小的区域内

这种方法的输出如下所示,它仍然在我打算排除的区域内进行插值。

如何在contourf插值中避免使用零,以绘制CFD速度数据。

英文:

From a CFD simulation in Ansys Fluent, I have a dataframe from a csv containing 4 columns: x,y,z (nodal coordinates of irregular grid), and u (streamwise velocity magnitude). I want to plot a contour plot of u over the x-z plane. The solid body around which air flows has u=0, and I want this to be masked for the interpolation, i.e. I want to create a contour plot with an irregular boundary. The first attached image is more or less what I'd like to get with Python, obtained with Ansys CFD-Post -- the geometry of the solid body is outlined in black:

如何在contourf插值中避免使用零,以绘制CFD速度数据。

This is what the data looks like. Note column values are not unique or sorted.

  1. ### geometric parameters, in m
  2. L = 0.3048
  3. hwall = 0.0095
  4. Lin = L-hwall*2
  5. H = 0.073
  6. Lpad = Lin/10
  7. Hpad = H/10
  8. ### get df: x,y,z coordinates and instantaneous streamwise velocity
  9. df = pd.read_csv(&#39;test2.csv&#39;,names=[&#39;x&#39;,&#39;y&#39;,&#39;z&#39;,&#39;u&#39;])
  10. dfsub = df.loc[(df.x&gt;-Lin/2-Lpad)&amp;(df.x&lt;Lin/2+Lpad)&amp;(df.z&lt;H+Hpad)] # limit to smaller region
  11. dfsub
  12. x y z u
  13. 2 -0.141747 2.106994e-11 0.010645 0.106242
  14. 3 -0.139540 -6.458060e-12 0.010615 0.456511
  15. 5 -0.132303 -1.308423e-12 0.010602 1.138072
  16. 8 0.141747 -2.106730e-11 0.010650 -0.154759
  17. 9 0.139543 1.165080e-11 0.010619 -0.150316
  18. ... ... ... ... ...
  19. 3597 0.159718 -2.567698e-11 0.027614 -0.532316
  20. 3598 0.159934 2.542068e-13 0.027258 -0.544210
  21. 3599 0.159501 1.936669e-12 0.027613 -0.520241
  22. 3600 0.157081 -6.854833e-12 0.035597 -0.392042
  23. 3601 0.156974 1.765435e-11 0.027732 -0.382951

Here is a scatterplot to show the data:

  1. umax = max(np.abs(dfsub.u))
  2. fig,ax=plt.subplots(figsize=(16,3))
  3. dfsub.plot.scatter(&#39;x&#39;,&#39;z&#39;,c=&#39;u&#39;,cmap =&#39;seismic&#39;,vmin=-umax,vmax=umax,ax=ax)
  4. plt.show()

如何在contourf插值中避免使用零,以绘制CFD速度数据。

And here is the basic code for plotting, which I don't expect to work since the solid region is just read as velocity = 0 for interpolation:

  1. ### contour plot
  2. crange = 4
  3. fig,ax=plt.subplots(figsize=(16,3))
  4. tcf = ax.tricontourf(dfsub.x,dfsub.z,dfsub.u,levels=np.arange(
  5. crange,crange,0.1),cmap=&#39;seismic&#39;,extend=&#39;both&#39;)
  6. plt.colorbar(tcf,ax=ax,label=&#39;$u$ (m/s)&#39;)
  7. ax.set_title(&#39;basic&#39;,size=14)
  8. plt.show()

and here is the output:
如何在contourf插值中避免使用零,以绘制CFD速度数据。

I've tried to mask these values in several ways, e.g. replace 0s with nans, which gives "ValueError: z array must not contain non-finite values within the triangulation":

  1. ### get df: x,y,z coordinates and instantaneous streamwise velocity
  2. df = pd.read_csv(&#39;test2.csv&#39;,names=[&#39;x&#39;,&#39;y&#39;,&#39;z&#39;,&#39;u&#39;])
  3. df.replace(0, np.nan, inplace=True)
  4. dfsub = df.loc[(df.x&gt;-Lin/2-Lpad)&amp;(df.x&lt;Lin/2+Lpad)&amp;(df.z&lt;H+Hpad)] # limit to smaller region

or to remove the 0s from the dataframe:

  1. ### get df: x,y,z coordinates and instantaneous streamwise velocity
  2. df = pd.read_csv(&#39;test2.csv&#39;,names=[&#39;x&#39;,&#39;y&#39;,&#39;z&#39;,&#39;u&#39;])
  3. df = df.loc[df.u != 0]
  4. dfsub = df.loc[(df.x&gt;-Lin/2-Lpad)&amp;(df.x&lt;Lin/2+Lpad)&amp;(df.z&lt;H+Hpad)] # limit to smaller region

The output for this is in the attached image. It still interpolates in the regions I mean to exclude.

如何在contourf插值中避免使用零,以绘制CFD速度数据。

答案1

得分: 0

如果我理解您的问题正确的话,您想要使用一个遮罩数组。在绘制遮罩数组的轮廓时,遮罩的区域将被忽略。没有实际数据来了解它的格式,我会留给您来想出如何创建您的遮罩数组。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. plt.close("all")
  4. x = np.linspace(-1, 1, 100)
  5. y = np.linspace(0, 1, 100)
  6. X, Y = np.meshgrid(x, y)
  7. U = X + 2*Y
  8. # 创建一个不希望轮廓存在的区域
  9. solid = (X >= -0.25) & (X <= 0) & (Y >= 0) & (Y <= 0.75)
  10. # mask参数接受一个布尔数组,指示哪些元素被遮罩
  11. U_masked = np.ma.array(U, mask=solid)
  12. fig, ax = plt.subplots()
  13. # contourf不会绘制被遮罩的区域
  14. p = ax.contourf(X, Y, U_masked, corner_mask=False)
  15. fig.colorbar(p, ax=ax, label="u")
  16. ax.set_xlabel("x")
  17. ax.set_ylabel("y")

如何在contourf插值中避免使用零,以绘制CFD速度数据。

编辑:由于数据是不规则间隔的,使用tricontourf可能会更合适。这种方法的唯一问题是角落可能会被截断(或者我不确定如何处理它)。

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import matplotlib.tri as tri
  4. plt.close("all")
  5. x = np.linspace(-1, 1, 100)
  6. y = np.linspace(0, 1, 100)
  7. X, Y = np.meshgrid(x, y)
  8. U = X + 2*Y
  9. # 创建一个不希望轮廓存在的区域
  10. solid = (X >= -0.25) & (X <= 0) & (Y >= 0) & (Y <= 0.75)
  11. # 创建三角形;我使用了之前的扁平化X和Y,但我认为使用数据的x和y值也可以
  12. triang = tri.Triangulation(X.flatten(), Y.flatten())
  13. # 基于`solid`布尔矩阵遮罩三角形
  14. triang.set_mask(np.any(solid.flatten()[triang.triangles], axis=1))
  15. fig, ax = plt.subplots()
  16. p = ax.tricontourf(triang, U.flatten())
  17. fig.colorbar(p, ax=ax, label="u")
  18. ax.set_xlabel("x")
  19. ax.set_ylabel("y")

如何在contourf插值中避免使用零,以绘制CFD速度数据。

英文:

If I understand your question correctly, you want to use a masked array. When plotting the contours of masked arrays, the masked regions are ignored. Without the actual data to understand how it is formatted, I leave it to you to figure out how to create your masking array.

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. plt.close(&quot;all&quot;)
  4. x = np.linspace(-1, 1, 100)
  5. y = np.linspace(0, 1, 100)
  6. X, Y = np.meshgrid(x, y)
  7. U = X + 2*Y
  8. # create a region where we do not want the contour to exist
  9. solid = (X &gt;= -0.25) &amp; (X &lt;= 0) &amp; (Y &gt;= 0) &amp; (Y &lt;= 0.75)
  10. # the mask argument takes a boolean array that says which elements are masked
  11. U_masked = np.ma.array(U, mask=solid)
  12. fig, ax = plt.subplots()
  13. # contourf will not plot the masked regions
  14. p = ax.contourf(X, Y, U_masked, corner_mask=False)
  15. fig.colorbar(p, ax=ax, label=&quot;u&quot;)
  16. ax.set_xlabel(&quot;x&quot;)
  17. ax.set_ylabel(&quot;y&quot;)

如何在contourf插值中避免使用零,以绘制CFD速度数据。


Edit: Since the data is irregularly spaced, using tricontourf might work instead. The only issue with this method is that corners will be cut off (or at least I am not sure how to deal with that).

  1. import numpy as np
  2. import matplotlib.pyplot as plt
  3. import matplotlib.tri as tri
  4. plt.close(&quot;all&quot;)
  5. x = np.linspace(-1, 1, 100)
  6. y = np.linspace(0, 1, 100)
  7. X, Y = np.meshgrid(x, y)
  8. U = X + 2*Y
  9. # create a region where we do not want the contour to exist
  10. solid = (X &gt;= -0.25) &amp; (X &lt;= 0) &amp; (Y &gt;= 0) &amp; (Y &lt;= 0.75)
  11. # create the triangles; I used the flattened X and Y from before,
  12. # but I think using the x and y values from the data will work
  13. triang = tri.Triangulation(X.flatten(), Y.flatten())
  14. # masking triangles based on the `solid` boolean matrix
  15. triang.set_mask(np.any(solid.flatten()[triang.triangles], axis=1))
  16. fig, ax = plt.subplots()
  17. p = ax.tricontourf(triang, U.flatten())
  18. fig.colorbar(p, ax=ax, label=&quot;u&quot;)
  19. ax.set_xlabel(&quot;x&quot;)
  20. ax.set_ylabel(&quot;y&quot;)

如何在contourf插值中避免使用零,以绘制CFD速度数据。

答案2

得分: 0

以下是您要翻译的内容:

@jared的解决方案似乎有点效果,但我还按照this解决方案创建了一个用于这些数据的掩码。

用于掩码的3个几何条件

cond1 = (df.x > -L/2) & (df.x < L/2) & (df.z < hbase)
cond2 = (df.x > -L/2) & (df.x < -Lin/2) & (df.z < H)
cond3 = (df.x > Lin/2) & (df.x < L/2) & (df.z < H)

df.loc[cond1 | cond2 | cond3, 'u'] = 0 # 在这些区域将列u设置为0

从DataFrame列中提取值

x = df.x.values
z = df.z.values
u = df.u.values

基于u数组中的零值设置掩码

isbad = u == 0

进行三角剖分,并计算三角形的索引

triang = tri.Triangulation(x, z)
mask = np.all(np.where(isbad[triang.triangles], True, False), axis=1)
triang.set_mask(mask)

使用带有掩码的tricontourf绘制轮廓

crange = 4
fig, ax = plt.subplots(figsize=(16, 3))
tcf = ax.tricontourf(triang, u, levels=np.arange(-crange, crange, 0.005), cmap='seismic', extend='both')
plt.colorbar(tcf, ax=ax, label='$u$ (m/s)')
ax.set_ylim(0,0.08)
ax.set_xlim(-0.165,0.165)
plt.xlabel('x')
plt.ylabel('z')
plt.show()

似乎可以防止在零值上进行插值,但是三角剖分非常粗糙,所以掩码效果不佳。

我猜解决方案是优化网格并进行某种插值?

英文:

The solution from @jared somewhat works, but I also followed this solution to create a mask for this data.

  1. # 3 geometric conditions for mask
  2. cond1 = (df.x &gt; -L/2) &amp; (df.x &lt; L/2) &amp; (df.z &lt; hbase)
  3. cond2 = (df.x &gt; -L/2) &amp; (df.x &lt; -Lin/2) &amp; (df.z &lt; H)
  4. cond3 = (df.x &gt; Lin/2) &amp; (df.x &lt; L/2) &amp; (df.z &lt; H)
  5. df.loc[cond1 | cond2 | cond3, &#39;u&#39;] = 0 # set column u = 0 in those regions
  6. # Extract the values from the DataFrame columns
  7. x = df.x.values
  8. z = df.z.values
  9. u = df.u.values
  10. # Set up the mask based on zero values in the u array
  11. isbad = u == 0
  12. # triangulate, and evaluate indices of triangles
  13. triang = tri.Triangulation(x, z)
  14. mask = np.all(np.where(isbad[triang.triangles], True, False), axis=1)
  15. triang.set_mask(mask)
  16. # Plot the contour using tricontourf with a mask
  17. crange = 4
  18. fig, ax = plt.subplots(figsize=(16, 3))
  19. tcf = ax.tricontourf(triang, u, levels=np.arange(-crange, crange, 0.005), cmap=&#39;seismic&#39;, extend=&#39;both&#39;)
  20. plt.colorbar(tcf, ax=ax, label=&#39;$u$ (m/s)&#39;)
  21. ax.set_ylim(0,0.08)
  22. ax.set_xlim(-0.165,0.165)
  23. plt.xlabel(&#39;x&#39;)
  24. plt.ylabel(&#39;z&#39;)
  25. plt.show()

It does seem to prevent interpolation over the zeros, but the triangulation is very coarse, so the mask isn't great. 如何在contourf插值中避免使用零,以绘制CFD速度数据。

I guess the solution is to refine the grid + interpolate somehow?

huangapple
  • 本文由 发表于 2023年6月6日 05:41:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410184.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定