-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds utility for building the 'magnet surface' and shooting rays at it #142
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
from parastell.radial_distance_utils import * | ||
|
||
coils_file = "coils_wistelld.txt" | ||
circ_cross_section = ["circle", 25] | ||
toroidal_extent = 90.0 | ||
vmec_file = "plasma_wistelld.nc" | ||
vmec = read_vmec.VMECData(vmec_file) | ||
|
||
magnet_set = magnet_coils.MagnetSet( | ||
coils_file, circ_cross_section, toroidal_extent | ||
) | ||
|
||
reordered_filaments = get_reordered_filaments(magnet_set) | ||
|
||
build_magnet_surface(reordered_filaments) | ||
|
||
toroidal_angles = np.linspace(0, 90, 72) | ||
poloidal_angles = np.linspace(0, 360, 96) | ||
wall_s = 1.08 | ||
|
||
radial_build_dict = {} | ||
|
||
radial_build = ivb.RadialBuild( | ||
toroidal_angles, poloidal_angles, wall_s, radial_build_dict | ||
) | ||
build = ivb.InVesselBuild(vmec, radial_build, split_chamber=False) | ||
build.populate_surfaces() | ||
build.calculate_loci() | ||
ribs = build.Surfaces["chamber"].Ribs | ||
radial_distances = measure_radial_distance(ribs) | ||
np.savetxt("radial_distances.csv", radial_distances, delimiter=",") |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,156 @@ | ||||||||||||||||||||||||||||||
import numpy as np | ||||||||||||||||||||||||||||||
from . import magnet_coils | ||||||||||||||||||||||||||||||
from . import invessel_build as ivb | ||||||||||||||||||||||||||||||
import pystell.read_vmec as read_vmec | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
import cubit | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def calc_z_radius(point): | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
Calculate the distance from the z axis. | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Arguments: | ||||||||||||||||||||||||||||||
point (iterable of [x,y,z] float): point to find distance for | ||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||
(float): distance to z axis. | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
return (point[0] ** 2 + point[1] ** 2) ** 0.5 | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def get_start_index(filament): | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
Find the index at which the filament crosses the xy plane on the OB | ||||||||||||||||||||||||||||||
side of the filament | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Arguments: | ||||||||||||||||||||||||||||||
filament (list of list of float): List of points defining the filament | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||
max_z_index (int): index at which the filament crosses the xy plane | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
max_z_index = None | ||||||||||||||||||||||||||||||
max_z_radius = 0 | ||||||||||||||||||||||||||||||
for index, (point, next_point) in enumerate( | ||||||||||||||||||||||||||||||
zip(filament[0:-1], filament[1:]) | ||||||||||||||||||||||||||||||
): | ||||||||||||||||||||||||||||||
if point[2] / next_point[2] < 0: | ||||||||||||||||||||||||||||||
z_radius = calc_z_radius(point) | ||||||||||||||||||||||||||||||
if max_z_radius < z_radius: | ||||||||||||||||||||||||||||||
max_z_index = index | ||||||||||||||||||||||||||||||
max_z_radius = z_radius | ||||||||||||||||||||||||||||||
return max_z_index | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def sort_filaments_toroidally(filaments): | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
Reorder filaments in order of increasing toroidal angle | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Arguments: | ||||||||||||||||||||||||||||||
filaments (list of list of list of float): List of filaments, which are | ||||||||||||||||||||||||||||||
lists of points defining each filament. | ||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||
filaments (list of list of list of float): filaments in order of | ||||||||||||||||||||||||||||||
increasing toroidal angle. | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
com_list = np.zeros((len(filaments), 3)) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
for idx, fil in enumerate(filaments): | ||||||||||||||||||||||||||||||
com_list[idx] = np.average(fil, axis=0) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
phi_arr = np.arctan2(com_list[:, 1], com_list[:, 0]) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
filaments = np.array([x for _, x in sorted(zip(phi_arr, filaments))]) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
return filaments | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def reorder_filaments(filaments): | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
Reorder the filaments so they start near the outboard xy plane crossing, | ||||||||||||||||||||||||||||||
and begin by increasing z value. | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
Arguments: | ||||||||||||||||||||||||||||||
filaments (list of list of list of float): List of filaments, which are | ||||||||||||||||||||||||||||||
lists of points defining each filament. | ||||||||||||||||||||||||||||||
Returns: | ||||||||||||||||||||||||||||||
filaments (list of list of list of float): Reordered list of filaments, | ||||||||||||||||||||||||||||||
suitable for building the magnet surface. | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
for filament_index, filament in enumerate(filaments): | ||||||||||||||||||||||||||||||
# start the filament at the outboard | ||||||||||||||||||||||||||||||
max_z_index = get_start_index(filament) | ||||||||||||||||||||||||||||||
reordered_filament = np.concatenate( | ||||||||||||||||||||||||||||||
[filament[max_z_index:], filament[1:max_z_index]] | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
# make sure z is increasing initially | ||||||||||||||||||||||||||||||
if reordered_filament[0, 2] > reordered_filament[1, 2]: | ||||||||||||||||||||||||||||||
reordered_filament = np.flip(reordered_filament, axis=0) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
# ensure filament is a closed loop | ||||||||||||||||||||||||||||||
reordered_filament = np.concatenate( | ||||||||||||||||||||||||||||||
[reordered_filament, [reordered_filament[0]]] | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
filaments[filament_index] = reordered_filament | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
filaments = sort_filaments_toroidally(filaments) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
return filaments | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def get_reordered_filaments(magnet_set): | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
Convenience function to get the reordered filament data from a magnet | ||||||||||||||||||||||||||||||
""" | ||||||||||||||||||||||||||||||
magnet_set._extract_filaments() | ||||||||||||||||||||||||||||||
magnet_set._set_average_radial_distance() | ||||||||||||||||||||||||||||||
magnet_set._set_filtered_filaments() | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
filtered_filaments = magnet_set.filtered_filaments | ||||||||||||||||||||||||||||||
filaments = reorder_filaments(filtered_filaments) | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
return filaments | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def build_magnet_surface(reordered_filaments): | ||||||||||||||||||||||||||||||
for fil1, fil2 in zip(reordered_filaments[0:-1], reordered_filaments[1:]): | ||||||||||||||||||||||||||||||
for index, _ in enumerate(fil1): | ||||||||||||||||||||||||||||||
x1 = fil1[index, 0] | ||||||||||||||||||||||||||||||
x2 = fil2[index, 0] | ||||||||||||||||||||||||||||||
y1 = fil1[index, 1] | ||||||||||||||||||||||||||||||
y2 = fil2[index, 1] | ||||||||||||||||||||||||||||||
z1 = fil1[index, 2] | ||||||||||||||||||||||||||||||
z2 = fil2[index, 2] | ||||||||||||||||||||||||||||||
cubit.cmd( | ||||||||||||||||||||||||||||||
f"create curve location {x1} {y1} {z1} location {x2} {y2} {z2}" | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How about this?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. need to use list comprehension to make a list of str first but this will work. join() doesn't like to operate on iterables of things that are not str seems like |
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
loops = np.array(cubit.get_entities("curve")) | ||||||||||||||||||||||||||||||
Edgar-21 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
loops = np.reshape( | ||||||||||||||||||||||||||||||
loops, (len(reordered_filaments) - 1, len(reordered_filaments[0])) | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
for loop in loops: | ||||||||||||||||||||||||||||||
for line in loop[0:-1]: | ||||||||||||||||||||||||||||||
cubit.cmd(f"create surface skin curve {line} {line + 1}") | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
def measure_radial_distance(ribs): | ||||||||||||||||||||||||||||||
distances = [] | ||||||||||||||||||||||||||||||
for rib in ribs: | ||||||||||||||||||||||||||||||
distance_subset = [] | ||||||||||||||||||||||||||||||
for point, direction in zip(rib.rib_loci, rib._normals()): | ||||||||||||||||||||||||||||||
cubit.cmd(f"create vertex {point[0]} {point[1]} {point[2]}") | ||||||||||||||||||||||||||||||
vertex_id = cubit.get_last_id("vertex") | ||||||||||||||||||||||||||||||
cubit.cmd( | ||||||||||||||||||||||||||||||
f"create curve location at vertex {vertex_id} " | ||||||||||||||||||||||||||||||
f"location fire ray location at vertex {vertex_id} " | ||||||||||||||||||||||||||||||
f"direction {direction[0]} {direction[1]} {direction[2]} at " | ||||||||||||||||||||||||||||||
"surface all maximum hits 1" | ||||||||||||||||||||||||||||||
) | ||||||||||||||||||||||||||||||
curve_id = cubit.get_last_id("curve") | ||||||||||||||||||||||||||||||
distance = cubit.get_curve_length(curve_id) | ||||||||||||||||||||||||||||||
distance_subset.append(distance) | ||||||||||||||||||||||||||||||
distances.append(distance_subset) | ||||||||||||||||||||||||||||||
return np.array(distances) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if the max z point isn't where the filament crosses the x-y plane?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this is a poor variable name. It's called max_z_radius because its should end up being the point where it crosses the x-y plane with the larger distance to the z axis (has the larger radius if the center is the z axis) of the two crossings, not anything to do with the actual z value of the points. The if statement above checks for a sign change in z between the two points, and only checks for what the z radius is if there is a sign change (crosses the xy plane). I'll rename these to something hopefully a bit clearer.