3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

2次元熱拡散シミュレーション結果をPython VTKで出力する

Last updated at Posted at 2020-06-01

はじめに

熱拡散シミュレーションで得たndarray形式の2次元格子の温度データを、VTKデータで出力する方法を記載します。

方法

Python VTKライブラリを利用して、StructuredGrid形式で出力します。

環境 

  • Windows 10 home(FEniCSの計算ではWSLを利用)
  • Anaconda(python 3.7.6)
  • FEniCS 2018

シミュレーション結果

温度拡散シミュレーションは、次の熱拡散方程式をPythonインターフェースのFEniCSを利用して、有限要素法で計算しました。
$$
\frac{\partial}{\partial t} u = \alpha\nabla ^2 u
$$
$u$:温度スカラー $\alpha$:熱拡散係数です。計算結果は、次の図のようになります。
result.png
図:計算結果

FEniCSは、以下の記事を参考にしてください。
https://qiita.com/matsxxx/items/b696d2fe730be1683d8d
今回利用したシミュレーション結果を作るコードは、以下になります。

import fenics as fe
import numpy as np

tol = 1e-14 #
Lx = 80 #x方向長さ
Ly = 100 #y方向長さ
Nx = 80 #x軸セル数
Ny = 100 #y軸セル数
T = 10.0 #計算する時間
num_steps = 10 #時間ステップ
dt = T/num_steps #時間刻み
alpha = 100.#熱拡散係数

# メッシュ作成
mesh = fe.RectangleMesh(fe.Point(0, 0), fe.Point(Lx, Ly), Nx, Ny)
V = fe.FunctionSpace(mesh, "P", 1)#有限要素空間

# fenicsの配列を並べ替えるのに利用する。
vertex_to_dof_map = fe.vertex_to_dof_map(V)

# 境界条件の位置設定
def boundary_right(x, on_boundary):
    #x[0]:x座標、x[1]:y座標
    return on_boundary and fe.near(x[0], Lx, tol)


def boundary_top(x, on_boundary):
    #x[0]:x座標、x[1]:y座標
    return on_boundary and fe.near(x[1], Ly, tol)

# 第一種境界条件の設定
bc_right = fe.DirichletBC(V, fe.Constant(100), boundary_right)#Lx側を100℃
bc_top = fe.DirichletBC(V, fe.Constant(80), boundary_top)#Ly側を80℃

# 試行/試験関数の設定
u = fe.TrialFunction(V) #解きたい変数
v = fe.TestFunction(V) #重み関数

# 初期条件
u_0 = fe.Expression('0',degree=2)#初期温度0
u_n = fe.interpolate(u_0, V)

# 変分法の熱拡散方程式
F= u * v * fe.dx + alpha * dt * fe.dot(fe.grad(u), fe.grad(v)) * fe.dx - (u_n) * v * fe.dx 
a, L = fe.lhs(F), fe.rhs(F)

# 変数
u = fe.Function(V)
t = 0#時間

# 非定常計算の実行
for n in range(num_steps):
    #時間更新
    t += dt
    
    #方程式を解く
    fe.solve(a == L, u, [bc_right, bc_top])
    
    #解を更新
    u_n.assign(u)

# 最終結果をndarrayで取り出す。
u_np_temp = u.vector().get_local()
# fenics内の変数の並びからT[0,0], T[0,1]・・・T[Nx-1,Ny-2],T[Nx-1,Ny-1]の並びに変換
u_np = np.zeros_like(u_np_temp)
for i,v in enumerate(vertex_to_dof_map):
    u_np[i] = u_np_temp[v]
    
# npyで保存
np.save("solution", u_np)

# fenicsにはVTKデータで出力することが可能なので、通常はこちらを使う。
# vtk = fe.File("output.pvd")
# vtk << u

VTKライブラリを用いた出力

ndarray形式のシミュレーション結果を、VTKライブラリのStructuredGrid形式で出力します。

import numpy as np
import vtk
Nx = 80
Ny = 100

# シミュレーション結果読み込み
u = np.load("solution.npy")

# 点データの作成
points = vtk.vtkPoints()

for iy in range(Ny+1):
    for ix in range(Nx+1):
        x = ix 
        y = iy
        points.InsertNextPoint(x,y,0)#2次元なので、z座標は0にする
    
# 点データをstructuredGridにセットする
structured_mesh = vtk.vtkStructuredGrid()
structured_mesh.SetExtent(0, Nx, 0, Ny, 0, 0)
structured_mesh.SetPoints(points)

# 温度データをvtk arrayに入力する
temp_value = vtk.vtkDoubleArray()
temp_value.SetName("Temperature")
for t in u:
    temp_value.InsertNextValue(t)
# StructuredGridのPointDataに温度データを追加
structured_mesh.GetPointData().AddArray(temp_value)

# データ出力
writer = vtk.vtkXMLDataObjectWriter()
writer.SetFileName("temperature.vts")
writer.SetInputData(structured_mesh)
writer.Update()

おまけ:PyEVTKを利用して出力

VTKデータで出力するだけなら、PyEVTKを利用したほうが簡単です。

import numpy as np 
import evtk

Nx = 80
Ny = 100
u = np.load("solution.npy")
u = u.reshape(Ny+1, -1)#x,yの並び注意
u = u[:,:,np.newaxis]

# meshgridで座標作成
x = np.arange(0, Nx+1)
y = np.arange(0, Ny+1)
X, Y = np.meshgrid(x,y)
X = X[:,:,np.newaxis]
Y = Y[:,:,np.newaxis]

Z = np.zeros_like(X)#2次元のため、Z座標は0

evtk.hl.gridToVTK("temperature_evtk", X, Y, Z, pointData={"temperature":u})
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?