class ExampleScene(TracerScene): source_y = t_api.Range(0., 5., 2.) source_z = t_api.Range(0., 5., 1.) def __init__(self): # The energy bundle we'll use for now: nrm = 1/(N.sqrt(2)) direct = N.c_[[0,-nrm, nrm],[0,0,-1]] position = N.tile(N.c_[[0, self.source_y, self.source_z]], (1, 2)) self.bund = RayBundle(vertices=position, directions=direct, energy=N.r_[1, 1]) # The assembly for ray tracing: rot1 = N.dot(G.rotx(N.pi/4)[:3,:3], G.roty(N.pi)[:3,:3]) surf1 = rect_one_sided_mirror(width=10, height=10) surf1.set_rotation(rot1) surf2 = rect_one_sided_mirror(width=10, height=10) self.assembly = Assembly(objects=[surf1, surf2]) TracerScene.__init__(self, self.assembly, self.bund) @t_api.on_trait_change('_scene.activated') def initialize_camere(self): self._scene.mlab.view(0, -90) self._scene.mlab.roll(0) @t_api.on_trait_change('source_y, source_z') def bundle_move(self): position = N.tile(N.c_[[0, self.source_y, self.source_z]], (1, 2)) self.bund.set_vertices(position) self.plot_ray_trace() view = tui.View( tui.Item('_scene', editor=SceneEditor(scene_class=MayaviScene), height=400, width=300, show_label=False), tui.HGroup('-', 'source_y', 'source_z'))
class TestTraceProtocol1(unittest.TestCase): """ Tests intersect_ray and the bundle driver with a single flat surface, not rotated, with a single interation """ def setUp(self): dir = N.array([[1,1,-1],[-1,1,-1],[-1,-1,-1],[1,-1,-1]]).T/math.sqrt(3) position = N.c_[[0,0,1],[1,-1,1],[1,1,1],[-1,1,1]] self._bund = RayBundle(position, dir, energy=N.ones(4)) self.assembly = Assembly() object = AssembledObject() object.add_surface(Surface(FlatGeometryManager(), opt.perfect_mirror)) self.assembly.add_object(object) self.engine = TracerEngine(self.assembly) def test_intersect_ray1(self): surfaces = self.assembly.get_surfaces() objects = self.assembly.get_objects() surfs_per_obj = [len(obj.get_surfaces()) for obj in objects] surf_ownership = N.repeat(N.arange(len(objects)), surfs_per_obj) ray_ownership = -1*N.ones(self._bund.get_num_rays()) surfs_relevancy = N.ones((len(surfaces), self._bund.get_num_rays()), dtype=N.bool) params = self.engine.intersect_ray(self._bund, surfaces, objects, \ surf_ownership, ray_ownership, surfs_relevancy)[0] self.failUnless(params.all()) def test_ray_tracer(self): """Ray tracer after one iteration returns what the surface would have""" params = self.engine.ray_tracer(self._bund,1,.05)[0] correct_pts = N.zeros((3,4)) correct_pts[:2,0] = 1 N.testing.assert_array_almost_equal(params, correct_pts)
class TestTraceProtocol2(unittest.TestCase): """ Tests intersect_ray with a flat surface rotated around the x axis 45 degrees """ def setUp(self): ns = -1 / N.sqrt(2) dir = N.c_[[0, 0, 1], [0, 0, -1], [0, ns, ns]] position = N.c_[[0, 0, 1], [0, 1, 2], [0, 0, 1]] self._bund = RayBundle(position, dir, energy=N.ones(3)) def test_intersect_ray2(self): rot = general_axis_rotation([1, 0, 0], N.pi / 4) surface = Surface(FlatGeometryManager(), opt.perfect_mirror, rotation=rot) assembly = Assembly() object = AssembledObject() object.add_surface(surface) assembly.add_object(object) engine = TracerEngine(assembly) surfaces = assembly.get_surfaces() objects = assembly.get_objects() surfs_per_obj = [len(obj.get_surfaces()) for obj in objects] surf_ownership = N.repeat(N.arange(len(objects)), surfs_per_obj) ray_ownership = -1 * N.ones(self._bund.get_num_rays()) surfs_relevancy = N.ones((len(surfaces), self._bund.get_num_rays()), dtype=N.bool) params = engine.intersect_ray(self._bund, surfaces, objects, \ surf_ownership, ray_ownership, surfs_relevancy)[0] correct_params = N.array([[False, True, False]]) N.testing.assert_array_almost_equal(params, correct_params)
def setUp(self): surface1 = Surface(HemisphereGM(2.), opt.perfect_mirror, rotation=general_axis_rotation( N.r_[1, 0, 0], N.pi / 2.)) surface2 = Surface(HemisphereGM(2.), opt.perfect_mirror, location=N.array([0, -2, 0]), rotation=general_axis_rotation( N.r_[1, 0, 0], -N.pi / 2.)) self._bund = RayBundle() self._bund.set_directions(N.c_[[0, 1, 0]]) self._bund.set_vertices(N.c_[[0, -1, 0]]) self._bund.set_energy(N.r_[[1]]) self._bund.set_ref_index(N.r_[[1]]) assembly = Assembly() object1 = AssembledObject() object2 = AssembledObject() object1.add_surface(surface1) object2.add_surface(surface2) assembly.add_object(object1) assembly.add_object(object2) self.engine = TracerEngine(assembly)
def test_up_down(self): """Rays coming from below are absorbed, from above reflected""" going_down = N.c_[[1, 1, -1], [-1, 1, -1], [-1, -1, -1], [1, -1, -1]] / N.sqrt(3) going_up = going_down.copy() going_up[2] = 1 / N.sqrt(3) pos_up = N.c_[[0,0,1], [1,-1,1], [1,1,1], [-1,1,1]] pos_down = pos_up.copy() pos_down[2] = -1 bund = RayBundle() bund.set_directions(N.hstack((going_down, going_up))) bund.set_vertices(N.hstack((pos_up, pos_down))) bund.set_energy(N.tile(100, 8)) bund.set_ref_index(N.tile(1, 8)) gm = FlatGeometryManager() prm = gm.find_intersections(N.eye(4), bund) absref = optics_callables.AbsorberReflector(0.) selector = N.arange(8) gm.select_rays(selector) outg = absref(gm, bund, selector) e = outg.get_energy() N.testing.assert_array_equal(e[:4], 100) N.testing.assert_array_equal(e[4:], 0)
class TestTraceProtocol5(unittest.TestCase): """ Tests a spherical surface """ def setUp(self): surface = Surface(HemisphereGM(1.), opt.perfect_mirror, rotation=general_axis_rotation(N.r_[1, 0, 0], N.pi)) self._bund = RayBundle(energy=N.ones(3)) self._bund.set_directions(N.c_[[0, 1, 0], [0, 1, 0], [0, -1, 0]]) self._bund.set_vertices(N.c_[[0, -2., 0.001], [0, 0, 0.001], [0, 2, 0.001]]) assembly = Assembly() object = AssembledObject() object.add_surface(surface) assembly.add_object(object) self.engine = TracerEngine(assembly) def test_ray_tracer1(self): params = self.engine.ray_tracer(self._bund, 1, .05)[0] correct_params = N.c_[[0, -1, 0], [0, 1, 0], [0, 1, 0]] N.testing.assert_array_almost_equal(params, correct_params, decimal=3)
def regular_square_bundle(num_rays, center, direction, width): """ Generate a ray bundles whose rays are equally spaced along a square grid, and all pointing in the same direction. Arguments: num_rays - number of rays to generate. center - a column 3-array with the 3D coordinate of the disk's center direction - a 1D 3-array with the unit direction vector for the bundle. width - of the square of starting points. Returns: A RayBundle object with the above charachteristics set. """ rot = rotation_to_z(direction) directions = N.tile(direction[:,None], (1, num_rays)) range = N.s_[-width:width:float(2*width)/N.sqrt(num_rays)] xs, ys = N.mgrid[range, range] vertices_local = N.array([xs.flatten(), ys.flatten(), N.zeros(len(xs.flatten()))]) vertices_global = N.dot(rot, vertices_local) rayb = RayBundle() rayb.set_vertices(vertices_global + center) rayb.set_directions(directions) return rayb
def edge_rays_bundle(num_rays, center, direction, radius, ang_range, flux=None, radius_in=0.): radius = float(radius) radius_in = float(radius_in) a = edge_rays_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[..., None] * a[None, ...], axis=1) # Locations: # See [1] xi1 = random.uniform(size=num_rays) thetas = random.uniform(high=2. * N.pi, size=num_rays) rs = N.sqrt(radius_in**2. + xi1 * (radius**2. - radius_in**2.)) xs = rs * N.cos(thetas) ys = rs * N.sin(thetas) # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((xs, ys, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: rayb.set_energy(N.pi * (radius**2. - radius_in**2.) / num_rays * flux * N.ones(num_rays)) return rayb
class TestParabolicDish(unittest.TestCase): def setUp(self): pos = N.zeros((3,4)) pos[0] = N.r_[0, 0.5, 2, -2] pos[2] = 2. dir = N.tile(N.c_[[0,0,-1]], (1,4)) self.bund = RayBundle() self.bund.set_vertices(pos) self.bund.set_directions(dir) self.surf = Surface(ParabolicDishGM(2., 1.), opt.perfect_mirror) def test_selection_at_origin(self): """Simple dish rejects missing rays""" misses = N.isinf(self.surf.register_incoming(self.bund)) N.testing.assert_array_equal(misses, N.r_[False, False, True, True]) def test_transformed(self): """Translated and rotated dish rejects missing rays""" trans = generate_transform(N.r_[1., 0., 0.], N.pi/4., N.c_[[0., 0., 1.]]) self.surf.transform_frame(trans) misses = N.isinf(self.surf.register_incoming(self.bund)) N.testing.assert_array_equal(misses, N.r_[False, False, True, True]) def test_mesh(self): """Parabolic dish mesh looks OK""" p = ParabolicDishGM(5, 3) x, y, z = p.mesh(5) N.testing.assert_array_almost_equal(z, p.a*(x**2 + y**2)) self.failIf(N.any(x**2 + y**2 > 6.25))
class TestTraceProtocol2(unittest.TestCase): """ Tests intersect_ray with a flat surface rotated around the x axis 45 degrees """ def setUp(self): ns = -1/N.sqrt(2) dir = N.c_[[0,0,1],[0,0,-1],[0,ns,ns]] position = N.c_[[0,0,1],[0,1,2],[0,0,1]] self._bund = RayBundle(position, dir, energy=N.ones(3)) def test_intersect_ray2(self): rot = general_axis_rotation([1,0,0],N.pi/4) surface = Surface(FlatGeometryManager(), opt.perfect_mirror, rotation=rot) assembly = Assembly() object = AssembledObject() object.add_surface(surface) assembly.add_object(object) engine = TracerEngine(assembly) surfaces = assembly.get_surfaces() objects = assembly.get_objects() surfs_per_obj = [len(obj.get_surfaces()) for obj in objects] surf_ownership = N.repeat(N.arange(len(objects)), surfs_per_obj) ray_ownership = -1*N.ones(self._bund.get_num_rays()) surfs_relevancy = N.ones((len(surfaces), self._bund.get_num_rays()), dtype=N.bool) params = engine.intersect_ray(self._bund, surfaces, objects, \ surf_ownership, ray_ownership, surfs_relevancy)[0] correct_params = N.array([[False, True, False]]) N.testing.assert_array_almost_equal(params, correct_params)
def edge_rays_bundle(num_rays, center, direction, radius, ang_range, flux=None, radius_in=0.): radius = float(radius) radius_in = float(radius_in) a = edge_rays_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[...,None] * a[None,...], axis=1) # Locations: # See [1] xi1 = random.uniform(size=num_rays) thetas = random.uniform(high=2.*N.pi, size=num_rays) rs = N.sqrt(radius_in**2.+xi1*(radius**2.-radius_in**2.)) xs = rs * N.cos(thetas) ys = rs * N.sin(thetas) # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((xs, ys, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: rayb.set_energy(N.pi*(radius**2.-radius_in**2.)/num_rays*flux*N.ones(num_rays)) return rayb
class TestInterface(unittest.TestCase): def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2*N.pi, self.num_rays, endpoint=False) position = N.vstack((N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle(position, dir) # The boundary is positioned to create a bottom hemisphere. boundary = BoundarySphere(radius=4., location=N.r_[0., 0., -4*N.sqrt(3)/2.]) self.gm = CutSphereGM(2., boundary) self.prm = self.gm.find_intersections(N.eye(4), self._bund) def test_find_intersections(self): """The correct parametric locations are found for cut sphere geometry""" self.failUnlessEqual(self.prm.shape, (self.num_rays,)) N.testing.assert_array_almost_equal(self.prm, 1 + 2*N.sin(N.pi/3)) def test_get_normals(self): """Cut sphere surface returns center-pointing normals""" self.gm.select_rays(N.arange(self.num_rays)) n = self.gm.get_normals() N.testing.assert_array_almost_equal(n[-1,0], n[-1,1:]) N.testing.assert_array_almost_equal(self._bund.get_vertices()[:2], -n[:2]/N.sqrt((n[:2]**2).sum(axis=0))) def test_inters_points_global(self): """Cut sphere returns correct intersections""" self.gm.select_rays(N.arange(self.num_rays)) pts = self.gm.get_intersection_points_global() N.testing.assert_array_equal(pts[:2], self._bund.get_vertices()[:2]) N.testing.assert_array_almost_equal(pts[2], -2*N.sin(N.pi/3))
class TestParabolicDish(unittest.TestCase): def setUp(self): pos = N.zeros((3, 4)) pos[0] = N.r_[0, 0.5, 2, -2] pos[2] = 2. dir = N.tile(N.c_[[0, 0, -1]], (1, 4)) self.bund = RayBundle() self.bund.set_vertices(pos) self.bund.set_directions(dir) self.surf = Surface(ParabolicDishGM(2., 1.), opt.perfect_mirror) def test_selection_at_origin(self): """Simple dish rejects missing rays""" misses = N.isinf(self.surf.register_incoming(self.bund)) N.testing.assert_array_equal(misses, N.r_[False, False, True, True]) def test_transformed(self): """Translated and rotated dish rejects missing rays""" trans = generate_transform(N.r_[1., 0., 0.], N.pi / 4., N.c_[[0., 0., 1.]]) self.surf.transform_frame(trans) misses = N.isinf(self.surf.register_incoming(self.bund)) N.testing.assert_array_equal(misses, N.r_[False, False, True, True]) def test_mesh(self): """Parabolic dish mesh looks OK""" p = ParabolicDishGM(5, 3) x, y, z = p.mesh(5) N.testing.assert_array_almost_equal(z, p.a * (x**2 + y**2)) self.failIf(N.any(x**2 + y**2 > 6.25))
def rect_ray_bundle(num_rays, center, direction, x, y, sunshape, ang_rang, flux=None, BUIE=None): ''' generate a rectancular ray bundle for different sunshape options Arguments: num_rays - number of rays to generate center - a column 3-array with the 3D coordinate of the ray bundle's center direction - a 1D 3-array with the unit average direction vector for the bundle. x - width of the rectangular ray bundle y - height of the rectangular ray bundle sunshape - str, 'pillbox', 'Gaussian','Buie' or 'collimated' ang_rang - the angular width of the solar disk (pillbox), sigma (gaussian) or CSR (Buie sunshape) flux - if not None, the ray bundle's energy is set such that each ray has an equal amount of energy, and the total energy is flux*pi*radius**2 Returns: A RayBundle object with the above characteristics set. ''' if sunshape == 'pillbox': a = pillbox_sunshape_directions(num_rays, ang_rang) elif sunshape == 'gaussian': a = gaussian_sunshape_directions(num_rays, ang_rang) elif sunshape == 'buie': a = buie_sunshape_directions(num_rays, BUIE.sample, BUIE.FI) elif sunshape == 'collimated': a = collimated_directions(num_rays) # making sure the rect bundle can cover the whole region of interest x *= 1.2 y *= 1.2 # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[..., None] * a[None, ...], axis=1) # Locations: # See [1] xs = N.random.uniform(low=-x / 2., high=x / 2., size=num_rays) ys = N.random.uniform(low=-y / 2., high=y / 2., size=num_rays) # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((xs, ys, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: rayb.set_energy(x * y / num_rays * flux * N.ones(num_rays)) return rayb
def runTest(self): pos = N.array([[0, 1.5], [0, -1.5], [1, 0], [-1, 0], [0.1, 0.1], [-0.1, 0.6]]) bund = RayBundle() bund.set_vertices(N.vstack((pos.T, N.ones(pos.shape[0])))) bund.set_directions(N.tile(N.c_[[0,0,-1]], (1,6))) surf = Surface(HexagonalParabolicDishGM(2., 1.), opt.perfect_mirror) misses = N.isinf(surf.register_incoming(bund)) N.testing.assert_array_equal(misses, N.r_[True, True, True, True, False, False])
def triangular_bundle(num_rays, A, AB, AC, direction, ang_range=N.pi / 2., flux=None, procs=1): """ Triangular ray-casting surface anchored on the point A. Arguments: - num_rays: the number of rays - A: The first summit of the triangle and its anchor point. - AB and AC the vertices of the sides of the triangle in its plane of reference. - 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 for tracing """ # Triangle ray vertices: # Declare random numbers: r1 = N.vstack(N.random.uniform(size=num_rays)) r2 = N.vstack(N.random.uniform(size=num_rays)) # Define points in a local referential where A is at [0,0] on a z=0 plane. sqrtr1 = N.sqrt(r1) Plocs = sqrtr1 * (1. - r2) * AB + r2 * sqrtr1 * AC # Triangle point picking vertices_local = N.array([Plocs[:, 0], Plocs[:, 1], N.zeros(num_rays)]) # Bring everything back to the global referential: rot = rotation_to_z(direction) vertices_global = N.dot(rot, vertices_local) + N.vstack(A) # Local referential directions: a = pillbox_sunshape_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: directions = N.sum(rot[..., None] * a[None, ...], axis=1) rayb = RayBundle() rayb.set_vertices(vertices_global) rayb.set_directions(directions) l1 = N.sqrt(N.sum(AB**2)) l2 = N.sqrt(N.sum(AC**2)) l3 = N.sqrt(N.sum((-AB + AC)**2)) s = (l1 + l2 + l3) / 2. area = N.sqrt(s * (s - l1) * (s - l2) * (s - l3)) if flux != None: rayb.set_energy(N.ones(num_rays) * flux * area / float(num_rays)) else: rayb.set_energy(N.ones(num_rays) / float(num_rays) / procs) return rayb
def setUp(self): dir = N.c_[[0., 0, -1], [0, 1, -1], [0, 11, -2], [0, 1, 0]] dir /= N.sqrt(N.sum(dir**2, axis=0)) position = N.c_[[0., 0, 1], [0, -1, 1], [0, -11, 2], [0, 1, 1]] bund = RayBundle() bund.set_vertices(position) bund.set_directions(dir) self.bund = bund self.correct = N.r_[1., N.sqrt(2), N.sqrt(11**2 + 4)]
def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2 * N.pi, self.num_rays, endpoint=False) position = N.vstack( (N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle(position, dir) self.gm = HemisphereGM(radius=2.) self.prm = self.gm.find_intersections(N.eye(4), self._bund)
def setUp(self): pos = N.zeros((3, 4)) pos[0] = N.r_[0, 0.5, 2, -2] pos[2] = 2. dir = N.tile(N.c_[[0, 0, -1]], (1, 4)) self.bund = RayBundle() self.bund.set_vertices(pos) self.bund.set_directions(dir) self.surf = Surface(ParabolicDishGM(2., 1.), opt.perfect_mirror)
def setUp(self): dir = N.array([[1, 1, -1], [-1, 1, -1], [-1, -1, -1], [1, -1, -1] ]).T / math.sqrt(3) position = N.c_[[0, 0, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]] self._bund = RayBundle(position, dir, energy=N.ones(4)) self.assembly = Assembly() object = AssembledObject() object.add_surface(Surface(FlatGeometryManager(), opt.perfect_mirror)) self.assembly.add_object(object) self.engine = TracerEngine(self.assembly)
def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2*N.pi, self.num_rays, endpoint=False) position = N.vstack((N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle() self._bund.set_vertices(position) self._bund.set_directions(dir) self.gm = Paraboloid(a=5., b=5.) self.prm = self.gm.find_intersections(N.eye(4), self._bund)
def pillbox_rect_bundle(num_rays, center, direction, x, y, ang_rang, flux=None): ''' generate a rectancular ray bundle for pillbox sunshape Arguments: num_rays - number of rays to generate center - a column 3-array with the 3D coordinate of the ray bundle's center direction - a 1D 3-array with the unit average direction vector for the bundle. x - width of the rectangular ray bundle y - height of the rectangular ray bundle ang_rang - the angular width of the solar disk flux - if not None, the ray bundle's energy is set such that each ray has an equal amount of energy, and the total energy is flux*pi*radius**2 Returns: A RayBundle object with the above characteristics set. ''' a = pillbox_sunshape_directions(num_rays, ang_rang) x *= 1.2 y *= 1.2 # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[..., None] * a[None, ...], axis=1) # Locations: # See [1] xs = N.random.uniform(low=-x / 2., high=x / 2., size=num_rays) ys = N.random.uniform(low=-y / 2., high=y / 2., size=num_rays) #if (direction == N.array([0,0,-1])).all(): # xs, ys = ys, xs # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((xs, ys, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) #dirct=N.vstack((-N.ones(num_rays)*direction[0],-N.ones(num_rays)*direction[1],-N.ones(num_rays)*direction[2])) #vertices_global=vertices_local+dirct*100. rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: rayb.set_energy(x * y / num_rays * flux * N.ones(num_rays)) return rayb
def pillbox_effective_rays(num_rays, X, Y, Z, hits, direction, A_source, ang_rang, DNI): ''' Generate a ray bundle according to Buie et al.: "Sunshape distributions for terrestrial simulations." Solar Energy 74 (2003) 113-122 (DOI: 10.1016/S0038-092X(03)00125-7). *the ray source just cover each individule mirror Arguments: num_rays - number of rays over one heliostat, therefore total num of rays is num_rays*num_helios direction - (1,3)direction of the normal to the source disc. vertices - (3,n) array vertices of each ray energy - float - energy of each ray , W DNI - Direct normal irradiantion W/m2 Returns: A raybundle object with the above characteristics set. ''' total_rays = num_rays * N.sum(hits) a = pillbox_sunshape_directions(total_rays, ang_rang) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[..., None] * a[None, ...], axis=1) Xs = N.array([]) Ys = N.array([]) Zs = N.array([]) #X,Y=N.meshgrid(X,Y) for i in xrange(len(hits)): for j in xrange(len(hits[i])): if hits[i, j] == 1: xs = N.random.uniform(low=X[i], high=X[i + 1], size=num_rays) ys = N.random.uniform(low=Y[j], high=Y[j + 1], size=num_rays) zs = Z * N.ones(num_rays) Xs = N.append(Xs, xs) Ys = N.append(Ys, ys) Zs = N.append(Zs, zs) vertices = N.vstack((Xs, Ys, Zs)) energy = N.ones(total_rays) * DNI * A_source / float(total_rays) rayb = RayBundle(vertices=vertices, directions=directions) if DNI != None: rayb.set_energy(energy) print total_rays return rayb
def setUp(self): self.mirror = rect_one_sided_mirror(1.5, 1.5, 0.9) pos = N.zeros((3, 8)) pos[0] = N.tile(N.r_[0, 0.5, 2, -2], 2) pos[2] = N.repeat(N.r_[1, -1], 4) dir = N.zeros((3, 8)) dir[2] = N.repeat(N.r_[-1, 1], 4) self.bund = RayBundle() self.bund.set_vertices(pos) self.bund.set_directions(dir) self.bund.set_energy(N.ones(8) * 1000) self.bund.set_ref_index(N.ones(8))
class TestHomogenizer(unittest.TestCase): def setUp(self): """A homogenizer transforms a bundle correctly""" hmg = rect_homogenizer(5., 3., 10., 0.9) self.engine = TracerEngine(hmg) self.bund = RayBundle() # 4 rays starting somewhat above (+z) the homogenizer pos = N.zeros((3, 4)) pos[2] = N.r_[11, 11, 11, 11] self.bund.set_vertices(pos) # One ray going to each wall: dir = N.c_[[1, 0, -1], [-1, 0, -1], [0, 1, -1], [0, -1, -1]] / N.sqrt(2) self.bund.set_directions(dir) # Laborious setup details: self.bund.set_energy(N.ones(4) * 4.) self.bund.set_ref_index(N.ones(4)) def test_first_hits(self): """Test bundle enters homogenizer correctly""" v, d = self.engine.ray_tracer(self.bund, 1, 0.05) out_dirs = N.c_[[-1, 0, -1], [1, 0, -1], [0, -1, -1], [0, 1, -1]] / N.sqrt(2) N.testing.assert_array_almost_equal(d, out_dirs) out_hits = N.c_[[2.5, 0, 8.5], [-2.5, 0, 8.5], [0, 1.5, 9.5], [0, -1.5, 9.5]] N.testing.assert_array_almost_equal(v, out_hits)
def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2 * N.pi, self.num_rays, endpoint=False) position = N.vstack( (N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle(position, dir) # The boundary is positioned to create a bottom hemisphere. boundary = BoundarySphere(radius=4., location=N.r_[0., 0., -4 * N.sqrt(3) / 2.]) self.gm = CutSphereGM(2., boundary) self.prm = self.gm.find_intersections(N.eye(4), self._bund)
def solar_disk_bundle(num_rays, center, direction, radius, ang_range, flux=None, radius_in=0., angular_span=[0.,2.*N.pi], procs=1): """ Generates a ray bundle emanating from a disk, with each surface element of the disk having the same ray density. The rays all point at directions uniformly distributed between a given angle range from a given direction. Setting of the bundle's energy is left to the caller. Arguments: num_rays - number of rays to generate. center - a column 3-array with the 3D coordinate of the disk's center direction - a 1D 3-array with the unit average direction vector for the bundle. radius - of the disk. ang_range - in radians, the maximum deviation from <direction>. flux - if not None, the ray bundle's energy is set such that each ray has an equal amount of energy, and the total energy is flux*pi*radius**2 radius_in - Inner radius if the disc is pierced angular_span - wedge of the disc to consider Returns: A RayBundle object with the above characteristics set. """ # FIXME why should 'center' be a column vector... that's just annoying. radius = float(radius) radius_in = float(radius_in) a = pillbox_sunshape_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[...,None] * a[None,...], axis=1) # Locations: # See [1] xi1 = random.uniform(size=num_rays) thetas = random.uniform(low=angular_span[0], high=angular_span[1], size=num_rays) rs = N.sqrt(radius_in**2.+xi1*(radius**2.-radius_in**2.)) xs = rs * N.cos(thetas) ys = rs * N.sin(thetas) # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((xs, ys, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: rayb.set_energy(N.pi*(radius**2.-radius_in**2.)/num_rays*flux*N.ones(num_rays)) else: rayb.set_energy(N.ones(num_rays)/num_rays/procs) return rayb
class TestHomogenizer(unittest.TestCase): def setUp(self): """A homogenizer transforms a bundle correctly""" hmg = rect_homogenizer(5., 3., 10., 0.9) self.engine = TracerEngine(hmg) self.bund = RayBundle() # 4 rays starting somewhat above (+z) the homogenizer pos = N.zeros((3,4)) pos[2] = N.r_[11, 11, 11, 11] self.bund.set_vertices(pos) # One ray going to each wall: dir = N.c_[[1, 0, -1], [-1, 0, -1], [0, 1, -1], [0, -1, -1]]/N.sqrt(2) self.bund.set_directions(dir) # Laborious setup details: self.bund.set_energy(N.ones(4)*4.) self.bund.set_ref_index(N.ones(4)) def test_first_hits(self): """Test bundle enters homogenizer correctly""" v, d = self.engine.ray_tracer(self.bund, 1, 0.05) out_dirs = N.c_[[-1, 0, -1], [1, 0, -1], [0, -1, -1], [0, 1, -1]]/N.sqrt(2) N.testing.assert_array_almost_equal(d, out_dirs) out_hits = N.c_[ [2.5, 0, 8.5], [-2.5, 0, 8.5], [0, 1.5, 9.5], [0, -1.5, 9.5]] N.testing.assert_array_almost_equal(v, out_hits)
class TestTraceProtocol6(unittest.TestCase): """ Tests a spherical surface """ def setUp(self): surface1 = Surface(HemisphereGM(2.), opt.perfect_mirror, rotation=general_axis_rotation(N.r_[1,0,0], N.pi/2.)) surface2 = Surface(HemisphereGM(2.), opt.perfect_mirror, location=N.array([0,-2,0]), rotation=general_axis_rotation(N.r_[1,0,0], -N.pi/2.)) self._bund = RayBundle() self._bund.set_directions(N.c_[[0,1,0]]) self._bund.set_vertices(N.c_[[0,-1,0]]) self._bund.set_energy(N.r_[[1]]) self._bund.set_ref_index(N.r_[[1]]) assembly = Assembly() object1 = AssembledObject() object2 = AssembledObject() object1.add_surface(surface1) object2.add_surface(surface2) assembly.add_object(object1) assembly.add_object(object2) self.engine = TracerEngine(assembly) def test_ray_tracers1(self): params = self.engine.ray_tracer(self._bund, 1, .05)[0] correct_params = N.c_[[0,2,0]] N.testing.assert_array_almost_equal(params,correct_params)
def test_paraxial_ray(self): """A paraxial ray in reflected correctly""" bund = RayBundle() bund.set_vertices(N.c_[[0.01, 0., 2.]]) bund.set_directions(N.c_[[0., 0., -1.]]) bund.set_energy(N.r_[100.]) bund.set_ref_index(N.r_[1]) self.engine.ray_tracer(bund, 15, 10.) non_degenerate = self.engine.tree[-1].get_energy() > 10 v = self.engine.tree[-1].get_vertices()[:, non_degenerate] d = self.engine.tree[-1].get_directions()[:, non_degenerate] # Not high equality demanded, because of spherical aberration. N.testing.assert_array_almost_equal(v, N.c_[[-0.01, 0., 1.5]], 2) N.testing.assert_array_almost_equal(d, N.c_[[0., 0., 1.]], 2)
def setUp(self): surface = Surface(HemisphereGM(1.), opt.perfect_mirror, rotation=general_axis_rotation(N.r_[1, 0, 0], N.pi)) self._bund = RayBundle(energy=N.ones(3)) self._bund.set_directions(N.c_[[0, 1, 0], [0, 1, 0], [0, -1, 0]]) self._bund.set_vertices(N.c_[[0, -2., 0.001], [0, 0, 0.001], [0, 2, 0.001]]) assembly = Assembly() object = AssembledObject() object.add_surface(surface) assembly.add_object(object) self.engine = TracerEngine(assembly)
class TestObjectBuilding1(unittest.TestCase): """Tests an object composed of sphere surfaces""" def setUp(self): self.assembly = Assembly() surface1 = Surface(HemisphereGM(3.), optics_callables.perfect_mirror, location=N.array([0,0,-1.]), rotation=general_axis_rotation(N.r_[1,0,0], N.pi)) surface2 = Surface(HemisphereGM(3.), optics_callables.perfect_mirror, location=N.array([0,0,1.])) self.object = AssembledObject() self.object.add_surface(surface1) self.object.add_surface(surface2) self.assembly.add_object(self.object) dir = N.c_[[0,0,1.],[0,0,1.]] position = N.c_[[0,0,-3.],[0,0,-1.]] self._bund = RayBundle(position, dir, energy=N.ones(2)) def test_object(self): """Tests that the assembly heirarchy works at a basic level""" self.engine = TracerEngine(self.assembly) inters = self.engine.ray_tracer(self._bund,1,.05)[0] correct_inters = N.c_[[0,0,2],[0,0,-2]] N.testing.assert_array_almost_equal(inters, correct_inters) def test_translation(self): """Tests an assembly that has been translated""" trans = N.array([[1,0,0,0],[0,1,0,0],[0,0,1,1],[0,0,0,1]]) self.assembly.transform_children(trans) self.engine = TracerEngine(self.assembly) params = self.engine.ray_tracer(self._bund,1,.05)[0] correct_params = N.c_[[0,0,3],[0,0,-1]] N.testing.assert_array_almost_equal(params, correct_params) def test_rotation_and_translation(self): """Tests an assembly that has been translated and rotated""" self._bund = RayBundle() self._bund.set_vertices(N.c_[[0,-5,1],[0,5,1]]) self._bund.set_directions(N.c_[[0,1,0],[0,1,0]]) self._bund.set_energy(N.r_[[1,1]]) self._bund.set_ref_index(N.r_[[1,1]]) trans = generate_transform(N.r_[[1,0,0]], N.pi/2, N.c_[[0,0,1]]) self.assembly.transform_children(trans) self.engine = TracerEngine(self.assembly) params = self.engine.ray_tracer(self._bund,1,.05)[0] correct_params = N.c_[[0,-2,1]] N.testing.assert_array_almost_equal(params, correct_params)
def test_all_refracted(self): dir = N.c_[[1, 1, -1], [-1, 1, -1], [-1, -1, -1], [1, -1, -1]] / N.sqrt(3) position = N.c_[[0,0,1], [1,-1,1], [1,1,1], [-1,1,1]] en = N.r_[100, 200, 300, 400] bund = RayBundle(position, dir, energy=en, ref_index=N.ones(4)) gm = FlatGeometryManager() prm = gm.find_intersections(N.eye(4), bund) refractive = optics_callables.RefractiveHomogenous(1,1.5) selector = N.array([0, 1, 3]) gm.select_rays(selector) outg = refractive(gm, bund, selector) correct_pts = N.zeros((3,4)) correct_pts[:2,0] = 1 correct_pts = N.hstack((correct_pts[:,selector], correct_pts[:,selector])) N.testing.assert_array_equal(outg.get_vertices(), correct_pts) norm = N.c_[gm.get_normals()[:,0]] correct_refl_cos = -(dir*norm).sum(axis=0)[selector] correct_refr_cos = -N.sqrt(1 - (1./1.5)**2*(1 - correct_refl_cos**2)) outg_cos = (outg.get_directions()*norm).sum(axis=0) N.testing.assert_array_equal(outg_cos, N.r_[correct_refl_cos, correct_refr_cos]) N.testing.assert_array_equal(outg.get_energy().reshape(2,-1).sum(axis=0), \ N.r_[100, 200, 400]) # reflection and refraction sum to 100% N.testing.assert_array_equal(outg.get_parents(), N.tile(selector, 2))
def setUp(self): self.assembly = Assembly() surface1 = Surface(FlatGeometryManager(), opt.RefractiveHomogenous(1., 1.5), location=N.array([0, 0, -1.])) surface2 = Surface(FlatGeometryManager(), opt.RefractiveHomogenous(1., 1.5), location=N.array([0, 0, 1.])) object1 = AssembledObject(surfs=[surface1, surface2]) boundary = BoundarySphere(location=N.r_[0, 0., 3], radius=3.) surface3 = Surface(CutSphereGM(2., boundary), opt.perfect_mirror) object2 = AssembledObject(surfs=[surface3], transform=translate(0., 0., 2.)) self.assembly = Assembly(objects=[object1, object2]) x = 1. / (math.sqrt(2)) dir = N.c_[[0, 1., 0.], [0, x, x], [0, 0, 1.]] position = N.c_[[0, 0, 2.], [0, 0, 2.], [0, 0., 2.]] self._bund = RayBundle(position, dir, ref_index=N.ones(3), energy=N.ones(3)) self.engine = TracerEngine(self.assembly)
def setUp(self): self._surf = Surface(FlatGeometryManager(), perfect_mirror) dir = N.array([[1, 1, -1], [-1, 1, -1], [-1, -1, -1], [1, -1, -1] ]).T / math.sqrt(3) position = c_[[0, 0, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]] self._bund = RayBundle(position, dir, energy=N.ones(4) * 100)
def test_tetrahedron(self): """Triangular mesh with oblique triangles""" # Face set: theta = np.arange(np.pi / 2., np.pi * 2, 2 * np.pi / 3) base_verts = np.vstack((np.cos(theta), np.sin(theta), np.ones(3))).T verts = np.vstack((np.zeros(3), base_verts)) faces = np.array([[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]) fset = TriangulatedSurface(verts, faces, perfect_mirror) # Flat floor: floor = rect_one_sided_mirror(5., 5., 1.) floor.set_location(np.r_[0., 0., 1.]) assembly = Assembly(objects=[fset, floor]) # Ray bundle of 3 rays starting at equal angles around the tetrahedron: theta -= np.pi / 3. pos = np.vstack((np.cos(theta), np.sin(theta), np.ones(3) * 0.2)) * 0.2 direct = np.vstack((np.zeros((2, 3)), np.ones(3))) rayb = RayBundle(pos, direct, energy=np.ones(6)) # Check that the points on the floor describe an isosceles. engine = TracerEngine(assembly) engine.ray_tracer(rayb, 2, .05)[0] verts = engine.tree[-1].get_vertices() sizes = np.sqrt(np.sum((verts - np.roll(verts, 1, axis=1))**2, axis=0)) self.assertAlmostEqual(sizes[0], sizes[1]) self.assertAlmostEqual(sizes[2], sizes[1])
def test_pyramid(self): """A simple right-pyramid triangular mesh""" # Face set: verts = np.vstack( (np.zeros(3), np.eye(3))) # origin + unit along each axis faces = np.array([[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]) assembly = Assembly( objects=[TriangulatedSurface(verts, faces, perfect_mirror)]) # Ray bundle: pos = np.c_[[1.5, 0.5, 0.5], [-0.5, 0.5, 0.5], [0.5, 1.5, 0.5], [0.5, -0.5, 0.5], [0.5, 0.5, -0.5], [0.5, 0.5, 1.5]] direct = np.c_[[-1., 0., 0.], [1., 0., 0.], [0., -1., 0.], [0., 1., 0.], [0., 0., 1.], [0., 0., -1.]] rayb = RayBundle(pos, direct, energy=np.ones(6)) engine = TracerEngine(assembly) verts = engine.ray_tracer(rayb, 1, .05)[0] p = engine.tree[-1].get_parents() zrays = (p >= 4) np.testing.assert_array_equal(verts[:, zrays], np.tile(np.c_[[0.5, 0.5, 0.]], (1, 4))) yrays = (p == 2) | (p == 3 ) # Only 2 rays here. Edge degeneracy? maybe. np.testing.assert_array_equal(verts[:, yrays], np.tile(np.c_[[0.5, 0., 0.5]], (1, 4))) xrays = (p < 2) np.testing.assert_array_equal(verts[:, xrays], np.tile(np.c_[[0., 0.5, 0.5]], (1, 4)))
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()
def setUp(self): self.assembly = Assembly() surface1 = Surface(flat_surface.FlatGeometryManager(), optics_callables.RefractiveHomogenous(1., 1.5), location=N.array([0, 0, -1.])) surface2 = Surface(flat_surface.FlatGeometryManager(), optics_callables.RefractiveHomogenous(1., 1.5), location=N.array([0, 0, 1.])) self.object1 = AssembledObject() self.object1.add_surface(surface1) self.object1.add_surface(surface2) boundary = BoundarySphere(location=N.r_[0, 0., 3], radius=3.) surface3 = Surface(CutSphereGM(2., boundary), optics_callables.perfect_mirror) self.object2 = AssembledObject() self.object2.add_surface(surface3) self.transform = generate_transform(N.r_[1, 0., 0], 0., N.c_[[0., 0, 2]]) self.assembly.add_object(self.object1) self.assembly.add_object(self.object2, self.transform) x = 1. / (math.sqrt(2)) dir = N.c_[[0, 1., 0.], [0, x, x], [0, 0, 1.]] position = N.c_[[0, 0, 2.], [0, 0, 2.], [0, 0., 2.]] self._bund = RayBundle(position, dir, energy=N.ones(3), ref_index=N.ones(3))
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 rect_buie_sunshape(num_rays, center, direction, width, height, CSR, flux=None, pre_process_CSR=True, rays_direction=None): ''' Generate a ray bundle according to Buie et al.: "Sunshape distributions for terrestrial simulations." Solar Energy 74 (2003) 113-122 (DOI: 10.1016/S0038-092X(03)00125-7). Arguments: num_rays - number of rays in the bundle center - position of the source center direction - direction of the normal to the source disc. radius - radius of the source disc CSR - Circumsolar ratio, fraction of the incoming solar energy which incident angle is greater than the angle subtended by the solar disc. flux - horizontal radiation density in W/m2 pre_process_CSR=True - Use or not the polynomial pre-processing to get better I/O match using the Buie sunshape rays_direction=None - If the general direction of propagation of the source is different from the source normal. Returns: A raybundle object with the above characteristics set. ''' # Rays vertices (start positions): xs = width * (random.uniform(size=num_rays) - 0.5) ys = height * (random.uniform(size=num_rays) - 0.5) # Source surface area: S = width * height # Rays escaping direction setup: if rays_direction == None: rays_direction = direction # Uniform ray energy: cosangle = 2. * N.sin(N.sqrt(N.sum((rays_direction - direction)**2)) / 2.) energy = N.ones(num_rays) * flux * S / num_rays * N.cos(cosangle) # Buie sunshape directions: a = buie_distribution(num_rays, CSR, pre_process_CSR) # Rotate to a frame in which <rays_direction> is Z: perp_rot = rotation_to_z(rays_direction) directions = N.sum(perp_rot[..., None] * a[None, ...], axis=1) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((xs, ys, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions, energy=energy) return rayb
class TestTraceProtocol3(unittest.TestCase): """ Tests intersect_ray and the bundle driver with two rotated planes, with a single iteration """ def setUp(self): self.x = 1 / (math.sqrt(2)) dir = N.c_[[0, self.x, -self.x], [0, 1, 0]] position = N.c_[[0, 0, 1], [0, 0, 1]] self._bund = RayBundle(position, dir, energy=N.ones(2)) rot1 = general_axis_rotation([1, 0, 0], N.pi / 4) rot2 = general_axis_rotation([1, 0, 0], N.pi / (-4)) surf1 = Surface(FlatGeometryManager(), opt.perfect_mirror, rotation=rot1) surf2 = Surface(FlatGeometryManager(), opt.perfect_mirror, rotation=rot2) self.assembly = Assembly() object = AssembledObject() object.add_surface(surf1) object.add_surface(surf2) self.assembly.add_object(object) self.engine = TracerEngine(self.assembly) def test_intersect_ray(self): surfaces = self.assembly.get_surfaces() objects = self.assembly.get_objects() surfs_per_obj = [len(obj.get_surfaces()) for obj in objects] surf_ownership = N.repeat(N.arange(len(objects)), surfs_per_obj) ray_ownership = -1 * N.ones(self._bund.get_num_rays()) surfs_relevancy = N.ones((len(surfaces), self._bund.get_num_rays()), dtype=N.bool) params = self.engine.intersect_ray(self._bund, surfaces, objects, \ surf_ownership, ray_ownership, surfs_relevancy)[0] correct_params = N.array([[True, True], [False, False]]) N.testing.assert_array_almost_equal(params, correct_params) def test_ray_tracer1(self): params = self.engine.ray_tracer(self._bund, 1, .05)[0] correct_params = N.c_[[0, .5, .5], [0, 1, 1]] N.testing.assert_array_almost_equal(params, correct_params)
def setUp(self): # Two rays inside, two outside; two horizontal, two slanted. pos = N.c_[[0., 0., 0.], [0., 0., 0.], [0., 1., 0.], [0., 1., 0.]] dir = N.c_[[0., 1., 0.], [0., 1., 1.], [0., -1., 0.], [0., -1., 1.]] dir /= N.sqrt(N.sum(dir**2, axis=0)) self.bund = RayBundle(pos, dir) self.gm = InfiniteCylinder(diameter=1.)
def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2*N.pi, self.num_rays, endpoint=False) position = N.vstack((N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle(position, dir) self.gm = HemisphereGM(radius=2.) self.prm = self.gm.find_intersections(N.eye(4), self._bund)
def test_paraxial_ray(self): """A paraxial ray in reflected correctly""" bund = RayBundle() bund.set_vertices(N.c_[[0.01, 0., 2.]]) bund.set_directions(N.c_[[0., 0., -1.]]) bund.set_energy(N.r_[100.]) bund.set_ref_index(N.r_[1]) self.engine.ray_tracer(bund, 15, 10.) non_degenerate = self.engine.tree[-1].get_energy() > 10 v = self.engine.tree[-1].get_vertices()[:,non_degenerate] d = self.engine.tree[-1].get_directions()[:,non_degenerate] # Not high equality demanded, because of spherical aberration. N.testing.assert_array_almost_equal(v, N.c_[[-0.01, 0., 1.5]], 2) N.testing.assert_array_almost_equal(d, N.c_[[0., 0., 1.]], 2)
def triangular_bundle(num_rays, A, AB, AC, direction, ang_range=N.pi/2., flux=None, procs=1): """ Triangular ray-casting surface anchored on the point A. Arguments: - num_rays: the number of rays - A: The first summit of the triangle and its anchor point. - AB and AC the vertices of the sides of the triangle in its plane of reference. - 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 for tracing """ # Triangle ray vertices: # Declare random numbers: r1 = N.vstack(N.random.uniform(size=num_rays)) r2 = N.vstack(N.random.uniform(size=num_rays)) # Define points in a local referential where A is at [0,0] on a z=0 plane. sqrtr1 = N.sqrt(r1) Plocs = sqrtr1*(1.-r2)*AB+r2*sqrtr1*AC # Triangle point picking vertices_local = N.array([Plocs[:,0], Plocs[:,1], N.zeros(num_rays)]) # Bring everything back to the global referential: rot = rotation_to_z(direction) vertices_global = N.dot(rot, vertices_local)+N.vstack(A) # Local referential directions: a = pillbox_sunshape_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: directions = N.sum(rot[...,None] * a[None,...], axis=1) rayb = RayBundle() rayb.set_vertices(vertices_global) rayb.set_directions(directions) l1 = N.sqrt(N.sum(AB**2)) l2 = N.sqrt(N.sum(AC**2)) l3 = N.sqrt(N.sum((-AB+AC)**2)) s = (l1+l2+l3)/2. area = N.sqrt(s*(s-l1)*(s-l2)*(s-l3)) if flux != None: rayb.set_energy(N.ones(num_rays)*flux*area/float(num_rays)) else: rayb.set_energy(N.ones(num_rays)/float(num_rays)/procs) return rayb
def single_ray_source(position, direction, flux=None): ''' Establishes a single ray source originating from a definned point on a defined exact direction for the purpose of testing single ray behviours. Arguments: position - column 3-array with the ray's starting position. direction - a 1D 3-array with the unit average direction vector for the bundle. flux - if not None, the energy transported by the ray. Returns: A Raybundle object with the corresponding characteristics. ''' directions = N.tile(direction[:,None],1) directions /= N.sqrt(N.sum(directions**2, axis=0)) singray = RayBundle(vertices = position, directions = directions) singray.set_energy(flux*N.ones(1)) return singray
def setUp(self): dir = N.array([[1,1,-1],[-1,1,-1],[-1,-1,-1],[1,-1,-1]]).T/math.sqrt(3) position = N.c_[[0,0,1],[1,-1,1],[1,1,1],[-1,1,1]] self._bund = RayBundle(position, dir, energy=N.ones(4)) self.assembly = Assembly() object = AssembledObject() object.add_surface(Surface(FlatGeometryManager(), opt.perfect_mirror)) self.assembly.add_object(object) self.engine = TracerEngine(self.assembly)
class TestTraceProtocol3(unittest.TestCase): """ Tests intersect_ray and the bundle driver with two rotated planes, with a single iteration """ def setUp(self): self.x = 1/(math.sqrt(2)) dir = N.c_[[0,self.x,-self.x],[0,1,0]] position = N.c_[[0,0,1],[0,0,1]] self._bund = RayBundle(position, dir, energy=N.ones(2)) rot1 = general_axis_rotation([1,0,0],N.pi/4) rot2 = general_axis_rotation([1,0,0],N.pi/(-4)) surf1 = Surface(FlatGeometryManager(), opt.perfect_mirror, rotation=rot1) surf2 = Surface(FlatGeometryManager(), opt.perfect_mirror, rotation=rot2) self.assembly = Assembly() object = AssembledObject() object.add_surface(surf1) object.add_surface(surf2) self.assembly.add_object(object) self.engine = TracerEngine(self.assembly) def test_intersect_ray(self): surfaces = self.assembly.get_surfaces() objects = self.assembly.get_objects() surfs_per_obj = [len(obj.get_surfaces()) for obj in objects] surf_ownership = N.repeat(N.arange(len(objects)), surfs_per_obj) ray_ownership = -1*N.ones(self._bund.get_num_rays()) surfs_relevancy = N.ones((len(surfaces), self._bund.get_num_rays()), dtype=N.bool) params = self.engine.intersect_ray(self._bund, surfaces, objects, \ surf_ownership, ray_ownership, surfs_relevancy)[0] correct_params = N.array([[True, True],[False, False]]) N.testing.assert_array_almost_equal(params,correct_params) def test_ray_tracer1(self): params = self.engine.ray_tracer(self._bund, 1,.05)[0] correct_params = N.c_[[0,.5,.5],[0,1,1]] N.testing.assert_array_almost_equal(params,correct_params)
def setUp(self): pos = N.zeros((3,4)) pos[0] = N.r_[0, 0.5, 2, -2] pos[2] = 2. dir = N.tile(N.c_[[0,0,-1]], (1,4)) self.bund = RayBundle() self.bund.set_vertices(pos) self.bund.set_directions(dir) self.surf = Surface(ParabolicDishGM(2., 1.), opt.perfect_mirror)
def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2*N.pi, self.num_rays, endpoint=False) position = N.vstack((N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle(position, dir) # The boundary is positioned to create a bottom hemisphere. boundary = BoundarySphere(radius=4., location=N.r_[0., 0., -4*N.sqrt(3)/2.]) self.gm = CutSphereGM(2., boundary) self.prm = self.gm.find_intersections(N.eye(4), self._bund)
class TestInterface(unittest.TestCase): def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2*N.pi, self.num_rays, endpoint=False) position = N.vstack((N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle() self._bund.set_vertices(position) self._bund.set_directions(dir) self.gm = Paraboloid(a=5., b=5.) self.prm = self.gm.find_intersections(N.eye(4), self._bund) def test_find_intersections(self): """The correct parametric locations are found for paraboloid geometry""" self.failUnlessEqual(self.prm.shape, (self.num_rays,)) N.testing.assert_array_almost_equal(self.prm, 0.96) def test_get_normals(self): """Paraboloid surface returns center-pointing normals""" self.gm.select_rays(N.arange(self.num_rays)) n = self.gm.get_normals() # all rays selected N.testing.assert_array_equal(n[-1,0], n[-1,1:]) N.testing.assert_array_almost_equal(self._bund.get_vertices()[:2], -n[:2]/N.sqrt((n[:2]**2).sum(axis=0))) def test_inters_points_global(self): """Paraboloid returns correct intersections""" self.gm.select_rays(N.arange(self.num_rays)) pts = self.gm.get_intersection_points_global() N.testing.assert_array_equal(pts[:2], self._bund.get_vertices()[:2]) N.testing.assert_array_almost_equal(pts[2], 0.04)
def setUp(self): surface = Surface(HemisphereGM(1.), opt.perfect_mirror, rotation=general_axis_rotation(N.r_[1,0,0], N.pi)) self._bund = RayBundle(energy=N.ones(3)) self._bund.set_directions(N.c_[[0,1,0],[0,1,0],[0,-1,0]]) self._bund.set_vertices(N.c_[[0,-2.,0.001],[0,0,0.001],[0,2,0.001]]) assembly = Assembly() object = AssembledObject() object.add_surface(surface) assembly.add_object(object) self.engine = TracerEngine(assembly)
def solar_rect_bundle(num_rays, center, direction, x, y, ang_range, flux=None): a = pillbox_sunshape_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(direction) directions = N.sum(perp_rot[...,None] * a[None,...], axis=1) xs = random.uniform(low=-x/2., high=x/2., size=num_rays) ys = random.uniform(low=-y/2., high=y/2., size=num_rays) if (direction == N.array([0,0,-1])).all(): xs, ys = ys, xs # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((ys, xs, N.zeros(num_rays))) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: rayb.set_energy(x*y/num_rays*flux*N.ones(num_rays)) return rayb
def setUp(self): self.mirror = rect_one_sided_mirror(1.5, 1.5, 0.9) pos = N.zeros((3,8)) pos[0] = N.tile(N.r_[0, 0.5, 2, -2], 2) pos[2] = N.repeat(N.r_[1, -1], 4) dir = N.zeros((3,8)) dir[2] = N.repeat(N.r_[-1, 1], 4) self.bund = RayBundle() self.bund.set_vertices(pos) self.bund.set_directions(dir) self.bund.set_energy(N.ones(8)*1000) self.bund.set_ref_index(N.ones(8))
class TestTraceProtocol5(unittest.TestCase): """ Tests a spherical surface """ def setUp(self): surface = Surface(HemisphereGM(1.), opt.perfect_mirror, rotation=general_axis_rotation(N.r_[1,0,0], N.pi)) self._bund = RayBundle(energy=N.ones(3)) self._bund.set_directions(N.c_[[0,1,0],[0,1,0],[0,-1,0]]) self._bund.set_vertices(N.c_[[0,-2.,0.001],[0,0,0.001],[0,2,0.001]]) assembly = Assembly() object = AssembledObject() object.add_surface(surface) assembly.add_object(object) self.engine = TracerEngine(assembly) def test_ray_tracer1(self): params = self.engine.ray_tracer(self._bund, 1, .05)[0] correct_params = N.c_[[0,-1,0],[0,1,0],[0,1,0]] N.testing.assert_array_almost_equal(params,correct_params, decimal=3)
def oblique_solar_rect_bundle(num_rays, center, source_direction, rays_direction, x, y, ang_range, flux=None, procs=1): a = pillbox_sunshape_directions(num_rays, ang_range) # Rotate to a frame in which <direction> is Z: perp_rot = rotation_to_z(rays_direction) directions = N.sum(perp_rot[...,None] * a[None,...], axis=1) xs = random.uniform(low=-x/2., high=x/2., size=num_rays) ys = random.uniform(low=-y/2., high=y/2., size=num_rays) if (source_direction == N.array([0,0,-1])).all(): xs, ys = ys, xs # Rotate locations to the plane defined by <direction>: vertices_local = N.vstack((ys, xs, N.zeros(num_rays))) perp_rot = rotation_to_z(source_direction) vertices_global = N.dot(perp_rot, vertices_local) rayb = RayBundle(vertices=vertices_global + center, directions=directions) if flux != None: cosangle = 2.*N.sin(N.sqrt(N.sum((rays_direction-source_direction)**2))/2.) rayb.set_energy(x*y/num_rays*flux*N.ones(num_rays)*N.cos(cosangle)) else: rayb.set_energy(N.ones(num_rays)/float(num_rays)/procs) return rayb
class TestInterface(unittest.TestCase): def setUp(self): self.num_rays = 10 dir = N.tile(N.c_[[0, 0, -1]], (1, self.num_rays)) theta = N.linspace(0, 2*N.pi, self.num_rays, endpoint=False) position = N.vstack((N.cos(theta), N.sin(theta), N.ones(self.num_rays))) self._bund = RayBundle(position, dir) self.gm = HemisphereGM(radius=2.) self.prm = self.gm.find_intersections(N.eye(4), self._bund) def test_find_intersections(self): """The correct parametric locations are found for hemisphere geometry""" self.failUnlessEqual(self.prm.shape, (self.num_rays,)) N.testing.assert_array_almost_equal(self.prm, 1 + 2*N.sin(N.pi/3)) def test_get_normals(self): """Hemisphere surface returns center-pointing normals""" self.gm.select_rays(N.arange(self.num_rays)) n = self.gm.get_normals() N.testing.assert_array_almost_equal(n[-1,0], n[-1,1:]) N.testing.assert_array_almost_equal(self._bund.get_vertices()[:2], -n[:2]/N.sqrt((n[:2]**2).sum(axis=0))) def test_inters_points_global(self): """Hemisphere returns correct intersections""" self.gm.select_rays(N.arange(self.num_rays)) pts = self.gm.get_intersection_points_global() N.testing.assert_array_equal(pts[:2], self._bund.get_vertices()[:2]) N.testing.assert_array_almost_equal(pts[2], -2*N.sin(N.pi/3)) def test_mesh(self): """The HemisphereGM mesh represents the lower hemisphere only""" x, y, z = self.gm.mesh(10) self.failUnless(N.all(z <= 1e-15)) self.failIf(N.any(x**2 + y**2 > 4.0001))