File size: 8,737 Bytes
bdce880
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
import vtk
import os
import numpy as np
from vtk.util.numpy_support import vtk_to_numpy
from scipy.spatial import ConvexHull


def unstructured_grid_data_to_poly_data(unstructured_grid_data):
    filter = vtk.vtkDataSetSurfaceFilter()
    filter.SetInputData(unstructured_grid_data)
    filter.Update()
    poly_data = filter.GetOutput()
    return poly_data, filter


def load_unstructured_grid_data(file_name):
    reader = vtk.vtkUnstructuredGridReader()
    reader.SetFileName(file_name)
    reader.Update()
    output = reader.GetOutput()
    return output


############## calculate rectangle ##############
def calculate_pos(pos):
    hull = ConvexHull(pos[:, :2])
    A = hull.volume
    return A


############## surf area ##############
def calculate_mesh_cell_area(unstructured_grid_data):
    # Read VTK file
    poly_data, _ = unstructured_grid_data_to_poly_data(unstructured_grid_data)

    # Get the points and cells
    points = poly_data.GetPoints()
    cells = poly_data.GetPolys()

    # Initialize an array to store point areas
    cell_areas = np.zeros(cells.GetNumberOfCells())

    # Iterate through cells to calculate areas
    cells.InitTraversal()
    cell = vtk.vtkIdList()
    id = 0
    while cells.GetNextCell(cell):
        # Check if the cell is a quadrilateral
        if cell.GetNumberOfIds() == 4:
            # Get the four vertices of the quadrilateral
            p1 = np.array(points.GetPoint(cell.GetId(0)))
            p2 = np.array(points.GetPoint(cell.GetId(1)))
            p3 = np.array(points.GetPoint(cell.GetId(2)))
            p4 = np.array(points.GetPoint(cell.GetId(3)))
            # Calculate the area of the quadrilateral
            area = 0.5 * (
                    np.linalg.norm(np.cross(p2 - p1, p3 - p1)) +
                    np.linalg.norm(np.cross(p3 - p1, p4 - p1))
            )

            # Add the area to each vertex of the quadrilateral
            cell_areas[id] += area
            id += 1

    return cell_areas


############## velocity gradient ##############
def calculate_cell_velocity_gradient(unstructured_grid_data, velocity):
    # Create a vtkDoubleArray for velocity
    velocity_data = vtk.vtkDoubleArray()
    velocity_data.SetNumberOfComponents(3)  # Assuming 3D velocity field
    velocity_data.SetNumberOfTuples(unstructured_grid_data.GetNumberOfPoints())
    velocity_data.SetName("Velocity")  # Replace "Velocity" with the desired array name

    # Set the velocity array values
    for i in range(unstructured_grid_data.GetNumberOfPoints()):
        velocity_data.SetTuple(i, velocity[i])

    # Add the velocity array to the point data
    unstructured_grid_data.GetPointData().AddArray(velocity_data)

    # Get the points and cell data (assuming velocity is stored as point data)
    poly_data, _ = unstructured_grid_data_to_poly_data(unstructured_grid_data)
    points = poly_data.GetPoints()

    # Initialize arrays to store velocity gradients
    grad_u = np.zeros((poly_data.GetNumberOfCells(), 3))  # Assuming 3D velocity field
    # Iterate through cells to calculate gradients
    cells = poly_data.GetPolys()
    cells.InitTraversal()
    cell = vtk.vtkIdList()
    id = 0
    while cells.GetNextCell(cell):
        # Check if the cell is a quadrilateral
        if cell.GetNumberOfIds() == 4:
            # Get the four vertices of the quadrilateral
            p1 = np.array(points.GetPoint(cell.GetId(0)))
            p2 = np.array(points.GetPoint(cell.GetId(1)))
            p3 = np.array(points.GetPoint(cell.GetId(2)))
            p4 = np.array(points.GetPoint(cell.GetId(3)))
            # Calculate the velocity at each vertex
            u1 = np.array(poly_data.GetPointData().GetArray("Velocity").GetTuple(cell.GetId(0)))
            u2 = np.array(poly_data.GetPointData().GetArray("Velocity").GetTuple(cell.GetId(1)))
            u3 = np.array(poly_data.GetPointData().GetArray("Velocity").GetTuple(cell.GetId(2)))
            u4 = np.array(poly_data.GetPointData().GetArray("Velocity").GetTuple(cell.GetId(3)))

            # Calculate the gradients using finite differences
            du_dx = (u2 - u1 + u3 - u4) / (np.linalg.norm(p2 - p1 + p3 - p4) + 1e-8)
            du_dy = (u3 - u1 + u4 - u2) / (np.linalg.norm(p3 - p1 + p4 - p2) + 1e-8)
            du_dz = (u4 - u1 + u2 - u3) / (np.linalg.norm(p4 - p1 + p2 - p3) + 1e-8)

            # Add the gradients to each vertex of the quadrilateral
            grad_u[id] += (du_dx + du_dy + du_dz)
            id += 1

    return grad_u


############## calculate drag ##############
def calculate_drag_force(cell_areas, surface_normals, pressure_array, velocity_gradients, dynamic_viscosity):
    # Calculate the pressure force component along the flow direction
    pressure_force_component = -np.dot(pressure_array.flatten() * cell_areas.flatten(), surface_normals.flatten())

    # Calculate the wall shear stress component along the flow direction
    wall_shear_stress_component = -np.dot(velocity_gradients.flatten() * cell_areas.flatten(),
                                          surface_normals.flatten()) * dynamic_viscosity
    # Sum the pressure force and wall shear stress components to get the total drag force
    drag_force = np.sum(pressure_force_component + wall_shear_stress_component)

    return drag_force


############## calculate norm ##############
def get_normal(unstructured_grid_data):
    poly_data, surface_filter = unstructured_grid_data_to_poly_data(unstructured_grid_data)
    normal_filter = vtk.vtkPolyDataNormals()
    normal_filter.SetInputData(poly_data)
    normal_filter.SetAutoOrientNormals(1)
    normal_filter.SetConsistency(1)
    normal_filter.SetComputeCellNormals(1)
    normal_filter.SetComputePointNormals(0)
    normal_filter.Update()
    return vtk_to_numpy(normal_filter.GetOutput().GetCellData().GetNormals())


############## calculate coefficient ##############
def cal_coefficient(file_name, press_surf=None, velo_surf=None):
    root = '/data/PDE_data/mlcfd_data/training_data'
    save_path = '/data/PDE_data/mlcfd_data/preprocessed_data/param0/' + file_name
    file_name_press = 'param0/' + file_name + '/quadpress_smpl.vtk'
    file_name_velo = 'param0/' + file_name + '/hexvelo_smpl.vtk'
    file_name_press = os.path.join(root, file_name_press)
    file_name_velo = os.path.join(root, file_name_velo)
    unstructured_grid_data_press = load_unstructured_grid_data(file_name_press)
    unstructured_grid_data_velo = load_unstructured_grid_data(file_name_velo)

    # normal
    normal_surf = get_normal(unstructured_grid_data_press)
    # front area
    points_surf = vtk_to_numpy(unstructured_grid_data_press.GetPoints().GetData())
    A = calculate_pos(points_surf)
    # mesh area
    cell_areas = calculate_mesh_cell_area(unstructured_grid_data_press)
    # mesh velo
    if velo_surf is None:
        velo = vtk_to_numpy(unstructured_grid_data_velo.GetPointData().GetVectors())
        points_velo = vtk_to_numpy(unstructured_grid_data_velo.GetPoints().GetData())
        velo_dict = {tuple(p): velo[i] for i, p in enumerate(points_velo)}
        velo_surf = np.array([velo_dict[tuple(p)] if tuple(p) in velo_dict else np.zeros(3) for p in points_surf])
    # gradient u
    grad_u = calculate_cell_velocity_gradient(unstructured_grid_data_press, velo_surf)
    # press
    if press_surf is None:
        c2p = vtk.vtkPointDataToCellData()
        c2p.SetInputData(unstructured_grid_data_press)
        c2p.Update()
        unstructured_grid_data_press = c2p.GetOutput()
        press_surf = vtk_to_numpy(unstructured_grid_data_press.GetCellData().GetScalars())
    else:
        # Create a vtkDoubleArray for press
        press_data = vtk.vtkDoubleArray()
        press_data.SetNumberOfComponents(1)  # Assuming 3D velocity field
        press_data.SetNumberOfTuples(unstructured_grid_data_press.GetNumberOfPoints())
        press_data.SetName("my_press")  # Replace "my_press" with the desired array name

        # Set the velocity array values
        for i in range(unstructured_grid_data_press.GetNumberOfPoints()):
            press_data.SetTuple(i, press_surf[i])

        # Add the velocity array to the point data
        unstructured_grid_data_press.GetPointData().AddArray(press_data)
        c2p = vtk.vtkPointDataToCellData()
        c2p.SetInputData(unstructured_grid_data_press)
        c2p.Update()
        unstructured_grid_data_press = c2p.GetOutput()
        press_surf = vtk_to_numpy(unstructured_grid_data_press.GetCellData().GetArray("my_press"))

    drag_force = calculate_drag_force(cell_areas, normal_surf[:, -1], press_surf, grad_u[:, -1], np.array(1.8e-5))
    nu = 72 / 3.6
    air_density = 0.3
    cd = (2 / ((nu ** 2) * A * air_density)) * drag_force
    return cd