예제 #1
0
class TowerScene():
	""" Creates a scene of the heliostats, tower and receiver """
	# recobj is an assembled receiver object
	# surf_ls is a list of all surfaces used in the receiver
	# crit_ls is a list of all surfaces to be viewed in a histogram
	# heliostat is a csv file of coordinates (Example: sandia_hstat_coordinates.csv)
	# dx,dy,dz are x,y,z offsets from the origin (default dz is 6.1 metres)
	# rx,ry,rz are rotations about the x,y,z axes in radians (default 0)
	def __init__(self,rec_obj,surf_ls,crit_ls,heliostat,sun_az = 0.,sun_elev = 34.9,\
	dx = 0., dy = 0., dz = 6.1, rx = 0, ry = 0, rz = 0):
		self.sun_az = sun_az
		self.sun_elev = sun_elev
		self.rec_obj = rec_obj
		self.surf_ls = surf_ls
		self.crit_ls = crit_ls
		# add offset properties
		self.dx = dx
		self.dy = dy
		self.dz = dz
		# add rotation properties
		self.rx = rx
		self.ry = ry
		self.rz = rz
		# add the heliostat coordinates
		self.pos = N.loadtxt(heliostat, delimiter=",")
		self.pos *= 0.1
		# generate the entire plant now
		self.gen_plant()
		# creates an attribute which shows number of rays used, start at zero
		self.no_of_rays = 0
		self.helio_hits = 0

	def gen_rays(self):
		sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        	rpos = (self.pos + sun_vec).T
        	direct = N.tile(-sun_vec, (self.pos.shape[0], 1)).T
        	rays = RayBundle(rpos, direct, energy=N.ones(self.pos.shape[0]))

		return rays

	def gen_plant(self):
		"""Generates the entire plant"""
		# set heliostat field characteristics: 0.52m*0.52m, abs = 0, aim_h =61
		self.field = HeliostatField(self.pos, 6.09e-1, 6.09e-1, 0, 6.1, 1e-3)
		# generates a transformation matrix of the receiver rec_trans for rotations
		rx_M = N.matrix(rotx(self.rx))
		ry_M = N.matrix(rotx(self.ry))
		rz_M = N.matrix(rotx(self.rz))
		rec_trans = N.array((rx_M)*(ry_M)*(rz_M))
		# applies translations to the rotation matrix to get the final transformation
		rec_trans[0,3] = self.dx
		rec_trans[1,3] = self.dy
		rec_trans[2,3] = self.dz
		# applies the transformation to the receiver object
		self.rec_obj.set_transform(rec_trans)
		# combines all objects into a single plant
		self.plant = Assembly(objects = [self.rec_obj], subassemblies=[self.field])


	def aim_field(self):
		"""Aims the field to the sun?"""
		self.field.aim_to_sun(self.sun_az*degree, self.sun_elev*degree)

	def trace(self, rph, iters = 10000, minE = 1e-9, render = False):
		"""Commences raytracing using (rph) number of rays per heliostat, for a maximum of 
		   (iters) iterations, discarding rays with energy less than (minE). If render is
		   True, a 3D scene will be displayed which would need to be closed to proceed."""
		# Get the solar vector using azimuth and elevation
		sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        	# Calculate number of rays used. Rays per heliostat * number of heliostats.
        	num_rays = rph*len(self.field.get_heliostats())
		self.no_of_rays += num_rays
		# Generates the ray bundle
        	rot_sun = rotation_to_z(-sun_vec)
        	direct = N.dot(rot_sun, pillbox_sunshape_directions(num_rays, 0.00465))
        
        	xy = N.random.uniform(low=-0.25, high=0.25, size=(2, num_rays))
        	base_pos = N.tile(self.pos, (rph, 1)).T #Check if its is rph or num_rays
       		base_pos += N.dot(rot_sun[:,:2], xy)
        	
        	base_pos -= direct
        	rays = RayBundle(base_pos, direct, energy=N.ones(num_rays))

		# Perform the raytracing
		e = TracerEngine(self.plant)
		e.ray_tracer(rays, iters, minE, tree=True)
		e.minener = minE
		rays_in = sum(e.tree._bunds[0].get_energy())
		self.helio_hits = sum(e.tree._bunds[1].get_energy())


		# Optional rendering
		if render == True:
			trace_scene = Renderer(e)
			trace_scene.show_rays()
			
	def hist_comb(self, no_of_bins=100):
		"""Returns a combined histogram of all critical surfaces and relevant data"""
		# H is the histogram array
		# boundlist is a list of plate boundaries given in x coordinates
		# extent is a list of [xmin,xmax,ymin,ymax] values
		# binarea is the area of each bin. Used to estimate flux concentration

		# Define empty elements
		X_offset = 0	# Used to shift values to the right for each subsequent surface
		all_X = []	# List of all x-coordinates
		all_Y = []	# List of all y-coordinates
		all_E = []	# List of all energy values
		boundlist = [0]	# List of plate boundaries, starts with x=0

		#print("length here"+str(len((self.plant.get_local_objects()[0]).get_surfaces())))

		#for plate in self.crit_ls:	#For each surface within the list of critical surfs
		crit_length = len(self.crit_ls)
		count = 0
		while count < crit_length: # count is one less than crit_length for indexing convention
			surface = (self.plant.get_local_objects()[0]).get_surfaces()[count]
			# returns all coordinates where a hit occured and its energy absorbed
			energy, pts = surface.get_optics_manager().get_all_hits()
			corners = surface.mesh(1) #corners is an array of all corners of the plate
			# BLC is bottom left corner "origin" of the histogram plot
			# BRC is the bottom right corner "x-axis" used for vector u
			# TLC is the top right corner "y-axis" used for vector v
			BLC = N.array([corners[0][1][1],corners[1][1][1],corners[2][1][1]])
			BRC = N.array([corners[0][0][1],corners[1][0][1],corners[2][0][1]])
			TLC = N.array([corners[0][1][0],corners[1][1][0],corners[2][1][0]])
			# Get vectors u and v in array form of array([x,y,z])
			u = BRC - BLC
			v = TLC - BLC
			# Get width(magnitude of u) and height(magnitude of v) in float form
			w = (sum(u**2))**0.5
			h = (sum(v**2))**0.5
			# Get unit vectors of u and v in form of array([x,y,z])
			u_hat = u/w
			v_hat = v/h
			# Local x-position determined using dot product of each point with direction
			# Returns a list of local x and y coordinates
			origin = N.array([[BLC[0]],[BLC[1]],[BLC[2]]])
			local_X = list((N.array(N.matrix(u_hat)*N.matrix(pts-origin))+X_offset)[0])
			#local_Y = list((N.array(N.matrix(v_hat)*N.matrix(pts-origin)))[0])
			local_Y = list((((N.array(N.matrix(v_hat)*N.matrix(pts-origin)))[0])*-1)+h)
			# Adds to the lists
			all_X += local_X
			all_Y += local_Y
			all_E += list(energy)
			X_offset += w
			boundlist.append(X_offset)
			count += 1
		# Now time to build a histogram
		rngy = h
		rngx = X_offset
		bins = [no_of_bins,int(no_of_bins*X_offset)]
		H,ybins,xbins = N.histogram2d(all_Y,all_X,bins,range=([0,rngy],[0,rngx]), weights=all_E)
		extent = [xbins[0],xbins[-1],ybins[0],ybins[-1]]
		binarea = (float(h)/no_of_bins)*(float(X_offset)/int(no_of_bins*X_offset))
		return H, boundlist, extent, binarea

	def energies(self):
		"""Returns the total number of hits on the heliostats, receiver and the total energy absorbed"""
		
		totalenergy = 0.0
		totalhits = 0
		heliohits = self.helio_hits
		#length = 0
		#for surface in self.plant.get_local_objects()[0].get_surfaces():
		for surface in (self.plant.get_local_objects()[0]).get_surfaces():
			energy, pts = surface.get_optics_manager().get_all_hits()
			absorp = surface._opt._opt._abs
			#length += len(energy)
			#plt.plot(range(0,len(energy)),energy,'ro')
			#plt.show()
			totalenergy += sum(energy)
			totalhits += sum(energy == absorp)
		#print("Length is"+str(length))
		return totalenergy, totalhits, heliohits
예제 #2
0
class TowerScene(TracerScene):
    # Location of the sun:
    sun_az = t_api.Range(0, 180, 90, label="Sun azimuth")
    sun_elev = t_api.Range(0, 90, 45, label="Sun elevation")
    
    # Heliostat placement distance:
    radial_res = t_api.Float(1., label="Radial distance")
    ang_res = t_api.Float(N.pi/8, lable="Angular distance")
    
    # Flux map figure:
    fmap = t_api.Instance(Figure)
    fmap_btn = t_api.Button(label="Update flux map")
    
    def __init__(self):
        self.gen_plant()
        TracerScene.__init__(self, self.plant, self.gen_rays())
        
        self.aim_field()
        self.set_background((0., 0.5, 1.))
    
    def gen_rays(self):
        sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        rpos = (self.pos + sun_vec).T
        direct = N.tile(-sun_vec, (self.pos.shape[0], 1)).T
        rays = RayBundle(rpos, direct, energy=N.ones(self.pos.shape[0]))
        
        return rays
    
    def gen_plant(self):
        xy = radial_stagger(-N.pi/4, N.pi/4 + 0.0001, self.ang_res, 5, 20, self.radial_res)
        self.pos = N.hstack((xy, N.zeros((xy.shape[0], 1))))
        self.field = HeliostatField(self.pos, 0.5, 0.5, 0, 10)

        self.rec, recobj = one_sided_receiver(1., 1.)
        rec_trans = roty(N.pi/2)
        rec_trans[2,3] = 10
        recobj.set_transform(rec_trans)

        self.plant = Assembly(objects=[recobj], subassemblies=[self.field])
    
    @t_api.on_trait_change('sun_az, sun_elev')
    def aim_field(self):
        self.clear_scene()
        rays = self.gen_rays()
        self.field.aim_to_sun(self.sun_az*degree, self.sun_elev*degree)
        
        self.set_assembly(self.plant) # Q&D example.
        self.set_source(rays)
    
    @t_api.on_trait_change('radial_res, ang_res')
    def replace_plant(self):
        self.gen_plant()
        self.aim_field()
    
    @t_api.on_trait_change('_scene.activated')
    def initialize_camere(self):
        self._scene.mlab.view(0, -90)
        self._scene.mlab.roll(90)
    
    def _fmap_btn_fired(self):
        """Generate a flux map using much more rays than drawn"""
        # Generate a large ray bundle using a radial stagger much denser
        # than the field.
        sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        
        hstat_rays = 1000
        num_rays = hstat_rays*len(self.field.get_heliostats())
        rot_sun = rotation_to_z(-sun_vec)
        direct = N.dot(rot_sun, pillbox_sunshape_directions(num_rays, 0.00465))
        
        xy = N.random.uniform(low=-0.25, high=0.25, size=(2, num_rays))
        base_pos = N.tile(self.pos, (hstat_rays, 1)).T
        base_pos += N.dot(rot_sun[:,:2], xy)
        
        base_pos -= direct
        rays = RayBundle(base_pos, direct, energy=N.ones(num_rays))
        
        # Perform the trace:
        self.rec.get_optics_manager().reset()
        e = TracerEngine(self.plant)
        e.ray_tracer(rays, 1000, 0.05)
        
        # Show a histogram of hits:
        energy, pts = self.rec.get_optics_manager().get_all_hits()
        x, y = self.rec.global_to_local(pts)[:2]
        rngx = 0.5
        rngy = 0.5
        
        bins = 50
        H, xbins, ybins = N.histogram2d(x, y, bins, \
            range=([-rngx,rngx], [-rngy,rngy]), weights=energy)
        
        self.fmap.axes[0].images=[]
        self.fmap.axes[0].imshow(H, aspect='auto')
        wx.CallAfter(self.fmap.canvas.draw) 
    
    def _fmap_default(self):
        figure = Figure()
        figure.add_axes([0.05, 0.04, 0.9, 0.92])
        return figure
    
    # Parameters of the form that is shown to the user:
    view = tui.View(tui.HGroup(tui.VGroup(
        TracerScene.scene_view_item(500, 500),
        tui.HGroup('-', 'sun_az', 'sun_elev'),
        tui.HGroup('radial_res', 'ang_res'),
        tui.Item('fmap_btn', show_label=False)),
        tui.Item('fmap', show_label=False, editor=MPLFigureEditor())))
예제 #3
0
class TowerScene():
    # Location of the sun:
    sun_az = 80.
    sun_elev = 45.
    
    # Heliostat placement distance:
    radial_res = 1.
    ang_res = N.pi/8
    
    def __init__(self):
        self.gen_plant() 
   
    def gen_rays(self):
        sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        rpos = (self.pos + sun_vec).T
        direct = N.tile(-sun_vec, (self.pos.shape[0], 1)).T
        rays = RayBundle(rpos, direct, energy=N.ones(self.pos.shape[0]))
        
        return rays
    
    def gen_plant(self):
        xy = radial_stagger(-N.pi/4, N.pi/4 + 0.0001, self.ang_res, 5., 20., self.radial_res)
        self.pos = N.hstack((xy, N.zeros((xy.shape[0], 1))))
        self.field = HeliostatField(self.pos, 0.5, 0.5, 0, 10)

        self.rec, recobj = one_sided_receiver(1., 1.)
        rec_trans = roty(N.pi/2)
        rec_trans[2,3] = 10
        recobj.set_transform(rec_trans)

        self.plant = Assembly(objects=[recobj], subassemblies=[self.field])
    
    def aim_field(self):
        self.field.aim_to_sun(self.sun_az*degree, self.sun_elev*degree)
    
    def trace(self):
        """Generate a flux map using much more rays than drawn"""
        # Generate a large ray bundle using a radial stagger much denser
        # than the field.
        sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        
        hstat_rays = 20
        num_rays = hstat_rays*len(self.field.get_heliostats())
        rot_sun = rotation_to_z(-sun_vec)
        direct = N.dot(rot_sun, pillbox_sunshape_directions(num_rays, 0.00465))
        
        xy = N.random.uniform(low=-0.25, high=0.25, size=(2, num_rays))
        base_pos = N.tile(self.pos, (hstat_rays, 1)).T
        base_pos += N.dot(rot_sun[:,:2], xy)
        
        base_pos -= direct
        rays = RayBundle(base_pos, direct, energy=N.ones(num_rays))
        
        # Perform the trace:
        e = TracerEngine(self.plant)
        e.ray_tracer(rays, 100, 0.05, tree=True)
        e.minener = 1e-5

		# Render:
        trace_scene = Renderer(e)
        trace_scene.show_rays()
예제 #4
0
class TowerScene():
    # Location of the sun:
    sun_az = 80.
    sun_elev = 45.

    # Heliostat placement distance:
    radial_res = 1.
    ang_res = N.pi / 8

    def __init__(self):
        self.gen_plant()

    def gen_rays(self):
        sun_vec = solar_vector(self.sun_az * degree, self.sun_elev * degree)
        rpos = (self.pos + sun_vec).T
        direct = N.tile(-sun_vec, (self.pos.shape[0], 1)).T
        rays = RayBundle(rpos, direct, energy=N.ones(self.pos.shape[0]))

        return rays

    def gen_plant(self):
        xy = radial_stagger(-N.pi / 4, N.pi / 4 + 0.0001, self.ang_res, 5.,
                            20., self.radial_res)
        self.pos = N.hstack((xy, N.zeros((xy.shape[0], 1))))
        self.field = HeliostatField(self.pos, 0.5, 0.5, 0, 10)

        self.rec, recobj = one_sided_receiver(1., 1.)
        rec_trans = roty(N.pi / 2)
        rec_trans[2, 3] = 10
        recobj.set_transform(rec_trans)

        self.plant = Assembly(objects=[recobj], subassemblies=[self.field])

    def aim_field(self):
        self.field.aim_to_sun(self.sun_az * degree, self.sun_elev * degree)

    def trace(self):
        """Generate a flux map using much more rays than drawn"""
        # Generate a large ray bundle using a radial stagger much denser
        # than the field.
        sun_vec = solar_vector(self.sun_az * degree, self.sun_elev * degree)

        hstat_rays = 20
        num_rays = hstat_rays * len(self.field.get_heliostats())
        rot_sun = rotation_to_z(-sun_vec)
        direct = N.dot(rot_sun, pillbox_sunshape_directions(num_rays, 0.00465))

        xy = N.random.uniform(low=-0.25, high=0.25, size=(2, num_rays))
        base_pos = N.tile(self.pos, (hstat_rays, 1)).T
        base_pos += N.dot(rot_sun[:, :2], xy)

        base_pos -= direct
        rays = RayBundle(base_pos, direct, energy=N.ones(num_rays))

        # Perform the trace:
        e = TracerEngine(self.plant)
        e.ray_tracer(rays, 100, 0.05, tree=True)
        e.minener = 1e-5

        # Render:
        trace_scene = Renderer(e)
        trace_scene.show_rays()
예제 #5
0
class TowerScene():
    # Location of the sun:
    sun_az = 80. # degrees from positive X-axis. azimuth
    sun_elev = 45. # degrees from XY-plane

    
    def __init__(self):
        self.gen_plant() 
   
    def gen_rays(self):
        sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        #notice here the angles are positive. Hmmm? The sun rays are pointing up?
        rpos = (self.pos + sun_vec).T
        #where does self.pos come from? And T?
        direct = N.tile(-sun_vec, (self.pos.shape[0], 1)).T
        rays = RayBundle(rpos, direct, energy=N.ones(self.pos.shape[0]))
        
        return rays
    
    def gen_plant(self):
        # import custom coordinate file
        self.pos = N.loadtxt("sandia_hstat_coordinates.csv", delimiter=',')
        self.pos *= 0.1
        # set heliostat field characteristics: 0.52m*0.52m, abs = 0, aim_h = 61
        self.field = HeliostatField(self.pos, 6.09e-1, 6.09e-1, 0, 6.1,1e-3)

        self.reclist, recobj = one_sided_receiver(1.0, 1.0, 0.8)
        rec_trans = rotx(N.pi/-2) # originally N.pi/2, changed to minus rotx(N.pi/-2)
	print(recobj)
        rec_trans[2,3] = 6.1 # height of the tower original 6.1
        recobj.set_transform(rec_trans)
	
        self.plant = Assembly(objects=[recobj], subassemblies=[self.field])
    
    def aim_field(self):
        self.field.aim_to_sun(self.sun_az*degree, self.sun_elev*degree)
    
    def trace(self):
        """Generate a flux map using much more rays than drawn"""
        # Generate a large ray bundle using a radial stagger much denser
        # than the field.
        sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
        #hstat_rays
        hstat_rays = 1000
        num_rays = hstat_rays*len(self.field.get_heliostats())
        rot_sun = rotation_to_z(-sun_vec)
        direct = N.dot(rot_sun, pillbox_sunshape_directions(num_rays, 0.00465))
        
        xy = N.random.uniform(low=-0.25, high=0.25, size=(2, num_rays))
        base_pos = N.tile(self.pos, (hstat_rays, 1)).T
        base_pos += N.dot(rot_sun[:,:2], xy)
        
        base_pos -= direct
        rays = RayBundle(base_pos, direct, energy=N.ones(num_rays))
        
        # Perform the trace:
        e = TracerEngine(self.plant)
        e.ray_tracer(rays, 100, 0.05, tree=True)
        e.minener = 1e-6 # default 1e-5

	# Render:
        #trace_scene = Renderer(e)
        #trace_scene.show_rays()

        # Initialise a histogram of hits:
        energy, pts = self.reclist.get_optics_manager().get_all_hits()
        x, y = self.reclist.global_to_local(pts)[:2]
        rngx = 0.55 #0.5
        rngy = 0.55 #0.5
        
        bins = 100 #50
        H, xbins, ybins = N.histogram2d(x, y, bins, \
            range=([-rngx,rngx], [-rngy,rngy]), weights=energy)
        
        #print(H, xbins, ybins)
        total=N.sum(H)
        print(total)

        extent = [ybins[0], ybins[-1], xbins[-1], xbins[0]]
        plt.imshow(H, extent=extent, interpolation='nearest')
        plt.colorbar()
	plt.title("front")
        plt.show()