-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathshock_model.py
106 lines (76 loc) · 5.42 KB
/
shock_model.py
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
# shock_model.py
import numpy as np
class ShockModel:
def __init__(self, C_viscosity):
# Initialize the ShockModel with the artificial viscosity coefficient (C_viscosity)
self.C_viscosity = C_viscosity
def compute_shock_properties(self, velocity, pressure, density):
# Implement shock-capturing methods to handle shocks in the flow field
# Compute the speed of sound in the flow
speed_of_sound = np.sqrt(pressure / density)
# Compute the local Mach number (e.g., magnitude of the velocity divided by the speed of sound)
local_mach_number = np.linalg.norm(velocity, axis=-1) / speed_of_sound
# Compute the artificial viscosity to capture shock waves
artificial_viscosity = self.C_viscosity * (grid_size * speed_of_sound) ** 2
# Apply the artificial viscosity to the velocity and pressure fields
velocity += artificial_viscosity[:, :, np.newaxis] * np.gradient(velocity, axis=(1, 2))
pressure += artificial_viscosity * np.sum(np.gradient(velocity, axis=1), axis=0)
def compute_fluxes(self):
# Compute fluxes for the fluid solver (e.g., mass, momentum, energy)
# Finite volume method for compressible flow
# Cell face areas (assuming uniform grid spacing in both x and y directions)
dx = 1.0 # Grid spacing in the x-direction
dy = 1.0 # Grid spacing in the y-direction
cell_face_area_x = dy
cell_face_area_y = dx
# Compute the convective fluxes (momentum fluxes) for each cell face
convective_flux_x = self.density * self.velocity[:, :, 0] * cell_face_area_x
convective_flux_y = self.density * self.velocity[:, :, 1] * cell_face_area_y
# Compute the diffusive fluxes (viscous fluxes) for each cell face using the turbulent viscosity
grad_u = np.gradient(self.velocity, axis=(1, 2))
diffusive_flux_x = -self.turbulent_viscosity * grad_u[0] * cell_face_area_x
diffusive_flux_y = -self.turbulent_viscosity * grad_u[1] * cell_face_area_y
# Compute the total fluxes (momentum fluxes) for each cell face
total_flux_x = convective_flux_x + diffusive_flux_x
total_flux_y = convective_flux_y + diffusive_flux_y
# Apply the fluxes to update the flow field variables using the finite volume method
delta_t = self.time_step
self.velocity[:, :, 0] += (delta_t / cell_face_area_x) * (np.roll(total_flux_x, -1, axis=1) - total_flux_x)
self.velocity[:, :, 1] += (delta_t / cell_face_area_y) * (np.roll(total_flux_y, -1, axis=0) - total_flux_y)
# For compressible flow, the density and pressure are updated based on mass and momentum fluxes.
# Note: The specific implementation may vary depending on the numerical scheme and fluid properties.
# Compute the mass fluxes for each cell face
mass_flux_x = self.density * self.velocity[:, :, 0] * cell_face_area_x
mass_flux_y = self.density * self.velocity[:, :, 1] * cell_face_area_y
# Apply the mass fluxes to update the density field
self.density += (delta_t / cell_face_area_x) * (np.roll(mass_flux_x, -1, axis=1) - mass_flux_x)
self.density += (delta_t / cell_face_area_y) * (np.roll(mass_flux_y, -1, axis=0) - mass_flux_y)
# Compute the energy fluxes for each cell face (assuming an energy equation is included in the fluid solver)
# energy_flux_x = ...
# energy_flux_y = ...
# self.energy += (delta_t / cell_face_area_x) * (np.roll(energy_flux_x, -1, axis=1) - energy_flux_x)
# self.energy += (delta_t / cell_face_area_y) * (np.roll(energy_flux_y, -1, axis=0) - energy_flux_y)
# Note: In this example, we have only shown the computation and update of mass and momentum fluxes.
# For compressible flow, additional steps would be needed to compute energy fluxes and update the energy field.
# ... (additional implementation specific to your compressible flow model)
def update_boundary_conditions(self):
# Update boundary conditions for each time step in the simulation
# Example: Outflow boundary condition (zero-gradient for pressure)
# Right boundary (outflow)
self.pressure[-1, :] = self.pressure[-2, :] # Zero-gradient for pressure
# Additional boundary conditions can be implemented based on the problem requirements.
# For example, specifying inflow, wall, or periodic boundary conditions.
# Note: The specific implementation of boundary conditions may vary depending on
# the flow problem, numerical method, and simulation domain characteristics.
def save_results_to_file(self):
# Save shock model results to files for post-processing and visualization
# Create a directory to store shock model results
if not os.path.exists("shock_model_results"):
os.makedirs("shock_model_results")
# Save shock model data at each time step
for t in range(self.num_time_steps):
# Save shock model data to a file (e.g., shock properties, shock wave profiles, etc.)
shock_properties_file = f"shock_model_results/shock_properties_t{t}.npy"
np.save(shock_properties_file, self.shock_properties)
# You can add other data to save here, depending on your specific shock model and analysis needs.
# You can implement additional methods and properties specific to your shock model as needed.