def Materials(): #Defines magnetic materials for the Undulators Poles and Magnets #Pole (~iron type Va Permendur) material data H = [ 0.8, 1.5, 2.2, 3.6, 5, 6.8, 9.8, 18, 28, 37.5, 42, 55, 71.5, 80, 85, 88, 92, 100, 120, 150, 200, 300, 400, 600, 800, 1000, 2000, 4000, 6000, 10000, 25000, 40000 ] M = [ 0.000998995, 0.00199812, 0.00299724, 0.00499548, 0.00699372, 0.00999145, 0.0149877, 0.0299774, 0.0499648, 0.0799529, 0.0999472, 0.199931, 0.49991, 0.799899, 0.999893, 1.09989, 1.19988, 1.29987, 1.41985, 1.49981, 1.59975, 1.72962, 1.7995, 1.89925, 1.96899, 1.99874, 2.09749, 2.19497, 2.24246, 2.27743, 2.28958, 2.28973 ] convH = 4. * 3.141592653589793e-07 #ma = [] #for i in range(len(H)): ma.append([H[i]*convH, M[i]]) #mp = rad.MatSatIsoTab(ma) #A more compact way: mp = rad.MatSatIsoTab([[H[i] * convH, M[i]] for i in range(len(H))]) #(Permanent) Magnet material: NdFeB with 1.2 Tesla Remanent Magnetization mm = rad.MatStd('NdFeB', 1.2) return mp, mm
def build_box(center, size, material, magnetization, div): n_mag = numpy.linalg.norm(magnetization) g_id = radia.ObjRecMag(center, size, magnetization) if div: radia.ObjDivMag(g_id, div) # do not apply a material unless a magentization of some magnitude has been set if n_mag > 0: radia.MatApl(g_id, radia.MatStd(material, n_mag)) return g_id
def build_model(self): """Build a Radia or Opera model with the current result set.""" length = self.length_spinbox.value() if self.build_button.text() == 'Radia': rad.UtiDelAll() item = self.listview.selectedItems()[0] # build magnet geometry magnet = rad.ObjCnt([rad.ObjThckPgn(0, length, pg[2:].reshape((4, 2)).tolist(), "z", list(pg[:2]) + [0, ]) for pg in self.state['results'][tuple(item.text().split(', '))]]) rad.MatApl(magnet, rad.MatStd('NdFeB', next(c for c in self.controls if c.switch == 'Br').control.value())) # plot geometry in 3d ax = self.plot3d.axes ax.cla() ax.set_axis_off() polygons = rad.ObjDrwVTK(magnet)['polygons'] vertices = np.array(polygons['vertices']).reshape((-1, 3)) # [x, y, z, x, y, z] -> [[x, y, z], [x, y, z]] [set_lim(vertices.min(), vertices.max()) for set_lim in (ax.set_xlim3d, ax.set_ylim3d, ax.set_zlim3d)] vertices = np.split(vertices, np.cumsum(polygons['lengths'])[:-1]) # split to find each face ax.add_collection3d(Poly3DCollection(vertices, linewidths=0.1, edgecolors='black', facecolors=self.get_colour(), alpha=0.2)) # add arrows magnetisation = np.array(rad.ObjM(magnet)).reshape((-1, 6)).T # reshape to [x, y, z, mx, my, mz] for end in (-1, 1): # one at each end of the block, not in the middle magnetisation[2] = end * length / 2 ax.quiver(*magnetisation, color='black', lw=1, pivot='middle') self.tab_control.setCurrentIndex(2) # switch to '3d' tab # solve the model try: rad.Solve(magnet, 0.00001, 10000) # precision and number of iterations except RuntimeError: self.statusBar().showMessage('Radia solve error') # get results dx = 0.1 multipoles = [mpole_names.index(c.label) for c in self.controls if c.label.endswith('pole') and c.get_arg()] i = multipoles[-1] xs = np.linspace(-dx, dx, 4) fit_field = np.polyfit(xs / 1000, [rad.Fld(magnet, 'by', [x, 0, 0]) for x in xs], i) fit_int = np.polyfit(xs / 1000, [rad.FldInt(magnet, 'inf', 'iby', [x, 0, -1], [x, 0, 1]) * 0.001 for x in xs], i) text = '' for j, (l, c, ic, u, iu) in enumerate( zip(mpole_names, fit_field[::-1], fit_int[::-1], units[1:], units[:-1])): if j in multipoles: f = factorial(j) # 1 for dip, quad; 2 for sext; 6 for oct text += f'{l} field = {c * f:.3g} {u}, integral = {ic * f:.3g} {iu}, length = {ic / c:.3g} m\n' ax.text2D(1, 1, text, transform=ax.transAxes, va='top', ha='right', fontdict={'size': 8}) self.plot3d.canvas.draw()
def build_box(center, size, material, magnetization, div, h_m_curve=None): n_mag = numpy.linalg.norm(magnetization) g_id = radia.ObjRecMag(center, size, magnetization) if div: radia.ObjDivMag(g_id, div) # do not apply a material unless a magentization of some magnitude has been set if n_mag > 0: if material == 'custom': mat = radia.MatSatIsoTab( [[_MU_0 * h_m_curve[i][0], h_m_curve[i][1]] for i in range(len(h_m_curve))]) else: mat = radia.MatStd(material, n_mag) radia.MatApl(g_id, mat) return g_id
def materials(H, M, material_type_string, magnet_remanence): """ define magnetic materials for the undulator poles and magnets arguments: H = list of magnetic field values / (Amp/m) M = corresponding magnetization values / T material_type_string = material type string magnet_remanence = remanent magnetization / T return: Radia representations of ... pole-tip material, magnet material """ # -- magnetic property of poles ma = [[sc.mu_0 * H[i], M[i]] for i in range(len(H))] mp = rad.MatSatIsoTab(ma) # -- permanent magnet material mm = rad.MatStd(material_type_string, magnet_remanence) return mp, mm
def materials(h, m, smat, rm): """ define magnetic materials for the undulator poles and magnets arguments: H = list of magnetic field values / (Amp/m) M = corresponding magnetization values / T smat = material type string rm = remanent magnetization / T return: Radia representations of ... pole-tip material, magnet material """ # -- magnetic property of poles ma = [[mu0 * h[i], m[i]] for i in range(len(h))] mp = radia.MatSatIsoTab(ma) # -- permanent magnet material mm = radia.MatStd(smat, rm) return mp, mm
def _radia_material(material_type, magnetization_magnitude, h_m_curve): if material_type == 'custom': return radia.MatSatIsoTab( [[_MU_0 * h_m_curve[i][0], h_m_curve[i][1]] for i in range(len(h_m_curve))] ) return radia.MatStd(material_type, magnetization_magnitude)
#rad.ObjDrwOpenGL(mag01) trf01 = rad.TrfPlSym([0,10,0], [0,1,0]) trf02 = rad.TrfRot([0,10,0], [0,0,1], 1.) trf03 = rad.TrfTrsl([30,10,0]) trf04 = rad.TrfInv() trf05 = rad.TrfCmbL(trf01, trf04) trf06 = rad.TrfCmbR(trf01, trf04) #rad.TrfMlt(mag01, trf03, 3) rad.TrfOrnt(mag01, trf06) #rad.ObjDrwOpenGL(mag01) matNdFeB = rad.MatStd('NdFeB') M = rad.MatMvsH(matNdFeB, 'M', [0,0,0]) print('NdFeB material index:', matNdFeB, ' Magnetization:', M) matLin01 = rad.MatLin([0.1,0.2],1.1) matLin02 = rad.MatLin([0.1,0.2],[0,0,1.1]) print('Linear material indexes:', matLin01, matLin02) dmp = rad.UtiDmp([mag01, trf02], 'bin') #print(dmp) elemsRest = rad.UtiDmpPrs(dmp) print('Indexes of restored elements:', elemsRest) #rad.ObjDrwOpenGL(elemsRest[0]) print(rad.UtiDmp(elemsRest[0], 'asc'))
def build(self): """Create a quadrupole with the given geometry.""" if self.solve_state < SolveState.SHAPES: self.define_shapes() rad.UtiDelAll() origin = [0, 0, 0] nx = [1, 0, 0] ny = [0, 1, 0] nz = [0, 0, 1] tip_mesh = round(self.min_mesh) pole_mesh = round(self.min_mesh * self.pole_mult) yoke_mesh = round(self.min_mesh * self.yoke_mult) length = self.length # Subdivide the pole tip cylindrically. The axis is where the edge of the tapered pole meets the Y-axis. points = rotate45(self.tip_points) x2, y2 = points[-2] # top right of pole x3, y3 = points[-3] # bottom right of pole m = (y2 - y3) / (x2 - x3) c = y2 - m * x2 pole_tip = rad.ObjThckPgn(length / 2, length, points, "z") # Slice off the chamfer (note the indexing at the end here - selects the pole not the cut-off piece) pole_tip = rad.ObjCutMag(pole_tip, [length - self.chamfer, 0, self.r], [1, 0, -1])[0] n_div = max(1, round(math.sqrt((x2 - x3) ** 2 + (y2 - y3) ** 2) / pole_mesh)) # We have to specify the q values here (second element of each sublist in the subdivision argument) # otherwise weird things happen mesh = [[n_div, 4], [tip_mesh / 3, 1], [tip_mesh, 1]] div_opts = 'Frame->Lab;kxkykz->Size' # rad.ObjDivMag(pole_tip, [[tip_mesh, 1], [tip_mesh, 1], [tip_mesh, 3]], div_opts) rad.ObjDivMag(pole_tip, mesh, "cyl", [[[0, c, 0], nz], nx, 1], div_opts) rad.TrfOrnt(pole_tip, rad.TrfRot(origin, nz, -math.pi / 4)) pole = rad.ObjThckPgn(length / 2, length, rotate45(self.pole_points), "z") rad.ObjDivMag(pole, [pole_mesh, ] * 3, div_opts) rad.TrfOrnt(pole, rad.TrfRot(origin, nz, -math.pi / 4)) # Need to split yoke since Radia can't build concave blocks points = rotate45(self.yoke_points[:2] + self.yoke_points[-2:]) # yoke1 is the part that joins the pole to the yoke # Subdivide this cylindrically since the flux goes around a corner here # The axis is the second point (x1, y1) x1, y1 = points[1] yoke1 = rad.ObjThckPgn(length / 2, length, points, "z") cyl_div = [[[x1, y1, 0], nz], [self.width, self.width, 0], 1] # The first (kr) argument, corresponding to radial subdivision, # in rad.ObjDivMag cuts by number not size even though kxkykz->Size is specified. # So we have to fudge this. It seems to require a larger number to give the right number of subdivisions. n_div = max(1, round(2 * self.width / yoke_mesh)) rad.ObjDivMag(yoke1, [n_div, yoke_mesh, yoke_mesh], "cyl", cyl_div, div_opts) rad.TrfOrnt(yoke1, rad.TrfRot(origin, nz, -math.pi / 4)) # For the second part of the yoke, we use cylindrical subdivision again. But the axis is not on the corner; # instead we calculate the point where the two lines converge (xc, yc). points = self.yoke_points[1:3] + self.yoke_points[-3:-1] x0, y0 = points[0] x1, y1 = points[1] x2, y2 = points[2] x3, y3 = points[3] m1 = (y3 - y0) / (x3 - x0) m2 = (y2 - y1) / (x2 - x1) c1 = y0 - m1 * x0 c2 = y1 - m2 * x1 xc = (c2 - c1) / (m1 - m2) yc = m1 * xc + c1 yoke2 = rad.ObjThckPgn(length / 2, length, points, 'z') cyl_div = [[[xc, yc, 0], nz], [x3 - xc, y3 - yc, 0], 1] n_div = max(1, round(0.7 * n_div)) # this is a bit of a fudge rad.ObjDivMag(yoke2, [n_div, yoke_mesh, yoke_mesh], "cyl", cyl_div, div_opts) yoke3 = rad.ObjThckPgn(length / 2, length, self.yoke_points[2:6], "z") rad.ObjDivMag(yoke3, [yoke_mesh, ] * 3, div_opts) steel = rad.ObjCnt([pole_tip, pole, yoke1, yoke2, yoke3]) rad.ObjDrwAtr(steel, [0, 0, 1], 0.001) # blue steel rad.TrfOrnt(steel, rad.TrfRot(origin, ny, -math.pi / 2)) rad.ObjDrwOpenGL(steel) rad.TrfOrnt(steel, rad.TrfRot(origin, ny, math.pi / 2)) # rad.TrfMlt(steel, rad.TrfPlSym([0, 0, 0], [1, -1, 0]), 2) # reflect along X=Y line to create a quadrant rad.TrfZerPerp(steel, origin, [1, -1, 0]) rad.TrfZerPerp(steel, origin, nz) steel_material = rad.MatSatIsoFrm([2000, 2], [0.1, 2], [0.1, 2]) steel_material = rad.MatStd('Steel42') steel_material = rad.MatSatIsoFrm([959.703184, 1.41019852], [33.9916543, 0.5389669], [1.39161186, 0.64144324]) rad.MatApl(steel, steel_material) coil = rad.ObjRaceTrk(origin, [5, 5 + self.coil_width], [self.coil_x * 2 - self.r, length * 2], self.coil_height, 4, self.current_density) rad.TrfOrnt(coil, rad.TrfRot(origin, nx, -math.pi / 2)) rad.TrfOrnt(coil, rad.TrfTrsl([0, self.r + self.taper_height + self.coil_height / 2, 0])) rad.TrfOrnt(coil, rad.TrfRot(origin, nz, -math.pi / 4)) rad.ObjDrwAtr(coil, [1, 0, 0], 0.001) # red coil quad = rad.ObjCnt([steel, coil]) rad.TrfZerPara(quad, origin, nx) rad.TrfZerPara(quad, origin, ny) # rad.ObjDrwOpenGL(quad) self.radia_object = quad self.solve_state = SolveState.BUILT
mag07 = rad.ObjCylMag([0,20,0], 5, 10, 21, 'z', [0,0,1]) mag08 = rad.ObjRecCur([-15,0,0], [5,7,15], [0.5,0.5,1.]) mag09 = rad.ObjArcCur([0,0,-5], [10,13], [0,2.5], 10, 15, 1.7, 'man', 'z') mag10 = rad.ObjRaceTrk([0,0,0], [27,28], [1,2.5], 5, 15, 1.7, 'man', 'z') mag11 = rad.ObjFlmCur([[-10,-30,-10],[30,-30,-10],[30,25,25],[-30,25,25],[-30,-30,-10]], 10.2) mag = rad.ObjCnt([mag00, mag01, mag02, mag03, mag04, mag05, mag06, mag07, mag08, mag09]) rad.ObjAddToCnt(mag, [mag10, mag11]) cnt02 = rad.ObjCnt([mag00, mag]) mat = rad.MatStd('NdFeB', 1.2) rad.MatApl(mag01, mat) print('Magn. Material index:', mat, ' appled to object:', mag01) magDpl = rad.ObjDpl(mag, 'FreeSym->False') print('Number of objects in the container:', rad.ObjCntSize(mag)) print('Number of objects in 2nd container:', rad.ObjCntSize(cnt02)) print('Number of objects in fake container:', rad.ObjCntSize(mag04)) print('Indices of elements in the container:', rad.ObjCntStuf(mag)) print('Indices of elements in the duplicated container:', rad.ObjCntStuf(magDpl)) #rad.ObjDrwOpenGL(mag) #rad.ObjDrwOpenGL(magDpl)