Shamrock 2025.10.0
Astrophysical Code
Loading...
Searching...
No Matches
iterative.hpp
Go to the documentation of this file.
1// -------------------------------------------------------//
2//
3// SHAMROCK code for hydrodynamics
4// Copyright (c) 2021-2026 Timothée David--Cléris <tim.shamrock@proton.me>
5// SPDX-License-Identifier: CeCILL Free Software License Agreement v2.1
6// Shamrock is licensed under the CeCILL 2.1 License, see LICENSE for more information
7//
8// -------------------------------------------------------//
9
10#pragma once
11
32
33#include "shambackends/math.hpp"
34#include "shambackends/sycl.hpp"
35
36namespace shammodels::gsph::riemann {
37
44 template<class Tscal>
46 Tscal p_star;
47 Tscal v_star;
48 };
49
74 template<class Tscal>
76 Tscal u_L,
77 Tscal rho_L,
78 Tscal p_L,
79 Tscal u_R,
80 Tscal rho_R,
81 Tscal p_R,
82 Tscal gamma,
83 Tscal tol = Tscal{1.0e-6},
84 u32 max_iter = 20) {
85
86 RiemannResult<Tscal> result;
87
88 // Safety check for non-physical values
89 const Tscal smallp = Tscal{1.0e-25};
90 const Tscal smallrho = Tscal{1.0e-25};
91
92 if (rho_L < smallrho || rho_R < smallrho || p_L < smallp || p_R < smallp) {
93 // Return acoustic approximation for near-vacuum
94 result.p_star = sycl::fmax(smallp, Tscal{0.5} * (p_L + p_R));
95 result.v_star = Tscal{0.5} * (u_L + u_R);
96 return result;
97 }
98
99 // Derived constants
100 const Tscal gm1 = gamma - Tscal{1};
101 const Tscal gp1 = gamma + Tscal{1};
102 const Tscal gamma1 = Tscal{0.5} * gp1 / gamma; // (gamma+1)/(2*gamma)
103
104 // Specific volumes
105 const Tscal V_L = Tscal{1} / rho_L;
106 const Tscal V_R = Tscal{1} / rho_R;
107
108 // Lagrangian sound speeds: c_lag = sqrt(gamma * p * rho)
109 const Tscal c_L = sycl::sqrt(gamma * p_L * rho_L);
110 const Tscal c_R = sycl::sqrt(gamma * p_R * rho_R);
111
112 // Initial guess for p_star using PVRS (Primitive Variable Riemann Solver)
113 // p_star = p_L + (p_R - p_L - c_R*(u_R - u_L)) * c_L / (c_L + c_R)
114 Tscal p_star = p_R - p_L - c_R * (u_R - u_L);
115 p_star = p_L + p_star * c_L / (c_L + c_R);
116 p_star = sycl::fmax(p_star, smallp);
117
118 // Newton-Raphson iteration
119 for (u32 iter = 0; iter < max_iter; ++iter) {
120 const Tscal p_star_old = p_star;
121
122 // Left wave impedance: W_L = c_L * sqrt(1 + gamma1*(p_star - p_L)/p_L)
123 Tscal W_L = Tscal{1} + gamma1 * (p_star - p_L) / p_L;
124 W_L = c_L * sycl::sqrt(sycl::fmax(W_L, smallp));
125
126 // Right wave impedance: W_R = c_R * sqrt(1 + gamma1*(p_star - p_R)/p_R)
127 Tscal W_R = Tscal{1} + gamma1 * (p_star - p_R) / p_R;
128 W_R = c_R * sycl::sqrt(sycl::fmax(W_R, smallp));
129
130 // Derivatives dW/dp for Newton-Raphson
131 // Z_L = -dW_L/dp * W_L (note the sign convention)
132 // Add smallp to denominator to prevent division by zero near vacuum/shock
133 Tscal Z_L = Tscal{4} * V_L * W_L * W_L;
134 Z_L = -Z_L * W_L / (Z_L - gp1 * (p_star - p_L) + smallp);
135
136 // Z_R = dW_R/dp * W_R
137 Tscal Z_R = Tscal{4} * V_R * W_R * W_R;
138 Z_R = Z_R * W_R / (Z_R - gp1 * (p_star - p_R) + smallp);
139
140 // Intermediate velocities from each side
141 // u*_L = u_L - (p* - p_L) / W_L
142 // u*_R = u_R + (p* - p_R) / W_R
143 const Tscal ustar_L = u_L - (p_star - p_L) / W_L;
144 const Tscal ustar_R = u_R + (p_star - p_R) / W_R;
145
146 // Newton-Raphson update: p_new = p - f(p)/f'(p)
147 // where f(p) = u*_R - u*_L (velocity mismatch)
148 // and f'(p) = du*_R/dp - du*_L/dp = 1/Z_R - 1/Z_L
149 const Tscal denom = Z_R - Z_L;
150 if (sycl::fabs(denom) > smallp) {
151 p_star = p_star + (ustar_R - ustar_L) * (Z_L * Z_R) / denom;
152 }
153 p_star = sycl::fmax(smallp, p_star);
154
155 // Check convergence
156 if (sycl::fabs(p_star - p_star_old) / p_star < tol) {
157 break;
158 }
159 }
160
161 // Recalculate wave impedances with final p_star
162 Tscal W_L = Tscal{1} + gamma1 * (p_star - p_L) / p_L;
163 W_L = c_L * sycl::sqrt(sycl::fmax(W_L, smallp));
164
165 Tscal W_R = Tscal{1} + gamma1 * (p_star - p_R) / p_R;
166 W_R = c_R * sycl::sqrt(sycl::fmax(W_R, smallp));
167
168 // Calculate final u_star (average of left and right estimates)
169 const Tscal ustar_L = u_L - (p_star - p_L) / W_L;
170 const Tscal ustar_R = u_R + (p_star - p_R) / W_R;
171 const Tscal u_star = Tscal{0.5} * (ustar_L + ustar_R);
172
173 result.p_star = p_star;
174 result.v_star = u_star;
175
176 return result;
177 }
178
195 template<class Tscal>
197 Tscal u_L, Tscal rho_L, Tscal p_L, Tscal u_R, Tscal rho_R, Tscal p_R, Tscal gamma) {
198
200 const Tscal smallval = Tscal{1.0e-25};
201
202 // Compute Eulerian sound speeds
203 const Tscal c_L = sycl::sqrt(gamma * p_L / sycl::fmax(rho_L, smallval));
204 const Tscal c_R = sycl::sqrt(gamma * p_R / sycl::fmax(rho_R, smallval));
205
206 // Roe averages for wave speed estimates
207 const Tscal sqrt_rho_L = sycl::sqrt(rho_L);
208 const Tscal sqrt_rho_R = sycl::sqrt(rho_R);
209 const Tscal roe_inv = Tscal{1} / (sqrt_rho_L + sqrt_rho_R + smallval);
210
211 const Tscal u_roe = (sqrt_rho_L * u_L + sqrt_rho_R * u_R) * roe_inv;
212 const Tscal c_roe = (sqrt_rho_L * c_L + sqrt_rho_R * c_R) * roe_inv;
213
214 // Wave speed estimates (following reference implementation)
215 const Tscal S_L = sycl::fmin(u_L - c_L, u_roe - c_roe);
216 const Tscal S_R = sycl::fmax(u_R + c_R, u_roe + c_roe);
217
218 // HLL flux formula (following reference g_fluid_force.cpp hll_solver)
219 // c1 = rho_L * (S_L - u_L)
220 // c2 = rho_R * (S_R - u_R)
221 // c3 = 1 / (c1 - c2)
222 // c4 = p_L - u_L * c1
223 // c5 = p_R - u_R * c2
224 // v* = (c5 - c4) * c3
225 // p* = (c1 * c5 - c2 * c4) * c3
226 const Tscal c1 = rho_L * (S_L - u_L);
227 const Tscal c2 = rho_R * (S_R - u_R);
228 const Tscal c3 = Tscal{1} / (c1 - c2 + smallval);
229 const Tscal c4 = p_L - u_L * c1;
230 const Tscal c5 = p_R - u_R * c2;
231
232 result.v_star = (c5 - c4) * c3;
233 result.p_star = sycl::fmax(smallval, (c1 * c5 - c2 * c4) * c3);
234
235 return result;
236 }
237
238} // namespace shammodels::gsph::riemann
std::uint32_t u32
32 bit unsigned integer
RiemannResult< Tscal > hllc_solver(Tscal u_L, Tscal rho_L, Tscal p_L, Tscal u_R, Tscal rho_R, Tscal p_R, Tscal gamma)
HLL approximate Riemann solver.
RiemannResult< Tscal > iterative_solver(Tscal u_L, Tscal rho_L, Tscal p_L, Tscal u_R, Tscal rho_R, Tscal p_R, Tscal gamma, Tscal tol=Tscal{1.0e-6}, u32 max_iter=20)
Approximate ("two-shock") iterative Riemann solver (van Leer 1997).
Definition iterative.hpp:75
Tscal v_star
Interface velocity (normal component).
Definition iterative.hpp:47