Example #1
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
Example #2
0
	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()
Example #3
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
Example #4
0
    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()
Example #5
0
    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()
Example #6
0
 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 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 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]))
Example #9
0
    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()
Example #10
0
	def traceMP(self, rays_per_run, iters = 10000, minE = 1e-9, render = False,procs = 1):
		"""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)
		rot_sun = rotation_to_z(-sun_vec)
        	# Calculate number of rays used. Rays per heliostat * number of heliostats.
		rppph = int(rays_per_run/(procs*len(self.field.get_heliostats())))
		rpp = rppph*len(self.field.get_heliostats())
		rpr = rpp*procs					#actual rays per run used

		ray_sources = []
		n = 1
		while n <= procs:
			direct = N.dot(rot_sun, pillbox_sunshape_directions(rpp, 0.00465))
			xy = N.random.uniform(low=-0.25, high=0.25, size=(2, rpp))
        		base_pos = N.tile(self.pos, (rppph, 1)).T
        		base_pos += N.dot(rot_sun[:,:2], xy)

        		base_pos -= direct
        		rays = RayBundle(base_pos, direct, energy=N.ones(rpp))
			ray_sources.append(rays)
			n += 1

		e = TracerEngineMP(self.plant)
		e.multi_ray_sim(ray_sources,procs)
		self.plant = e._asm
		self.helio_hits = sum(e.tree._bunds[1].get_energy())
			# Note that you may need some stuff in here
		if render == True:
			trace_scene = Renderer(e)
			trace_scene.show_rays(resolution=10)
			render = False

		return rpr #this is special
Example #11
0
 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 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()
			#===========================================================================
		'''
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()
    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()
Example #15
0
    def gen_plant(self):

        #--------------
        #    field
        #--------------
        # heliostats
        self.hst_w = 1.85
        self.hst_h = 2.44
        reflectivity = 0.9
        slope_type = 'normal'  #'normal' or 'pillbox' or 'perfect'-- for one mirror only
        slope_error = 1.64e-3  #rad (0 is a perfect mirror)
        curved = True  # or False: flat mirror
        self.oneMirror = False  # or True: for simulating just one mirror
        hst_file = './examples/heliostat_field_example/hst_info.csv'  #or None
        #hst_file=None

        if self.oneMirror:
            if hst_file != None:
                # index of the position of the heliostats
                index = 2
                pos = N.zeros(3)
                foc = 0.
            else:
                # or hst_file=None,by putting the specific pos and focal
                index = -1  #
                pos = N.r_[0., 20., 0.]
                foc = 30.

        else:
            index = -1
            pos = N.zeros(3)
            foc = 0.

        heliostat = HeliostatGenerator(self.hst_w,
                                       self.hst_h,
                                       absorptivity=1. - reflectivity,
                                       sigma_xy=slope_error,
                                       slope=slope_type,
                                       curved=curved,
                                       one_mirror=self.oneMirror,
                                       index=index,
                                       pos=pos,
                                       foc=foc)

        # layout and field

        layout = KnownField(hst_file, pos, foc)

        # tracking
        tracking_mode = 'AzEl'  # 'AzEl'or 'TiltRoll'

        # aiming
        aiming_mode = 'SinglePoint'  # 'MultiFixed' or 'SinglePoint'

        #---------------
        #   receiver
        #---------------
        rec_w = 1.3
        rec_h = 1.3
        absorptivity = 0.96
        rec_loc = N.r_[0., 0., 26.8]  # receiver location
        rec_rot = N.r_[106., 0.,
                       0.] * degree  # receiver rot through x, y, z (rad)

        receiver = FlatOneSidedReceiver(rec_w, rec_h, absorptivity)
        mount_rec = MountReceiver(rec_loc, rec_rot)

        #--------------
        #     solar
        #--------------
        self.sunshape = 'pillbox'
        self.sigma = 4.65e-3
        self.DNI = 1000.
        sun_az = 180.
        sun_zenith = 0.
        self.sun_vec = solar_vector(sun_az, sun_zenith)

        tower_scene = TowerScene(self.sun_vec, self.oneMirror)
        tower_scene(heliostat, layout, aiming_mode, tracking_mode, receiver,
                    mount_rec)

        self.system = tower_scene.system
        self.pos = heliostat.pos
Example #16
0
    def gen_plant(self):
        # define the case
        if self.case[0]=='A':
            if self.case[1]=='1':
                if self.case[:4]=='A1.1':
                    distribution='pillbox'
                    err=float(self.case[-1])*1.e-3
                    self.A1(err, distribution)
                elif self.case[:4]=='A1.2':
                    distribution='normal'
                    err=float(self.case[-1])*1.e-3
                    self.A1(err, distribution)
            elif self.case[1]=='2':
                if self.case[3]=='1':
                    sunshape='pillbox'
                    self.A2(sunshape)
                elif self.case[3]=='2':
                    sunshape='gaussian'
                    self.A2(sunshape)
                else:
                    sunshape='buie'
                    CSR=float(self.case[-1])*1.e-2
                    self.A2(sunshape, CSR)
            else:
                if self.case[-1]=='1':
                    sunshape='pillbox'
                else:
                    sunshape='buie'
                self.A3(sunshape)

        elif self.case[0]=='B':
            if self.case[1]=='1':
                sunshape='pillbox'
            else:
                sunshape='buie'

            if self.case[3]=='1':
                # solar noon
                sun_az=0.
                sun_zenith=12.
            else:
                # morning
                sun_az=-104.
                sun_zenith=68.

            if self.case[-1]=='1':
                hst_pos=N.r_[0., 46.5, 0.]
            elif self.case[-1]=='2':
                hst_pos=N.r_[0., 536.9, 0.]
            elif self.case[-1]=='3':
                hst_pos=N.r_[-324.3, 427.9, 0.]
            else:
                hst_pos=N.r_[252.5, 118.1, 0.]

            self.B(hst_pos, sunshape, sun_az, sun_zenith)

        elif self.case[0]=='C':
            if self.case[1]=='1':
                sunshape='pillbox'
            else:
                sunshape='buie'

            if self.case[3]=='1':
                # solar noon
                sun_az=0.
                sun_zenith=12.
            else:
                # morning
                sun_az=-104.
                sun_zenith=68.

            self.C(sunshape, sun_az, sun_zenith)

        self.output_parameters(self.savefolder)

        #--------------
        #    field
        #--------------
        heliostat=HeliostatGenerator(self.hst_w, self.hst_h, absorptivity=1.-self.reflectivity, sigma_xy=self.slope_error, slope=self.slope_type,curved=self.curved, one_mirror=self.oneMirror, index=self.index, pos=self.pos, foc=self.foc)
        # layout and field
        layout=KnownField(self.hst_file,self.pos,self.foc)

        #---------------
        #   receiver
        #---------------
        self.loc_z=self.rec_loc[-1]
        receiver=FlatOneSidedReceiver(self.rec_w,self.rec_h,self.absorptivity)
        mount_rec=MountReceiver(self.rec_loc,self.rec_rot)

        #--------------
        #     solar
        #--------------
        self.sun_vec=solar_vector(self.sun_az, self.sun_zenith)
        if self.sunshape=='buie':
            self.BUIE=buie_integration(CSR=self.sun_width,  preproc_CSR='CA')
        else:
            self.BUIE=None

        # Creating the tower scene
        #------------------------------
        tower_scene=TowerScene(self.sun_vec, self.oneMirror)
        tower_scene(heliostat, layout, self.aiming_mode, self.tracking_mode,receiver,mount_rec)

        self.system=tower_scene.system
        self.pos=heliostat.pos

        if self.oneMirror:
            self.num_hst=1
        else:
            self.num_hst=len(self.pos)