plot3d网格读取写入与可视化


目录
  • 说明
  • 对于程序的说明
  • 源码


说明

plot3d格式是NASA制定并大量使用的CFD网格文件格式,在CFD编程过程中经常涉及到。本文利用Python语言编写一个读取plot3d文件,写入plot3d文件的通用类,并利用vtk完成网格的显示。

对于程序的说明

  1. 使用说明

在主函数中,写入如下代码:

# 新建对象
mesh = Mesh()

# 读文件
fname = 'demo.fmt'
mesh.read(fname)

fname1 = "1111.dat"
mesh.write(fname1)
  1. 程序思路

定义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)