def __init__(self, config, family='S', nTF=16, obj='L'): self.nTF = nTF self.config = config datadir = trim_dir('../../Data') file = 'salome_input' # config # +'_{}{}{}'.format(family,nTF,obj) self.filename = datadir + '/' + file + '.json' self.profile = Profile(config['TF'], family=family, load=True, part='TF', nTF=nTF, obj=obj, npoints=250) setup = Setup(config['eq']) self.sf = SF(setup.filename) self.tf = TF(self.profile, sf=self.sf) self.pf = PF(self.sf.eqdsk) self.PF_support() # calculate PF support seats self.CS_support() # calculate CS support seats self.Gravity_support() self.cage = coil_cage(nTF=nTF, rc=self.tf.rc, ny=3, plasma={'config': config['eq']}, coil=self.tf.x['cl']) self.eq = EQ(self.sf, self.pf, dCoil=0.5, sigma=0, boundary=self.sf.get_sep(expand=0.5), n=1e3) self.eq.plasma() self.ff = force_feild(self.pf.index, self.pf.coil, self.eq.coil, self.eq.plasma_coil)
def __init__(self, sf, setup, npoints=500): self.setup = setup self.sf = sf self.npoints = npoints self.dataname = setup.configuration self.datadir = trim_dir('../../../Data/') self.segment = {} # store section segments (divertor,fw,blanket...)
def __init__(self, file, directory='../../Data/'): directory = trim_dir(directory) self.file = directory + file + '.pkl' self.data = { 'rb': None, 'sf': None, 'eq': None, 'cc': None, 'inv': None, 'ax': None, 'pf': None } self.data = od(sorted(self.data.items(), key=lambda x: x[0])) self.inmemory = False
def __init__(self, name, family='S', part='TF', npoints=200, symetric=False, read_write=True, **kwargs): self.npoints = npoints self.name = name self.part = part self.read_write = read_write self.initalise_loop(family, npoints, symetric=symetric) # initalize loop object data_dir = trim_dir('../../Data/') self.dataname = data_dir + self.name + '_{}.pkl'.format(part) self.nTF = kwargs.get('nTF', 'unset') self.obj = kwargs.get('obj', 'L') self.read_loop_dict()
def ansys(self, plot=False, nl=250, nr=5, ny=5): datadir = trim_dir('../../Data/') filename = datadir + 'TFload_{:d}'.format(self.nTF) ans = table(filename) ans.f.write('! loading tables for {:d}TF coil concept\n'.format( self.nTF)) ans.f.write('! loop length parameterized from 0-1\n') ans.f.write('! loop starts at the inboard midplane\n') ans.f.write('! loop progresses in the anti-clockwise direction\n') ans.f.write('! tables defined with cylindrical coordinate system\n') ans.f.write( '! body applied to nodes of winding-pack in cartisean system x,y,z\n' ) ans.f.write( '! winding-pack must be labled as named-selection \'wp\'\n') ans.f.write('\nlocal,11,1,{:1.9f},0,{:1.9f},0,90,0'\ .format(self.sf.mo[0],self.sf.mo[1])) ans.f.write(' ! define local cylindrical coordinate system\n') ans.f.write('csys,0 ! restore to cartesian\n') ans.f.write('\n! per-TF PF coil forces (Fr,Fz) [N]\n') ans.f.write('! order as numbered in plots\n') F = self.ff.get_force()['F'] ans.load('F_coil', 1e6 * F / self.nTF) ans.write_array() apdlstr = ''' nPF = 4 *do,i,1,nPF F,c%i-1%,Fz,1e6*F_coil(i,2) *enddo F,cs,Fz,1e6*F_coil(i+1,2) ''' ans.f.write('\n/nopr ! suppress large table output\n') self.tf.loop_interpolators(offset=0, full=True) # construct TF interpolators TFloop = self.tf.fun['cl'] ngrid = {'nr': 20, 'nt': 150} # coordinate interpolation grid ndata = { 'nl': nl, 'nr': nr, 'ny': ny } # coordinate interpolation grid l = np.linspace(0, 1, 250) # calculate grid extent xin, zin = self.tf.fun['in']['r'](l), self.tf.fun['in']['z'](l) rin = np.sqrt((xin - self.sf.mo[0])**2 + (zin - self.sf.mo[1])**2) rmin = np.min(rin) # minimum radius xout, zout = self.tf.fun['out']['r'](l), self.tf.fun['out']['z'](l) rout = np.sqrt((xout - self.sf.mo[0])**2, (zout - self.sf.mo[1])**2) rmax = np.max(rout) # maximum radius radius = np.linspace(rmin, rmax, ngrid['nr']) theta = np.linspace(-np.pi, np.pi, ngrid['nt']) l_map = np.zeros((ngrid['nr'], ngrid['nt'])) dr_map = np.zeros((ngrid['nr'], ngrid['nt'])) for i in range(ngrid['nr']): for j in range(ngrid['nt']): x = self.sf.mo[0] + radius[i] * np.cos(theta[j]) z = self.sf.mo[1] + radius[i] * np.sin(theta[j]) L = minimize_scalar(OCC.OIS_placment, method='bounded', args=(TFloop, (x, z)), bounds=[0, 1]).x xl, zl = TFloop['r'](L), TFloop['z'](L) l_map[i, j] = L dr_map[i,j] = np.sqrt((x-xl)**2+(z-zl)**2)*\ np.sign(np.dot([x-xl,z-zl],[x-self.sf.mo[0],z-self.sf.mo[1]])) width = self.tf.section['winding_pack']['width'] depth = self.tf.section['winding_pack']['depth'] cross_section = width * depth l_data = np.linspace(0, 1, ndata['nl']) if ndata['nr'] > 1: dr_data = np.linspace(-width / 2, width / 2, ndata['nr']) else: dr_data = np.array([0]) if ndata['ny'] > 1: dy_data = np.linspace(-depth / 2, depth / 2, ndata['ny']) else: dy_data = np.array([0]) Fbody = {} for var in ['x', 'y', 'z']: Fbody[var] = np.zeros((ndata['nl'], ndata['nr'], ndata['ny'])) self.tf.loop_interpolators(offset=0, full=True) # centreline Jturn = self.cage.Iturn / cross_section # current density magnitude for i, l in enumerate(l_data): iter_str = '\rcalculating TF body force:' iter_str += 'segment {:d} of {:d}'.format(i, ndata['nl']) sys.stdout.write(iter_str) sys.stdout.flush() xo = self.tf.fun['cl']['r'](l) zo = self.tf.fun['cl']['z'](l) dxo = self.tf.fun['cl']['dr'](l) dzo = self.tf.fun['cl']['dz'](l) that = np.array([dxo, 0, dzo]) that /= np.linalg.norm(that) J = Jturn * that # current density vector nhat = np.array([that[2], 0, -that[0]]) for j, dr in enumerate(dr_data): for k, dy in enumerate(dy_data): point = np.array([xo, dy, zo]) + dr * nhat Fb = self.ff.topple(point, J, self.cage, self.eq.Bpoint, method='BS') # body force for m, var in enumerate(['x', 'y', 'z']): # store Fbody[var][i, j, k] = Fb[m] if plot: Fvec = 1e-8 * Fb #/np.linalg.norm(Fb) #Fvec = that pl.arrow(point[0], point[2], Fvec[0], Fvec[2], head_width=0.3, head_length=0.6) pl.plot(point[0], point[2], 'o', color=0.15 * np.ones(3), ms=3) print('\n', np.sum(Fbody['x'][:-1, :, :]) * 1e-9, np.sum(Fbody['y'][:-1, :, :]) * 1e-9, np.sum(Fbody['z'][:-1, :, :]) * 1e-9) ans.f.write('\n! parametric coil length, fn(theta)\n') ans.load('l_map', l_map, [radius, theta]) ans.write(['radus', 'theta']) ans.f.write('\n! parametric coil offset, fn(theta)\n') ans.load('dr_map', dr_map, [radius, theta]) ans.write(['radus', 'theta']) for var in ['x', 'y', 'z']: ans.f.write( '\n! winding-pack body force, Fbody_{} [N/m3]\n'.format(var)) ans.load('Fbody_{}'.format(var), Fbody[var], [l_data, dr_data, dy_data]) ans.write(['l_map', 'dr_map', 'offset']) ans.f.write('/gopr ! enable output\n') apdlstr = ''' pi = 4*atan(1) csys,11 ! switch to cylindrical coordinate system esel,s,elem,,wp ! select winding pack (requires named selection 'wp') *get,nel,elem,0,count *vget,el_sel,elem,,esel ! selection mask *vget,el_id,elem,,elist ! winding pack selection array *vget,el_vol,elem,,geom ! element volume *vget,el_radius,elem,,cent,x ! element radius *vget,el_theta,elem,,cent,y ! element theta *vget,el_offset,elem,,cent,z ! element axial offset *voper,el_theta,el_theta,mult,pi/180 ! convert to radians csys,0 ! return coordinate system ! compress selections *dim,el_v,array,nel *dim,el_r,array,nel *dim,el_t,array,nel *dim,el_o,array,nel *dim,el_l,array,nel *dim,el_dr,array,nel *vmask,el_sel *vfun,el_v,comp,el_vol ! volume *vmask,el_sel *vfun,el_r,comp,el_radius ! radius *vmask,el_sel *vfun,el_t,comp,el_theta ! theta *vmask,el_sel *vfun,el_o,comp,el_offset ! offset *vitrp,el_l,l_map,el_r,el_t ! interpolate l_map table *vitrp,el_dr,dr_map,el_r,el_t ! interpolate dr_map table xyz = 'x','y','z' ! axes fcum,add ! accumulate nodal forces *do,i,1,nel ! apply forces to loads esel,s,elem,,el_id(i) nsle ! select nodes attached to element nsel,r,node,,wp ! ensure all nodes from winding pack *get,nnd,node,0,count ! count nodes *do,j,1,3 ! Fx,Fy,Fz - all nodes attached to element F,all,F%xyz(j)%,Fbody_%xyz(j)%(el_l(i),el_dr(i),el_o(i))*el_v(i)/nnd *enddo *enddo allsel ''' ans.f.write(apdlstr) ans.close()
font='sans-serif', palette='Set2', font_scale=7 / 8, rc=rc) color = sns.color_palette('Set2', 5) config, setup = select(base={'TF': 'dtt', 'eq': 'DEMO_FW_SOF'}, nTF=18) sf = SF(setup.filename) pf = PF(sf.eqdsk) pf.plot(coils=pf.coil, label=True, plasma=False, current=True) levels = sf.contour(plot_vac=False) rb = RB(setup, sf) rb.firstwall(plot=True, debug=False, color=color[1]) rb.trim_sol() filename = trim_dir('../../Data/') + 'CATIA_FW.xlsx' wb = load_workbook(filename=filename, read_only=True, data_only=True) ws = wb[wb.get_sheet_names()[0]] FW = {} for col, var in zip([5, 6], ['r', 'z']): row = ws.columns[col] FW[var] = np.zeros(len(row) - 1) for i, r in enumerate(row[1:]): try: FW[var][i] = 1e-3 * float(r.value) # m except: break r, z = geom.pointloop(FW['r'], FW['z'], ref='min') pl.plot(r[:-1], z[:-1]) '''
from OCC import UnitsAPI UnitsAPI.unitsapi_SetCurrentUnit('LENGTH', 'meter') from amigo.IO import trim_dir sys.path.insert(0, r'D:/Code/Nova/nova/TF/geom') def add_line(point): p = [] for i in range(2): p.append(gp_Pnt(point[i]['r'], 0, point[i]['z'])) edge = BRepBuilderAPI_MakeEdge(p[0], p[1]).Edge() return edge datadir = trim_dir('../../../Data/') with open(datadir + 'occ_input.json', 'r') as f: data = json.load(f) loop, cs, pf, nTF = data['p'], data['section'], data['pf'], data['nTF'] color = data['color'] PFsupport, CSsupport = data['PFsupport'], data['CSsupport'] Gsupport, OISsupport = data['Gsupport'], data['OISsupport'] w = [] for segment in loop: Pnt = TColgp_Array1OfPnt(1, 4) for i in range(4): point = segment['p{:d}'.format(i)] Pnt.SetValue(i + 1, gp_Pnt(point['r'], 0, point['z'])) curve = Geom_BezierCurve(Pnt) w.append(BRepBuilderAPI_MakeEdge(curve.GetHandle()).Edge())
def eqwrite(self, pf, CREATE=False, prefix='Nova', config=''): if len(config) > 0: name = prefix + '_' + config else: name = prefix if CREATE: # save with create units (Webber/loop, negated Iplasma) name = 'CREATE_format_' + name norm = 2 * np.pi # reformat: webber/loop Ip_dir = -1 # reformat: reverse plasma current psi_offset = self.get_Xpsi()[0] # reformat: boundary psi=0 else: norm, Ip_dir, psi_offset = 1, 1, 0 # no change nc, rc, zc, drc, dzc, Ic = pf.unpack_coils()[:-1] psi_ff = np.linspace(0, 1, self.nr) pad = np.zeros(self.nr) eq = { 'name': name, 'nx': self.nr, 'ny': self.nz, # Number of horizontal and vertical points 'r': self.r, 'z': self.z, # Location of the grid-points 'rdim': self.r[-1] - self.r[0], # Size of the domain in meters 'zdim': self.z[-1] - self.z[0], # Size of the domain in meters 'rcentr': self.eqdsk['rcentr'], # Reference vacuum toroidal field (m, T) 'bcentr': self.eqdsk['bcentr'], # Reference vacuum toroidal field (m, T) 'rgrid1': self.r[0], # R of left side of domain 'zmid': self.z[0] + (self.z[-1] - self.z[0]) / 2, # Z at the middle of the domain 'rmagx': self.Mpoint[0], # Location of magnetic axis 'zmagx': self.Mpoint[1], # Location of magnetic axis 'simagx': float(self.Mpsi) * norm, # Poloidal flux at the axis (Weber / rad) 'sibdry': self.Xpsi * norm, # Poloidal flux at plasma boundary (Weber / rad) 'cpasma': self.eqdsk['cpasma'] * Ip_dir, 'psi': (np.transpose(self.psi).reshape((-1, )) - psi_offset) * norm, # Poloidal flux in Weber/rad on grid points 'fpol': self.Fpsi( psi_ff), # Poloidal current function on uniform flux grid 'ffprim': self.b_scale * self.FFprime(psi_ff) / norm, # "FF'(psi) in (mT)^2/(Weber/rad) on uniform flux grid" 'pprime': self.b_scale * self.Pprime(psi_ff) / norm, # "P'(psi) in (N/m2)/(Weber/rad) on uniform flux grid" 'pressure': pad, # Plasma pressure in N/m^2 on uniform flux grid 'qpsi': pad, # q values on uniform flux grid 'nbdry': self.nbdry, 'rbdry': self.rbdry, 'zbdry': self.zbdry, # Plasma boundary 'nlim': self.nlim, 'xlim': self.xlim, 'ylim': self.ylim, # first wall 'ncoil': nc, 'rc': rc, 'zc': zc, 'drc': drc, 'dzc': dzc, 'Ic': Ic } # coils eqdir = trim_dir('../../eqdsk') filename = eqdir + '/' + config + '.eqdsk' print('writing eqdsk', filename) nova.geqdsk.write(filename, eq)