.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples\adaptive_library\OblongStatorDuct.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_adaptive_library_OblongStatorDuct.py: Oblong stator ducts with thermal adjustment ================= This script applies the adaptive templates functionality to modify rectangular ducts into oblong ducts. Further, the thermal effect of modified duct is taken into account by modifying the area adjustment under housing water jacket in thermal module. .. GENERATED FROM PYTHON SOURCE LINES 31-38 Perform required imports ------------------------ Import ``pymotorcad`` to access Motor-CAD. Import ``Arc``, ``Line``, ``Coordinate``, ``rt_to_xy``, ``xy_to_rt``, ``math`` to define the adaptive template geometry. Import ``os``, ``shutil``, ``sys``, and ``tempfile`` to open and save a temporary .mot file if none is open. .. GENERATED FROM PYTHON SOURCE LINES 38-48 .. code-block:: Python import math import os import shutil import sys import tempfile import ansys.motorcad.core as pymotorcad from ansys.motorcad.core.geometry import Arc, Coordinate, Line, rt_to_xy, xy_to_rt .. GENERATED FROM PYTHON SOURCE LINES 50-61 Connect to Motor-CAD -------------------- If this script is loaded into the Adaptive Templates file in Motor-CAD, the current Motor-CAD instance is used. If the script is run externally, these actions occur: a new Motor-CAD instance is opened, the e9 IPM motor template is loaded and set up with rectangular stator ducts, and the file is saved to a temporary folder. To keep a new Motor-CAD instance open after executing the script, use the ``MotorCAD(keep_instance_open=True)`` option when opening the new instance. Alternatively, use the ``MotorCAD()`` method, which closes the Motor-CAD instance after the script is executed. .. GENERATED FROM PYTHON SOURCE LINES 61-93 .. code-block:: Python if pymotorcad.is_running_in_internal_scripting(): # Use existing Motor-CAD instance if possible mc = pymotorcad.MotorCAD(open_new_instance=False) else: mc = pymotorcad.MotorCAD(keep_instance_open=True) # Disable popup messages mc.set_variable("MessageDisplayState", 2) mc.set_visible(True) mc.load_template("e9") mc.set_variable("StatorDuctType", 4) # selected rectangular ducts mc.set_variable("CircularDuctLayers", 1) # set number of duct layers mc.set_variable("CircularDuctL1RadialDiameter", 180) # set number of duct radial diameter mc.set_variable("CircularDuctL1ChannelWidth", 2) # set duct width mc.set_variable("CircularDuctL1ChannelHeight", 3) # set duct height mc.set_variable("CircularDuctL1Channels", 48) # set number of duct channels mc.set_variable("HousingType", 0) # set housing type to 'Round' # Open relevant file working_folder = os.path.join(tempfile.gettempdir(), "adaptive_library") try: shutil.rmtree(working_folder) except: pass os.mkdir(working_folder) mot_name = "Oblong_duct" mc.save_to_file(working_folder + "/" + mot_name + ".mot") # Reset geometry to default mc.reset_adaptive_geometry() .. GENERATED FROM PYTHON SOURCE LINES 94-100 Define necessary functions -------------------------- Set adaptive parameter if required ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ``set_default_parameter`` function is defined to check if a parameter exists. If not, it creates the parameter with a default value. .. GENERATED FROM PYTHON SOURCE LINES 100-107 .. code-block:: Python def set_default_parameter(parameter_name, default_value): try: mc.get_adaptive_parameter_value(parameter_name) except pymotorcad.MotorCADError: mc.set_adaptive_parameter_value(parameter_name, default_value) .. GENERATED FROM PYTHON SOURCE LINES 108-116 Check line distance from origin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The rectangle consists of two lines of length equal to the rectangle width. Only the top and bottom lines requires modification. It is necessary to check whether the line is closest to the origin. As this will affect the center of arcs needs to convert the lines. Index ``i`` is the line under investigation. Index ``j`` is the adjacent line. If the radius of midpoint of line ``i`` is less than that of line ``j`` , line ``i`` is closer to the origin. .. GENERATED FROM PYTHON SOURCE LINES 116-135 .. code-block:: Python def check_line_origin_distance(i, duct_region): if i == 0: # first index of rectangle duct j = 1 else: j = i - 1 rad_start_i, _ = xy_to_rt(duct_region.entities[i].start.x, duct_region.entities[i].start.y) rad_end_i, _ = xy_to_rt(duct_region.entities[i].end.x, duct_region.entities[i].end.y) rad_mid_i = (rad_start_i + rad_end_i) / 2 rad_start_j, _ = xy_to_rt(duct_region.entities[j].start.x, duct_region.entities[j].start.y) rad_end_j, _ = xy_to_rt(duct_region.entities[j].end.x, duct_region.entities[j].end.y) rad_mid_j = (rad_start_j + rad_end_j) / 2 if rad_mid_i < rad_mid_j: return True else: return False .. GENERATED FROM PYTHON SOURCE LINES 136-140 Generate arc associated with oblong duct ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Two separate functions are needed depending on full duct or half duct (due to symmetry) is present under Geometry Editor .. GENERATED FROM PYTHON SOURCE LINES 140-190 .. code-block:: Python def get_arc_radius(entity_start, entity_end, height): # Generate arc radius and center based on # line and arc height start_point_xy = [entity_start.x, entity_start.y] end_point_xy = [entity_end.x, entity_end.y] x = math.dist(start_point_xy, end_point_xy) / 2 # chord length/2 y = height # conversion to polar coordinates start_point_r, start_point_t = xy_to_rt(entity_start.x, entity_start.y) end_point_r, end_piont_t = xy_to_rt(entity_end.x, entity_end.y) r = (x**2 + y**2) / (2 * y) # radius return r def get_arc_radius_halfduct(entity_start, entity_end, height, Line_origin, Symm_angle): # Generate arc radius, center, start and end point based on for half duct # line and arc height start_point_xy = [entity_start.x, entity_start.y] end_point_xy = [entity_end.x, entity_end.y] x = math.dist(start_point_xy, end_point_xy) # chord length y = height start_point_r, start_point_t = xy_to_rt(entity_start.x, entity_start.y) end_point_r, end_piont_t = xy_to_rt(entity_end.x, entity_end.y) r = (x**2 + y**2) / (2 * y) # radius if Line_origin == True: # line is closer to origin if start_point_t == 0 or round(start_point_t / Symm_angle, 2) == 1: # start point is on symmetry boundary of geometry new_start_x, new_start_y = rt_to_xy(start_point_r - height, start_point_t) new_end_x, new_end_y = entity_end.x, entity_end.y elif end_piont_t == 0 or round(end_piont_t / Symm_angle, 2) == 1: # end point is on symmetry boundary of geometry new_start_x, new_start_y = entity_start.x, entity_start.y new_end_x, new_end_y = rt_to_xy(end_point_r - height, end_piont_t) else: # Line is far from origin if start_point_t == 0 or round(start_point_t / Symm_angle, 2) == 1: # start point is on symmetry boundary of geometry new_start_x, new_start_y = rt_to_xy(start_point_r + height, start_point_t) new_end_x, new_end_y = entity_end.x, entity_end.y elif end_piont_t == 0 or round(end_piont_t / Symm_angle, 2) == 1: # end point is on symmetry boundary of geometry new_start_x, new_start_y = entity_start.x, entity_start.y new_end_x, new_end_y = rt_to_xy(end_point_r + height, end_piont_t) new_start_point = Coordinate(new_start_x, new_start_y) new_end_point = Coordinate(new_end_x, new_end_y) return r, new_start_point, new_end_point .. GENERATED FROM PYTHON SOURCE LINES 191-197 Get required parameters and objects ----------------------------------- From Motor-CAD, get the adaptive parameters and their values. Use the ``set_default_parameter()`` method to set the required ``Duct Arc Height`` parameter if undefined. .. GENERATED FROM PYTHON SOURCE LINES 197-200 .. code-block:: Python set_default_parameter("Duct Arc Height", 0.7) .. GENERATED FROM PYTHON SOURCE LINES 201-203 Set required parameters for the oblong: height of arc ``Duct Arc Height``, duct width and duct height. .. GENERATED FROM PYTHON SOURCE LINES 203-208 .. code-block:: Python duct_arc_height = mc.get_adaptive_parameter_value("Duct Arc Height") duct_height = mc.get_variable("CircularDuctL1ChannelHeight") duct_width = mc.get_variable("CircularDuctL1ChannelWidth") duct_area = duct_height * duct_width .. GENERATED FROM PYTHON SOURCE LINES 209-210 Get the standard template stator region. This can be drawn for debugging if required. .. GENERATED FROM PYTHON SOURCE LINES 210-212 .. code-block:: Python st_region = mc.get_region("stator") # get the stator region .. GENERATED FROM PYTHON SOURCE LINES 213-227 Create the Adaptive Templates geometry -------------------------------------- For each child region of the stator region: * Check whether the region is a stator duct. * Find the top and bottom lines that makes up the duct. * Modify the lines with respective arcs. * Set the region in Motor-CAD. The script accounts for whether ducts are full ducts or half ducts (the case when a duct spans the rotor pole boundary) .. GENERATED FROM PYTHON SOURCE LINES 227-293 .. code-block:: Python for child_name in st_region.child_names: if "StatorDuctFluidRegion" in child_name: duct_region = mc.get_region(child_name) if round(duct_region.area / duct_area, 2) == 1: # check if full duct is drawn for i, entity in enumerate(duct_region.entities): if round(entity.length / duct_width, 2) == 1: # check if the line is duct width # additional check in case width = height _, angle_start_point_angle = xy_to_rt(entity.start.x, entity.start.y) _, angle_end_point_angle = xy_to_rt(entity.end.x, entity.end.y) if ( abs(angle_end_point_angle - angle_start_point_angle) > 0.05 ): # 0.05 degree is tolerance # get radius and center # convert this line segment to Arc Line_origin = check_line_origin_distance( i, duct_region ) # line near of far from origin radius = get_arc_radius(entity.start, entity.end, duct_arc_height) Duct_Arc = Arc(entity.start, entity.end, radius=radius) duct_region.entities[i] = Duct_Arc elif round(duct_region.area / duct_area, 2) == 0.5: # if the half duct is drawn Symm_angle = 360 / duct_region.duplications # angle of symmetry for i, entity in enumerate(duct_region.entities): if ( round(entity.length / duct_width, 2) == 0.5 ): # check if the line is half duct width # additional check in case width/2 = height _, angle_start_point_angle = xy_to_rt(entity.start.x, entity.start.y) _, angle_end_point_angle = xy_to_rt(entity.end.x, entity.end.y) if ( abs(angle_end_point_angle - angle_start_point_angle) > 0.05 ): # 0.05 degree is tolerance # get radius and center # convert this line segment to Arc Line_origin = check_line_origin_distance(i, duct_region) radius, start_point, end_point = get_arc_radius_halfduct( entity.start, entity.end, duct_arc_height, Line_origin, Symm_angle ) Duct_Arc = Arc(start_point, end_point, radius=radius) duct_region.entities[i] = Duct_Arc elif round(entity.length / duct_height, 2) == 1: # modify the line on symmetry planes rad_start_point, angle_start_point = xy_to_rt(entity.start.x, entity.start.y) rad_end_point, angle_end_point = xy_to_rt(entity.end.x, entity.end.y) if angle_start_point == 0 and angle_end_point == 0: # line located at x=0 entity.start.x = entity.start.x - duct_arc_height entity.end.x = entity.end.x + duct_arc_height elif ( round(angle_start_point / Symm_angle, 2) == 1 and round(angle_end_point / Symm_angle, 2) == 1 ): # line on symmetry plane # start and end point follow anticlockwise naming convention rad_start_point = rad_start_point + duct_arc_height rad_end_point = rad_end_point - duct_arc_height new_start_x, new_start_y = rt_to_xy(rad_start_point, angle_start_point) new_end_x, new_end_y = rt_to_xy(rad_end_point, angle_end_point) start_point = Coordinate(new_start_x, new_start_y) end_point = Coordinate(new_end_x, new_end_y) duct_region.entities[i] = Line(start_point, end_point) mc.set_region(duct_region) .. GENERATED FROM PYTHON SOURCE LINES 294-296 .. image:: ../../images/adaptive_templates/OblongDuct.png :width: 600pt .. GENERATED FROM PYTHON SOURCE LINES 298-310 Apply surface area correction in Motor-CAD Thermal -------------------------------------------------- The oblong stator ducts can be used in the Motor-CAD Thermal model as channels for water jacket cooling. The **Housing Water Jacket** cooling model in Motor-CAD can be set up to use stator duct channels when a housing type without channels is selected in the **Geometry** tab. As of Motor-CAD v2024R2, the **Housing Water Jacket** calculations will use duct areas from the Motor-CAD Standard Template geometry - not the custom Adaptive Templates geometry. For example, when the stator duct geometry has been updated from rectangular to oblong shapes, the duct area has increased. For this example, the area increases from 6 mm\ :sup:`2` to 8.03852\ :sup:`2`. This can be seen in the **Geometry -> Editor -> Geometry** tab, or by using the ``area`` method for the duct region. .. GENERATED FROM PYTHON SOURCE LINES 312-314 .. image:: ../../images/adaptive_templates/OblongDuct_area.png :width: 600pt .. GENERATED FROM PYTHON SOURCE LINES 316-319 To account for this in the **Housing Water Jacket** cooling model, you can apply a cross section area adjustment. By default, this is set to 0. To see this in the Motor-CAD interface, go to the **Input Data -> Housing Water Jacket -> Fluid FLow** tab in the **Thermal** context. .. GENERATED FROM PYTHON SOURCE LINES 321-323 .. image:: ../../images/adaptive_templates/OblongDuct_HWJ_before.png :width: 600pt .. GENERATED FROM PYTHON SOURCE LINES 325-329 The appropriate area adjustment is calculated and applied within the Adaptive Templates script. To calculate the area adjustment, get the area of the stator duct regions using the ``area`` method. For the case where there are two half-ducts, it is necessary to get the area for all duct regions and to calculate the sum of the areas. .. GENERATED FROM PYTHON SOURCE LINES 329-339 .. code-block:: Python oblong_duct_areas = [] num_slots = mc.get_variable("Slot_Number") num_ducts = mc.get_variable("CircularDuctL1Channels") ducts_per_slot = num_ducts / num_slots for child_name in st_region.child_names: if "StatorDuctFluidRegion" in child_name: oblong_duct_areas.append(mc.get_region(child_name).area) oblong_duct_area = sum(oblong_duct_areas) / ducts_per_slot .. GENERATED FROM PYTHON SOURCE LINES 340-342 The area of the original rectangular duct was already calculated earlier (``duct_area``). The area adjustment is calculated by subtracting the rectangular duct area from the oblong duct area. .. GENERATED FROM PYTHON SOURCE LINES 342-345 .. code-block:: Python area_adjustment = oblong_duct_area - duct_area .. GENERATED FROM PYTHON SOURCE LINES 346-347 Set the area adjustment value in Motor-CAD. .. GENERATED FROM PYTHON SOURCE LINES 347-349 .. code-block:: Python mc.set_array_variable("HousingWJ_Channel_CSArea_L1_A_Adjustment", 0, area_adjustment) .. GENERATED FROM PYTHON SOURCE LINES 350-352 The area adjustment is applied by the Adaptive Templates script and is updated any time the geometry is changed. .. GENERATED FROM PYTHON SOURCE LINES 354-356 .. image:: ../../images/adaptive_templates/OblongDuct_HWJ_after.png :width: 600pt .. GENERATED FROM PYTHON SOURCE LINES 358-368 Load in Adaptive Templates script if required --------------------------------------------- When this script is run externally, the script executes the following: * Set **Geometry type** to **Adaptive**. * Load the script into the **Adaptive Templates** tab. * Go to the **Geometry -> Radial** tab to run the Adaptive Templates script and display the new geometry. .. GENERATED FROM PYTHON SOURCE LINES 370-373 .. note:: When running in a Jupyter Notebook, you must provide the path for the Adaptive Templates script (PY file) instead of ``sys.argv[0]`` when using the ``load_adaptive_script()`` method. .. GENERATED FROM PYTHON SOURCE LINES 373-377 .. code-block:: Python if not pymotorcad.is_running_in_internal_scripting(): mc.set_variable("GeometryTemplateType", 1) mc.load_adaptive_script(sys.argv[0]) mc.display_screen("Geometry;Radial") .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 42.719 seconds) .. _sphx_glr_download_examples_adaptive_library_OblongStatorDuct.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: OblongStatorDuct.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: OblongStatorDuct.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: OblongStatorDuct.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_