使用 matplotlib 绘制有限元网格的最有效方法?
Most efficient way to plot finite element mesh using matplotlib?
我的问题很简单,但对于那些需要更多上下文的人,请参阅 wikipedia page on finite element methods。
我正在寻找使用 matplotlib 绘制网格的最有效方法,给出以下信息、每个节点的坐标、每个元素属于哪些节点以及每个节点具有的值。下面我有一些示例数据和图像显示网格的样子
nodeinfo=[[0.000,0.000],[1.000,0.000],[2.000,0.500],[0.000,1.000],
[1.000,1.000],[1.750,1.300],[1.000,1.700]]
elementInfo=[[1,2,5],[5,4,1],[2,3,6],[6,5,2],[4,5,7],[5,6,7]]
nodevalues=[1,2,1,2,7,4,5]
nodeinfo是每个节点的坐标(例如节点7有坐标(1,1.7)),elementInfo给出了每个元素由哪些节点组成(例如元素3有节点2,3,6),nodevalues给出了每个节点的值(例如节点 5 的值为 7)。
Using this info how can I plot meshes with matplotlib with a colour gradient showing the different values of the nodes(if possible it would be great if there was a colour gradient between nodes as each element is linear).
备注
如果您想使用它,请创建一些代码将信息组织到节点对象中。
class node:
# Initializer / Instance Attributes
def __init__(self, number, xCord, yCord):
self.number=number
self.value=1
self.isOnBoundary=False
self.xCord=xCord
self.yCord=yCord
self.boundaryType=None
self.element=[]
#makes all class variables callable
def __call__(self):
return self
def checkIfOnBoundary(self,boundarylist):
# Checks if the node is on the boundary when it is invoked
# If the node is not on the boundary then it is set to false
if self.number in boundarylist:
self.isOnBoundary=True
self.boundaryType=boundarylist[self.number][0]
if self.boundaryType == "Dirchlet":
self.value=boundarylist[self.number][1]
else:
self.isOnBoundary=False
def setElement(self,elementInfo):
#given a list in the form [element1,element2,...,elementn]
#where element1 is a list that contains all the nodes that are on that element
for element in elementInfo:
if self.number in element:
self.element.append(elementInfo.index(element)+1)
def setValue(self,value):
# changes the value of the node
self.value=value
def description(self):
return "Node Number: {}, Node Value: {}, Element Node Belongs to: {}, Is Node On the Boundary: {}".format(self.number, self.value, self.element, self.isOnBoundary)
nodeinfo=[[0.000,0.000],[1.000,0.000],[2.000,0.500],[0.000,1.000],
[1.000,1.000],[1.750,1.300],[1.000,1.700]]
elementInfo=[[1,2,5],[5,4,1],[2,3,6],[6,5,2],[4,5,7],[5,6,7]]
nodevalues=[1,2,1,2,7,4,5]
#create list of node objects which we will call on often
nodes=[]
for i in range(len(nodeinfo)):
print(i)
nodes.append(node(i+1,nodeinfo[i][0],nodeinfo[i][1]))
nodes[i].setElement(elementInfo)
#print information related to each object
for phi in nodes:
print(vars(phi))
首先,使用matplotlib.tri.Triangulation(x, y, triangles)
创建一个非结构化的三角网格,其中:
x
是一个包含每个节点x坐标的一维列表;
y
是一维列表,包含每个节点的y坐标;
triangles
是一个“二维列表”,包含每个三角形的节点 (0
基于索引);
其次,使用 matplotlib.pyplot.triplot(triangulation, linespec)
仅绘制网格(仅线),其中:
triangulation
是matplotlib.tri.Triangulation(x, y, triangles)
创建的实例;
linespec
为行规范;
第三,使用matplotlib.pyplot.tricontourf(triangulation, scalars)
绘制标量场等高线,其中:
triangulation
是matplotlib.tri.Triangulation(x, y, triangles)
创建的实例;
scalars
包含节点标量数据的一维列表;
最后,使用matplotlib.pyplot.colorbar()
和matplotlib.pyplot.show()
。
完整代码:
import matplotlib.pyplot as plt
import matplotlib.tri as tri
nodes_x = [0.000, 1.000, 2.000, 0.000, 1.000, 1.750, 1.000]
nodes_y = [0.000, 0.000, 0.500, 1.000, 1.000, 1.300, 1.700]
scalars = [1.000, 2.000, 1.000, 2.000, 7.000, 4.000, 5.000]
elements = [
[0, 1, 4],
[4, 3, 0],
[1, 2, 5],
[5, 4, 1],
[3, 4, 6],
[4, 5, 6]
]
triangulation = tri.Triangulation(nodes_x, nodes_y, elements)
plt.triplot(triangulation, '-k')
plt.tricontourf(triangulation, scalars)
plt.colorbar()
plt.show()
输出:
如果你想可视化其他类型的二维元素(四边形或高阶元素),你必须先 "split" 将它们变成三角形。但是,如果你想可视化 3D 元素,或者如果你想让你的生活更轻松,你的代码更多 efficient/faster 大网格,你必须放弃 matplotlib 并使用 VTK 之类的东西。
编辑
检查我对以下问题的回答以绘制包含四边形的 FEM 网格:
我的问题很简单,但对于那些需要更多上下文的人,请参阅 wikipedia page on finite element methods。
我正在寻找使用 matplotlib 绘制网格的最有效方法,给出以下信息、每个节点的坐标、每个元素属于哪些节点以及每个节点具有的值。下面我有一些示例数据和图像显示网格的样子
nodeinfo=[[0.000,0.000],[1.000,0.000],[2.000,0.500],[0.000,1.000],
[1.000,1.000],[1.750,1.300],[1.000,1.700]]
elementInfo=[[1,2,5],[5,4,1],[2,3,6],[6,5,2],[4,5,7],[5,6,7]]
nodevalues=[1,2,1,2,7,4,5]
nodeinfo是每个节点的坐标(例如节点7有坐标(1,1.7)),elementInfo给出了每个元素由哪些节点组成(例如元素3有节点2,3,6),nodevalues给出了每个节点的值(例如节点 5 的值为 7)。
Using this info how can I plot meshes with matplotlib with a colour gradient showing the different values of the nodes(if possible it would be great if there was a colour gradient between nodes as each element is linear).
备注 如果您想使用它,请创建一些代码将信息组织到节点对象中。
class node:
# Initializer / Instance Attributes
def __init__(self, number, xCord, yCord):
self.number=number
self.value=1
self.isOnBoundary=False
self.xCord=xCord
self.yCord=yCord
self.boundaryType=None
self.element=[]
#makes all class variables callable
def __call__(self):
return self
def checkIfOnBoundary(self,boundarylist):
# Checks if the node is on the boundary when it is invoked
# If the node is not on the boundary then it is set to false
if self.number in boundarylist:
self.isOnBoundary=True
self.boundaryType=boundarylist[self.number][0]
if self.boundaryType == "Dirchlet":
self.value=boundarylist[self.number][1]
else:
self.isOnBoundary=False
def setElement(self,elementInfo):
#given a list in the form [element1,element2,...,elementn]
#where element1 is a list that contains all the nodes that are on that element
for element in elementInfo:
if self.number in element:
self.element.append(elementInfo.index(element)+1)
def setValue(self,value):
# changes the value of the node
self.value=value
def description(self):
return "Node Number: {}, Node Value: {}, Element Node Belongs to: {}, Is Node On the Boundary: {}".format(self.number, self.value, self.element, self.isOnBoundary)
nodeinfo=[[0.000,0.000],[1.000,0.000],[2.000,0.500],[0.000,1.000],
[1.000,1.000],[1.750,1.300],[1.000,1.700]]
elementInfo=[[1,2,5],[5,4,1],[2,3,6],[6,5,2],[4,5,7],[5,6,7]]
nodevalues=[1,2,1,2,7,4,5]
#create list of node objects which we will call on often
nodes=[]
for i in range(len(nodeinfo)):
print(i)
nodes.append(node(i+1,nodeinfo[i][0],nodeinfo[i][1]))
nodes[i].setElement(elementInfo)
#print information related to each object
for phi in nodes:
print(vars(phi))
首先,使用matplotlib.tri.Triangulation(x, y, triangles)
创建一个非结构化的三角网格,其中:
x
是一个包含每个节点x坐标的一维列表;y
是一维列表,包含每个节点的y坐标;triangles
是一个“二维列表”,包含每个三角形的节点 (0 基于索引);
其次,使用 matplotlib.pyplot.triplot(triangulation, linespec)
仅绘制网格(仅线),其中:
triangulation
是matplotlib.tri.Triangulation(x, y, triangles)
创建的实例;linespec
为行规范;
第三,使用matplotlib.pyplot.tricontourf(triangulation, scalars)
绘制标量场等高线,其中:
triangulation
是matplotlib.tri.Triangulation(x, y, triangles)
创建的实例;scalars
包含节点标量数据的一维列表;
最后,使用matplotlib.pyplot.colorbar()
和matplotlib.pyplot.show()
。
完整代码:
import matplotlib.pyplot as plt
import matplotlib.tri as tri
nodes_x = [0.000, 1.000, 2.000, 0.000, 1.000, 1.750, 1.000]
nodes_y = [0.000, 0.000, 0.500, 1.000, 1.000, 1.300, 1.700]
scalars = [1.000, 2.000, 1.000, 2.000, 7.000, 4.000, 5.000]
elements = [
[0, 1, 4],
[4, 3, 0],
[1, 2, 5],
[5, 4, 1],
[3, 4, 6],
[4, 5, 6]
]
triangulation = tri.Triangulation(nodes_x, nodes_y, elements)
plt.triplot(triangulation, '-k')
plt.tricontourf(triangulation, scalars)
plt.colorbar()
plt.show()
输出:
如果你想可视化其他类型的二维元素(四边形或高阶元素),你必须先 "split" 将它们变成三角形。但是,如果你想可视化 3D 元素,或者如果你想让你的生活更轻松,你的代码更多 efficient/faster 大网格,你必须放弃 matplotlib 并使用 VTK 之类的东西。
编辑
检查我对以下问题的回答以绘制包含四边形的 FEM 网格: