示例#1
0
    def _generate_rays(self, template, ray_count):

        origin_vectors = self._sphere_sampler(ray_count)
        directions = self._vector_sampler(ray_count)

        rays = []
        for n in range(ray_count):

            # calculate surface point
            origin = origin_vectors[n].copy()
            origin.length = self._radius
            origin = Point3D(*origin)

            # calculate surface normal
            normal = -origin_vectors[n]

            # transform sampling direction from surface space
            direction = directions[n].transform(
                rotate_basis(normal, normal.orthogonal()))

            # USE WITH HEMISPHERECOSINESAMPLER
            # cosine weighted distribution, projected area weight is
            # implicit in distribution, so set weight appropriately
            rays.append((template.copy(origin, direction), 0.5))

        return rays
示例#2
0
    def _generate_rays(self, template, ray_count):

        origin_vectors = self._sphere_sampler(ray_count)
        directions = self._vector_sampler(ray_count)

        rays = []
        for n in range(ray_count):

            # calculate surface point
            origin = origin_vectors[n].copy()
            origin.length = self._radius
            origin = Point3D(*origin)

            # calculate surface normal
            normal = -origin_vectors[n]

            # transform sampling direction from surface space
            direction = directions[n].transform(rotate_basis(normal, normal.orthogonal()))

            # USE WITH HEMISPHERECOSINESAMPLER
            # cosine weighted distribution, projected area weight is
            # implicit in distribution, so set weight appropriately
            rays.append((template.copy(origin , direction), 0.5))

        return rays
示例#3
0
 def point(self, value):
     if not (self._direction.x == 0 and self._direction.y == 0
             and self._direction.z == 1):
         up = Vector3D(0, 0, 1)
     else:
         up = Vector3D(1, 0, 0)
     self._point = value
     self._observer.transform = translate(
         value.x, value.y, value.z) * rotate_basis(self._direction, up)
示例#4
0
 def direction(self, value):
     if value.x != 0 and value.y != 0 and value.z != 1:
         up = Vector3D(0, 0, 1)
     else:
         up = Vector3D(1, 0, 0)
     self._direction = value
     self._observer.transform = translate(self._point.x, self._point.y,
                                          self._point.z) * rotate_basis(
                                              value, up)
示例#5
0
    def __init__(self, slit_id, centre_point, basis_x, dx, basis_y, dy, dz=0.001,
                 parent=None, csg_aperture=False, curvature_radius=0):

        # perform validation of input parameters

        if not isinstance(dx, (float, int)):
            raise TypeError("dx argument for BolometerSlit must be of type float/int.")
        if not dx > 0:
            raise ValueError("dx argument for BolometerSlit must be greater than zero.")

        if not isinstance(dy, (float, int)):
            raise TypeError("dy argument for BolometerSlit must be of type float/int.")
        if not dy > 0:
            raise ValueError("dy argument for BolometerSlit must be greater than zero.")

        if not isinstance(centre_point, Point3D):
            raise TypeError("centre_point argument for BolometerSlit must be of type Point3D.")

        if not isinstance(curvature_radius, (float, int)):
            raise TypeError("curvature_radius argument for BolometerSlit "
                            "must be of type float/int.")
        if curvature_radius < 0:
            raise ValueError("curvature_radius argument for BolometerSlit "
                             "must not be negative.")

        if not isinstance(basis_x, Vector3D):
            raise TypeError("The basis vectors of BolometerSlit must be of type Vector3D.")
        if not isinstance(basis_y, Vector3D):
            raise TypeError("The basis vectors of BolometerSlit must be of type Vector3D.")

        self._centre_point = centre_point
        self._basis_x = basis_x.normalise()
        self.dx = dx
        self._basis_y = basis_y.normalise()
        self.dy = dy
        self.dz = dz
        self._curvature_radius = curvature_radius

        # NOTE - target primitive and aperture surface cannot be co-incident otherwise numerics will cause Raysect
        # to be blind to one of the two surfaces.
        slit_normal = basis_x.cross(basis_y)
        transform = translate(centre_point.x, centre_point.y, centre_point.z) * rotate_basis(slit_normal, basis_y)

        super().__init__(parent=parent, transform=transform, name=slit_id)

        self.target = Box(lower=Point3D(-dx/2*1.01, -dy/2*1.01, -dz/2), upper=Point3D(dx/2*1.01, dy/2*1.01, dz/2),
                          transform=None, material=NullMaterial(), parent=self, name=slit_id+' - target')

        self._csg_aperture = None
        self.csg_aperture = csg_aperture

        # round off the detector corners, if applicable
        if self._curvature_radius > 0:
            mask_corners(self)
示例#6
0
    def __init__(self,
                 slit_id,
                 centre_point,
                 basis_x,
                 dx,
                 basis_y,
                 dy,
                 dz=0.001,
                 parent=None,
                 csg_aperture=False):

        self._centre_point = centre_point
        self._basis_x = basis_x.normalise()
        self.dx = dx
        self._basis_y = basis_y.normalise()
        self.dy = dy
        self.dz = dz

        # NOTE - target primitive and aperture surface cannot be co-incident otherwise numerics will cause Raysect
        # to be blind to one of the two surfaces.
        slit_normal = basis_x.cross(basis_y)
        transform = translate(centre_point.x, centre_point.y,
                              centre_point.z) * rotate_basis(
                                  slit_normal, basis_y)

        super().__init__(parent=parent, transform=transform, name=slit_id)

        self.target = Box(lower=Point3D(-dx / 2 * 1.01, -dy / 2 * 1.01,
                                        -dz / 2),
                          upper=Point3D(dx / 2 * 1.01, dy / 2 * 1.01, dz / 2),
                          transform=None,
                          material=NullMaterial(),
                          parent=self,
                          name=slit_id + ' - target')

        self._csg_aperture = None
        self.csg_aperture = csg_aperture
示例#7
0
from cherab.tools.plasmas.slab import build_slab_plasma

from renate.cherab_models import RenateBeamEmissionLine, RenateBeam


world = World()


# PLASMA ----------------------------------------------------------------------
plasma = build_slab_plasma(peak_density=5e19, world=world)
plasma.b_field = ConstantVector3D(Vector3D(0, 0.6, 0))


# BEAM SETUP ------------------------------------------------------------------
integration_step = 0.0025
beam_transform = translate(-0.5, 0.0, 0) * rotate_basis(Vector3D(1, 0, 0), Vector3D(0, 0, 1))
line = Line(hydrogen, 0, (3, 2))

beam = RenateBeam(parent=world, transform=beam_transform)
beam.plasma = plasma
beam.energy = 100000
beam.power = 3e6
beam.element = hydrogen
beam.temperature = 30
beam.sigma = 0.05
beam.divergence_x = 0.
beam.divergence_y = 0.
beam.length = 3.0
beam.models = [RenateBeamEmissionLine(line)]
beam.integrator.step = integration_step
beam.integrator.min_samples = 10
示例#8
0
    u1 = Point3D(u1x, u1y, u1z)
    u2x, u2y, u2z = s1_vertices[v2]
    u2 = Point3D(u2x, u2y, u2z)
    u3x, u3y, u3z = s1_vertices[v3]
    u3 = Point3D(u3x, u3y, u3z)
    uc = Point3D((u1x + u2x + u3x) / 3, (u1y + u2y + u3y) / 3,
                 (u1z + u2z + u3z) / 3)
    u1u2 = u1.vector_to(u2).normalise()
    u1u3 = u1.vector_to(u3).normalise()
    n_pi1 = u1u2.cross(u1u3).normalise()  # normal vector of plane 1

    debug_vertices = [[u1x, u1y, u1z], [u2x, u2y, u2z], [u3x, u3y, u3z]]
    debug_triangles = [[0, 1, 2]]

    # transform to x-y plane
    s1_transform = translate(u1.x, u1.y, u1.z) * rotate_basis(u1u2, n_pi1)
    s1_inv_transform = s1_transform.inverse()

    points = set()
    for vertex in (u1, u2, u3):
        tv = vertex.transform(s1_inv_transform)
        points.add((tv.x, tv.z))

    debug_intersection_points = []
    for intersection in s1_intersections[s1_tri_id]:

        s2_tri_id, ut1, ut2 = intersection
        print('-->')
        print('s2_tri_id', s2_tri_id)
        print(ut1.distance_to(ut2))
示例#9
0
r, _, z, t_samples = sample3d(h0.distribution.density, (-1, 2, 200), (0, 0, 1),
                              (-1, 1, 200))
plt.imshow(np.transpose(np.squeeze(t_samples)), extent=[-1, 2, -1, 1])
plt.colorbar()
plt.axis('equal')
plt.xlabel('x axis')
plt.ylabel('z axis')
plt.title("Neutral Density profile in x-z plane")

###########################
# Inject beam into plasma #

adas = OpenADAS(permit_extrapolation=True, missing_rates_return_null=True)

integration_step = 0.0025
beam_transform = translate(-0.5, 0.0, 0) * rotate_basis(
    Vector3D(1, 0, 0), Vector3D(0, 0, 1))

beam_energy = 50000  # keV

beam_full = Beam(parent=world, transform=beam_transform)
beam_full.plasma = plasma
beam_full.atomic_data = adas
beam_full.energy = beam_energy
beam_full.power = 3e6
beam_full.element = deuterium
beam_full.sigma = 0.05
beam_full.divergence_x = 0.5
beam_full.divergence_y = 0.5
beam_full.length = 3.0
beam_full.attenuator = SingleRayAttenuator(clamp_to_zero=True)
beam_full.models = [BeamCXLine(Line(carbon, 5, (8, 7)))]
示例#10
0
    def __init__(self,
                 pini_geometry,
                 pini_parameters,
                 plasma,
                 atomic_data,
                 attenuation_instructions,
                 emission_instructions,
                 integration_step=0.02,
                 parent=None,
                 name=""):

        source, direction, divergence, initial_width, length = pini_geometry
        energy, power_fractions, self._turned_on_func, element = pini_parameters

        self._components = []
        self._length = length
        self._parent_reminder = parent

        # Rotation between 'direction' and the z unit vector
        # This is important because the beam primitives are defined along the z axis.
        self._origin = source
        self._direction = direction
        direction.normalise()
        rotation = rotate_basis(direction, Vector3D(0., 0., 1.))
        transform_pini = translate(*source) * rotation

        Node.__init__(self, parent=parent, transform=transform_pini, name=name)

        attenuation_model_class, attenuation_model_arg = attenuation_instructions

        # the 3 energy components are different beams
        for comp_nb in [1, 2, 3]:

            # creation of the attenuation model
            # Note that each beamlet needs its own attenuation class instance.
            attenuation_model = attenuation_model_class(
                **attenuation_model_arg)

            # creation of the emission models
            emission_models = []
            for (emission_model_class,
                 argument_dictionary) in emission_instructions:
                emission_models.append(
                    emission_model_class(**argument_dictionary))

            beam = Beam(parent=self,
                        transform=translate(0., 0., 0.),
                        name="Beam component {}".format(comp_nb))
            beam.plasma = plasma
            beam.atomic_data = atomic_data
            beam.energy = energy / comp_nb
            beam.power = power_fractions[comp_nb - 1]
            beam.element = element
            beam.sigma = initial_width
            beam.divergence_x = divergence[0]
            beam.divergence_y = divergence[1]
            beam.length = length
            beam.attenuator = attenuation_model
            beam.models = emission_models
            beam.integrator.step = integration_step
            beam.integrator.min_samples = 10

            self._components.append(beam)
示例#11
0
def load_kb1_camera(parent=None):

    camera_id = 'KB1'

    # Transforms, read from KB1 CAD model for INDIVIDUAL_BOLOMETER_ASSEMBLY
    # Note that the rotation angle is positive when Axis is the Z axis, and
    # negative when Axis is the -Z axis
    camera_transforms = [
        translate(-1.73116, 2.59086, 3.31650) * rotate_z(123.75),
        translate(-3.05613, 0.60790, 3.31650) * rotate_z(168.75),
        translate(1.73116, -2.59086, 3.31650) * rotate_z(-56.25),
        translate(3.05613, -0.60790, 3.31650) * rotate_z(-11.25),
    ]
    # Transform for INDIVIDUAL_BOLOMETER_ASSEMBLY/SINGLE_BOLOMETER_ASSEMBLY/FOIL 1
    # in CAD model
    foil_camera_transform = translate(0, 0, 18.70e-3)
    # Foils point downwards towards the plasma
    foil_orientation_transform = rotate_basis(Vector3D(0, 0, -1),
                                              Vector3D(0, 1, 0))
    # Dimensions read from edge to edge (and adjacent vertices defining rounded corners) on
    # INDIVIDUAL_BOLOMETER_ASSEMBLY/SINGLE_BOLOMETER_ASSEMBLY/FOIL SUPPORT 1,
    # edges (and vertices) closest to the foil
    foil_width = 11e-3
    foil_height = 11e-3
    foil_curvature_radius = 1e-3

    # KB1 does not really have a slit, per-se. The vessel functions as the
    # aperture. To ensure a sufficiently displaced bounding sphere for the
    # TargettedPixel, we'll put a dummy slit at the exit of the port through
    # which the camera views. Note that with the camera transform defined above,
    # the y axis is in the toroidal direction and the x axis in the inward
    # radial direction.
    #
    # The foil is not centred on the centre of the port. To measure the
    # displacement, the centre of the port was read from the CAD model for
    # KB1-1, then the vector from the foil centre to the centre of the port exit
    # for this channel was calculated in the foil's local coordinate system.
    foil_slit_transform = translate(-0.05025, 0, 1.38658)
    slit_width = 0.25  # slightly larger than widest point of port (~225 mm)
    slit_height = 0.09  # sligtly larger than length of port (~73.84 mm)

    num_slits = len(camera_transforms)
    num_foils = len(camera_transforms)

    bolometer_camera = BolometerCamera(name=camera_id, parent=parent)

    slit_objects = {}
    for i in range(num_slits):
        slit_id = '{}_Slit_#{}'.format(camera_id, i + 1)
        slit_transform = (camera_transforms[i] * foil_orientation_transform *
                          foil_slit_transform * foil_camera_transform)
        centre_point = Point3D(0, 0, 0).transform(slit_transform)
        basis_x = Vector3D(1, 0, 0).transform(slit_transform)
        basis_y = Vector3D(0, 1, 0).transform(slit_transform)
        dx = slit_width
        dy = slit_height
        slit_objects[slit_id] = BolometerSlit(slit_id,
                                              centre_point,
                                              basis_x,
                                              dx,
                                              basis_y,
                                              dy,
                                              csg_aperture=True,
                                              parent=bolometer_camera)

    for i in range(num_foils):
        foil_id = '{}_CH{}_Foil'.format(camera_id, i + 1)
        slit_id = '{}_Slit_#{}'.format(camera_id, i + 1)
        foil_transform = (camera_transforms[i] * foil_orientation_transform *
                          foil_camera_transform)
        centre_point = Point3D(0, 0, 0).transform(foil_transform)
        basis_x = Vector3D(1, 0, 0).transform(foil_transform)
        basis_y = Vector3D(0, 1, 0).transform(foil_transform)
        dx = foil_width
        dy = foil_height
        rc = foil_curvature_radius
        foil = BolometerFoil(foil_id,
                             centre_point,
                             basis_x,
                             dx,
                             basis_y,
                             dy,
                             slit_objects[slit_id],
                             curvature_radius=rc,
                             parent=bolometer_camera)

        bolometer_camera.add_foil_detector(foil)

    return bolometer_camera
示例#12
0
pini_8_1 = load_pini_from_ppf(PULSE, '8.1', plasma, adas,
                              attenuation_instructions,
                              beam_emission_instructions, world)
pini_8_2 = load_pini_from_ppf(PULSE, '8.2', plasma, adas,
                              attenuation_instructions,
                              beam_emission_instructions, world)
pini_8_5 = load_pini_from_ppf(PULSE, '8.5', plasma, adas,
                              attenuation_instructions,
                              beam_emission_instructions, world)
pini_8_6 = load_pini_from_ppf(PULSE, '8.6', plasma, adas,
                              attenuation_instructions,
                              beam_emission_instructions, world)

# ############################### OBSERVATION ############################### #
print('Observation')

los = Point3D(4.22950, -0.791368, 0.269430)
direction = Vector3D(-0.760612, -0.648906, -0.0197396).normalise()
los = los + direction * 0.9
up = Vector3D(0, 0, 1)

camera = PinholeCamera(
    (512, 512),
    fov=45,
    parent=world,
    transform=translate(los.x, los.y, los.z) * rotate_basis(direction, up))
camera.pixel_samples = 50
camera.spectral_bins = 15

camera.observe()
示例#13
0
def raytraced_etendue(distance, detector_radius=0.001, ray_count=100000, batches=10):

    # generate the transform to the detector position and orientation
    detector_transform = translate(0, 0, distance) * rotate_basis(Vector3D(0, 0, -1), Vector3D(0, -1, 0))

    # generate bounding sphere and convert to local coordinate system
    sphere = target.bounding_sphere()
    spheres = [(sphere.centre.transform(detector_transform), sphere.radius, 1.0)]

    # instance targetted pixel sampler
    targetted_sampler = TargettedHemisphereSampler(spheres)

    point_sampler = DiskSampler3D(detector_radius)

    detector_area = detector_radius**2 * np.pi
    solid_angle = 2 * np.pi
    etendue_sampled = solid_angle * detector_area

    etendues = []
    for i in range(batches):

        # sample pixel origins
        origins = point_sampler(samples=ray_count)

        passed = 0.0
        for origin in origins:

            # obtain targetted vector sample
            direction, pdf = targetted_sampler(origin, pdf=True)
            path_weight = R_2_PI * direction.z/pdf

            origin = origin.transform(detector_transform)
            direction = direction.transform(detector_transform)

            while True:

                # Find the next intersection point of the ray with the world
                intersection = world.hit(CoreRay(origin, direction))

                if intersection is None:
                    passed += 1 * path_weight
                    break

                elif isinstance(intersection.primitive.material, NullMaterial):
                    hit_point = intersection.hit_point.transform(intersection.primitive_to_world)
                    origin = hit_point + direction * 1E-9
                    continue

                else:
                    break

        if passed == 0:
            raise ValueError("Something is wrong with the scene-graph, calculated etendue should not zero.")

        etendue_fraction = passed / ray_count
        etendues.append(etendue_sampled * etendue_fraction)

    etendue = np.mean(etendues)
    etendue_error = np.std(etendues)

    return etendue, etendue_error
示例#14
0
shift = translate(0, 0, -1)
radiation_emitter = VolumeTransform(RadiationFunction(rad_function_3d),
                                    shift.inverse())
geom = Cylinder(CYLINDER_RADIUS,
                CYLINDER_HEIGHT,
                transform=shift,
                parent=world,
                material=radiation_emitter)

######################
# visualise emission #

# run some plots to check the distribution functions and emission profile are as expected
r, z, t_samples = sample2d(rad_function, (0, 4, 200), (-2, 2, 200))
plt.imshow(np.transpose(np.squeeze(t_samples)), extent=[0, 3, -1.5, 1.5])
plt.colorbar()
plt.axis('equal')
plt.xlabel('r axis')
plt.ylabel('z axis')
plt.title("Radiation profile in r-z plane")

camera = PinholeCamera((256, 256), pipelines=[PowerPipeline2D()], parent=world)
camera.transform = translate(-3.5, -1.5, 0) * rotate_basis(
    Vector3D(1, 0, 0), Vector3D(0, 0, 1))
camera.pixel_samples = 1

plt.ion()
camera.observe()
plt.ioff()
plt.show()
示例#15
0
    def __init__(self, detector_id, centre_point, basis_x, dx, basis_y, dy, slit,
                 parent=None, units="Power", accumulate=False, curvature_radius=0):

        # perform validation of input parameters

        if not isinstance(dx, (float, int)):
            raise TypeError("dx argument for BolometerFoil must be of type float/int.")
        if not dx > 0:
            raise ValueError("dx argument for BolometerFoil must be greater than zero.")

        if not isinstance(dy, (float, int)):
            raise TypeError("dy argument for BolometerFoil must be of type float/int.")
        if not dy > 0:
            raise ValueError("dy argument for BolometerFoil must be greater than zero.")

        if not isinstance(slit, BolometerSlit):
            raise TypeError("slit argument for BolometerFoil must be of type BolometerSlit.")

        if not isinstance(centre_point, Point3D):
            raise TypeError("centre_point argument for BolometerFoil must be of type Point3D.")

        if not isinstance(curvature_radius, (float, int)):
            raise TypeError("curvature_radius argument for BolometerFoil "
                            "must be of type float/int.")
        if curvature_radius < 0:
            raise ValueError("curvature_radius argument for BolometerFoil "
                             "must not be negative.")

        if not isinstance(basis_x, Vector3D):
            raise TypeError("The basis vectors of BolometerFoil must be of type Vector3D.")
        if not isinstance(basis_y, Vector3D):
            raise TypeError("The basis vectors of BolometerFoil must be of type Vector3D.")

        self._centre_point = centre_point
        self._basis_x = basis_x.normalise()
        self._basis_y = basis_y.normalise()
        self._normal_vec = self._basis_x.cross(self._basis_y)
        self._slit = slit
        self._foil_to_slit_vec = self._centre_point.vector_to(self._slit.centre_point).normalise()
        self._curvature_radius = curvature_radius
        self.units = units

        # setup root bolometer foil transform
        translation = translate(self._centre_point.x, self._centre_point.y, self._centre_point.z)
        rotation = rotate_basis(self._normal_vec, self._basis_y)

        if self.units == "Power":
            pipeline = PowerPipeline0D(accumulate=accumulate)
        elif self.units == "Radiance":
            pipeline = RadiancePipeline0D(accumulate=accumulate)
        else:
            raise ValueError("The units argument of BolometerFoil must be one of 'Power' or 'Radiance'.")

        super().__init__([slit.target], targetted_path_prob=1.0,
                         pipelines=[pipeline],
                         pixel_samples=1000, x_width=dx, y_width=dy, spectral_bins=1, quiet=True,
                         parent=parent, transform=translation * rotation, name=detector_id)

        # round off the detector corners, if applicable
        if self._curvature_radius > 0:
            mask_corners(self)
示例#16
0
for i, detector in enumerate(aug_wall_detectors):

    print()
    print("detector {}".format(i))

    y_width = detector[2]
    centre_point = detector[3]
    normal_vector = detector[4]
    y_vector = detector[5]
    pixel_area = X_WIDTH * y_width

    power_data = PowerPipeline0D()

    pixel_transform = translate(centre_point.x, centre_point.y,
                                centre_point.z) * rotate_basis(
                                    normal_vector, y_vector)
    pixel = Pixel([power_data],
                  x_width=X_WIDTH,
                  y_width=y_width,
                  name='pixel-{}'.format(i),
                  spectral_bins=1,
                  transform=pixel_transform,
                  parent=world,
                  pixel_samples=500)

    pixel.observe()

    powers.append(power_data.value.mean / pixel_area)
    power_errors.append(power_data.value.error() / pixel_area)
    detector_numbers.append(i)
示例#17
0
    # unpack triangle 1

    v1, v2, v3 = s1_triangles[s1_tri_id]
    u1x, u1y, u1z = s1_vertices[v1]
    u1 = Point3D(u1x, u1y, u1z)
    u2x, u2y, u2z = s1_vertices[v2]
    u2 = Point3D(u2x, u2y, u2z)
    u3x, u3y, u3z = s1_vertices[v3]
    u3 = Point3D(u3x, u3y, u3z)
    uc = Point3D((u1x + u2x + u3x) / 3, (u1y + u2y + u3y) / 3, (u1z + u2z + u3z) / 3)
    u1u2 = u1.vector_to(u2).normalise()
    u1u3 = u1.vector_to(u3).normalise()
    n_pi1 = u1u2.cross(u1u3).normalise()  # normal vector of plane 1

    # transform to x-y plane
    s1_transform = translate(u1.x, u1.y, u1.z) * rotate_basis(u1u2, n_pi1)
    s1_inv_transform = s1_transform.inverse()

    points = set()
    for vertex in (u1, u2, u3):
        tv = vertex.transform(s1_inv_transform)
        points.add((tv.x, tv.z))

    debug_intersection_points = []
    for intersection in s1_intersections[s1_tri_id]:

        s2_tri_id, ut1, ut2 = intersection

        debug_intersection_points.append((ut1, ut2))

        ut1t = ut1.transform(s1_inv_transform)
示例#18
0
plasma.integrator.min_samples = 1000
plasma.atomic_data = adas
plasma.geometry = Cylinder(sigma * 2, sigma * 10.0)
plasma.geometry_transform = translate(0, -sigma * 5.0, 0) * rotate(0, 90, 0)

# # # ########################### NBI CONFIGURATION ############################# #

#Geometry
south_pos = Point3D(0.188819939, -6.88824321,
                    0.0)  #Position of PINI grid center
duct_pos = Point3D(0.539, -1.926, 0.00)  #position of beam duct
south_pos.vector_to(duct_pos)  #beam vector
beam_axis = south_pos.vector_to(duct_pos).normalise()

up = Vector3D(0, 0, 1)
beam_rotation = rotate_basis(beam_axis, up)

beam_position = translate(south_pos.x, south_pos.y, south_pos.z)

beam_full = Beam(parent=world, transform=beam_position * beam_rotation)
beam_full.plasma = plasma
beam_full.atomic_data = adas
beam_full.energy = 65000
beam_full.power = 3e6
beam_full.element = elements.deuterium
beam_full.sigma = 0.025
beam_full.divergence_x = 0  #0.5
beam_full.divergence_y = 0  #0.5
beam_full.length = 10.0
beam_full.attenuator = SingleRayAttenuator(clamp_to_zero=True)
beam_full.models = [
示例#19
0
def raytraced_etendue(distance,
                      detector_radius=0.001,
                      ray_count=100000,
                      batches=10):

    # generate the transform to the detector position and orientation
    detector_transform = translate(0, 0, distance) * rotate_basis(
        Vector3D(0, 0, -1), Vector3D(0, -1, 0))

    # generate bounding sphere and convert to local coordinate system
    sphere = target.bounding_sphere()
    spheres = [(sphere.centre.transform(detector_transform), sphere.radius,
                1.0)]

    # instance targetted pixel sampler
    targetted_sampler = TargettedHemisphereSampler(spheres)

    point_sampler = DiskSampler3D(detector_radius)

    detector_area = detector_radius**2 * np.pi
    solid_angle = 2 * np.pi
    etendue_sampled = solid_angle * detector_area

    etendues = []
    for i in range(batches):

        # sample pixel origins
        origins = point_sampler(samples=ray_count)

        passed = 0.0
        for origin in origins:

            # obtain targetted vector sample
            direction, pdf = targetted_sampler(origin, pdf=True)
            path_weight = R_2_PI * direction.z / pdf

            origin = origin.transform(detector_transform)
            direction = direction.transform(detector_transform)

            while True:

                # Find the next intersection point of the ray with the world
                intersection = world.hit(CoreRay(origin, direction))

                if intersection is None:
                    passed += 1 * path_weight
                    break

                elif isinstance(intersection.primitive.material, NullMaterial):
                    hit_point = intersection.hit_point.transform(
                        intersection.primitive_to_world)
                    origin = hit_point + direction * 1E-9
                    continue

                else:
                    break

        if passed == 0:
            raise ValueError(
                "Something is wrong with the scene-graph, calculated etendue should not zero."
            )

        etendue_fraction = passed / ray_count
        etendues.append(etendue_sampled * etendue_fraction)

    etendue = np.mean(etendues)
    etendue_error = np.std(etendues)

    return etendue, etendue_error
示例#20
0
visualise_scenegraph(world)
input('pause...')

world = World()
Subtract(s1, b2, parent=world)
visualise_scenegraph(world)
input('pause...')

########################################################################################################################
# Cone and Cylinder

c1 = Cone(0.15, 1)
c2 = Cylinder(0.15,
              0.5,
              transform=translate(-0.25, 0, 0.5) *
              rotate_basis(Vector3D(1, 0, 0), Vector3D(0, 0, 1)))

world = World()
Union(c1, c2, parent=world)
visualise_scenegraph(world)
input('pause...')

world = World()
Intersect(c1, c2, parent=world)
visualise_scenegraph(world)
input('pause...')

world = World()
Subtract(c1, c2, parent=world)
visualise_scenegraph(world)
input('pause...')