Skip to content

Commit

Permalink
Merge pull request #357 from fusion-energy/adding_animation
Browse files Browse the repository at this point in the history
started animation of spherical
  • Loading branch information
shimwell authored Dec 11, 2024
2 parents 833b994 + 90f7dfe commit fcdbd13
Show file tree
Hide file tree
Showing 6 changed files with 365 additions and 2 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -175,4 +175,7 @@ src/_version.py
*.stp
*.sql
*.html
*.png

*.png
*.gif
*.svg
Binary file added docs/_static/spherical_tokamak_animation.mp4
Binary file not shown.
Binary file added docs/_static/tokamak_animation.mp4
Binary file not shown.
19 changes: 18 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,24 @@ Paramak provides parameter driven creation of Tokamak and Spherical Tokamak CAD

The style of reaction, sizes of components, plasma shape and number of radial or vertical layers can be specified,


.. raw:: html

<div style="display: flex; justify-content: center;">
<video width="45%" controls autoplay loop>
<source src="_static/spherical_tokamak_animation.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
<video width="45%" controls autoplay loop>
<source src="_static/tokamak_animation.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</div>

.. video:: _static/tokamak_animation.mp4
:alt: Spherical Tokamak Animation
:align: center
:autoplay: true
:loop: true

.. grid:: 1 1 3 3
:gutter: 2
Expand Down
168 changes: 168 additions & 0 deletions examples/spherical_tokamak_from_plasma_animation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import paramak
import cadquery_png_plugin.plugin
import numpy as np
import cadquery as cq

# Original radial build values
original_radial_build = [
(paramak.LayerType.GAP, 55),
(paramak.LayerType.SOLID, 50),
(paramak.LayerType.SOLID, 15),
(paramak.LayerType.GAP, 50),
(paramak.LayerType.PLASMA, 300),
(paramak.LayerType.GAP, 60),
(paramak.LayerType.SOLID, 15),
(paramak.LayerType.SOLID, 60),
(paramak.LayerType.SOLID, 10),
]
original_elongation = 2
original_triangularity = 0.55
original_n_tf_coils = 8
original_coil_height_factor = 1
original_divertor_thickness = 50

# Function to create a reactor with modified radial build
def create_reactor(
radial_build=original_radial_build,
elongation = original_elongation,
triangularity = original_triangularity,
n_tf_coils = original_n_tf_coils,
coil_height_factor = original_coil_height_factor,
divertor_thickness=original_divertor_thickness
):

reactor_diameter = sum([layer[1] for layer in radial_build])
minor_radius = radial_build[4][1]/2
major_radius = sum([layer[1] for layer in radial_build][:4])+minor_radius

theta = 3 * np.pi / 2
divertor_radius = major_radius + minor_radius * np.cos(theta + triangularity * np.sin(theta))

reactor_height = elongation * radial_build[4][1] * 0.5 + sum([layer[1] for layer in radial_build[5:]])

# makes a rectangle that overlaps the lower blanket under the plasma
# the intersection of this and the layers will form the lower divertor
points = [(divertor_radius-divertor_thickness, -2000), (divertor_radius-divertor_thickness, 0), (divertor_radius+divertor_thickness, 0), (divertor_radius+divertor_thickness, -2000)]
divertor_lower = cq.Workplane("XZ", origin=(0, 0, 0)).polyline(points).close().revolve(180)

tf_coils = paramak.toroidal_field_coil_rectangle(
horizontal_start_point=(10, reactor_height+5),
vertical_mid_point=(reactor_diameter+5,0),
thickness = 40,
distance = 50 ,
rotation_angle = 180.0,
name = "toroidal_field_coil",
with_inner_leg = True,
azimuthal_placement_angles=np.linspace(0, 180, n_tf_coils)
)

coils = [tf_coils]
for case_thickness, height, width, center_point in zip(
[10, 15, 15, 10],
[20, 50, 50, 20],
[20, 50, 50, 20],
[
(reactor_diameter+5+50+10+20/2, 300*coil_height_factor),
(reactor_diameter+5+50+15+50/2, 100*coil_height_factor),
(reactor_diameter+5+50+15+50/2, -100*coil_height_factor),
(reactor_diameter+5+50+10+20/2, -300*coil_height_factor)
]
):
coils.append(
paramak.poloidal_field_coil(
height=height, width=width,
center_point=center_point,
rotation_angle=180
)
)
coils.append(
paramak.poloidal_field_coil_case(
coil_height=height,
coil_width=width,
casing_thickness=case_thickness,
rotation_angle=180,
center_point=center_point
)
)

return paramak.spherical_tokamak_from_plasma(
radial_build=radial_build,
elongation=elongation,
triangularity=triangularity,
rotation_angle=180,
colors={
"layer_1": (0.4, 0.9, 0.4),
"layer_2": (0.6, 0.8, 0.6),
"plasma": (1., 0.7, 0.8, 0.6),
"layer_3": (0.1, 0.1, 0.9),
"layer_4": (0.4, 0.4, 0.8),
"layer_5": (0.5, 0.5, 0.8),
"add_extra_cut_shape_1": (0.6, 0.3, 0.4), # tf coils
"add_extra_cut_shape_2": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_3": (0.9, 0.4, 0.4), # pf coil case
"add_extra_cut_shape_4": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_5": (0.9, 0.4, 0.4), # pf coil case
"add_extra_cut_shape_6": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_7": (0.9, 0.4, 0.4), # pf coil case
"add_extra_cut_shape_8": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_9": (0.9, 0.4, 0.4), # pf coil case
"extra_intersect_shapes": (0.1, 0.1, 0.4), # divertor lower

},
extra_cut_shapes=coils,
extra_intersect_shapes=[divertor_lower]
)

# Function to export reactor to PNG
def export_reactor_to_png(reactor, file_path):
reactor.add(
cq.Workplane('XZ').text("Paramak", fontsize=200, distance=10
).translate((0, 0, -615)))
reactor.exportPNG(
options={
"width": int(1280/2),
"height": int(1024/2),
"zoom": 1.4,
},
file_path=file_path
)
print(f'written {file_path}')

# Generate reactors with varying radial build values
frame = 0
factors = [1.0, 1.25, 1.5, 1.75, 2.0, 1.75, 1.5, 1.25, 1.0]
for i in range(len(original_radial_build)):
layer_type, original_value = original_radial_build[i]
for factor in factors:
modified_radial_build = original_radial_build.copy()
modified_radial_build[i] = (layer_type, original_value * factor)
reactor = create_reactor(modified_radial_build)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for factor in factors:
modified_elongation = original_elongation * factor
reactor = create_reactor(elongation=modified_elongation)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for modified_triangularity in [0.55, 0.3667, 0.1833, 0.0, -0.1833, -0.3667, -0.55, -0.3667, -0.1833, 0.0, 0.1833, 0.3667, 0.55]:
reactor = create_reactor(triangularity=modified_triangularity)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for modified_n_tf_coils in [original_n_tf_coils, original_n_tf_coils -1 , original_n_tf_coils -2, original_n_tf_coils-3, original_n_tf_coils-2, original_n_tf_coils-1,original_n_tf_coils]:
reactor = create_reactor(n_tf_coils=modified_n_tf_coils)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for modified_coil_height_factor in [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.4, 1.3, 1.2, 1.1, 1]:
reactor = create_reactor(coil_height_factor=modified_coil_height_factor)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for factor in factors:
modified_divertor_thickness = original_divertor_thickness * factor
reactor = create_reactor(divertor_thickness=modified_divertor_thickness)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1
175 changes: 175 additions & 0 deletions examples/tokamak_from_plasma_animation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
import paramak
import imageio
import cadquery_png_plugin.plugin
import numpy as np
import cadquery as cq

original_radial_build=[
(paramak.LayerType.GAP, 40),
# (paramak.LayerType.SOLID, 30),
(paramak.LayerType.SOLID, 50),
(paramak.LayerType.SOLID, 10),
(paramak.LayerType.SOLID, 120),
(paramak.LayerType.SOLID, 20),
(paramak.LayerType.GAP, 60),
(paramak.LayerType.PLASMA, 300),
(paramak.LayerType.GAP, 60),
(paramak.LayerType.SOLID, 20),
(paramak.LayerType.SOLID, 120),
(paramak.LayerType.SOLID, 10),
]
original_elongation=4
original_triangularity=0.55
original_rotation_angle=180
original_n_tf_coils = 8
original_coil_height_factor = 1
original_divertor_thickness = 55

# Function to create a reactor with modified radial build
def create_reactor(
radial_build=original_radial_build,
elongation = original_elongation,
triangularity = original_triangularity,
n_tf_coils = original_n_tf_coils,
coil_height_factor = original_coil_height_factor,
divertor_thickness=original_divertor_thickness
):

reactor_diameter = sum([layer[1] for layer in radial_build])
minor_radius = radial_build[6][1]/2
major_radius = sum([layer[1] for layer in radial_build][:6])+minor_radius

theta = 3 * np.pi / 2
divertor_radius = major_radius + minor_radius * np.cos(theta + triangularity * np.sin(theta))
outer_blanket_thickness = sum([layer[1] for layer in radial_build[2:6]])
pf_radial_position = divertor_radius + outer_blanket_thickness + 40
reactor_height = 0.5*elongation * radial_build[6][1] + outer_blanket_thickness

# makes a rectangle that overlaps the lower blanket under the plasma
# the intersection of this and the layers will form the lower divertor
points = [(divertor_radius-divertor_thickness, -2000), (divertor_radius-divertor_thickness, 2000), (divertor_radius+divertor_thickness, 0), (divertor_radius+divertor_thickness, -700)]
divertor = cq.Workplane("XZ", origin=(0, 0, 0)).polyline(points).close().revolve(180)


tf_coils = paramak.toroidal_field_coil_princeton_d(
r2=reactor_diameter+30,
r1=10,
thickness = 40,
distance = 50 ,
rotation_angle = 180.0,
name = "toroidal_field_coil",
with_inner_leg = True,
azimuthal_placement_angles=np.linspace(0, 180, n_tf_coils)
)

coils = [tf_coils]
for case_thickness, height, width, center_point in zip(
[10, 15, 15, 10],
[20, 50, 50, 20],
[20, 50, 50, 20],
[
(pf_radial_position, reactor_height),
(reactor_diameter+5+50+15+50/2, 150*coil_height_factor),
(reactor_diameter+5+50+15+50/2, -150*coil_height_factor),
(pf_radial_position, -reactor_height)
]
):
coils.append(
paramak.poloidal_field_coil(
height=height, width=width,
center_point=center_point,
rotation_angle=180
)
)
coils.append(
paramak.poloidal_field_coil_case(
coil_height=height,
coil_width=width,
casing_thickness=case_thickness,
rotation_angle=180,
center_point=center_point
)
)

return paramak.tokamak_from_plasma(
radial_build=radial_build,
elongation=elongation,
triangularity=triangularity,
rotation_angle=180,
colors={
"layer_1": (0.4, 0.9, 0.4),
"layer_2": (0.6, 0.8, 0.6),
"plasma": (1., 0.7, 0.8, 0.6),
"layer_3": (0.1, 0.1, 0.9),
"layer_4": (0.4, 0.4, 0.8),
"layer_5": (0.5, 0.5, 0.8),
"add_extra_cut_shape_1": (0.6, 0.3, 0.4), # tf coils
"add_extra_cut_shape_2": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_3": (0.9, 0.4, 0.4), # pf coil case
"add_extra_cut_shape_4": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_5": (0.9, 0.4, 0.4), # pf coil case
"add_extra_cut_shape_6": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_7": (0.9, 0.4, 0.4), # pf coil case
"add_extra_cut_shape_8": (0.4, 0.9, 0.4), # pf coil
"add_extra_cut_shape_9": (0.9, 0.4, 0.4), # pf coil case
"extra_intersect_shapes": (0.1, 0.1, 0.4), # divertor lower

},
extra_cut_shapes=coils,
extra_intersect_shapes=[divertor]
)

# Function to export reactor to PNG
def export_reactor_to_png(reactor, file_path):
reactor.add(
cq.Workplane('XZ').text("Paramak", fontsize=200, distance=10
).translate((0, 0, -1215)))
reactor.exportPNG(
options={
"width": int(1280/2),
"height": int(1024/2),
"zoom": 1.25,
},
file_path=file_path
)
print(f'written {file_path}')


# Generate reactors with varying radial build values
frame = 0
factors = [1.0, 1.25, 1.5, 1.75, 2.0, 1.75, 1.5, 1.25, 1.0]
for i in range(len(original_radial_build)):
layer_type, original_value = original_radial_build[i]
for factor in factors:
modified_radial_build = original_radial_build.copy()
modified_radial_build[i] = (layer_type, original_value * factor)
reactor = create_reactor(modified_radial_build, original_elongation, original_triangularity, original_n_tf_coils, original_coil_height_factor)
export_reactor_to_png(reactor, f'tokamak_frame_{frame:03d}.png')
frame += 1

for factor in factors:
modified_elongation = original_elongation * factor
reactor = create_reactor(elongation=modified_elongation)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for modified_triangularity in [0.55, 0.3667, 0.1833, 0.0, -0.1833, -0.3667, -0.55, -0.3667, -0.1833, 0.0, 0.1833, 0.3667, 0.55]:
reactor = create_reactor(triangularity=modified_triangularity)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for modified_n_tf_coils in [original_n_tf_coils, original_n_tf_coils -1 , original_n_tf_coils -2, original_n_tf_coils-3, original_n_tf_coils-2, original_n_tf_coils-1,original_n_tf_coils]:
reactor = create_reactor(n_tf_coils=modified_n_tf_coils)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for modified_coil_height_factor in [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.4, 1.3, 1.2, 1.1, 1]:
reactor = create_reactor(coil_height_factor=modified_coil_height_factor)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

for factor in factors:
modified_divertor_thickness = original_divertor_thickness * factor
reactor = create_reactor(divertor_thickness=modified_divertor_thickness)
export_reactor_to_png(reactor, f'spherical_tokamak_frame_{frame:03d}.png')
frame += 1

0 comments on commit fcdbd13

Please sign in to comment.