diff --git a/final/numpy_stl_experiment.py b/final/numpy_stl_experiment.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea2045c79dc88295c35512d73cfec5bac9c4ed6d
--- /dev/null
+++ b/final/numpy_stl_experiment.py
@@ -0,0 +1,34 @@
+import os
+import numpy as np
+from stl import mesh
+import matplotlib.pyplot as plt
+from mpl_toolkits import mplot3d
+
+def load_stl_files():
+    stl_files = [file for file in os.listdir() if file.endswith('.stl')]
+    meshes = []
+    for file in stl_files:
+        meshes.append(mesh.Mesh.from_file(file))
+    return meshes
+
+def main():
+    # Load STL files
+    meshes = load_stl_files()
+
+    # Create a 3D plot
+    figure = plt.figure()
+    axes = mplot3d.Axes3D(figure)
+
+    # Plot the meshes
+    for mesh_data in meshes:
+        axes.add_collection3d(mplot3d.art3d.Poly3DCollection(mesh_data.vectors))
+
+    # Set plot parameters
+    axes.auto_scale_xyz([-100, 100], [-100, 100], [-100, 100])
+    plt.axis('off')
+
+    # Show the plot
+    plt.show()
+
+if __name__ == '__main__':
+    main()
\ No newline at end of file
diff --git a/final/rotor.SLDPRT b/final/rotor.SLDPRT
new file mode 100644
index 0000000000000000000000000000000000000000..2a033d51129bb3cc37da61cf161a9d3c871c1b1b
Binary files /dev/null and b/final/rotor.SLDPRT differ
diff --git a/final/rotor.STEP b/final/rotor.STEP
new file mode 100644
index 0000000000000000000000000000000000000000..e14e8bd35beff960c7f1e00e237a38351c821640
--- /dev/null
+++ b/final/rotor.STEP
@@ -0,0 +1,231 @@
+ISO-10303-21;
+HEADER;
+FILE_DESCRIPTION (( 'STEP AP214' ),
+    '1' );
+FILE_NAME ('rotor.STEP',
+    '2023-05-14T01:01:21',
+    ( '' ),
+    ( '' ),
+    'SwSTEP 2.0',
+    'SolidWorks 2021',
+    '' );
+FILE_SCHEMA (( 'AUTOMOTIVE_DESIGN' ));
+ENDSEC;
+
+DATA;
+#1 = PRESENTATION_STYLE_ASSIGNMENT (( #105 ) ) ;
+#2 = AXIS2_PLACEMENT_3D ( 'NONE', #207, #59, #113 ) ;
+#3 = PRODUCT_CONTEXT ( 'NONE', #53, 'mechanical' ) ;
+#4 = UNCERTAINTY_MEASURE_WITH_UNIT (LENGTH_MEASURE( 1.000000000000000082E-05 ), #196, 'distance_accuracy_value', 'NONE');
+#5 = VECTOR ( 'NONE', #11, 1000.000000000000000 ) ;
+#6 = VECTOR ( 'NONE', #48, 1000.000000000000000 ) ;
+#7 = VERTEX_POINT ( 'NONE', #210 ) ;
+#8 = EDGE_CURVE ( 'NONE', #158, #42, #197, .T. ) ;
+#9 = EDGE_LOOP ( 'NONE', ( #186, #45, #144, #61 ) ) ;
+#10 = ORIENTED_EDGE ( 'NONE', *, *, #55, .F. ) ;
+#11 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#12 = ORIENTED_EDGE ( 'NONE', *, *, #51, .F. ) ;
+#13 = ORIENTED_EDGE ( 'NONE', *, *, #135, .T. ) ;
+#14 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#15 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#16 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION (  '', ( #166 ), #54 ) ;
+#17 =( LENGTH_UNIT ( ) NAMED_UNIT ( * ) SI_UNIT ( .MILLI., .METRE. ) );
+#18 = CIRCLE ( 'NONE', #209, 0.2500000000000000000 ) ;
+#19 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
+#20 =( NAMED_UNIT ( * ) PLANE_ANGLE_UNIT ( ) SI_UNIT ( $, .RADIAN. ) );
+#21 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
+#22 = AXIS2_PLACEMENT_3D ( 'NONE', #115, #119, #133 ) ;
+#23 = VERTEX_POINT ( 'NONE', #47 ) ;
+#24 = VERTEX_POINT ( 'NONE', #114 ) ;
+#25 = EDGE_CURVE ( 'NONE', #80, #140, #125, .T. ) ;
+#26 = PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE ( 'ANY', '', #116, .NOT_KNOWN. ) ;
+#27 = AXIS2_PLACEMENT_3D ( 'NONE', #72, #202, #19 ) ;
+#28 = ORIENTED_EDGE ( 'NONE', *, *, #41, .F. ) ;
+#29 = ORIENTED_EDGE ( 'NONE', *, *, #135, .F. ) ;
+#30 = FILL_AREA_STYLE_COLOUR ( '', #102 ) ;
+#31 = EDGE_LOOP ( 'NONE', ( #142, #78 ) ) ;
+#32 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#33 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#34 = PLANE ( 'NONE',  #171 ) ;
+#35 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#36 = AXIS2_PLACEMENT_3D ( 'NONE', #118, #208, #150 ) ;
+#37 = CYLINDRICAL_SURFACE ( 'NONE', #77, 0.3499999999999999778 ) ;
+#38 = ADVANCED_FACE ( 'NONE', ( #160, #60 ), #34, .F. ) ;
+#39 =( NAMED_UNIT ( * ) SI_UNIT ( $, .STERADIAN. ) SOLID_ANGLE_UNIT ( ) );
+#40 = PRODUCT_DEFINITION_CONTEXT ( 'detailed design', #71, 'design' ) ;
+#41 = EDGE_CURVE ( 'NONE', #23, #7, #109, .T. ) ;
+#42 = VERTEX_POINT ( 'NONE', #152 ) ;
+#43 = VECTOR ( 'NONE', #83, 1000.000000000000000 ) ;
+#44 = AXIS2_PLACEMENT_3D ( 'NONE', #191, #50, #130 ) ;
+#45 = ORIENTED_EDGE ( 'NONE', *, *, #187, .F. ) ;
+#46 = EDGE_CURVE ( 'NONE', #42, #158, #92, .T. ) ;
+#47 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, -0.2500000000000000000 ) ) ;
+#48 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#49 = DIRECTION ( 'NONE',  ( 0.000000000000000000, -0.000000000000000000, 1.000000000000000000 ) ) ;
+#50 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#51 = EDGE_CURVE ( 'NONE', #155, #42, #189, .T. ) ;
+#52 = SURFACE_STYLE_USAGE ( .BOTH. , #193 ) ;
+#53 = APPLICATION_CONTEXT ( 'automotive_design' ) ;
+#54 =( GEOMETRIC_REPRESENTATION_CONTEXT ( 3 ) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT ( ( #90 ) ) GLOBAL_UNIT_ASSIGNED_CONTEXT ( ( #17, #70, #39 ) ) REPRESENTATION_CONTEXT ( 'NONE', 'WORKASPACE' ) );
+#55 = EDGE_CURVE ( 'NONE', #140, #80, #85, .T. ) ;
+#56 = DIRECTION ( 'NONE',  ( 1.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#57 = EDGE_LOOP ( 'NONE', ( #28, #29 ) ) ;
+#58 = CIRCLE ( 'NONE', #123, 0.3499999999999999778 ) ;
+#59 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#60 = FACE_BOUND ( 'NONE', #175, .T. ) ;
+#61 = ORIENTED_EDGE ( 'NONE', *, *, #46, .T. ) ;
+#62 = FACE_OUTER_BOUND ( 'NONE', #205, .T. ) ;
+#63 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, -0.3499999999999999778 ) ) ;
+#64 = MECHANICAL_DESIGN_GEOMETRIC_PRESENTATION_REPRESENTATION (  '', ( #127 ), #75 ) ;
+#65 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#66 = PRODUCT_DEFINITION_SHAPE ( 'NONE', 'NONE',  #87 ) ;
+#67 = CYLINDRICAL_SURFACE ( 'NONE', #44, 0.2500000000000000000 ) ;
+#68 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#69 = ADVANCED_FACE ( 'NONE', ( #192, #81 ), #147, .T. ) ;
+#70 =( NAMED_UNIT ( * ) PLANE_ANGLE_UNIT ( ) SI_UNIT ( $, .RADIAN. ) );
+#71 = APPLICATION_CONTEXT ( 'automotive_design' ) ;
+#72 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#73 = FACE_OUTER_BOUND ( 'NONE', #111, .T. ) ;
+#74 = EDGE_CURVE ( 'NONE', #7, #140, #132, .T. ) ;
+#75 =( GEOMETRIC_REPRESENTATION_CONTEXT ( 3 ) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT ( ( #184 ) ) GLOBAL_UNIT_ASSIGNED_CONTEXT ( ( #122, #185, #198 ) ) REPRESENTATION_CONTEXT ( 'NONE', 'WORKASPACE' ) );
+#76 = SURFACE_STYLE_FILL_AREA ( #88 ) ;
+#77 = AXIS2_PLACEMENT_3D ( 'NONE', #68, #172, #21 ) ;
+#78 = ORIENTED_EDGE ( 'NONE', *, *, #94, .T. ) ;
+#79 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#80 = VERTEX_POINT ( 'NONE', #82 ) ;
+#81 = FACE_BOUND ( 'NONE', #57, .T. ) ;
+#82 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, -0.2500000000000000000 ) ) ;
+#83 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#84 = AXIS2_PLACEMENT_3D ( 'NONE', #211, #15, #65 ) ;
+#85 = CIRCLE ( 'NONE', #201, 0.2500000000000000000 ) ;
+#86 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#87 = PRODUCT_DEFINITION ( 'UNKNOWN', '', #26, #40 ) ;
+#88 = FILL_AREA_STYLE ('',( #170 ) ) ;
+#89 = ADVANCED_FACE ( 'NONE', ( #62 ), #67, .F. ) ;
+#90 = UNCERTAINTY_MEASURE_WITH_UNIT (LENGTH_MEASURE( 1.000000000000000082E-05 ), #17, 'distance_accuracy_value', 'NONE');
+#91 = APPLICATION_PROTOCOL_DEFINITION ( 'draft international standard', 'automotive_design', 1998, #53 ) ;
+#92 = CIRCLE ( 'NONE', #84, 0.3499999999999999778 ) ;
+#93 = EDGE_LOOP ( 'NONE', ( #146, #203 ) ) ;
+#94 = EDGE_CURVE ( 'NONE', #24, #155, #137, .T. ) ;
+#95 = ORIENTED_EDGE ( 'NONE', *, *, #41, .T. ) ;
+#96 = ORIENTED_EDGE ( 'NONE', *, *, #55, .T. ) ;
+#97 = ORIENTED_EDGE ( 'NONE', *, *, #8, .T. ) ;
+#98 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#99 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#100 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#101 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#102 = COLOUR_RGB ( '',0.7921568627450980005, 0.8196078431372548767, 0.9333333333333333481 ) ;
+#103 =( GEOMETRIC_REPRESENTATION_CONTEXT ( 3 ) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT ( ( #4 ) ) GLOBAL_UNIT_ASSIGNED_CONTEXT ( ( #196, #20, #153 ) ) REPRESENTATION_CONTEXT ( 'NONE', 'WORKASPACE' ) );
+#104 = SURFACE_SIDE_STYLE ('',( #76 ) ) ;
+#105 = SURFACE_STYLE_USAGE ( .BOTH. , #104 ) ;
+#106 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, -0.3499999999999999778 ) ) ;
+#107 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#108 = ORIENTED_EDGE ( 'NONE', *, *, #149, .F. ) ;
+#109 = CIRCLE ( 'NONE', #156, 0.2500000000000000000 ) ;
+#110 = ORIENTED_EDGE ( 'NONE', *, *, #149, .T. ) ;
+#111 = EDGE_LOOP ( 'NONE', ( #129, #13, #110, #10 ) ) ;
+#112 = AXIS2_PLACEMENT_3D ( 'NONE', #14, #179, #49 ) ;
+#113 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#114 = CARTESIAN_POINT ( 'NONE',  ( 4.286263797015735979E-17, 4.599999999999999645, 0.3499999999999999778 ) ) ;
+#115 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#116 = PRODUCT ( 'rotor', 'rotor', '', ( #3 ) ) ;
+#117 = EDGE_LOOP ( 'NONE', ( #174, #190, #97, #12 ) ) ;
+#118 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#119 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#120 = CLOSED_SHELL ( 'NONE', ( #89, #195, #69, #38, #138, #199 ) ) ;
+#121 = DIRECTION ( 'NONE',  ( 0.000000000000000000, -0.000000000000000000, 1.000000000000000000 ) ) ;
+#122 =( LENGTH_UNIT ( ) NAMED_UNIT ( * ) SI_UNIT ( .MILLI., .METRE. ) );
+#123 = AXIS2_PLACEMENT_3D ( 'NONE', #168, #124, #86 ) ;
+#124 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#125 = CIRCLE ( 'NONE', #141, 0.2500000000000000000 ) ;
+#126 = EDGE_CURVE ( 'NONE', #24, #158, #128, .T. ) ;
+#127 = STYLED_ITEM ( 'NONE', ( #1 ), #206 ) ;
+#128 = LINE ( 'NONE', #182, #6 ) ;
+#129 = ORIENTED_EDGE ( 'NONE', *, *, #74, .F. ) ;
+#130 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
+#131 = FILL_AREA_STYLE ('',( #30 ) ) ;
+#132 = LINE ( 'NONE', #165, #43 ) ;
+#133 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
+#134 = CARTESIAN_POINT ( 'NONE',  ( 4.286263797015735979E-17, 0.000000000000000000, 0.3499999999999999778 ) ) ;
+#135 = EDGE_CURVE ( 'NONE', #7, #23, #18, .T. ) ;
+#136 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, -0.2500000000000000000 ) ) ;
+#137 = CIRCLE ( 'NONE', #36, 0.3499999999999999778 ) ;
+#138 = ADVANCED_FACE ( 'NONE', ( #148 ), #212, .T. ) ;
+#139 = SHAPE_DEFINITION_REPRESENTATION ( #66, #206 ) ;
+#140 = VERTEX_POINT ( 'NONE', #214 ) ;
+#141 = AXIS2_PLACEMENT_3D ( 'NONE', #163, #145, #98 ) ;
+#142 = ORIENTED_EDGE ( 'NONE', *, *, #187, .T. ) ;
+#143 = MANIFOLD_SOLID_BREP ( 'Boss-Extrude1', #120 ) ;
+#144 = ORIENTED_EDGE ( 'NONE', *, *, #51, .T. ) ;
+#145 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#146 = ORIENTED_EDGE ( 'NONE', *, *, #46, .F. ) ;
+#147 = PLANE ( 'NONE',  #112 ) ;
+#148 = FACE_OUTER_BOUND ( 'NONE', #9, .T. ) ;
+#149 = EDGE_CURVE ( 'NONE', #23, #80, #177, .T. ) ;
+#150 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#151 = VECTOR ( 'NONE', #200, 1000.000000000000000 ) ;
+#152 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, -0.3499999999999999778 ) ) ;
+#153 =( NAMED_UNIT ( * ) SI_UNIT ( $, .STERADIAN. ) SOLID_ANGLE_UNIT ( ) );
+#154 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
+#155 = VERTEX_POINT ( 'NONE', #106 ) ;
+#156 = AXIS2_PLACEMENT_3D ( 'NONE', #100, #181, #99 ) ;
+#157 = ORIENTED_EDGE ( 'NONE', *, *, #25, .T. ) ;
+#158 = VERTEX_POINT ( 'NONE', #134 ) ;
+#159 = AXIS2_PLACEMENT_3D ( 'NONE', #107, #154, #56 ) ;
+#160 = FACE_OUTER_BOUND ( 'NONE', #93, .T. ) ;
+#161 = ORIENTED_EDGE ( 'NONE', *, *, #74, .T. ) ;
+#162 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#163 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#164 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#165 = CARTESIAN_POINT ( 'NONE',  ( 3.061616997868383018E-17, 4.599999999999999645, 0.2500000000000000000 ) ) ;
+#166 = STYLED_ITEM ( 'NONE', ( #194 ), #143 ) ;
+#167 = PRESENTATION_LAYER_ASSIGNMENT (  '', '', ( #166 ) ) ;
+#168 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#169 = FACE_OUTER_BOUND ( 'NONE', #117, .T. ) ;
+#170 = FILL_AREA_STYLE_COLOUR ( '', #188 ) ;
+#171 = AXIS2_PLACEMENT_3D ( 'NONE', #35, #164, #121 ) ;
+#172 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#173 = PRODUCT_RELATED_PRODUCT_CATEGORY ( 'part', '', ( #116 ) ) ;
+#174 = ORIENTED_EDGE ( 'NONE', *, *, #94, .F. ) ;
+#175 = EDGE_LOOP ( 'NONE', ( #157, #96 ) ) ;
+#176 = PRESENTATION_LAYER_ASSIGNMENT (  '', '', ( #127 ) ) ;
+#177 = LINE ( 'NONE', #136, #151 ) ;
+#178 = ORIENTED_EDGE ( 'NONE', *, *, #25, .F. ) ;
+#179 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#180 = SURFACE_STYLE_FILL_AREA ( #131 ) ;
+#181 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#182 = CARTESIAN_POINT ( 'NONE',  ( 4.286263797015735979E-17, 4.599999999999999645, 0.3499999999999999778 ) ) ;
+#183 = CYLINDRICAL_SURFACE ( 'NONE', #27, 0.2500000000000000000 ) ;
+#184 = UNCERTAINTY_MEASURE_WITH_UNIT (LENGTH_MEASURE( 1.000000000000000082E-05 ), #122, 'distance_accuracy_value', 'NONE');
+#185 =( NAMED_UNIT ( * ) PLANE_ANGLE_UNIT ( ) SI_UNIT ( $, .RADIAN. ) );
+#186 = ORIENTED_EDGE ( 'NONE', *, *, #126, .F. ) ;
+#187 = EDGE_CURVE ( 'NONE', #155, #24, #58, .T. ) ;
+#188 = COLOUR_RGB ( '',0.7921568627450980005, 0.8196078431372548767, 0.9333333333333333481 ) ;
+#189 = LINE ( 'NONE', #63, #5 ) ;
+#190 = ORIENTED_EDGE ( 'NONE', *, *, #126, .T. ) ;
+#191 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#192 = FACE_OUTER_BOUND ( 'NONE', #31, .T. ) ;
+#193 = SURFACE_SIDE_STYLE ('',( #180 ) ) ;
+#194 = PRESENTATION_STYLE_ASSIGNMENT (( #52 ) ) ;
+#195 = ADVANCED_FACE ( 'NONE', ( #169 ), #37, .T. ) ;
+#196 =( LENGTH_UNIT ( ) NAMED_UNIT ( * ) SI_UNIT ( .MILLI., .METRE. ) );
+#197 = CIRCLE ( 'NONE', #2, 0.3499999999999999778 ) ;
+#198 =( NAMED_UNIT ( * ) SI_UNIT ( $, .STERADIAN. ) SOLID_ANGLE_UNIT ( ) );
+#199 = ADVANCED_FACE ( 'NONE', ( #73 ), #183, .F. ) ;
+#200 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#201 = AXIS2_PLACEMENT_3D ( 'NONE', #162, #101, #79 ) ;
+#202 = DIRECTION ( 'NONE',  ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
+#203 = ORIENTED_EDGE ( 'NONE', *, *, #8, .F. ) ;
+#204 = APPLICATION_PROTOCOL_DEFINITION ( 'draft international standard', 'automotive_design', 1998, #71 ) ;
+#205 = EDGE_LOOP ( 'NONE', ( #95, #161, #178, #108 ) ) ;
+#206 = ADVANCED_BREP_SHAPE_REPRESENTATION ( 'rotor', ( #143, #159 ), #103 ) ;
+#207 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#208 = DIRECTION ( 'NONE',  ( 0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
+#209 = AXIS2_PLACEMENT_3D ( 'NONE', #213, #33, #32 ) ;
+#210 = CARTESIAN_POINT ( 'NONE',  ( 3.061616997868383018E-17, 4.599999999999999645, 0.2500000000000000000 ) ) ;
+#211 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
+#212 = CYLINDRICAL_SURFACE ( 'NONE', #22, 0.3499999999999999778 ) ;
+#213 = CARTESIAN_POINT ( 'NONE',  ( 0.000000000000000000, 4.599999999999999645, 0.000000000000000000 ) ) ;
+#214 = CARTESIAN_POINT ( 'NONE',  ( 3.061616997868383018E-17, 0.000000000000000000, 0.2500000000000000000 ) ) ;
+ENDSEC;
+END-ISO-10303-21;
diff --git a/final/saved_meshes/rotor.3MF b/final/saved_meshes/rotor.3MF
new file mode 100644
index 0000000000000000000000000000000000000000..aee8c9c8de5736e238ebbdd8bf24af75ff931cf3
Binary files /dev/null and b/final/saved_meshes/rotor.3MF differ
diff --git a/final/saved_meshes/rotor.STL b/final/saved_meshes/rotor.STL
new file mode 100644
index 0000000000000000000000000000000000000000..6e193c6cc8305a1d22f176a65977416da82579b4
Binary files /dev/null and b/final/saved_meshes/rotor.STL differ
diff --git a/final/saved_meshes/rotor1.STL b/final/saved_meshes/rotor1.STL
new file mode 100644
index 0000000000000000000000000000000000000000..00cafe062695e8b0e2d33e54de962688c599873b
Binary files /dev/null and b/final/saved_meshes/rotor1.STL differ
diff --git a/final/saved_meshes/stanford_original.stl b/final/saved_meshes/stanford_original.stl
new file mode 100644
index 0000000000000000000000000000000000000000..bec02fcb5de8a83bcdde97562619c6135c1146bf
Binary files /dev/null and b/final/saved_meshes/stanford_original.stl differ
diff --git a/final/scan_compare.blend b/final/scan_compare.blend
new file mode 100644
index 0000000000000000000000000000000000000000..404d050aeb0e622d4d4d8ae8b3d1d7388fff21ab
Binary files /dev/null and b/final/scan_compare.blend differ
diff --git a/final/scan_compare.blend1 b/final/scan_compare.blend1
new file mode 100644
index 0000000000000000000000000000000000000000..97b9f4d7770cba71652be1ba504fe0893f6c752b
Binary files /dev/null and b/final/scan_compare.blend1 differ
diff --git a/final/stanford.stl b/final/stanford.stl
new file mode 100644
index 0000000000000000000000000000000000000000..791b82b6a2d52943395e2add367e847e6079917a
Binary files /dev/null and b/final/stanford.stl differ
diff --git a/final/step_gui.py b/final/step_gui.py
new file mode 100644
index 0000000000000000000000000000000000000000..7fcb7d686285bb1c824457e73f3a3b290e0cb488
--- /dev/null
+++ b/final/step_gui.py
@@ -0,0 +1,19 @@
+import steputils
+
+# Get the path to the .step file
+file_path = "rotor.stp"
+
+# Create a STEP reader
+reader = steputils.Reader()
+
+# Read the file
+reader.read_file(file_path)
+
+# Get the shape from the reader
+shape = reader.shape()
+
+# Create a visualization of the shape
+visualizer = steputils.Visualizer()
+
+# Display the visualization
+visualizer.display(shape)
\ No newline at end of file
diff --git a/week13/17_1_LFSR.py b/week13/17_1_LFSR.py
new file mode 100644
index 0000000000000000000000000000000000000000..43576c4320bcb58959b1f09a8ea3c300da631554
--- /dev/null
+++ b/week13/17_1_LFSR.py
@@ -0,0 +1,92 @@
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib.animation as animation
+
+from pylfsr import LFSR
+import torch
+# print(torch.cuda.is_available())
+from torch import nn
+from torch.optim import Adam
+from torch import Tensor
+
+'''
+17_1:
+Train a multi-layer perceptron to predict the output of an order 10 maximal length linear feedback shift register 
+from the preceding 10 values, then generate new data by feeding the output back to the input and compare the generated and correct sequences.
+
+This XOR example was a helpful reference:
+https://www.youtube.com/watch?v=3I_66lyFOqI
+'''
+
+def create_data(state_0 = [1,0,0,0,0,0,0,0,0,0]):
+    L = LFSR(initstate = state_0, verbose = False)
+    x = []
+    y = []
+    for i in range(2**10):
+        x.append(L.state)
+        y.append([L.outbit])
+        L.next()
+    x = np.array(x, dtype = np.float32)
+    y = np.array(y, dtype = np.float32)
+    # override the first outbit which is -1
+    y[0] = [0]
+    return x, y
+
+class LFSRModel(nn.Module):
+    def __init__(self):
+        super().__init__()
+        self.layers = nn.Sequential(
+            nn.Linear(10, 10), # 2nd ten can be any number mapping the input size to some space 10x10 has 100 edges/numbers/weights
+            # linear is all just multiplictions of weights and inputs
+            nn.Sigmoid(), # sigmoid (or relu) creates a non-linearity threshold
+            nn.Linear(10, 10), # number of inputs, must be number of outputs, here we map all of the previous outputs to a single output
+            nn.Sigmoid(),
+            nn.Linear(10, 1), # number of inputs, must be number of outputs, here we map all of the previous outputs to a single output
+            nn.Sigmoid(),
+        )
+        self.optimizer = Adam(self.parameters()) # after you have the gradient, now we have to choose how to update the weights
+        self.loss = nn.MSELoss() # how we compare the predicted and actual values
+    
+    def forward(self, X):
+        return self.layers(X)
+    
+    def fit(self, X, y_true):
+        self.optimizer.zero_grad() # zero the gradients
+        y_pred = self.forward(X) # feed the network with an input
+        loss = self.loss(y_true, y_pred) # then calculate the loss (error between prediction and groudn truth)
+        loss.backward() # backwards calculates the gradients over every weight
+        self.optimizer.step() # then updates the weights
+        return loss.item()
+
+
+# Initialize the data and model
+xs, ys = create_data()
+# create a copy of the data
+real_solution = ys.copy()
+xs = Tensor(xs)
+ys = Tensor(ys)
+print(xs.shape)
+print(ys.shape)
+lfsr_model = LFSRModel()
+# print(lfsr_model(xs))
+
+# Now train the model, printing every mod epochs to get an idea of convergence
+EPOCHS = 5000
+for epoch in range(EPOCHS):
+    loss = lfsr_model.fit(xs, ys)
+    if epoch % 1000 == 0:
+        print(loss)
+
+# Now predict again
+new_model = lfsr_model(xs)
+new_model = np.round(new_model.detach().numpy()) # round the values to 0 or 1
+
+# return all indeces where real_sum and predicted_sum are different
+# this is where the model is wrong
+wrong = np.where(new_model != real_solution)[0]
+# fprint
+print("Number of wrong predictions: " + str(len(wrong)))
+print("Indeces where solution and predicted differ: " + str(wrong))
+print("Inputs with incorrect outputs: " + str(xs[wrong]))
+print("Predicted Values: " + str(new_model[wrong]))
+print("Solution Values: " + str(real_solution[wrong]))
\ No newline at end of file
diff --git a/week13/17_4_CARTPOLE.py b/week13/17_4_CARTPOLE.py
new file mode 100644
index 0000000000000000000000000000000000000000..269675fafdf4cdfbe9bc07d39b86d30824a932d7
--- /dev/null
+++ b/week13/17_4_CARTPOLE.py
@@ -0,0 +1,120 @@
+import torch as T
+import torch.nn as nn
+import torch.nn.functional as F
+import torch.optim as optim
+
+import numpy as np
+
+'''
+17_4:
+Use policy gradient reinforcement learning to balance an inverted pendulum mounted on a cart driven by a controller that you train.
+References:
+https://lilianweng.github.io/posts/2018-04-08-policy-gradient/
+https://www.youtube.com/watch?v=wc-FxNENg9U&t=87s
+
+We have two actions, push left or push right.
+We have four states, cart position, cart velocity, pole angle, and pole velocity at tip.
+
+Pole angle and velocity are also symmetric
+
+'''
+
+class DeepQNetwork(nn.Module):
+    def __init__(self, lr,input_dims, fc1_dims, fc2_dims, n_actions):
+        super(DeepQNetwork, self).__init__()
+        self.input_dims = input_dims
+        self.fc1_dims = fc1_dims
+        self.fc2_dims = fc2_dims
+        self.n_actions = n_actions
+        self.fc1 = nn.Linear(*self.input_dims,self.fc1_dims)
+        self.fc2 = nn.Linear(self.fc1_dims,self.fc2_dims)
+        self.fc3 = nn.Linear(self.fc2_dims,self.n_actions)
+        self.optimizer = optim.Adam(self.parameters(),lr=lr)
+        self.loss = nn.MSELoss()
+        self.device = T.device('cuda:0' if T.cuda.is_available() else 'cpu')
+        self.to(self.device)
+
+    def forward(self,state):
+        x = F.relu(self.fc1(state))
+        x = F.relu(self.fc2(x))
+        actions = self.fc3(x)
+
+        return actions
+    
+class Agent():
+    def __init__(self, gamma, epsilon, lr, input_dims, batch_size, n_actions,
+                 max_mem_size=100000, eps_end=0.01, eps_dec=5e-4):
+        self.gamma = gamma
+        self.epsilon = epsilon
+        self.eps_min = eps_end
+        self.eps_dec = eps_dec
+        self.lr = lr
+        self.action_space = [i for i in range(n_actions)]
+        self.mem_size = max_mem_size
+        self.batch_size = batch_size
+        self.mem_cntr = 0
+
+        self.Q_eval = DeepQNetwork(self.lr, n_actions=n_actions, input_dims=input_dims,
+                                    fc1_dims=256, fc2_dims=256)
+        self.state_memory = np.zeros((self.mem_size,*input_dims), dtype=np.float32)
+        self.new_state_memory = np.zeros((self.mem_size,*input_dims), dtype=np.float32)
+        self.action_memory = np.zeros(self.mem_size, dtype=np.int32)
+        self.reward_memory = np.zeros(self.mem_size, dtype=np.float32)
+        self.terminal_memory = np.zeros(self.mem_size, dtype=np.bool) # whether the state is terminal or not (game is done or not)
+
+    def store_transition(self, state, action, reward, state_, terminal):
+        index = self.mem_cntr % self.mem_size
+        self.state_memory[index] = state
+        self.new_state_memory[index] = state_
+        self.reward_memory[index] = reward
+        self.terminal_memory[index] = terminal
+        self.action_memory[index] = action
+
+        self.mem_cntr += 1
+
+    def choose_action(self, observation):
+        if np.random.random() > self.epsilon:
+            state = T.tensor([observation]).to(self.Q_eval.device)
+            actions = self.Q_eval.forward(state)
+            action = T.argmax(actions).item()
+        else:
+            action = np.random.choice(self.action_space)
+
+        return action
+    
+    def learn(self):
+        """
+        Get's called every step
+        """
+        if self.mem_cntr < self.batch_size:
+            return
+
+        self.Q_eval.optimizer.zero_grad()
+
+        max_mem = self.mem_cntr if self.mem_cntr < self.mem_size else self.mem_size
+
+        batch = np.random.choice(max_mem,self.batch_size,replace=False)
+
+        batch_index = np.arange(self.batch_size,dtype=np.int32)
+
+        state_batch = T.tensor(self.state_memory[batch]).to(self.Q_eval.device)
+        new_state_batch = T.tensor(self.new_state_memory[batch]).to(self.Q_eval.device)
+        reward_batch = T.tensor(self.reward_memory[batch]).to(self.Q_eval.device)
+        terminal_batch = T.tensor(self.terminal_memory[batch]).to(self.Q_eval.device)
+        action_batch = self.action_memory[batch]
+
+        q_eval = self.Q_eval.forward(state_batch)[batch_index,action_batch]
+        q_next = self.Q_eval.forward(new_state_batch)
+        q_next[terminal_batch] = 0.0
+
+        q_target = reward_batch + self.gamma*T.max(q_next,dim=1)[0] # returns a tuple of (values,indices), we want the value so [0]
+
+        loss = self.Q_eval.loss(q_target,q_eval).to(self.Q_eval.device)
+        loss.backward()
+        self.Q_eval.optimizer.step()
+
+        self.epsilon = self.epsilon - self.eps_dec if self.epsilon > self.eps_min else self.eps_min
+
+import gym
+if __name__ == '__main__':
+    
\ No newline at end of file
diff --git a/week13/README.MD b/week13/README.MD
new file mode 100644
index 0000000000000000000000000000000000000000..905211c291f23b4089adf278b0fd7bf8046a8099
--- /dev/null
+++ b/week13/README.MD
@@ -0,0 +1,21 @@
+# Week 12 - Search
+
+## Rosenbrock search with Nelder Mead
+
+<img src="img/nelder_mead.jpg" height="500">
+
+## Rosenbrock search with Gradient Descent
+
+Had to add pretty substantial inertia to get all the way to the edge of the banana
+
+<img src="img/grad_descent.jpg" height="500">
+
+## Rosenbrock search with CMA_ES
+
+Using the nicely packaged cmaes library here
+
+<img src="img/cmaes_rosenbrock.gif" height="500">
+
+To be sure I searched a parabola as well:
+
+<img src="img/cmaes_parabola.gif" height="500">
\ No newline at end of file
diff --git a/week13/img/cmaes_parabola.gif b/week13/img/cmaes_parabola.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4d830871a31faad153e5aa70e50584a3ccc6128b
Binary files /dev/null and b/week13/img/cmaes_parabola.gif differ
diff --git a/week13/img/cmaes_rosenbrock.gif b/week13/img/cmaes_rosenbrock.gif
new file mode 100644
index 0000000000000000000000000000000000000000..8a66fb5449b566749fdd9fc9306bbe3daa45364f
Binary files /dev/null and b/week13/img/cmaes_rosenbrock.gif differ
diff --git a/week13/img/grad_descent.jpg b/week13/img/grad_descent.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ffe19a50614792074531996792a08bc57dbd3805
Binary files /dev/null and b/week13/img/grad_descent.jpg differ
diff --git a/week13/img/nelder_mead.jpg b/week13/img/nelder_mead.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..b2bd816f79ab55f155f212df1be319679eb9a7e5
Binary files /dev/null and b/week13/img/nelder_mead.jpg differ
diff --git a/week6/README.MD b/week6/README.MD
index 0e1b8b91f03a0ab9589d63988bb4bc028442c6e1..610bcfd6a81291c23ba879e7c47cea4835ae5fd9 100644
--- a/week6/README.MD
+++ b/week6/README.MD
@@ -1,3 +1,3 @@
 # Week 6 - Finite Elements
 
-## 10.2
\ No newline at end of file
+<img src="img/6_2.png" height="500">
\ No newline at end of file
diff --git a/week6/img/6_2.png b/week6/img/6_2.png
new file mode 100644
index 0000000000000000000000000000000000000000..13221ced604e40693d66794b7a720dc8f9df2999
Binary files /dev/null and b/week6/img/6_2.png differ
diff --git a/week6/week6_2.py b/week6/week6_2.py
index a049a74dffad1a6ba959594ed0e8575f16a66dce..963ab3404750e19e7d966901761755105f107381 100644
--- a/week6/week6_2.py
+++ b/week6/week6_2.py
@@ -5,11 +5,11 @@ import matplotlib.animation as animation
 from matplotlib.animation import FuncAnimation, writers
 
 '''
-Adapted from: https://polymerfem.com/full-finite-element-solver-in-100-lines-of-python/
 6.2)
 Model the bending of a beam (equation 10.29) under an applied load. Use Hermite polynomial interpolation,
 and boundary conditions fixing the displacement and slope at one end, and applying a force at the other end.
 V = int(0, L)[0.5*EI * (d^2u/dx^2)^2 - u(x) * f(x)]dx
+Adapted from: https://polymerfem.com/full-finite-element-solver-in-100-lines-of-python/
 '''
 
 # Supporting functions
@@ -115,7 +115,7 @@ plt.axis('equal')
 plt.show()
 
 # my_dpi = 96
-# f = r"c://Users/david/Desktop/NMM/week5/img/wave_no_damp.gif" 
+# f = r"c://Users/david/Desktop/NMM/week6/img/beam.gif" 
 # fps2 = 20
 # writervideo = animation.FFMpegWriter(fps=fps2, extra_args=['-vcodec', 'libx264']) 
 # anim.save(f, writer='imagemagick', fps=fps2, dpi=my_dpi)
\ No newline at end of file