def part_fill(self, trim=None, dt=0, ref_o=4 / 8 * np.pi, dref=np.pi / 4, edge=True, ends=True, color='k', label=None, alpha=0.8, referance='theta', loop=False, s=0, plot=False): Rin, Zin = self.R, self.Z if loop: Napp = 5 # Nappend R = np.append(self.R, self.R[:Napp]) R = np.append(self.R[-Napp:], R) Z = np.append(self.Z, self.Z[:Napp]) Z = np.append(self.Z[-Napp:], Z) R, Z = geom.rzSLine(R, Z, npoints=len(R), s=s) if isinstance(dt, (np.ndarray, list)): dt = np.append(dt, dt[:Napp]) dt = np.append(dt[-Napp:], dt) Rout, Zout = geom.offset(R, Z, dt) print('part fill') Rout, Zout = Rout[Napp:-Napp], Zout[Napp:-Napp] Rout[-1], Zout[-1] = Rout[0], Zout[0] else: R, Z = geom.rzSLine(self.R, self.Z, npoints=len(self.R), s=s) Rout, Zout = geom.offset(R, Z, dt) self.R, self.Z = Rout, Zout # update if trim is None: Lindex = [0, len(Rin)] else: Lindex = self.trim(trim) if plot: flag = 0 for i in np.arange(Lindex[0], Lindex[1] - 1): Rfill = np.array([Rin[i], Rout[i], Rout[i + 1], Rin[i + 1]]) Zfill = np.array([Zin[i], Zout[i], Zout[i + 1], Zin[i + 1]]) if flag is 0 and label is not None: flag = 1 pl.fill(Rfill, Zfill, facecolor=color, alpha=alpha, edgecolor='none', label=label) else: pl.fill(Rfill, Zfill, facecolor=color, alpha=alpha, edgecolor='none')
def get_seperatrix(self, nplasma=80, alpha=1 - 1e-3, **kwargs): self.nplasma = nplasma self.plasma_loop = np.zeros((self.nplasma, 3)) # initalise loop array if 'sf' in kwargs: # seperatrix directly from sf object r, z = kwargs['sf'].get_boundary(alpha=alpha) elif 'config' in kwargs: setup = Setup(kwargs.get('config')) r, z = ripple.get_boundary(setup.filename, alpha=alpha) elif 'eqdsk' in kwargs: # seperatrix from eqdsk eqdsk = geqdsk.read(kwargs.get('eqdsk')) r, z = eqdsk['rbdry'], eqdsk['zbdry'] elif 'r' in kwargs and 'z' in kwargs: # separatrix from input r, z = kwargs.get('r'), kwargs.get('z') else: errtxt = '\n' errtxt += 'Require plasma={} input of following types:\n' errtxt += '1) configuration flag, {\'config\':\'SN\'} \n' errtxt += '2) eqdsk file, {\'eqdsk\':\'\'} \n' errtxt += '3) seperatrix profile, {\'r\':[],\'z\':[]}' raise ValueError(errtxt) r, z = geom.clock(r, z) (self.plasma_loop[:,0],self.plasma_loop[:,2]) = \ geom.rzSLine(r,z,npoints=self.nplasma) self.plasma_length = geom.length(self.plasma_loop[:, 0], self.plasma_loop[:, 2]) rfun, zfun = geom.rzfun(r, z) self.plasma_interp = {'r': rfun, 'z': zfun}
def draw(self, **kwargs): self.set_input(**kwargs) ro, zo, sl, f1, f2, a1, a2 = self.get_xo() asum = a1 + a2 # straight section r = ro * np.ones(2) z = np.array([zo, zo + sl]) # small arc theta = np.linspace(0, a1, round(0.5 * self.npoints * a1 / np.pi)) r = np.append(r, r[-1] + f1 * (1 - np.cos(theta))) z = np.append(z, z[-1] + f1 * np.sin(theta)) # mid arc theta = np.linspace(theta[-1], asum, round(0.5 * self.npoints * a2 / np.pi)) r = np.append(r, r[-1] + f2 * (np.cos(a1) - np.cos(theta))) z = np.append(z, z[-1] + f2 * (np.sin(theta) - np.sin(a1))) # large arc rl = (z[-1] - zo) / np.sin(np.pi - asum) theta = np.linspace(theta[-1], np.pi, 60) r = np.append( r, r[-1] + rl * (np.cos(np.pi - theta) - np.cos(np.pi - asum))) z = np.append(z, z[-1] - rl * (np.sin(asum) - np.sin(np.pi - theta))) r = np.append(r, r[::-1])[::-1] z = np.append(z, -z[::-1] + 2 * zo)[::-1] r, z = geom.rzSLine(r, z, self.npoints) # distribute points #L = geom.length(r,z,norm=False)[-1] # coil length x = {'r': r, 'z': z} return x
def add_vessel(self,vessel,npoint=80,offset=[0.12,0.2]): rvv,zvv = geom.rzSLine(vessel['r'],vessel['z'],npoint) rvv,zvv = geom.offset(rvv,zvv,offset[1]) rmin = np.min(rvv) rvv[rvv<=rmin+offset[0]] = rmin+offset[0] self.add_bound({'r':rvv,'z':zvv},'internal') # vessel self.add_bound({'r':np.min(rvv)-5e-3,'z':0},'interior') # vessel
def set_TFcoil(self, cl, smooth=False): r, z = geom.clock(cl['r'], cl['z']) self.npoints = len(r) self.coil_loop = np.zeros((self.npoints, 3)) self.coil_loop[:,0],self.coil_loop[:,2] = \ geom.rzSLine(r,z,npoints=self.npoints) # coil centerline self.gfl = cc.GreenFeildLoop(self.coil_loop, rc=self.rc, smooth=smooth) self.pattern() self.amp_turns() # set coil cage amp-turns
def vessel_fill(self, gap=True): r, z = self.segment['blanket_fw']['r'], self.segment['blanket_fw']['z'] loop = Loop(r, z) r, z = loop.fill(dt=0.05) rb = np.append(r, r[0]) zb = np.append(z, z[0]) profile = Profile(self.setup.configuration, family='S', part='vv', npoints=400, read_write=False) shp = Shape(profile, objective='L') shp.loop.adjust_xo('upper', lb=0.6) shp.loop.adjust_xo('lower', lb=0.6) shp.loop.adjust_xo('l', lb=0.6) #shp.loop.remove_oppvar('flat') r, z = geom.rzSLine(rb, zb, 200) # sub-sample rup, zup = r[z > self.sf.Xpoint[1]], z[z > self.sf.Xpoint[1]] shp.add_bound({'r': rup, 'z': zup}, 'internal') # vessel inner bounds rd, zd = r[z < self.sf.Xpoint[1]], z[z < self.sf.Xpoint[1]] ro, zo = geom.offset(rd, zd, 0.1) # divertor offset shp.add_bound({'r': rd, 'z': zd}, 'internal') # vessel inner bounds shp.add_bound({ 'r': rd, 'z': zd - 0.25 }, 'internal') # gap below divertor #shp.plot_bounds() shp.minimise() #shp.loop.plot() x = profile.loop.draw() rin, zin = x['r'], x['z'] loop = Loop(rin, zin) r, z = loop.fill(dt=self.setup.build['VV'], ref_o=2 / 8 * np.pi, dref=np.pi / 6) shp.clear_bound() shp.add_bound({'r': r, 'z': z}, 'internal') # vessel outer bounds shp.minimise() x = profile.loop.draw() r, z = x['r'], x['z'] if 'SX' in self.setup.configuration or gap == True: vv = wrap({'r': rin, 'z': zin}, {'r': r, 'z': z}) else: vv = wrap({'r': rb, 'z': zb}, {'r': r, 'z': z}) vv.sort_z('inner', select=self.sf.Xloc) vv.sort_z('outer', select=self.sf.Xloc) self.segment['vessel_inner'] = {'r': rin, 'z': zin} self.segment['vessel_outer'] = {'r': r, 'z': z} self.segment['vessel'] = vv.fill()[1] return vv
def draw(self, **kwargs): self.npoints = kwargs.get('npoints', self.npoints) self.set_input(**kwargs) self.segments = {'r': [], 'z': []} ro, zo, sl, f1, f2, a1, a2 = self.get_xo() a1 *= np.pi / 180 # convert to radians a2 *= np.pi / 180 asum = a1 + a2 # straight section r = ro * np.ones(2) z = np.array([zo, zo + sl]) self.segments['r'].append(r) self.segments['z'].append(z) # small arc theta = np.linspace(0, a1, round(0.5 * self.npoints * a1 / np.pi)) rx, zx = r[-1], z[-1] r = np.append(r, r[-1] + f1 * (1 - np.cos(theta))) z = np.append(z, z[-1] + f1 * np.sin(theta)) self.segments['r'].append(rx + f1 * (1 - np.cos(theta))) self.segments['z'].append(zx + f1 * np.sin(theta)) # mid arc theta = np.linspace(theta[-1], asum, round(0.5 * self.npoints * a2 / np.pi)) rx, zx = r[-1], z[-1] r = np.append(r, r[-1] + f2 * (np.cos(a1) - np.cos(theta))) z = np.append(z, z[-1] + f2 * (np.sin(theta) - np.sin(a1))) self.segments['r'].append(rx + f2 * (np.cos(a1) - np.cos(theta))) self.segments['z'].append(zx + f2 * (np.sin(theta) - np.sin(a1))) # large arc rl = (z[-1] - zo) / np.sin(np.pi - asum) theta = np.linspace(theta[-1], np.pi, 60) rx, zx = r[-1], z[-1] r = np.append( r, r[-1] + rl * (np.cos(np.pi - theta) - np.cos(np.pi - asum))) z = np.append(z, z[-1] - rl * (np.sin(asum) - np.sin(np.pi - theta))) self.segments['r'].append( rx + rl * (np.cos(np.pi - theta) - np.cos(np.pi - asum))) self.segments['z'].append(zx - rl * (np.sin(asum) - np.sin(np.pi - theta))) r = np.append(r, r[::-1])[::-1] z = np.append(z, -z[::-1] + 2 * zo)[::-1] r, z = geom.rzSLine(r, z, self.npoints) # distribute points x = {'r': r, 'z': z} x = close_loop(x, self.npoints) x['r'], x['z'] = geom.clock(x['r'], x['z']) return x
def get_seperatrix(self, nplasma=80, alpha=1 - 1e-4, plot=False, **kwargs): self.nplasma = nplasma self.plasma_loop = np.zeros((self.nplasma, 3)) # initalise loop array if 'sf' in kwargs or 'setup' in kwargs or 'config' in kwargs: if 'sf' in kwargs: # seperatrix directly from sf object sf = kwargs['sf'] elif 'setup' in kwargs: setup = kwargs.get('setup') sf = SF(setup.filename) elif 'config' in kwargs: setup = Setup(kwargs.get('config')) sf = SF(setup.filename) r, z = sf.get_boundary(alpha=alpha) self.eqdsk = sf.eqdsk self.LFP = np.array([sf.LFPr, sf.LFPz]) else: if 'eqdsk' in kwargs: # seperatrix from eqdsk self.eqdsk = geqdsk.read(kwargs.get('eqdsk')) r, z = self.eqdsk['rbdry'], self.eqdsk['zbdry'] elif 'r' in kwargs and 'z' in kwargs: # separatrix from input r, z = kwargs.get('r'), kwargs.get('z') self.eqdsk = { 'rcentr': 9.0735, 'zmagx': 0.15295, 'bcentr': -5.6211 } LFindex = np.argmax(r) self.LFP = np.array([r[LFindex], z[LFindex]]) if not hasattr(self, 'eqdsk'): errtxt = '\n' errtxt += 'Require plasma={} input of following types:\n' errtxt += '1) configuration flag, {\'config\':\'SN\'} \n' errtxt += '2) eqdsk file, {\'eqdsk\':\'\'} \n' errtxt += '3) seperatrix profile, {\'r\':[],\'z\':[]}' raise ValueError(errtxt) r, z = geom.clock(r, z) (self.plasma_loop[:,0],self.plasma_loop[:,2]) = \ geom.rzSLine(r,z,npoints=self.nplasma) self.plasma_length = geom.length(self.plasma_loop[:, 0], self.plasma_loop[:, 2]) rfun, zfun = geom.rzfun(r, z) self.plasma_interp = {'r': rfun, 'z': zfun} if plot: pl.plot(self.plasma_loop[:, 0], self.plasma_loop[:, 2])
def add_bound(self, sf): rpl, zpl = sf.get_offset(self.config['dr'], Nsub=self.config['Nsub']) self.shp.add_bound({ 'r': rpl, 'z': zpl }, 'internal') # vessel inner bounds Xpoint = sf.Xpoint_array[:, 0] # select lower self.shp.add_bound( { 'r': Xpoint[0] + 0.12 * sf.shape['a'], 'z': Xpoint[1] }, 'internal') self.shp.add_bound( { 'r': Xpoint[0], 'z': Xpoint[1] - 0.01 * sf.shape['a'] }, 'internal') if self.config['flux_fit']: # add flux boundary points sf.get_LFP() # get low feild point rflux, zflux = sf.first_wall_psi(psi_n=self.config['psi_n'], trim=False)[:2] rflux, zflux = sf.midplane_loop(rflux, zflux) rflux, zflux = geom.order(rflux, zflux) istop = next((i for i in range(len(zflux)) if zflux[i] < sf.LFPz), -1) rflux, zflux = rflux[:istop], zflux[:istop] dL = np.diff(geom.length(rflux, zflux)) if np.max(dL) > 3*np.median(dL) or \ np.argmax(zflux) == len(zflux)-1: wtxt = '\n\nOpen feild line detected\n' wtxt += 'disabling flux fit for ' wtxt += '{:1.1f}% psi_n \n'.format(1e2 * self.config['psi_n']) wtxt += 'configuration: ' + sf.filename + '\n' warn(wtxt) else: # add flux_fit bounds rflux, zflux = geom.rzSLine(rflux, zflux, int(self.config['Nsub'] / 2)) self.shp.add_bound({'r': rflux, 'z': zflux}, 'internal')
def get_fw(self, plot=False): rbl = self.parts['Blanket']['in']['r'] # read blanket zbl = self.parts['Blanket']['in']['z'] zmin = np.zeros(len(self.limiter)) # select divertor limiter for i, limiter in enumerate(self.limiter): zmin[i] = np.min(self.limiter[limiter]['z']) imin = np.argmin(zmin) div = list(self.limiter.keys())[imin] rdiv = self.limiter[div]['r'] # set divertor profile zdiv = self.limiter[div]['z'] cut = np.zeros(2, dtype=int) # cut and join divertor for i, j in enumerate([0, -1]): cut[i] = np.argmin(norm([rbl[j] - rdiv, zbl[j] - zdiv], axis=0)) cut = np.sort(cut) r = np.append(rbl, rdiv[cut[0]:cut[1]]) z = np.append(zbl, zdiv[cut[0]:cut[1]]) r, z = np.append(r, r[0]), np.append(z, z[0]) r, z = geom.rzSLine(r, z) r, z = r[::-1], z[::-1] # flip self.fw = {'r': r, 'z': z} if plot: pl.plot(r, z, color=0.5 * np.ones(3))
def close_loop(x, npoints): for var in ['r', 'z']: x[var] = np.append(x[var], x[var][0]) x['r'], x['z'] = geom.rzSLine(x['r'], x['z'], npoints=npoints) return x
def set_boundary(self, r, z, n=5e2): self.nbdry = int(n) self.rbdry, self.zbdry = geom.rzSLine(r, z, npoints=n)
pf.plot(coils=pf.coil, label=True, plasma=False, current=True) levels = sf.contour() rb = RB(setup, sf) rb.firstwall(plot=False, debug=False) profile = Profile(config['TF'], family='S', part='TF', nTF=18, obj='L', load=True) shp = Shape(profile, obj='L', eqconf=config['eq'], load=True) # ,nTF=18 rvv, zvv = geom.rzSLine(rb.segment['vessel']['r'], rb.segment['vessel']['z'], 31) rvv, zvv = geom.offset(rvv, zvv, 0.2) rmin = np.min(rvv) rvv[rvv <= rmin + 0.12] = rmin + 0.12 shp.loop.xo['r1'] = { 'value': 4.486, 'lb': np.min(rvv), 'ub': 8 } # inner radius shp.loop.xo['upper'] = {'value': 0.33, 'lb': 0.5, 'ub': 1} shp.loop.xo['lower'] = {'value': 0.33, 'lb': 0.5, 'ub': 1} shp.add_bound({'r': rvv, 'z': zvv}, 'internal') # vessel shp.plot_bounds() shp.minimise() #shp.loop.plot()
def set_TFcoil(self, cl, npoints=80, smooth=False): r, z = geom.clock(cl['r'], cl['z']) self.coil_loop = np.zeros((npoints, 3)) self.coil_loop[:,0],self.coil_loop[:,2] = \ geom.rzSLine(r,z,npoints=npoints) # coil centerline self.gfl = cc.GreenFeildLoop(self.coil_loop, smooth=smooth)
def get_offset(self, dr, Nsub=0): rpl, zpl = self.get_boundary() # boundary points rpl, zpl = geom.offset(rpl, zpl, dr) # offset from sep if Nsub > 0: # sub-sample rpl, zpl = geom.rzSLine(rpl, zpl, Nsub) return rpl, zpl
pl.plot(sep['x'], sep['y']) config = {'TF': 'NTP'} #setup = Setup(config) #sf = SF(setup.filename) #sf.get_boundary(plot=True) profile = Profile(config['TF'], family='S', part='TF') shp = Shape(profile, obj='L', nTF=18, sep={ 'r': sep['x'], 'z': sep['y'] }) # ,eqconf=config['eq'] #shp.cage.pattern(plot=True) rvv, zvv = geom.rzSLine(vv['x'], vv['y'], 60) rvv, zvv = geom.offset(rvv, zvv, 0.2) rmin = np.min(rvv) rvv[rvv <= rmin + 0.12] = rmin + 0.12 shp.add_bound({'r': rvv, 'z': zvv}, 'internal') # vessel #shp.plot_bounds() shp.minimise(ripple=True, ripple_limit=0.6) shp.update() shp.tf.fill() shp.cage.plot_contours(variable='ripple', n=2e3, loop={ 'r': vv['x'], 'z': vv['y']
#sf.get_legs(debug=True) rb.set_firstwall(sf.eqdsk['xlim'], sf.eqdsk['ylim']) pl.plot(rb.Rb, rb.Zb) sf.sol(dr=3e-3) rb.get_sol(plot=True) pl.plot(sf.eqdsk['xlim'], sf.eqdsk['ylim']) r = demo.parts['Vessel']['r'] # set vessel boundary z = demo.parts['Vessel']['z'] r, z = geom.offset(r, z, 0.2) # 200mm offset from vessel r, z = geom.rzSLine(r, z, npoints=20) rb.loop = geom.Loop(r, z) #sf.sol(plot=True) ''' nTF = 18 tf = TF(shape={'vessel':rb.loop,'pf':pf,'sf':sf,'fit':True, 'setup':setup,'coil_type':'S','config':config},nTF=nTF) #tf = TF(shape={'coil_type':'S','config':config,'sf':sf}) tf.coil.plot() tf.fill(text=True) tf.plot_oppvar() '''