說明
plot3d格式是NASA制定並大量使用的CFD網格文件格式,在CFD編程過程中經常涉及到。本文利用Python語言編寫一個讀取plot3d文件,寫入plot3d文件的通用類,並利用vtk完成網格的顯示。
對於程序的說明
- 使用說明
在主函數中,寫入如下代碼:
# 新建對象
mesh = Mesh()
# 讀文件
fname = 'demo.fmt'
mesh.read(fname)
fname1 = "1111.dat"
mesh.write(fname1)
- 程序思路
定義Mesh類,包含有:
屬性:
1. 網格維度: DIM = 3
2. 網格塊數目: int BlockNum
3. 網格塊坐標數目:np.array([]) Block_list
4. 網格塊列表 list(Block)
方法:
1. setBlockNum: 設置網格塊數目
2. setBlockList: 設置網格塊數目
3. MeshInit: 創建mesh對象,給BlockNum和Block_list賦值
4. setBlock: 設置每一個塊的坐標和IBLANK
每個Block具有:
1. id,jd,kd: 三個方向上坐標數目
2. X,Y,Z: 三個方向的坐標分量(一維列陣)
3. IBlank:當前塊的IBlank值
源碼
# !/usr/bin/env python
# -*- coding:utf-8 -*-
import math
import numpy as np
class Block():
"""
描述Plot3d文件中的一個Block
"""
def __init__(self, ID, JD, KD):
self.id = ID
self.jd = JD
self.kd = KD
self.X = np.zeros(self.id)
self.Y = np.zeros(self.jd)
self.Z = np.zeros(self.kd)
self.IBlank = np.zeros(self.id * self.jd * self.kd)
def setX(self, x_list):
self.X = x_list
def setY(self, y_list):
self.Y = y_list
def setZ(self, z_list):
self.Z = z_list
def setBlank(self, blank_list):
self.IBlank = blank_list
def setXYZ(self, x_list, y_list, z_list):
self.X = x_list
self.Y = y_list
self.Z = z_list
class Mesh():
"""
描述一個plot3d網格文件
"""
def __init__(self):
self.DIM = 3
self.blockNum = 1
self.block_list = []
self.BLOCK = []
def setBlockNum(self, block_num):
self.blockNum = block_num
def setBlockList(self, block_list):
self.block_list = block_list
def MeshInit(self, block_num, block_list):
self.setBlockNum(block_num)
self.setBlockList(block_list)
for i in range(self.blockNum):
bl = Block(*self.block_list[3 * i:3 * (i + 1)])
self.BLOCK.append(bl)
def setBlock(self, i, coordinates_list, iblank_list):
self.BLOCK[i - 1].setXYZ(*coordinates_list)
self.BLOCK[i - 1].setBlank(iblank_list)
def check(self):
if len(self.block_list) != self.blockNum * self.DIM:
print("The Block Num and the Block list is not consistent.")
for i in range(self.blockNum):
block = self.BLOCK[i]
ID = block.id
JD = block.jd
KD = block.kd
pointNum = ID * JD * KD
flag = len(block.X) == pointNum and len(block.Y) == pointNum
flag = flag and len(block.Z) == pointNum
if not flag:
print("The point number is not consistent.")
def write(self, fname):
self.check()
data = ''
try:
with open(fname, 'w') as f:
# 寫入Block數目
line = '\t{:>8d}\n'
data += line.format(self.blockNum)
# f.write(line.format(self.blockNum))
line = '\t'
for i in range(len(self.block_list)):
line = line + '{' + str(i) + ':>8d}\t'
if (i + 1) % 6 == 0:
line += '\n\t'
line += '\n'
data += line.format(*self.block_list)
# f.write(line.format(*self.block_list))
for block in self.BLOCK:
# 循環寫入X,Y,Z坐標
for xi in [block.X, block.Y, block.Z]:
line = ' '
for i in range(len(xi)):
line = line + '{' + str(i) + ': 7E} '
if (i + 1) % 5 == 0:
line += '\n '
line += '\n'
data += line.format(*xi)
# f.write(line.format(*xi))
# 寫入iBlank
line = '\t'
for i in range(len(block.IBlank)):
line = line + '{' + str(i) + ': 9d}' + '\t'
if (i + 1) % 6 == 0:
line += '\n\t'
line += '\n'
data += line.format(*block.IBlank)
# f.write(line.format(*block.IBlank))
f.write(data)
except (BaseException):
print("寫出文件時發生錯誤!請檢查您的輸出數據結構。")
exit(1)
def read(self, fname):
try:
with open(fname, 'r') as f:
# 讀取塊號
line = f.readline().strip()
self.blockNum = int(line)
# 讀取block_list
num = math.ceil((self.DIM * self.blockNum) / 6)
line = ''
for i in range(num):
line += f.readline()
line = line.split()
block_list = np.array([int(i) for i in line])
self.block_list = block_list
# 初始化Mesh
self.MeshInit(self.blockNum, self.block_list)
# 讀取每個塊信息
for ibl in range(self.blockNum):
bl = self.BLOCK[ibl]
# 獲取block_list信息
bl.id, bl.jd, bl.kd = self.block_list[self.DIM *
ibl:self.DIM *
(ibl + 1)]
point_num = bl.id * bl.jd * bl.kd
num = math.ceil(point_num / 5)
# 獲得x
line = ''
for i in range(num):
line += f.readline()
line = line.split()
x_list = np.array([float(im) for im in line])
# 獲得y
line = ''
for i in range(num):
line += f.readline()
line = line.split()
y_list = np.array([float(im) for im in line])
# 獲得z
line = ''
for i in range(num):
line += f.readline()
line = line.split()
z_list = np.array([float(im) for im in line])
# 獲得iblank
line = ''
num = math.ceil(bl.id * bl.jd * bl.kd / 6)
for i in range(num):
line += f.readline()
line = line.split()
iblank_list = np.array([int(im) for im in line])
self.setBlock(ibl, [x_list, y_list, z_list], iblank_list)
except (BaseException):
pass
self.check()
def visual(self):
"""
顯示網格信息
"""
pass
if __name__ == '__main__':
mesh = Mesh()
# 讀文件
fname = 'demo.fmt'
mesh.read(fname)
fname1 = "1111.dat"
mesh.write(fname1)