From 8358109e0185fc804129d9157891e92f7e76bc3a Mon Sep 17 00:00:00 2001 From: Elias Aoubala <2432537A@student.gla.ac.uk> Date: Wed, 24 Jan 2024 22:38:08 +0000 Subject: [PATCH 1/2] Initial push for supersonic profiling --- src/turborocket/meanline/lossmodels.py | 150 ++++++++++++ .../__pycache__/circular.cpython-311.pyc | Bin 0 -> 4189 bytes .../__pycache__/transition.cpython-311.pyc | Bin 0 -> 7073 bytes .../profiling/Supersonic/circular.py | 127 ++++++++++ .../profiling/Supersonic/transition.py | 225 ++++++++++++++++++ .../profiling/supersonic_profile.py | 7 + .../__pycache__/solver.cpython-311.pyc | Bin 0 -> 2457 bytes src/turborocket/solvers/solver.py | 62 +++++ ...test_circular.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 13462 bytes ...st_transition.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 24189 bytes tests/profiling/supersonic/test_circular.py | 46 ++++ tests/profiling/supersonic/test_transition.py | 69 ++++++ .../test_solver.cpython-311-pytest-7.4.4.pyc | Bin 0 -> 3098 bytes tests/solvers/test_solver.py | 11 + 14 files changed, 697 insertions(+) create mode 100644 src/turborocket/meanline/lossmodels.py create mode 100644 src/turborocket/profiling/Supersonic/__pycache__/circular.cpython-311.pyc create mode 100644 src/turborocket/profiling/Supersonic/__pycache__/transition.cpython-311.pyc create mode 100644 src/turborocket/profiling/Supersonic/circular.py create mode 100644 src/turborocket/profiling/Supersonic/transition.py create mode 100644 src/turborocket/profiling/supersonic_profile.py create mode 100644 src/turborocket/solvers/__pycache__/solver.cpython-311.pyc create mode 100644 src/turborocket/solvers/solver.py create mode 100644 tests/profiling/supersonic/__pycache__/test_circular.cpython-311-pytest-7.4.4.pyc create mode 100644 tests/profiling/supersonic/__pycache__/test_transition.cpython-311-pytest-7.4.4.pyc create mode 100644 tests/profiling/supersonic/test_circular.py create mode 100644 tests/profiling/supersonic/test_transition.py create mode 100644 tests/solvers/__pycache__/test_solver.cpython-311-pytest-7.4.4.pyc create mode 100644 tests/solvers/test_solver.py diff --git a/src/turborocket/meanline/lossmodels.py b/src/turborocket/meanline/lossmodels.py new file mode 100644 index 0000000..379575a --- /dev/null +++ b/src/turborocket/meanline/lossmodels.py @@ -0,0 +1,150 @@ +""" + +This file contains a series of loss-model utilities functions for mean-line design of turbines + +Each Loss model is encapsulated into an object with a series of functions calculating loss contributions. + +Loss-Models currently implemented: + + - craigcox: Loss Model by Craig and Cox + - kackerOkapuu: Loss Model by Kacker and Okapuu (1982) + - Aungier: Loss Modely by Aungier + +""" + +import numpy as np + +class Aungier: + """ + + The Aungier Loss Model + + Variables: + Y_p: Profile Loss parameters + K_mod: Experience factor (derived from the kackerOkapuu method) + K_inc: Off-design incidence factor + K_m: Mach Number Factor + K_p: Compressibility Factor + K_RE: Reynolds Number Factor + + Y_p1: Profile Loss coefficient for nozzle blades (beta_1 = 0) + Y_p2: Profile Loss coefficent for rotor blades (beta_1 = alpha_2) + + Y_s: Secondary Flow Losses for low aspect ratio + + """ + + def __init__(): + # Intialising core parameters of the loss model + return + + def Y(self): + """ + Total Pressure Loss Coefficient (Y) + + This function solves for the profile loss coefficient of the turbine stage, characterising the increase in total pressure of the turbine exit stage + + Y = (P_t1 - P_t2) / (P_t2 - P_2) + + Variables: + Y_p: The Profile Loss Coefficient + Y_s: The Secondary Flow loss coefficient + Y_tcl: The blade clearnace loss coefficient + Y_te: The trailing edge loss coefficient + Y_ex: The supersonic expansion loss coefficient + Y_sh: The shock loss coefficient + T_lw: The lashing wire loss coefficient (rotors) + """ + + return Y_p + Y_s + Y_tcl + T_te + Y_ex + Y_sh + Y_lw + + def delta_h_par(self): + """ + Parasitic Losses (delta_h_par) + + The parasitic losses accounts for waster work due to losses in disk friction, shear forces and partial admission. + + These are reflected in an increase in total enthalph of the discharge flow + relative to the value produced when the flow passes through the blade row. + + In contrast to the pressure loss coefficient, these losses do not affect total pressure, but do influence stage efficiency. + + Variables: + delta_h_adm: Partial admission losses (rotors) + delta_h_df: Disk friction work (diaphragm-disk rotors) + delta_h_seal: Leakage bypass loss (shourded rotors and rotor balance holes) + delta_h_gap: Clearnace gap windage loss (shrouded blades and nozzles of diaphragm-disk rotors) + delta_h_q: moisture work loss (rotors) + """ + + return delta_h_adm + delta_h_df + delta_h_seal + delta_h_gap + delta_h_q + + def yp(self): + """ + The Profile Loss Coefficient (Y_p) + + This pressure loss coefficient characterises the profile losses of the turbine stage + + Variables: + K_mod: kackerOkapuu Experience factor + K_inc: Correction for off-design incidence effects + K_m: Correction for Mach Number effects + K_p: correction for Compressibility effects + K_re: correction for Reynolds Number effects + Y_p1: profile loss coefficient for nozzle blades (beta_1 = 90) + Y_p2: profile loss coefficients for impulse blades (alpha_2 = beta_1) + + Returns: + _type_: _description_ + """ + + prt = (y_p1 + ((beta_1/alpha_2)**2 ) * (y_p2 - y_p1))*((5*t/c)**(beta_1/alpha_2)) - delta_y_te + + y_p = k_mod * k_inc * k_m * k_p * k_re * prt; + + return y_p + + def F_ar(self): + + if h_c < 2: + f_ar = 0.5 * (2*c/h)**(0.7) + else: + f_ar = (c/h) + + return f_ar + + def Y_s(self): + y_bar_s = 0.0334 * F_ar * (C_l / (s_c))**2 * (np.cos(alpha_2)/np.cos(beta_1))*(np.cos(alpha_2)**2/np.cos(alpha_m)***3) + + y_s = k_s*k_re*(y_bar_s**2 / (1 + 7.5*y_bar_s))**(1/2) + + return y_s + + def Y_sh(self): + + y_bar_sh = 0.8*x_1**2 + x_2**2 + + y_sh = (y_bar_sh**2 / (1 + y_bar_sh**2))**(1/2) + + return y_sh + + def Y_ex(self): + + y_ex = ((M2 - 1)/M2)**2; + + return y_ex + + def Y_te(self): + + y_te = ((t_2/s) * np.sin(beta_g) - t_2)**2 + + return y_te + + def Y_tcl(self): + + if TIP_TYPE = "shrouded": + B = 0.37 + else: + B = 0.47 + + Y_tcl = B*(c/h)*(t_cl / c)**(0.78) * (C_l/(s/c))**2 * (np.cos(alpha_2)**2 /np.cos(alpha_m)**3) \ No newline at end of file diff --git a/src/turborocket/profiling/Supersonic/__pycache__/circular.cpython-311.pyc b/src/turborocket/profiling/Supersonic/__pycache__/circular.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc9e94aafd07846f9960e1cc1e05d1d202e01bfd GIT binary patch literal 4189 zcmeHKUuYc18K1qqJLyh$(VZ&EHl*$N560)nQZ7vlk&B(PEn^p-Tt`yCMzE}QSJEb{ z-Sf=u*%D`}Kwkt3$WNBQf%8iu6AH?k`%rLSO30HI`d|(UrlkbGopADEDD?Yg|Hy~z zxG8we3{Q@2|O3QKN!s%A^*Tm^d!Q@vy;%cOLTIb=#rkWr0WS? z{yn)a>q($VJq0wSr-7#RE}&g{H_&c9F+oZh^*0hB*>fh-JWFN6wZ&|9a^B>WJ08;v zI%`@6HEd0-aTs?EPF2gI?mUcmw&t3S%_%c(cqTJ+I_ogX%_Y;G6C7HolyW2FbY{hX z>&-CJHt39{>c$X=S(bA%lA2|PLF*24jayXZ+*_!jm0@%XjK-{BQw_`q-?-4cV7T*6 z=!jP{70Q!V8iqAl`+_*qyR4;1F}ro zZ<1Vbt-SL7y0kK~ezhrWO!}FFO?7i@tMcH|!{UQ857kG-KkEMRv;NVue)qY@+1{O0 zqQAI&x!p~2`?r((o`E9L0V#k$0I4=K?h+Rn!slaL6Y&7d5MT%<=!<`V)-H(PJN6NH z@~gSrSRWxD$FPpH0eq7Yd>aJyeF6Mm#WJYL>ckp|)GOEdrvYQZ^#uum<0CIIzY z2KaL=S~V5{ixqngQq{3~>9w#Agls|Clq3REu@w-2GH1@csAfPtTEN&d| zvxhea{LIMTvbojL+SK~hJJ*^+ThjdzzrVaS=J&tvXGi~<9o>7YD8S8YLK~URFY_gX+dx~tyr~r^|kShb|r;{hZF^{;GNMmZOd>)@^U;k zXd=^)u&y~?%>pFcG~Ic`g2|v@sJ3gJ5U~jrzB0q9=%QjNCS}{9K|z!3=68!vm8jl$yg^ zGLTZLC08+1R23(vn;4!}+JMxfI2^@9f)ME;h#v-V4qmHOc<|1ZrnXtWKkN4o`Guja;+FAH{n~s~{#tp&zp4DW?!Q;{%T>R3{Bdz`y?E!q z`ig%u3pEg??ztgd#+~D9mk9P}RQ#JSiw+99nNVu$7 z(b;OZ`eHEQ!U)&0=*kh@)Q(kdnII8%LtpnCyh;fH9Cj2|5!zw{BMLaKbyPZ16+HVh zEE9Dc`y~)@q{_XqdUEaP%IVe9pP#*Vp?Pv+{NA|Vb9_5_Tm-C?X>}=z?r4hAO2K`n zwip=0^SwBri4r6>dVoK)AgZ1a7r=bp{p$rs_blTy8-`H~8vhhXTb3lLoybbbHbJtV zNI%;qeZjAtE=v2`BqqmtrF@&j&H#2}@^((@Ym=D#A|t)kCVPo+@!ulO BPp|+0 literal 0 HcmV?d00001 diff --git a/src/turborocket/profiling/Supersonic/__pycache__/transition.cpython-311.pyc b/src/turborocket/profiling/Supersonic/__pycache__/transition.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..378d2960333104008a5cc1867242df223f430c21 GIT binary patch literal 7073 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 m^rKIUz$f%=l7NfcyGArg%t;!hZk`G77N( literal 0 HcmV?d00001 diff --git a/src/turborocket/profiling/Supersonic/circular.py b/src/turborocket/profiling/Supersonic/circular.py new file mode 100644 index 0000000..9b479eb --- /dev/null +++ b/src/turborocket/profiling/Supersonic/circular.py @@ -0,0 +1,127 @@ +""" +Circular.py + +This source file encapsulates all the functions required for sizing the circular sections of the tubrine blade, following the free vortex assumption. + +The following equations follows the method for supersonic turbine design presented in NASA TN D-4421. + +Free vortex flow is assumed for the blade flow. + +# noqa: E501 +""" + +import numpy as np + + +def M_star(gamma, M): + """ + Critical Velocity Ratio + + This function computes the critical velocity ratio of the flow as a function of Mach number and specific heat ratio. + + Variables: + gamma: Specific Heat Ratio + M: Mach Number + + # noqa: E501 + """ + + crit_vel_rat = ( + (((gamma + 1) / 2) * M**2) / (1 + ((gamma - 1) / 2) * M**2) + ) ** (1 / 2) + + return crit_vel_rat + + +def prandtl_meyer(gamma, crit_vel_rat): + """ + Prandtl Meyer Angle (v) + + This function computes the Prandtl-Meyer angle v based on the mach number of a flow. + + # noqa: E501 + """ + + v = np.pi / 4 * (((gamma + 1) / (gamma - 1)) ** (1 / 2) - 1) + (1 / 2) * ( + (((gamma + 1) / (gamma - 1)) ** (1 / 2)) + * np.arcsin((gamma - 1) * crit_vel_rat**2 - gamma) + + np.arcsin((gamma + 1) / crit_vel_rat**2 - gamma) + ) + + return v + + +def arc_angles_upper(beta_o, beta_i, v_i, v_o, v_u): + """ + Upper Circular Arc Angles Alpha + + This function computes the circular arc angles based on the inlet and outlet angles, + coupled with their prantl-meyer angles + + Variables: + alpha_l_i: Lower Arc Inlet Angle + alpha_l_o: Lower Arc Outlet Angle + alpha_u_i: Upper Arc Inlet Angle + alpha_u_o: Upper Arc Outlet Angle + beta_i: Inlet relative flow angle + beta_o: Exit relative + + # noqa: E501 + """ + + alpha_u_i = beta_i - (v_u - v_i) + + alpha_u_o = beta_o + (v_u - v_o) + + return [alpha_u_i, alpha_u_o] + + +def arc_angles_lower(beta_o, beta_i, v_i, v_o, v_l): + """ + Lower Circular Arc Angles Alpha + + This function computes the arc angles based on the inlet and outlet angles, coupled with their prantl-meyer angles + + Variables: + alpha_l_i: Lower Arc Inlet Angle + alpha_l_o: Lower Arc Outlet Angle + alpha_u_i: Upper Arc Inlet Angle + alpha_u_o: Upper Arc Outlet Angle + beta_i: Inlet relative flow angle + beta_o: Exit relative + + # noqa: E501 + """ + + alpha_l_i = beta_i - (v_i - v_l) + + alpha_l_o = beta_o + (v_o - v_l) + + return [alpha_l_i, alpha_l_o] + + +def beta_o(M_i, M_o, gamma, beta_i): + """ """ + + exit_o = -np.arccos( + ( + (M_i / M_o) + * ((1 + (gamma - 1) / 2 * M_o**2) / (1 + (gamma - 1) / 2 * M_i**2)) + ** ((gamma + 1) / (2 * (gamma - 1))) + ) + * np.cos(beta_i) + ) + + return exit_o + + +def A_rat(beta_i, beta_o): + """ + The Area Ratio (A_i / A_o) + + This equation computes the area ratio of the supersonic turbine blade, assuming that the spacings are equal on the inlet and exit sides of the turbine (Axial turbine) + + # noqa: E501 + """ + + return np.cos(beta_i) / np.cos(beta_o) diff --git a/src/turborocket/profiling/Supersonic/transition.py b/src/turborocket/profiling/Supersonic/transition.py new file mode 100644 index 0000000..255b8ea --- /dev/null +++ b/src/turborocket/profiling/Supersonic/transition.py @@ -0,0 +1,225 @@ +""" +transition.py + +This source file encapsulates all the functions required for sizing the transition arc sections of the turbine blade, utilising the method of characteristics. + +The following equations follows the method for supersonic turbine design presented in NASA TN D-4421. + + + +# noqa: E501 + +""" + +from src.turborocket.solvers.solver import adjoint + +import numpy as np + + +def func_R_star(R_star, gamma): + """ + Function of R* ( f(R*) ) + + This equation describes the generalised function of the non-dimentionalised radius + defining the expansion line angle. + + Variables: + gamma: Specific Heat Ratio + R_star: Non-dimentionalised Radius + + """ + + f_r_star = ((gamma + 1) / (gamma - 1)) ** (1 / 2) * np.arcsin( + (gamma - 1) / R_star**2 - gamma + ) + np.arcsin((gamma + 1) * R_star**2 - gamma) + + return f_r_star + + +def func_R_star_k(gamma, v_i, dv, k): + f_r_star_k = ( + 2 * v_i + - np.pi / 2 * (((gamma + 1) / (gamma - 1)) ** (1 / 2) - 1) + - 2 * (k - 1) * dv + ) + + return f_r_star_k + + +def R_star(gamma, v_i, dv, k, guess): + # We use the ajoint equation + + target = func_R_star_k(gamma, v_i, dv, k) + + r_star = adjoint(func_R_star, guess, -0.01, 50, 0.1, target, params=[gamma]) + + return r_star + + +def phi_k(v_i, v_l, k, dv): + phi_k_i = v_i - v_l - (k - 1) * dv + + return phi_k_i + + +def vortex_coords(R_star_k, phi_k): + x_star = -R_star_k * np.sin(phi_k) + y_star = R_star_k * np.cos(phi_k) + + return [x_star, y_star] + + +def mue_k(gamma, R_star_k): + mach_angle = -np.arcsin( + (((gamma + 1) / 2) * R_star_k**2 - ((gamma - 1) / 2)) ** (1 / 2) + ) + + return mach_angle + + +def mach_slope(phi_k_1, phi_k_2, mue_k_1, mue_k_2): + # This function computes the gradient of the mach line + + m_k = np.tan(((phi_k_1 + phi_k_2) / 2) + ((mue_k_1 + mue_k_2) / 2)) + + return m_k + + +def wall_slope(phi_k_1): + # This function computes the slope the wall at a given segment + + m_bar_k = np.tan(phi_k_1) + + return m_bar_k + + +def wall_coords(x_star_l_k_1, y_star_l_k_1, y_star_k, x_star_k, m_bar_k, m_k): + x_star_l_k = ( + (y_star_l_k_1 - m_bar_k * x_star_l_k_1) - (y_star_k - m_k * x_star_k) + ) / (m_k - m_bar_k) + y_star_l_k = ( + m_k * (y_star_l_k_1 - m_bar_k * x_star_l_k_1) + - m_bar_k * (y_star_k - m_k * x_star_k) + ) / (m_k - m_bar_k) + + return [x_star_l_k, y_star_l_k] + + +def transform_coord(x_star_l_k, y_star_l_k, alpha_l_i): + # This function does the co-ordinate transformation for the transition co-ords + + x_star_l_k_t = x_star_l_k * np.cos(alpha_l_i) - y_star_l_k * np.sin(alpha_l_i) + + y_star_l_k_t = x_star_l_k * np.sin(alpha_l_i) + y_star_l_k * np.cos(alpha_l_i) + + return [x_star_l_k_t, y_star_l_k_t] + + +def moc(k_max, v_i, v_l, gamma, alpha_l_i): + # This function encapsulates the overall method of characteristics procedure for solving + # for the shape of the transition arcs + + # First we need to define the k_max value, this needs to be an integer, + # so what we do is we can invert this + + delta_v = (v_i - v_l) / k_max + + # We setup our history arrays accordingly + phi_hist = [] + r_star_hist = [] + xk_hist = [] + yk_hist = [] + mue_hist = [] + mk_hist = [] + m_bar_k_hist = [] + xlk_hist = [] + ylk_hist = [] + xlkt_hist = [] + ylkt_hist = [] + + # We can now do the intial look to get the intial values of the loop. + phi = phi_k(v_i, v_l, k_max + 1, delta_v) + + phi_hist.append(phi) + + # We now must solver R* using the adjoint method + r_star = R_star(gamma, v_i, delta_v, k_max + 1, 1) + + r_star_hist.append(r_star) + + # We can now compute the co-ordinates of the expansion line + [xk, yk] = vortex_coords(r_star, phi) + + xk_hist.append(xk) + yk_hist.append(yk) + + # We need to now compute the mach angle + mue = mue_k(gamma, r_star) + + mue_hist.append(mue) + + # Gradients need to be 0 at the intial point which is vertical + mk_hist.append(0) + m_bar_k_hist.append(0) + + # Wall co-ordinates are the same as the intial co-ordinates + xlk_hist.append(xk) + ylk_hist.append(yk) + + # Finally, we do a co-ordinate transformation + + [xlkt, ylkt] = transform_coord(xk, yk, alpha_l_i) + + xlkt_hist.append(xlkt) + ylkt_hist.append(ylkt) + + # Having established the delta_v, we can then loop through k values + + for k in np.linspace(k_max, 1, num=k_max): + # We evaluate our phi angle + phi = phi_k(v_i, v_l, k, delta_v) + + phi_hist.append(phi) + + # We now must solver R* using the adjoint method + r_star = R_star(gamma, v_i, delta_v, k, 1) + + r_star_hist.append(r_star) + + # We can now compute the co-ordinates of the expansion line + [xk, yk] = vortex_coords(r_star, phi) + + xk_hist.append(xk) + yk_hist.append(yk) + + # We need to now compute the mach angle + mue = mue_k(gamma, r_star) + + mue_hist.append(mue) + + # We must thus compute the slope of the mach line, based on the average of the current point and previous (k+1) + m_k = mach_slope(phi_hist[k_max - k], phi, mue_hist[k_max - k], mue) + + mk_hist.append(m_k) + + # We can now compute the wall segment slope + m_bar_k = wall_slope(phi_hist[k_max - k]) + + m_bar_k_hist.append(m_bar_k) + + # Wall Co-ordinates + [xlk, ylk] = wall_coords(xlk_hist, ylk_hist, yk_hist, xk_hist, m_bar_k, m_k) + + xlk_hist.append(xlk) + ylk_hist.append(ylk) + + # Finally, we do a co-ordinate transformation + + [xlkt, ylkt] = transform_coord(xlk, ylk, alpha_l_i) + + xlkt_hist.append(xlkt) + ylkt_hist.append(ylkt) + + # Finally, we return the transformed co-ordinates + + return [xlkt_hist, ylkt_hist] diff --git a/src/turborocket/profiling/supersonic_profile.py b/src/turborocket/profiling/supersonic_profile.py new file mode 100644 index 0000000..e912984 --- /dev/null +++ b/src/turborocket/profiling/supersonic_profile.py @@ -0,0 +1,7 @@ +# This file encapsulates the main function for computing the supersonic profile + + +def supersonic_profile(beta_I, beta_o, M_i, M_o): + + # The first process required for the design of the supersonic blade profile is the definition of the upper and lower circular arcs. + diff --git a/src/turborocket/solvers/__pycache__/solver.cpython-311.pyc b/src/turborocket/solvers/__pycache__/solver.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..be79199f1f385e0d03cafd9a31fe08cc11816714 GIT binary patch literal 2457 zcmd58OK2NMbapi>jV0|`>qL$%Y}bk1B+4PgmxQ<>5Mnz?AqjDu99)MWd)JC>SyFaa ztu5BYltR}*G%5tD+(apEiW^7|g&s=jF@+v>&4R^1z-^jCZZ5f$occz;*p{txA2V;> zoA=(l&%9aoJ5lr_02+U)-uEK(k});ltHhh5Kzxl9q;Lr|&Xrew-ZPFl6h{g_%`2YI zxp6_^ZlWlD&5W*%Op&TFTi{^if%ztZ*+Fr%L}0eS^ur9m4D!fCCKu;S?>F2i`VuXP zrf3RT2yRI-TZ&-Z2&TBoA+!dw0vs~^#Tv6?HKhhkvX3U$pc&X(Q)$pNSdLYgtrZUn zWO_`G!D>*2A3Up2hc%cL7(#dcTxu;>fS9cc&$8~U36aTXf&L#$eU$_*bDP*6Mx1p&gpOn$0Q@Yc&Re zmRx6$;%&%co78M+CRKdRq!8V%x3t4AX(lzBN|mNjnSo{}D@~&^gS%~ab_#rs0@pNF z@Yn1c5#^~TnVF}8Vl1ZB_&@hvT0i~!_xZ7`cqyamdhg{K-AHMRS#em?Qd*sDS*Vk3 z70D$nrquU*Lkqq4z%trGy|Hv!O)8X6rYT9xB=vM`N~NBeq(MEgNu7Gq34`KvA_Z8# zm->VXX$^!?nd0e8a*FyE?#5Xplvfrgm!yKGCSnWJYs9p;YEW-Frp4xU8Wn9vIHu0YlV(O$dwJBQne5&zJ#&@<>sjWovO~ds&_ZM9lAI; zaZ6V4~w7HkletP0gvsgsx3Z7>w7dd@AuVv(U@y$@C)i#gy3; z_CPTSNIncJN5yG@!~@9^MSf z`H_`tKwxPDhu3j9uR6HP#a%Y;D($)F|KjRrSM$dl9C2~P#*q>}uz@4%I8qpJaJP%Q zZQT7zY|VXCkP8=z15Yp7;weWw<%*}a&_Ur$8Cl$B=wKe_Z-WN+c=*ws;;0ioW`_oz z90gPvmarKL7rb9dK#;Z#(z#AL3-3Fm*Co9+=`HQKCp{D&i23QljiUVc)}#62q|<)f zAyJn^Z4xb!)`!vqDX%#s;*y9>B2bq@hl?^O&OVc$-S{!=9zEl6DjUIZj7voe?)Ea3G(mmTOT1!Ze^ zi=dF4A6)s=7JG`3Cl|i$cEpp_;w^sD*OpgoUj)Vr63CH!dm-YGewXyyr2iG$ zS@Gxmmj4wIt&~H0T+(Bco)^H)I;7Jjoi^!YTr=5RJxiuJy&~pBO9axEjyR;xC4DyO zYdmAdAssI1ut^7##aE=9WJ#L=Ie$2J*2V|lK)a!+mkRJ9NH1#aCxy!MF@rtI#LOhL zXZd-0E2|a+dAUu$M_M1F4+DBj&dsNkOhP@c9S4?uTJ+0+wmclil~9{q8zuCfy>q~Q Ro&Dgsu!YWY;eAor(|-+n9%TRk literal 0 HcmV?d00001 diff --git a/src/turborocket/solvers/solver.py b/src/turborocket/solvers/solver.py new file mode 100644 index 0000000..85304e4 --- /dev/null +++ b/src/turborocket/solvers/solver.py @@ -0,0 +1,62 @@ +import numpy as np +import matplotlib.pyplot as plt + + +def adjoint(func, x_guess, dx, n, relax, target, params=[], RECORD_HIST=False): + # We first evaluate the error as a function of x + + x_hist = [] + guess_hist = [] + error_hist = [] + error_grad_hist = [] + dx_hist = [] + + # We first evaluate the error of the guess + guess = func(x_guess, *params) + + error = guess - target + + guess_hist.append(guess) + error_hist.append(error) + x_hist.append(x_guess) + error_grad_hist.append(0) + + for k in np.linspace(1, n, num=n, dtype=int): + # We now timestep in the x space + guess = func(x_hist[k - 1] + dx, *params) + + error = guess - target + + guess_hist.append(guess) + error_hist.append(error) + x_hist.append(x_hist[k - 1] + dx) + dx_hist.append(dx) + # Now we computed the gradient + + error_grad = (error_hist[k] - error_hist[k - 1]) / (x_hist[k] - x_hist[k - 1]) + + error_grad_hist.append(error_grad) + if abs(error) < 1e-5: + break + + # based on this gradient, we can thus find the new x-step based on this gradient # noqa: E501 + + dx = -(1 / error_grad) * error_hist[k] * relax + + if RECORD_HIST is True: + plt.plot(x_hist, error_hist) + + plt.show() + + print("Guess History") + print(guess_hist) + print("Error History") + print(error_hist) + print("x History") + print(x_hist) + print("Error Grad History") + print(error_grad_hist) + print("Dx hist") + print(dx_hist) + + return x_hist[k] diff --git a/tests/profiling/supersonic/__pycache__/test_circular.cpython-311-pytest-7.4.4.pyc b/tests/profiling/supersonic/__pycache__/test_circular.cpython-311-pytest-7.4.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..acddc591855efae70ee61befdf3d4b83facf9531 GIT binary patch literal 13462 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 O3Kou1Ni#}s$NvD{-IAFA literal 0 HcmV?d00001 diff --git a/tests/profiling/supersonic/__pycache__/test_transition.cpython-311-pytest-7.4.4.pyc b/tests/profiling/supersonic/__pycache__/test_transition.cpython-311-pytest-7.4.4.pyc new file mode 100644 index 0000000000000000000000000000000000000000..620d50a3932401f2d5d0ea2a00042e0a98964854 GIT binary patch literal 24189 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 literal 0 HcmV?d00001 diff --git a/tests/solvers/test_solver.py b/tests/solvers/test_solver.py new file mode 100644 index 0000000..f87003b --- /dev/null +++ b/tests/solvers/test_solver.py @@ -0,0 +1,11 @@ +from src.turborocket.solvers.solver import adjoint + +import pytest + + +def dummy_function(x): + return x**2 - 4 + + +def test_adjoint(): + assert adjoint(dummy_function, 4, 0.1, 100, 0.6, 0) == pytest.approx(2, 1e-3) From 2e84e029813bac3c38e6a7ee38194171366054c9 Mon Sep 17 00:00:00 2001 From: Elias Aoubala <2432537A@student.gla.ac.uk> Date: Wed, 24 Jan 2024 22:40:22 +0000 Subject: [PATCH 2/2] Fixed local .gitignore for caches --- .gitignore | 1 + .../__pycache__/circular.cpython-311.pyc | Bin 4189 -> 0 bytes .../__pycache__/transition.cpython-311.pyc | Bin 7073 -> 0 bytes .../solvers/__pycache__/solver.cpython-311.pyc | Bin 2457 -> 0 bytes .../test_circular.cpython-311-pytest-7.4.4.pyc | Bin 13462 -> 0 bytes ...test_transition.cpython-311-pytest-7.4.4.pyc | Bin 24189 -> 0 bytes .../test_solver.cpython-311-pytest-7.4.4.pyc | Bin 3098 -> 0 bytes 7 files changed, 1 insertion(+) create mode 100644 .gitignore delete mode 100644 src/turborocket/profiling/Supersonic/__pycache__/circular.cpython-311.pyc delete mode 100644 src/turborocket/profiling/Supersonic/__pycache__/transition.cpython-311.pyc delete mode 100644 src/turborocket/solvers/__pycache__/solver.cpython-311.pyc delete mode 100644 tests/profiling/supersonic/__pycache__/test_circular.cpython-311-pytest-7.4.4.pyc delete mode 100644 tests/profiling/supersonic/__pycache__/test_transition.cpython-311-pytest-7.4.4.pyc delete mode 100644 tests/solvers/__pycache__/test_solver.cpython-311-pytest-7.4.4.pyc diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ed8ebf5 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +__pycache__ \ No newline at end of file diff --git a/src/turborocket/profiling/Supersonic/__pycache__/circular.cpython-311.pyc b/src/turborocket/profiling/Supersonic/__pycache__/circular.cpython-311.pyc deleted file mode 100644 index dc9e94aafd07846f9960e1cc1e05d1d202e01bfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4189 zcmeHKUuYc18K1qqJLyh$(VZ&EHl*$N560)nQZ7vlk&B(PEn^p-Tt`yCMzE}QSJEb{ z-Sf=u*%D`}Kwkt3$WNBQf%8iu6AH?k`%rLSO30HI`d|(UrlkbGopADEDD?Yg|Hy~z zxG8we3{Q@2|O3QKN!s%A^*Tm^d!Q@vy;%cOLTIb=#rkWr0WS? z{yn)a>q($VJq0wSr-7#RE}&g{H_&c9F+oZh^*0hB*>fh-JWFN6wZ&|9a^B>WJ08;v zI%`@6HEd0-aTs?EPF2gI?mUcmw&t3S%_%c(cqTJ+I_ogX%_Y;G6C7HolyW2FbY{hX z>&-CJHt39{>c$X=S(bA%lA2|PLF*24jayXZ+*_!jm0@%XjK-{BQw_`q-?-4cV7T*6 z=!jP{70Q!V8iqAl`+_*qyR4;1F}ro zZ<1Vbt-SL7y0kK~ezhrWO!}FFO?7i@tMcH|!{UQ857kG-KkEMRv;NVue)qY@+1{O0 zqQAI&x!p~2`?r((o`E9L0V#k$0I4=K?h+Rn!slaL6Y&7d5MT%<=!<`V)-H(PJN6NH z@~gSrSRWxD$FPpH0eq7Yd>aJyeF6Mm#WJYL>ckp|)GOEdrvYQZ^#uum<0CIIzY z2KaL=S~V5{ixqngQq{3~>9w#Agls|Clq3REu@w-2GH1@csAfPtTEN&d| zvxhea{LIMTvbojL+SK~hJJ*^+ThjdzzrVaS=J&tvXGi~<9o>7YD8S8YLK~URFY_gX+dx~tyr~r^|kShb|r;{hZF^{;GNMmZOd>)@^U;k zXd=^)u&y~?%>pFcG~Ic`g2|v@sJ3gJ5U~jrzB0q9=%QjNCS}{9K|z!3=68!vm8jl$yg^ zGLTZLC08+1R23(vn;4!}+JMxfI2^@9f)ME;h#v-V4qmHOc<|1ZrnXtWKkN4o`Guja;+FAH{n~s~{#tp&zp4DW?!Q;{%T>R3{Bdz`y?E!q z`ig%u3pEg??ztgd#+~D9mk9P}RQ#JSiw+99nNVu$7 z(b;OZ`eHEQ!U)&0=*kh@)Q(kdnII8%LtpnCyh;fH9Cj2|5!zw{BMLaKbyPZ16+HVh zEE9Dc`y~)@q{_XqdUEaP%IVe9pP#*Vp?Pv+{NA|Vb9_5_Tm-C?X>}=z?r4hAO2K`n zwip=0^SwBri4r6>dVoK)AgZ1a7r=bp{p$rs_blTy8-`H~8vhhXTb3lLoybbbHbJtV zNI%;qeZjAtE=v2`BqqmtrF@&j&H#2}@^((@Ym=D#A|t)kCVPo+@!ulO BPp|+0 diff --git a/src/turborocket/profiling/Supersonic/__pycache__/transition.cpython-311.pyc b/src/turborocket/profiling/Supersonic/__pycache__/transition.cpython-311.pyc deleted file mode 100644 index 378d2960333104008a5cc1867242df223f430c21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7073 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 m^rKIUz$f%=l7NfcyGArg%t;!hZk`G77N( diff --git a/src/turborocket/solvers/__pycache__/solver.cpython-311.pyc b/src/turborocket/solvers/__pycache__/solver.cpython-311.pyc deleted file mode 100644 index be79199f1f385e0d03cafd9a31fe08cc11816714..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2457 zcmd58OK2NMbapi>jV0|`>qL$%Y}bk1B+4PgmxQ<>5Mnz?AqjDu99)MWd)JC>SyFaa ztu5BYltR}*G%5tD+(apEiW^7|g&s=jF@+v>&4R^1z-^jCZZ5f$occz;*p{txA2V;> zoA=(l&%9aoJ5lr_02+U)-uEK(k});ltHhh5Kzxl9q;Lr|&Xrew-ZPFl6h{g_%`2YI zxp6_^ZlWlD&5W*%Op&TFTi{^if%ztZ*+Fr%L}0eS^ur9m4D!fCCKu;S?>F2i`VuXP zrf3RT2yRI-TZ&-Z2&TBoA+!dw0vs~^#Tv6?HKhhkvX3U$pc&X(Q)$pNSdLYgtrZUn zWO_`G!D>*2A3Up2hc%cL7(#dcTxu;>fS9cc&$8~U36aTXf&L#$eU$_*bDP*6Mx1p&gpOn$0Q@Yc&Re zmRx6$;%&%co78M+CRKdRq!8V%x3t4AX(lzBN|mNjnSo{}D@~&^gS%~ab_#rs0@pNF z@Yn1c5#^~TnVF}8Vl1ZB_&@hvT0i~!_xZ7`cqyamdhg{K-AHMRS#em?Qd*sDS*Vk3 z70D$nrquU*Lkqq4z%trGy|Hv!O)8X6rYT9xB=vM`N~NBeq(MEgNu7Gq34`KvA_Z8# zm->VXX$^!?nd0e8a*FyE?#5Xplvfrgm!yKGCSnWJYs9p;YEW-Frp4xU8Wn9vIHu0YlV(O$dwJBQne5&zJ#&@<>sjWovO~ds&_ZM9lAI; zaZ6V4~w7HkletP0gvsgsx3Z7>w7dd@AuVv(U@y$@C)i#gy3; z_CPTSNIncJN5yG@!~@9^MSf z`H_`tKwxPDhu3j9uR6HP#a%Y;D($)F|KjRrSM$dl9C2~P#*q>}uz@4%I8qpJaJP%Q zZQT7zY|VXCkP8=z15Yp7;weWw<%*}a&_Ur$8Cl$B=wKe_Z-WN+c=*ws;;0ioW`_oz z90gPvmarKL7rb9dK#;Z#(z#AL3-3Fm*Co9+=`HQKCp{D&i23QljiUVc)}#62q|<)f zAyJn^Z4xb!)`!vqDX%#s;*y9>B2bq@hl?^O&OVc$-S{!=9zEl6DjUIZj7voe?)Ea3G(mmTOT1!Ze^ zi=dF4A6)s=7JG`3Cl|i$cEpp_;w^sD*OpgoUj)Vr63CH!dm-YGewXyyr2iG$ zS@Gxmmj4wIt&~H0T+(Bco)^H)I;7Jjoi^!YTr=5RJxiuJy&~pBO9axEjyR;xC4DyO zYdmAdAssI1ut^7##aE=9WJ#L=Ie$2J*2V|lK)a!+mkRJ9NH1#aCxy!MF@rtI#LOhL zXZd-0E2|a+dAUu$M_M1F4+DBj&dsNkOhP@c9S4?uTJ+0+wmclil~9{q8zuCfy>q~Q Ro&Dgsu!YWY;eAor(|-+n9%TRk diff --git a/tests/profiling/supersonic/__pycache__/test_circular.cpython-311-pytest-7.4.4.pyc b/tests/profiling/supersonic/__pycache__/test_circular.cpython-311-pytest-7.4.4.pyc deleted file mode 100644 index acddc591855efae70ee61befdf3d4b83facf9531..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13462 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 O3Kou1Ni#}s$NvD{-IAFA diff --git a/tests/profiling/supersonic/__pycache__/test_transition.cpython-311-pytest-7.4.4.pyc b/tests/profiling/supersonic/__pycache__/test_transition.cpython-311-pytest-7.4.4.pyc deleted file mode 100644 index 620d50a3932401f2d5d0ea2a00042e0a98964854..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24189 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