示例#1
0
    def get_midplane_lcfs(self, psi_p=1.005):
        '''
        Function for getting the inner and outer radial position of the LCFS at the midplane

        input: self,  a reference to the object itself
               psi_p, the flux surface of the LCFS, standard is psi_p = 1.005 (otherwise the field-line
                      is located inside the LCFS)

        return: Rcross, a list with the outer and inner radial position of the mid-plane LCFS
        '''

        r_vec, z_vec = np.meshgrid(self.r_vec, self.z_vec)
        # Get contour
        cont = plt.contour(r_vec, z_vec, self.psi_n, [psi_p])
        cont = cont.allsegs[0]

        # Loop over the contours
        for c_i in cont:
            is_core = any(c_i[:, 1] > 0) * any(c_i[:, 1] < 0)
            if is_core:
                func1 = np.array((c_i[:, 0], c_i[:, 1]))
                func2 = np.array(
                    (np.array([0., np.max(r_vec)]), np.array([0., 0.])))
                (_, _), (r_lcfs, _) = intersection(func1, func2)

        plt.close()  # plt.contour opens a plot, close it

        return r_lcfs
示例#2
0
def project_heat_flux(heat_flux_profile_omp, surface_position, equilibrium):
    '''
    Function for projecting a heat flux from the OMP to a given surface (without taking diffusion
    into account)

    Input:  heat_flux_profile_omp, a 2-by-n numpy array, where heat_flux_profile_omp[0] is the radial
                                   coordinates of each point at the OMP and heat_flux_profile_omp[1]
                                   is the parallel heat flux at the corresponding radial points
            surface_position,      a 2-by-m numpy array with the surface_position[0] being the radial
                                   coordinates and surface_position[1] being the poloidal positions
            equilibrium,           a string with the equilibrium to load, e.g. eq_0002

    Return: heat_flux_at_intersection, a 3-by-n numpy array, where heat_flux_at_intersection[0]
                                       is the radial coordinates of each point at the target,
                                       heat_flux_at_intersection[1] is the vertical coordinates
                                       of each point at the target, and heat_flux_profile_omp[2]
                                       is the parallel heat flux at the corresponding positions
    '''
    x_after_lcfs = heat_flux_profile_omp[0]
    equlibrium_file = '../fiesta/' + equilibrium

    if pathlib.Path(equlibrium_file + '.pickle').exists():
        field_lines = load_pickle(equlibrium_file)
    else:
        field_lines = map_field_lines(x_after_lcfs, equlibrium_file)

    intersection_x = []
    intersection_y = []
    for i in field_lines:
        func1 = np.array((field_lines[i]['R'], field_lines[i]['Z']))
        (_, _), (x_at_surface, y_at_surface) = intersection(func1,
                                                            (surface_position))
        if np.isnan(x_at_surface):
            break
        intersection_x.append(x_at_surface[0])
        intersection_y.append(y_at_surface[0])

    intersection_x = np.array(intersection_x)
    intersection_y = np.array(intersection_y)

    not_in_div = len(intersection_x)
    x_after_lcfs = x_after_lcfs[:not_in_div]
    f_x = np.zeros(not_in_div)
    dist_div = np.sqrt(np.square(intersection_x[1:]-intersection_x[:-1])
                       + np.square(intersection_y[1:]-intersection_y[:-1]))
    f_x[0:-1] = (dist_div)/(x_after_lcfs[1:]-x_after_lcfs[:-1])
    f_x[-1] = f_x[-2]
    f_x = savgol_filter(f_x, 51, 3)
    q_div = x_after_lcfs/intersection_x * \
          heat_flux_profile_omp[1, :not_in_div]/f_x

    heat_flux_at_intersection = np.array([intersection_x, intersection_y, q_div])

    return heat_flux_at_intersection
示例#3
0
def map_field_lines(x_vec_at_omp, file_path, configuration='diverted'):
    '''
    Function for mapping each field-line to the intersection with the vessel walls

    Input: x_vec_at_omp,  a numpy array with the radial points at the OMP where
                          we want the mapping to start
           file_path,     a string with the path to the FIESTA equilibrium .mat file
           configuration, a string with either 'limited' or 'diverted', where 'diverted'
                          is the defualt configuration

    return: field_line_dict, a python dictionary with the radial position from the OMP in m
                             as the key and the field-line dictionary with the R, phi
                             and Z components along the field line as well as the length, l,
                             from the LCFS to the current point along the field-line
    '''
    field_line = FieldLine(file_path)
    field_line_dict = {}
    for i in x_vec_at_omp:
        field_lines = field_line.follow_field_in_plane(p_0=[i, 0, 0], max_length=10.0)

        func1 = np.array([field_lines["R"], field_lines["Z"]])
        func2 = np.array([field_line.fiesta_equil.r_limiter, field_line.fiesta_equil.z_limiter])

        (i_intersect_func1, _),\
        (r_intersect, z_intersect) = intersection(func1, func2)
        if not np.any(np.isnan(r_intersect)):
            i_int = int(np.floor(i_intersect_func1))
            i_first_intersect = np.argmin(field_lines["l"][i_int])
            i_intersection = i_intersect_func1[i_first_intersect]
            i_intersection = int(np.ceil(i_intersection))
            if configuration == 'limited':
                i_min_intersect = np.argmin(field_lines["R"][i_intersection] - r_intersect)
                i_intersection = np.where(field_lines["R"][:] < r_intersect[i_min_intersect])[0][0]
            elif configuration == 'diverted':
                i_min_intersect = np.argmin(field_lines["Z"][i_intersection] - z_intersect)
                i_intersection = np.where(field_lines["Z"][:] < z_intersect[i_min_intersect])[0][0]
            else:
                raise NotImplementedError("Error: unknown configuration.\
                                          Please use either 'limited' or 'diverted'")

            field_lines["l"] = field_lines["l"][:i_intersection+1]
            field_lines["R"] = field_lines["R"][:i_intersection+1]
            field_lines["Z"] = field_lines["Z"][:i_intersection+1]

            field_lines["Vessel_Intersect"] = (r_intersect[i_min_intersect],
                                               z_intersect[i_min_intersect])

            field_line_dict[i] = field_lines
        else:
            field_lines["Vessel_Intersect"] = (np.nan, np.nan)
            field_line_dict[i] = field_lines

    return field_line_dict
示例#4
0
def project_field_lines(x_axis_omp, surface_coords, fiesta):
    '''
    Function mapping the field-lines from the specified coordinates at the
    OMP to the specified coordinates at a given surface. Currently the surface
    is assumed to be represented by a 1D polynomial function, y = ax + b.

    Parameters
    ----------
    x_axis_omp : n-x-1 np.array
        Numpy array with the radial coordinates we wish to map at the OMP
    fiesta : Fiesta
        A Fiesta object with the 2D equilibrium we wish to map
    divertor_coords : 2-x-2 np.array
        A 2-x-2 numpy array containg the corner points of the divertor in the
        2D projection

    Returns
    -------
    divertor_map : dictionary
        A dictionary containing:
            "R_div" : an n-x-1 array
                with the R-coordinates at the divertor tile
                corresponding to the same psi_n as at the OMP
            "Z_div" : an n-x-1 array
                with the Z-coordinates at the divertor tile
                corresponding to the same psi_n as at the OMP
            "Angles" : an n-x-1 array
                with the angles between the field lines and the divertor tile
                corresponding to the same psi_n as at the OMP
            "Flux_expansion" : an n-x-1 array
                with the flux expasion at the divertor tile
                corresponding to the same psi_n as at the OMP

    '''
    # Interpolate b_pol (to be used when evaluating the flux expansion)
    b_pol = fiesta.b_theta.T
    b_pol_interp = Interpolate2DCubic(fiesta.r_vec, fiesta.z_vec, b_pol)

    field_lines = {}

    if os.path.exists("Random_filename"):
        field_lines = load_pickle("Random_filename")
    else:
        field_line = FieldLine(fiesta)
        for i in x_axis_omp:
            p_0 = [i, 0, 0]
            field_line_dict = field_line.follow_field_in_plane(p_0=p_0,
                                                               max_length=15.0)
            field_lines[i] = field_line_dict

    _v_2 = np.array([
        surface_coords[0, 1] - surface_coords[0, 0],
        surface_coords[1, 1] - surface_coords[1, 0]
    ])

    divertor_map = {}
    for i in field_lines:
        func1 = np.array((field_lines[i]['R'], field_lines[i]['Z']))
        (i_func1, _), (x_at_surface,
                       y_at_surface) = intersection(func1, (surface_coords))
        if np.isnan(x_at_surface):
            break

        _x_component = field_lines[i]['R'][int(i_func1)] - field_lines[i]['R'][
            int(i_func1) + 1]
        _y_component = field_lines[i]['Z'][int(i_func1)] - field_lines[i]['Z'][
            int(i_func1) + 1]
        _v_1 = [_x_component, _y_component]

        temp_dict = {}
        temp_dict["R_pos"] = x_at_surface[0]
        temp_dict["Z_pos"] = y_at_surface[0]
        temp_dict["alpha"] = calculate_angle(_v_1, _v_2)
        temp_dict["f_x"] = _flux_expansion(b_pol_interp, (i, 0),
                                           (x_at_surface[0], y_at_surface[0]))
        divertor_map[i] = temp_dict

    return divertor_map
示例#5
0
#f.gca().set_aspect('equal', adjustable='box')
#f.gca().set_ylim([-4,0])
#print (len(field_line_dict))

field_lines = []
for fl in field_line_dict:
    field_lines.append(np.array([fl['R'], fl['Z']]))

divertor_points = 3
#divertor_x = np.linspace( 1.9, 2.45,divertor_points)
#divertor_y = np.linspace(-3,-3.6,divertor_points)
divertor_x = np.array([0.385, 0.425, 0.49])
divertor_y = np.array([-0.9, -0.75, -0.6])
divertor_xy = np.array([divertor_x, divertor_y])

result = np.array([intersection(i, divertor_xy) for i in field_lines])
(x_p, y_p) = zip(*result[:, 1])

for i in field_line_dict:
    plt.plot(i['R'], i['Z'], c='r')
plt.plot(field_line.fiesta_equil.r_limiter, field_line.fiesta_equil.z_limiter)
plt.plot(divertor_x, divertor_y, c='g')
plt.plot(x_p, y_p, '*k')
plt.gca().set_aspect('equal', adjustable='box')
plt.gca().set_ylim([-1., -0.5])
plt.gca().set_xlim([0.0, 0.5])

imageFile = getOption('imageFile')
if imageFile:
    plt.savefig(imageFile)
else:
示例#6
0
def map_psi(fiesta_equil, divertor_pos, nr_segments=1000, end_segment=1./10.):
    '''
    Function for mapping the radial and poloidal positions to a given surface.

    Input: fiesta_equil, an object of the Fiesta class with the desired equilibrium
           divertor_pos, a 2-by-n numpy array with the coordinates for the surface we
                         wish to calculate the intersection with, where divertor_pos[0]
                         is the radial coordinates and divertor_pos[1] are the poloidal
                         coordinates
           nr_segments,  an integer with the number of contours we wish to evaluate,
                         essentially giving the resolution
           end_segment,  a float with the last psi_n you wish to evaluate, so
                         e.g. end_segment = 1./10 will set the last contour to
                         psi_n = 1.1

    return: psi_map,     a dictionary with:
                         'psi_n', the normalised flux surface position,
                         'R_omp', the radial position at the OMP,
                         'Z_omp', the vertical position at the OMP (all 0),
                         'R_div, the radial position of the intersection with
                         the specified surface,
                         'Z_div', the radial position of the intersection with
                         the specified surface
    '''
    r_vec, z_vec = np.meshgrid(fiesta_equil.r_vec, fiesta_equil.z_vec)

    lcfs_psi_n = 1
    psi_p = []
    for i in range(nr_segments):
        psi_p.append(lcfs_psi_n+i/nr_segments*end_segment)

    cont = plt.contour(r_vec, z_vec, fiesta_equil.psi_n, psi_p)
    cont = cont.allsegs
#    plt.close()

    r_omp = []
    z_omp = []
    omp_pos = np.array((np.array([0.0, 1.0]), np.array([0.0, 0.0])))
    r_div = []
    z_div = []
    psi = []
    i = 0
    for c_i in cont:
        c_i = c_i[0]
        is_core = any(c_i[:, 1] > 0)*any(c_i[:, 1] < 0)
        if is_core:
            psi_contour = np.array((c_i[:, 0], c_i[:, 1]))
            (_, _), (r_omp_intersect, z_omp_intersect) = intersection(psi_contour, omp_pos)
            (_, _), (r_div_intersect, z_div_intersect) = intersection(psi_contour, divertor_pos)
            r_omp.append(r_omp_intersect[1])
            z_omp.append(z_omp_intersect[1])
            r_div.append(r_div_intersect)
            z_div.append(z_div_intersect)
            psi.append(psi_p[i])
        i += 1

    psi_map = {}
    psi_map['R_div'] = r_div
    psi_map['Z_div'] = z_div
    psi_map['R_omp'] = r_omp
    psi_map['Z_omp'] = z_omp
    psi_map['psi_n'] = psi
    return psi_map
#f.gca().set_aspect('equal', adjustable='box')
#f.gca().set_ylim([-4,0])
#print (len(field_line_dict))

field_lines = []
for fl in field_line_dict:
    field_lines.append( np.array([ fl['R'], fl['Z'] ]) )

divertor_points = 3
#divertor_x = np.linspace( 1.9, 2.45,divertor_points)
#divertor_y = np.linspace(-3,-3.6,divertor_points)
divertor_x = np.array([1.2, 1.2, 1.15])
divertor_y = np.array([-1.5, -1.7, -2.05])
divertor_xy = np.array([divertor_x, divertor_y])

result = [intersection(i, divertor_xy) for i in field_lines]
x_p,y_p = zip (*result)

for i in field_line_dict:
    plt.plot(i['R'],i['Z'],c='r')
plt.plot(divertor_x,divertor_y,c='g')
#plt.plot(x_p,y_p,'*k')
plt.gca().set_aspect('equal', adjustable='box')
#plt.gca().set_ylim([-4,-2.5])
plt.show(block=True)

print(midplane_range)
fx = []
for i in range(len(midplane_range)-1):
    fx.append( math.hypot(x_p[i+1] - x_p[i], y_p[i+1] - y_p[i]) / 
              ( midplane_range[i+1] - midplane_range[i] ) *