private unsafe void IntersectionSearch(double *y, double *dydx, double hupper, KerrBlackHoleEquation equation) { double hlower = 0.0; equation.Function(y, dydx); while ((y[0] > equation.Rhor) && (y[0] < equation.R0 * 2)) { double *yout = stackalloc double[equation.N]; double *yerr = stackalloc double[equation.N]; double hdiff = hupper - hlower; if (Math.Abs(hdiff) < 1e-7) { RungeKutta.IntegrateStep(equation, y, dydx, hupper, yout, yerr); Util.memcpy((IntPtr)y, (IntPtr)yout, equation.N * sizeof(double)); return; } double hmid = (hupper + hlower) / 2; RungeKutta.IntegrateStep(equation, y, dydx, hmid, yout, yerr); if (yout[0] < equation.R0) { hlower = hmid; } else { hupper = hmid; } } }
/// <summary> /// Use Runge-Kutta steps to find intersection with horizontal plane of the scene. /// This is necessary to stop integrating when the ray hits the accretion disc. /// </summary> private unsafe void IntersectionSearch(double *y, double *dydx, double hupper, KerrBlackHoleEquation equation) { double hlower = 0.0; int side; if (y[1] > Math.PI / 2) { side = 1; } else if (y[1] < Math.PI / 2) { side = -1; } else { // unlikely, but needs to handle a situation when ray hits the plane EXACTLY return; } equation.Function(y, dydx); while ((y[0] > equation.Rhor) && (y[0] < equation.R0) && (side != 0)) { double *yout = stackalloc double[equation.N]; double *yerr = stackalloc double[equation.N]; double hdiff = hupper - hlower; if (Math.Abs(hdiff) < 1e-7) { RungeKutta.IntegrateStep(equation, y, dydx, hupper, yout, yerr); Util.memcpy((IntPtr)y, (IntPtr)yout, equation.N * sizeof(double)); return; } double hmid = (hupper + hlower) / 2; RungeKutta.IntegrateStep(equation, y, dydx, hmid, yout, yerr); if (side * (yout[1] - Math.PI / 2) > 0) { hlower = hmid; } else { hupper = hmid; } } }
protected unsafe void IntersectionSearch(double *y, double *dydx, double hupper, KerrBlackHoleEquation equation) { double hlower = 0.0; double tempX = 0, tempY = 0, tempZ = 0; equation.Function(y, dydx); while ((y[0] > equation.Rhor) && (y[0] < equation.R0)) { double *yout = stackalloc double[equation.N]; double *yerr = stackalloc double[equation.N]; double hdiff = hupper - hlower; if (Math.Abs(hdiff) < 1e-7) { RungeKutta.IntegrateStep(equation, y, dydx, hupper, yout, yerr); Util.memcpy((IntPtr)y, (IntPtr)yout, equation.N * sizeof(double)); return; } double hmid = (hupper + hlower) / 2; RungeKutta.IntegrateStep(equation, y, dydx, hmid, yout, yerr); Util.ToCartesian(yout[0], yout[1], yout[2], ref tempX, ref tempY, ref tempZ); double distance = Math.Sqrt((tempX - centerX) * (tempX - centerX) + (tempY - centerY) * (tempY - centerY) + (tempZ - centerZ) * (tempZ - centerZ)); if (distance > radius) { hlower = hmid; } else { hupper = hmid; } } }