def derive_mm_w_pm(GP, SD): GP["mm_w_pm"].value = ( GP['mm_r_os'].value - GP["mm_d_bg_air"].value - (GP['mm_r_ri'].value + GP['mm_d_ri'].value)) / np.cos( GP['deg_alpha_vspm'].value) - GP['mm_d_pm'].value * np.tan( GP['deg_alpha_vspm'].value) return GP["mm_w_pm"].value
def transmission(xvals, parms): #position=p[0]; intensity=p[1]; slit=p[2]; stth=p[3]; background=p[4]; thickness=p[5]; absorption=p[6] #x0=p[0]; i0=p[1]; w=p[2]; theta=p[3]; ib=p[4]; thick=p[5]; u=p[6]; #th = np.deg2rad(theta) #p0 = w * np.cos(th)/np.cos(2*th) #out = [] #for x in xvals: # if x < (x0 - p0): # val = ib # elif ((x>=x0-p0) and (x < x0)): # val = i0*(x-x0+p0)*(x-x0+p0)+ib # elif ((x>=x0) and (x<(x0+p0))): # val = i0*(2.0*p0*p0-(x0+p0-x)*(x0+p0-x))+ib # elif (x>=x0+p0): # val=2*i0*p0*p0 +ib # out = out + [val] x0 = parms[0] i0 = parms[1] w = parms[2] theta = parms[3] ib = parms[4] thick = parms[5] u = parms[6] th = np.deg2rad(theta) p = w * np.cos(th) Atot = w * w / np.sin(2.0 * th) out = [] for x in xvals: if (x <= (x0 - p)): val = ib elif ((x > (x0 - p)) and (x <= x0)): val = ib + i0 * ((x - (x0 - p)) * ((x - (x0 - p)) * np.tan(th))) / Atot elif ((x > x0) and (x <= x0 + p)): val = ib + i0 * (Atot - (x0 + p - x) * (x0 + p - x) * np.tan(th)) / Atot elif (x > x0 + p): val = ib + i0 out = out + [val] return np.array(out)
def wall(xvals, parms): #position=p[0]; intensity=p[1]; slit=p[2]; stth=p[3]; background=p[4]; thickness=p[5]; absorption=p[6] midpoint = parms[0] i0 = parms[1] w = parms[2] theta = parms[3] ib = parms[4] thick = parms[5] u = parms[6] midpoint = parms[0] x0 = midpoint - thick / 2.0 th = np.deg2rad(theta) p = w * np.cos(th) Atot = w * w / np.sin(2.0 * th) out = [] for x in xvals: if (x <= (x0 - p)): val = ib #elif ((x0-p) >= (x-thick)) and ((x0+p) >= x): #Gauge volume is smaller than thickness if ((x > (x0 - p)) and (x0 - p > (x - thick)) and (x <= x0)): val = ib + i0 * ((x - (x0 - p)) * ((x - (x0 - p)) * np.tan(th))) / Atot elif ((x > x0) and (x <= x0 + p) and (x0 - p > (x - thick))): val = ib + i0 * (Atot - (x0 + p - x) * (x0 + p - x) * np.tan(th)) / Atot elif (x0 - p > (x - thick) and (x0 + p < x)): #Gauge volume is smaller than thickness val = ib + i0 elif (x0 - p < (x - thick) and (x0 + p > x)): #Gauge volume is larger than thickness A2 = (x0 + p - x) * (x0 + p - x) * np.tan(th) A3 = ((x - thick) - (x0 - p)) * (((x - thick) - (x0 - p)) * np.tan(th)) val = ib + i0 * (Atot - A2 - A3) / Atot elif ((x0 - p) < (x - thick)) and ((x0 + p) < x) and (x0 >= (x - thick)): A3 = ((x - thick) - (x0 - p)) * (((x - thick) - (x0 - p)) * np.tan(th)) val = ib + i0 * (Atot - A3) / Atot elif (x0 < (x - thick) and ((x0 + p >= (x - thick)))): A2 = (x0 + p - (x - thick)) * ((x0 + p) - (x - thick)) * np.tan(th) val = ib + i0 * (A2 / Atot) elif (x0 + p < (x - thick)): val = ib #elif ((x0-p) < (x-thick)) and ((x0+p) >= x): #Gauge volume is larger than thickness # A2 = (x0+p-x)*(x0+p-x)*np.tan(th) # A3 = ((x-thick)-(x0-p))*(((x-thick)-(x0-p))*np.tan(th)) # val = ib + i0*(Atot-A2-A3)/Atot out = out + [val] return np.array(out)
def reflection1(xvals, parms): #position=p[0]; intensity=p[1]; slit=p[2]; stth=p[3]; background=p[4]; thickness=p[5]; absorption=p[6] x0 = parms[0] i0 = parms[1] w = parms[2] theta = parms[3] ib = parms[4] thick = parms[5] u = parms[6] th = np.deg2rad(theta) p = w * np.sin(th) Atot = w * w / np.sin(2.0 * th) out = [] ni = 5 irng = np.array(range(1, ni + 1)) for x in xvals: if x < (x0 - p): val = ib elif ((x0 - p) < x and x0 > x): l1 = x - (x0 - p) nrleft = int(np.ceil(l1 / (2 * p) * ni)) if nrleft < 1: nrleft = 1 irngleft = np.array(range(1, nrleft + 1)) dl1 = l1 / float(nrleft) dl = irngleft * dl1 triA = dl * dl / np.tan(th) #triangle areas secA = [triA[0] ] + [triA[i] - triA[i - 1] for i in range(1, nrleft)] #section areas secA = np.array(secA) m1 = np.linspace( x0 - p + dl1 / 2.0, x - dl1 / 2.0, nrleft ) #section midpoint position - path length calculated from this plen = np.abs(2 * m1 / np.sin(th)) val = ib + np.sum(i0 * secA * np.exp(-u * plen)) elif (x0 <= x) and (x0 + p >= x): l1 = p nrleft = int(np.ceil(l1 / (2 * p) * ni)) if nrleft < 1: nrleft = 1 irngleft = np.array(range(1, nrleft + 1)) dl1left = l1 / float(nrleft) dlleft = irngleft * dl1left triAleft = dlleft * dlleft / np.tan(th) #triangle areas secAleft = [triAleft[0]] + [ triAleft[i] - triAleft[i - 1] for i in range(1, nrleft) ] #section areas secAleft = np.array(secAleft) m1left = np.linspace(x0 - p + dl1left / 2.0, x0 - dl1left / 2.0, nrleft) + (x - x0) plenleft = np.abs(2 * m1left / np.sin(th)) valleft = np.sum(i0 * secAleft * np.exp(-u * plenleft)) l2 = x - x0 nrright = int(np.ceil(x - x0 / (2 * p) * ni)) if nrright < 1: nrright = 1 irngright = np.array(range(1, nrright + 1)) dl1right = l2 / float(nrright) dlright = p - np.append(0.0, dl1right * irngright) triAright = dlright * dlright / np.tan(th) secAright = [ triAright[i] - triAright[i + 1] for i in range(nrright) ] secAright = np.array(secAright) m1right = np.linspace(x - x0 - dl1right / 2.0, dl1right / 2.0, nrright) plenright = np.abs(2 * m1right / np.sin(th)) valright = np.sum(i0 * secAright * np.exp(-u * plenright)) val = ib + valleft + valright elif (x > x0 + p): l1 = p #nrleft = int(np.ceil(l1/(x-(x0-p))*ni)); nrleft = int(np.ceil(l1 / (2 * p) * ni)) if nrleft < 1: nrleft = 1 irngleft = np.array(range(1, nrleft + 1)) dl1left = l1 / float(nrleft) dlleft = irngleft * dl1left triAleft = dlleft * dlleft / np.tan(th) #triangle areas secAleft = [triAleft[0]] + [ triAleft[i] - triAleft[i - 1] for i in range(1, nrleft) ] #section areas secAleft = np.array(secAleft) m1left = np.linspace(x0 - p + dl1left / 2.0, x0 - dl1left / 2.0, nrleft) + (x - x0) plenleft = np.abs(2 * m1left / np.sin(th)) valleft = np.sum(i0 * secAleft * np.exp(-u * plenleft)) l2 = p nrright = int(np.ceil(l2 / (2 * p) * ni)) if nrright < 1: nrright = 1 irngright = np.array(range(1, nrright + 1)) dl1right = l2 / float(nrright) dlright = p - np.append(0.0, dl1right * irngright) triAright = dlright * dlright / np.tan(th) secAright = [ triAright[i] - triAright[i + 1] for i in range(nrright) ] secAright = np.array(secAright) m1right = np.linspace(dlright[0] - dl1right / 2.0, dlright[-1] + dl1right / 2.0, nrright) + (x - (x0 + p)) plenright = np.abs(2 * m1right / np.sin(th)) valright = np.sum(i0 * secAright * np.exp(-u * plenright)) val = ib + valleft + valright out = out + [val] return np.array(out)
def walltransmission(xvals, parms): #position=p[0]; intensity=p[1]; slit=p[2]; stth=p[3]; background=p[4]; thickness=p[5]; absorption=p[6] midpoint = parms[0] i0 = parms[1] w = parms[2] theta = parms[3] ib = parms[4] thick = parms[5] u = parms[6] midpoint = parms[0] x0 = midpoint - thick / 2.0 th = np.deg2rad(theta) p = w * np.cos(th) t = thick Atot1 = w * w / np.sin(2.0 * th) Atot = 2 * w * np.sin(th) * w * np.cos(th) out = [] baselength = 2 * p Gvol_area = 2 * w * w * np.sin(th) * np.cos(th) if baselength > thick: Ar = 0.5 * (p - thick / 2.0) * (p - thick / 2.0) * np.tan(th) maxbeam = Gvol_area - 4.0 * Ar else: maxbeam = Gvol_area for x in xvals: x1 = x x2 = x - thick if (x1 <= (x0 - p)) and (x2 <= x0 - p): val = ib elif (x0 - p) >= x2 and (x0 - p <= x1) and (x0 > x1): A = (x1 - (x0 - p)) val = ib + A * A * np.tan(th) / maxbeam * i0 elif (x0 - p <= x2) and (x0 >= x1): C = (x1 - (x0 - p)) B = (x2 - (x0 - p)) val = ib + (C * C * np.tan(th) - B * B * np.tan(th)) / maxbeam * i0 elif (x2 <= (x0 - p)) and (x0 >= x2) and (x0 <= x1) and (x1 <= (x0 + p)): A = (x1 - (x0 + p)) val = ib + (Gvol_area - A * A * np.tan(th)) / maxbeam * i0 elif (x2 <= (x0 - p)) and (x0 >= x2) and (x0 <= x1) and (x1 >= (x0 + p)): val = ib + i0 elif (x2 >= (x0 - p)) and (x0 >= x2) and (x0 <= x1) and (x1 <= (x0 + p)): A = (x1 - (x0 + p)) B = (x2 - (x0 - p)) val = ib + (Gvol_area - A * A * np.tan(th) - B * B * np.tan(th)) / maxbeam * i0 elif (x2 >= (x0 - p)) and (x0 >= x2) and (x0 <= x1) and (x1 >= (x0 + p)): B = (x2 - (x0 - p)) val = ib + (Gvol_area - B * B * np.tan(th)) / maxbeam * i0 elif (x0 + p >= x1) and (x0 <= x2): A = (x1 - (x0 + p)) C = (x2 - (x0 + p)) val = ib + (C * C * np.tan(th) - A * A * np.tan(th)) / maxbeam * i0 elif (x2 >= (x0 - p)) and (x0 <= x2) and (x0 <= x1) and ( x1 >= (x0 + p)) and (x2 <= (x0 + p)): A = (x0 + p - x2) val = ib + A * A * np.tan(th) / maxbeam * i0 elif (x0 - p) >= x2 and (x0 + p) <= x2: val = ib out = out + [val] return np.array(out)
def redraw_cross_section_outline_with_pyx(tool_tikz, no_repeat_stator, no_repeat_rotor, mm_rotor_outer_radius, mm_air_gap_length, mm_rotor_outer_steel_radius, mm_rotor_inner_radius): # PyX tool_tikz.c = pyx.canvas.canvas( ) # clear the canvas because we want to redraw 90 deg with the data tool_tikz.track_path print('Index | Path data') p_stator = None #pyx.path.path() p_rotor = None #pyx.path.path() for index, path in enumerate( tool_tikz.track_path ): # track_path is passed by reference and is changed by mirror # Failed to fill the closed path, because there is no arc-like path available. # p = pyx.path.line(4, 0, 5, 0) << pyx.path.line(5, 0, 5, 1) << pyx.path.line(5, 1, 4, 1) # p.append(path.closepath()) # tool_tikz.c.stroke(p) # tool_tikz.c.stroke(path.rect(0, 0, 1, 1), [pyx.style.linewidth.Thick, # pyx.color.rgb.red, # pyx.deco.filled([pyx.color.rgb.green])]) path_mirror = deepcopy(path) # for mirror copy (along x-axis) path_mirror[1] = path[1] * -1 path_mirror[3] = path[3] * -1 # for mirror copy (along y-axis) # path_mirror[0] = path[0]*-1 # path_mirror[2] = path[2]*-1 bool_exclude_path = False # rotate path and plot if is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): Q = no_repeat_stator else: Q = no_repeat_rotor * 2 EPS = 1e-6 if is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): # 按照Eric的要求,把不必要的线给删了。 if abs(path[1] + path[3]) < EPS: # 镜像对称线 bool_exclude_path = True if abs(path[0] - path[2]) + np.cos( 2 * np.pi / Q / 2) < EPS: # 旋转对称线(特别情况,tan(90°) = ∞ bool_exclude_path = True else: if abs( abs((path[1] - path[3]) / (path[0] - path[2])) - abs(np.tan(2 * np.pi / Q / 2))) < EPS: # 旋转对称线 bool_exclude_path = True if not is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): # 按照Eric的要求,把不必要的线给删了。 if (abs(np.sqrt(path[0]**2+path[1]**2) - mm_rotor_inner_radius)<EPS or abs(np.sqrt(path[2]**2+path[3]**2) - mm_rotor_inner_radius)<EPS) \ and (len(path)==4): # 转子铁芯内径到外径的直线(len(path)==4) bool_exclude_path = True # # 特别的是,画永磁体的时候,边界要闭合哦。 # if abs(np.sqrt(path[0]**2+path[1]**2) - mm_rotor_outer_steel_radius) < EPS or abs(np.sqrt(path[2]**2+path[3]**2) - mm_rotor_outer_steel_radius) < EPS: # bool_exclude_path = False # A trick that makes sure models with different outer diameters have the same scale. # tool_tikz.draw_arc([125,0], [-125,0], relangle=sign*180, untrack=True) tool_tikz.c.fill( pyx.path.circle(0, 0, 125), [pyx.color.transparency(1)] ) # use this if THICK is used. <- Warn: Transparency not available in PostScript, proprietary ghostscript extension code inserted. (save as eps format) # tool_tikz.c.fill(pyx.path.circle(0, 0, 125), [pyx.color.rgb.white]) # use this if THICK is used. <- this will over-write everthing... how to change zorder? _ = 2 * np.pi / Q if True: # full model for counter in range(Q): # 转子:旋转复制 if not is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): path[0], path[1] = rotate(_, path[0], path[1]) path[2], path[3] = rotate(_, path[2], path[3]) 路径 = tool_tikz.pyx_draw_path( path, sign=1, bool_exclude_path=bool_exclude_path, bool_stroke=True) if 路径 is not None: if p_rotor is None: p_rotor = 路径 else: p_rotor = p_rotor << 路径 # 定子:镜像+旋转复制 if is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): path[0], path[1] = rotate(_, path[0], path[1]) path[2], path[3] = rotate(_, path[2], path[3]) 路径 = tool_tikz.pyx_draw_path( path, sign=1, bool_exclude_path=bool_exclude_path, bool_stroke=True) # print(index, '\t|', ',\t'.join(['%g'%(el) for el in path])) if 路径 is not None: if p_stator is None: p_stator = 路径 else: p_stator = p_stator << 路径 path_mirror[0], path_mirror[1] = rotate( _, path_mirror[0], path_mirror[1]) path_mirror[2], path_mirror[3] = rotate( _, path_mirror[2], path_mirror[3]) 路径 = tool_tikz.pyx_draw_path( path_mirror, sign=-1, bool_exclude_path=bool_exclude_path, bool_stroke=True) if 路径 is not None: if p_stator is None: p_stator = 路径 else: p_stator = p_stator << 路径 # break else: # backup # 转子:旋转复制 if not is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): path[0], path[1] = rotate(0.5 * np.pi - 0.5 * 0.5 * _, path[0], path[1]) path[2], path[3] = rotate(0.5 * np.pi - 0.5 * 0.5 * _, path[2], path[3]) pyx_draw_path(tool_tikz, path, sign=1, bool_exclude_path=bool_exclude_path) # print(index, '\t|', ',\t'.join(['%g'%(el) for el in path])) # path[0], path[1] = rotate(0.5*np.pi - 0*0.5*_, path[0], path[1]) # path[2], path[3] = rotate(0.5*np.pi - 0*0.5*_, path[2], path[3]) # pyx_draw_path(tool_tikz, path, sign=1, bool_exclude_path=bool_exclude_path) # 定子:镜像+旋转复制 if is_at_stator(path, mm_rotor_outer_radius, mm_air_gap_length): path[0], path[1] = rotate(0.5 * np.pi - 0.5 * _, path[0], path[1]) path[2], path[3] = rotate(0.5 * np.pi - 0.5 * _, path[2], path[3]) pyx_draw_path(tool_tikz, path, sign=1, bool_exclude_path=bool_exclude_path) # print(index, '\t|', ',\t'.join(['%g'%(el) for el in path])) path_mirror[0], path_mirror[1] = rotate( 0.5 * np.pi - 0.5 * _, path_mirror[0], path_mirror[1]) path_mirror[2], path_mirror[3] = rotate( 0.5 * np.pi - 0.5 * _, path_mirror[2], path_mirror[3]) pyx_draw_path(tool_tikz, path_mirror, sign=-1, bool_exclude_path=bool_exclude_path) # 注意,所有 tack_path 中的 path 都已经转动了90度了! # for mirror copy (along y-axis) path[0] *= -1 path[2] *= -1 pyx_draw_path(tool_tikz, path, sign=-1, bool_exclude_path=bool_exclude_path) path_mirror[0] *= -1 path_mirror[2] *= -1 pyx_draw_path(tool_tikz, path_mirror, sign=1, bool_exclude_path=bool_exclude_path)
def ModifiedBianchi2006(self, fea_config_dict, SD, GP, OP): air_gap_flux_density_B = SD['guess_air_gap_flux_density_B'] # air_gap_flux_density_B = 0.9 stator_tooth_flux_density_B_ds = SD[ 'guess_stator_tooth_flux_density_B_ds'] # stator_tooth_flux_density_B_ds = 1.5 stator_yoke_flux_density_Bys = SD['guess_stator_yoke_flux_density_Bys'] if SD['p'] >= 2: ROTOR_STATOR_YOKE_HEIGHT_RATIO = 0.75 alpha_rm_over_alpha_rp = 1.0 # stator_yoke_flux_density_Bys = 1.2 else: # penalty for p=1 motor, i.e., large yoke height ROTOR_STATOR_YOKE_HEIGHT_RATIO = 0.5 alpha_rm_over_alpha_rp = 0.75 # stator_yoke_flux_density_Bys = 1.5 stator_outer_diameter_Dse = 0.128 # m stator_outer_radius_r_os = 0.5 * stator_outer_diameter_Dse speed_rpm = SD['ExcitationFreqSimulated'] * 60 / SD['p'] # rpm split_ratio = 0.5 # refer to 2020-MLMS-0953@Fig. 5 stator_inner_radius_r_is = stator_outer_radius_r_os * split_ratio stator_inner_diameter_Dis = stator_inner_radius_r_is * 2 mm_sleeve_length = 0.5 mm_airgap_plus_sleeve_length = SD[ 'minimum_mechanical_air_gap_length_mm'] + mm_sleeve_length rotor_outer_radius_r_or = stator_inner_radius_r_is - mm_airgap_plus_sleeve_length * 1e-3 # m rotor_outer_diameter_Dr = rotor_outer_radius_r_or * 2 # Bianchi2006@(1)--(3) stator_yoke_height_h_ys = air_gap_flux_density_B * np.pi * stator_inner_diameter_Dis * alpha_rm_over_alpha_rp / ( 2 * stator_yoke_flux_density_Bys * 2 * SD['p']) stator_tooth_height_h_ds = ( stator_outer_diameter_Dse - stator_inner_diameter_Dis) / 2 - stator_yoke_height_h_ys stator_slot_height_h_ss = stator_tooth_height_h_ds stator_tooth_width_b_ds = air_gap_flux_density_B * np.pi * stator_inner_diameter_Dis / ( stator_tooth_flux_density_B_ds * SD['Qs']) # Bianchi2006@(4) OP['stator_slot_area'] = stator_slot_area = np.pi / (4 * SD['Qs']) * ( (stator_outer_diameter_Dse - 2 * stator_yoke_height_h_ys)**2 - stator_inner_diameter_Dis** 2) - stator_tooth_width_b_ds * stator_tooth_height_h_ds # Bianchi2006@(5) slot_pitch_pps = np.pi * (stator_inner_diameter_Dis + stator_slot_height_h_ss) / SD['Qs'] kov = 1.8 # \in [1.6, 2.0] OP['end_winding_length_Lew'] = end_winding_length_Lew = np.pi * 0.5 * ( slot_pitch_pps + stator_tooth_width_b_ds ) + slot_pitch_pps * kov * (SD['coil_pitch_y'] - 1) Q = SD['Qs'] p = SD['p'] # STATOR GP['deg_alpha_st'].value = 360 / Q - 2 # deg GP['deg_alpha_so'].value = GP[ 'deg_alpha_st'].value / 2 # im_template uses alpha_so as 0. GP['mm_r_si'].value = 1e3 * stator_inner_radius_r_is # mm GP['mm_r_os'].value = 1e3 * stator_outer_diameter_Dse / 2 # mm GP['mm_d_so'].value = 1 # mm GP['mm_d_sp'].value = 1.5 * GP['mm_d_so'].value GP['mm_d_st'].value = 1e3 * ( 0.5 * stator_outer_diameter_Dse - stator_yoke_height_h_ys ) - GP['mm_r_si'].value - GP['mm_d_sp'].value # mm GP['mm_d_sy'].value = 1e3 * stator_yoke_height_h_ys # mm GP['mm_w_st'].value = 1e3 * stator_tooth_width_b_ds # mm # ROTOR GP['mm_d_sleeve'].value = mm_sleeve_length GP['mm_d_fixed_air_gap'].value = SD[ 'minimum_mechanical_air_gap_length_mm'] GP['split_ratio'].value = split_ratio GP['mm_d_pm'].value = 4 # mm GP['mm_d_ri'].value = 1e3 * ROTOR_STATOR_YOKE_HEIGHT_RATIO * stator_yoke_height_h_ys # TODO:This ratio (0.75) is randomly specified GP['mm_r_or'].value = 1e3 * rotor_outer_radius_r_or GP['mm_r_ri'].value = 1e3 * stator_inner_radius_r_is - GP[ 'mm_d_pm'].value - GP['mm_d_ri'].value - GP[ 'mm_d_sleeve'].value - GP['mm_d_fixed_air_gap'].value # Vernier specific GP["deg_alpha_vspm"].value = 20.3 GP["mm_d_bg_air"].value = 1.5 GP["mm_d_bg_magnet"].value = 1.5 GP["mm_w_pm"].value = ( GP['mm_r_os'].value - GP["mm_d_bg_air"].value - (GP['mm_r_ri'].value + GP['mm_d_ri'].value)) / np.cos( GP['deg_alpha_vspm'].value) - GP['mm_d_pm'].value * np.tan( GP['deg_alpha_vspm'].value)