From b3656f0ccee15c10e89630131cdc299481612d88 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Tue, 3 Jun 2025 11:02:40 -0500 Subject: [PATCH 01/12] draft --- ...stressed_modal_cyclic_symmetry_analysis.py | 666 ++++++++++++++++++ 1 file changed, 666 insertions(+) create mode 100644 examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py new file mode 100644 index 00000000..3b229a31 --- /dev/null +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -0,0 +1,666 @@ +# Copyright (C) 2023 - 2025 ANSYS, Inc. and/or its affiliates. +# SPDX-License-Identifier: MIT +# +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +""".. _ref_example_td_013: + +Centrifugal Impeller Analysis Using Cyclic Symmetry and Linear Perturbation +--------------------------------------------------------------------------- + +The impeller blade assembly in this example is a subsystem of a gas turbine +engine used in aerospace applications. The model consists of a shroud and +an impeller blade assembly with a sector angle of 27.692 degrees. The full +model is composed of 13 primary blades and splitters located at a distance +of 1 mm from the rigid wall at the start of the analysis. + +Coverage: +Modal, perturbed prestressed modal with linear and nonlinear base static +solution, full-harmonic are performed on the cyclic-sector model. +Cyclic symmetry is applied. +Pressure, rotational velocity and thermal boundary condition are applied. + +""" + +# %% +# Import necessary libraries +# ~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Import the required libraries for the analysis. +# The libraries include os, string, json for file handling and data manipulation, +# PIL for image processing, ansys.mechanical.core for Ansys Mechanical API, +# matplotlib for plotting and animation. +import os +import os.path + +from ansys.mechanical.core import App +from ansys.mechanical.core.examples import delete_downloads, download_file + +# %% +# Embed mechanical and set global variables +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Embed the Ansys Mechanical application and set the global variables. + +app = App(version=251) +app.update_globals(globals()) +print(app) + +cwd = os.path.join(os.getcwd(), "out") + +# %% +# Define function to display images +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Define a function to display images using matplotlib. +# The function takes the image name as input and displays the image using matplotlib. + + +def display_image(image_name): + plt.figure(figsize=(16, 9)) + plt.imshow(mpimg.imread(os.path.join(cwd, image_name))) + plt.xticks([]) + plt.yticks([]) + plt.axis("off") + plt.show() + + +# %% +# Configure graphics for image export +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Set the graphics resolution and background color for image export. +# The resolution is set to 1280x720 pixels, and the background color is set to white. + +Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Iso) +Graphics.Camera.SetFit() +image_export_format = GraphicsImageExportFormat.PNG +settings_720p = Ansys.Mechanical.Graphics.GraphicsImageExportSettings() +settings_720p.Resolution = GraphicsResolutionType.EnhancedResolution +settings_720p.Background = GraphicsBackgroundType.White +settings_720p.Width = 1280 +settings_720p.Height = 720 +settings_720p.CurrentGraphicsDisplay = False +Graphics.Camera.Rotate(180, CameraAxisType.ScreenY) + +# %% +# Download and Import CDB File +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Download the CDB file from the specified URL +# and save it to a temporary directory. +# The CDB file is then imported into the Ansys Mechanical model +# using the Model Import API. +# The CDB file is a pre-existing model file that contains +# the geometry and mesh information for the analysis. + +geometry_import_group = Model.GeometryImportGroup +geometry_import = geometry_import_group.AddModelImport() +geometry_path = download_file("cyclic_sector_model.cdb", "pymechanical", "embedding") +geometry_import.ModelImportSourceFilePath = geometry_path +geometry_import.UnitSystemTypeForImport = ModelImportUnitSystemType.UnitSystemMetricNMM +geometry_import.Import() + +app.plot() + +# %% +# Store all main tree nodes as variables +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Store the main tree nodes of the Ansys Mechanical model +# in variables for easy access. +# The variables include the model, geometry, mesh, +# named selections, connections, and coordinate systems. + +GEOM = ExtAPI.DataModel.Project.Model.Geometry +MSH = ExtAPI.DataModel.Project.Model.Mesh +NS_GRP = ExtAPI.DataModel.Project.Model.NamedSelections +CONN_GRP = ExtAPI.DataModel.Project.Model.Connections +CS_GRP = ExtAPI.DataModel.Project.Model.CoordinateSystems + +# %% +# Define and Select NMM Units System +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Define the unit system for the model as Standard NMM (Newton, millimeter). +# This unit system is commonly used in engineering applications +# and is suitable for the analysis being performed. + +ExtAPI.Application.ActiveUnitSystem = MechanicalUnitSystem.StandardNMM + +# %% +# Materials Assignment +# ~~~~~~~~~~~~~~~~~~~~~ +# Assign materials to the geometry components of the model. +# The materials are defined in the Ansys Mechanical +# database and are assigned to the geometry components based on their names. + +blade1 = GEOM.Children[1] +blade1.Material = "Structural Steel" +blade2 = GEOM.Children[2] +blade2.Material = "Structural Steel" + +# %% +# Coordinate System Definition +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Define a local coordinate system (LCS) for the model. + +LCS1 = CS_GRP.AddCoordinateSystem() +LCS1.CoordinateSystemType = CoordinateSystemTypeEnum.Cylindrical +LCS1.OriginX = Quantity("0 [mm]") +LCS1.OriginY = Quantity("0 [mm]") +LCS1.OriginZ = Quantity("0 [mm]") +LCS1.SecondaryAxisDefineBy = CoordinateSystemAlignmentType.GlobalZ + +# %% +# Add Named Selections +# ~~~~~~~~~~~~~~~~~~~~~ +# The named selections are used to specify the locations +# where loads and boundary conditions will be applied during the analysis. + +NS_LOW = NS_GRP.AddNamedSelection() +NS_LOW.Name = "NS_LOW" +NS_LOW.ScopingMethod = GeometryDefineByType.Worksheet + +GEN_CRT = NS_LOW.GenerationCriteria +CRT1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT1.Active = True +CRT1.Action = SelectionActionType.Add +CRT1.EntityType = SelectionType.GeoFace +CRT1.Criterion = SelectionCriterionType.Size +CRT1.Operator = SelectionOperatorType.Equal +CRT1.Value = Quantity("607.35 [mm^2]") +GEN_CRT.Add(CRT1) + +CRT2 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT2.Active = True +CRT2.Action = SelectionActionType.Filter +CRT2.EntityType = SelectionType.GeoFace +CRT2.Criterion = SelectionCriterionType.LocationZ +CRT2.Operator = SelectionOperatorType.Equal +CRT2.Value = Quantity("46.544 [mm]") +GEN_CRT.Add(CRT2) + +CRT3 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT3.Active = True +CRT3.Action = SelectionActionType.Add +CRT3.EntityType = SelectionType.GeoFace +CRT3.Criterion = SelectionCriterionType.Size +CRT3.Operator = SelectionOperatorType.Equal +CRT3.Value = Quantity("997.65 [mm^2]") +GEN_CRT.Add(CRT3) + +CRT4 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT4.Active = True +CRT4.Action = SelectionActionType.Filter +CRT4.EntityType = SelectionType.GeoFace +CRT4.Criterion = SelectionCriterionType.LocationZ +CRT4.Operator = SelectionOperatorType.GreaterThan +CRT4.Value = Quantity("21 [mm]") +GEN_CRT.Add(CRT4) +NS_LOW.Activate() +NS_LOW.Generate() + +NS_HIGH = NS_GRP.AddNamedSelection() +NS_HIGH.Name = "NS_LOW" +NS_HIGH.ScopingMethod = GeometryDefineByType.Worksheet + +GEN_CRT = NS_HIGH.GenerationCriteria +CRT1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT1.Active = True +CRT1.Action = SelectionActionType.Add +CRT1.EntityType = SelectionType.GeoFace +CRT1.Criterion = SelectionCriterionType.Size +CRT1.Operator = SelectionOperatorType.Equal +CRT1.Value = Quantity("607.35 [mm^2]") +GEN_CRT.Add(CRT1) + +CRT2 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT2.Active = True +CRT2.Action = SelectionActionType.Filter +CRT2.EntityType = SelectionType.GeoFace +CRT2.Criterion = SelectionCriterionType.LocationZ +CRT2.Operator = SelectionOperatorType.Equal +CRT2.Value = Quantity("24.348 [mm]") +GEN_CRT.Add(CRT2) + +CRT3 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT3.Active = True +CRT3.Action = SelectionActionType.Add +CRT3.EntityType = SelectionType.GeoFace +CRT3.Criterion = SelectionCriterionType.Size +CRT3.Operator = SelectionOperatorType.Equal +CRT3.Value = Quantity("997.65 [mm^2]") +GEN_CRT.Add(CRT3) + +CRT4 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT4.Active = True +CRT4.Action = SelectionActionType.Filter +CRT4.EntityType = SelectionType.GeoFace +CRT4.Criterion = SelectionCriterionType.LocationX +CRT4.Operator = SelectionOperatorType.GreaterThan +CRT4.Value = Quantity("13 [mm]") +GEN_CRT.Add(CRT4) +NS_HIGH.Activate() +NS_HIGH.Generate() + +NS_PRES = NS_GRP.AddNamedSelection() +NS_PRES.Name = "NS_PRES" +NS_PRES.ScopingMethod = GeometryDefineByType.Worksheet + +GEN_CRT = NS_PRES.GenerationCriteria +CRT1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT1.Active = True +CRT1.Action = SelectionActionType.Add +CRT1.EntityType = SelectionType.GeoFace +CRT1.Criterion = SelectionCriterionType.Size +CRT1.Operator = SelectionOperatorType.Equal +CRT1.Value = Quantity("2423.7 [mm^2]") +GEN_CRT.Add(CRT1) + +CRT2 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT2.Active = True +CRT2.Action = SelectionActionType.Add +CRT2.EntityType = SelectionType.GeoFace +CRT2.Criterion = SelectionCriterionType.Size +CRT2.Operator = SelectionOperatorType.Equal +CRT2.Value = Quantity("101.11 [mm^2]") +GEN_CRT.Add(CRT2) +NS_PRES.Activate() +NS_PRES.Generate() + +NS_BODIES = NS_GRP.AddNamedSelection() +NS_BODIES.Name = "NS_BODIES" +NS_BODIES.ScopingMethod = GeometryDefineByType.Worksheet + +GEN_CRT = NS_BODIES.GenerationCriteria +CRT1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT1.Active = True +CRT1.Action = SelectionActionType.Add +CRT1.EntityType = SelectionType.GeoBody +CRT1.Criterion = SelectionCriterionType.Size +CRT1.Operator = SelectionOperatorType.GreaterThan +CRT1.Value = Quantity("1 [mm^3]") +GEN_CRT.Add(CRT1) +NS_BODIES.Activate() +NS_BODIES.Generate() + +NS_RESP_VERTEX = NS_GRP.AddNamedSelection() +NS_RESP_VERTEX.Name = "NS_RESP_VERTEX" +NS_RESP_VERTEX.ScopingMethod = GeometryDefineByType.Worksheet + +GEN_CRT = NS_RESP_VERTEX.GenerationCriteria +CRT1 = Ansys.ACT.Automation.Mechanical.NamedSelectionCriterion() +CRT1.Active = True +CRT1.Action = SelectionActionType.Add +CRT1.EntityType = SelectionType.GeoVertex +CRT1.Criterion = SelectionCriterionType.LocationX +CRT1.Operator = SelectionOperatorType.Equal +CRT1.Value = Quantity("96.3 [mm]") +GEN_CRT.Add(CRT1) +NS_RESP_VERTEX.Activate() +NS_RESP_VERTEX.Generate() + +# %% +# Add and Define Premeshed Cyclic Region +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Add a symmetry region to the model to define the +# cyclic symmetry boundary conditions. +# The symmetry region is defined by specifying the +# low and high boundary locations,the coordinate system, +# and the number of sectors. +# The symmetry region allows for the analysis of a smaller +# portion of the model while accounting for the cyclic +# nature of the full model. + +SYMM = Model.AddSymmetry() +SYMMETRY_REGION = SYMM.AddPreMeshedCyclicRegion() +SYMMETRY_REGION.LowBoundaryLocation = NS_LOW +SYMMETRY_REGION.HighBoundaryLocation = NS_HIGH +SYMMETRY_REGION.CoordinateSystem = LCS1 +SYMMETRY_REGION.NumberOfSectors = 13 + +# %% +# Define Analysis +# ~~~~~~~~~~~~~~~~~~~~ +# The analysis type is set to Modal, which is used to +# determine the natural frequencies and mode shapes of the system. +# The analysis is performed in a cyclic symmetry environment, +# which allows for the analysis of a smaller portion of the +# model while accounting for the cyclic nature of the full model. +# The analysis is defined with a maximum of 2 modes to find +# and a harmonic index range of 0 to 6. +# The harmonic index is used to specify the frequency range for the analysis. +# The analysis settings and solution settings are defined for the modal analysis. + +modal = Model +MODAL01 = modal.AddModalAnalysis() + +# Solve first standalone Modal analysis +ANA_SETTING_MODAL01 = Model.Analyses[0].AnalysisSettings +SOLN_MODAL01 = Model.Analyses[0].Solution + +ANA_SETTING_MODAL01.MaximumModesToFind = 2 +ANA_SETTING_MODAL01.HarmonicIndexRange = CyclicHarmonicIndex.Manual +ANA_SETTING_MODAL01.MaximumHarmonicIndex = 6 + +# %% +# Insert results +# ~~~~~~~~~~~~~~~~ +# Insert results for the modal analysis. +# The results include the total deformation, which is +# used to visualize the mode shapes of the system. +# The total deformation is calculated based on the modal analysis results. + +TOT_DEF_MODAL01 = SOLN_MODAL01.AddTotalDeformation() + +# %% +# Solve Modal Analysis +# ~~~~~~~~~~~~~~~~~~~~~ +# Solve the modal analysis to obtain the natural frequencies and mode shapes of the system. +# The solution is performed for the specified number of modes and harmonic indices. +# The results are stored in the solution object for further analysis and visualization. +SOLN_MODAL01.Solve(True) +SOLN_MODAL01_SS = SOLN_MODAL01.Status + +app.save_as(os.path.join(cwd, "prestressed.mechdb"), overwrite=True) +# sphinx_gallery_start_ignore +assert str(SOLN_MODAL01_SS) == "Done", "Solution status is not 'Done'" +# sphinx_gallery_end_ignore + +H0_FRQ1_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][0] +H0_FRQ2_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][1] +H1_FRQ1_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][2] +H1_FRQ2_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][3] +H2_FRQ1_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][4] +H2_FRQ2_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][5] +H3_FRQ1_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][6] +H3_FRQ2_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][7] +H4_FRQ1_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][8] +H4_FRQ2_MODAL01 = TOT_DEF_MODAL01.TabularData["Frequency"][9] + +# %% +# Add Static Structural Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The static structural analysis is used to analyze +# the response of the system under static loading conditions. +# The analysis is performed in a cyclic symmetry environment, +# which allows for the analysis of a smaller portion +# of the model while accounting for the cyclic nature of the full model. +# The analysis settings and solution settings are defined for the static structural analysis. +# The analysis is set to be a linear static analysis, which means that the response of the system +# is assumed to be linear with respect to the applied loads. + +STAT_STRUC01 = modal.AddStaticStructuralAnalysis() +ANA_SETTING_STAT_STRUC01 = Model.Analyses[1].AnalysisSettings +SOLN_STAT_STRUC01 = Model.Analyses[1].Solution + +# %% +# Apply Loads and Boundary Conditions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Apply pressure, rotational velocity and thermal boundary conditions + +PRES_STAT_STRUC01 = STAT_STRUC01.AddPressure() +PRES_STAT_STRUC01.Location = NS_PRES +PRES_STAT_STRUC01.Magnitude.Output.DiscreteValues = [Quantity("20 [MPa]")] + +ROT_VEL_STAT_STRUC01 = STAT_STRUC01.AddRotationalVelocity() +ROT_VEL_STAT_STRUC01.DefineBy = LoadDefineBy.Components +ROT_VEL_STAT_STRUC01.CoordinateSystem = LCS1 +ROT_VEL_STAT_STRUC01.ZComponent.Output.DiscreteValues = [Quantity("3000 [rad sec^-1]")] + +THERM_COND_STRUC01 = STAT_STRUC01.AddThermalCondition() +THERM_COND_STRUC01.Location = NS_BODIES +THERM_COND_STRUC01.Magnitude.Output.DiscreteValues = [Quantity("50 [C]")] + +# %% +# Add Modal to perform prestress modal analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Setup and solve prestress modal analysis +# The prestress modal analysis is used to analyze the +# response of the system under prestressed conditions. + +MODAL02 = modal.AddModalAnalysis() +Pre_Stress02 = MODAL02.Children[0] +Pre_Stress02.PreStressICEnvironment = Model.Analyses[1] +ANA_SETTING_MODAL02 = Model.Analyses[2].AnalysisSettings +SOLN_MODAL02 = Model.Analyses[2].Solution + +ANA_SETTING_MODAL02.MaximumModesToFind = 2 +ANA_SETTING_MODAL02.HarmonicIndexRange = CyclicHarmonicIndex.Manual +ANA_SETTING_MODAL02.MaximumHarmonicIndex = 6 + +# %% +# Insert results +# ~~~~~~~~~~~~~~~~ +# Insert results for the prestress modal analysis. + +TOT_DEF_MODAL02 = SOLN_MODAL02.AddTotalDeformation() + +# %% +# Solve Prestressed Modal Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Solve the prestress modal analysis to obtain +# the natural frequencies and mode shapes of the +# system under prestressed conditions. +# The solution is performed for the specified number +# of modes and harmonic indices. +# The results are stored in the solution object for +# further analysis and visualization. + +SOLN_MODAL02.Solve(True) +SOLN_MODAL02_SS = SOLN_MODAL02.Status +# sphinx_gallery_start_ignore +assert str(SOLN_MODAL02_SS) == "Done", "Solution status is not 'Done'" +# sphinx_gallery_end_ignore + +H0_FRQ1_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][0] +H0_FRQ2_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][1] +H1_FRQ1_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][2] +H1_FRQ2_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][3] +H2_FRQ1_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][4] +H2_FRQ2_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][5] +H3_FRQ1_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][6] +H3_FRQ2_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][7] +H4_FRQ1_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][8] +H4_FRQ2_MODAL02 = TOT_DEF_MODAL02.TabularData["Frequency"][9] + +# %% +# Add Static Structural to perform Non-linear Static Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Setup Non-linear Static Structural Analysis +# The non-linear static analysis is used to analyze the +# response of the system under non-linear loading conditions. +STAT_STRUC02 = modal.AddStaticStructuralAnalysis() +ANA_SETTING_STAT_STRUC02 = Model.Analyses[3].AnalysisSettings +SOLN_STAT_STRUC02 = Model.Analyses[3].Solution + +# %% +# Turn on large deflection option +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# This option is required for the non-linear static +# analysis to account for large displacements and rotations. + +ANA_SETTING_STAT_STRUC02.LargeDeflection = True + +# %% +# Apply Loads and Boundary Conditions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Apply pressure, rotational velocity and thermal boundary conditions + +PRES_STAT_STRUC02 = STAT_STRUC02.AddPressure() +PRES_STAT_STRUC02.Location = NS_PRES +PRES_STAT_STRUC02.Magnitude.Output.DiscreteValues = [Quantity("20 [MPa]")] + +ROT_VEL_STAT_STRUC02 = STAT_STRUC02.AddRotationalVelocity() +ROT_VEL_STAT_STRUC02.DefineBy = LoadDefineBy.Components +ROT_VEL_STAT_STRUC02.CoordinateSystem = LCS1 +ROT_VEL_STAT_STRUC02.ZComponent.Output.DiscreteValues = [Quantity("6000 [rad sec^-1]")] + +THERM_COND_STRUC02 = STAT_STRUC02.AddThermalCondition() +THERM_COND_STRUC02.Location = NS_BODIES +THERM_COND_STRUC02.Magnitude.Output.DiscreteValues = [Quantity("50 [C]")] + +# %% +# Add modal to perform prestress modal analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Setup and solve modal with prestress from non-linear static analysis + +MODAL03 = modal.AddModalAnalysis() +Pre_Stress03 = MODAL03.Children[0] +Pre_Stress03.PreStressICEnvironment = Model.Analyses[3] +ANA_SETTING_MODAL03 = Model.Analyses[4].AnalysisSettings +SOLN_MODAL03 = Model.Analyses[4].Solution + +ANA_SETTING_MODAL03.MaximumModesToFind = 2 +ANA_SETTING_MODAL03.HarmonicIndexRange = CyclicHarmonicIndex.Manual +ANA_SETTING_MODAL03.MaximumHarmonicIndex = 6 + +# %% +# Insert results +# ~~~~~~~~~~~~~~~~ +# Insert results for the prestress modal analysis. +# The results include the total deformation, which is used to +# visualize the mode shapes of the system. + +TOT_DEF_MODAL03 = SOLN_MODAL03.AddTotalDeformation() + +# %% +# Solve Prestressed Modal Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Solve the prestress modal analysis to obtain the natural +# frequencies and mode shapes of the system under prestressed conditions. +# The solution is performed for the specified number of modes and harmonic indices. +# The results are stored in the solution object for further analysis and visualization. + +SOLN_MODAL03.Solve(True) +SOLN_MODAL03_SS = SOLN_MODAL03.Status +# sphinx_gallery_start_ignore +assert str(SOLN_MODAL03_SS) == "Done", "Solution status is not 'Done'" +# sphinx_gallery_end_ignore + +H0_FRQ1_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][0] +H0_FRQ2_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][1] +H1_FRQ1_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][2] +H1_FRQ2_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][3] +H2_FRQ1_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][4] +H2_FRQ2_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][5] +H3_FRQ1_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][6] +H3_FRQ2_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][7] +H4_FRQ1_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][8] +H4_FRQ2_MODAL03 = TOT_DEF_MODAL03.TabularData["Frequency"][9] + +# %% +# Add Harmonic Response Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Setup and Solve Standalone FULL Harmonic Analysis +# The harmonic response analysis is used to analyze the +# response of the system under harmonic loading conditions. + +HARM_RESP01 = modal.AddHarmonicResponseAnalysis() +ANA_SETTING_HARM_RESP01 = Model.Analyses[5].AnalysisSettings +SOLN_HARM_RESP01 = Model.Analyses[5].Solution + +# %% +# Specify the frequency range for the harmonic response analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +ANA_SETTING_HARM_RESP01.RangeMinimum = Quantity("1200 [Hz]") +ANA_SETTING_HARM_RESP01.RangeMaximum = Quantity("5500 [Hz]") +ANA_SETTING_HARM_RESP01.SolutionIntervals = 10 + +# %% +# Specify Full Harmonic Response Analysis Method +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# The full harmonic response analysis method is used to +# analyze the response of the system under harmonic loading conditions. +# The method is specified as Full, which means that the analysis +# will consider the full frequency range specified above. + +ANA_SETTING_HARM_RESP01.SolutionMethod = HarmonicMethod.Full + +# %% +# Apply Structural Damping Coefficient +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Structural damping coefficient is used to account for +# energy dissipation in the material during dynamic loading. + +ANA_SETTING_HARM_RESP01.StructuralDampingCoefficient = 0.02 + +# %% +# Apply Loads and Boundary Conditions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Apply Pressure + +PRES_HARM_RESP01 = HARM_RESP01.AddPressure() +PRES_HARM_RESP01.Location = NS_PRES +PRES_HARM_RESP01.Magnitude.Output.DiscreteValues = [Quantity("20 [MPa]")] + +# %% +# Insert results +# ~~~~~~~~~~~~~~~ +# Insert results for the harmonic response analysis. +# The results include the total deformation, which is used to visualize +# the response of the system under harmonic loading conditions. +# The total deformation is calculated based on the harmonic response analysis.. +# The results are stored in the solution object for further analysis and visualization. + +FRQ_RES_DEF_HARM_RESP01 = SOLN_HARM_RESP01.AddDeformationFrequencyResponse() +FRQ_RES_DEF_HARM_RESP01.Location = NS_RESP_VERTEX +FRQ_RES_DEF_HARM_RESP01.NormalOrientation = NormalOrientationType.YAxis + +SOLN_HARM_RESP01.Activate() +TOT_DEF4_1 = SOLN_HARM_RESP01.AddTotalDeformation() +TOT_DEF4_1.Frequency = Quantity(3000, "Hz") +TOT_DEF4_1.Amplitude = True +TOT_DEF4_1.Name = "Total Deformation" +TOT_DEF4_1.CreateParameter("Maximum") + +SOLN_HARM_RESP01.Activate() +TOT_DEF4_2 = SOLN_HARM_RESP01.AddTotalDeformation() +TOT_DEF4_2.Frequency = Quantity(2500, "Hz") +TOT_DEF4_2.Amplitude = True +TOT_DEF4_2.Name = "Total Deformation 2" +TOT_DEF4_2.CreateParameter("Maximum") + +# %% +# Solve Full Harmonic Response Analysis +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Solve the full harmonic response analysis to obtain the frequency response of the system. + +SOLN_HARM_RESP01.Solve(True) +SOLN_HARM_RESP01_SS = SOLN_HARM_RESP01.Status +# sphinx_gallery_start_ignore +assert str(SOLN_HARM_RESP01_SS) == "Done", "Solution status is not 'Done'" +# sphinx_gallery_end_ignore + +# %% +# Post-process results +# ~~~~~~~~~~~~~~~~~~~~~~~~ +# Activate the results and set the view to isometric + +TOT_DEF4_1.Activate() +Graphics.Camera.SetFit() +Graphics.ExportImage( + os.path.join(cwd, "deform_frequency_response.png"), + image_export_format, + settings_720p, +) +display_image("deform_frequency_response.png") + + +# Close the app +app.close() + +# delete example file +delete_downloads() From afbcc941288112657fc0b6af3cf26e419549bc29 Mon Sep 17 00:00:00 2001 From: Dipin Nair Date: Fri, 20 Jun 2025 12:11:39 -0400 Subject: [PATCH 02/12] update globals --- .pre-commit-config.yaml | 4 ++-- .../prestressed_modal_cyclic_symmetry_analysis.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e3122edf..22302b6a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: rev: 1.19.1 hooks: - id: blacken-docs - additional_dependencies: [black==23.12.1] + additional_dependencies: [black==25.1.0] - repo: https://github.com/pycqa/isort rev: 6.0.1 @@ -44,4 +44,4 @@ repos: hooks: - id: add-license-headers args: - - --start_year=2023 \ No newline at end of file + - --start_year=2023 diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 3b229a31..5810dd41 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -51,14 +51,14 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file +from matplotlib import pyplot as plt # %% # Embed mechanical and set global variables # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Embed the Ansys Mechanical application and set the global variables. -app = App(version=251) -app.update_globals(globals()) +app = App(globals=globals()) print(app) cwd = os.path.join(os.getcwd(), "out") From 17c6942caf0f8d58a1c770239f6ff9424b5bbe51 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Sun, 22 Jun 2025 20:04:59 -0500 Subject: [PATCH 03/12] add save files --- .../prestressed_modal_cyclic_symmetry_analysis.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 5810dd41..512d96e5 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -112,6 +112,7 @@ def display_image(image_name): geometry_import.ModelImportSourceFilePath = geometry_path geometry_import.UnitSystemTypeForImport = ModelImportUnitSystemType.UnitSystemMetricNMM geometry_import.Import() +app.save_as(os.path.join(cwd, "after_cdb_import.mechdb"), overwrite=True) app.plot() @@ -370,10 +371,12 @@ def display_image(image_name): # Solve the modal analysis to obtain the natural frequencies and mode shapes of the system. # The solution is performed for the specified number of modes and harmonic indices. # The results are stored in the solution object for further analysis and visualization. +app.save_as(os.path.join(cwd, "before_solve_prestressed.mechdb"), overwrite=True) + SOLN_MODAL01.Solve(True) SOLN_MODAL01_SS = SOLN_MODAL01.Status -app.save_as(os.path.join(cwd, "prestressed.mechdb"), overwrite=True) +app.save_as(os.path.join(cwd, "after_solve_prestressed.mechdb"), overwrite=True) # sphinx_gallery_start_ignore assert str(SOLN_MODAL01_SS) == "Done", "Solution status is not 'Done'" # sphinx_gallery_end_ignore From f73cc6cd44ed7345633532b52b19d6f4f8c8021d Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Sun, 22 Jun 2025 20:08:41 -0500 Subject: [PATCH 04/12] upload exampels --- .github/workflows/ci_cd_nightly.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci_cd_nightly.yml b/.github/workflows/ci_cd_nightly.yml index 9b7f9acf..7bd1c1cf 100644 --- a/.github/workflows/ci_cd_nightly.yml +++ b/.github/workflows/ci_cd_nightly.yml @@ -102,18 +102,7 @@ jobs: ANSYS_WORKBENCH_LOGGING_FILTER_LEVEL: 0 run: | . /env/bin/activate - xvfb-run mechanical-env make -C doc html > doc_build_output.txt 2>&1 || true - cat doc_build_output.txt - # - # Check if "build succeeded" string is present in doc_build_output.txt - # - if grep -q "build succeeded" doc_build_output.txt; then - echo "Documentation building succeeded" - exit 0 - else - echo "Documentation building failed" - exit 1 - fi + xvfb-run mechanical-env make -C doc html - name: Upload HTML Documentation uses: actions/upload-artifact@v4 @@ -122,6 +111,13 @@ jobs: path: doc/_build/html retention-days: 7 + - name: Upload example output + uses: actions/upload-artifact@v4 + with: + name: examples + path: examples/02_technology_showcase + retention-days: 7 + build-failure: name: Teams notify on failure if: failure() From f0c065bf08d453cb6dc7f6d8118bae62c211b546 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Sun, 22 Jun 2025 20:53:05 -0500 Subject: [PATCH 05/12] fix mpig --- .github/workflows/ci_cd.yml | 7 +++++++ .../prestressed_modal_cyclic_symmetry_analysis.py | 1 + 2 files changed, 8 insertions(+) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 839291ad..7cb000e2 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -95,6 +95,13 @@ jobs: path: doc/_build/html retention-days: 7 + - name: Upload examples + uses: actions/upload-artifact@v4 + with: + name: examples-out + path: examples/02_technology_showcase + retention-days: 7 + doc-deploy: name: Documentation deploy runs-on: ubuntu-latest diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 512d96e5..a323aab4 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -51,6 +51,7 @@ from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file +from matplotlib import image as mpimg from matplotlib import pyplot as plt # %% From 297a8caeb90c42fcf67d622f9cb374bff1109b73 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Sun, 22 Jun 2025 22:53:32 -0500 Subject: [PATCH 06/12] fix styling --- ...stressed_modal_cyclic_symmetry_analysis.py | 145 +++++++++++------- 1 file changed, 92 insertions(+), 53 deletions(-) diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index a323aab4..5049ef28 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -39,63 +39,96 @@ """ -# %% -# Import necessary libraries -# ~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Import the required libraries for the analysis. -# The libraries include os, string, json for file handling and data manipulation, -# PIL for image processing, ansys.mechanical.core for Ansys Mechanical API, -# matplotlib for plotting and animation. -import os -import os.path +## %% +# Import the necessary libraries +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from pathlib import Path +from typing import TYPE_CHECKING from ansys.mechanical.core import App from ansys.mechanical.core.examples import delete_downloads, download_file from matplotlib import image as mpimg from matplotlib import pyplot as plt +if TYPE_CHECKING: + import Ansys + # %% -# Embed mechanical and set global variables -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Embed the Ansys Mechanical application and set the global variables. +# Initialize the embedded application +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -app = App(globals=globals()) +app = App(globals=globals(), version=251) print(app) -cwd = os.path.join(os.getcwd(), "out") # %% -# Define function to display images -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Define a function to display images using matplotlib. -# The function takes the image name as input and displays the image using matplotlib. - - -def display_image(image_name): - plt.figure(figsize=(16, 9)) - plt.imshow(mpimg.imread(os.path.join(cwd, image_name))) - plt.xticks([]) - plt.yticks([]) - plt.axis("off") +# Create functions to set camera and display images +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Set the path for the output files (images, gifs, mechdat) +output_path = Path.cwd() / "out" + + +def display_image( + image_path: str, + pyplot_figsize_coordinates: tuple = (16, 9), + plot_xticks: list = [], + plot_yticks: list = [], + plot_axis: str = "off", +) -> None: + """Display the image with the specified parameters. + + Parameters + ---------- + image_path : str + The path to the image file to display. + pyplot_figsize_coordinates : tuple + The size of the figure in inches (width, height). + plot_xticks : list + The x-ticks to display on the plot. + plot_yticks : list + The y-ticks to display on the plot. + plot_axis : str + The axis visibility setting ('on' or 'off'). + """ + # Set the figure size based on the coordinates specified + plt.figure(figsize=pyplot_figsize_coordinates) + # Read the image from the file into an array + image_path = str(output_path / image_path) + plt.imshow(mpimg.imread(image_path)) + # Get or set the current tick locations and labels of the x-axis + plt.xticks(plot_xticks) + # Get or set the current tick locations and labels of the y-axis + plt.yticks(plot_yticks) + # Turn off the axis + plt.axis(plot_axis) + # Display the figure plt.show() # %% # Configure graphics for image export -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Set the graphics resolution and background color for image export. -# The resolution is set to 1280x720 pixels, and the background color is set to white. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Define the graphics and camera +graphics = app.Graphics +camera = graphics.Camera + +# Set the camera orientation to the isometric view and set the camera to fit the model +camera.SetSpecificViewOrientation(ViewOrientationType.Iso) +camera.SetFit() -Graphics.Camera.SetSpecificViewOrientation(ViewOrientationType.Iso) -Graphics.Camera.SetFit() +# Set the image export format and settings image_export_format = GraphicsImageExportFormat.PNG settings_720p = Ansys.Mechanical.Graphics.GraphicsImageExportSettings() -settings_720p.Resolution = GraphicsResolutionType.EnhancedResolution -settings_720p.Background = GraphicsBackgroundType.White +settings_720p.Resolution = ( + Ansys.Mechanical.DataModel.Enums.GraphicsResolutionType.EnhancedResolution +) +settings_720p.Background = Ansys.Mechanical.DataModel.Enums.GraphicsBackgroundType.White settings_720p.Width = 1280 settings_720p.Height = 720 settings_720p.CurrentGraphicsDisplay = False -Graphics.Camera.Rotate(180, CameraAxisType.ScreenY) # %% # Download and Import CDB File @@ -106,15 +139,19 @@ def display_image(image_name): # using the Model Import API. # The CDB file is a pre-existing model file that contains # the geometry and mesh information for the analysis. +# Define the model -geometry_import_group = Model.GeometryImportGroup -geometry_import = geometry_import_group.AddModelImport() geometry_path = download_file("cyclic_sector_model.cdb", "pymechanical", "embedding") +model = app.Model + +# Add the geometry import to the geometry import group +geometry_import_group = model.GeometryImportGroup +geometry_import = geometry_import_group.AddModelImport() geometry_import.ModelImportSourceFilePath = geometry_path geometry_import.UnitSystemTypeForImport = ModelImportUnitSystemType.UnitSystemMetricNMM geometry_import.Import() -app.save_as(os.path.join(cwd, "after_cdb_import.mechdb"), overwrite=True) +# Visualize the model in 3D app.plot() # %% @@ -324,8 +361,8 @@ def display_image(image_name): # The symmetry region allows for the analysis of a smaller # portion of the model while accounting for the cyclic # nature of the full model. - -SYMM = Model.AddSymmetry() +model = app.Model +SYMM = model.AddSymmetry() SYMMETRY_REGION = SYMM.AddPreMeshedCyclicRegion() SYMMETRY_REGION.LowBoundaryLocation = NS_LOW SYMMETRY_REGION.HighBoundaryLocation = NS_HIGH @@ -345,12 +382,11 @@ def display_image(image_name): # The harmonic index is used to specify the frequency range for the analysis. # The analysis settings and solution settings are defined for the modal analysis. -modal = Model -MODAL01 = modal.AddModalAnalysis() +MODAL01 = model.AddModalAnalysis() # Solve first standalone Modal analysis -ANA_SETTING_MODAL01 = Model.Analyses[0].AnalysisSettings -SOLN_MODAL01 = Model.Analyses[0].Solution +ANA_SETTING_MODAL01 = model.Analyses[0].AnalysisSettings +SOLN_MODAL01 = model.Analyses[0].Solution ANA_SETTING_MODAL01.MaximumModesToFind = 2 ANA_SETTING_MODAL01.HarmonicIndexRange = CyclicHarmonicIndex.Manual @@ -372,12 +408,12 @@ def display_image(image_name): # Solve the modal analysis to obtain the natural frequencies and mode shapes of the system. # The solution is performed for the specified number of modes and harmonic indices. # The results are stored in the solution object for further analysis and visualization. -app.save_as(os.path.join(cwd, "before_solve_prestressed.mechdb"), overwrite=True) +app.save_as(str(output_path / "before_solve_prestressed.mechdb"), overwrite=True) SOLN_MODAL01.Solve(True) SOLN_MODAL01_SS = SOLN_MODAL01.Status -app.save_as(os.path.join(cwd, "after_solve_prestressed.mechdb"), overwrite=True) +app.save_as(str(output_path / "after_solve_prestressed.mechdb"), overwrite=True) # sphinx_gallery_start_ignore assert str(SOLN_MODAL01_SS) == "Done", "Solution status is not 'Done'" # sphinx_gallery_end_ignore @@ -405,7 +441,7 @@ def display_image(image_name): # The analysis is set to be a linear static analysis, which means that the response of the system # is assumed to be linear with respect to the applied loads. -STAT_STRUC01 = modal.AddStaticStructuralAnalysis() +STAT_STRUC01 = model.AddStaticStructuralAnalysis() ANA_SETTING_STAT_STRUC01 = Model.Analyses[1].AnalysisSettings SOLN_STAT_STRUC01 = Model.Analyses[1].Solution @@ -434,7 +470,7 @@ def display_image(image_name): # The prestress modal analysis is used to analyze the # response of the system under prestressed conditions. -MODAL02 = modal.AddModalAnalysis() +MODAL02 = model.AddModalAnalysis() Pre_Stress02 = MODAL02.Children[0] Pre_Stress02.PreStressICEnvironment = Model.Analyses[1] ANA_SETTING_MODAL02 = Model.Analyses[2].AnalysisSettings @@ -485,7 +521,7 @@ def display_image(image_name): # Setup Non-linear Static Structural Analysis # The non-linear static analysis is used to analyze the # response of the system under non-linear loading conditions. -STAT_STRUC02 = modal.AddStaticStructuralAnalysis() +STAT_STRUC02 = model.AddStaticStructuralAnalysis() ANA_SETTING_STAT_STRUC02 = Model.Analyses[3].AnalysisSettings SOLN_STAT_STRUC02 = Model.Analyses[3].Solution @@ -520,7 +556,7 @@ def display_image(image_name): # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Setup and solve modal with prestress from non-linear static analysis -MODAL03 = modal.AddModalAnalysis() +MODAL03 = model.AddModalAnalysis() Pre_Stress03 = MODAL03.Children[0] Pre_Stress03.PreStressICEnvironment = Model.Analyses[3] ANA_SETTING_MODAL03 = Model.Analyses[4].AnalysisSettings @@ -571,7 +607,7 @@ def display_image(image_name): # The harmonic response analysis is used to analyze the # response of the system under harmonic loading conditions. -HARM_RESP01 = modal.AddHarmonicResponseAnalysis() +HARM_RESP01 = model.AddHarmonicResponseAnalysis() ANA_SETTING_HARM_RESP01 = Model.Analyses[5].AnalysisSettings SOLN_HARM_RESP01 = Model.Analyses[5].Solution @@ -654,14 +690,17 @@ def display_image(image_name): # Activate the results and set the view to isometric TOT_DEF4_1.Activate() -Graphics.Camera.SetFit() -Graphics.ExportImage( - os.path.join(cwd, "deform_frequency_response.png"), +camera.SetFit() +camera.SetFit() +graphics.ExportImage( + str(output_path / "deform_frequency_response.png"), image_export_format, settings_720p, ) display_image("deform_frequency_response.png") +app.save_as(str(output_path / "final.mechdb"), overwrite=True) + # Close the app app.close() From 7e4ef60c4062ed41349e0b369877ead81c2fbd34 Mon Sep 17 00:00:00 2001 From: Dipin <26918585+dipinknair@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:21:20 -0500 Subject: [PATCH 07/12] Update examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py --- .../prestressed_modal_cyclic_symmetry_analysis.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 5049ef28..7fe8ab5f 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -149,6 +149,7 @@ def display_image( geometry_import = geometry_import_group.AddModelImport() geometry_import.ModelImportSourceFilePath = geometry_path geometry_import.UnitSystemTypeForImport = ModelImportUnitSystemType.UnitSystemMetricNMM +print(geometry_import.UnitSystemTypeForImport) geometry_import.Import() # Visualize the model in 3D From 5aecb4c4229c01b59343139c7b019828ae387502 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Sun, 6 Jul 2025 07:56:20 -0500 Subject: [PATCH 08/12] no core to 1 --- .../prestressed_modal_cyclic_symmetry_analysis.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 7fe8ab5f..79fee271 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -61,6 +61,10 @@ app = App(globals=globals(), version=251) print(app) +# set the number of cores to use for the solve process + +config = app.ExtAPI.Application.SolveConfigurations["My Computer"] +config.SolveProcessSettings.MaxNumberOfCores = 1 # %% # Create functions to set camera and display images From fae85d1d57ec660cbde31aec30d020cf4bbe0eaa Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 7 Jul 2025 06:19:38 -0500 Subject: [PATCH 09/12] more shm size --- .github/workflows/ci_cd.yml | 2 +- .../prestressed_modal_cyclic_symmetry_analysis.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index 7cb000e2..d752944b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -48,7 +48,7 @@ jobs: timeout-minutes: 60 container: image: ghcr.io/ansys/mechanical:25.1.0 - options: --entrypoint /bin/bash + options: --entrypoint /bin/bash --shm-size=2g needs: [style, doc-style] steps: diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 79fee271..77724d1f 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -63,8 +63,8 @@ # set the number of cores to use for the solve process -config = app.ExtAPI.Application.SolveConfigurations["My Computer"] -config.SolveProcessSettings.MaxNumberOfCores = 1 +# config = app.ExtAPI.Application.SolveConfigurations["My Computer"] +# config.SolveProcessSettings.MaxNumberOfCores = 1 # %% # Create functions to set camera and display images From e195bae078a4ec1ed6b312073281d61b7276dd95 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 7 Jul 2025 06:54:23 -0500 Subject: [PATCH 10/12] add mechanical-env --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index d752944b..74dc2f3e 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -86,7 +86,7 @@ jobs: SPHINXOPTS: '-j auto -W --keep-going' run: | . /env/bin/activate - xvfb-run make -C doc linkcheck + xvfb-run mechanical-env make -C doc linkcheck - name: Upload HTML Documentation uses: actions/upload-artifact@v4 From ec79257865d3df404053057bff0fa97b93872c7d Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Tue, 7 Oct 2025 14:35:11 -0500 Subject: [PATCH 11/12] remove version --- .../prestressed_modal_cyclic_symmetry_analysis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py index 77724d1f..01200a16 100644 --- a/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py +++ b/examples/02_technology_showcase/prestressed_modal_cyclic_symmetry_analysis.py @@ -58,7 +58,7 @@ # Initialize the embedded application # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -app = App(globals=globals(), version=251) +app = App(globals=globals()) print(app) # set the number of cores to use for the solve process From 28ff56bc87269021f9631828f1dc56c144fe0732 Mon Sep 17 00:00:00 2001 From: dkunhamb Date: Mon, 20 Oct 2025 23:18:03 -0500 Subject: [PATCH 12/12] use 261 --- .github/workflows/ci_cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index bd9cc5bd..8465584b 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -47,7 +47,7 @@ jobs: runs-on: public-ubuntu-latest-8-cores timeout-minutes: 60 container: - image: ghcr.io/ansys/mechanical:25.2.0 + image: ghcr.io/ansys/mechanical:26.1.0 options: --entrypoint /bin/bash needs: [style, doc-style]