def test_integration_2d(self): """ Testing against ToroidalVoxelGrid""" world = World() rtc = RayTransferCylinder(radius_outer=4., height=2., n_radius=2, n_height=2, radius_inner=2., parent=world) rtc.step = 0.001 * rtc.step ray = Ray(origin=Point3D(4., 1., 2.), direction=Vector3D(-4., -1., -2.) / np.sqrt(21.), min_wavelength=500., max_wavelength=501., bins=rtc.bins) spectrum = ray.trace(world) world = World() vertices = [] for rv in [2., 3.]: for zv in [0., 1.]: vertices.append([ Point2D(rv, zv + 1.), Point2D(rv + 1., zv + 1.), Point2D(rv + 1., zv), Point2D(rv, zv) ]) tvg = ToroidalVoxelGrid(vertices, parent=world, primitive_type='csg', active='all') tvg.set_active('all') spectrum_test = ray.trace(world) self.assertTrue( np.allclose(spectrum_test.samples, spectrum.samples, atol=0.001))
def load_cad(self, load_full=False): from raysect.primitive.mesh import Mesh from raysect.optical.material.absorber import AbsorbingSurface from raysect.optical import World import os world = World() if load_full: MESH_PARTS = MASTU_FULL_MESH + VACUUM_VESSEL + \ UPPER_DIVERTOR_NOSE + UPPER_DIVERTOR_ARMOUR + UPPER_DIVERTOR + \ LOWER_DIVERTOR_NOSE + LOWER_DIVERTOR_ARMOUR + LOWER_DIVERTOR + \ LOWER_ELM_COILS + LOWER_GAS_BAFFLE + \ UPPER_ELM_COILS + UPPER_GAS_BAFFLE + \ ELM_COILS + PF_COILS + \ T5_LOWER + T4_LOWER + T3_LOWER + T2_LOWER + T1_LOWER + \ T5_UPPER + T4_UPPER + T3_UPPER + T2_UPPER + T1_UPPER + \ C6_TILES + C5_TILES + C4_TILES + C3_TILES + C2_TILES + C1_TILE + \ B1_UPPER + B2_UPPER + B3_UPPER + B4_UPPER + \ B1_LOWER + B2_LOWER + B3_LOWER + B4_LOWER + \ BEAM_DUMPS + SXD_BOLOMETERS else: MESH_PARTS = CENTRE_COLUMN + LOWER_DIVERTOR_ARMOUR #MESH_PARTS=VACUUM_VESSEL for cad_file in MESH_PARTS: directory, filename = os.path.split(cad_file[0]) name, ext = filename.split('.') print("importing {} ...".format(filename)) Mesh.from_file(cad_file[0], parent=world, material=AbsorbingSurface(), name=name) return world
def get_proj_matrix(self, pixel_side=60, out_file="proj_matrix1"): geo_matrix = np.empty((32, 0)) for pixel in range(pixel_side * pixel_side): print('Progress: ' + str(round(100 * pixel / (pixel_side * pixel_side), 1)) + " %") self.world = World() self.add_isttok() self.pixel_source = Cylinder(radius=self.vessel_in_rad - 0.0015, height=self.vessel_width, parent=self.world, transform=translate(0, 0, 0) * rotate(0, 0, 0), name='PlasmaSource') one_pixel = PixelMaterial(pixel_side=pixel_side, pixel_id=pixel, print=False) self.pixel_source.material = one_pixel self.simulate_rays() column = np.hstack((self.top_data, self.out_data)).reshape((32, 1)) geo_matrix = np.hstack((geo_matrix, column)) np.save(out_file, geo_matrix)
def test_evaluate_function_2d(self): """ Unlike test_integration_2d() in TestRayTransferCylinder here we test how CylindricalRayTransferEmitter works with NumericalIntegrator in axysimmetric case. Testing against ToroidalVoxelGrid. """ world = World() material = CylindricalRayTransferEmitter( (2, 2), (1., 1.), rmin=2., integrator=NumericalIntegrator(0.0001)) primitive = Subtract(Cylinder(3.999999, 1.999999), Cylinder(2.0, 1.999999), material=material, parent=world) ray = Ray(origin=Point3D(4., 1., 2.), direction=Vector3D(-4., -1., -2.) / np.sqrt(21.), min_wavelength=500., max_wavelength=501., bins=4) spectrum = ray.trace(world) world = World() vertices = [] for rv in [2., 3.]: for zv in [0., 1.]: vertices.append([ Point2D(rv, zv + 1.), Point2D(rv + 1., zv + 1.), Point2D(rv + 1., zv), Point2D(rv, zv) ]) tvg = ToroidalVoxelGrid(vertices, parent=world, primitive_type='csg', active='all') tvg.set_active('all') spectrum_test = ray.trace(world) self.assertTrue( np.allclose(spectrum_test.samples, spectrum.samples, atol=0.001))
def load_vessel_world(mesh_parts, shift_p5=False): """Load the world containing the vessel mesh parts. <mesh_parts> is a list of filenames containing mesh files in either RSM or OBJ format, which are to be loaded into the world. If shift_p5 is True, the mesh files representing the P5 coils will have a downward shift applied to them to account for the UEP sag. This is described in CD/MU/04783. Returns world, the root of the scenegraph. """ world = World() for path, _ in mesh_parts: print("importing {} ...".format(os.path.split(path)[1])) filename = os.path.split(path)[-1] name, ext = filename.split('.') if 'P5_' in path and shift_p5: p5_zshift = -0.00485 # From CD/MU/04783 transform = translate(0, 0, p5_zshift) else: transform = None if ext.lower() == 'rsm': Mesh.from_file(path, parent=world, material=AbsorbingSurface(), transform=transform, name=name) elif ext.lower() == 'obj': import_obj(path, parent=world, material=AbsorbingSurface(), name=name) else: raise ValueError("Only RSM and OBJ meshes are supported.") # Add a solid cylinder at R=0 to prevent rays finding their way through the # gaps in the centre column armour. This is only necessary for the MAST # meshes, but it does no harm to add it to MAST-U meshes too height = 6 radius = 0.1 Cylinder(radius=radius, height=height, parent=world, transform=translate(0, 0, -height / 2), material=AbsorbingSurface(), name='Blocking Cylinder') return world
def __init__(self): world = World() self.world = world self.top_px = [] self.out_px = [] self.top_power = [] self.out_power = [] self.vessel_width = 0.060 self.vessel_in_rad = 0.100 self.vessel_out_rad = 0.101 self.lid_height = 0.0016 # self.cam_out_radius = 0.0189 self.cam_in_radius = 0.0184 self.tube_height = 0.0401 # self.lid_top = 0.00110 # como parece certo pela folha # self.lid_outer = 0.00155 # # # self.lid_top = 0.00155 # como estava inicialmente # # self.lid_outer = 0.00110 self.lid_top = 0.00155 self.lid_outer = 0.00155 # Top calib 2 self.x_shift_top = -0.005 self.y_shift_top = 0.09685 self.x_shift_outer = -0.1091 self.top_twist = 0.000 + 0.0003 self.top_px_first_x = self.x_shift_top + 0.0001 + 0.000375 + 7 * 0.00095 + 0.0 self.top_px_first_y = self.y_shift_top + 0.009 + self.top_twist - 0.0003 self.top_px_z = self.vessel_width / 2 self.out_twist = 0.0007 - 0.0003 self.out_px_first_y = 0.0001 + 0.000375 + 7 * 0.00095 - 0.00015 + 0.0001 self.out_px_first_x = self.x_shift_outer - 0.009 + self.out_twist + 0.00035 - 0.0005 self.out_px_z = self.vessel_width / 2 self.top_data = [] self.out_data = [] self.real_data = []
def test_integration_3d(self): world = World() rtc = RayTransferCylinder(radius_outer=2., height=2., n_radius=2, n_height=2, n_polar=3, period=90., parent=world) rtc.step = 0.001 * rtc.step ray = Ray(origin=Point3D(np.sqrt(2.), np.sqrt(2.), 2.), direction=Vector3D(-1., -1., -np.sqrt(2.)) / 2., min_wavelength=500., max_wavelength=501., bins=rtc.bins) spectrum = ray.trace(world) spectrum_test = np.zeros(rtc.bins) spectrum_test[2] = spectrum_test[9] = np.sqrt(2.) self.assertTrue( np.allclose(spectrum_test, spectrum.samples, atol=0.001))
def test_integration(self): world = World() rtb = RayTransferBox(xmax=3., ymax=3., zmax=3., nx=3, ny=3, nz=3, parent=world) rtb.step = 0.01 * rtb.step ray = Ray(origin=Point3D(4., 4., 4.), direction=Vector3D(-1., -1., -1.) / np.sqrt(3), min_wavelength=500., max_wavelength=501., bins=rtb.bins) spectrum = ray.trace(world) spectrum_test = np.zeros(rtb.bins) spectrum_test[0] = spectrum_test[13] = spectrum_test[26] = np.sqrt(3.) self.assertTrue( np.allclose(spectrum_test, spectrum.samples, atol=0.001))
def test_evaluate_function(self): """ Unlike test_integration() in TestRayTransferBox here we test how CartesianRayTransferEmitter works with NumericalIntegrator. """ world = World() material = CartesianRayTransferEmitter( (3, 3, 3), (1., 1., 1.), integrator=NumericalIntegrator(0.0001)) box = Box(lower=Point3D(0, 0, 0), upper=Point3D(2.99999, 2.99999, 2.99999), material=material, parent=world) ray = Ray(origin=Point3D(4., 4., 4.), direction=Vector3D(-1., -1., -1.) / np.sqrt(3), min_wavelength=500., max_wavelength=501., bins=material.bins) spectrum = ray.trace(world) spectrum_test = np.zeros(material.bins) spectrum_test[0] = spectrum_test[13] = spectrum_test[26] = np.sqrt(3.) self.assertTrue( np.allclose(spectrum_test, spectrum.samples, atol=0.001))
def __init__(self, reflections=True, pixel_samples=1000): self.reflections = reflections self.pixel_samples = pixel_samples self.world = World() self.vessel_width = 0.060 self.vessel_in_rad = 0.100 self.vessel_out_rad = 0.101 self.lid_height = 0.0016 self.cam_in_radius = 0.0184 self.tube_height = 0.0401 self.lid_top = 0.00155 self.lid_outer = 0.00155 self.x_shift_top = -0.005 self.y_shift_top = 0.09685 self.x_shift_outer = -0.1091 self.top_twist = 0.000 + 0.0003 self.top_px_first_x = self.x_shift_top + 0.0001 + 0.000375 + 7 * 0.00095 + 0.0 self.top_px_first_y = self.y_shift_top + 0.009 + self.top_twist - 0.0003 self.top_px_z = self.vessel_width / 2 self.out_twist = 0.0007 - 0.0003 self.out_px_first_y = 0.0001 + 0.000375 + 7 * 0.00095 - 0.00015 + 0.0001 self.out_px_first_x = self.x_shift_outer - 0.009 + self.out_twist + 0.00035 - 0.0005 self.out_px_z = self.vessel_width / 2 self.vessel = None self.camera_top, self.camera_outer = None, None self.top_pinhole, self.out_pinhole = None, None self.top_data = [] self.out_data = [] self.add_isttok()
def test_evaluate_function_3d(self): """ Unlike test_integration_3d() in TestRayTransferCylinder here we test how CylindricalRayTransferEmitter works with NumericalIntegrator in 3D case. """ world = World() material = CylindricalRayTransferEmitter( (2, 3, 2), (1., 30., 1.), period=90., integrator=NumericalIntegrator(0.0001)) primitive = Subtract(Cylinder(1.999999, 1.999999), Cylinder(0.000001, 1.999999), material=material, parent=world) ray = Ray(origin=Point3D(np.sqrt(2.), np.sqrt(2.), 2.), direction=Vector3D(-1., -1., -np.sqrt(2.)) / 2., min_wavelength=500., max_wavelength=501., bins=12) spectrum = ray.trace(world) spectrum_test = np.zeros(12) spectrum_test[2] = spectrum_test[9] = np.sqrt(2.) self.assertTrue( np.allclose(spectrum_test, spectrum.samples, atol=0.001))
import time import matplotlib.pyplot as plt from raysect.primitive import import_obj from raysect.optical import World from raysect.optical.material import AbsorbingSurface from cherab.jet.machine import import_jet_mesh from cherab.jet.machine.cad_files import KB5V, KB5H from cherab.jet.bolometry import load_kb5_camera, load_kb5_inversion_grid # Calculate KB5V camera sensitivities kb5v_world = World() inversion_grid = load_kb5_inversion_grid(parent=kb5v_world, name="KB5 inversion grid") import_jet_mesh(kb5v_world, override_material=AbsorbingSurface()) kb5v_collimator_mesh = import_obj(KB5V[0][0], scaling=0.001, parent=kb5v_world, material=AbsorbingSurface()) kb5v = load_kb5_camera('KB5V', parent=kb5v_world) kb5v_ch14 = kb5v['KB5V_CH14'] start_time = time.time() sensitivities = kb5v_ch14.calculate_sensitivity(inversion_grid, ray_count=1000) print("run time - {:.2G}mins".format((time.time() - start_time) / 60)) plt.ion() inversion_grid.plot(voxel_values=sensitivities) plt.show()
from raysect.optical import World, translate, Point3D from raysect.optical.library import schott from raysect.primitive import Sphere """ World contains point -------------------- This demo shows how the world.contains() method can be used to query the world for all primitives that intersect the test point. This simple scene contains a Sphere at the origin of radius 0.5m. A grid of test points is generated in the x-y plane. Each point is tested to see if it lies inside the sphere. """ world = World() # Place test sphere at origin sphere = Sphere(radius=0.5, transform=translate(0, 0, 0), material=schott("N-BK7")) sphere.parent = world # Construct test points in x-y plane xpts = np.linspace(-1.0, 1.0) ypts = np.linspace(-1.0, 1.0) x_inside = [] y_inside = [] x_outside = [] y_outside = []
from cherab_mastu.mast_cad_files import CENTRE_COLUMN, LOWER_DIVERTOR_ARMOUR from core.model.impact_excitation.pec_line import ExcitationLine, RecombinationLine from raysect.core.ray import Ray as CoreRay from raysect.optical.material.absorber import AbsorbingSurface # Cherab and raysect imports from cherab.core.atomic import Line from cherab.core.atomic import deuterium # Core and external imports from raysect.core import Vector3D, Point3D from raysect.optical import World, translate, rotate_basis from raysect.optical.observer import FibreOptic, SpectralPipeline0D from raysect.primitive.mesh import Mesh plt.ion() world = World() MESH_PARTS = CENTRE_COLUMN + LOWER_DIVERTOR_ARMOUR for cad_file in MESH_PARTS: directory, filename = os.path.split(cad_file) name, ext = filename.split('.') print("importing {} ...".format(filename)) Mesh.from_file(cad_file, parent=world, material=AbsorbingSurface(), name=name) # Load plasma from SOLPS model mds_server = 'solps-mdsplus.aug.ipp.mpg.de:8001' ref_number = 69636
def __init__(self, solps_ref_no, view, line, camera, optics='MAST_CI_mod', cherab_down_sample=50, verbose=True, display=False, overwrite=False): """ :param solps_ref_no: int :param view: str :param line: str :param camera: str :param optics: str :param cherab_down_sample: int downsample the image by ths factor in both dimensions, for speed / testing. :param verbose: bool :param display: bool :param overwrite: bool """ self.world = World() self.solps_ref_no = solps_ref_no self.line = line self.view = view self.camera = camera self.optics = optics self.cherab_down_sample = cherab_down_sample self.verbose = verbose self.display = display self.overwrite = overwrite self.radiance = NotImplemented self.spectral_radiance = NotImplemented self.pupil_point = settings.view[self.view]['pupil_point'] self.view_vector = settings.view[self.view]['view_vector'] self.sensor_format = settings.camera[self.camera]['sensor_format'] for s in self.sensor_format: assert s % cherab_down_sample == 0 self.sensor_format_ds = tuple((np.array(self.sensor_format) / cherab_down_sample).astype(np.int)) self.pixel_size = settings.camera[self.camera]['pixel_size'] self.pixel_size_ds = self.pixel_size * cherab_down_sample self.x, self.y, = self.calc_pixel_position(self.pixel_size, self.sensor_format) self.x_pixel = self.x.x_pixel self.y_pixel = self.y.y_pixel self.x_ds = self.x.isel(x=slice(0, self.sensor_format[0], cherab_down_sample, )) self.y_ds = self.y.isel(y=slice(0, self.sensor_format[1], cherab_down_sample, )) self.x_pixel_ds = self.x_ds.x_pixel self.y_pixel_ds = self.y_ds.y_pixel self.chunks = {'x': 800, 'y': 800} # calculate field of view (FOV) (horizontal) using sensor geometry and lens focal lengths f_1, f_2, f_3 = settings.optics[self.optics] sensor_dim = self.sensor_format[0] * self.pixel_size self.fov = 2 * np.arctan((sensor_dim / 2) * f_2 / (f_3 * f_1)) * 180 / np.pi # deg # # file and directory paths self.dir_name = str(solps_ref_no) + '_' + view + '_' + line + '_' + camera self.dir_path = os.path.join(path_saved_data, self.dir_name) fname = 'spec_power.nc' fname_ds = 'spec_power_ds.nc' self.fpath_ds = os.path.join(self.dir_path, fname_ds, ) self.fpath = os.path.join(self.dir_path, fname, ) # load SOLPS plasma and set emission line model self.sim = load_solps_from_mdsplus(mds_server, self.solps_ref_no) self.plasma = self.sim.create_plasma(parent=self.world) self.plasma.atomic_data = OpenADAS(permit_extrapolation=True) emission_line = settings.line[self.line] element, charge, transition = [emission_line[s] for s in ['element', 'charge', 'transition', ]] line_obj = Line(element, charge, transition, ) self._line_excit = ExcitationLine(line_obj, lineshape=StarkBroadenedLine) self._line_recom = RecombinationLine(line_obj, lineshape=StarkBroadenedLine) self.plasma.models = [Bremsstrahlung(), self._line_excit, self._line_recom] wl_0_nm = self._line_excit.atomic_data.wavelength(element, charge, transition, ) self.wl_0 = wl_0_nm * 1e-9 # [m] self.wl_min_nm, self.wl_max_nm = wl_0_nm - 0.2, wl_0_nm + 0.2 # [m] # ugly, but I want to convert the density units to 10^{20} m^{-3} def get_ne(x, y, z, ): return 1e-20 * self.plasma.electron_distribution.density(x, y, z, ) def get_ni(x, y, z, ): return 1e-20 * self.plasma.composition.get(deuterium, 0).distribution.density(x, y, z, ) def get_b_field_mag(x, y, z, ): """ magnitude of the magnetic field at x, y, z :param x: :param y: :param z: :return: """ return self.plasma.b_field(x, y, z, ).length def get_emiss_excit(x, y, z, ): return self._line_excit.emission(Point3D(x, y, z, ), Vector3D(1, 1, 1), Spectrum(380, 700, 100)).total() def get_emiss_recom(x, y, z, ): return self._line_recom.emission(Point3D(x, y, z, ), Vector3D(1, 1, 1), Spectrum(380, 700, 100)).total() self.valid_param_get_fns = {'ne': get_ne, 'ni': get_ni, 'te': self.plasma.electron_distribution.effective_temperature, 'ti': self.plasma.composition.get(deuterium, 0).distribution.effective_temperature, 'tn': self.plasma.composition.get(deuterium, 1).distribution.effective_temperature, 'b_field_mag': get_b_field_mag, 'emiss_excit': get_emiss_excit, 'emiss_recom': get_emiss_recom, } self.valid_params = list(self.valid_param_get_fns.keys()) # load / make the cherab image if os.path.isdir(self.dir_path) and self.overwrite is False: if os.path.isfile(self.fpath) and os.path.isfile(self.fpath_ds): pass else: if not os.path.isdir(self.dir_path): os.mkdir(self.dir_path) self.make_cherab_image() ds, ds_ds = self.load_cherab_image() self.spectral_radiance = ds['spectral_radiance'] self.radiance = self.spectral_radiance.integrate(dim='wavelength') self.radiance = xr.where(xr.ufuncs.isnan(self.radiance), 0, self.radiance, ) self.spectral_radiance_ds = ds_ds['spectral_radiance_ds'] self.radiance_ds = ds_ds['radiance_ds'] self.view_vectors = ds_ds['view_vectors_ds'] self.ray_lengths = ds_ds['ray_lengths_ds'] ds.close()
import os import time import matplotlib.pyplot as plt from raysect.optical import World from cherab.aug.machine import plot_aug_wall_outline, import_mesh_segment, VESSEL, PSL, ICRH, DIVERTOR, A_B_COILS from cherab.aug.bolometry import FDC_TUBE, FLX_TUBE, FVC_TUBE, FHS_TUBE, load_default_bolometer_config from cherab.aug.bolometry import load_standard_inversion_grid start_time = time.time() # Load default inversion grid grid = load_standard_inversion_grid() # Calculate FLX camera sensitivities flx_world = World() import_mesh_segment(flx_world, FLX_TUBE) flx = load_default_bolometer_config('FLX', parent=flx_world) for detector in flx: print('calculating detector {}'.format(detector.detector_id)) detector.calculate_sensitivity(grid) flx.save("FLX_camera.pickle") # Calculate FDC camera sensitivities fdc_world = World() import_mesh_segment(fdc_world, FDC_TUBE) fdc = load_default_bolometer_config('FDC', parent=fdc_world) for detector in fdc: print('calculating detector {}'.format(detector.detector_id)) detector.calculate_sensitivity(grid) fdc.save("FDC_camera.pickle")
import os import matplotlib.pyplot as plt from raysect.optical import World from cherab.aug.machine import plot_aug_wall_outline import cherab.aug.bolometry from cherab.aug.bolometry import load_default_bolometer_config from cherab.aug.bolometry import load_standard_inversion_grid plt.ion() grid = load_standard_inversion_grid() full_world = World() def plot_detector(detector): detector.los_radiance_sensitivity.plot() plot_aug_wall_outline() detector.volume_radiance_sensitivity.plot() plot_aug_wall_outline() flx = load_default_bolometer_config('FLX', parent=full_world, inversion_grid=grid) for detector in flx: plot_detector(detector) plt.show() input("waiting...") plt.close('all') fdc = load_default_bolometer_config('FDC', parent=full_world, inversion_grid=grid)
# Internal imports from raysect.optical import World, translate, Point3D from raysect.optical.library import schott from raysect.primitive import Sphere """ World contains point -------------------- This demo shows how the world.contains() method can be used to query the world for all primitives that intersect the test point. This simple scene contains a Sphere at the origin of radius 0.5m. A grid of test points is generated in the x-y plane. Each point is tested to see if it lies inside the sphere. """ world = World() # Place test sphere at origin sphere = Sphere(radius=0.5, transform=translate(0, 0, 0), material=schott("N-BK7")) sphere.parent = world # Construct test points in x-y plane xpts = np.linspace(-1.0, 1.0) ypts = np.linspace(-1.0, 1.0) x_inside = [] y_inside = [] x_outside = []
import numpy as np from raysect.optical import World from cherab.aug.bolometry import FDC_TUBE, FLX_TUBE, FVC_TUBE, FHS_TUBE, load_default_bolometer_config from cherab.aug.bolometry import load_standard_inversion_grid # Load default inversion grid grid = load_standard_inversion_grid() fvc_world = World() fvc = load_default_bolometer_config('FVC', parent=fvc_world) fvc_ch10 = fvc['FVC1_C_CH10'] detector = fvc_ch10 detector.calculate_etendue() mb_area_foil = 4.940000E-06 # f_foil mb_area_pinhole = 1.811040E-05 # f_blende mb_d = 0.07304400 # d mb_delta = -8.400000 # delta mb_gamma = 1.993000 # gamma mb_alpha = -6.407000 # alpha mb_etendue = 1.325230E-09 mb_mesh_area_reduction = mb_area_pinhole / (detector.slit.dx * detector.slit.dy) mb_omega = mb_area_pinhole * np.cos(np.deg2rad(mb_gamma)) / mb_d**2 mb_calc_etendue = np.cos(np.deg2rad(mb_alpha)) * mb_area_foil * mb_omega cherab_solid_angle = detector.etendue / detector._volume_observer.etendue * 2 * np.pi
Rays are launched in the same way as the pinhole camera. The simple scene consists of the Stanford bunny model sitting on a platform. For every ray that is launched, the cartesian hit point of the ray with the materials in the scene (rabit and floor) is recorded. In Figure 1 the 3D hit point for each ray in the camera is plotted in 3D space. In Figure 2 the z coordinate of each hit point is scaled and plotted to indicate distance from the camera. Both methods allow simple visualisation of a scene and extraction of intersection geometry data. Bunny model source: Stanford University Computer Graphics Laboratory http://graphics.stanford.edu/data/3Dscanrep/ Converted to obj format using MeshLab """ world = World() mesh_path = path.join(path.dirname(__file__), "../resources/stanford_bunny.rsm") mesh = Mesh.from_file(mesh_path, parent=world, transform=rotate(180, 0, 0)) # LIGHT BOX padding = 1e-5 enclosure_thickness = 0.001 + padding glass_thickness = 0.003 light_box = Node(parent=world) enclosure_outer = Box(Point3D(-0.10 - enclosure_thickness, -0.02 - enclosure_thickness, -0.10 - enclosure_thickness), Point3D(0.10 + enclosure_thickness, 0.0, 0.10 + enclosure_thickness)) enclosure_inner = Box(Point3D(-0.10 - padding, -0.02 - padding, -0.10 - padding), Point3D(0.10 + padding, 0.001, 0.10 + padding))
from raysect.optical.material.emitter import UnityVolumeEmitter, UniformSurfaceEmitter samples = 100000 sphere_radius = 0.5 cube_size = 2 min_wl = 400 max_wl = 401 # sanity check! if cube_size <= 2 * sphere_radius: raise ValueError("The cube dimensions must be larger that the sphere.") # set-up scenegraph world = World() emitter = Sphere(radius=sphere_radius, parent=world) # The observer plane covers 1 side of a cube - to work out total power, multiply result by 6 power = PowerPipeline0D(accumulate=False) observing_plane = Pixel([power], x_width=cube_size, y_width=cube_size, min_wavelength=min_wl, max_wavelength=max_wl, spectral_bins=1, pixel_samples=samples, parent=world, transform=rotate(0, 0, 0) * translate(0, 0, -cube_size / 2))
# perform Delaunay triangulation to produce triangular mesh triangles = Delaunay(vertex_coords).simplices # sample our plasma functions at the mesh vertices d0_vertex_densities = np.array( [neutral_distribution(r, peak_density) for r, z in vertex_coords]) d1_vertex_densities = np.array( [ion_distribution(r, peak_density, 0) for r, z in vertex_coords]) d1_vertex_temperatures = np.array( [ion_distribution(r, peak_temperature, 0) for r, z in vertex_coords]) ################### # plasma creation # world = World() # setup scenegraph plasma = Plasma(parent=world) plasma.atomic_data = OpenADAS(permit_extrapolation=True) plasma.geometry = Cylinder(1.5, 4, transform=translate(0, 0, -2)) plasma.geometry_transform = translate(0, 0, -2) # No net velocity for any species zero_velocity = ConstantVector3D(Vector3D(0, 0, 0)) # define neutral species distribution # create a 2D interpolator from the mesh coords and data samples d0_density_interp = Interpolator2DMesh(vertex_coords, d0_vertex_densities, triangles,