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 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
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 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 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 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 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 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
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 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 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
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 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)
def setUp(self): dir = N.c_[[1, 1, 1], [-1, 1, 1], [-1, -1, 1], [1, -1, 1]] / math.sqrt(3) position = N.c_[[0, 0, -1], [1, -1, -1], [1, 1, -1], [-1, 1, -1]] self._bund = RayBundle(position, dir) self.gm = FlatGeometryManager() self.prm = self.gm.find_intersections(N.eye(4), self._bund)
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 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 setUp(self): """Set up the ray bundle and geometry""" 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] self._bund = RayBundle(position, dir, energy=en) self.gm = FlatGeometryManager() self.prm = self.gm.find_intersections(N.eye(4), self._bund)
def setUp(self): dir = N.c_[[1, 1, -1], [-1, 1, -1], [-1, -1, -1], [1, -1, -1]] / math.sqrt(3) position = N.c_[[0, 0, 1], [1, -1, 1], [1, 1, 1], [-1, 1, 1]] self._bund = RayBundle(position, dir) self.gm = FlatGeometryManager() frame = SP.translate(1., 0., 0.) self.prm = self.gm.find_intersections(frame, self._bund)
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 test_cylinder_height(self): """The bounding cylinder exists for planoconvex lens""" f = self.lens.focal_length() rb = RayBundle(N.c_[[0., 0., -0.01]], N.c_[[1., 0., 0.]], energy=N.r_[1.], ref_index=N.r_[1.5]) e = TracerEngine(Assembly([self.lens])) verts, dirs = e.ray_tracer(rb, 1, 1e-6) N.testing.assert_array_equal(verts, N.array([]).reshape(3,0))
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): 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 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 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 test_selection(self): pos = N.zeros((3,4)) pos[0] = N.r_[0, 0.05, 0.2, -0.3] pos[2] = 1. dir = N.tile(N.c_[[0,0,-1]], (1,4)) bund = RayBundle(pos, dir) surf = Surface(ExtrudedRectPlateGM(width=1, height=1, extr_center=N.vstack([0.2,0.1]), extr_width=0.2, extr_height=0.4), opt.perfect_mirror) misses = N.isinf(surf.register_incoming(bund)) N.testing.assert_array_equal(misses, N.r_[False, False, True, False])
def test_selection(self): pos = N.zeros((3,4)) pos[0] = N.r_[0, 0.5, 2, -2] pos[2] = 1. dir = N.tile(N.c_[[0,0,-1]], (1,4)) bund = RayBundle(pos, dir) surf = Surface(RoundPlateGM(1), opt.perfect_mirror) misses = N.isinf(surf.register_incoming(bund)) N.testing.assert_array_equal(misses, N.r_[False, False, True, True])
def test_cylinder(self): """The bounding cylinder exists for biconcave lens""" f = self.lens.focal_length() rb = RayBundle(N.c_[[0., 0., 0.08]], N.c_[[1., 0., 0.]], energy=N.r_[1.], ref_index=N.r_[1.5]) e = TracerEngine(Assembly([self.lens])) verts, dirs = e.ray_tracer(rb, 1, 1e-6) N.testing.assert_array_equal(verts, N.tile(N.c_[[0.5, 0., 0.08]], (1,2))) N.testing.assert_array_equal(dirs, N.c_[[-1., 0., 0.], [1., 0., 0.]])
def setUp(self): pos = N.c_[[-1.,0,0], [2,0,0], [1,0,2], [4,0,0],[2,0,1]] dir = N.c_[[0.,0,1], [-1,0,1], [-1,2,0], [0,0,1],[-1,0,0]] self.prm = N.r_[1,N.sqrt(2),N.sqrt(5),N.inf,1] self.pts = N.c_[[-1.,0,1],[1,0,1],[0,2,2],[1,0,1]] self.nrm = N.c_[[-1.,0,-1],[1,0,-1],[0,-1,1],[1,0,-1]] dir /= N.sqrt(N.sum(dir**2, axis=0)) # normalise dir self.nrm /= N.sqrt(N.sum(self.nrm**2, axis=0)) # normalise nrm self.bund = RayBundle(vertices=pos, directions=dir) self.gm = FiniteCone(r = 3., h = 3.)