@sh.add_function(dsp, outputs=['gear_box_ratios'])
def design_gear_box_ratios(n_gears, first_gear_box_ratio, last_gear_box_ratio):
"""
Designs the gear box ratios [-].
:param n_gears:
Number of gears [-].
:type n_gears: int
:param first_gear_box_ratio:
Gear box ratio of the first gear [-].
:type first_gear_box_ratio: float
:param last_gear_box_ratio:
Gear box ratio of the last gear [-].
:type last_gear_box_ratio: float
:return:
Gear box ratios [-].
:rtype: dict
"""
n_gears = int(n_gears)
d = dfl.functions.design_gear_box_ratios
f_two, f_tuning = np.asarray(d.f_two), np.asarray(d.f_tuning)
ix = np.indices((len(f_two), len(f_tuning))).reshape(2, -1).T
f_two, f_tuning = f_two[ix[:, 0]][:, None], f_tuning[ix[:, 1]][:, None]
ratios = np.zeros((ix.shape[0], n_gears), float)
ratios[:, 0], ratios[:, -1] = first_gear_box_ratio, last_gear_box_ratio
n, fgbr, lgbr = n_gears - 1, first_gear_box_ratio, last_gear_box_ratio
f_one = f_tuning * (fgbr / (f_two ** (n * (n - 1) / 2))) ** (1 / n)
n = n_gears - np.arange(2, n_gears)
ratios[:, 1:-1] = lgbr * (f_one ** n) * (f_two ** (n * (n - 1) / 2))
dr = np.diff(ratios, axis=1)
b = np.all(dr < 0, axis=1)
if b.any():
ratios, dr = ratios[b], dr[b]
b = dr[:, 0] < 2
if b.any():
ratios, dr = ratios[b], dr[b]
b = np.all(np.diff(dr, axis=1) > 0, axis=1)
if b.any():
ratios, dr = ratios[b], dr[b]
res = np.linalg.lstsq(
np.vander(np.arange(n_gears - 1), 3), dr.T, rcond=-1
)[0]
b = res[0] < 0
if b.any():
ratios, dr, res = ratios[b], dr[b], res[:, b]
return dict(enumerate(ratios[np.argmin(res[0])], 1))