예제 #1
0
    def gen_plant(self,
                  width=6.1,
                  height=6.1,
                  absorptivity=0.04,
                  aim_height=60.,
                  sigma_xy=1e-3,
                  rec_w=11.,
                  rec_h=11.):

        self.pos[:,
                 1] = self.pos[:,
                               1] - 4.  # correction for the true position of the plate on the tower.
        self.width = width
        self.height = height
        self.absorptivity = absorptivity
        self.field = HeliostatField(self.pos, width, height, absorptivity,
                                    aim_height, sigma_xy)
        self.rec_w = rec_w
        self.rec_h = rec_h
        rec, recobj = one_sided_receiver(self.rec_w, self.rec_h)
        rec_trans = rotx(N.pi / -2)
        rec_trans[2, 3] = self.field._th

        # Evaluating just the receiver
        recobj.set_transform(rec_trans)

        self.plant = Assembly(objects=[recobj], subassemblies=[self.field])
예제 #2
0
class TestHeliostatField(unittest.TestCase):
    def setUp(self):
        spread = N.r_[50:101:10]
        self.pos = N.zeros((2*len(spread), 3))
        self.pos[:len(spread), 0] = spread
        self.pos[len(spread):, 1] = spread
        self.pos[:,2] = 4.5
        
        self.field = HeliostatField(self.pos, 8., 8., 0., 90.)
        s2 = N.sqrt(2)/2
        self.sunvec = N.r_[-s2, 0, s2] # Noon, winterish.
        
        ray_pos = (self.pos + self.sunvec).T
        ray_dir = N.tile(-self.sunvec, (self.pos.shape[0], 1)).T
        self.rays = RayBundle(ray_pos, ray_dir, energy=N.ones(self.pos.shape[0]))
    
    def test_secure_position(self):
        """Heliostats at default position absorb the sunlight"""
        e = TracerEngine(self.field)
        e.ray_tracer(self.rays, 1, 0.05)
        
        N.testing.assert_array_equal(e.tree[-1].get_energy(), 0)
    
    def test_aim(self):
        """Aiming heliostats works"""
        elev = N.pi/4
        az = N.pi/2
        self.field.aim_to_sun(az, elev)
        
        e = TracerEngine(self.field)
        v, d = e.ray_tracer(self.rays, 1, 0.05)
        
        N.testing.assert_array_almost_equal(d[1, :self.pos.shape[0]/2], 0)
        N.testing.assert_array_almost_equal(d[0, self.pos.shape[0]/2:], 0)
        N.testing.assert_array_almost_equal(abs(d[2]*(v[0] + v[1])/(d[0] + d[1])), 85.5)
예제 #3
0
    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])
예제 #4
0
    def setUp(self):
        spread = N.r_[50:101:10]
        self.pos = N.zeros((2 * len(spread), 3))
        self.pos[:len(spread), 0] = spread
        self.pos[len(spread):, 1] = spread
        self.pos[:, 2] = 4.5

        self.field = HeliostatField(self.pos, 8., 8., 0., 90.)
        s2 = N.sqrt(2) / 2
        self.sunvec = N.r_[-s2, 0, s2]  # Noon, winterish.

        ray_pos = (self.pos + self.sunvec).T
        ray_dir = N.tile(-self.sunvec, (self.pos.shape[0], 1)).T
        self.rays = RayBundle(ray_pos,
                              ray_dir,
                              energy=N.ones(self.pos.shape[0]))
예제 #5
0
	def gen_plant(self):

		# set heliostat field characteristics: 6.09m*6.09m, abs = 0, aim_h = 61
		self.pos[:,1] = self.pos[:,1]-4. # correct6ion for the true position of the plate on the tower.
		self.field = HeliostatField(self.pos, 6.09, 6.09, absorptivity=0.04, aim_height=60,  sigma_xy=1e-3, option=None)
		self.rec_w = 11
		self.rec_h = 11
		self.rec, recobj = one_sided_receiver(self.rec_w, self.rec_h)
		rec_trans = rotx(N.pi/-2)
		rec_trans[2,3] = self.field._th

		#=================
		ground_rec = False
		#=================

		if ground_rec:
			# Evaluating missed rays in the field along with receiver
			radius = 1.10 * math.sqrt((self.x_dist/2)**2 + (self.y_dist/2)**2)
			self.ground_rec, ground_recobj = one_sided_receiver(3*radius, 3*radius)

			ground_rec_trans = rotz(0)
			ground_rec_trans[0,3] = self.field_centre[0]
			ground_rec_trans[1,3] = self.field_centre[1]
			
			recobj.set_transform(rec_trans)
			ground_recobj.set_transform(ground_rec_trans)
			self.plant = Assembly(objects=[recobj, ground_recobj], subassemblies=[self.field])
		else:
			# Evaluating just the receiver
			recobj.set_transform(rec_trans)
		
			self.plant = Assembly(objects=[recobj], subassemblies=[self.field])	  
예제 #6
0
    def gen_plant(self):

        # set heliostat field characteristics: 6.09m*6.09m, abs = 0, aim_h = 61
        self.pos[:,
                 1] = self.pos[:,
                               1] - 4.  # correct6ion for the true position of the plate on the tower.
        self.field = HeliostatField(self.pos,
                                    6.09,
                                    6.09,
                                    absorptivity=0.04,
                                    aim_height=60,
                                    sigma_xy=1e-3,
                                    option=None)
        self.rec_w = 11
        self.rec_h = 11
        self.rec, recobj = one_sided_receiver(self.rec_w, self.rec_h)
        rec_trans = rotx(N.pi / -2)
        rec_trans[2, 3] = self.field._th

        #=================
        ground_rec = False
        #=================

        if ground_rec:
            # Evaluating missed rays in the field along with receiver
            radius = 1.10 * math.sqrt((self.x_dist / 2)**2 +
                                      (self.y_dist / 2)**2)
            self.ground_rec, ground_recobj = one_sided_receiver(
                3 * radius, 3 * radius)

            ground_rec_trans = rotz(0)
            ground_rec_trans[0, 3] = self.field_centre[0]
            ground_rec_trans[1, 3] = self.field_centre[1]

            recobj.set_transform(rec_trans)
            ground_recobj.set_transform(ground_rec_trans)
            self.plant = Assembly(objects=[recobj, ground_recobj],
                                  subassemblies=[self.field])
        else:
            # Evaluating just the receiver
            recobj.set_transform(rec_trans)

            self.plant = Assembly(objects=[recobj], subassemblies=[self.field])
예제 #7
0
class TestHeliostatField(unittest.TestCase):
    def setUp(self):
        spread = N.r_[50:101:10]
        self.pos = N.zeros((2 * len(spread), 3))
        self.pos[:len(spread), 0] = spread
        self.pos[len(spread):, 1] = spread
        self.pos[:, 2] = 4.5

        self.field = HeliostatField(self.pos, 8., 8., 0., 90.)
        s2 = N.sqrt(2) / 2
        self.sunvec = N.r_[-s2, 0, s2]  # Noon, winterish.

        ray_pos = (self.pos + self.sunvec).T
        ray_dir = N.tile(-self.sunvec, (self.pos.shape[0], 1)).T
        self.rays = RayBundle(ray_pos,
                              ray_dir,
                              energy=N.ones(self.pos.shape[0]))

    def test_secure_position(self):
        """Heliostats at default position absorb the sunlight"""
        e = TracerEngine(self.field)
        e.ray_tracer(self.rays, 1, 0.05)

        N.testing.assert_array_equal(e.tree[-1].get_energy(), 0)

    def test_aim(self):
        """Aiming heliostats works"""
        elev = N.pi / 4
        az = N.pi / 2
        self.field.aim_to_sun(az, elev)

        e = TracerEngine(self.field)
        v, d = e.ray_tracer(self.rays, 1, 0.05)

        N.testing.assert_array_almost_equal(d[1, :self.pos.shape[0] / 2], 0)
        N.testing.assert_array_almost_equal(d[0, self.pos.shape[0] / 2:], 0)
        N.testing.assert_array_almost_equal(
            abs(d[2] * (v[0] + v[1]) / (d[0] + d[1])), 85.5)
예제 #8
0
 def setUp(self):
     spread = N.r_[50:101:10]
     self.pos = N.zeros((2*len(spread), 3))
     self.pos[:len(spread), 0] = spread
     self.pos[len(spread):, 1] = spread
     self.pos[:,2] = 4.5
     
     self.field = HeliostatField(self.pos, 8., 8., 0., 90.)
     s2 = N.sqrt(2)/2
     self.sunvec = N.r_[-s2, 0, s2] # Noon, winterish.
     
     ray_pos = (self.pos + self.sunvec).T
     ray_dir = N.tile(-self.sunvec, (self.pos.shape[0], 1)).T
     self.rays = RayBundle(ray_pos, ray_dir, energy=N.ones(self.pos.shape[0]))
예제 #9
0
    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 gen_plant(self, width=6.1, height=6.1, absorptivity=0.04, aim_height=60.,  sigma_xy=1e-3, rec_w=11., rec_h=11.):

		self.pos[:,1] = self.pos[:,1]-4. # correction for the true position of the plate on the tower.
		self.width = width
		self.height = height
		self.absorptivity = absorptivity
		self.field = HeliostatField(self.pos, width, height, absorptivity, aim_height,  sigma_xy)
		self.rec_w = rec_w
		self.rec_h = rec_h
		rec, recobj = one_sided_receiver(self.rec_w, self.rec_h)
		rec_trans = rotx(N.pi/-2)
		rec_trans[2,3] = self.field._th

		# Evaluating just the receiver
		recobj.set_transform(rec_trans)
	
		self.plant = Assembly(objects=[recobj], subassemblies=[self.field])	  
예제 #11
0
	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])
예제 #12
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()
예제 #13
0
class TowerScene():

	# Location of the sun:
	sun_az = 0
	sun_elev = 34.96

	sun_vec = solar_vector(sun_az*degree, sun_elev*degree)
	hstat_normals = N.zeros((218,3))
	
	# import custom coordinate file
	pos = N.loadtxt("/home/charles/Documents/Tracer/examples/sandia_hstat_coordinates.csv", delimiter=',')
		
	# Field-based calculations for source size parameters
	#===================================================
	t_pos = pos.T
	xc_min = t_pos[0][N.argmin(t_pos[0])]
	xc_max = t_pos[0][N.argmax(t_pos[0])]
	yc_min = t_pos[1][N.argmin(t_pos[1])]
	yc_max = t_pos[1][N.argmax(t_pos[1])]

	x_dist = xc_max - xc_min
	y_dist = yc_max - yc_min

	xc_cent = (xc_min + xc_max) / 2
	yc_cent = (yc_min + yc_max) / 2
	field_centre = N.r_[xc_cent, yc_cent, 0]
	#===================================================
	
	def __init__(self):
		self.gen_plant() 

	def gen_rays(self, num_rays, flux=1000.):
		#========================
		individual_source = True
		#========================

		if individual_source:
			# Pillbox source on a per-heliostat basis
			radius = 1.20 * math.sqrt(2 * 3.405**2)

			direction = N.array(-self.sun_vec)

			ray_list = []
			num_surfs = self.pos.shape[0]
			for i in xrange(num_surfs):
				centre = N.c_[50 * self.sun_vec + self.pos[i]]
				rayb = solar_disk_bundle(num_rays/num_surfs, centre, direction, radius, 4.65e-3, flux)
				ray_list.append(rayb)

			rays = concatenate_rays(ray_list)
			del ray_list
			
		else:
			# Large pillbox sunshape source disc source covering entire field area:
			radius = 1.10 * math.sqrt((self.x_dist/2)**2 + (self.y_dist/2)**2)

			self.source_area = N.pi * radius**2

			centre = N.c_[300*self.sun_vec + self.field_centre]
			direction = N.array(-self.sun_vec)

			rays = solar_disk_bundle(num_rays, centre, direction, radius, 4.65e-3, flux)
				
		return rays
	
	def gen_plant(self):

		# set heliostat field characteristics: 6.09m*6.09m, abs = 0, aim_h = 61
		self.pos[:,1] = self.pos[:,1]-4. # correct6ion for the true position of the plate on the tower.
		self.field = HeliostatField(self.pos, 6.09, 6.09, absorptivity=0.04, aim_height=60,  sigma_xy=1e-3, option=None)
		self.rec_w = 11
		self.rec_h = 11
		self.rec, recobj = one_sided_receiver(self.rec_w, self.rec_h)
		rec_trans = rotx(N.pi/-2)
		rec_trans[2,3] = self.field._th

		#=================
		ground_rec = False
		#=================

		if ground_rec:
			# Evaluating missed rays in the field along with receiver
			radius = 1.10 * math.sqrt((self.x_dist/2)**2 + (self.y_dist/2)**2)
			self.ground_rec, ground_recobj = one_sided_receiver(3*radius, 3*radius)

			ground_rec_trans = rotz(0)
			ground_rec_trans[0,3] = self.field_centre[0]
			ground_rec_trans[1,3] = self.field_centre[1]
			
			recobj.set_transform(rec_trans)
			ground_recobj.set_transform(ground_rec_trans)
			self.plant = Assembly(objects=[recobj, ground_recobj], subassemblies=[self.field])
		else:
			# Evaluating just the receiver
			recobj.set_transform(rec_trans)
		
			self.plant = Assembly(objects=[recobj], subassemblies=[self.field])	  
	
	def aim_field(self):
		hstat_az, hstat_elev = self.field.aim_to_sun(self.sun_az*degree, self.sun_elev*degree)

		return hstat_az, hstat_elev

	def calculate_area(self, hstat_az, hstat_elev):
		'''
		Calculates the heliostats areas as seen from the source, necessary for shading calculations.
		'''
		# CONVERSION
		# sun_vec az	0	   -45	 -90	 +-180	   +90	 +45
		# hstat_az	  -90	 -45	 0	   +90		 +-180   -135
		hstat_az = -hstat_az - N.pi/2
		
		for i in xrange(len(self.pos)):
			self.hstat_normals[i] = solar_vector(hstat_az[i], hstat_elev[i])
		
		self.hstat_proj_areas = [0]*len(self.pos)
		for i in xrange(len(self.pos)):
			self.hstat_proj_areas[i] = (6.09**2) * abs(N.dot(-self.sun_vec, self.hstat_normals[i]))
	
	def trace(self):
		'''
		Raytrace method.

		Raytraces successive bundles and stores the resultsogf the shading, blicking, incoming radiative power on the heliostats and the fluxmap on the receiver.
		'''
		# Generate a large ray bundle using [a radial stagger much denser
		# than the field] a Buie sunshape with radius equal to the longest
		# dimension of the field.

		#=============
		render = False
		#=============
		
		sun_vec = solar_vector(self.sun_az*degree, self.sun_elev*degree)
		
		# Generate the following number of rays
		num_rays = 500000.
		iters = 40

		# Results bins:
		incoming = N.zeros(len(self.pos))
		prev_incoming = N.zeros(len(self.pos))
		incoming_Q = N.zeros(len(self.pos))
		incoming_stdev = N.zeros(len(self.pos))

		shading = N.ones(len(self.pos))
		prev_shading = N.zeros(len(self.pos))
		shading_Q = N.zeros(len(self.pos))
		shading_stdev = N.zeros(len(self.pos))

		blocking = N.zeros(len(self.pos))
		prev_blocking = N.zeros(len(self.pos))
		blocking_Q= N.zeros(len(self.pos))
		blocking_stdev= N.zeros(len(self.pos))

		timer_mcrt = 0. 
		timer_postprocess = 0.

		# Receiver bins:
		dl=11./50.
		bins = N.arange(-5.5,5.5+dl, dl)
		fluxmap = N.zeros((len(bins)-1,len(bins)-1))

		# Raytrace:
		mcrt = time.clock()
		e = TracerEngineMP(self.plant)
		procs = 8
		e.minener = 1e-10
		timer_mcrt += time.clock()-mcrt
		hits_helios=0
		i=0

		#while hits_helios < 20e6:
		for i in xrange(iters):
			print ' '
			print ' '
			print 'ITERATION ', i+1#, ' of ', iters 
			mcrt = time.clock()
			# Perform the trace:
			sources = []
			self.flux = 1000.
			for s in xrange(procs):
				sources.append(self.gen_rays(num_rays/float(procs), flux=self.flux/float(procs)))
			e.multi_ray_sim(sources, procs)
			self.plant = e._asm
			self.field._heliostats = self.plant._assemblies[0].get_surfaces()
			self.rec = self.plant._objects[0].get_surfaces()[0]

			timer_mcrt += time.clock()-mcrt
			postprocess = time.clock()

			# Render:
			if render:
				trace_scene = Renderer(e)
				trace_scene.show_rays(resolution=10)

			# Get the energy and location of all hits using optics manager
			en, pts = self.rec.get_optics_manager().get_all_hits()
			x, y = self.rec.global_to_local(pts)[:2]

			# FLUX MAP OPERATIONS
			#===========================================================================
			H, xbins, ybins = N.histogram2d(x, y, bins, weights=en)
			extent = [ybins[0], ybins[-1], xbins[-1], xbins[0]]

			fluxmap = (fluxmap*float(i)+H/(1000.*dl**2.))/(i+1.)
			#===========================================================================
		
			# BLOCKAGE and SHADING
			#===========================================================================
			# Detect blockage and look for the parents of the blocked rays. Identify from which heliostats teh oarents come and associate the blockage losses to the heliostats where blockage is suffered.
			
			hz = (e.tree._bunds[1].get_vertices()[2]) < (self.field._th-self.rec_h/2.)
			hits_helios += N.sum(hz)
			print 'Useful rays:', hits_helios
			# Get the 3rd bundle (after 2 hits):
			bund_2 = e.tree._bunds[2].get_vertices()
			bund_2_ener = e.tree._bunds[2].get_energy()

			# Remove receiver hits from the bundle to get only hits on heliostats:
			bund_2_helio_hits = N.ravel(N.nonzero(bund_2[2] < (self.field._th-self.rec_h/2.)))
			bund_2_bloc = bund_2[:, bund_2_helio_hits]

			# Get the bundle emitting the blocked rays and isolate the blocked rays:
			bund_1_helio_blocs = e.tree._bunds[2].get_parents()[bund_2_helio_hits]
			bund_1 = e.tree._bunds[1].get_vertices()
			bund_1_ener = e.tree._bunds[1].get_energy()
			bund_1_bloc = bund_1[:, bund_1_helio_blocs]

			# Screen the field to find where blocked rays originate:
			for h in xrange(len(self.pos)):
				# Get the information from the optics manager of the heliostat:
				abs_hstats, hits_hstats, dirs_hstats = self.field._heliostats[h].get_optics_manager().get_all_hits()

				blocs = []
				hit_0s = []

				# Check if any hits:
				if len(hits_hstats)!=0:
					# Screen through every hit:
					for r in xrange(N.shape(hits_hstats)[1]):
						# Is the hit a ray that will be blocked or a blocked ray?
						bloc = N.nonzero(hits_hstats[0,r] == bund_1_bloc[0])[0]
						# Next "if" is because if there are no valid hits the bloc returns an empty array or to isolate each hit in case of 2 hits matching.
						if len(bloc)>0:
							for b in xrange(len(bloc)):
								# If sthe first coordinate matches, do the rest of them?
								if (hits_hstats[:,r]==N.ravel(bund_1_bloc[:,bloc[b]])).all():
									# If so add the blocked energy to the result bin.
									blocs.append(bund_1_helio_blocs[bloc[b]])

						else:
							hit_0 = N.nonzero(hits_hstats[0,r] == bund_1[0])[0]
							if len(hit_0)>0:
								for s in xrange(len(hit_0)):
									if (hits_hstats[:,r]==N.ravel(bund_1[:,hit_0[s]])).all():			
										hit_0s.append(e.tree._bunds[1].get_parents()[hit_0[s]])
				prev_blocking[h] = blocking[h]

				# Monte-Carlo sampling:
				blocking[h] = (blocking[h]*i+N.sum(bund_1_ener[blocs]))/(i+1.)		

				# Shading is the theoretical energy hitting subtracted by the energy absorbed without the backside blocking.
				prev_incoming[h] = incoming[h]
				# Monte-Carlo sampling:
				incoming[h] = (incoming[h]*i+N.sum(e.tree._bunds[0].get_energy()[hit_0s]))/(i+1.)

				prev_shading[h] = shading[h]
				# Monte-Carlo sampling:
				shading[h] = (shading[h]*i+self.flux*self.hstat_proj_areas[h]-incoming[h])/(i+1.)
				
			# Streamlined stats variable:
			incoming_Q = incoming_Q+i/(i+1.)*(incoming-prev_incoming)**2.
			blocking_Q = blocking_Q+i/(i+1.)*(blocking-prev_blocking)**2.
			shading_Q = shading_Q+i/(i+1.)*(shading-prev_shading)**2.

			# Standard deviatiosn updates:
			if i>0:
				incoming_stdev = N.sqrt(incoming_Q/i)
				blocking_stdev = N.sqrt(blocking_Q/i)
				shading_stdev = N.sqrt(shading_Q/i)

			print 'Shading=', N.sum(shading)
			print 'Blockage=', N.sum(blocking)

			timer_postprocess += time.clock()-postprocess

			print 'timer_mcrt: ', timer_mcrt/60., 'min'
			print 'timer_postprocess: ', timer_postprocess/60., 'min'

			print 'Peak flux (kW/m2):', N.amax(fluxmap)
			print 'AVG flux (kW/m2): ', N.sum(fluxmap)/(N.shape(fluxmap)[0]*N.shape(fluxmap)[1])
			print 'Total radiative power (kW): ', N.sum(fluxmap*(11./50.)**2)

			i+=1
		
			#===========================================================================
			e.tree._bunds = []
			for clear in xrange(len(e._asm.get_surfaces())):
				e._asm.get_surfaces()[clear].get_optics_manager().reset()
			#===========================================================================
		'''
예제 #14
0
class TowerScene():

    # Location of the sun:
    sun_az = 0
    sun_zenith = 35.05  #34.96

    sun_vec = solar_vector(sun_az * degree, sun_zenith * degree)
    hstat_normals = N.zeros((218, 3))

    # import custom coordinate file
    pos = N.loadtxt(
        "/home/charles/Documents/Tracer/examples/sandia_hstat_coordinates.csv",
        delimiter=',')

    # Field-based calculations for source size parameters
    #===================================================
    t_pos = pos.T
    xc_min = t_pos[0][N.argmin(t_pos[0])]
    xc_max = t_pos[0][N.argmax(t_pos[0])]
    yc_min = t_pos[1][N.argmin(t_pos[1])]
    yc_max = t_pos[1][N.argmax(t_pos[1])]

    x_dist = xc_max - xc_min
    y_dist = yc_max - yc_min

    xc_cent = (xc_min + xc_max) / 2
    yc_cent = (yc_min + yc_max) / 2
    field_centre = N.r_[xc_cent, yc_cent, 0]

    #===================================================

    def __init__(self):
        self.gen_plant()

    def gen_rays(self, num_rays, flux=1000.):
        #========================
        individual_source = False
        #========================

        if individual_source:
            # Pillbox source on a per-heliostat basis
            radius = 1.20 * math.sqrt(2 * 3.405**2)

            direction = N.array(-self.sun_vec)

            ray_list = []
            num_surfs = self.pos.shape[0]
            for i in xrange(num_surfs):
                centre = N.c_[50 * self.sun_vec + self.pos[i]]
                #rayb = solar_disk_bundle(num_rays/num_surfs, centre, direction, radius, 4.65e-3, flux)
                rayb = buie_sunshape(num_rays / num_surfs,
                                     centre,
                                     direction,
                                     radius,
                                     CSR=0.01,
                                     flux=flux)
                ray_list.append(rayb)

            rays = concatenate_rays(ray_list)
            del ray_list

        else:
            # Large pillbox sunshape source disc source covering entire field area:
            radius = 1.10 * math.sqrt((self.x_dist / 2)**2 +
                                      (self.y_dist / 2)**2)

            self.source_area = N.pi * radius**2

            centre = N.c_[300 * self.sun_vec + self.field_centre]
            direction = N.array(-self.sun_vec)

            #rays = solar_disk_bundle(num_rays, centre, direction, radius, 4.65e-3, flux)
            rays = buie_sunshape(num_rays,
                                 centre,
                                 direction,
                                 radius,
                                 CSR=0.01,
                                 flux=flux,
                                 pre_process_CSR=False)

        return rays

    def gen_plant(self,
                  width=6.1,
                  height=6.1,
                  absorptivity=0.04,
                  aim_height=60.,
                  sigma_xy=1e-3,
                  rec_w=11.,
                  rec_h=11.):

        self.pos[:,
                 1] = self.pos[:,
                               1] - 4.  # correction for the true position of the plate on the tower.
        self.width = width
        self.height = height
        self.absorptivity = absorptivity
        self.field = HeliostatField(self.pos, width, height, absorptivity,
                                    aim_height, sigma_xy)
        self.rec_w = rec_w
        self.rec_h = rec_h
        rec, recobj = one_sided_receiver(self.rec_w, self.rec_h)
        rec_trans = rotx(N.pi / -2)
        rec_trans[2, 3] = self.field._th

        # Evaluating just the receiver
        recobj.set_transform(rec_trans)

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

    def aim_field(self):
        hstat_az, hstat_elev = self.field.aim_to_sun(self.sun_az * degree,
                                                     self.sun_zenith * degree)

        return hstat_az, hstat_elev

    def calculate_area(self, hstat_az, hstat_elev):
        '''
		Calculates the heliostats areas as seen from the source, necessary for shading calculations.
		'''
        # CONVERSION
        # sun_vec az	0	   -45	 -90	 +-180	   +90	 +45
        # hstat_az	  -90	 -45	 0	   +90		 +-180   -135
        hstat_az = -hstat_az - N.pi / 2

        for i in xrange(len(self.pos)):
            self.hstat_normals[i] = solar_vector(hstat_az[i], hstat_elev[i])

        self.hstat_proj_areas = [0] * len(self.pos)
        for i in xrange(len(self.pos)):
            self.hstat_proj_areas[i] = (6.1**2) * abs(
                N.dot(-self.sun_vec, self.hstat_normals[i]))

    def trace(self, num_rays=1e5, nbins_w=50., nbins_h=50.):
        '''
		Raytrace method.

		Raytraces successive bundles and stores the resultsogf the shading, blicking, incoming radiative power on the heliostats and the fluxmap on the receiver.
		'''
        # Generate a large ray bundle using [a radial stagger much denser
        # than the field] a Buie sunshape with radius equal to the longest
        # dimension of the field.

        #=============
        render = False
        #=============

        sun_vec = solar_vector(self.sun_az * degree, self.sun_zenith * degree)

        bundlesize = 1e4
        iters = int(num_rays / bundlesize)

        # Results bins:
        incoming = N.zeros(len(self.pos))
        prev_incoming = N.zeros(len(self.pos))
        incoming_Q = N.zeros(len(self.pos))
        incoming_stdev = N.zeros(len(self.pos))

        shading = N.ones(len(self.pos))
        prev_shading = N.zeros(len(self.pos))
        shading_Q = N.zeros(len(self.pos))
        shading_stdev = N.zeros(len(self.pos))

        blocking = N.zeros(len(self.pos))
        prev_blocking = N.zeros(len(self.pos))
        blocking_Q = N.zeros(len(self.pos))
        blocking_stdev = N.zeros(len(self.pos))

        timer_mcrt = 0.
        timer_postprocess = 0.

        # Receiver bins:

        dlw = self.rec_w / nbins_w
        dlh = self.rec_h / nbins_h
        bins_w = N.arange(-self.rec_w / 2., self.rec_w / 2. + dlw, dlw)
        bins_h = N.arange(-self.rec_h / 2., self.rec_h / 2. + dlh, dlh)
        bins = [bins_w, bins_h]
        self.bins = bins
        fluxmap = N.zeros((len(bins_w) - 1, len(bins_h) - 1))

        # Raytrace:
        mcrt = time.clock()
        e = TracerEngineMP(self.plant)
        procs = 1
        e.minener = 1e-10
        timer_mcrt += time.clock() - mcrt
        hits_helios = 0
        i = 0

        #while hits_helios < num_rays:
        for i in xrange(iters):
            print ' '
            print ' '
            print 'ITERATION ', i + 1, ' of ', iters
            #print hits_helios, 'hits out of ', num_rays
            mcrt = time.clock()
            # Perform the trace:
            sources = []
            self.flux = 1000.
            for s in xrange(procs):
                sources.append(
                    self.gen_rays(num_rays=bundlesize / float(procs),
                                  flux=self.flux / float(procs)))
            e.multi_ray_sim(sources=sources, procs=procs)
            self.plant = e._asm
            self.field._heliostats = self.plant._assemblies[0].get_surfaces()
            self.rec = self.plant._objects[0].get_surfaces()[0]

            timer_mcrt += time.clock() - mcrt
            postprocess = time.clock()

            # Render:
            if render:
                trace_scene = Renderer(e)
                trace_scene.show_rays(resolution=10)

            # Get the energy and location of all hits using optics manager
            en, pts = self.rec.get_optics_manager().get_all_hits()
            x, y = self.rec.global_to_local(pts)[:2]

            # FLUX MAP OPERATIONS
            #===========================================================================
            H, xbins, ybins = N.histogram2d(x,
                                            y,
                                            bins,
                                            weights=en / (dlw * dlh) * 1e-3)
            extent = [ybins[0], ybins[-1], xbins[-1], xbins[0]]

            fluxmap = (fluxmap * float(i) + H) / (i + 1.)
            #===========================================================================

            # BLOCKAGE and SHADING
            #===========================================================================
            # Detect blockage and look for the parents of the blocked rays. Identify from which heliostats the parents come and associate the blockage losses to the heliostats where blockage is suffered.

            hz = (e.tree._bunds[1].get_vertices()[2]) < (self.field._th -
                                                         self.rec_h / 2.)
            hits_helios += N.sum(hz)
            print 'Useful rays:', hits_helios
            # Get the 3rd bundle (after 2 hits):
            bund_2 = e.tree._bunds[2].get_vertices()
            bund_2_ener = e.tree._bunds[2].get_energy()

            # Remove receiver hits from the bundle to get only hits on heliostats:
            bund_2_helio_hits = N.ravel(
                N.nonzero(bund_2[2] < (self.field._th - self.rec_h / 2.)))
            bund_2_bloc = bund_2[:, bund_2_helio_hits]

            # Get the bundle emitting the blocked rays and isolate the blocked rays:
            bund_1_helio_blocs = e.tree._bunds[2].get_parents(
            )[bund_2_helio_hits]
            bund_1 = e.tree._bunds[1].get_vertices()
            bund_1_ener = e.tree._bunds[1].get_energy()
            bund_1_bloc = bund_1[:, bund_1_helio_blocs]

            # Screen the field to find where blocked rays originate:
            for h in xrange(len(self.pos)):
                # Get the information from the optics manager of the heliostat:
                abs_hstats, hits_hstats, dirs_hstats = self.field._heliostats[
                    h].get_optics_manager().get_all_hits()

                blocs = []
                hit_0s = []

                # Check if any hits:
                if len(hits_hstats) != 0:
                    # Screen through every hit:
                    for r in xrange(N.shape(hits_hstats)[1]):
                        # Is the hit a ray that will be blocked or a blocked ray?
                        bloc = N.nonzero(hits_hstats[0,
                                                     r] == bund_1_bloc[0])[0]
                        # Next "if" is because if there are no valid hits the bloc returns an empty array or to isolate each hit in case of 2 hits matching.
                        if len(bloc) > 0:
                            for b in xrange(len(bloc)):
                                # If sthe first coordinate matches, do the rest of them?
                                if (hits_hstats[:, r] == N.ravel(
                                        bund_1_bloc[:, bloc[b]])).all():
                                    # If so add the blocked energy to the result bin.
                                    blocs.append(bund_1_helio_blocs[bloc[b]])

                        else:
                            hit_0 = N.nonzero(hits_hstats[0,
                                                          r] == bund_1[0])[0]
                            if len(hit_0) > 0:
                                for s in xrange(len(hit_0)):
                                    if (hits_hstats[:, r] == N.ravel(
                                            bund_1[:, hit_0[s]])).all():
                                        hit_0s.append(
                                            e.tree._bunds[1].get_parents()[
                                                hit_0[s]])
                prev_blocking[h] = blocking[h]

                # Monte-Carlo sampling:
                blocking[h] = (blocking[h] * i +
                               N.sum(bund_1_ener[blocs])) / (i + 1.)

                # Shading is the theoretical energy hitting subtracted by the energy absorbed without the backside blocking.
                prev_incoming[h] = incoming[h]
                # Monte-Carlo sampling:
                incoming[h] = (incoming[h] * i + N.sum(
                    e.tree._bunds[0].get_energy()[hit_0s])) / (i + 1.)

                prev_shading[h] = shading[h]
                # Monte-Carlo sampling:
                shading[h] = (shading[h] * i +
                              self.flux * self.hstat_proj_areas[h] -
                              incoming[h]) / (i + 1.)

            # Streamlined stats variable:
            incoming_Q = incoming_Q + i / (i + 1.) * (incoming -
                                                      prev_incoming)**2.
            blocking_Q = blocking_Q + i / (i + 1.) * (blocking -
                                                      prev_blocking)**2.
            shading_Q = shading_Q + i / (i + 1.) * (shading - prev_shading)**2.

            # Standard deviatiosn updates:
            if i > 0:
                incoming_stdev = N.sqrt(incoming_Q / i)
                blocking_stdev = N.sqrt(blocking_Q / i)
                shading_stdev = N.sqrt(shading_Q / i)

            print 'Shading=', N.sum(shading)
            print 'Blockage=', N.sum(blocking)

            timer_postprocess += time.clock() - postprocess

            print 'timer_mcrt: ', timer_mcrt / 60., 'min'
            print 'timer_postprocess: ', timer_postprocess / 60., 'min'

            print 'Peak flux (kW/m2):', N.amax(fluxmap)
            print 'AVG flux (kW/m2): ', N.sum(fluxmap) / (N.shape(fluxmap)[0] *
                                                          N.shape(fluxmap)[1])
            print 'Total radiative power (kW): ', N.sum(fluxmap *
                                                        (11. / 50.)**2)

            i += 1

            #===========================================================================
            e.tree._bunds = []
            for clear in xrange(len(e._asm.get_surfaces())):
                e._asm.get_surfaces()[clear].get_optics_manager().reset()
            #===========================================================================
            del (self.plant)
        results = {
            'positions': self.pos,
            'blocking': blocking,
            'blocking_stdev': blocking_stdev,
            'shading': shading,
            'shading_stdev': shading_stdev,
            'incoming': incoming,
            'incoming_stdev': incoming_stdev,
            'fluxmap': fluxmap,
            'extent': extent,
            'width': self.width,
            'height': self.height,
            'absorptivity': self.absorptivity,
            'rec_width': self.rec_w,
            'rec_height': self.rec_h,
            'rec_bins': self.bins
        }
        filesave = open(
            '/home/charles/Documents/Boulot/These/Heliostat field/Sandia_data',
            'w')
        pickle.dump(results, filesave)
        filesave.close()
예제 #15
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()
예제 #16
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
예제 #17
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()
예제 #18
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())))