<jupyter_start><jupyter_text>Tài liệu này mang giấy phép Creative Commons Attribution (CC BY). (c) <NAME> 06/2019.[@SangVn](https://github.com/SangVn) [@VnCFD](https://vncfdgroup.wordpress.com/)*Thực hành CFD với Python!*  Bài 24. Bài toán dòng chảy quanh hình trụ, NACA0012, Crew Dragon. Điều kiện biên *joint, farfield*.Để giải một bài toán bất kì, ta cần thay đổi: **lưới và thông số trong module setup**.  1. Dòng chảy quanh hình trụ**Bài toán:** Xác định dòng chảy quanh hình trụ bán kính 1m với thông số dòng chảy tự do: $T=293.15 (K), (u,v) = (40, 0) (m/s), p = 101325 (Pa)$ a. Tạo lưới Để sử dụng các hàm tạo dữ liệu Cells, Sides đòi hỏi ta tạo lưới **đúng thứ tự quy ước** như khi tạo lưới cho bài toán dòng chảy trên âm. Tức là cần tạo lưới có các `biên` như trên hình (thứ tự theo chiều chỉ số i, j: biên 0, 1, 2, 3):Đối với dòng chảy bao khi tạo lưới cần chú ý đến kích thước (độ dày) của lớp ô lưới đầu tiên trên bề mặt và tỉ lệ tăng kích thước này của hai lớp kế tiếp (thông thường lấy bằng 1.2).<jupyter_code># %cd lib
import numpy as np
import matplotlib.pyplot as plt
from functions import export_mesh

# Tạo lưới bài toán dòng chảy quanh hình trụ
def generate_mesh_cylinder(Nj, Ni):
    # chia góc 2Pi ra thành Ni điểm lưới 
    alpha = np.linspace(0.0, -2*np.pi, Ni)
    
    # bán kính tại các điểm lưới  
    r = np.zeros(Nj)
    r[0] = 1.0  # bán kính hình trụ 
    dr = 1e-2   # kích thước ('dộ dày') ô lưới đầu tiên sát biên (bề mặt trụ)
    ratio = 1.2 # tỷ lệ tăng kích thước ô lưới 
    for j in range(1, Nj):
        r[j] = r[j-1]+dr
        dr *= ratio 
    
    # tạo độ điểm lưới 
    points = np.zeros((Nj, Ni, 2))
    for j in range(Nj):
        for i in range(Ni):
            points[j, i, 0] = r[j]*np.cos(alpha[i])
            points[j, i, 1] = r[j]*np.sin(alpha[i])
    return points
Nj = 41
Ni = 61
points = generate_mesh_cylinder(Nj, Ni)
plt.plot(points[:, :, 0], points[:, :, 1], 'r+')
plt.show()
# export_mesh(Nj, Ni, points, 'data/mesh_cylinder.dat')<jupyter_output><empty_output><jupyter_text>b. Điều kiện biênĐối với bài toán dòng chảy trên âm ta có 4 điều kiện biên `(0, 1, 2, 3)` lần lượt là `(supersonic_inflow, supersonic_outflow, wall, wall)`. Còn với bài toán này thì sao? Dễ dàng nhận thấy: điều kiện tại `biên 2` là `wall`, `biên 0 và 1` trùng nhau ta gọi là `joint` (hay `điều kiện biên tuần hoàn`), `biên 3` ở xa bề mặt trụ ta gọi là `farfield` (khi tạo lưới chú ý để biên 3 ở `đủ xa` bề mặt trụ).- **Điều kiện 'joint'**:`ô lưới bên trái biên 0 chính là ô lưới bên trái biên 1, ô lưới bên phải bên 1 chính là ô lưới bên phải biên 0 hay là side_0.cells[0] = side_1.cells[0], side_1.cells[1] = side_0.cells[1]` và khi đó các side ở trên biên trở thành inner_side (có đầy đủ hai ô lưới hai bên trái phải).- **Điều kiện 'farfield'**:`nếu hướng vận tốc tại ô lưới phía trong biên là chảy vào thì thông số trên biên bằng thông số dòng tự do, ngược lại - thông số trên biên bằng thông số của ô lưới sát biên`:Thêm vào định nghĩa lớp Sides và module boco các hàm sau:<jupyter_code># Thêm vào định nghĩa lớp Sides, module 'data.py'

# Trường hợp điều kiện biên tuần hoàn
def set_joint(self, boundary_0, boundary_1):
    for side_0, side_1 in zip(boundary_0, boundary_1):
        side_0.cells[0] = side_1.cells[0] # set ô lưới bên trái của các side biên 0
        self.inner_sides.append(side_0)   # side_0 trở thành inner_side 
# Thêm vào module boco.py

# Điều kiện biên farfield
def farfield(boundary, ic):
    for side in boundary:
        V_in = side.cells[ic].P[1:3]  # vận tốc tại ô lưới phía trong biên 
        Vn = -sign_ic(ic)*side.normal.dot(V_in)  # hướng vận tốc so với phương pháp tuyến (quay ra) của biên 
        if Vn >= 0: # chảy ra
            F = P2F(side.cells[ic].P, side)
        else: # chảy vào 
            F = P2F(P_freestream, side)
        side.cells[ic].res += sign_ic(ic) * F

# Điều kiện biên joint
def joint(boundary, ic):
    pass # vì các side trên biên đã trở thành inner_side nên không phải làm gì hết tại đây 

# ta có `từ điển` điều kiện biên: <tên gọi> : <<NAME>>
boco_dict = {'supersonic_inflow': supersonic_inflow, 'supersonic_outflow': supersonic_outflow, 'wall': wall_no_slip, \
             'farfield': farfield, 'joint': joint}<jupyter_output><empty_output><jupyter_text>c. setupTrong module setup ta thay đổi các thông thông số cần thiết:<jupyter_code># coding: utf-8
# Module setup.py

from numpy import array
from fluxes import flux_roe
from boco import boco_dict, set_freestream
from functions import P2U, rho

# cylinder
P_freestream = array([rho(293.15, 101325.0), 40, 0.0, 101325.0]) # freestream

def init_field(cells):
    P_t0 = P_freestream
    U_t0 = P2U(P_t0)
    for cell in cells[:]:
        cell.P = P_t0.copy()
        cell.U = U_t0.copy()
    
# điều kiện biên
def set_boco(sides):
    set_freestream(P_freestream)
    boco_name = ['joint', 'joint', 'wall', 'farfield']
    boco_func = [boco_dict[name] for name in boco_name]
    sides.set_joint(sides.boundary_0, sides.boundary_1)
    sides.set_boco(boco_func)

# các thông số khác
CFL = 0.45
time_target = 1.0
iter_target = None 

write_field_iter = 1000 # thời điểm ghi kết quả giữa chừng
flux_func = flux_roe

mesh_filename = 'data/cylinder_mesh.dat'
field_filename = 'data/cylinder_cell_data.dat'<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10737240075614367, 'fraction_numerical': 0.02608695652173913, 'mean_word_length': 3.3799668874172184, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '573983', 'license': 'CC-BY-3.0', 'n_tokens_mistral': 2750, 'n_tokens_neox': 2666, 'n_words': 752, 'path': 'Bai_24.ipynb', 'repo_name': 'SangVn/CFD_Notebook_P3', 'size': '5312'}