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 test_concat(self): r1 = RB.RayBundle(N.ones((3, 4)), N.ones((3, 4))) r2 = RB.RayBundle(N.zeros((3, 4)), N.zeros((3, 4))) con = RB.concatenate_rays((r1, r2)) correct = N.hstack((N.ones((3, 4)), N.zeros((3, 4)))) N.testing.assert_array_equal(con.get_vertices(), correct) N.testing.assert_array_equal(con.get_directions(), correct)
def test_extra_prop(self): r1 = RB.RayBundle( N.ones((3, 4)), N.ones((3, 4)), wavelen=N.ones((3, 4))) r2 = RB.RayBundle( N.zeros((3, 4)), N.zeros((3, 4)), wavelen=N.zeros((3, 4))) con = RB.concatenate_rays((r1, r2)) correct = N.hstack((N.ones((3, 4)), N.zeros((3, 4)))) N.testing.assert_array_equal(con.get_wavelen(), correct)
def test_extra_prop(self): r1 = RB.RayBundle(N.ones((3, 4)), N.ones((3, 4)), wavelen=N.ones((3, 4))) r2 = RB.RayBundle(N.zeros((3, 4)), N.zeros((3, 4)), wavelen=N.zeros((3, 4))) con = RB.concatenate_rays((r1, r2)) correct = N.hstack((N.ones((3, 4)), N.zeros((3, 4)))) N.testing.assert_array_equal(con.get_wavelen(), correct)
def trapezoid_bundle(num_rays, A, B, C, direction=None, ang_range=N.pi / 2., flux=None, procs=1): """ Regular trapezoid ray-casting surface. ABCD must be placed to follow the perimeter of the quadrilateral. AB is the first base and CD is the second base. Arguments: - num_rays: the number of rays cast - A: the first point of the trapezoid. - B: second vertex forming AB the first base. - C: third vertex forming AC the first diagonal. D is obtained by symmetry. - direction: The around which the rays escape the source. If None: the normal of the surface with respect to the right hand rule. - ang_range: the angular range of the rays emitted by the source Returns: - A ray-bundle object to ray-trace """ AB = B - A AC = C - A # Separate into two triangles ABC and ACD and calculate their respective areas: l1 = N.sqrt(N.sum(AB**2)) l2 = N.sqrt(N.sum(AC**2)) cos_theta = N.dot(AC, AB) / (l1 * l2) cB = AB * (1. - 1. / l1 * l2 * cos_theta) CD = -(AB - 2. * cB) AD = AC + CD D = A + AD l3 = N.sqrt(N.sum(AD**2)) l4 = N.sqrt(N.sum((-AB + AC)**2)) l5 = N.sqrt(N.sum((-AC + AD)**2)) # Area calculated using Heron's formula s1 = (l1 + l2 + l4) / 2. s2 = (l2 + l3 + l5) / 2. area_ABC = N.sqrt(s1 * (s1 - l1) * (s1 - l2) * (s1 - l4)) area_ACD = N.sqrt(s2 * (s2 - l2) * (s2 - l3) * (s2 - l5)) # Calculate how many rays per triangle are needed considering the number of rays asked for: num_rays_ABC = int(area_ABC / (area_ABC + area_ACD) * num_rays) num_rays_ACD = num_rays - num_rays_ABC # Get a ray-bundle for each triangle and concatenate them: rayb_ABC = triangular_bundle(num_rays_ABC, A, B, C, direction, ang_range, flux) rayb_ACD = triangular_bundle(num_rays_ACD, A, C, D, direction, ang_range, flux) rayb = concatenate_rays([rayb_ABC, rayb_ACD]) if flux == None: rayb.set_energy(N.ones(num_rays) / float(num_rays) / procs) return rayb
def trapezoid_bundle(num_rays, A, AB, AC, AD, direction, ang_range=N.pi / 2., flux=None, procs=1): """ Trapezoidal ray-casting surface. ABCD must be placed to follow the perimeter of teh quadrilateral. AB is the first base and CD is the second base. Arguments: - num_rays: the number of rays cast - A: the first point of the trapezoid and its anchor point in the global referential. - AB: first base of the trapezoid on its plane of reference. - AC: first diagonal of the trapezoid - AD: last vertex of the trapezoid - direction: The direction at which the source is pointing - ang_range: the angular range of the rays emitted by the source Returns: - A ray-bundle object to ray-trace """ # Separate into two triangles ABC and ACD and calculate their respective areas: l1 = N.sqrt(N.sum(AB**2)) l2 = N.sqrt(N.sum(AC**2)) l3 = N.sqrt(N.sum(AD**2)) l4 = N.sqrt(N.sum((-AB + AC)**2)) l5 = N.sqrt(N.sum((-AC + AD)**2)) # Area calculated using Heron's formula s1 = (l1 + l2 + l4) / 2. s2 = (l2 + l3 + l5) / 2. area_ABC = N.sqrt(s1 * (s1 - l1) * (s1 - l2) * (s1 - l4)) area_ACD = N.sqrt(s2 * (s2 - l2) * (s2 - l3) * (s2 - l5)) # Calculate how many rays per triangle are needed considering the number of rays asked for: num_rays_ABC = int(area_ABC / (area_ABC + area_ACD) * num_rays) num_rays_ACD = num_rays - num_rays_ABC # Get a ray-bundle for each triangle and concatenate them: rayb_ABC = triangular_bundle(num_rays_ABC, A, AB, AC, direction, ang_range, flux) rayb_ACD = triangular_bundle(num_rays_ACD, A, AC, AD, direction, ang_range, flux) rayb = concatenate_rays([rayb_ABC, rayb_ACD]) if flux == None: rayb.set_energy(N.ones(num_rays) / float(num_rays) / procs) return rayb
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 trapezoid_bundle(num_rays, A, AB, AC, AD, direction, ang_range=N.pi/2., flux=None, procs=1): """ Trapezoidal ray-casting surface. ABCD must be placed to follow the perimeter of the quadrilateral. AB is the first base and CD is the second base. Arguments: - num_rays: the number of rays cast - A: the first point of the trapezoid and its anchor point in the global referential. - AB: first base of the trapezoid on its plane of reference. - AC: first diagonal of the trapezoid - AD: last vertex of the trapezoid - direction: The direction at which the source is pointing - ang_range: the angular range of the rays emitted by the source Returns: - A ray-bundle object to ray-trace """ # Separate into two triangles ABC and ACD and calculate their respective areas: l1 = N.sqrt(N.sum(AB**2)) l2 = N.sqrt(N.sum(AC**2)) l3 = N.sqrt(N.sum(AD**2)) l4 = N.sqrt(N.sum((-AB+AC)**2)) l5 = N.sqrt(N.sum((-AC+AD)**2)) # Area calculated using Heron's formula s1 = (l1+l2+l4)/2. s2 = (l2+l3+l5)/2. area_ABC = N.sqrt(s1*(s1-l1)*(s1-l2)*(s1-l4)) area_ACD = N.sqrt(s2*(s2-l2)*(s2-l3)*(s2-l5)) # Calculate how many rays per triangle are needed considering the number of rays asked for: num_rays_ABC = int(area_ABC/(area_ABC+area_ACD)*num_rays) num_rays_ACD = num_rays-num_rays_ABC # Get a ray-bundle for each triangle and concatenate them: rayb_ABC = triangular_bundle(num_rays_ABC, A, AB, AC, direction, ang_range, flux) rayb_ACD = triangular_bundle(num_rays_ACD, A, AC, AD, direction, ang_range, flux) rayb = concatenate_rays([rayb_ABC,rayb_ACD]) if flux == None: rayb.set_energy(N.ones(num_rays)/float(num_rays)/procs) return rayb