From e6cfa7dc5f8c44cb3dc2bce156839ee2e9f80ba2 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:13:07 +0200 Subject: [PATCH 1/7] dbg: use CI/CD for generating scene --- .github/workflows/geometry-mesh.yml | 2 +- doc/make.bat | 22 +- geometry-mechanical-dpf/outputs/pcb.pmdb | Bin 0 -> 530152 bytes geometry-mechanical-dpf/requirements_24.1.txt | 2 +- geometry-mechanical-dpf/wf_gmd_01_geometry.py | 456 +++++++++--------- 5 files changed, 253 insertions(+), 229 deletions(-) create mode 100644 geometry-mechanical-dpf/outputs/pcb.pmdb diff --git a/.github/workflows/geometry-mesh.yml b/.github/workflows/geometry-mesh.yml index bdcc8c4f..79537866 100644 --- a/.github/workflows/geometry-mesh.yml +++ b/.github/workflows/geometry-mesh.yml @@ -40,7 +40,7 @@ jobs: strategy: fail-fast: false matrix: - ansys-release: [24.1, 24.2, 25.1] + ansys-release: [25.1] steps: - name: Checkout code diff --git a/doc/make.bat b/doc/make.bat index caaa0c6b..e8082244 100644 --- a/doc/make.bat +++ b/doc/make.bat @@ -14,17 +14,17 @@ if "%1" == "" goto help if "%1" == "clean" goto clean REM Check if vtk is installed - if so, uninstall and install vtk-osmesa -set IS_VTK_INSTALLED=0 -pip show vtk >NUL 2>NUL -if %ERRORLEVEL% EQU 0 ( - set IS_VTK_INSTALLED=1 - echo Uninstalling vtk... - pip uninstall -y vtk -) -if %IS_VTK_INSTALLED% EQU 1 ( - echo Installing vtk-osmesa... - pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.3.0 -) +REM set IS_VTK_INSTALLED=0 +REM pip show vtk >NUL 2>NUL +REM if %ERRORLEVEL% EQU 0 ( +REM set IS_VTK_INSTALLED=1 +REM echo Uninstalling vtk... +REM pip uninstall -y vtk +REM ) +REM if %IS_VTK_INSTALLED% EQU 1 ( +REM echo Installing vtk-osmesa... +REM pip install --extra-index-url https://wheels.vtk.org vtk-osmesa==9.3.0 +REM ) %SPHINXBUILD% >NUL 2>NUL if errorlevel 9009 ( diff --git a/geometry-mechanical-dpf/outputs/pcb.pmdb b/geometry-mechanical-dpf/outputs/pcb.pmdb new file mode 100644 index 0000000000000000000000000000000000000000..3154f79de6a42ed4675c5542aaa6ffbfbac4e6fb GIT binary patch literal 530152 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 z&nP22fd<-5)v@sry`CMNXmj31X=|DQf_s*!8a1&5Nsqn_sbt;jo;~`sz`-WiO+gLw zp|7UeJa|uQ=rkhY&UpicU4|ns{B{1%zsZ0RfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 z00@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p z2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?x zfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=900@8p2!H?xfB*=9 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 z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U NAV7csfiIE3-vL}5tcd^s literal 0 HcmV?d00001 diff --git a/geometry-mechanical-dpf/requirements_24.1.txt b/geometry-mechanical-dpf/requirements_24.1.txt index 26ec07f9..58adb870 100644 --- a/geometry-mechanical-dpf/requirements_24.1.txt +++ b/geometry-mechanical-dpf/requirements_24.1.txt @@ -1,3 +1,3 @@ -ansys-geometry-core[all]==0.7.6 +ansys-geometry-core[all]==0.4.14 ansys-mechanical-core==0.11.7 ansys-dpf-core[plotting]==0.12.2 diff --git a/geometry-mechanical-dpf/wf_gmd_01_geometry.py b/geometry-mechanical-dpf/wf_gmd_01_geometry.py index 2da8f765..f5d30deb 100644 --- a/geometry-mechanical-dpf/wf_gmd_01_geometry.py +++ b/geometry-mechanical-dpf/wf_gmd_01_geometry.py @@ -1,216 +1,240 @@ -# Copyright (C) 2024 - 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_geometry_mech_dpf_01-geometry: - -Geometry generation -################### - -This example shows how to generate a simple PCB using PyAnsys Geometry via -the Ansys Geometry Service. The example demonstrates how to create a sketch, -perform modeling operations, and export the file in different formats (in this -specific case, PMDB). - -""" # noqa: D400, D415 - -import os -from pathlib import Path - -from ansys.geometry.core import launch_modeler -from ansys.geometry.core.connection import GEOMETRY_SERVICE_DOCKER_IMAGE, GeometryContainers -from ansys.geometry.core.designer import DesignFileFormat -from ansys.geometry.core.math import Plane, Point2D, Point3D, UnitVector3D -from ansys.geometry.core.misc import DEFAULT_UNITS, UNITS -from ansys.geometry.core.sketch import Sketch - -############################################################################### -# Preparing the environment -# ------------------------- -# This section is only necessary for workflow runs and docs generation. It checks -# the environment variables to determine which image to use for the geometry service. -# If you are running this script outside of a workflow, you can ignore this section. -# -image = None -if "ANSYS_GEOMETRY_RELEASE" in os.environ: - image_tag = os.environ["ANSYS_GEOMETRY_RELEASE"] - for geom_services in GeometryContainers: - if image_tag == f"{GEOMETRY_SERVICE_DOCKER_IMAGE}:{geom_services.value[2]}": - print(f"Using {image_tag} image") - image = geom_services - break - -# sphinx_gallery_start_ignore -# Check if the __file__ variable is defined. If not, set it. -# This is a workaround to run the script in Sphinx-Gallery. -if "__file__" not in locals(): - __file__ = Path(os.getcwd(), "wf_gmd_01_geometry.py") -# sphinx_gallery_end_ignore - -############################################################################### -# Parameters for the script -# ------------------------- -# The following parameters are used to control the script execution. You can -# modify these parameters to suit your needs. -# - -GRAPHICS_BOOL = False # Set to True to display the graphics -OUTPUT_DIR = Path(Path(__file__).parent, "outputs") # Output directory - -# sphinx_gallery_start_ignore -if "DOC_BUILD" in os.environ: - GRAPHICS_BOOL = True -# sphinx_gallery_end_ignore - -############################################################################### -# Start a modeler session -# ----------------------- -# Start a modeler session to interact with the Ansys Geometry Service. The -# modeler object is used to create designs, sketches, and perform modeling -# operations. -# - -modeler = launch_modeler(image=image) -print(modeler) - -############################################################################### -# Create PCB geometry -# ----------------------- -# - -# Define default length units -DEFAULT_UNITS.LENGTH = UNITS.cm - -# Define the radius of holes in pcb -pcb_hole_radius = 1 - -# Create PCB Substrate -sketch_substrate = Sketch() -( - sketch_substrate.segment(Point2D([5, 0]), Point2D([122, 0])) - .arc_to_point(Point2D([127, 5]), Point2D([122, 5])) - .segment_to_point(Point2D([127, 135])) - .arc_to_point(Point2D([122, 140]), Point2D([122, 135])) - .segment_to_point(Point2D([5, 140])) - .arc_to_point(Point2D([0, 135]), Point2D([5, 135])) - .segment_to_point(Point2D([0, 5])) - .arc_to_point(Point2D([5, 0]), Point2D([5, 5])) - .circle(Point2D([6.35, 6.35]), radius=3.94 / 2) - .circle(Point2D([127 - 6.35, 6.35]), radius=3.94 / 2) - .circle(Point2D([127 - 6.35, 140 - 6.35]), radius=3.94 / 2) - .circle(Point2D([6.35, 140 - 6.35]), radius=3.94 / 2) -) -substrate_height = 1.575 -plane = Plane( - origin=Point3D([0, 0, substrate_height]), - direction_x=[1, 0, 0], - direction_y=[0, 1, 0], -) - -# create IC -sketch_IC = Sketch(plane) -sketch_IC.box(Point2D([62 / 2 + 7.5, 51 / 2 + 5]), 15, 10) - -# create capacitor sketch -sketch_capacitor = Sketch(plane=plane) -sketch_capacitor.circle(center=Point2D([95, 104]), radius=4.4) - -# create ic -sketch_ic_7 = Sketch(plane=plane) -sketch_ic_7.box(Point2D([25, 108]), 18, 24) - -# create ic -sketch_ic_8 = Sketch(plane=plane) -sketch_ic_8.box(Point2D([21, 59]), 10, 18) - -############################################################################### -# Modeling operations -# ------------------------- -# Now that the sketch is ready to be extruded, perform some modeling operations, -# including creating the design, creating the body directly on the design, and -# plotting the body. -# - -# Start by creating the Design -design = modeler.create_design("pcb_design") - -# Create all necessary components for pcb -component = design.add_component("PCB") -component.extrude_sketch("substrate", sketch_substrate, distance=substrate_height) -ic_1 = component.extrude_sketch("ic-1", sketch_IC, distance=4.5) - -ic_2 = ic_1.copy(parent=component, name="ic-2") -ic_2.translate(direction=UnitVector3D([1, 0, 0]), distance=17) - -ic_3 = ic_1.copy(parent=component, name="ic-3") -ic_3.translate(direction=UnitVector3D([0, 1, 0]), distance=17) - -ic_4 = ic_2.copy(parent=component, name="ic-4") -ic_4.translate(direction=UnitVector3D([1, 0, 0]), distance=17) - -ic_5 = ic_2.copy(parent=component, name="ic-5") -ic_5.translate(direction=UnitVector3D([0, 1, 0]), distance=17) - -ic_6 = ic_5.copy(parent=component, name="ic-6") -ic_6.translate(direction=UnitVector3D([1, 0, 0]), distance=17) - -ic_7 = component.extrude_sketch("ic-7", sketch=sketch_ic_7, distance=2) -ic_8 = component.extrude_sketch("ic-8", sketch=sketch_ic_8, distance=2) - -capacitor_1 = component.extrude_sketch("capacitor_1", sketch_capacitor, distance=20) -capacitor_2 = capacitor_1.copy(parent=component, name="capacitor_2") -capacitor_2.translate(direction=UnitVector3D([0, 1, 0]), distance=-20) -capacitor_3 = capacitor_1.copy(parent=component, name="capacitor_3") -capacitor_3.translate(direction=UnitVector3D([0, 1, 0]), distance=-40) -capacitor_4 = capacitor_1.copy(parent=component, name="capacitor_4") -capacitor_4.translate(direction=UnitVector3D([0, 1, 0]), distance=-60) - -# Create named selections -for body in component.bodies: - design.create_named_selection(name=body.name, bodies=[body]) - -# Plot the the entire geometry -if GRAPHICS_BOOL: - design.plot() - -############################################################################### -# Export the design -# ----------------- -# Once modeling operations are finalized, you can export files -# in different formats. For the formats supported by DMS, see the -# ``DesignFileFormat`` class in the ``Design`` module documentation. -# - -# Export files in PMDB format for Mechanical. -OUTPUT_DIR.mkdir(exist_ok=True) -download_file = Path(OUTPUT_DIR, "pcb.pmdb") -design.download(file_location=download_file, format=DesignFileFormat.PMDB) - -############################################################################### -# Close session -# ------------- -# -# When you finish interacting with your modeling service, you should close the active -# server session. This frees resources wherever the service is running. -# - -# Close the server session. -modeler.close() +# # Copyright (C) 2024 - 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_geometry_mech_dpf_01-geometry: +# +# Geometry generation +# ################### +# +# This example shows how to generate a simple PCB using PyAnsys Geometry via +# the Ansys Geometry Service. The example demonstrates how to create a sketch, +# perform modeling operations, and export the file in different formats (in this +# specific case, PMDB). +# +# """ # noqa: D400, D415 +# +# import os +# from pathlib import Path +# +# from ansys.geometry.core import launch_modeler +# from ansys.geometry.core.connection import GEOMETRY_SERVICE_DOCKER_IMAGE, GeometryContainers +# from ansys.geometry.core.designer import DesignFileFormat +# from ansys.geometry.core.math import Plane, Point2D, Point3D, UnitVector3D +# from ansys.geometry.core.misc import DEFAULT_UNITS, UNITS +# from ansys.geometry.core.sketch import Sketch +# +# ############################################################################### +# # Preparing the environment +# # ------------------------- +# # This section is only necessary for workflow runs and docs generation. It checks +# # the environment variables to determine which image to use for the geometry service. +# # If you are running this script outside of a workflow, you can ignore this section. +# # +# image = None +# if "ANSYS_GEOMETRY_RELEASE" in os.environ: +# image_tag = os.environ["ANSYS_GEOMETRY_RELEASE"] +# for geom_services in GeometryContainers: +# if image_tag == f"{GEOMETRY_SERVICE_DOCKER_IMAGE}:{geom_services.value[2]}": +# print(f"Using {image_tag} image") +# image = geom_services +# break +# +# # sphinx_gallery_start_ignore +# # Check if the __file__ variable is defined. If not, set it. +# # This is a workaround to run the script in Sphinx-Gallery. +# if "__file__" not in locals(): +# __file__ = Path(os.getcwd(), "wf_gmd_01_geometry.py") +# # sphinx_gallery_end_ignore +# +# ############################################################################### +# # Parameters for the script +# # ------------------------- +# # The following parameters are used to control the script execution. You can +# # modify these parameters to suit your needs. +# # +# +# GRAPHICS_BOOL = False # Set to True to display the graphics +# OUTPUT_DIR = Path(Path(__file__).parent, "outputs") # Output directory +# +# # sphinx_gallery_start_ignore +# if "DOC_BUILD" in os.environ: +# GRAPHICS_BOOL = True +# # sphinx_gallery_end_ignore +# +# ############################################################################### +# # Start a modeler session +# # ----------------------- +# # Start a modeler session to interact with the Ansys Geometry Service. The +# # modeler object is used to create designs, sketches, and perform modeling +# # operations. +# # +# +# modeler = launch_modeler(mode="spaceclaim") +# print(modeler) +# +# ############################################################################### +# # Create PCB geometry +# # ----------------------- +# # +# +# # Define default length units +# DEFAULT_UNITS.LENGTH = UNITS.cm +# +# # Define the radius of holes in pcb +# pcb_hole_radius = 1 +# +# # Create PCB Substrate +# sketch_substrate = Sketch() +# ( +# sketch_substrate.segment(Point2D([5, 0]), Point2D([122, 0])) +# .arc_to_point(Point2D([127, 5]), Point2D([122, 5])) +# .segment_to_point(Point2D([127, 135])) +# .arc_to_point(Point2D([122, 140]), Point2D([122, 135])) +# .segment_to_point(Point2D([5, 140])) +# .arc_to_point(Point2D([0, 135]), Point2D([5, 135])) +# .segment_to_point(Point2D([0, 5])) +# .arc_to_point(Point2D([5, 0]), Point2D([5, 5])) +# .circle(Point2D([6.35, 6.35]), radius=3.94 / 2) +# .circle(Point2D([127 - 6.35, 6.35]), radius=3.94 / 2) +# .circle(Point2D([127 - 6.35, 140 - 6.35]), radius=3.94 / 2) +# .circle(Point2D([6.35, 140 - 6.35]), radius=3.94 / 2) +# ) +# substrate_height = 1.575 +# plane = Plane( +# origin=Point3D([0, 0, substrate_height]), +# direction_x=[1, 0, 0], +# direction_y=[0, 1, 0], +# ) +# +# # create IC +# sketch_IC = Sketch(plane) +# sketch_IC.box(Point2D([62 / 2 + 7.5, 51 / 2 + 5]), 15, 10) +# +# # create capacitor sketch +# sketch_capacitor = Sketch(plane=plane) +# sketch_capacitor.circle(center=Point2D([95, 104]), radius=4.4) +# +# # create ic +# sketch_ic_7 = Sketch(plane=plane) +# sketch_ic_7.box(Point2D([25, 108]), 18, 24) +# +# # create ic +# sketch_ic_8 = Sketch(plane=plane) +# sketch_ic_8.box(Point2D([21, 59]), 10, 18) +# +# ############################################################################### +# # Modeling operations +# # ------------------------- +# # Now that the sketch is ready to be extruded, perform some modeling operations, +# # including creating the design, creating the body directly on the design, and +# # plotting the body. +# # +# +# # Start by creating the Design +# design = modeler.create_design("pcb_design") +# +# # Create all necessary components for pcb +# component = design.add_component("PCB") +# component.extrude_sketch("substrate", sketch_substrate, distance=substrate_height) +# ic_1 = component.extrude_sketch("ic-1", sketch_IC, distance=4.5) +# +# ic_2 = ic_1.copy(parent=component, name="ic-2") +# ic_2.translate(direction=UnitVector3D([1, 0, 0]), distance=17) +# +# ic_3 = ic_1.copy(parent=component, name="ic-3") +# ic_3.translate(direction=UnitVector3D([0, 1, 0]), distance=17) +# +# ic_4 = ic_2.copy(parent=component, name="ic-4") +# ic_4.translate(direction=UnitVector3D([1, 0, 0]), distance=17) +# +# ic_5 = ic_2.copy(parent=component, name="ic-5") +# ic_5.translate(direction=UnitVector3D([0, 1, 0]), distance=17) +# +# ic_6 = ic_5.copy(parent=component, name="ic-6") +# ic_6.translate(direction=UnitVector3D([1, 0, 0]), distance=17) +# +# ic_7 = component.extrude_sketch("ic-7", sketch=sketch_ic_7, distance=2) +# ic_8 = component.extrude_sketch("ic-8", sketch=sketch_ic_8, distance=2) +# +# capacitor_1 = component.extrude_sketch("capacitor_1", sketch_capacitor, distance=20) +# capacitor_2 = capacitor_1.copy(parent=component, name="capacitor_2") +# capacitor_2.translate(direction=UnitVector3D([0, 1, 0]), distance=-20) +# capacitor_3 = capacitor_1.copy(parent=component, name="capacitor_3") +# capacitor_3.translate(direction=UnitVector3D([0, 1, 0]), distance=-40) +# capacitor_4 = capacitor_1.copy(parent=component, name="capacitor_4") +# capacitor_4.translate(direction=UnitVector3D([0, 1, 0]), distance=-60) +# +# # Create named selections +# for body in component.bodies: +# design.create_named_selection(name=body.name, bodies=[body]) +# +# # Plot the the entire geometry +# if GRAPHICS_BOOL: +# +# from ansys.geometry.core.plotting import GeometryPlotter +# plotter = GeometryPlotter(show_plane=False) +# plotter.plot(design) +# plotter.show() +# +# ############################################################################### +# # Export the design +# # ----------------- +# # Once modeling operations are finalized, you can export files +# # in different formats. For the formats supported by DMS, see the +# # ``DesignFileFormat`` class in the ``Design`` module documentation. +# # +# +# # Export files in PMDB format for Mechanical. +# OUTPUT_DIR.mkdir(exist_ok=True) +# download_file = Path(OUTPUT_DIR, "pcb.pmdb") +# design.download(file_location=download_file, format=DesignFileFormat.PMDB) +# +# ############################################################################### +# # Close session +# # ------------- +# # +# # When you finish interacting with your modeling service, you should close the active +# # server session. This frees resources wherever the service is running. +# # +# +# # Close the server session. +# modeler.close() + +# Mesh the file + +import ansys.meshing.prime as prime +import pathlib + +file = pathlib.Path(__file__).parent / "outputs" / "pcb.pmdb" + +prime_client = prime.launch_prime() +model = prime_client.model +mesh_util = prime.lucid.Mesh(model=model) + +mesh_util.read(str(file.resolve().absolute())) +mesh_util.surface_mesh(min_size=2.0) + +from ansys.meshing.prime.graphics.plotter import PrimePlotter + +plotter = PrimePlotter() +plotter.plot(model) +plotter.show() From c7fb820ff6d112d6086f52b07d0426198ffe472b Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:15:19 +0200 Subject: [PATCH 2/7] ci: remove unnecessary files --- .github/workflows/ci_cd.yml | 27 -- .github/workflows/docs.yml | 112 ------- .github/workflows/fluent-mechanical.yml | 232 -------------- .github/workflows/geometry-mesh-fluent.yml | 345 --------------------- .github/workflows/geometry-mesh.yml | 236 -------------- 5 files changed, 952 deletions(-) delete mode 100644 .github/workflows/ci_cd.yml delete mode 100644 .github/workflows/docs.yml delete mode 100644 .github/workflows/fluent-mechanical.yml delete mode 100644 .github/workflows/geometry-mesh-fluent.yml delete mode 100644 .github/workflows/geometry-mesh.yml diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml deleted file mode 100644 index f8179989..00000000 --- a/.github/workflows/ci_cd.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: GitHub CI -on: - pull_request: - workflow_dispatch: - push: - tags: - - "*" - branches: - - main - -env: - MAIN_PYTHON_VERSION: '3.12' - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - code-style: - name: "Code style checks" - runs-on: ubuntu-latest - steps: - - name: "Run PyAnsys code style checks" - uses: ansys/actions/code-style@v9 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml deleted file mode 100644 index 55551e0f..00000000 --- a/.github/workflows/docs.yml +++ /dev/null @@ -1,112 +0,0 @@ -name: Documentation build - -on: - workflow_dispatch: - schedule: - - cron: "0 1 * * *" - -env: - MAIN_PYTHON_VERSION: '3.12' - DOCUMENTATION_CNAME: 'workflows.docs.pyansys.com' - -jobs: - geometry-mesh: - uses: ./.github/workflows/geometry-mesh.yml - secrets: inherit - with: - doc-build: true - - geometry-mesh-fluent: - uses: ./.github/workflows/geometry-mesh-fluent.yml - secrets: inherit - with: - doc-build: true - - geometry-mechanical-dpf: - uses: ./.github/workflows/geometry-mechanical-dpf.yml - secrets: inherit - with: - doc-build: true - - fluent-mechanical: - uses: ./.github/workflows/fluent-mechanical.yml - secrets: inherit - with: - doc-build: true - - compile-docs: - runs-on: ubuntu-latest - needs: [geometry-mesh, geometry-mesh-fluent, geometry-mechanical-dpf, fluent-mechanical] - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: main - fetch-depth: 0 - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r doc/requirements.txt - - - name: Download artifacts for geometry-mesh - uses: actions/download-artifact@v4 - with: - name: geometry-mesh-docs - path: doc/ - - - name: Download artifacts for geometry-mesh-fluent - uses: actions/download-artifact@v4 - with: - name: geometry-mesh-fluent-docs - path: doc/ - - - name: Download artifacts for geometry-mechanical-dpf - uses: actions/download-artifact@v4 - with: - name: geometry-mechanical-dpf-docs - path: doc/ - - - name: Download artifacts for fluent-mechanical - uses: actions/download-artifact@v4 - with: - name: fluent-mechanical-docs - path: doc/ - - - name: Build the documentation - run: | - cd doc - make html - - - name: Upload the documentation - uses: actions/upload-artifact@v4 - with: - name: documentation-html - path: doc/_build/html/ - - publish-docs: - runs-on: ubuntu-latest - needs: compile-docs - steps: - - name: "Download the documentation artifact" - uses: actions/download-artifact@v4 - with: - name: documentation-html - path: doc - - - name: List all files - run: ls -R . - - - name: "Deploy documentation to gh-pages" - uses: peaceiris/actions-gh-pages@v4 - with: - publish_dir: ./doc - commit_message: "DOC: update documentation" - github_token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} - cname: ${{ env.DOCUMENTATION_CNAME }} - force_orphan: true diff --git a/.github/workflows/fluent-mechanical.yml b/.github/workflows/fluent-mechanical.yml deleted file mode 100644 index 0cb93e00..00000000 --- a/.github/workflows/fluent-mechanical.yml +++ /dev/null @@ -1,232 +0,0 @@ -name: Fluent - Mechanical Exhaust Manifold Workflow - -on: - workflow_dispatch: - inputs: - doc-build: - required: false - default: false - type: boolean - description: 'Whether to build the documentation' - workflow_call: - inputs: - doc-build: - required: false - default: false - type: boolean - description: 'Whether to build the documentation' - push: - branches: - - main - pull_request: - paths: - - 'fluent-mechanical/**' - -env: - MAIN_PYTHON_VERSION: '3.12' - FLUENT_DOCKER_IMAGE: 'ghcr.io/ansys/pyfluent' - MECHANICAL_DOCKER_IMAGE: 'ghcr.io/ansys/mechanical' - DOCKER_MECH_CONTAINER_NAME: mechanical - PYMECHANICAL_PORT: 10000 - ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER )}} - PYANSYS_WORKFLOWS_CI: true - ANSYS_RELEASE_FOR_DOCS: 25.1 - RUN_DOC_BUILD: false - PYMECHANICAL_START_INSTANCE: false - -jobs: - fluent: - name: Fluent - runs-on: public-ubuntu-latest-8-cores - strategy: - fail-fast: false - matrix: - ansys-release: [24.1, 24.2, 25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - fluent-mechanical - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r fluent-mechanical/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download Fluent service container - run: docker pull ${{ env.FLUENT_DOCKER_IMAGE }}:v${{ matrix.ansys-release }}.0 - - - name: Run the Fluent script - env: - FLUENT_IMAGE_TAG: v${{ matrix.ansys-release }}.0 - run: | - python fluent-mechanical/wf_fm_01_fluent.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: fluent-mechanical-workflow-fluent-outputs-${{ matrix.ansys-release }} - path: | - fluent-mechanical/outputs/htc_temp_mapping_LOW_TEMP.csv - fluent-mechanical/outputs/htc_temp_mapping_MEDIUM_TEMP.csv - fluent-mechanical/outputs/htc_temp_mapping_HIGH_TEMP.csv - - - name: Stop all containers (if any) - run: | - if [ -n "$(docker ps -a -q)" ]; then - docker rm -f $(docker ps -a -q) - fi - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - echo "Requested to build docs..." - if [ "${{ matrix.ansys-release }}" == "${{ env.ANSYS_RELEASE_FOR_DOCS }}" ]; then - echo "Building docs" - echo "RUN_DOC_BUILD=true" >> $GITHUB_ENV - else - echo "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $GITHUB_ENV - fi - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS}}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - FLUENT_IMAGE_TAG: v${{ matrix.ansys-release }}.0 - BUILD_DOCS_SCRIPT: 'fluent-mechanical/wf_fm_01_fluent.py' - run: | - cd doc - pip install -r requirements.txt - make html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: fluent-mechanical-docs-stage-fluent - path: | - doc/_build/ - doc/source/examples/fluent-mechanical/ - overwrite: true - - mechanical: - name: Mechanical - runs-on: [public-ubuntu-latest-8-cores] - needs: fluent - strategy: - fail-fast: false - matrix: - ansys-release: [24.1, 24.2, 25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - fluent-mechanical - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Install system dependencies - run: | - sudo apt-get update - sudo apt-get install -y nodejs npm graphviz xvfb - npm install -g @mermaid-js/mermaid-cli - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m venv .venv - . .venv/bin/activate - pip install -r fluent-mechanical/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download (if needed) launch, and validate Mechanical service - env: - LICENSE_SERVER: ${{ secrets.LICENSE_SERVER }} - MECHANICAL_IMAGE: ${{ env.MECHANICAL_DOCKER_IMAGE }}:${{ matrix.ansys-release }}.0 - run: | - docker pull ${{ env.MECHANICAL_IMAGE }} - docker run --restart always --name ${{ env.DOCKER_MECH_CONTAINER_NAME }} -e ANSYSLMD_LICENSE_FILE=1055@${{ env.LICENSE_SERVER }} -p ${{ env.PYMECHANICAL_PORT }}:10000 ${{ env.MECHANICAL_IMAGE }} > log.txt & - grep -q 'WB Initialize Done' <(timeout 60 tail -f log.txt) - - - name: Check out the fluent outputs - uses: actions/download-artifact@v4 - with: - name: fluent-mechanical-workflow-fluent-outputs-${{ matrix.ansys-release }} - path: fluent-mechanical/outputs - - - name: Run the PyMechanical script - run: | - . .venv/bin/activate - xvfb-run python fluent-mechanical/wf_fm_02_mechanical.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: fluent-mechanical-workflow-mechanical-outputs-${{ matrix.ansys-release }} - path: fluent-mechanical/outputs - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - echo "Requested to build docs..." - if [ "${{ matrix.ansys-release }}" = "${{ env.ANSYS_RELEASE_FOR_DOCS }}" ]; then - echo "Building docs" - echo "RUN_DOC_BUILD=true" >> $GITHUB_ENV - else - echo "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $GITHUB_ENV - fi - - - name: (DOCS) Download the docs artifacts - uses: actions/download-artifact@v4 - if: ${{ env.RUN_DOC_BUILD == 'true' }} - with: - name: fluent-mechanical-docs-stage-fluent - path: doc - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS }}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - BUILD_DOCS_SCRIPT: 'fluent-mechanical/wf_fm_02_mechanical.py' - run: | - . .venv/bin/activate - cd doc - pip install -r requirements.txt - xvfb-run make html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: fluent-mechanical-docs - path: | - doc/_build/ - doc/source/examples/fluent-mechanical/ - overwrite: true \ No newline at end of file diff --git a/.github/workflows/geometry-mesh-fluent.yml b/.github/workflows/geometry-mesh-fluent.yml deleted file mode 100644 index a85f3fa7..00000000 --- a/.github/workflows/geometry-mesh-fluent.yml +++ /dev/null @@ -1,345 +0,0 @@ -name: Geometry Mesh Fluent Workflow - -on: - workflow_dispatch: - inputs: - doc-build: - required: false - default: false - type: boolean - description: 'Whether to build the documentation' - workflow_call: - inputs: - doc-build: - required: false - default: false - type: boolean - description: 'Whether to build the documentation' - push: - branches: - - main - pull_request: - paths: - - 'geometry-mesh-fluent/**' - -env: - MAIN_PYTHON_VERSION: '3.12' - GEOMETRY_DOCKER_IMAGE: 'ghcr.io/ansys/geometry' - FLUENT_DOCKER_IMAGE: 'ghcr.io/ansys/pyfluent' - ANSRV_GEO_PORT: 700 - ANSRV_GEO_LICENSE_SERVER: ${{ secrets.LICENSE_SERVER }} - ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER )}} - PYANSYS_WORKFLOWS_CI: true - ANSYS_RELEASE_FOR_DOCS: 25.1 - RUN_DOC_BUILD: false - -jobs: - geometry: - name: Geometry - runs-on: [self-hosted, Windows, pyansys-workflows] - strategy: - fail-fast: false - matrix: - ansys-release: [24.1, 24.2, 25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - geometry-mesh-fluent - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Setup headless display - uses: pyvista/setup-headless-display-action@v4 - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m venv .venv - .venv/Scripts/activate - pip install -r geometry-mesh-fluent/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download (if needed) and run Geometry service container - run: | - # If we are on 25.1 or above - the tag name is different - remember we are on powershell - if (${{ matrix.ansys-release }} -ge 25.2) { - $env:ANSYS_GEOMETRY_RELEASE = "${{ env.GEOMETRY_DOCKER_IMAGE }}:core-windows-${{ matrix.ansys-release }}" - } else { - $env:ANSYS_GEOMETRY_RELEASE = "${{ env.GEOMETRY_DOCKER_IMAGE }}:windows-${{ matrix.ansys-release }}" - } - Write-Host "Running Geometry service container: $env:ANSYS_GEOMETRY_RELEASE" - # Pull the container image - docker pull $env:ANSYS_GEOMETRY_RELEASE - # Define the ANSYS_GEOMETRY_RELEASE environment variable to be used in the next stages - echo "ANSYS_GEOMETRY_RELEASE=$env:ANSYS_GEOMETRY_RELEASE" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Run the PyAnsys Geometry script - run: | - .venv/Scripts/activate - python geometry-mesh-fluent/wf_gmf_01_geometry.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-fluent-workflow-geometry-outputs-${{ matrix.ansys-release }} - path: geometry-mesh-fluent/outputs - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - Write-Host "Requested to build docs..." - if ("${{ matrix.ansys-release }}" -eq $env:ANSYS_RELEASE_FOR_DOCS) { - Write-Host "Building docs" - echo "RUN_DOC_BUILD=true" >> $env:GITHUB_ENV - } else { - Write-Host "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $env:GITHUB_ENV - } - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS}}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - BUILD_DOCS_SCRIPT: 'geometry-mesh-fluent/wf_gmf_01_geometry.py' - run: | - .venv/Scripts/activate - cd doc - pip install -r requirements.txt - ./make.bat html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-fluent-docs-stage-geometry - path: | - doc/_build/ - doc/source/examples/geometry-mesh-fluent/ - - - name: Stop any remaining containers - if: always() - run: | - $dockerContainers = docker ps -a -q - if (-not [string]::IsNullOrEmpty($dockerContainers)) { - docker stop $dockerContainers - docker rm $dockerContainers - } - - fluent-mesh: - name: Fluent Meshing - runs-on: public-ubuntu-latest-8-cores - needs: geometry - strategy: - fail-fast: false - matrix: - ansys-release: [24.1, 24.2, 25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - geometry-mesh-fluent - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r geometry-mesh-fluent/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download Fluent service container - run: docker pull ${{ env.FLUENT_DOCKER_IMAGE }}:v${{ matrix.ansys-release }}.0 - - - name: Check out the geometry outputs - uses: actions/download-artifact@v4 - with: - name: geometry-mesh-fluent-workflow-geometry-outputs-${{ matrix.ansys-release }} - path: geometry-mesh-fluent/outputs - - - name: Run the Fluent meshing script - env: - FLUENT_IMAGE_TAG: v${{ matrix.ansys-release }}.0 - run: | - python geometry-mesh-fluent/wf_gmf_02_fluent_meshing.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-fluent-workflow-fluent-mesh-outputs-${{ matrix.ansys-release }} - path: | - geometry-mesh-fluent/outputs/NACA_Airfoil_*.pmdb - geometry-mesh-fluent/outputs/NACA_Airfoil_*.msh.h5 - - - name: Stop all containers (if any) - run: | - if [ -n "$(docker ps -a -q)" ]; then - docker rm -f $(docker ps -a -q) - fi - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - echo "Requested to build docs..." - if [ "${{ matrix.ansys-release }}" == "${{ env.ANSYS_RELEASE_FOR_DOCS }}" ]; then - echo "Building docs" - echo "RUN_DOC_BUILD=true" >> $GITHUB_ENV - else - echo "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $GITHUB_ENV - fi - - - name: (DOCS) Download the docs artifacts - uses: actions/download-artifact@v4 - if: ${{ env.RUN_DOC_BUILD == 'true' }} - with: - name: geometry-mesh-fluent-docs-stage-geometry - path: doc - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS}}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - FLUENT_IMAGE_TAG: v${{ matrix.ansys-release }}.0 - BUILD_DOCS_SCRIPT: 'geometry-mesh-fluent/wf_gmf_02_fluent_meshing.py' - run: | - cd doc - find . -type f -exec sed -i 's|C:\\Users\\ansys\\actions-runner\\_work\\pyansys-workflows\\pyansys-workflows\\doc\\source\\examples\\geometry-mesh-fluent\\images\\|./images/|g' {} + - pip install -r requirements.txt - make html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-fluent-docs-stage-mesh - path: | - doc/_build/ - doc/source/examples/geometry-mesh-fluent/ - overwrite: true - - fluent-solve: - name: Fluent Solver - runs-on: public-ubuntu-latest-8-cores # Potential memory issues with 24.1 otherwise - needs: fluent-mesh - strategy: - fail-fast: false - matrix: - ansys-release: [24.1, 24.2, 25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - geometry-mesh-fluent - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r geometry-mesh-fluent/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download Fluent service container - run: docker pull ${{ env.FLUENT_DOCKER_IMAGE }}:v${{ matrix.ansys-release }}.0 - - - name: Check out the meshing outputs - uses: actions/download-artifact@v4 - with: - name: geometry-mesh-fluent-workflow-fluent-mesh-outputs-${{ matrix.ansys-release }} - path: geometry-mesh-fluent/outputs - - - name: Run the Fluent solver script - env: - FLUENT_IMAGE_TAG: v${{ matrix.ansys-release }}.0 - run: | - python geometry-mesh-fluent/wf_gmf_03_fluent_solver.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-fluent-workflow-fluent-solve-outputs-${{ matrix.ansys-release }} - path: | - geometry-mesh-fluent/outputs/NACA_Airfoil_*.pmdb - geometry-mesh-fluent/outputs/NACA_Airfoil_*.msh.h5 - geometry-mesh-fluent/outputs/NACA_Airfoil_*.cas.h5 - geometry-mesh-fluent/outputs/NACA_Airfoil_*.dat.h5 - - - name: Stop all containers (if any) - run: | - if [ -n "$(docker ps -a -q)" ]; then - docker rm -f $(docker ps -a -q) - fi - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - echo "Requested to build docs..." - if [ "${{ matrix.ansys-release }}" == "${{ env.ANSYS_RELEASE_FOR_DOCS }}" ]; then - echo "Building docs" - echo "RUN_DOC_BUILD=true" >> $GITHUB_ENV - else - echo "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $GITHUB_ENV - fi - - - name: (DOCS) Download the docs artifacts - uses: actions/download-artifact@v4 - if: ${{ env.RUN_DOC_BUILD == 'true' }} - with: - name: geometry-mesh-fluent-docs-stage-mesh - path: doc - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS}}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - FLUENT_IMAGE_TAG: v${{ matrix.ansys-release }}.0 - BUILD_DOCS_SCRIPT: 'geometry-mesh-fluent/wf_gmf_03_fluent_solver.py' - run: | - cd doc - pip install -r requirements.txt - make html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-fluent-docs - path: | - doc/_build/ - doc/source/examples/geometry-mesh-fluent/ - overwrite: true diff --git a/.github/workflows/geometry-mesh.yml b/.github/workflows/geometry-mesh.yml deleted file mode 100644 index 79537866..00000000 --- a/.github/workflows/geometry-mesh.yml +++ /dev/null @@ -1,236 +0,0 @@ -name: Geometry Mesh Workflow - -on: - workflow_dispatch: - inputs: - doc-build: - required: false - default: false - type: boolean - description: 'Whether to build the documentation' - workflow_call: - inputs: - doc-build: - required: false - default: false - type: boolean - description: 'Whether to build the documentation' - push: - branches: - - main - pull_request: - paths: - - 'geometry-mesh/**' - -env: - MAIN_PYTHON_VERSION: '3.12' - GEOMETRY_DOCKER_IMAGE: 'ghcr.io/ansys/geometry' - PRIME_DOCKER_IMAGE: 'ghcr.io/ansys/prime' - ANSRV_GEO_PORT: 700 - ANSRV_GEO_LICENSE_SERVER: ${{ secrets.LICENSE_SERVER }} - PYPRIMEMESH_LAUNCH_CONTAINER: 1 - ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER )}} - ANSYS_RELEASE_FOR_DOCS: 25.1 - RUN_DOC_BUILD: false - -jobs: - geometry: - name: Geometry - runs-on: [self-hosted, Windows, pyansys-workflows] - strategy: - fail-fast: false - matrix: - ansys-release: [25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - geometry-mesh - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Setup headless display - uses: pyvista/setup-headless-display-action@v4 - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - python -m venv .venv - .venv/Scripts/activate - pip install -r geometry-mesh/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download (if needed) and run Geometry service container - run: | - # If we are on 25.1 or above - the tag name is different - remember we are on powershell - if (${{ matrix.ansys-release }} -ge 25.2) { - $env:ANSYS_GEOMETRY_RELEASE = "${{ env.GEOMETRY_DOCKER_IMAGE }}:core-windows-${{ matrix.ansys-release }}" - } else { - $env:ANSYS_GEOMETRY_RELEASE = "${{ env.GEOMETRY_DOCKER_IMAGE }}:windows-${{ matrix.ansys-release }}" - } - Write-Host "Running Geometry service container: $env:ANSYS_GEOMETRY_RELEASE" - # Pull the container image - docker pull $env:ANSYS_GEOMETRY_RELEASE - # Define the ANSYS_GEOMETRY_RELEASE environment variable to be used in the next stages - echo "ANSYS_GEOMETRY_RELEASE=$env:ANSYS_GEOMETRY_RELEASE" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Run the PyAnsys Geometry script - run: | - .venv/Scripts/activate - python geometry-mesh/wf_gm_01_geometry.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-workflow-geometry-outputs-${{ matrix.ansys-release }} - path: geometry-mesh/outputs - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - Write-Host "Requested to build docs..." - if ("${{ matrix.ansys-release }}" -eq $env:ANSYS_RELEASE_FOR_DOCS) { - Write-Host "Building docs" - echo "RUN_DOC_BUILD=true" >> $env:GITHUB_ENV - } else { - Write-Host "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $env:GITHUB_ENV - } - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS}}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - BUILD_DOCS_SCRIPT: 'geometry-mesh/wf_gm_01_geometry.py' - run: | - .venv/Scripts/activate - cd doc - pip install -r requirements.txt - ./make.bat html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-docs-stage-geometry - path: | - doc/_build/ - doc/source/examples/geometry-mesh/ - - - name: Stop any remaining containers - if: always() - run: | - $dockerContainers = docker ps -a -q - if (-not [string]::IsNullOrEmpty($dockerContainers)) { - docker stop $dockerContainers - docker rm $dockerContainers - } - - prime: - name: Meshing - runs-on: ubuntu-latest - needs: geometry - strategy: - fail-fast: false - matrix: - ansys-release: [24.1, 24.2, 25.1] - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - sparse-checkout: | - geometry-mesh - doc - - - name: Set up Python ${{ env.MAIN_PYTHON_VERSION }} - uses: actions/setup-python@v5 - with: - python-version: ${{ env.MAIN_PYTHON_VERSION }} - - - name: Setup headless display - uses: pyvista/setup-headless-display-action@v4 - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r geometry-mesh/requirements_${{ matrix.ansys-release }}.txt - - - name: Login to GitHub Container Registry - uses: docker/login-action@v3 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Download PRIME service container - run: docker pull ${{ env.PRIME_DOCKER_IMAGE }}:${{ matrix.ansys-release }} - - - name: Check out the geometry outputs - uses: actions/download-artifact@v4 - with: - name: geometry-mesh-workflow-geometry-outputs-${{ matrix.ansys-release }} - path: geometry-mesh/outputs - - - name: Run the PyPrimeMesh script - env: - PYPRIMEMESH_IMAGE_TAG: ${{ matrix.ansys-release }} - run: | - python geometry-mesh/wf_gm_02_mesh.py - - - name: Store the outputs - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-workflow-prime-outputs-${{ matrix.ansys-release }} - path: geometry-mesh/outputs - - - name: (DOCS) Check if docs should be built - if: (github.event_name == 'workflow_dispatch' || github.event_name == 'schedule') && inputs.doc-build - run: | - echo "Requested to build docs..." - if [ "${{ matrix.ansys-release }}" == "${{ env.ANSYS_RELEASE_FOR_DOCS }}" ]; then - echo "Building docs" - echo "RUN_DOC_BUILD=true" >> $GITHUB_ENV - else - echo "Not building docs - since not primary release" - echo "RUN_DOC_BUILD=false" >> $GITHUB_ENV - fi - - - name: (DOCS) Download the docs artifacts - uses: actions/download-artifact@v4 - if: ${{ env.RUN_DOC_BUILD == 'true' }} - with: - name: geometry-mesh-docs-stage-geometry - path: doc - - - name: (DOCS) Build the documentation (only on ${{ env.ANSYS_RELEASE_FOR_DOCS}}) - if: ${{ env.RUN_DOC_BUILD == 'true' }} - env: - PYPRIMEMESH_IMAGE_TAG: ${{ matrix.ansys-release }} - BUILD_DOCS_SCRIPT: 'geometry-mesh/wf_gm_02_mesh.py' - run: | - cd doc - find . -type f -exec sed -i 's|C:\\Users\\ansys\\actions-runner\\_work\\pyansys-workflows\\pyansys-workflows\\doc\\source\\examples\\geometry-mesh\\images\\|./images/|g' {} + - pip install -r requirements.txt - make html - - - name: (DOCS) Upload docs artifacts - if: ${{ env.RUN_DOC_BUILD == 'true' }} - uses: actions/upload-artifact@v4 - with: - name: geometry-mesh-docs - path: | - doc/_build/ - doc/source/examples/geometry-mesh/ - overwrite: true From 3980da8308ec2e9a2c970dc76165b9929e8fe956 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:17:45 +0200 Subject: [PATCH 3/7] ci: use concurrency --- .github/workflows/geometry-mechanical-dpf.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/geometry-mechanical-dpf.yml b/.github/workflows/geometry-mechanical-dpf.yml index 84d74941..a221f7b0 100644 --- a/.github/workflows/geometry-mechanical-dpf.yml +++ b/.github/workflows/geometry-mechanical-dpf.yml @@ -33,6 +33,10 @@ env: ANSYS_RELEASE_FOR_DOCS: 25.1 RUN_DOC_BUILD: false +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + jobs: geometry: name: Geometry @@ -40,7 +44,7 @@ jobs: strategy: fail-fast: false matrix: - ansys-release: [24.1, 24.2, 25.1] + ansys-release: [25.1] steps: - name: Checkout code From 37d766d8536970d2e305ae206d31e67c0fc4fbee Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:22:10 +0200 Subject: [PATCH 4/7] doc: build --- .github/workflows/geometry-mechanical-dpf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/geometry-mechanical-dpf.yml b/.github/workflows/geometry-mechanical-dpf.yml index a221f7b0..4b0e2c7a 100644 --- a/.github/workflows/geometry-mechanical-dpf.yml +++ b/.github/workflows/geometry-mechanical-dpf.yml @@ -31,7 +31,7 @@ env: ANSYSLMD_LICENSE_FILE: ${{ format('1055@{0}', secrets.LICENSE_SERVER )}} PYANSYS_WORKFLOWS_CI: true ANSYS_RELEASE_FOR_DOCS: 25.1 - RUN_DOC_BUILD: false + RUN_DOC_BUILD: true concurrency: group: ${{ github.workflow }}-${{ github.ref }} From db12f65314cee0669f38f09e9a1737b39145a62d Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:31:10 +0200 Subject: [PATCH 5/7] fix: update requirements --- geometry-mechanical-dpf/requirements_25.1.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/geometry-mechanical-dpf/requirements_25.1.txt b/geometry-mechanical-dpf/requirements_25.1.txt index cc5e30d0..d94a6289 100644 --- a/geometry-mechanical-dpf/requirements_25.1.txt +++ b/geometry-mechanical-dpf/requirements_25.1.txt @@ -1,3 +1,4 @@ ansys-geometry-core[all]==0.9.2 ansys-mechanical-core==0.11.13 ansys-dpf-core[plotting]==0.13.4 +ansys-meshing-prime[all]==0.8.1 From 32b6e9895bf0a81af457aafc0b30545ed4e8e787 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:40:27 +0200 Subject: [PATCH 6/7] ci: install prime service --- .github/workflows/geometry-mechanical-dpf.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/geometry-mechanical-dpf.yml b/.github/workflows/geometry-mechanical-dpf.yml index 4b0e2c7a..11118c7d 100644 --- a/.github/workflows/geometry-mechanical-dpf.yml +++ b/.github/workflows/geometry-mechanical-dpf.yml @@ -32,6 +32,8 @@ env: PYANSYS_WORKFLOWS_CI: true ANSYS_RELEASE_FOR_DOCS: 25.1 RUN_DOC_BUILD: true + DOCKER_IMAGE_PRIME_NAME: ghcr.iop/ansys/prime + DOCKER_IMAGE_PRIME_TAG: '25.2.0' concurrency: group: ${{ github.workflow }}-${{ github.ref }} @@ -90,6 +92,11 @@ jobs: # Define the ANSYS_GEOMETRY_RELEASE environment variable to be used in the next stages echo "ANSYS_GEOMETRY_RELEASE=$env:ANSYS_GEOMETRY_RELEASE" | Out-File -FilePath $env:GITHUB_ENV -Append + + - name: Pull prime service + run: | + docker pull ${{ env.DOCKER_IMAGE_PRIME_NAME }}:${{ env.DOCKER_IMAGE_PRIME_TAG }} + - name: Run the PyAnsys Geometry script run: | .venv/Scripts/activate From 2339613540e1ef4a80c7ed9ee436c90afca8db96 Mon Sep 17 00:00:00 2001 From: Jorge Martinez Garrido Date: Mon, 2 Jun 2025 14:48:21 +0200 Subject: [PATCH 7/7] ci: fix link --- .github/workflows/geometry-mechanical-dpf.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/geometry-mechanical-dpf.yml b/.github/workflows/geometry-mechanical-dpf.yml index 11118c7d..de701ad7 100644 --- a/.github/workflows/geometry-mechanical-dpf.yml +++ b/.github/workflows/geometry-mechanical-dpf.yml @@ -32,7 +32,7 @@ env: PYANSYS_WORKFLOWS_CI: true ANSYS_RELEASE_FOR_DOCS: 25.1 RUN_DOC_BUILD: true - DOCKER_IMAGE_PRIME_NAME: ghcr.iop/ansys/prime + DOCKER_IMAGE_PRIME_NAME: ghcr.io/ansys/prime DOCKER_IMAGE_PRIME_TAG: '25.2.0' concurrency: