diff --git a/.devcontainer/2_converting_cadquery_objects.ipynb b/.devcontainer/2_converting_cadquery_objects.ipynb new file mode 100644 index 00000000..597ebf15 --- /dev/null +++ b/.devcontainer/2_converting_cadquery_objects.ipynb @@ -0,0 +1,20 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Converting CadQuery objects\n", + "\n", + "In memory transfer" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 2db48c38..136acada 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -40,8 +40,8 @@ RUN cp tasks/task_08_CSG_mesh_tally/1_example_2d_regular_mesh_tallies.ipynb task RUN cp tasks/task_14_variance_reduction/2_shielded_room_single_ww.ipynb tasks/half-day-workshop/task_15_example_variane_shielded_room_ww_single_iteration.ipynb RUN cp tasks/task_14_variance_reduction/3_sphere_iterative_per_run_ww.ipynb tasks/half-day-workshop/task_16_example_variance_reduction_sphere_ww_multiple_iterations.ipynb RUN cp tasks/task_10_activation_transmutation_depletion/3_full_pulse_schedule.ipynb tasks/half-day-workshop/task_17_full_pulse_schedule.ipynb -RUN cp tasks/task_19_design_task/1_optimal_design.ipynb tasks/half-day-workshop/task_18_optimal_design.ipynb -RUN cp tasks/task_19_design_task/1_optimal_design_with_hints.ipynb tasks/half-day-workshop/task_18_optimal_designs_with_hints.ipynb +RUN cp tasks/task_21_design_task/1_optimal_design.ipynb tasks/half-day-workshop/task_18_optimal_design.ipynb +RUN cp tasks/task_21_design_task/1_optimal_design_with_hints.ipynb tasks/half-day-workshop/task_18_optimal_designs_with_hints.ipynb WORKDIR /tasks diff --git a/tasks/task_15_making_CAD_geometry/1_make_CAD_shapes_from_points.ipynb b/tasks/task_15_making_CAD_geometry/1_make_CAD_shapes_from_points.ipynb deleted file mode 100644 index 131e662c..00000000 --- a/tasks/task_15_making_CAD_geometry/1_make_CAD_shapes_from_points.ipynb +++ /dev/null @@ -1,285 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Part 1 - Making a parametric shape\n", - "\n", - "CAD geometry has a few advatanges over traditional Constructive Solid Geometry (CSG):\n", - "\n", - "- The ability to model curved spline surfaces.\n", - "- Implicit void creation so there is no need to define void cells.\n", - "\n", - "This notebook allows users to create a CAD model from coordinates / points.\n", - "\n", - "This geometry creation makes use of the Paramak package which has been designed to make neutronics ready CAD geometry for fusion reactors.\n", - "\n", - "The Paramak is:\n", - "\n", - " Open-source: https://github.com/fusion-energy/paramak\n", - " Documented: https://paramak.readthedocs.io\n", - " Published: https://f1000research.com/articles/10-27\n", - " Video presentation: https://www.youtube.com/watch?v=fXboew3U7rw" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import IFrame\n", - "IFrame(src=\"https://www.youtube.com/embed/Bn_TcJSOvaA\", width=560, height=340)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "3D shapes can be made using coordinates and CAD opperations such as extrude, rotate and sweep.\n", - "\n", - "This first example shows 4 points connected by straight edges and rotated by 180 degrees." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "my_shape = paramak.RotateStraightShape(\n", - " points=[\n", - " (50,50),\n", - " (50,100),\n", - " (100,100),\n", - " (100,50)\n", - " ],\n", - " rotation_angle=180\n", - ")\n", - "\n", - "my_shape.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This second example shows 4 points connected by spline edges and rotated by 180 degrees." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_shape = paramak.RotateSplineShape(\n", - " points=[\n", - " (50,50),\n", - " (50,100),\n", - " (100,100),\n", - " (100,50)\n", - " ],\n", - " rotation_angle=180\n", - ")\n", - "\n", - "my_shape.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This second example shows 4 points connected by straight edges and extruded by by 20." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_shape = paramak.ExtrudeStraightShape(\n", - " points=[\n", - " (50,50),\n", - " (50,100),\n", - " (100,100),\n", - " (100,50)\n", - " ],\n", - " distance=20\n", - ")\n", - "\n", - "my_shape.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This second example shows 4 points connected by spline edges and extruded by by 20." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_shape = paramak.ExtrudeSplineShape(\n", - " points=[\n", - " (50,50),\n", - " (50,100),\n", - " (100,100),\n", - " (100,50)\n", - " ],\n", - " distance=20\n", - ")\n", - "\n", - "my_shape.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Boolean opperations like cut, union and intersection are also supported.\n", - "\n", - "The following example makes two shapes and cuts the first one away from the second." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "small_Shape = paramak.ExtrudeStraightShape(\n", - " points=[\n", - " (60,60),\n", - " (60,90),\n", - " (90,90),\n", - " (90,60)\n", - " ],\n", - " distance=20,\n", - ")\n", - "\n", - "my_shape = paramak.ExtrudeStraightShape(\n", - " points=[\n", - " (50,50),\n", - " (50,100),\n", - " (100,100),\n", - " (100,50)\n", - " ],\n", - " distance=20,\n", - " cut=small_Shape\n", - ")\n", - "\n", - "my_shape.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The 3D volumes produced can then be:\n", - "- exported to stp files.\n", - "- exported to stl files." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_shape.export_stp('example_shape.stp')\n", - "my_shape.export_stl('example_shape.stl')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The geometry can also be converted into a DAGMC h5m file and used in neutronics simulations.\n", - "\n", - "To visualize the h5m file it can be converted into a vtk file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from stl_to_h5m import stl_to_h5m\n", - "\n", - "stl_to_h5m(\n", - " files_with_tags=[('example_shape.stl', 'mat1')],\n", - " h5m_filename='dagmc.h5m',\n", - ")\n", - "\n", - "import os\n", - "os.system('mbconvert dagmc.h5m dagmc.vtk')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The geometry produced can be downloaded and viewed in FreeCAD (stp and stl) or Paraview (stl, vtk)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import FileLink\n", - "display(FileLink('example_shape.stp'))\n", - "display(FileLink('example_shape.stl'))\n", - "display(FileLink('dagmc.vtk'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "There are additional Shape attributes that allow more complex shapes to be made. For more details take a look at the Documented: https://paramak.readthedocs.io" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "interpreter": { - "hash": "e6c41b96ed9fbad96e04cc7638353f3e0586ef712f1ad27cb7f46f0c7023c1cc" - }, - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.5" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_15_making_CAD_geometry/1_making_cad_with_cadquery.ipynb b/tasks/task_15_making_CAD_geometry/1_making_cad_with_cadquery.ipynb new file mode 100644 index 00000000..e03800c9 --- /dev/null +++ b/tasks/task_15_making_CAD_geometry/1_making_cad_with_cadquery.ipynb @@ -0,0 +1,205 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Part 1 - Making CAD with CadQuery\n", + "\n", + "CadQuery is an intuitive, easy-to-use Python module for building parametric 3D CAD models. Using CadQuery, you can write short, simple scripts that produce high quality CAD models. It is easy to make many different objects using a single script that can be customized.\n", + "\n", + "More details can be found\n", + "- On the documentation https://cadquery.readthedocs.io/en/latest/\n", + "- On GitHub https://github.com/CadQuery/cadquery/\n", + "\n", + "CadQuery is particular well suited to fusion neutronics:\n", + "- CadQuery is used by [cad-to-dagmc](https://github.com/fusion-energy/cad_to_dagmc) to convert CAD geometry to DAGMC neutronics geometry\n", + "- Cadquery can pass geometry in memory to popular meshing software GMsh\n", + "- CadQuery can tag surfaces and volumes so that their tags appear in the meshes and can automate boundary condition assignment in engineering workflows\n", + "- CadQuery is easy to install with pip or conda" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this task we are going start by making a few simple CAD shapes" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First we import cadquery" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "import cadquery as cq" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "circle_solid = cq.Workplane(\"XY\").circle(1.0).extrude(3.0)\n", + "\n", + "circle_solid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "More complex shapes can be made that include splines. These types of curves are not available with traditional CSG geometry " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "xyz_coordinates = [\n", + " (-1.0, -2.0),\n", + " (-0.5, 2.0),\n", + " (1.0, 3.0),\n", + " (2.0, 2.0),\n", + "]\n", + "spine_solid = cq.Workplane(\"XY\").spline(listOfXYTuple=xyz_coordinates, periodic=True).close().extrude(0.5)\n", + "spine_solid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Boolean operations are also supported" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "cut_spline = spine_solid.cut(circle_solid)\n", + "cut_spline" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Assemblies can also be built up to contain several shapes" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assembly = cq.Assembly()\n", + "assembly.add(circle_solid, color=cq.Color(\"red\"))\n", + "assembly.add(cut_spline, color=cq.Color(\"blue\"))\n", + "assembly" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "CAD geometry can also be save to STEP files which are a well supported open standard CAD file format \n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "assembly.export('my-cad-geometry.step')\n", + "\n", + "!ls *.step" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also load CAD files with CadQuery" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "loaded_shape = cq.importers.importStep('my-cad-geometry.step')\n", + "loaded_shape" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The benefits of CAD geometry over CSG are:\n", + "- CAD can be used to make more complex geometry\n", + "- CAD can be used by other disciplines (e.g. mechanical engineering)\n", + "- The void space does not need to be defined when we convert the geometry to a neutronics geomeyty. More on this later\n", + "\n", + "The potential disadvantage is that simulations might be slower. However understanding neutron transport algorthiums and building geometry well can help minimise this disadvantage.\n", + "\n", + "For more information on CadQuery take a look at the CadQuery examples \n", + "- https://cadquery.readthedocs.io/en/latest/examples.html\n", + "- https://cadquery.readthedocs.io/en/latest/free-func.html\n", + "- https://cadquery.readthedocs.io/en/latest/sketch.html\n", + "- https://cadquery.readthedocs.io/en/latest/assy.html" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "text = cq.Workplane().text(txt=\"GitHub stars are appreciated \", fontsize=10, distance=1)\n", + "text.export('cad_geometry.step')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "cq-2.5.2", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tasks/task_15_making_CAD_geometry/2_make_CAD_components_from_parameters.ipynb b/tasks/task_15_making_CAD_geometry/2_make_CAD_components_from_parameters.ipynb deleted file mode 100644 index da45e41a..00000000 --- a/tasks/task_15_making_CAD_geometry/2_make_CAD_components_from_parameters.ipynb +++ /dev/null @@ -1,256 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Part 2 - Making a parametric component\n", - "\n", - "In part one we made Shapes using coordinates / points.\n", - "\n", - "This workshop makes use of paramatric components, these are wrapped versions of Shapes and are able to do the tricky calculation of points on behalf of the user.\n", - "\n", - "Parameters are used with particular rules to define the production of components.\n", - "\n", - "In this notebook we make 3 components but others are available https://paramak.readthedocs.io/en/main/paramak.parametric_components.html" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Stage 1 - Poloidal Field Coils" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![pf](https://user-images.githubusercontent.com/8583900/94807412-86461280-03e7-11eb-9854-ecf66489c262.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This first stage makes a set of poloidal field coils using the Paramak package.\n", - "\n", - "The documentation includes a full description of the shape and arguments.\n", - "\n", - "https://paramak.readthedocs.io/en/main/paramak.parametric_components.html#poloidalfieldcoil" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "pf_1 = paramak.PoloidalFieldCoil(\n", - " height=50,\n", - " width=50,\n", - " center_point=(800,50),\n", - " rotation_angle=180\n", - ")\n", - "\n", - "pf_1.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Stage 2 - Toroidal Field Coils" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![tf](https://user-images.githubusercontent.com/56687624/98582371-cb991200-22ba-11eb-8e15-86d273a8b819.png)\n", - "\n", - "This second stage makes a toroidal field coil using the Paramak package.\n", - "\n", - "The documentation includes a full description of the shape and arguments.\n", - "\n", - "https://paramak.readthedocs.io/en/main/parametric_components.html#toroidalfieldcoilcoathanger" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "tf = paramak.ToroidalFieldCoilCoatHanger(\n", - " horizontal_start_point=(200, 500),\n", - " horizontal_length=400,\n", - " vertical_mid_point=(700, 50),\n", - " vertical_length=500,\n", - " thickness=50,\n", - " distance=50,\n", - " number_of_coils=12,\n", - " rotation_angle=180\n", - ")\n", - "tf.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Stage 3 - Plasma" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![tf](https://user-images.githubusercontent.com/8583900/94805331-226e1a80-03e4-11eb-8623-3e6db0aa1489.png)\n", - "\n", - "This third stage makes a plasma shape.\n", - "\n", - "The documentation includes a full description of the shape and arguments.\n", - "\n", - "https://paramak.readthedocs.io/en/latest/paramak.parametric_components.html#plasma" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plasma = paramak.Plasma(\n", - " minor_radius=150.,\n", - " major_radius=450.,\n", - " triangularity=0.55,\n", - " elongation=2.,\n", - " rotation_angle=180\n", - ")\n", - "\n", - "plasma.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Stage 4 - Blanket" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![bl](https://user-images.githubusercontent.com/8583900/94867319-f0d36e80-0438-11eb-8516-7b8f2a7cc7ee.png)\n", - "\n", - "This fourth stage makes a blanket around the plasma.\n", - "\n", - "The documentation includes a full description of the shape and arguments.\n", - "\n", - "https://paramak.readthedocs.io/en/latest/paramak.parametric_components.html#blanketfp" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "blanket = paramak.BlanketFP(\n", - " plasma=plasma, # this shape is built from another shape\n", - " thickness=20,\n", - " stop_angle=90,\n", - " start_angle=-90,\n", - " offset_from_plasma=20,\n", - " rotation_angle=180\n", - ")\n", - "\n", - "blanket.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "#### Stage 5 - Reactor object\n", - "\n", - "This final stage the combines the components into a single reactor object and exports them to CAD formats (stl and stp)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor = paramak.Reactor([pf_1, tf, blanket, plasma])\n", - "\n", - "my_reactor.export_stp()\n", - "my_reactor.export_stl()\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Links are provided so that the generated CAD files can be downloaded and opened locally.\n", - "\n", - "To open STL or STP files FreeCAD is great option and can be downloaded here: https://www.freecadweb.org/." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import FileLink\n", - "display(FileLink('PoloidalFieldCoil.stl'))\n", - "display(FileLink('PoloidalFieldCoil.stp'))\n", - "display(FileLink('ToroidalFieldCoilPrincetonD.stl'))\n", - "display(FileLink('ToroidalFieldCoilPrincetonD.stp'))\n", - "display(FileLink('plasma.stl'))\n", - "display(FileLink('plasma.stp'))\n", - "display(FileLink('BlanketFP.stl'))\n", - "display(FileLink('BlanketFP.stp'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Learning Outcomes for Part 1:**\n", - "\n", - "- CAD geometry can be used to build complex models with splines for use in neutronics simulations.\n", - "- CAD-based neutronics has a number of advantages over CSG-based neutronics such as implicit voids." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_15_making_CAD_geometry/2_making_cad_with_paramak.ipynb b/tasks/task_15_making_CAD_geometry/2_making_cad_with_paramak.ipynb new file mode 100644 index 00000000..59a043d4 --- /dev/null +++ b/tasks/task_15_making_CAD_geometry/2_making_cad_with_paramak.ipynb @@ -0,0 +1,279 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2 making CAD geometry with Paramak\n", + "\n", + "We learned how to make some basic shapes with CadQuery.\n", + "\n", + "Now if only there was a short cut to making a complete reactor model\n", + "\n", + "Good news there is a package called Paramak that makes parametric CAD for Tokamak geometries.\n", + "\n", + "The resulting geometry is a CadQuery Assembly so it can be added to and customised further.\n", + "\n", + "In this example we are going to make a few simple reactors." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import paramak" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will start with the most minimal tokamak, this spherical_tokamak_from_plasma offers some parameters for the user to customise the shape, number of layers and layer thickness.\n", + "\n", + "Try changing the elongation and triangularity or some of the layer thicknesses" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_reactor = paramak.spherical_tokamak_from_plasma(\n", + " radial_build=[\n", + " (paramak.LayerType.GAP, 10),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 15),\n", + " (paramak.LayerType.GAP, 50),\n", + " (paramak.LayerType.PLASMA, 300),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.SOLID, 15),\n", + " (paramak.LayerType.SOLID, 60),\n", + " (paramak.LayerType.SOLID, 10),\n", + " ],\n", + " elongation=2,\n", + " triangularity=0.55,\n", + " rotation_angle=180,\n", + ")\n", + "\n", + "my_reactor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "There are other reactor types available such as this tokamak function. This allows both a radial and vertical build profile to be specified.\n", + "\n", + "We also add some color to this one" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_reactor = paramak.tokamak(\n", + " radial_build=[\n", + " (paramak.LayerType.GAP, 10),\n", + " (paramak.LayerType.SOLID, 30),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 10),\n", + " (paramak.LayerType.SOLID, 70),\n", + " (paramak.LayerType.SOLID, 20),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.PLASMA, 300),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.SOLID, 20),\n", + " (paramak.LayerType.SOLID, 110),\n", + " (paramak.LayerType.SOLID, 10),\n", + " ],\n", + " vertical_build=[\n", + " (paramak.LayerType.SOLID, 15),\n", + " (paramak.LayerType.SOLID, 80),\n", + " (paramak.LayerType.SOLID, 10),\n", + " (paramak.LayerType.GAP, 50),\n", + " (paramak.LayerType.PLASMA, 700),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.SOLID, 10),\n", + " (paramak.LayerType.SOLID, 40),\n", + " (paramak.LayerType.SOLID, 15),\n", + " ],\n", + " triangularity=0.55,\n", + " rotation_angle=180,\n", + " colors={\n", + " 'layer_1':(0.4, 0.9, 0.4), # center column\n", + " 'layer_2':(0.6, 0.8, 0.6), # magnet shield\n", + " 'layer_3':(0.1, 0.8, 0.6), # first wall\n", + " 'layer_4':(0.1, 0.1, 0.9), # breeder\n", + " 'layer_5':(0.4, 0.4, 0.8), # rear wall\n", + " 'plasma':(1., 0.7, 0.8, 0.6), # plasma has 4 numbers as the last number is the transparency\n", + " },\n", + ")\n", + "\n", + "my_reactor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Further parameters are supported such as PF and TF magnets and divertors. Of course you can also add any CadQuery geometry so the models can be highly customised. Here is one final example of a more complete tokamak\n", + "\n", + "See if you can color the divertor blue in this more complex model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import cadquery as cq\n", + "\n", + "# makes a rectangle that overlaps the lower blanket under the plasma\n", + "# the intersection of this and the layers will form the lower divertor\n", + "points = [(300, -700), (300, 0), (400, 0), (400, -700)]\n", + "divertor_lower = cq.Workplane(\"XZ\", origin=(0, 0, 0)).polyline(points).close().revolve(180)\n", + "\n", + "# creates a toroidal\n", + "tf = paramak.toroidal_field_coil_rectangle(\n", + " horizontal_start_point=(10, 520),\n", + " vertical_mid_point=(860, 0),\n", + " thickness=50,\n", + " distance=40,\n", + " rotation_angle=180,\n", + " with_inner_leg=True,\n", + " azimuthal_placement_angles=[0, 30, 60, 90, 120, 150, 180],\n", + ")\n", + "\n", + "extra_cut_shapes = [tf]\n", + "\n", + "# creates pf coil\n", + "for case_thickness, height, width, center_point in zip(\n", + " [10, 15, 15, 10], [20, 50, 50, 20], [20, 50, 50, 20], [(730, 370), (810, 235), (810, -235), (730, -370)]\n", + "):\n", + " extra_cut_shapes.append(\n", + " paramak.poloidal_field_coil(height=height, width=width, center_point=center_point, rotation_angle=180)\n", + " )\n", + " extra_cut_shapes.append(\n", + " paramak.poloidal_field_coil_case(\n", + " coil_height=height,\n", + " coil_width=width,\n", + " casing_thickness=case_thickness,\n", + " rotation_angle=180,\n", + " center_point=center_point,\n", + " )\n", + " )\n", + "\n", + "my_reactor = paramak.tokamak(\n", + " radial_build=[\n", + " (paramak.LayerType.GAP, 10),\n", + " (paramak.LayerType.SOLID, 30),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 10),\n", + " (paramak.LayerType.SOLID, 60),\n", + " (paramak.LayerType.SOLID, 60),\n", + " (paramak.LayerType.SOLID, 20),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.PLASMA, 300),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.SOLID, 20),\n", + " (paramak.LayerType.SOLID, 60),\n", + " (paramak.LayerType.SOLID, 60),\n", + " (paramak.LayerType.SOLID, 10),\n", + " ],\n", + " vertical_build=[\n", + " (paramak.LayerType.SOLID, 10),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 20),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.PLASMA, 650),\n", + " (paramak.LayerType.GAP, 60),\n", + " (paramak.LayerType.SOLID, 20),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 50),\n", + " (paramak.LayerType.SOLID, 10),\n", + " ],\n", + " triangularity=0.55,\n", + " rotation_angle=180,\n", + " extra_cut_shapes=extra_cut_shapes,\n", + " extra_intersect_shapes=[divertor_lower],\n", + " colors={\n", + " # TODO see if you can color the divertor\n", + " # 'add_extra_cut_shape_1':\n", + " # 'add_extra_cut_shape_2':\n", + " # 'add_extra_cut_shape_3':\n", + " # 'add_extra_cut_shape_4':\n", + " # 'add_extra_cut_shape_5':\n", + " # 'add_extra_cut_shape_6':\n", + " # 'add_extra_cut_shape_7':\n", + " # 'add_extra_cut_shape_8':\n", + " # 'add_extra_cut_shape_9':\n", + " # 'extra_intersect_shapes_1':\n", + " 'layer_1':(0.4, 0.9, 0.4),\n", + " 'layer_2':(0.6, 0.8, 0.6),\n", + " 'layer_3':(0.1, 0.8, 0.6),\n", + " 'layer_4':(0.1, 0.1, 0.9),\n", + " 'layer_5':(0.4, 0.4, 0.8),\n", + " 'layer_6': (0.5, 0.5, 0.8),\n", + " 'plasma':(1., 0.7, 0.8, 0.6),\n", + " },\n", + ")\n", + "my_reactor" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Of course these can be saved as STEP, BREP, STL files or added to just like a CadQuery assembly.\n", + "\n", + "```my_reactor.names()``` is also useful for getting all the names of the parts in the assembly\n", + "\n", + "\n", + "More details on Paramak\n", + "- On the source code repository https://github.com/fusion-energy/paramak\n", + "- On the documentation https://fusion-energy.github.io/paramak/stable/index.html\n", + "- Example Paramak models https://github.com/fusion-energy/paramak/tree/main/examples" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "cq-2.5.2", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.2" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tasks/task_15_making_CAD_geometry/3_make_CAD_reactors.ipynb b/tasks/task_15_making_CAD_geometry/3_make_CAD_reactors.ipynb deleted file mode 100644 index b4d0e9a7..00000000 --- a/tasks/task_15_making_CAD_geometry/3_make_CAD_reactors.ipynb +++ /dev/null @@ -1,151 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Part 3 - Make a reactor geometry from parameters\n", - "\n", - "This notebook allows users to create a more complete 3D CAD model of a reactor using the Paramak and export it to a CAD format and images.\n", - "\n", - "There are several reactors available in the Paramak, examples of which are shown below. In this task, we are going to be making the upper left reactor model." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![cad](https://user-images.githubusercontent.com/8583900/99137324-fddfa200-2621-11eb-9063-f5f7f60ddd8d.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This digram shows how the parameters impact the 3D volume reated" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "![diagram](https://user-images.githubusercontent.com/8583900/99298720-09a9af00-2842-11eb-816b-86492555f97d.png)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This first code block creates a reactor object based on a the predefined deisgn and visulises it. Try running the code block and using the diagram about try changing some of the parameters to see how this impacts the model." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.BallReactor(\n", - " inner_bore_radial_thickness=10,\n", - " inboard_tf_leg_radial_thickness=30,\n", - " center_column_shield_radial_thickness=60,\n", - " divertor_radial_thickness=150,\n", - " inner_plasma_gap_radial_thickness=30,\n", - " plasma_radial_thickness=300,\n", - " outer_plasma_gap_radial_thickness=30,\n", - " firstwall_radial_thickness=30,\n", - " blanket_radial_thickness=50,\n", - " blanket_rear_wall_radial_thickness=30,\n", - " elongation=2,\n", - " triangularity=0.55,\n", - " number_of_tf_coils=16,\n", - " rotation_angle=90,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[500, 575, 575, 500],\n", - " pf_coil_vertical_position=[300, 100, -100, -300],\n", - " rear_blanket_to_tf_gap=50,\n", - " outboard_tf_coil_radial_thickness=100,\n", - " outboard_tf_coil_poloidal_thickness=50\n", - ")\n", - "\n", - "my_reactor.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This exports the 3D CAD files in STP format and a picture of the model as an SVG image" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_svg('reactor.svg')\n", - "filenames = my_reactor.export_stp('my_reactor.stp')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This code block generates the download links for all the different components that have just been made." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from IPython.display import FileLink\n", - "display(FileLink('reactor.svg'))\n", - "display(FileLink('reactor.stp'))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This model could then be used in neutronics simulations with some additional stages, see https://paramak-neutronics.readthedocs.io more details. The next few tasks also cover CAD based simulations." - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Learning Outcomes for Part 2:**\n", - "\n", - "- The Paramak tool allows CAD models of more complex reactor designs to be created easily." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.7" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_15_making_CAD_geometry/README.md b/tasks/task_15_making_CAD_geometry/README.md index 221a99f0..1a8e892f 100644 --- a/tasks/task_15_making_CAD_geometry/README.md +++ b/tasks/task_15_making_CAD_geometry/README.md @@ -5,9 +5,9 @@ Please allow 10 minutes for this task. Expected outputs from this task are also in the [presentation](https://slides.com/neutronics_workshop/neutronics_workshop#/11). -In this task you will use the paramak tool to create CAD geometry which can be converted into a neutronics-ready model. +In this task you will use CadQuery and Paramak to create CAD geometry which can be converted into a neutronics-ready model. **Learning Outcomes** - CAD geometry can be used to build complex models with splines for use in neutronics simulations. -- CAD-based neutronics has a number of advatages over CSG-based neutronics such as implicit voids. +- CAD-based neutronics has a number of advantages over CSG-based neutronics such as implicit voids. diff --git a/tasks/task_16_CAD_mesh_fast_flux/1_making_shapes_for_a_3d_mesh_tally_vtk.ipynb b/tasks/task_16_CAD_mesh_fast_flux/1_making_shapes_for_a_3d_mesh_tally_vtk.ipynb deleted file mode 100644 index ff03936b..00000000 --- a/tasks/task_16_CAD_mesh_fast_flux/1_making_shapes_for_a_3d_mesh_tally_vtk.ipynb +++ /dev/null @@ -1,349 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Heating Mesh Tally on CAD geometry made from Shapes\n", - "\n", - "This constructs a reactor geometry from 3 Shape objects each made from points.\n", - "\n", - "The Shapes made include a breeder blanket, PF coil and a central column shield.\n", - "\n", - "2D and 3D Meshes tally are then simulated to show nuclear heating, flux and tritium_production across the model." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a 3D geometry and material for the centre column" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "center_column = paramak.RotateMixedShape(\n", - " points=[\n", - " (50, 600, 'straight'),\n", - " (150, 600, 'spline'),\n", - " (100, 0, 'spline'),\n", - " (150, -600, 'straight'),\n", - " (50, -600, 'straight')\n", - " ],\n", - " name='center_column'\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a 3D geometry and material for breeder blanket. The azimuth_placement_angle argument is used to repeat the geometry around the Z axis at specified angles." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "blanket = paramak.RotateSplineShape(\n", - " points=[\n", - " (600, 0),\n", - " (600, -20),\n", - " (500, -300),\n", - " (400, -300),\n", - " (400, 0),\n", - " (400, 300),\n", - " (500, 300),\n", - " (600, 20)\n", - " ],\n", - " name='blanket',\n", - " rotation_angle=40,\n", - " azimuth_placement_angle=[0, 45, 90, 135],\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a reactor object from the three components" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor = paramak.Reactor([blanket, center_column])\n", - "\n", - "my_reactor.show()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section forms the neutronics model by combining the 3D model, the plasma source and some assigned materials. Additionally, the tallies to record the heating are specified." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_dagmc_h5m(filename='dagmc.h5m')" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next section combines makes the materials, it also checks the material tags appear in the dagmc.h5m file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "# makes use of the previously created neutronics geometry (h5m file) and assigns\n", - "# actual materials to the material tags. \n", - "\n", - "import openmc\n", - "\n", - "import neutronics_material_maker as nmm\n", - "\n", - "# this links the material tags in the dagmc h5m file with materials.\n", - "# these materials are input as strings so they will be looked up in the\n", - "# neutronics material maker package\n", - "\n", - " \n", - "mat1 = nmm.Material.from_library(name='DT_plasma').openmc_material\n", - "mat1.name = 'blanket'\n", - "mat2 = nmm.Material.from_library(name='Li4SiO4').openmc_material\n", - "mat2.name = 'center_column'\n", - "\n", - "materials = openmc.Materials([mat1, mat2])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section makes the OpenMC geometry from a DAGMC file. This particular DAGMC file does not have a \"graveyard\" surface at the edge of the geometry so the ```bound_universe()``` methodgeometry = openmc.DAGMCUniverse(filename='dagmc.h5m')\n", - " is used to automatically add the vacuum surface to the edge of the geometry" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "bound_dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe()\n", - "my_geometry = openmc.Geometry(root=bound_dag_univ)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section sets the the neutronics results to record (know as tallies)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "mesh = openmc.RegularMesh().from_domain(\n", - " my_geometry, # the corners of the mesh are being set automatically to surround the geometry\n", - " dimension=[100, 100, 100] # only 1 cell in the Y dimension\n", - ")\n", - "\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Create flux mesh tally to score alpha production\n", - "mesh_tally = openmc.Tally(tally_id=1, name='alpha_production_on_mesh') # note the tally_id is specified\n", - "mesh_tally.filters = [mesh_filter]\n", - "mesh_tally.scores = ['(n,Xa)'] # where X is a wild card\n", - "\n", - "\n", - "tallies = openmc.Tallies([mesh_tally])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Assigns a ring source of DT energy neutrons to the source.\n", - "\n", - "This source has a 14MeV neutron energy, with a radius of 350cm and is half a ring (0 to 180 degrees).\n", - "\n", - "If you are keen to make more realistic plasma sources take a looks at the openmc_plasma_source python package\n", - "\n", - "https://github.com/fusion-energy/openmc-plasma-source" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_source = openmc.IndependentSource()\n", - "my_source.angle = openmc.stats.Isotropic()\n", - "my_source.energy = openmc.stats.Discrete([14e6], [1])\n", - "my_source.space = openmc.stats.CylindricalIndependent(\n", - " r=openmc.stats.Discrete([350], [1]), # all source points at a radius of 350 cm\n", - " phi=openmc.stats.Uniform(a=0, b=3.14), # angular distribution between 0 and pi\n", - " z=openmc.stats.Discrete([0], [1]), # all source points at 0 on the z axis\n", - " origin=(0.0, 0.0, 0.0), # centered around 0,0,0 x,y,z\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Establishes the settings for the simulation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "settings.inactive = 0\n", - "settings.run_mode = 'fixed source'\n", - "settings.batches = 4\n", - "settings.particles = 1000\n", - "settings.source = my_source" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Sets simulation intensity, combines the geometry, materials, tallies and settings into a single object and runs the simulation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_model = openmc.Model(\n", - " materials=materials,\n", - " geometry=my_geometry,\n", - " settings=settings,\n", - " tallies=tallies\n", - ")\n", - "!rm *.h5 # just removes old summary.h5 or statepoint files\n", - "statepoint_file = my_model.run()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The following section opens the statepoint and converts the tally result into a VTK file. VTK files can be opened in paraview" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "# assumes you have a statepoint file from the OpenMC simulation\n", - "statepoint = openmc.StatePoint('statepoint.4.h5')\n", - "\n", - "# this shows the tallies present in the statepoint file\n", - "print(statepoint.tallies)\n", - "\n", - "# loads up a tally from the statepoint using it's name\n", - "my_tally = statepoint.get_tally(name='alpha_production_on_mesh')\n", - "\n", - "# converts the tally result into a VTK file\n", - "mesh.write_data_to_vtk(\n", - " datasets={'mean': my_tally.mean},\n", - " filename = \"shape_alpha_production_on_mesh.vtk\",\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now download the VTK file by moving to the file explorer, right mouse clicking on the file and selecting Download.\n", - "\n", - "Open the file in Paraview or another VTK file viewer on your local computer" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.8.12 ('paramak_dev')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - }, - "vscode": { - "interpreter": { - "hash": "c47dabf1cc2568b64caa04441372f68f02228a3c450a6b1274acdfdc3a93f19e" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_16_CAD_mesh_fast_flux/2_making_components_for_a_2d_mesh_tally_vtk.ipynb b/tasks/task_16_CAD_mesh_fast_flux/2_making_components_for_a_2d_mesh_tally_vtk.ipynb deleted file mode 100644 index 697611cc..00000000 --- a/tasks/task_16_CAD_mesh_fast_flux/2_making_components_for_a_2d_mesh_tally_vtk.ipynb +++ /dev/null @@ -1,395 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Heating Mesh Tally on CAD geometry made from Components\n", - "\n", - "This constructs a reactor geometry from 3 Component objects each made from points.\n", - "\n", - "The Component made include a breeder blanket, PF coil and a central column shield.\n", - "\n", - "2D and 3D Meshes tally are then simulated to show nuclear heating, flux and tritium_production across the model." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a 3D geometry and material for PF coil" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "pf_coil = paramak. PoloidalFieldCoil(\n", - " height=50,\n", - " width=50,\n", - " center_point=(725, 25),\n", - " name='pf_coil'\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a 3D geometry and material for the centre column" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "center_column = paramak.CenterColumnShieldHyperbola(\n", - " height=1200,\n", - " inner_radius=50,\n", - " mid_radius=100,\n", - " outer_radius=150,\n", - " name='center_column'\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a 3D geometry and material for breeder blanket. The azimuth_placement_angle argument is used to repeat the geometry around the Z axis at specified angles." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "blanket = paramak.BlanketConstantThicknessArcH(\n", - " inner_mid_point=(500, 0),\n", - " inner_upper_point=(400, 300),\n", - " inner_lower_point=(400, -300),\n", - " thickness= 100,\n", - " rotation_angle=40,\n", - " azimuth_placement_angle=[0, 45, 90, 135],\n", - " name='blanket'\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This makes a reactor object from the three components" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor = paramak.Reactor([blanket, pf_coil,center_column])\n", - "\n", - "my_reactor.show()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "At this stage we can export the reactor geometry as stp files and make them avaialbe from download and viewing in FreeCAD." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_stp('my_reactor.stp')\n", - "\n", - "from IPython.display import FileLink\n", - "display(FileLink('my_reactor.stp'))" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Combines and converts the stl file into a DAGMC h5m file that can be used for the model geometry" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_reactor.export_dagmc_h5m('dagmc.h5m')\n", - "\n", - "import openmc\n", - "bound_dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe()\n", - "geometry = openmc.Geometry(root=bound_dag_univ)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next section uses materials from the neutronics_material_maker package https://github.com/fusion-energy/neutronics_material_maker/\n", - "\n", - "This has an internal database that knows the isotopes and density of various materials.\n", - "\n", - "The ```.openmc_material``` obtains an openmc.material object" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# makes use of the previously created neutronics geometry (h5m file) and assigns\n", - "# actual materials to the material tags. \n", - "\n", - "import neutronics_material_maker as nmm\n", - "\n", - "# this links the material tags in the dagmc h5m file with materials.\n", - "# the materials names are changed after their creation to match the \n", - "# expected material tags in the dagmc file.\n", - "\n", - "mat1 = nmm.Material.from_library(name='copper').openmc_material\n", - "mat1.name = 'pf_coil'\n", - "mat2 = nmm.Material.from_library(name='Li4SiO4').openmc_material\n", - "mat2.name = 'blanket'\n", - "mat3 = nmm.Material.from_library(name='copper').openmc_material\n", - "mat3.name='center_column'\n", - "\n", - "\n", - "materials = openmc.Materials([mat1, mat2, mat3])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section makes the OpenMC geometry from a DAGMC file. This particular DAGMC file does not have a \"graveyard\" surface at the edge of the geometry so the bound_universe() method is used to automatically add the vacuum surface to the edge of the geometry" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "bound_dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m', auto_geom_ids=True).bounded_universe()\n", - "my_geometry = openmc.Geometry(root=bound_dag_univ)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next step makes a simple point source. This uses native OpenMC commands but one could also use the openmc-plasma-source package https://github.com/fusion-energy/openmc-plasma-source/" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "# initialises a new source object\n", - "source = openmc.IndependentSource()\n", - "\n", - "# sets the location of the source to x=0 y=0 z=0\n", - "source.space = openmc.stats.Point((100, 0, 0))\n", - "\n", - "# sets the direction to isotropic\n", - "source.angle = openmc.stats.Isotropic()\n", - "\n", - "# sets the energy distribution to 100% 14MeV neutrons\n", - "source.energy = openmc.stats.Discrete([14e6], [1])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next section combines the geometry with the materials and specifies a 2D mesh tally that spans the entire geometry" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "mesh = openmc.RegularMesh().from_domain(\n", - " my_geometry, # the corners of the mesh are being set automatically to surround the geometry\n", - " dimension=[100, 1, 100] # only 1 cell in the Y dimension\n", - ")\n", - "\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "\n", - "# Create flux mesh tally to score alpha production\n", - "mesh_tally = openmc.Tally(tally_id=1, name='alpha_production_on_mesh') # note the tally_id is specified\n", - "mesh_tally.filters = [mesh_filter]\n", - "mesh_tally.scores = ['(n,Xa)'] # where X is a wild card\n", - "\n", - "\n", - "tallies = openmc.Tallies([mesh_tally])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Assigns a ring source of DT energy neutrons to the source.\n", - "\n", - "This source has a 14MeV neutron energy, with a radius of 350cm and is half a ring (0 to 180 degrees)\n", - "\n", - "If you are keen to make more realistic plasma sources take a looks at the openmc_plasma_source python package\n", - "https://github.com/fusion-energy/openmc-plasma-source" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "my_source = openmc.IndependentSource()\n", - "my_source.angle = openmc.stats.Isotropic()\n", - "my_source.energy = openmc.stats.Discrete([14e6], [1])\n", - "my_source.space = openmc.stats.CylindricalIndependent(\n", - " r=openmc.stats.Discrete([350], [1]), # all source points at a radius of 350 cm\n", - " phi=openmc.stats.Uniform(a=0, b=3.14), # angular distribution between 0 and pi\n", - " z=openmc.stats.Discrete([0], [1]), # all source points at 0 on the z axis\n", - " origin=(0.0, 0.0, 0.0), # centered around 0,0,0 x,y,z\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Sets the simulation intensity then combines the materials, geometry, settines and tallies into a neutronics model and runs the simulation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "settings = openmc.Settings()\n", - "settings.inactive = 0\n", - "settings.run_mode = 'fixed source'\n", - "settings.batches = 10\n", - "settings.particles = 2000\n", - "settings.source = my_source\n", - "\n", - "my_model = openmc.Model(\n", - " materials=materials,\n", - " geometry=my_geometry,\n", - " settings=settings,\n", - " tallies=tallies\n", - ")\n", - "\n", - "!rm *.h5 # just removes old summary.h5 or statepoint files\n", - "statepoint_file = my_model.run()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next section produces download links for:\n", - "\n", - "- vtk files that contain the 3D mesh results (open with Paraview)\n", - "- png images that show the resuls of the 2D mesh tally" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# assumes you have a statepoint file from the OpenMC simulation\n", - "statepoint = openmc.StatePoint(statepoint_file)\n", - "\n", - "# this shows the tallies present in the statepoint file\n", - "print(statepoint.tallies)\n", - "\n", - "# loads up a tally from the statepoint using it's name\n", - "my_tally = statepoint.get_tally(name='alpha_production_on_mesh')\n", - "\n", - "# converts the tally result into a VTK file\n", - "mesh.write_data_to_vtk(\n", - " datasets={'mean': my_tally.mean},\n", - " filename = \"component_alpha_production_on_mesh.vtk\",\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The output file vtk file called \"n_Xa_on_3D_mesh.vtk\" should now appear in the left hand side sidebar. The file can be downloaded to your local computer by right mouse clicking on the file and selecting download." - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.8.12 ('paramak_dev')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - }, - "vscode": { - "interpreter": { - "hash": "c47dabf1cc2568b64caa04441372f68f02228a3c450a6b1274acdfdc3a93f19e" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_16_CAD_mesh_fast_flux/3_making_reactor_for_a_2d_mesh_tally_and_matplotlib_png.ipynb b/tasks/task_16_CAD_mesh_fast_flux/3_making_reactor_for_a_2d_mesh_tally_and_matplotlib_png.ipynb deleted file mode 100644 index 31fb5157..00000000 --- a/tasks/task_16_CAD_mesh_fast_flux/3_making_reactor_for_a_2d_mesh_tally_and_matplotlib_png.ipynb +++ /dev/null @@ -1,444 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Heating Mesh Tally on CAD geometry made from Components\n", - "\n", - "This constructs a reactor geometry from 3 Component objects each made from points.\n", - "\n", - "The Component made include a breeder blanket, PF coil and a central column shield.\n", - "\n", - "2D and 3D Meshes tally are then simulated to show nuclear heating, flux and tritium_production across the model." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section makes the 3d geometry for the entire reactor from a input parameters." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "my_reactor = paramak.BallReactor(\n", - " inner_bore_radial_thickness=50,\n", - " inboard_tf_leg_radial_thickness=55,\n", - " center_column_shield_radial_thickness=50,\n", - " divertor_radial_thickness=50,\n", - " inner_plasma_gap_radial_thickness=50,\n", - " plasma_radial_thickness=100,\n", - " outer_plasma_gap_radial_thickness=50,\n", - " firstwall_radial_thickness=1,\n", - " blanket_radial_thickness=100,\n", - " blanket_rear_wall_radial_thickness=10,\n", - " elongation=2,\n", - " triangularity=0.55,\n", - " number_of_tf_coils=16,\n", - " pf_coil_case_thicknesses=[10, 10, 10, 10],\n", - " pf_coil_radial_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_vertical_thicknesses=[20, 50, 50, 20],\n", - " pf_coil_radial_position=[440, 550, 550, 440],\n", - " pf_coil_vertical_position=[230, 100, -100, -230],\n", - " rear_blanket_to_tf_gap=5,\n", - " outboard_tf_coil_radial_thickness=30,\n", - " outboard_tf_coil_poloidal_thickness=30,\n", - " rotation_angle=90,\n", - ")\n", - "\n", - "# TF and PF coils can be added with additional arguments.\n", - "# see the documentation for more details \n", - "# https://paramak.readthedocs.io/en/main/paramak.parametric_reactors.html\n", - "\n", - "my_reactor.show()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Exports the 3D geometry to a DAGMC neutronics geometry. The plasma is not included as not many neutron interactions occur in the low density plasma" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# creates a h5m file of the geometry with material tags automatically assigned\n", - "my_reactor.export_dagmc_h5m(filename=\"dagmc.h5m\", min_mesh_size=5, max_mesh_size=20)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Names of material tags can be found with the command line tool" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!mbsize -ll dagmc.h5m | grep 'NAME = mat:'" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The next section defines the materials. This can be done using openmc.Materials or in this case strings that look up materials from the neutronics material maker." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "import neutronics_material_maker as nmm\n", - "import openmc\n", - "\n", - "\n", - "\n", - "# simplified material definitions have been used to keen this example minimal\n", - "mat_pf_coil_1 = nmm.Material.from_library(name='copper').openmc_material\n", - "mat_pf_coil_1.name='pf_coil_1'\n", - "\n", - "mat_pf_coil_2 = nmm.Material.from_library(name='copper').openmc_material\n", - "mat_pf_coil_2.name='pf_coil_2'\n", - "\n", - "mat_pf_coil_3 = nmm.Material.from_library(name='copper').openmc_material\n", - "mat_pf_coil_3.name='pf_coil_3'\n", - "\n", - "mat_pf_coil_4 = nmm.Material.from_library(name='copper').openmc_material\n", - "mat_pf_coil_4.name='pf_coil_4'\n", - "\n", - "mat_pf_coil_case_1 = openmc.Material(name=\"pf_coil_case_1\")\n", - "mat_pf_coil_case_1.add_element(\"Fe\", 1, \"ao\")\n", - "mat_pf_coil_case_1.set_density(\"g/cm3\", 8.96)\n", - "\n", - "mat_pf_coil_case_2 = openmc.Material(name=\"pf_coil_case_2\")\n", - "mat_pf_coil_case_2.add_element(\"Fe\", 1, \"ao\")\n", - "mat_pf_coil_case_2.set_density(\"g/cm3\", 8.96)\n", - "\n", - "mat_pf_coil_case_3 = openmc.Material(name=\"pf_coil_case_3\")\n", - "mat_pf_coil_case_3.add_element(\"Fe\", 1, \"ao\")\n", - "mat_pf_coil_case_3.set_density(\"g/cm3\", 8.96)\n", - "\n", - "mat_pf_coil_case_4 = openmc.Material(name=\"pf_coil_case_4\")\n", - "mat_pf_coil_case_4.add_element(\"Fe\", 1, \"ao\")\n", - "mat_pf_coil_case_4.set_density(\"g/cm3\", 8.96)\n", - "\n", - "mat_plasma = openmc.Material(name=\"plasma\")\n", - "mat_plasma.add_element(\"H\", 1, \"ao\")\n", - "mat_plasma.set_density(\"g/cm3\", 0.00001)\n", - "\n", - "mat_center_column_shield = openmc.Material(name=\"center_column_shield\")\n", - "mat_center_column_shield.add_element(\"W\", 1, \"ao\")\n", - "mat_center_column_shield.set_density(\"g/cm3\", 19.3)\n", - "\n", - "mat_outboard_firstwall = openmc.Material(name=\"firstwall\")\n", - "mat_outboard_firstwall.add_element(\"Fe\", 1, \"ao\")\n", - "mat_outboard_firstwall.set_density(\"g/cm3\", 7.7)\n", - "\n", - "mat_blanket = openmc.Material(name=\"blanket\")\n", - "mat_blanket.add_elements_from_formula(\"Pb842Li158\")\n", - "mat_blanket.set_density(\"g/cm3\", 19.)\n", - "\n", - "mat_divertor_upper = openmc.Material(name=\"divertor_upper\")\n", - "mat_divertor_upper.add_element(\"W\", 1, \"ao\")\n", - "mat_divertor_upper.set_density(\"g/cm3\", 19.3)\n", - "\n", - "mat_divertor_lower = openmc.Material(name=\"divertor_lower\")\n", - "mat_divertor_lower.add_element(\"W\", 1, \"ao\")\n", - "mat_divertor_lower.set_density(\"g/cm3\", 19.3)\n", - "\n", - "mat_supports = openmc.Material(name=\"supports\")\n", - "mat_supports.add_element(\"Fe\", 1, \"ao\")\n", - "mat_supports.set_density(\"g/cm3\", 7.7)\n", - "\n", - "mat_outboard_rear_blanket_wall = openmc.Material(name=\"blanket_rear_wall\")\n", - "mat_outboard_rear_blanket_wall.add_element(\"Fe\", 1, \"ao\")\n", - "mat_outboard_rear_blanket_wall.set_density(\"g/cm3\", 7.7)\n", - "\n", - "mat_inboard_tf_coils = nmm.Material.from_library(name='copper').openmc_material\n", - "mat_inboard_tf_coils.name = 'inboard_tf_coils'\n", - "\n", - "mat_tf_coils = nmm.Material.from_library(name='copper').openmc_material\n", - "mat_tf_coils.name = 'tf_coil'\n", - "\n", - "materials = openmc.Materials(\n", - " [\n", - " mat_pf_coil_1,\n", - " mat_pf_coil_2,\n", - " mat_pf_coil_3,\n", - " mat_pf_coil_4,\n", - " mat_pf_coil_case_1,\n", - " mat_pf_coil_case_2,\n", - " mat_pf_coil_case_3,\n", - " mat_pf_coil_case_4,\n", - " mat_plasma,\n", - " mat_center_column_shield,\n", - " mat_outboard_firstwall,\n", - " mat_blanket,\n", - " mat_divertor_upper,\n", - " mat_divertor_lower,\n", - " mat_supports,\n", - " mat_outboard_rear_blanket_wall,\n", - " mat_inboard_tf_coils,\n", - " mat_tf_coils,\n", - " ]\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next section builds the geometry, this is achieved using a filled CSG geometry with reflecting surfaces for the 90 degree wedge" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "import math\n", - "\n", - "# makes use of the dagmc geometry\n", - "dag_univ = openmc.DAGMCUniverse(\"dagmc.h5m\")\n", - "\n", - "# prints all the material tags used in the dagmc geometry\n", - "print(dag_univ.material_names)\n", - "\n", - "# creates an edge of universe boundary surface\n", - "vac_surf = openmc.Sphere(r=10000, surface_id=9999, boundary_type=\"vacuum\")\n", - "\n", - "# adds reflective surface for the sector model at 0 degrees\n", - "reflective_1 = openmc.Plane(\n", - " a=math.sin(0),\n", - " b=-math.cos(0),\n", - " c=0.0,\n", - " d=0.0,\n", - " surface_id=9991,\n", - " boundary_type=\"reflective\",\n", - ")\n", - "\n", - "# adds reflective surface for the sector model at 90 degrees\n", - "reflective_2 = openmc.Plane(\n", - " a=math.sin(math.radians(90)),\n", - " b=-math.cos(math.radians(90)),\n", - " c=0.0,\n", - " d=0.0,\n", - " surface_id=9990,\n", - " boundary_type=\"reflective\",\n", - ")\n", - "\n", - "# specifies the region as below the universe boundary and inside the reflective surfaces\n", - "region = -vac_surf & -reflective_1 & +reflective_2\n", - "\n", - "# creates a cell from the region and fills the cell with the dagmc geometry\n", - "containing_cell = openmc.Cell(cell_id=9999, region=region, fill=dag_univ)\n", - "\n", - "my_geometry = openmc.Geometry(root=[containing_cell])\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next step makes a simple point source." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# creates a simple isotropic neutron source in the center with 14MeV neutrons\n", - "my_source = openmc.IndependentSource()\n", - "\n", - "# the distribution of radius is just a single value at the plasma major radius\n", - "radius = openmc.stats.Discrete([293.], [1])\n", - "\n", - "# the distribution of source z values is just a single value\n", - "z_values = openmc.stats.Discrete([0], [1])\n", - "\n", - "# the distribution of source azimuthal angles values is a uniform distribution between 0 and 0.5 Pi\n", - "# these angles must be the same as the reflective angles\n", - "angle = openmc.stats.Uniform(a=0., b=math.radians(90))\n", - "\n", - "# this makes the ring source using the three distributions and a radius\n", - "my_source.space = openmc.stats.CylindricalIndependent(r=radius, phi=angle, z=z_values, origin=(0.0, 0.0, 0.0))\n", - "\n", - "# sets the direction to isotropic\n", - "my_source.angle = openmc.stats.Isotropic()\n", - "\n", - "# sets the energy distribution to a Muir distribution neutrons\n", - "my_source.energy = openmc.stats.muir(e0=14080000.0, m_rat=5.0, kt=20000.0)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# specifies the simulation computational intensity\n", - "settings = openmc.Settings()\n", - "settings.batches = 2\n", - "settings.particles = 1000\n", - "settings.inactive = 0\n", - "settings.run_mode = \"fixed source\"\n", - "settings.source = my_source" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Makes a 3D mesh tally" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# creates a mesh that covers the geometry\n", - "mesh = openmc.RegularMesh().from_domain(\n", - " my_geometry, # the corners of the mesh are being set automatically to surround the geometry\n", - " dimension=[100, 100, 100] # only 1 cell in the Y dimension\n", - ")\n", - "\n", - "# makes a mesh tally using the previously created mesh and records heating on the mesh\n", - "mesh_tally = openmc.Tally(name=\"heating_on_mesh\")\n", - "mesh_filter = openmc.MeshFilter(mesh)\n", - "mesh_tally.filters = [mesh_filter]\n", - "mesh_tally.scores = [\"heating\"]\n", - "\n", - "heating_tally = openmc.Tally(name=\"heating\")\n", - "heating_tally.scores = [\"heating\"]\n", - "\n", - "# groups the two tallies\n", - "tallies = openmc.Tallies([mesh_tally, heating_tally])" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "starts the simulation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# builds the openmc model\n", - "my_model = openmc.Model(\n", - " materials=materials, geometry=my_geometry, settings=settings, tallies=tallies\n", - ")\n", - "\n", - "# starts the simulation\n", - "statepoint_filename = my_model.run()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "extracts the 3d mesh tally result and plots it as a vtk" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# open the results file\n", - "sp = openmc.StatePoint(statepoint_filename)\n", - "\n", - "# access the tally using pandas dataframes\n", - "heating_tally = sp.get_tally(name=\"heating\")\n", - "\n", - "# print cell tally results with unit conversion\n", - "# raw tally result is multipled by 4 as this is a sector model of 1/4 of the total model (90 degrees from 360)\n", - "# raw tally result is divided by 1e6 to convert the standard units of eV to MeV\n", - "print(f\"The heating of {4*heating_tally.mean.sum()/1e6} MeV per source particle is deposited\")\n", - "print(f\"Standard deviation on the heating tally is {heating_tally.std_dev.sum()}\")\n", - "\n", - "# extracts the mesh tally result\n", - "heating_mesh_tally = sp.get_tally(name=\"heating_on_mesh\")\n", - "\n", - "mesh.write_data_to_vtk(\n", - " datasets={'heating_mean': heating_mesh_tally.mean},\n", - " filename=\"reactor_heating_on_mesh.vtk\",\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The vtk file should have appeared in the file explorer to the left. Right mouse click on the file to download it and then open with Paraview" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.9.1" - }, - "vscode": { - "interpreter": { - "hash": "d4d1e4263499bec80672ea0156c357c1ee493ec2b1c70f0acce89fc37c4a6abe" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_16_CAD_mesh_fast_flux/README.md b/tasks/task_16_CAD_mesh_fast_flux/README.md deleted file mode 100644 index 9653dec6..00000000 --- a/tasks/task_16_CAD_mesh_fast_flux/README.md +++ /dev/null @@ -1,24 +0,0 @@ - -## Task 12 - CAD mesh tally of fast flux - -Please allow 30 minutes for this task. - -Expected outputs from this task are also in the [presentation](https://slides.com/neutronics_workshop/neutronics_workshop#/13). - -In this task you will be using OpenMC, DAGMC to perform neutronics simulations -on 2D meshes and 3D meshes. - -The results will processed into VTK files and png images depending on the part. - -- part 1 creates a 3D mesh tally of a CAD geometry made from shapes and exports it in VTK format -- part 2 creates a 2D mesh tally of a CAD geometry made from components and exports it in VTK format -- part 3 creates a 2D mesh tally of a CAD geometry made from components and exports it in as a PNG image along with a slice of the geometry - - -**Learning Outcomes** - -- Mesh tallies can obtain spatial response throughout the geometry -- 3D and 2D spatial maps can be made -- The bounding box of DAGMC geometry can be found using -- How to process 2D mesh tallies into images using [regular_mesh_plotter](https://github.com/fusion-energy/regular_mesh_plotter) -- How to make sliced images of DAGMC geometry using [dagmc_geometry_slice_plotter](https://github.com/fusion-energy/dagmc_geometry_slice_plotter) diff --git a/tasks/task_16_converting_CAD_geometry_to_DAGMC/1_converting_cad_files.ipynb b/tasks/task_16_converting_CAD_geometry_to_DAGMC/1_converting_cad_files.ipynb new file mode 100644 index 00000000..b2f6699e --- /dev/null +++ b/tasks/task_16_converting_CAD_geometry_to_DAGMC/1_converting_cad_files.ipynb @@ -0,0 +1,37 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Converting CAD geometry to neutronics\n", + "\n", + "CAD geometry can be converted with cad-to-dagmc\n", + "\n", + "This makes DAGMC geometry which particle transport codes like OpenMC can understand and simulate particle transport through\n", + "\n", + "In this example we are going to convert some CAD to a neutronics model and simulate particles" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Read more about DAGMC geometry here\n", + "https://svalinn.github.io/DAGMC/" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tasks/task_17_CAD_cell_tally_heat/1_simulate_CAD_neutronics_geometry_with_cell_tally_heat.ipynb b/tasks/task_17_CAD_cell_tally_heat/1_simulate_CAD_neutronics_geometry_with_cell_tally_heat.ipynb deleted file mode 100644 index a00b5689..00000000 --- a/tasks/task_17_CAD_cell_tally_heat/1_simulate_CAD_neutronics_geometry_with_cell_tally_heat.ipynb +++ /dev/null @@ -1,284 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Neutronics simulation with CAD geometry\n", - "\n", - "This example creates a CAD geometry and then carries out a neutronics simulation with a heating cell tally." - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section makes a few components and places them in a reactor object. These will form the CAD model with which we will perform a neutronics simulation." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import paramak\n", - "\n", - "plasma = paramak.Plasma(\n", - " minor_radius=150.,\n", - " major_radius=450.,\n", - " triangularity=0.55,\n", - " elongation=2.,\n", - " rotation_angle=180,\n", - " name='plasma'\n", - ")\n", - "\n", - "blanket = paramak.BlanketFP(\n", - " plasma=plasma,\n", - " thickness=50,\n", - " stop_angle=90,\n", - " start_angle=-90,\n", - " offset_from_plasma=40,\n", - " rotation_angle=180,\n", - " name='blanket'\n", - ")\n", - "\n", - "my_reactor = paramak.Reactor([plasma, blanket])\n", - "my_reactor.show()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next code block exports the 3D reactor geometry as a DAGMC compatibile h5m file which can be used as a neutronics geometry. DAGMC is a neutronics code that allows particle transport on CAD geometry with various neutronics transport codes (including OpenMC).\n", - "\n", - "More details on DAGMC here https://svalinn.github.io/DAGMC/\n", - "\n", - "This export will take a reasonable amount of time compared to other cells" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!rm dagmc.h5m\n", - "my_reactor.export_dagmc_h5m(filename='dagmc.h5m', min_mesh_size=15, max_mesh_size=30)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The model can now be simulated in OpenMC. OpenMC is imported along with some convenience packages" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import openmc\n", - "import neutronics_material_maker as nmm # makes materials from a database" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This section forms the neutronics model by combining the DAGMC model with a plasma source and some assigned materials. Additionally, the tallies to record the heating are specified. The code block also sets simulation intensity and specifies the neutronics results to record (know as tallies)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# makes a bounding box around the CAD geometry with vacuum surfaces\n", - "bound_dag_univ = openmc.DAGMCUniverse(filename='dagmc.h5m').bounded_universe()\n", - "my_geometry = openmc.Geometry(root=bound_dag_univ)\n", - "\n", - "\n", - "# this links the material tags in the dagmc h5m file with materials.\n", - "# the materials names are changed after their creation to match the \n", - "# expected material tags in the dagmc file.\n", - "mat1 = nmm.Material.from_library(name='DT_plasma').openmc_material\n", - "mat1.name = 'plasma'\n", - "mat2 = nmm.Material.from_library(name='Li4SiO4').openmc_material\n", - "mat2.name = 'blanket'\n", - "\n", - "materials = openmc.Materials([mat1, mat2])\n", - "\n", - "\n", - "tally1 = openmc.Tally()\n", - "material_filter = openmc.MaterialFilter(mat2) # the center column material\n", - "tally1 = openmc.Tally(name='blanket_heating')\n", - "tally1.filters = [material_filter]\n", - "tally1.scores = ['heating']\n", - "\n", - "my_tallies = openmc.Tallies([tally1])\n", - "\n", - "# here an instance of the settings object has been created and attributes set on creation\n", - "my_settings = openmc.Settings(batches = 1, particles = 100, run_mode = 'fixed source')\n", - "\n", - "# Assigns a ring source of DT energy neutrons to the source. This source has a\n", - "# 14MeV neutron energy, with a radius of 350cm and is half a ring (0 to 180 degrees)\n", - "# If you are keen to make more realistic plasma sources take a looks at the\n", - "# openmc_plasma_source python package https://github.com/fusion-energy/openmc-plasma-source\n", - "my_source = openmc.IndependentSource()\n", - "my_source.angle = openmc.stats.Isotropic()\n", - "my_source.energy = openmc.stats.Discrete([14e6], [1])\n", - "my_source.space = openmc.stats.CylindricalIndependent(\n", - " r=openmc.stats.Discrete([350], [1]), # all source points at a radius of 350 cm\n", - " phi=openmc.stats.Uniform(a=0, b=3.14), # angular distribution between 0 and pi\n", - " z=openmc.stats.Discrete([0], [1]), # all source points at 0 on the z axis\n", - " origin=(0.0, 0.0, 0.0), # centered around 0,0,0 x,y,z\n", - ")\n", - "my_settings.source = my_source\n", - "\n", - "my_model = openmc.Model(\n", - " materials=materials, geometry=my_geometry, settings=my_settings, tallies=my_tallies\n", - ")\n", - "\n", - "# delete old files just in case they are there\n", - "!rm summary.h5\n", - "!rm statepoint*.h5\n", - "\n", - "# starts the simulation and gets the filename of the output file produced\n", - "statepoint_file = my_model.run()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Extracting the resulting tally value from the statepoint file" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sp = openmc.StatePoint(statepoint_file)\n", - "\n", - "heating_tally = sp.get_tally(name='blanket_heating')\n", - "\n", - "# this returns the tally in unknown base units\n", - "heating_tally.get_values().sum()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "This next cell just imports a post processing package and uses that package to find the units of the tally" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import openmc_tally_unit_converter as otuc\n", - "\n", - "tally = otuc.process_tally(\n", - " heating_tally,\n", - ")\n", - "# this prints the tally with base units identified\n", - "print(tally)" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Converts the units from the base units (eV/simulated particle) to MeV/simulated particle" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "otuc.process_tally(\n", - " heating_tally,\n", - " required_units=\"MeV/source_particle\"\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Converts units by normalising by the source strength (number of nuetrons per second)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "otuc.process_tally(\n", - " heating_tally,\n", - " required_units=\"gigawatts\",\n", - " source_strength=1e21\n", - ")" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "**Learning Outcomes from Task 11**\n", - "\n", - "- Neutronics simulations can be performed by combining CAD models, neutron sources and material definitions.\n", - "- Scaled the units of the output results using post processing package" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3.8.12 ('paramak_dev')", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.8.12" - }, - "vscode": { - "interpreter": { - "hash": "c47dabf1cc2568b64caa04441372f68f02228a3c450a6b1274acdfdc3a93f19e" - } - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/tasks/task_17_CAD_cell_tally_heat/README.md b/tasks/task_17_CAD_cell_tally_heat/README.md deleted file mode 100644 index c09c1107..00000000 --- a/tasks/task_17_CAD_cell_tally_heat/README.md +++ /dev/null @@ -1,8 +0,0 @@ - -## This task is currently under development and may not work - -## Task 11 - Tallying heat on surfaces - -Please allow 20 minutes for this task. - -Expected outputs from this task are also in the [presentation](https://slides.com/neutronics_workshop/neutronics_workshop#/12). diff --git a/tasks/task_17_using_DAGMC_models_in_openmc/1_cad_model_simulation_minimal.ipynb b/tasks/task_17_using_DAGMC_models_in_openmc/1_cad_model_simulation_minimal.ipynb new file mode 100644 index 00000000..bd6face8 --- /dev/null +++ b/tasks/task_17_using_DAGMC_models_in_openmc/1_cad_model_simulation_minimal.ipynb @@ -0,0 +1,18 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Simple CAD model simulation" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tasks/task_17_using_DAGMC_models_in_openmc/2_cad_model_simulation_with_boundary_types.ipynb b/tasks/task_17_using_DAGMC_models_in_openmc/2_cad_model_simulation_with_boundary_types.ipynb new file mode 100644 index 00000000..e47f34d9 --- /dev/null +++ b/tasks/task_17_using_DAGMC_models_in_openmc/2_cad_model_simulation_with_boundary_types.ipynb @@ -0,0 +1,27 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "vscode": { + "languageId": "plaintext" + } + }, + "source": [ + "# Adding boundary conditions to a CAD model\n", + "\n", + "Sometimes when we convert the model it is necessary to also add in boundary conditions to the containing CSG geometry.\n", + "\n", + "For example if the CAD is a sector model of a reactor, say a 180 degree model of a tokamak then you may want to put a reflective surface on one side of the bounding geometry.\n", + "\n" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tasks/task_17_using_DAGMC_models_in_openmc/3_cad_model_simulation_with_hybrid_csg.ipynb b/tasks/task_17_using_DAGMC_models_in_openmc/3_cad_model_simulation_with_hybrid_csg.ipynb new file mode 100644 index 00000000..a5f34920 --- /dev/null +++ b/tasks/task_17_using_DAGMC_models_in_openmc/3_cad_model_simulation_with_hybrid_csg.ipynb @@ -0,0 +1,20 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Making a hybrid CAD CSG model\n", + "\n", + "can be useful for bioshields ..." + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/tasks/task_18_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate.py b/tasks/task_20_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate.py similarity index 100% rename from tasks/task_18_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate.py rename to tasks/task_20_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate.py diff --git a/tasks/task_18_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate_concise.py b/tasks/task_20_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate_concise.py similarity index 100% rename from tasks/task_18_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate_concise.py rename to tasks/task_20_CAD_shut_down_dose_rate/1_unstrucutred_mesh_R2S_shut_down_dose_rate_concise.py diff --git a/tasks/task_19_design_task/1_optimal_design.ipynb b/tasks/task_21_design_task/1_optimal_design.ipynb similarity index 100% rename from tasks/task_19_design_task/1_optimal_design.ipynb rename to tasks/task_21_design_task/1_optimal_design.ipynb diff --git a/tasks/task_19_design_task/1_optimal_design_with_hints.ipynb b/tasks/task_21_design_task/1_optimal_design_with_hints.ipynb similarity index 100% rename from tasks/task_19_design_task/1_optimal_design_with_hints.ipynb rename to tasks/task_21_design_task/1_optimal_design_with_hints.ipynb