OpenFOAMデータのプロット#

import pyvista
from pyvista import examples

この例では,天井駆動のcavity流れのデータを使用しています. OpenFOAMファイルの読み込みには,データの読み込みをよりコントロールするために, pyvista.POpenFOAMReader を使用することをお勧めします.

この例は,vtk>=9.1.0のバージョンでのみ正しく動作します.それ以前のバージョンでは,パッチ配列の名前と,読み込んだメッシュのキーの結果が異なります.

filename = examples.download_cavity(load=False)
reader = pyvista.POpenFOAMReader(filename)

OpenFOAMのデータセットには,内部メッシュやパッチ,通常は境界を含む複数のサブデータセットが含まれています.これは,データを読み込む前に検査することができます.

print(f"All patch names: {reader.patch_array_names}")
print(f"All patch status: {reader.all_patch_arrays_status}")
All patch names: ['internalMesh', 'patch/movingWall', 'patch/fixedWalls', 'patch/frontAndBack']
All patch status: {'internalMesh': True, 'patch/movingWall': True, 'patch/fixedWalls': True, 'patch/frontAndBack': True}

このデータは pyvista.MultiBlock オブジェクトとして表現されます.内部のメッシュは,トップレベルのMultiBlockメッシュに配置されます.

mesh = reader.read()
print(f"Mesh patches: {mesh.keys()}")
internal_mesh = mesh["internalMesh"]  # or internal_mesh = mesh[0]
Mesh patches: ['internalMesh', 'boundary']

この場合,内部メッシュは pyvista.UnstructuredGrid となります.

print(internal_mesh)
UnstructuredGrid (0x7f21c0e863e0)
  N Cells:    400
  N Points:   882
  X Bounds:   0.000e+00, 1.000e-01
  Y Bounds:   0.000e+00, 1.000e-01
  Z Bounds:   0.000e+00, 1.000e-02
  N Arrays:   4

追加のPatchメッシュは,別のMultiBlockメッシュの中に入れ子になっています.サブレベルのMultiBlockメッシュの名前は,vtkのバージョンによって異なります.

boundaries = mesh["boundary"]
print(boundaries)
print(f"Boundaries patches: {boundaries.keys()}")
print(boundaries["movingWall"])
MultiBlock (0x7f21661bb3a0)
  N Blocks    3
  X Bounds    0.000, 0.100
  Y Bounds    0.000, 0.100
  Z Bounds    0.000, 0.010
Boundaries patches: ['movingWall', 'fixedWalls', 'frontAndBack']
PolyData (0x7f21661ba380)
  N Cells:    20
  N Points:   42
  N Strips:   0
  X Bounds:   0.000e+00, 1.000e-01
  Y Bounds:   1.000e-01, 1.000e-01
  Z Bounds:   0.000e+00, 1.000e-02
  N Arrays:   4

OpenFOAMReaderのデフォルトでは,既存のセルデータをポイントデータに変換します.そのため,セルデータの配列はポイントデータに複製されます.

print("Cell Data:")
print(internal_mesh.cell_data)
print("\nPoint Data:")
print(internal_mesh.point_data)
Cell Data:
pyvista DataSetAttributes
Association     : CELL
Active Scalars  : p
Active Vectors  : U
Active Texture  : None
Active Normals  : None
Contains arrays :
    U                       float32    (400, 3)             VECTORS
    p                       float32    (400,)               SCALARS

Point Data:
pyvista DataSetAttributes
Association     : POINT
Active Scalars  : p
Active Vectors  : U
Active Texture  : None
Active Normals  : None
Contains arrays :
    U                       float32    (882, 3)             VECTORS
    p                       float32    (882,)               SCALARS

セルデータのみが必要な場合は,この動作をオフにすることができます.

reader.cell_to_point_creation = False
internal_mesh = reader.read()["internalMesh"]
print("Cell Data:")
print(internal_mesh.cell_data)
print("\nPoint Data:")
print(internal_mesh.point_data)
Cell Data:
pyvista DataSetAttributes
Association     : CELL
Active Scalars  : p
Active Vectors  : U
Active Texture  : None
Active Normals  : None
Contains arrays :
    U                       float32    (400, 3)             VECTORS
    p                       float32    (400,)               SCALARS

Point Data:
pyvista DataSetAttributes
Association     : POINT
Active Scalars  : None
Active Vectors  : None
Active Texture  : None
Active Normals  : None
Contains arrays : None

ここで,最後の時刻でのすべてのデータを読み込んでみます.

print(f"Available Time Values: {reader.time_values}")
reader.set_active_time_value(2.5)
reader.cell_to_point_creation = True  # Need point data for streamlines
mesh = reader.read()
internal_mesh = mesh["internalMesh"]
boundaries = mesh["boundary"]
Available Time Values: [0.0, 0.5, 1.0, 1.5, 2.0, 2.5]

このOpenFOAMシミュレーションは,z方向に1つのセルしかない3Dである. pyvista.DataSetFilters.streamlines_evenly_spaced_2D() では,データがz=0の平面上にあることが必要です.そのため,領域をスライスした後, z=0 に変換します.

def slice_z_center(mesh):
    """Slice mesh through center in z normal direction, move to z=0."""
    slice_mesh = mesh.slice(normal='z')
    slice_mesh.translate((0, 0, -slice_mesh.center[-1]), inplace=True)
    return slice_mesh


slice_internal_mesh = slice_z_center(internal_mesh)
slice_boundaries = pyvista.MultiBlock(
    {key: slice_z_center(boundaries[key]) for key in boundaries.keys()}
)

流線はポイントデータ "U" を使って生成されます.

streamlines = slice_internal_mesh.streamlines_evenly_spaced_2D(
    vectors='U',
    start_position=(0.05, 0.05, 0),
    separating_distance=1,
    separating_distance_ratio=0.1,
)

速度の大きさで色分けされた流線をプロットします.さらに,移動壁と固定壁の境界線をプロットしています.

plotter = pyvista.Plotter()
plotter.add_mesh(slice_boundaries["movingWall"], color='red', line_width=3)
plotter.add_mesh(slice_boundaries["fixedWalls"], color='black', line_width=3)
plotter.add_mesh(streamlines.tube(radius=0.0005), scalars="U")
plotter.view_xy()
plotter.enable_parallel_projection()
plotter.show()
openfoam example

Total running time of the script: (0 minutes 0.769 seconds)

Sphinx-Galleryによるギャラリー