def conical_deflection_Mach_sigma(Mach, sigma, gamma=1.4, tol=1.0e-6): def rkf45(F, x, y, h): # Runge-Kutta-Fehlberg formulas C = [37./378, 0., 250./621, 125./594, 0., 512./1771] D = [2825./27648, 0., 18575./48384, 13525./55296, 277./14336, 1./4] n = len(y) K = numpy.zeros((6,n)) K[0] = h*F(x,y) K[1] = h*F(x + 1./5*h, y + 1./5*K[0]) K[2] = h*F(x + 3./10*h, y + 3./40*K[0] + 9./40*K[1]) K[3] = h*F(x + 3./5*h, y + 3./10*K[0]- 9./10*K[1] + 6./5*K[2]) K[4] = h*F(x + h, y - 11./54*K[0] + 5./2*K[1] - 70./27*K[2] + 35./27*K[3]) K[5] = h*F(x + 7./8*h, y + 1631./55296*K[0] + 175./512*K[1] + 575./13824*K[2] + 44275./110592*K[3] + 253./4096*K[4]) # Initialize arrays {dy} and {E} E = numpy.zeros((n)) dy = numpy.zeros((n)) # Compute solution increment {dy} and per-step error {E} for i in range(6): dy = dy + C[i]*K[i] E = E + (C[i] - D[i])*K[i] # Compute RMS error e e = math.sqrt(sum(E**2)/n) return dy, e def rhs(phi, data): th = data[0] ma = data[1] k = 1.-(ma*degree.sin(phi-th))**2 rhs=numpy.zeros(2) rhs[0] = -degree.sin(th)*degree.cos(phi-th)/degree.sin(phi)/k rhs[1] = math.pi/180.*degree.sin(th)*degree.sin(phi-th)/degree.sin(phi)/k*ma*(1.+.5*(gamma-1)*ma*ma) return rhs th = deflection_Mach_sigma(Mach, sigma, gamma) ma = downstream_Mn(Mach*degree.sin(sigma), gamma)/degree.sin(sigma-th) phi = sigma thma = numpy.array([th, ma]) h = -phi/10. conv = phi while (abs(conv) >= tol): dthma, err = rkf45(rhs, phi, thma, h) # Accept integration step if error e is within tolerance if err <= tol: conv = thma[0] - phi if conv/(h-dthma[0]) < 1: h = h*conv/(h-dthma[0]) else: thma = thma + dthma phi = phi + h print phi, thma else: h = 0.9*h*(tol/err)**0.2 print "new h ",h deflection = .5*(thma[0] + phi) return deflection
def rhs(phi, data): th = data[0] ma = data[1] k = 1.-(ma*degree.sin(phi-th))**2 rhs=numpy.zeros(2) rhs[0] = -degree.sin(th)*degree.cos(phi-th)/degree.sin(phi)/k rhs[1] = math.pi/180.*degree.sin(th)*degree.sin(phi-th)/degree.sin(phi)/k*ma*(1.+.5*(gamma-1)*ma*ma) return rhs