|
| 1 | +""" |
| 2 | +GSPH Sod Shock Tube Simulation with VTK Output |
| 3 | +=============================================== |
| 4 | +
|
| 5 | +Runs the Sod shock tube test using Godunov SPH (GSPH) with HLLC Riemann solver |
| 6 | +and outputs VTK files for visualization. |
| 7 | +
|
| 8 | +Uses the same initial conditions as the SPH Sod test for direct comparison. |
| 9 | +
|
| 10 | +Output: VTK files in output/ directory with simulation time metadata |
| 11 | +""" |
| 12 | + |
| 13 | +import json |
| 14 | +import os |
| 15 | + |
| 16 | +import shamrock |
| 17 | + |
| 18 | +# Physical parameters (same as SPH test) |
| 19 | +gamma = 1.4 |
| 20 | + |
| 21 | +rho_L = 1.0 # Left density |
| 22 | +rho_R = 0.125 # Right density |
| 23 | + |
| 24 | +P_L = 1.0 # Left pressure |
| 25 | +P_R = 0.1 # Right pressure |
| 26 | + |
| 27 | +# Derived quantities |
| 28 | +fact = (rho_L / rho_R) ** (1.0 / 3.0) |
| 29 | +u_L = P_L / ((gamma - 1) * rho_L) # Left internal energy |
| 30 | +u_R = P_R / ((gamma - 1) * rho_R) # Right internal energy |
| 31 | + |
| 32 | +# Resolution (same as SPH test) |
| 33 | +resol = 128 |
| 34 | + |
| 35 | +# Initialize context and model |
| 36 | +ctx = shamrock.Context() |
| 37 | +ctx.pdata_layout_new() |
| 38 | + |
| 39 | +# Use GSPH model with M6 kernel (same as SPH test) |
| 40 | +model = shamrock.get_Model_GSPH(context=ctx, vector_type="f64_3", sph_kernel="M6") |
| 41 | + |
| 42 | +# Configure solver |
| 43 | +cfg = model.gen_default_config() |
| 44 | + |
| 45 | +# Set HLLC Riemann solver |
| 46 | +cfg.set_riemann_hllc() |
| 47 | + |
| 48 | +# Set piecewise constant reconstruction (first-order, most stable) |
| 49 | +cfg.set_reconstruct_piecewise_constant() |
| 50 | + |
| 51 | +# Set periodic boundaries (with wall particles for shock tube) |
| 52 | +cfg.set_boundary_periodic() |
| 53 | + |
| 54 | +# Set adiabatic EOS |
| 55 | +cfg.set_eos_adiabatic(gamma) |
| 56 | + |
| 57 | +# Print configuration |
| 58 | +cfg.print_status() |
| 59 | +model.set_solver_config(cfg) |
| 60 | + |
| 61 | +model.init_scheduler(int(1e8), 1) |
| 62 | + |
| 63 | +# Setup domain (same as SPH test) |
| 64 | +(xs, ys, zs) = model.get_box_dim_fcc_3d(1, resol, 24, 24) |
| 65 | +dr = 1 / xs |
| 66 | +(xs, ys, zs) = model.get_box_dim_fcc_3d(dr, resol, 24, 24) |
| 67 | + |
| 68 | +model.resize_simulation_box((-xs, -ys / 2, -zs / 2), (xs, ys / 2, zs / 2)) |
| 69 | + |
| 70 | +# Setup initial conditions using HCP lattice (same as SPH test) |
| 71 | +# Left side: high density (smaller spacing) |
| 72 | +model.add_cube_hcp_3d(dr, (-xs, -ys / 2, -zs / 2), (0, ys / 2, zs / 2)) |
| 73 | +# Right side: low density (larger spacing) |
| 74 | +model.add_cube_hcp_3d(dr * fact, (0, -ys / 2, -zs / 2), (xs, ys / 2, zs / 2)) |
| 75 | + |
| 76 | +# Set internal energy |
| 77 | +model.set_value_in_a_box("uint", "f64", u_L, (-xs, -ys / 2, -zs / 2), (0, ys / 2, zs / 2)) |
| 78 | +model.set_value_in_a_box("uint", "f64", u_R, (0, -ys / 2, -zs / 2), (xs, ys / 2, zs / 2)) |
| 79 | + |
| 80 | +# Set particle mass (same as SPH test) |
| 81 | +vol_b = xs * ys * zs |
| 82 | +totmass = (rho_R * vol_b) + (rho_L * vol_b) |
| 83 | +pmass = model.total_mass_to_part_mass(totmass) |
| 84 | +model.set_particle_mass(pmass) |
| 85 | + |
| 86 | +print(f"Total mass: {totmass}") |
| 87 | +print(f"Particle mass: {pmass}") |
| 88 | + |
| 89 | +# Set CFL conditions (same as SPH test) |
| 90 | +model.set_cfl_cour(0.1) |
| 91 | +model.set_cfl_force(0.1) |
| 92 | + |
| 93 | +# Simulation parameters (same as SPH test) |
| 94 | +t_final = 0.245 |
| 95 | +n_outputs = 50 |
| 96 | +dt_output = t_final / n_outputs |
| 97 | + |
| 98 | +# Track output times |
| 99 | +times = [] |
| 100 | +output_count = 0 |
| 101 | + |
| 102 | +# Create output directory |
| 103 | +os.makedirs("output", exist_ok=True) |
| 104 | + |
| 105 | +# Initial output |
| 106 | +filename = f"output/gsph_sod_{output_count:04d}.vtk" |
| 107 | +model.do_vtk_dump(filename, True) |
| 108 | +times.append({"index": output_count, "time": 0.0, "file": filename}) |
| 109 | +print(f"Saved: {filename} (t = 0.0)") |
| 110 | +output_count += 1 |
| 111 | + |
| 112 | +# Time evolution with outputs |
| 113 | +t_current = 0.0 |
| 114 | +t_next_output = dt_output |
| 115 | + |
| 116 | +while t_current < t_final: |
| 117 | + # Evolve to next output time or final time |
| 118 | + t_target = min(t_next_output, t_final) |
| 119 | + model.evolve_until(t_target) |
| 120 | + t_current = t_target |
| 121 | + |
| 122 | + # Output VTK |
| 123 | + filename = f"output/gsph_sod_{output_count:04d}.vtk" |
| 124 | + model.do_vtk_dump(filename, True) |
| 125 | + times.append({"index": output_count, "time": t_current, "file": filename}) |
| 126 | + print(f"Saved: {filename} (t = {t_current:.6f})") |
| 127 | + output_count += 1 |
| 128 | + |
| 129 | + t_next_output += dt_output |
| 130 | + |
| 131 | +# Save times metadata |
| 132 | +with open("output/times_gsph_sod.json", "w") as f: |
| 133 | + json.dump( |
| 134 | + { |
| 135 | + "method": "GSPH", |
| 136 | + "riemann_solver": "HLLC", |
| 137 | + "kernel": "M6", |
| 138 | + "gamma": gamma, |
| 139 | + "rho_L": rho_L, |
| 140 | + "rho_R": rho_R, |
| 141 | + "P_L": P_L, |
| 142 | + "P_R": P_R, |
| 143 | + "t_final": t_final, |
| 144 | + "outputs": times, |
| 145 | + }, |
| 146 | + f, |
| 147 | + indent=2, |
| 148 | + ) |
| 149 | + |
| 150 | +print(f"\nSimulation complete! {output_count} VTK files saved to output/") |
| 151 | +print("\nNote: L2 error analysis not available for GSPH model.") |
| 152 | +print("Use post-processing scripts for comparison with analytical solution.") |
0 commit comments