如何读取有限元网格并将其视为非结构化网格

How to read finite element mesh and view it as UnstructuredGrid

我想从 HDF5 文件中读取有限元网格(即具有坐标的矩阵和具有连通性的矩阵)并使用 Python 界面在 ParaView 中显示它。

我知道如何做一些简单的事情:

from paraview.simple import *

Sphere()
Show()
Render()

可是,网格怎么做呢?让我们跳过 HDF5 部分,关注这个包含二维四边形的非常简单的二维网格:

from paraview.simple import *
import numpy as np

coor = np.array([
    [ 0.0 , 0.0 ],
    [ 1.0 , 0.0 ],
    [ 2.0 , 0.0 ],
    [ 0.0 , 1.0 ],
    [ 1.0 , 1.0 ],
    [ 2.0 , 1.0 ],
])

conn = np.array([
    [ 0 , 1 , 4 , 3 ],
    [ 1 , 2 , 5 , 4 ],
])

Where to go from here?

可能的方法

一种可能的方法是构建 vtkUnstructuredGrid。但问题是我不知道该怎么办。 IE。我如何告诉 ParaView 使用它?

from paraview import vtk

points = vtk.vtkPoints()

for i,(x,y) in enumerate(coor):
    points.InsertNextPoint(x,y,0.0)

grid = vtk.vtkUnstructuredGrid()

for el in conn:
    cell = vtk.vtkQuad()
    for i,ver in enumerate(el): 
        cell.GetPointIds().SetId(i,ver)
    grid.InsertNextCell(cell.GetCellType(),cell.GetPointIds())

grid.SetPoints(points)

了解如何包含单元格数据和点数据会非常有帮助,但我可能可以从解决这个问题开始解决这个问题。

首先,重要的是要注意在 ParaView 中有几个不同的 "levels" 和 Python 用法。您的第一个示例是从高级 Python 接口到 ParaView。您可以在用户界面中执行的大多数操作都可以在 ParaView 中通过 Python 控制台或通过 运行 脚本通过 Python 控制台在该级别完成。

在较低级别,Python 可用于定义 VTK 的操作。 Programmable FilterProgrammable Source 是完成此级别编程的地方。重要的是要注意 Programmable FilterProgrammable Source 对 ParaView 或 paraview.simple 一无所知 - 他们在 Python 环境中执行他们的 Python 脚本VTK 可用。例如,如果您导入 paraview.simple,则行为未定义。

为了您的目的,较低级别的 Python 编程似乎是合适的。我会定义一个 Programmable Source,将其 Output Data Set Type 设置为 vtkUnstructuredGrid。接下来,您的脚本将类似于:

import numpy as np

coor = np.array([
    [ 0.0 , 0.0 ],
    [ 1.0 , 0.0 ],
    [ 2.0 , 0.0 ],
    [ 0.0 , 1.0 ],
    [ 1.0 , 1.0 ],
    [ 2.0 , 1.0 ],
])

conn = np.array([
    [ 0 , 1 , 4 , 3 ],
    [ 1 , 2 , 5 , 4 ],
])

import vtk

grid = self.GetOutput()

points = vtk.vtkPoints()
for i,(x,y) in enumerate(coor):
    points.InsertNextPoint(x,y,0.0)
grid.SetPoints(points)

grid.Allocate()
for el in conn:
    cell = vtk.vtkQuad()
    for i,ver in enumerate(el): 
          cell.GetPointIds().InsertId(i,ver)
    grid.InsertNextCell(cell.GetCellType(),cell.GetPointIds())

请感谢@CoryQuammen,因为这确实是他的解决方案

为了将来参考完整的脚本,包括一些单元格和点数据

from paraview.simple import *

paraview.simple._DisableFirstRenderCameraReset()

# create a new 'Programmable Source'
mesh = ProgrammableSource()
mesh.OutputDataSetType = 'vtkUnstructuredGrid'
mesh.ScriptRequestInformation = ''
mesh.PythonPath = ''
mesh.Script = '''
import numpy as np

coor = np.array([
    [ 0.0 , 0.0 ],
    [ 1.0 , 0.0 ],
    [ 2.0 , 0.0 ],
    [ 0.0 , 1.0 ],
    [ 1.0 , 1.0 ],
    [ 2.0 , 1.0 ],
])

conn = np.array([
    [ 0 , 1 , 4 , 3 ],
    [ 1 , 2 , 5 , 4 ],
])

celldata = [
  1.0 ,
  2.0
]

normals = np.array([
  [ -1.0 , -1.0 ],
  [  0.0 , -1.0 ],
  [ +1.0 , -1.0 ],
  [ -1.0 , +1.0 ],
  [  0.0 , +1.0 ],
  [ +1.0 , +1.0 ],
])

normals /= np.tile(np.sqrt(np.sum(normals**2.,axis=1)).reshape(-1,1),(1,2))

import vtk

grid = self.GetOutput()

points = vtk.vtkPoints()
for i,(x,y) in enumerate(coor):
    points.InsertNextPoint(x,y,0.0)
grid.SetPoints(points)

grid.Allocate()
for el in conn:
    cell = vtk.vtkQuad()
    for i,ver in enumerate(el):
          cell.GetPointIds().InsertId(i,ver)
    grid.InsertNextCell(cell.GetCellType(),cell.GetPointIds())

data = vtk.vtkDoubleArray()
data.SetName("Example data")
for i in celldata:
  data.InsertNextValue(i)

grid.GetCellData().AddArray(data)

data = vtk.vtkDoubleArray()
data.SetNumberOfComponents(3)
data.SetName("Normals")
for i in normals:
  data.InsertNextTuple([i[0],i[1],0.0])

grid.GetPointData().AddArray(data)
'''

# show data from mesh
Mesh = Show(mesh)

Render()