@@ -256,8 +256,62 @@ void NewRadX_Apply(const cGH *restrict const cctkGH,
256256 rhs (p.I ) = -vx * g_dvar.dx - vy * g_dvar.dy - vz * g_dvar.dz -
257257 sv0 * (var (p.I ) - var0) / r;
258258
259- if (radpower > 0.0 ) {
260- // TODO: Coulomb correction (port from Cartesian overload)
259+ // Coulomb correction: estimate and extrapolate the 1/r^n
260+ // component from interior points to the radiative boundary.
261+ // Only applied at the outer boundary — at the inner boundary
262+ // the asymptotic 1/r^n assumption breaks down (r is small,
263+ // rint > r, so the rescaling amplifies rather than attenuates).
264+ if (radpower > 0.0 && p.NI [2 ] != -1 ) {
265+ // Displacement to get from p.I to interior point placed
266+ // nghostpoints away
267+ const vect<int , dim> displacement{grid.nghostzones [0 ] * p.NI [0 ],
268+ grid.nghostzones [1 ] * p.NI [1 ],
269+ grid.nghostzones [2 ] * p.NI [2 ]};
270+ const vect<int , dim> intp = p.I - displacement;
271+
272+ assert (intp[0 ] >= grid.nghostzones [0 ]);
273+ assert (intp[1 ] >= grid.nghostzones [1 ]);
274+ assert (intp[2 ] >= grid.nghostzones [2 ]);
275+ assert (intp[0 ] <= grid.lsh [0 ] - grid.nghostzones [0 ] - 1 );
276+ assert (intp[1 ] <= grid.lsh [1 ] - grid.nghostzones [1 ] - 1 );
277+ assert (intp[2 ] <= grid.lsh [2 ] - grid.nghostzones [2 ] - 1 );
278+
279+ // Global coordinates at interior point
280+ const auto xint = vcoordx (intp);
281+ const auto yint = vcoordy (intp);
282+ const auto zint = vcoordz (intp);
283+ const auto rint = sqrt (pow2 (xint) + pow2 (yint) + pow2 (zint));
284+
285+ // Find local wave speeds at interior point
286+ const auto vxint = sv0 * xint / rint;
287+ const auto vyint = sv0 * yint / rint;
288+ const auto vzint = sv0 * zint / rint;
289+
290+ // Local derivatives at interior point (centered stencils)
291+ const LocalFirstDerivatives l_dvar_int{.da = c2o<0 >(p, intp, var),
292+ .db = c2o<1 >(p, intp, var),
293+ .dc = c2o<2 >(p, intp, var)};
294+
295+ // Jacobians at interior point
296+ const Jacobians jac_int{
297+ vJ_da_dx (intp), vJ_da_dy (intp), vJ_da_dz (intp),
298+ vJ_db_dx (intp), vJ_db_dy (intp), vJ_db_dz (intp),
299+ vJ_dc_dx (intp), vJ_dc_dy (intp), vJ_dc_dz (intp)};
300+
301+ // Global derivatives at interior point
302+ const auto g_dvar_int{project_first (l_dvar_int, jac_int)};
303+
304+ // Radiative part at interior point
305+ const auto rad = -vxint * g_dvar_int.dx - vyint * g_dvar_int.dy -
306+ vzint * g_dvar_int.dz -
307+ sv0 * (var (intp) - var0) / rint;
308+
309+ // Extrapolate Coulomb component, rescale to account for radial
310+ // fall-off
311+ const auto aux = (rhs (intp) - rad) * pow (rint / r, radpower);
312+
313+ // Radiative rhs with extrapolated Coulomb correction
314+ rhs (p.I ) += aux;
261315 }
262316 });
263317}
0 commit comments