コード例 #1
0
    def to_cherab_equilibrium(self):
        """
        Function for converting this Fiesta object to a CHERAB equilibrium.

        rtype: EFITEquilibrium
        """

        try:
            from raysect.core import Point2D
            from cherab.tools.equilibrium import EFITEquilibrium

        except ImportError:
            raise RuntimeError("CHERAB integration not installed.")

        r_vec = self.r_vec
        z_vec = self.z_vec
        psi = np.swapaxes(self.psi, 0, 1)
        psi_axis = self.psi_axis
        psi_lcfs = self.psi_lcfs
        magnetic_axis = Point2D(self.mag_axis[0], self.mag_axis[1])

        x_points = []
        for point in self.x_points:
            x_points.append(Point2D(point[0], point[1]))

        strike_points = []

        f_profile = self.f_profile
        q_profile = self.q_profile

        b_vacuum_radius = self.b_vac_radius
        b_vacuum_magnitude = self.b_vac

        lcfs_polygon = self.lcfs_polygon  # shape 2xM, indexing to remove duplicated point
        if np.all(lcfs_polygon[:, 0] == lcfs_polygon[:, -1]):
            lcfs_polygon = lcfs_polygon[:, 0:-1]

        limiter_polygon = np.array([self.r_limiter, self.z_limiter])  # 2xM

        time = 0.0

        equilibrium = EFITEquilibrium(r_vec, z_vec, psi, psi_axis, psi_lcfs,
                                      magnetic_axis, x_points, strike_points,
                                      f_profile, q_profile, b_vacuum_radius,
                                      b_vacuum_magnitude, lcfs_polygon,
                                      limiter_polygon, time)

        return equilibrium
コード例 #2
0
 def voxel_matches_polygon(self, coordinate_list):
     for voxel_coords in coordinate_list:
         voxel_coords = np.asarray(voxel_coords)
         rmax = voxel_coords[:, 0].max()
         rmin = voxel_coords[:, 0].min()
         zmax = voxel_coords[:, 1].max()
         zmin = voxel_coords[:, 1].min()
         router = 1.5 * rmax
         rinner = 0.5 * rmin
         zupper = 1.5 * zmax if zmax > 0 else 0.5 * zmax
         zlower = 0.5 * zmin if zmin > 0 else 1.5 * zmin
         test_rs = np.linspace(rinner, router, int(100 * (router - rinner)))
         test_zs = np.linspace(zlower, zupper, int(100 * (zupper - zlower)))
         voxel_vertex_points = [Point2D(*v) for v in voxel_coords]
         voxel = AxisymmetricVoxel(voxel_vertex_points,
                                   parent=None,
                                   primitive_type='csg')
         polygon = Polygon(voxel_coords, closed=True)
         test_verts = list(itertools.product(test_rs, test_zs))
         try:
             inside_poly = polygon.contains_points(test_verts)
         except AttributeError:
             # Polygon.contains_points was only introduced in Matplotlib 2.2.
             # Before that we need to convert to Path
             inside_poly = Path(
                 polygon.get_verts()).contains_points(test_verts)
         inside_csg = [
             any(
                 child.contains(Point3D(r, 0, z))
                 for child in voxel.children) for (r, z) in test_verts
         ]
         self.assertSequenceEqual(inside_csg, inside_poly.tolist())
コード例 #3
0
ファイル: test_voxels.py プロジェクト: cherab/core
 def test_rectangle_centroid(self):
     for rectangle in RECTANGULAR_VOXEL_COORDS:
         coords = np.asarray(rectangle)
         voxel = AxisymmetricVoxel(coords)
         x0, y0 = coords.mean(axis=0)
         expected_centroid = Point2D(x0, y0)
         self.assertEqual(voxel.cross_section_centroid, expected_centroid)
コード例 #4
0
    def _process_efit_points(self, point_r, point_z):
        #avoid using the point if any coordinate is nan
        point_list = []
        for i in range(point_r.shape[0]):
            if not np.isnan(point_r[i]) and not np.isnan(point_z[i]):
                point_list.append(Point2D(point_r[i], point_z[i]))

        return point_list
コード例 #5
0
def load_kb1_voxel_grid(parent=None, name=None):

    grid_description = _read_grid_pickle()

    voxel_coordinates = []
    for voxel in grid_description['voxels']:
        v1 = Point2D(voxel[0][0], voxel[0][1])
        v2 = Point2D(voxel[1][0], voxel[1][1])
        v3 = Point2D(voxel[2][0], voxel[2][1])
        v4 = Point2D(voxel[3][0], voxel[3][1])
        voxel_coordinates.append((v1, v2, v3, v4))

    voxel_grid = ToroidalVoxelGrid(voxel_coordinates,
                                   parent=parent,
                                   name=name,
                                   primitive_type="csg")

    return voxel_grid
コード例 #6
0
def _build_reference_grid():
    index = 0
    voxels = []
    drs = np.diff(_VOXEL_RS)
    dzs = np.diff(_VOXEL_ZS)
    dr = np.abs(np.median(drs))
    dz = np.abs(np.median(dzs))
    for r in _VOXEL_RS:
        row = []
        for z in _VOXEL_ZS:
            top_left = (r - dr / 2, z + dz / 2)
            bottom_left = (r - dr / 2, z - dz / 2)
            bottom_right = (r + dr / 2, z - dz / 2)
            top_right = (r + dr / 2, z + dz / 2)
            row.append((index, Point2D(*top_left), Point2D(*bottom_left),
                        Point2D(*bottom_right), Point2D(*top_right)))
            index += 1
        voxels.append(row)
    return voxels
コード例 #7
0
ファイル: test_voxels.py プロジェクト: cherab/core
 def test_triangle_centroid(self):
     for triangle in TRIANGLE_VOXEL_COORDS:
         coords = np.asarray(triangle)
         voxel = AxisymmetricVoxel(coords)
         # The centroid for a triangle is simply the mean position
         # of the vertices
         expected_centroid = Point2D(*coords.mean(axis=0))
         if voxel.cross_sectional_area == 0:
             self.assertRaises(ZeroDivisionError, getattr, voxel, "cross_section_centroid")
         else:
             self.assertEqual(voxel.cross_section_centroid, expected_centroid)
コード例 #8
0
def example_equilibrium():
    """
    Return a populated instance of the example equilibrium.

    .. code-block:: pycon

       >>> from cherab.tools.equilibrium import example_equilibrium
       >>> equilibrium = example_equilibrium()
    """

    directory = os.path.split(__file__)[0]
    example_file = os.path.join(directory, 'example.json')
    with open(example_file, 'r') as fh:
        eq_data = json.load(fh)

    r = eq_data['r']
    z = eq_data['z']
    psi = eq_data['psi']
    psi_axis = eq_data['psi_axis']
    psi_lcfs = eq_data['psi_lcfs']
    ac = eq_data['axis_coord']
    axis_coord = Point2D(ac[0], ac[1])
    xp = eq_data['x_points']
    x_points = [Point2D(xp[0][0], xp[0][1])]
    sp = eq_data['strike_points']
    strike_points = [Point2D(sp[0][0], sp[0][1]), Point2D(sp[1][0], sp[1][1])]
    f_profile = eq_data['f_profile']
    q_profile = eq_data['q_profile']
    b_vacuum_radius = eq_data['b_vacuum_radius']
    b_vacuum_magnitude = eq_data['b_vacuum_magnitude']
    lcfs_polygon = eq_data['lcfs_polygon']
    limiter_polygon = eq_data['limiter_polygon']
    time = eq_data['time']

    equilibrium = EFITEquilibrium(r, z, psi, psi_axis, psi_lcfs, axis_coord,
                                  x_points, strike_points, f_profile,
                                  q_profile, b_vacuum_radius,
                                  b_vacuum_magnitude, lcfs_polygon,
                                  limiter_polygon, time)

    return equilibrium
コード例 #9
0
ファイル: test_voxels.py プロジェクト: cherab/core
 def test_polygon_centroid(self):
     for polygon in ARBITRARY_VOXEL_COORDS:
         coords = np.asarray(polygon)
         voxel = AxisymmetricVoxel(coords)
         x = coords[:, 0]
         y = coords[:, 1]
         signed_area = (np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1))) / 2
         xroll = np.roll(x, 1)
         yroll = np.roll(y, 1)
         cx = np.sum((x + xroll) * (x * yroll - xroll * y)) / (6 * signed_area)
         cy = np.sum((y + yroll) * (x * yroll - xroll * y)) / (6 * signed_area)
         expected_centroid = Point2D(cx, cy)
         self.assertEqual(voxel.cross_section_centroid, expected_centroid)
コード例 #10
0
ファイル: load_kl11.py プロジェクト: songjun19930131/jet
def load_kl11_voxel_grid(parent=None, name=None):

    directory = os.path.split(__file__)[0]
    voxel_grid_file = os.path.join(directory, "kl11_voxel_grid.csv")

    voxel_coordinates = []
    with open(voxel_grid_file, 'r') as fh:
        reader = csv.reader(fh)

        for row in reader:
            v1 = Point2D(float(row[1]), float(row[2]))
            v2 = Point2D(float(row[3]), float(row[4]))
            v3 = Point2D(float(row[5]), float(row[6]))
            v4 = Point2D(float(row[7]), float(row[8]))
            voxel_coordinates.append((v1, v2, v3, v4))

    voxel_grid = ToroidalVoxelGrid(voxel_coordinates,
                                   parent=parent,
                                   name=name,
                                   primitive_type='csg')

    return voxel_grid
コード例 #11
0
ファイル: test_voxels.py プロジェクト: cherab/core
 def test_voxel_indexing(self):
     grid = ToroidalVoxelGrid(self.voxel_grid_coords)
     nvoxels = self.voxel_grid_coords.shape[0]
     with self.assertRaises(IndexError, msg="Negative index did not raise IndexError"):
         grid[-2]
     with self.assertRaises(IndexError, msg="index > length did not raise IndexError"):
         grid[nvoxels + 3]
     with self.assertRaises(TypeError, msg="String index did not raise TypeError"):
         grid["blah"]
     # Check the correct voxel is returned, by looking at its vertices
     for i in range(grid.count):
         self.assertSequenceEqual(
             grid[i].vertices, [Point2D(r, z) for r, z in self.voxel_grid_coords[i]],
             msg="Wrong voxel returned for index {}".format(i)
         )
コード例 #12
0
def load_bul_voxel_grid(parent=None, name=None, active=None):

    directory = os.path.split(__file__)[0]
    voxel_grid_file = os.path.join(directory, "bul_voxel_grid.csv")

    voxel_coordinates = []
    with open(voxel_grid_file, 'r') as fh:
        reader = csv.reader(fh, )

        for row in reader:
            if row[0][0] == '#':
                continue
            v1 = Point2D(float(row[1]), float(row[2]))
            v2 = Point2D(float(row[3]), float(row[4]))
            v3 = Point2D(float(row[5]), float(row[6]))
            v4 = Point2D(float(row[7]), float(row[8]))
            voxel_coordinates.append((v1, v2, v3, v4))

    voxel_grid = ToroidalVoxelGrid(voxel_coordinates,
                                   parent=parent,
                                   name=name,
                                   active=active)

    return voxel_grid
コード例 #13
0
    def time(self, time):
        """
        Returns an equilibrium object for the time-slice closest to the requested time.

        The specific time-slice returned is held in the time attribute of the returned object.

        :param time: The equilibrium time point.
        :returns: An EFITEquilibrium object.
        """

        B_VACUUM_RADIUS = 2.96  # meters

        # locate the nearest time point and fail early if we are outside the time range of the data
        try:
            index = self._find_nearest(self.time_slices, time)
        except IndexError:
            raise ValueError(
                'Requested time lies outside the range of the data: [{}, {}]s.'
                .format(*self.time_range))

        # slice data for selected time point
        time = self.time_slices[index]
        f_profile_psin = self._f.dimensions[1].data
        f_profile_magnitude = self._f.data[index, :]
        psi_lcfs = self._psi_lcfs.data[index]
        psi_axis = self._psi_axis.data[index]
        axis_coord = Point2D(self._axis_coord_r.data[index],
                             self._axis_coord_z.data[index])
        b_vacuum_magnitude = self._b_vacuum_magnitude.data[index]
        lcfs_poly_r = self._lcfs_poly_r.data[index, :]
        lcfs_poly_z = self._lcfs_poly_z.data[index, :]

        # slice and reshape psi data for specified time point
        # the original data is 3D, packed into a 2D array, this must be reshaped
        psi = np.reshape(self._packed_psi.data[index, :],
                         (len(self._r.data), len(self._z.data)),
                         order='F')

        # convert raw lcfs poly coordinates into a polygon object
        lcfs_polygon = self._process_efit_lcfs_polygon(lcfs_poly_r,
                                                       lcfs_poly_z)

        return EFITEquilibrium(self._r, self._z, psi, psi_axis, psi_lcfs,
                               axis_coord, f_profile_psin, f_profile_magnitude,
                               B_VACUUM_RADIUS, b_vacuum_magnitude,
                               lcfs_polygon, time)
コード例 #14
0
    def time(self, time):
        """
        Returns an equilibrium object for the time-slice closest to the requested time.
        The specific time-slice returned is held in the time attribute of the returned object.
        :param time: The equilibrium time point.
        :returns: An EFITEquilibrium object.
        """
        time_index, time_slice = self._find_nearest(self._time_slice, time)

        r = self._r[time_index, :]  # get the R coords for psi_grid
        z = self._z[time_index, :]  # get the Z coords for psi_grid

        psi_grid = self._psi_grid[time_index, :, :]
        psi_axis = self._psi_axis[time_index]
        psi_lcfs = self._psi_lcfs[time_index]

        magnetic_axis = Point2D(self._magnetic_axis_r[time_index],
                                self._magnetic_axis_z[time_index])

        b_vacuum_radius = self._b_vacuum_radius
        b_vacuum_magnitude = self._b_vacuum_magnitude[time_index]

        lcfs_polygon = self._process_efit_polygon(self._lcfs_r[time_index, :],
                                                  self._lcfs_z[time_index, :])

        limiter_polygon = self._process_efit_polygon(self._limiter_r[time_index, :],
                                                     self._limiter_z[time_index, :])

        strikepoints = self._process_efit_points(self._strikepoint_r[time_index, :],
                                                 self._strikepoint_z[time_index, :])

        xpoints = self._process_efit_points(self._xpoint_r[time_index, :],
                                            self._xpoint_z[time_index, :])

        f_profile = np.array([self._psin, self._rBphi[time_index, :]])

        equilibrium = EFITEquilibrium(r=r, z=z, psi_grid=psi_grid, psi_axis=psi_axis,
                                      psi_lcfs=psi_lcfs, magnetic_axis=magnetic_axis,
                                      x_points = xpoints, strike_points=strikepoints,
                                      f_profile=f_profile, b_vacuum_radius=b_vacuum_radius,
                                      b_vacuum_magnitude=b_vacuum_magnitude,
                                      lcfs_polygon=lcfs_polygon, limiter_polygon=limiter_polygon,
                                      time=time_slice)

        return equilibrium
コード例 #15
0
def load_standard_voxel_grid(system,
                             parent=None,
                             name='',
                             voxel_range=None,
                             primitive_type='csg'):
    """
    Load the standard bolometry reconstruction grid.

    :param system: the name of the bolometer system used
    Currently 'core', 'core_high_res' and 'sxdl' are supported.
    :param parent: the parent node for the grid object.
    :param name: the name of the grid object
    :param voxel_range: if not none, return a subset of the
    grid cells, `voxels[voxel_range]`. Can be either a slice object or
    a range object.
    :param str primitive_type: specifies the representation type of the
    voxels in the grid. 'mesh' and 'csg' are supported. 'mesh' generally
    works well but can have extremely high memory usage on higher
    resolution grids, whereas 'csg' has much lower memory usage but can
    be slower on grids with many non-rectilinear voxels. Both types
    support voxels with arbitrary polygon cross sections.

    Before this function is called, the corresponding pickle file for the
    grid must have already been generated. This can be done by running the
    `/examples/bholometry/grid_generation/make_<system>_grid.py` scripts.
    """

    directory = os.path.split(__file__)[0]

    grid_file = os.path.join(directory,
                             '{}_rectilinear_grid.pickle'.format(system))

    with open(grid_file, 'rb') as f:
        grid_data = pickle.load(f)
    grid_voxels = grid_data['voxels']
    if voxel_range is not None:
        grid_voxels = grid_voxels[voxel_range]
    voxel_list = [[Point2D(*vertex) for vertex in voxel]
                  for voxel in grid_voxels]
    grid = ToroidalVoxelGrid(voxel_list,
                             parent=parent,
                             name=name,
                             primitive_type=primitive_type)
    return grid
コード例 #16
0
def rad_function(r, z):

    sample_point = Point2D(r, z)
    direction = PLASMA_AXIS.vector_to(sample_point)
    bearing = np.arctan2(direction.y, direction.x)

    # calculate radius of coordinate from magnetic axis
    radius_from_axis = direction.length
    closest_ring_point = PLASMA_AXIS + (direction.normalise() * 0.5)
    radius_from_ring = sample_point.distance_to(closest_ring_point)

    # evaluate pedestal-> core function
    if radius_from_axis <= LCFS_RADIUS:

        central_radiatior = RADIATION_PEAK * np.exp(
            -(radius_from_axis**2) / CENTRE_PEAK_WIDTH)

        ring_radiator = RADIATION_PEAK * np.cos(bearing) * np.exp(
            -(radius_from_ring**2) / RING_WIDTH)
        ring_radiator = max(0, ring_radiator)

        return central_radiatior + ring_radiator
    else:
        return 0
コード例 #17
0
ファイル: wall_from_polygon.py プロジェクト: cherab/core
import numpy as np
from raysect.core import Point2D
from raysect.primitive import export_obj

from cherab.tools.primitives import axisymmetric_mesh_from_polygon

PLASMA_AXIS = Point2D(1.5, 0)
LCFS_RADIUS = 1
RING_RADIUS = 0.5

RADIATION_PEAK = 1
CENTRE_PEAK_WIDTH = 0.05
RING_WIDTH = 0.025

# distance of wall from LCFS
WALL_LCFS_OFFSET = 0.1

CYLINDER_RADIUS = PLASMA_AXIS.x + LCFS_RADIUS + WALL_LCFS_OFFSET * 1.1
CYLINDER_HEIGHT = (LCFS_RADIUS + WALL_LCFS_OFFSET) * 2
WALL_RADIUS = LCFS_RADIUS + WALL_LCFS_OFFSET

##########################################
# make toroidal wall wrapping the plasma #

# number of poloidal wall elements
num = 250
d_angle = (2 * np.pi) / num

wall_polygon = np.zeros((num, 2))
for i in range(num):
    pr = PLASMA_AXIS.x + WALL_RADIUS * np.sin(d_angle * i)
コード例 #18
0
    def __init__(self, pulse):

        self.client = pyuda.Client()  # get the pyuda client

        # Poloidal magnetic flux per toroidal radian as a function of (Z,R) and timebase
        self.psi = self.client.get("efm_psi(r,z)", pulse)

        self.time_slices = self.psi.dims[0].data

        # Psi grid axes f(nr), f(nz)
        self.r = self.client.get("efm_grid(r)", pulse)
        self.z = self.client.get("efm_grid(z)", pulse)

        # f profile
        self.f = self.client.get("efm_f(psi)_(c)", pulse)# Poloidal current flux function, f=R*Bphi; f(psin, C)

        # q profile
        self.q = self.client.get("efm_q(psi)_(c)", pulse)

        self.psi_r = self.client.get("efm_psi(r)", pulse) #poloidal magnetic flux per toroidal radian as a function of radius at Z=0

        # Poloidal magnetic flux per toroidal radian at the plasma boundary and magnetic axis
        self.psi_lcfs = self.client.get("efm_psi_boundary", pulse)
        self.psi_axis = self.client.get("efm_psi_axis", pulse)

        # Plasma current
        self.plasma_current = self.client.get("efm_plasma_curr(C)", pulse)

        # Reference vaccuum toroidal B field at R = efm_bvac_r
        self.b_vacuum_magnitude = self.client.get("efm_bvac_val", pulse)

        self.b_vacuum_radius = self.client.get("efm_bvac_r", pulse)

        # Magnetic axis co-ordinates
        self.axis_coord_r = self.client.get("efm_magnetic_axis_r", pulse)
        self.axis_coord_z = self.client.get("efm_magnetic_axis_z", pulse)

        # X point coordinates
        xpoint1r = self.client.get("efm_xpoint1_r(c)", pulse).data
        xpoint1z = self.client.get("efm_xpoint1_z(c)", pulse).data
        xpoint2r = self.client.get("efm_xpoint2_r(c)", pulse).data
        xpoint2z = self.client.get("efm_xpoint2_z(c)", pulse).data
        self.xpoints = [
            (Point2D(r1, z1), Point2D(r2, z2))
            for (r1, z1, r2, z2) in zip(xpoint1r, xpoint1z, xpoint2r, xpoint2z)
        ]

        #minor radius
        self.minor_radius = self.client.get("efm_minor_radius", pulse)

        #lcfs boundary polygon
        self.lcfs_poly_r = self.client.get("efm_lcfs(r)_(c)", pulse)
        self.lcfs_poly_z = self.client.get("efm_lcfs(z)_(c)", pulse)

        # Number of LCFS co-ordinates
        self.nlcfs = self.client.get("efm_lcfs(n)_(c)", pulse)

        # limiter boundary polygon
        self.limiter_poly_r = self.client.get("efm_limiter(r)", pulse)
        self.limiter_poly_z = self.client.get("efm_limiter(z)", pulse)

        # Number of limiter co-ordinates
        self.nlimiter = self.client.get("efm_limiter(n)", pulse)

        # time slices when plasma is present
        self.plasma_times = self.client.get("efm_ip_times", pulse)

        self.time_range = self.time_slices.min(), self.time_slices.max()
コード例 #19
0
    def time(self, time):
        """
        Returns an equilibrium object for the time-slice closest to the requested time.

        The specific time-slice returned is held in the time attribute of the returned object.

        :param time: The equilibrium time point.
        :returns: An EFIT Equilibrium object.
        """

        # locate the nearest time point and fail early if we are outside the time range of the data

        try:
            index = self._find_nearest(self.time_slices, time)
            # Find the index in the time array defined as when the plasma is present
            plasma_index = self._find_nearest(self.plasma_times.data, time)
        except IndexError:
            raise ValueError('Requested time lies outside the range of the data: [{}, {}]s.'.format(*self.time_range))

        b_vacuum_radius = self.b_vacuum_radius.data[index]

        time = self.time_slices[index]

        psi = np.transpose(self.psi.data[index,:,:]) #transpose psi to get psi(R,Z) instead of psi(Z,R)

        psi_lcfs = self.psi_lcfs.data[plasma_index]

        psi_axis = self.psi_axis.data[plasma_index]

        print('psi_axis', psi_axis)

        f_profile_psin = self.f.dims[1].data
        self.f_profile_psin = f_profile_psin
        f_profile_magnitude = self.f.data[plasma_index, :]
        f_profile = np.asarray([f_profile_psin, f_profile_magnitude])

        q_profile_magnitude = self.q.data[plasma_index]
        q_profile_psin = self.q.dims[1].data
        q_profile = np.asarray([q_profile_psin, q_profile_magnitude])

        axis_coord = Point2D(self.axis_coord_r.data[plasma_index], self.axis_coord_z.data[plasma_index])

        b_vacuum_magnitude = self.b_vacuum_magnitude.data[index]

        lcfs_poly_r = self.lcfs_poly_r.data[plasma_index,:]
        lcfs_poly_z = self.lcfs_poly_z.data[plasma_index,:]

        # Get the actual co-ordinates of the LCFS
        lcfs_points = self.nlcfs.data[plasma_index]

        #Filter out padding in the LCFS coordinate arrays
        lcfs_poly_r = lcfs_poly_r[0:lcfs_points]
        lcfs_poly_z = lcfs_poly_z[0:lcfs_points]

        # convert raw lcfs poly coordinates into a polygon object
        lcfs_polygon = self._process_efit_lcfs_polygon(lcfs_poly_r, lcfs_poly_z)
        lcfs_polygon = np.ascontiguousarray(lcfs_polygon.T)  # 2xN contiguous
        self.lcfs_polygon = lcfs_polygon

        limiter_poly_r = self.limiter_poly_r.data.squeeze()
        limiter_poly_z = self.limiter_poly_z.data.squeeze()

        # Get the actual co-ordinates of the limiter
        limiter_points = self.nlimiter.data.item()

        #Filter out padding in the LIMITER coordinate arrays
        limiter_poly_r = limiter_poly_r[0:limiter_points]
        limiter_poly_z = limiter_poly_z[0:limiter_points]

        # convert raw limiter poly coordinates into a polygon object
        limiter_polygon = self._process_efit_lcfs_polygon(limiter_poly_r, limiter_poly_z)
        limiter_polygon = np.ascontiguousarray(limiter_polygon.T)  # 2xN contiguous
        self.limiter_polygon = limiter_polygon

        r = self.r.data.squeeze()
        z = self.z.data.squeeze()

        xpoints = self.xpoints[plasma_index]

        # MAST-U EFIT has no reliably-available strike point data (ASF not always available)
        strike_points = []

        minor_radius = self.minor_radius.data[plasma_index]

        print('minor radius', minor_radius)

        return EFITEquilibrium(r, z, psi, psi_axis, psi_lcfs, axis_coord,
                               xpoints, strike_points, f_profile, q_profile,
                               b_vacuum_radius, b_vacuum_magnitude,
                               lcfs_polygon, limiter_polygon, time)
コード例 #20
0
# HFS mapping
footprint = Eich(1, 0.0001)  # lambda_q=2.5, S=0.5

x = np.linspace(-1, 10, 100)
footprint.set_coordinates(x)
footprint.s_disconnected_dn_max = 2.1
footprint.fx_in_out = 5.
footprint.calculate_heat_flux_density("hfs")

field_tracer = FieldlineTracer(b_field,
                               method=RK2(step_size=0.0001,
                                          direction="negative"))

# HFS interface
POINT_A = Point2D(0.25, -0.5)
POINT_B = Point2D(0.3304, -0.5833)
power_profile = sample_power_at_surface(POINT_A,
                                        POINT_B,
                                        equilibrium,
                                        footprint,
                                        lcfs_radii_min=0.15,
                                        lcfs_radii_max=0.25,
                                        side="HFS")

interface_power = 5e5  # 0.5MW
angle_period = 45

interface_surface = InterfaceSurface(POINT_A, POINT_B, power_profile,
                                     interface_power)
interface_surface.map_power(interface_power,
コード例 #21
0
def plot_kernel(kernel, voxel_vertices):
    """Plot a 1D grid function as a 2D image"""
    voxels = [[Point2D(p[0], p[1]) for p in voxel] for voxel in voxel_vertices]
    grid = ToroidalVoxelGrid(voxels)
    grid.plot(voxel_values=abs(kernel))
    plt.show()
コード例 #22
0
ファイル: MASTU_equilibrium.py プロジェクト: sgibson-mse/MSE
    def time(self, time):
        """
        Returns an equilibrium object for the time-slice closest to the requested time.

        The specific time-slice returned is held in the time attribute of the returned object.

        :param time: The equilibrium time point.
        :returns: An EFIT Equilibrium object.
        """

        # locate the nearest time point and fail early if we are outside the time range of the data

        try:
            index = self._find_nearest(self.time_slices, time)
            # Find the index in the time array defined as when the plasma is present
            plasma_index = self._find_nearest(self.plasma_times.data, time)
        except IndexError:
            raise ValueError(
                'Requested time lies outside the range of the data: [{}, {}]s.'
                .format(*self.time_range))

        B_VACUUM_RADIUS = self.b_vacuum_radius.data[index]

        time = self.time_slices[index]

        psi = np.transpose(self.psi.data[
            index, :, :])  #transpose psi to get psi(R,Z) instead of psi(Z,R)

        psi_lcfs = self.psi_lcfs.data[plasma_index]

        psi_axis = self.psi_axis.data[plasma_index]

        print('psi_axis', psi_axis)

        psi_r = self.psi_r.data[:, plasma_index]

        f_profile_psin = self.f.dims[1].data
        self.f_profile_psin = f_profile_psin

        f_profile_magnitude = self.f.data[plasma_index, :]

        axis_coord = Point2D(self.axis_coord_r.data[plasma_index],
                             self.axis_coord_z.data[plasma_index])

        b_vacuum_magnitude = self.b_vacuum_magnitude.data[index]

        lcfs_poly_r = self.lcfs_poly_r.data[plasma_index, :]
        lcfs_poly_z = self.lcfs_poly_z.data[plasma_index, :]

        # Get the actual co-ordinates of the LCFS
        lcfs_points = self.nlcfs.data[plasma_index]

        #Filter out padding in the LCFS coordinate arrays
        lcfs_poly_r = lcfs_poly_r[0:lcfs_points]
        lcfs_poly_z = lcfs_poly_z[0:lcfs_points]

        # convert raw lcfs poly coordinates into a polygon object
        lcfs_polygon = self._process_efit_lcfs_polygon(lcfs_poly_r,
                                                       lcfs_poly_z)
        self.lcfs_polygon = lcfs_polygon

        r = self.r.data[0, :]
        z = self.z.data[0, :]

        minor_radius = self.minor_radius.data[plasma_index]

        print('minor radius', minor_radius)

        return EFITEquilibrium(r, z, psi, psi_axis, psi_lcfs, axis_coord,
                               f_profile_psin, f_profile_magnitude,
                               B_VACUUM_RADIUS, b_vacuum_magnitude,
                               lcfs_polygon, time)
コード例 #23
0
num_voxels = nx * ny

# Coordinate of vertices
xpoints = np.linspace(xrange[0], xrange[1], num=nx + 1)
ypoints = np.linspace(yrange[0], yrange[1], num=ny + 1)

grid_index_2D_to_1D_map = {}
grid_index_1D_to_2D_map = {}

grid_cells = []
unwrapped_cell_index = 0
for ix in range(nx - 1):
    for jy in range(ny - 1):

        p1 = Point2D(xpoints[ix], ypoints[jy])
        p2 = Point2D(xpoints[ix], ypoints[jy + 1])
        p3 = Point2D(xpoints[ix + 1], ypoints[jy + 1])
        p4 = Point2D(xpoints[ix + 1], ypoints[jy])

        if wall_mask(*p1) or wall_mask(*p2) or wall_mask(*p3) or wall_mask(
                *p4):
            grid_cells.append((p1, p2, p3, p4))
            grid_index_2D_to_1D_map[(ix, jy)] = unwrapped_cell_index
            grid_index_1D_to_2D_map[unwrapped_cell_index] = (ix, jy)
            unwrapped_cell_index += 1

num_cells = len(grid_cells)
cell_data = np.zeros((num_cells, 4, 2))
for i in range(num_cells):
    p1, p2, p3, p4 = grid_cells[i]
コード例 #24
0
ファイル: test_voxels.py プロジェクト: cherab/core
 def test_list_of_point2d(self):
     voxel_coords = [Point2D(*v) for v in RECTANGULAR_VOXEL_COORDS[0]]
     voxel = AxisymmetricVoxel(voxel_coords)
     for coord, vertex in zip(voxel_coords, voxel.vertices):
         self.assertEqual([coord[0], coord[1]], [vertex.x, vertex.y],
                          "Nx2 array coordinate mismatch")
コード例 #25
0
ファイル: mdsplus.py プロジェクト: traviskgray/solps
def load_mesh_from_mdsplus(mds_connection):
    """
    Load the SOLPS mesh geometry for a given MDSplus connection.

    :param mds_connection: MDSplus connection object. Already set to the SOLPS tree with pulse #ID.
    """

    # Load the R, Z coordinates of the cell vertices, original coordinates are (4, 38, 98)
    # re-arrange axes (4, 38, 98) => (98, 38, 4)
    x = np.swapaxes(mds_connection.get('\TOP.SNAPSHOT.GRID:R').data(), 0, 2)
    z = np.swapaxes(mds_connection.get('\TOP.SNAPSHOT.GRID:Z').data(), 0, 2)

    vol = np.swapaxes(
        mds_connection.get('\SOLPS::TOP.SNAPSHOT.VOL').data(), 0, 1)

    # build mesh object
    mesh = SOLPSMesh(x, z, vol)

    #############################
    # Add additional parameters #
    #############################

    # add the vessel geometry
    mesh.vessel = mds_connection.get('\SOLPS::TOP.SNAPSHOT.GRID:VESSEL').data()

    # Load the centre points of the grid cells.
    cr = np.swapaxes(mds_connection.get('\TOP.SNAPSHOT.GRID:CR').data(), 0, 1)
    cz = np.swapaxes(mds_connection.get('\TOP.SNAPSHOT.GRID:CZ').data(), 0, 1)
    mesh._cr = cr
    mesh._cz = cz

    # Load cell basis vectors
    nx = mesh.nx
    ny = mesh.ny

    cell_poloidal_basis = np.empty((nx, ny, 2), dtype=object)
    for i in range(nx):
        for j in range(ny):

            # Work out cell's 2D parallel vector in the poloidal plane
            if i == nx - 1:
                # Special case for end of array, repeat previous calculation.
                # This is because I don't have access to the gaurd cells.
                xp_x = cr[i, j] - cr[i - 1, j]
                xp_y = cz[i, j] - cz[i - 1, j]
                norm = np.sqrt(xp_x**2 + xp_y**2)
                cell_poloidal_basis[i, j, 0] = Point2D(xp_x / norm,
                                                       xp_y / norm)
            else:
                xp_x = cr[i + 1, j] - cr[i, j]
                xp_y = cz[i + 1, j] - cz[i, j]
                norm = np.sqrt(xp_x**2 + xp_y**2)
                cell_poloidal_basis[i, j, 0] = Point2D(xp_x / norm,
                                                       xp_y / norm)

            # Work out cell's 2D radial vector in the poloidal plane
            if j == ny - 1:
                # Special case for end of array, repeat previous calculation.
                yr_x = cr[i, j] - cr[i, j - 1]
                yr_y = cz[i, j] - cz[i, j - 1]
                norm = np.sqrt(yr_x**2 + yr_y**2)
                cell_poloidal_basis[i, j, 1] = Point2D(yr_x / norm,
                                                       yr_y / norm)
            else:
                yr_x = cr[i, j + 1] - cr[i, j]
                yr_y = cz[i, j + 1] - cz[i, j]
                norm = np.sqrt(yr_x**2 + yr_y**2)
                cell_poloidal_basis[i, j, 1] = Point2D(yr_x / norm,
                                                       yr_y / norm)

    mesh._poloidal_grid_basis = cell_poloidal_basis

    return mesh
コード例 #26
0
##############################
# setup the heatflux profile #

# specify and load heatflux profile
footprint = Eich(1.0e-3, 0.0001e-3)

x = np.linspace(-0.001, 0.01, 100)
footprint.set_coordinates(x)
footprint.s_disconnected_dn_max = 2.1
footprint.fx_in_out = 5.
footprint.calculate_heat_flux_density("lfs")
footprint.plot_heat_power_density()

# make a mesh of the interface surface
interface_point_a = Point2D(0.345941, -0.593439)
interface_point_b = Point2D(0.51091, -0.757166)
interface_vector = interface_point_a.vector_to(interface_point_b)
interface_polygon = np.zeros((100, 2))
psi_on_interface = []
for i in range(100):
    point = interface_point_a + interface_vector * i / 100
    interface_polygon[i, :] = point.x, point.y
    psi_on_interface.append(psin2d(point.x, point.y))
interface_mesh = axisymmetric_mesh_from_polygon(interface_polygon)
interface_mesh.parent = world
interface_mesh.name = "interface_mesh"


# find LCFS midplane radius
def psin(r, offset=0):
コード例 #27
0
# interface_surface.map_power(interface_power, angle_period, field_tracer, world,
#                             num_of_fieldlines=5000, phi_offset=-angle_period/2, debug_output=True)


# HFS mapping
footprint = Eich(1, 0.0001)  # lambda_q=2.5, S=0.5

x = np.linspace(-1, 10, 100)
footprint.set_coordinates(x)
footprint.s_disconnected_dn_max = 2.1
footprint.fx_in_out = 5.
footprint.calculate_heat_flux_density("hfs")

field_tracer = FieldlineTracer(b_field, method=RK2(step_size=0.0001, direction="negative"))

# HFS interface
POINT_A = Point2D(0.25, -0.5)
POINT_B = Point2D(0.340, -0.600)
power_profile = sample_power_at_surface(POINT_A, POINT_B, equilibrium, footprint,
                                        lcfs_radii_min=0.15, lcfs_radii_max=0.25, side="HFS")

interface_power = 5e5  # 0.5MW
angle_period = 45

interface_surface = InterfaceSurface(POINT_A, POINT_B, power_profile, interface_power)
# new function
interface_surface.histogram_plot()

interface_surface.map_power(interface_power, angle_period, field_tracer, world,
                            num_of_fieldlines=5000, phi_offset=-angle_period/2, debug_output=True)
コード例 #28
0
    return [r_div, z_div, power]


##########################
# add machine components #

config_file = get_resource("ST40-IVC1", "configuration", 'st40_ivc1_config')

########################
# load the equilibrium #
eq = get_resource("ST40-IVC1", "equilibrium", "eq_006_2T_export")
fiesta = Fiesta(eq)

##############################
# setup the heatflux profile #

# specify and load heatflux profile
lcfs = fiesta.get_midplane_lcfs(psi_p=1.00001)[1]
footprint = Eich(1.0e-3, 0.0001e-3, r0_lfs=lcfs)  # lambda_q=2.5, S=0.5

x = np.linspace(-1, 10, 100) * 1e-3
footprint.set_coordinates(x)
footprint.calculate_heat_flux_density("lfs")

POINT_A = Point2D(0.345941, -0.593439)
POINT_B = Point2D(0.51091, -0.757166)
power_profile = sample_power_at_surface(POINT_A, POINT_B, fiesta, footprint)
s = np.sqrt(power_profile[0]**2 +
            power_profile[1]**2) - np.sqrt(POINT_A[0]**2 + POINT_A[1]**2)
plt.plot(s, power_profile[2] / max(power_profile[2]) * 40)
コード例 #29
0
ファイル: mapping_ivc1.py プロジェクト: daniel-iglesias/core
equilibrium = fiesta.to_cherab_equilibrium()
psin2d = equilibrium.psi_normalised

##############################
# setup the heatflux profile #

# specify and load heatflux profile
footprint = Eich(1, 0.0001)  # lambda_q=2.5, S=0.5

x = np.linspace(-1, 10, 100)
footprint.set_coordinates(x)
footprint.s_disconnected_dn_max = 2.1
footprint.fx_in_out = 5.
footprint.calculate_heat_flux_density("lfs")

POINT_A = Point2D(0.340, -0.600)
POINT_B = Point2D(0.500, -0.810)
power_profile = sample_power_at_surface(POINT_A, POINT_B, equilibrium,
                                        footprint)
interface_power = 1e6  # 1MW
angle_period = 45

interface_surface = InterfaceSurface(POINT_A, POINT_B, power_profile,
                                     interface_power)
# new function
interface_surface.histogram_plot()

interface_surface.map_power(interface_power,
                            angle_period,
                            field_tracer,
                            world,
コード例 #30
0
equilibrium = fiesta.to_cherab_equilibrium()
psin2d = equilibrium.psi_normalised

##############################
# setup the heatflux profile #

# specify and load heatflux profile
footprint = Eich(2.5, 0.5)  # lambda_q=2.5, S=0.5

x = np.linspace(-1, 10, 100)
footprint.set_coordinates(x)
footprint.s_disconnected_dn_max = 2.1
footprint.fx_in_out = 5.
footprint.calculate_heat_flux_density("lfs")

POINT_A = Point2D(0.44, -0.79)
POINT_B = Point2D(0.57, -0.798)
power_profile = sample_power_at_surface(POINT_A, POINT_B, equilibrium,
                                        footprint)
interface_power = 1e6  # 1MW
angle_period = 45

interface_surface = InterfaceSurface(POINT_A, POINT_B, power_profile,
                                     interface_power)
interface_surface.map_power(interface_power,
                            angle_period,
                            field_tracer,
                            world,
                            num_of_fieldlines=100,
                            debug_output=True)