diff --git a/.github/workflows/ci_cd.yml b/.github/workflows/ci_cd.yml index b674294a09..39642f894d 100644 --- a/.github/workflows/ci_cd.yml +++ b/.github/workflows/ci_cd.yml @@ -15,8 +15,8 @@ on: env: DOCKER_IMAGE_NAME: ghcr.io/ansys/prime - DOCKER_IMAGE_TAG: '25.1.1' - MAIN_PYTHON_VERSION: '3.12' + DOCKER_IMAGE_TAG: '25.1.4' + MAIN_PYTHON_VERSION: '3.10' PACKAGE_NAME: 'ansys-meshing-prime' PACKAGE_NAMESPACE: 'ansys.meshing.prime' DOCUMENTATION_CNAME: 'prime.docs.pyansys.com' @@ -35,7 +35,7 @@ jobs: contents: write pull-requests: write steps: - - uses: ansys/actions/doc-deploy-changelog@v8 + - uses: ansys/actions/doc-deploy-changelog@v9 with: token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} bot-user: ${{ secrets.PYANSYS_CI_BOT_USERNAME }} @@ -46,7 +46,7 @@ jobs: runs-on: ubuntu-latest steps: - name: PyAnsys code style checks - uses: ansys/actions/code-style@v8 + uses: ansys/actions/code-style@v9 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} vale-config: "doc/.vale.ini" @@ -57,7 +57,7 @@ jobs: runs-on: ubuntu-latest steps: - name: PyAnsys documentation style checks - uses: ansys/actions/doc-style@v8 + uses: ansys/actions/doc-style@v9 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -77,7 +77,7 @@ jobs: os: macos-latest steps: - name: Build wheelhouse and perform smoke test - uses: ansys/actions/build-wheelhouse@v8 + uses: ansys/actions/build-wheelhouse@v9 with: library-name: ${{ env.PACKAGE_NAME }} library-namespace: ${{ env.PACKAGE_NAMESPACE }} @@ -100,10 +100,13 @@ jobs: run: docker pull ${{ env.DOCKER_IMAGE_NAME }}:${{ env.DOCKER_IMAGE_TAG }} - name: Setup headless display - uses: pyvista/setup-headless-display-action@v3 + uses: pyvista/setup-headless-display-action@v4 + + - name: Install compatible pyvista and vtk + run: pip install "pyvista>=0.42" vtk - name: "Run Ansys documentation building action" - uses: ansys/actions/doc-build@v8 + uses: ansys/actions/doc-build@v9 with: python-version: ${{ env.MAIN_PYTHON_VERSION }} check-links: false @@ -114,6 +117,7 @@ jobs: PYPRIMEMESH_SPHINX_BUILD: 1 PYPRIMEMESH_IMAGE_TAG: ${{ env.DOCKER_IMAGE_TAG }} ANSYSLMD_LICENSE_FILE: '1055@${{ secrets.LICENSE_SERVER }}' + PRIME_MODE: "GRPC_INSECURE" testing: name: Run Unit Tests @@ -137,9 +141,12 @@ jobs: path: tests/graphics/image_cache key: pyvista-image-cache-${{ runner.os }}-v-${{ env.RESET_IMAGE_CACHE }}-${{ hashFiles('pyproject.toml') }} restore-keys: pyvista-image-cache-${{ runner.os }}-v-${{ env.RESET_IMAGE_CACHE }} + + - name: Install compatible pyvista and vtk + run: pip install "pyvista>=0.42" vtk - name: "Run pytest" - uses: ansys/actions/tests-pytest@v8 + uses: ansys/actions/tests-pytest@v9 env: PYPRIMEMESH_LAUNCH_CONTAINER: 1 PYPRIMEMESH_IMAGE_TAG: ${{ env.DOCKER_IMAGE_TAG }} @@ -164,7 +171,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Build library source and wheel artifacts - uses: ansys/actions/build-library@v8 + uses: ansys/actions/build-library@v9 with: library-name: ${{ env.PACKAGE_NAME }} python-version: ${{ env.MAIN_PYTHON_VERSION }} @@ -176,14 +183,14 @@ jobs: runs-on: ubuntu-latest steps: - name: Release to the public PyPI repository - uses: ansys/actions/release-pypi-public@v8 + uses: ansys/actions/release-pypi-public@v9 with: library-name: ${{ env.PACKAGE_NAME }} twine-username: "__token__" twine-token: ${{ secrets.PYPI_TOKEN }} - name: Release to GitHub - uses: ansys/actions/release-github@v8 + uses: ansys/actions/release-github@v9 with: library-name: ${{ env.PACKAGE_NAME }} @@ -194,7 +201,7 @@ jobs: needs: [package] steps: - name: Deploy the latest documentation - uses: ansys/actions/doc-deploy-dev@v8 + uses: ansys/actions/doc-deploy-dev@v9 with: cname: ${{ env.DOCUMENTATION_CNAME }} token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} @@ -208,7 +215,7 @@ jobs: needs: [release] steps: - name: Deploy the stable documentation - uses: ansys/actions/doc-deploy-stable@v8 + uses: ansys/actions/doc-deploy-stable@v9 with: cname: ${{ env.DOCUMENTATION_CNAME }} token: ${{ secrets.PYANSYS_CI_BOT_TOKEN }} diff --git a/CHANGELOG.md b/CHANGELOG.md index da8ca40478..2c76635240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,48 @@ This project uses [towncrier](https://towncrier.readthedocs.io/) and the changes +## [0.8.2](https://github.com/ansys/pyprimemesh/releases/tag/v0.8.2) - December 15, 2025 + + +### Documentation + +- updates to release/0.8 [#1188](https://github.com/ansys/pyprimemesh/pull/1188) + +## [0.8.1](https://github.com/ansys/pyprimemesh/releases/tag/v0.8.1) - May 09, 2025 + + +### Maintenance + +- updated docker image tag for SP2 changes [#997](https://github.com/ansys/pyprimemesh/pull/997) + +## [0.8.1](https://github.com/ansys/pyprimemesh/releases/tag/v0.8.1) - April 29, 2025 + + +### Dependencies + +- build(deps): bump sphinx from 8.2.1 to 8.2.3 in the doc-dependencies group [#990](https://github.com/ansys/pyprimemesh/pull/990) +- build(deps): bump ansys-sphinx-theme[autoapi] from 1.3.2 to 1.3.3 in the doc-dependencies group [#992](https://github.com/ansys/pyprimemesh/pull/992) +- build(deps): bump the test-dependencies group across 1 directory with 2 updates [#993](https://github.com/ansys/pyprimemesh/pull/993) +- build(deps): bump ansys-sphinx-theme[autoapi] from 1.3.3 to 1.4.2 in the doc-dependencies group [#994](https://github.com/ansys/pyprimemesh/pull/994) +- build(deps): bump pytest-cov from 6.0.0 to 6.1.1 in the test-dependencies group [#996](https://github.com/ansys/pyprimemesh/pull/996) + + +### Miscellaneous + +- Sync ADO changes for sp2 [#1000](https://github.com/ansys/pyprimemesh/pull/1000) +- minor fix for release/0.8.1 [#1004](https://github.com/ansys/pyprimemesh/pull/1004) + + +### Documentation + +- Update fileio.rst [#980](https://github.com/ansys/pyprimemesh/pull/980) + + +### Maintenance + +- chore: update CHANGELOG for v0.8.0 [#988](https://github.com/ansys/pyprimemesh/pull/988) +- updated docker image tag for SP2 changes [#997](https://github.com/ansys/pyprimemesh/pull/997) + ## [0.8.0](https://github.com/ansys/pyprimemesh/releases/tag/v0.8.0) - 2025-02-27 diff --git a/doc/changelog.d/980.documentation.md b/doc/changelog.d/980.documentation.md deleted file mode 100644 index e6eaf87075..0000000000 --- a/doc/changelog.d/980.documentation.md +++ /dev/null @@ -1 +0,0 @@ -Update fileio.rst \ No newline at end of file diff --git a/doc/changelog.d/988.maintenance.md b/doc/changelog.d/988.maintenance.md deleted file mode 100644 index bf6ebae267..0000000000 --- a/doc/changelog.d/988.maintenance.md +++ /dev/null @@ -1 +0,0 @@ -chore: update CHANGELOG for v0.8.0 \ No newline at end of file diff --git a/doc/changelog.d/990.dependencies.md b/doc/changelog.d/990.dependencies.md deleted file mode 100644 index 4d741d4940..0000000000 --- a/doc/changelog.d/990.dependencies.md +++ /dev/null @@ -1 +0,0 @@ -build(deps): bump sphinx from 8.2.1 to 8.2.3 in the doc-dependencies group \ No newline at end of file diff --git a/doc/changelog.d/992.dependencies.md b/doc/changelog.d/992.dependencies.md deleted file mode 100644 index 4272ef36cd..0000000000 --- a/doc/changelog.d/992.dependencies.md +++ /dev/null @@ -1 +0,0 @@ -build(deps): bump ansys-sphinx-theme[autoapi] from 1.3.2 to 1.3.3 in the doc-dependencies group \ No newline at end of file diff --git a/doc/changelog.d/993.dependencies.md b/doc/changelog.d/993.dependencies.md deleted file mode 100644 index f7544789e4..0000000000 --- a/doc/changelog.d/993.dependencies.md +++ /dev/null @@ -1 +0,0 @@ -build(deps): bump the test-dependencies group across 1 directory with 2 updates \ No newline at end of file diff --git a/doc/changelog.d/994.dependencies.md b/doc/changelog.d/994.dependencies.md deleted file mode 100644 index 6b2a851b28..0000000000 --- a/doc/changelog.d/994.dependencies.md +++ /dev/null @@ -1 +0,0 @@ -build(deps): bump ansys-sphinx-theme[autoapi] from 1.3.3 to 1.4.2 in the doc-dependencies group \ No newline at end of file diff --git a/doc/changelog.d/996.dependencies.md b/doc/changelog.d/996.dependencies.md deleted file mode 100644 index 5026a35c9e..0000000000 --- a/doc/changelog.d/996.dependencies.md +++ /dev/null @@ -1 +0,0 @@ -build(deps): bump pytest-cov from 6.0.0 to 6.1.1 in the test-dependencies group \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index ba5436dae6..fdd5ab0c15 100755 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -10,6 +10,7 @@ from ansys.meshing.prime import __version__ +os.environ["PRIME_MODE"] = "GRPC_INSECURE" viz_interface.DOCUMENTATION_BUILD = True # Project information diff --git a/doc/source/getting_started/index.rst b/doc/source/getting_started/index.rst index ea814d85ae..2f5015be99 100644 --- a/doc/source/getting_started/index.rst +++ b/doc/source/getting_started/index.rst @@ -65,6 +65,60 @@ To install a basic version of the client, use this command instead: pip install -e . +Connecting through gRPC +----------------------- + +PyPrimeMesh uses gRPC to provide secure communications between client and server. +When you run the client and server on the same machine: + +- For Linux OS, PyPrimeMesh uses UDS (Unix Domain Socket) for communications. + +- For Windows OS, PyPrimeMesh uses interceptor to validate gRPC connections, + ensures the client is running on the same Windows user account as the server and authenticates the client. + +When you launch PyPrimeMesh, gRPC establishes a connection between the Client and Server +through the secure option. **Secure** is the default option when you use launch_prime(). +You should always use the **Secure** option to establish a secured connection between the client and server. + +When you want to make an insecure connection between the client and server, +you may need to specify the connection type as follows: + +.. code-block:: python + + client = prime.launch_prime( + connection_type=prime.internals.config.ConnectionType.GRPC_INSECURE + ) + +.. note:: + Insecure option is not recommended. + +Connect securely using certificates +-------------------------------------- + +PyPrimeMesh offers secure connection using certificates. For secure connection with mutual TLS (mTLS), you may pass a client certificate directory and server certificate directory using client_certs_dir and server_certs_dir respectively to launch_prime(). + +client_certs_dir should contain the following files: + +- client.crt + +- client.key + +- ca.crt + +server_certs_dir should contain the following files: + +- server.crt + +- server.key + +- ca.crt + +.. note:: + - Ensure that ca.crt file is the same for the client and the server. You should not modify the + file names in the client_certs_dir and server_certs_dir respectively. + + - The path of input the files must be the same for server and client and should be on the shared network. + Dependencies ------------ diff --git a/doc/styles/config/vocabularies/ANSYS/accept.txt b/doc/styles/config/vocabularies/ANSYS/accept.txt index 2187858b64..70833f0aa4 100644 --- a/doc/styles/config/vocabularies/ANSYS/accept.txt +++ b/doc/styles/config/vocabularies/ANSYS/accept.txt @@ -6,6 +6,7 @@ automesh Boolean BRep CAD +client_certs_dir conformally [Dd]efeature defeaturing diff --git a/docker/build_docker_linux.py b/docker/build_docker_linux.py index 15fa381814..074a47fbd4 100644 --- a/docker/build_docker_linux.py +++ b/docker/build_docker_linux.py @@ -143,12 +143,38 @@ def create_docker_image(dest_package_path): # Build the docker image print(">>> Building docker image. This might take some time...") + # Parse version from AWP_ROOT or command line argument + version = "latest" # default + if len(sys.argv) >= 3: + version = sys.argv[2] + + # Get the script directory for robust file path handling + script_dir = os.path.dirname(os.path.abspath(__file__)) + dockerfile_path = os.path.join(script_dir, "linux", "Dockerfile") + + # Verify Dockerfile exists + if not os.path.exists(dockerfile_path): + print(f"XXXXXXX Dockerfile not found at {dockerfile_path}. Exiting process. XXXXXXX") + exit(1) + + # Build Docker image with version tag + image_tag = f"ghcr.io/ansys/prime:{version}" + print(f">>> Building Docker image with tag: {image_tag}") + out = subprocess.run( - ["docker", "build", "-f", "linux/Dockerfile", "-t", "ghcr.io/ansys/prime:latest", "."], - cwd=os.path.dirname(os.path.abspath(__file__)), + ["docker", "build", "-f", dockerfile_path, "-t", image_tag, script_dir], capture_output=True, ) + # Check if docker build was successful + if out.returncode != 0: + print("XXXXXXX Docker build failed. XXXXXXX") + print("STDOUT:", out.stdout.decode()) + print("STDERR:", out.stderr.decode()) + exit(1) + else: + print(f">>> Docker image built successfully with tag: {image_tag}") + # ------------------------------------------------------------------------------- # diff --git a/docker/linux/Dockerfile b/docker/linux/Dockerfile index 3e1a6f272f..5ea991848f 100644 --- a/docker/linux/Dockerfile +++ b/docker/linux/Dockerfile @@ -37,4 +37,4 @@ ENV AWP_ROOT251="/prime" LABEL org.opencontainers.image.authors="ANSYS Inc." LABEL org.opencontainers.image.vendor="ANSYS Inc." -ENTRYPOINT [ "/prime/meshing/Prime/runPrime.sh", "server", "--ip", "0.0.0.0" ] +ENTRYPOINT [ "/prime/meshing/Prime/runPrime.sh", "server", "--ip", "0.0.0.0" ] \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 9da67409ef..57e2f08f58 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "flit_core.buildapi" [project] name = "ansys-meshing-prime" -version = "0.8.0" +version = "0.8.2" description = "PyPrimeMesh is a Python client to Ansys Prime Server, which delivers core Ansys meshing technology." readme = "README.md" requires-python = ">=3.10,<4" @@ -37,17 +37,17 @@ tests = [ "pytest-cov==6.1.1", "pytest-pyvista==0.1.9", "pytest-xvfb==3.1.1", - "pyvista[trame]==0.44.2" + "pyvista[trame]<=0.45.3" ] doc = [ "ansys-sphinx-theme[autoapi]==1.4.2", - "ansys-tools-visualization-interface==0.8.3", + "ansys-tools-visualization-interface<=0.11.0", "jupyter-sphinx==0.5.3", "numpydoc==1.8.0", - "sphinx==8.2.3", + "sphinx>=8.0.0,<8.2.0", "sphinx_design==0.6.1", "pyvista==0.44.2", - "sphinx-autodoc-typehints==3.1.0", + "sphinx-autodoc-typehints==3.0.1", "sphinx-copybutton==0.5.2", "sphinx-gallery==0.19.0", "sphinx-notfound-page==1.1.0", diff --git a/src/ansys/meshing/prime/autogen/automesh.py b/src/ansys/meshing/prime/autogen/automesh.py index 72ca9bc822..dd4512f5a0 100644 --- a/src/ansys/meshing/prime/autogen/automesh.py +++ b/src/ansys/meshing/prime/autogen/automesh.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/automeshstructs.py b/src/ansys/meshing/prime/autogen/automeshstructs.py index dc2fa6b09a..3dce359c96 100644 --- a/src/ansys/meshing/prime/autogen/automeshstructs.py +++ b/src/ansys/meshing/prime/autogen/automeshstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/autoquadmesher.py b/src/ansys/meshing/prime/autogen/autoquadmesher.py index 0e56f07813..391854612e 100644 --- a/src/ansys/meshing/prime/autogen/autoquadmesher.py +++ b/src/ansys/meshing/prime/autogen/autoquadmesher.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/autoquadmesherstructs.py b/src/ansys/meshing/prime/autogen/autoquadmesherstructs.py index 574c9b7fe9..3d082f854e 100644 --- a/src/ansys/meshing/prime/autogen/autoquadmesherstructs.py +++ b/src/ansys/meshing/prime/autogen/autoquadmesherstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/boundaryfittednurbs.py b/src/ansys/meshing/prime/autogen/boundaryfittednurbs.py index 25ced9e3ed..d869b044d9 100644 --- a/src/ansys/meshing/prime/autogen/boundaryfittednurbs.py +++ b/src/ansys/meshing/prime/autogen/boundaryfittednurbs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/collapsetool.py b/src/ansys/meshing/prime/autogen/collapsetool.py index 6359a91aa2..9465f91e41 100644 --- a/src/ansys/meshing/prime/autogen/collapsetool.py +++ b/src/ansys/meshing/prime/autogen/collapsetool.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/collapsetoolstructs.py b/src/ansys/meshing/prime/autogen/collapsetoolstructs.py index 5cb3243a27..59f94cf1de 100644 --- a/src/ansys/meshing/prime/autogen/collapsetoolstructs.py +++ b/src/ansys/meshing/prime/autogen/collapsetoolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/commonstructs.py b/src/ansys/meshing/prime/autogen/commonstructs.py index cabed1ef26..9ef24c20c3 100644 --- a/src/ansys/meshing/prime/autogen/commonstructs.py +++ b/src/ansys/meshing/prime/autogen/commonstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/commontypes.py b/src/ansys/meshing/prime/autogen/commontypes.py index 66343b63de..094114c527 100644 --- a/src/ansys/meshing/prime/autogen/commontypes.py +++ b/src/ansys/meshing/prime/autogen/commontypes.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/connect.py b/src/ansys/meshing/prime/autogen/connect.py index 3d6a970872..9c7fcfaedb 100644 --- a/src/ansys/meshing/prime/autogen/connect.py +++ b/src/ansys/meshing/prime/autogen/connect.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/connectstructs.py b/src/ansys/meshing/prime/autogen/connectstructs.py index 0b82eb031d..ebdfc5c24d 100644 --- a/src/ansys/meshing/prime/autogen/connectstructs.py +++ b/src/ansys/meshing/prime/autogen/connectstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/controldata.py b/src/ansys/meshing/prime/autogen/controldata.py index c2c91f2fbe..449ead4df9 100644 --- a/src/ansys/meshing/prime/autogen/controldata.py +++ b/src/ansys/meshing/prime/autogen/controldata.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/controlstructs.py b/src/ansys/meshing/prime/autogen/controlstructs.py index 5163f47043..ca7a14d185 100644 --- a/src/ansys/meshing/prime/autogen/controlstructs.py +++ b/src/ansys/meshing/prime/autogen/controlstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/coreobject.py b/src/ansys/meshing/prime/autogen/coreobject.py index 8e3a19fb09..a26f470f69 100644 --- a/src/ansys/meshing/prime/autogen/coreobject.py +++ b/src/ansys/meshing/prime/autogen/coreobject.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/deletetool.py b/src/ansys/meshing/prime/autogen/deletetool.py index 179981a241..592283279a 100644 --- a/src/ansys/meshing/prime/autogen/deletetool.py +++ b/src/ansys/meshing/prime/autogen/deletetool.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/deletetoolstructs.py b/src/ansys/meshing/prime/autogen/deletetoolstructs.py index 4af5ee9f0d..138aad94f7 100644 --- a/src/ansys/meshing/prime/autogen/deletetoolstructs.py +++ b/src/ansys/meshing/prime/autogen/deletetoolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/featureextraction.py b/src/ansys/meshing/prime/autogen/featureextraction.py index c367a74475..abd7d8c446 100644 --- a/src/ansys/meshing/prime/autogen/featureextraction.py +++ b/src/ansys/meshing/prime/autogen/featureextraction.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/featureextractionstructs.py b/src/ansys/meshing/prime/autogen/featureextractionstructs.py index f71d2f97d0..6b4d964521 100644 --- a/src/ansys/meshing/prime/autogen/featureextractionstructs.py +++ b/src/ansys/meshing/prime/autogen/featureextractionstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/fileio.py b/src/ansys/meshing/prime/autogen/fileio.py index d8638aa7e0..83359a7e01 100644 --- a/src/ansys/meshing/prime/autogen/fileio.py +++ b/src/ansys/meshing/prime/autogen/fileio.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/fileiostructs.py b/src/ansys/meshing/prime/autogen/fileiostructs.py index 5c87e56ec2..8de7bda227 100644 --- a/src/ansys/meshing/prime/autogen/fileiostructs.py +++ b/src/ansys/meshing/prime/autogen/fileiostructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/igastructs.py b/src/ansys/meshing/prime/autogen/igastructs.py index 0da52bc332..7f18978005 100644 --- a/src/ansys/meshing/prime/autogen/igastructs.py +++ b/src/ansys/meshing/prime/autogen/igastructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/materialpointmanager.py b/src/ansys/meshing/prime/autogen/materialpointmanager.py index 0d1e602f1c..5122551458 100644 --- a/src/ansys/meshing/prime/autogen/materialpointmanager.py +++ b/src/ansys/meshing/prime/autogen/materialpointmanager.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/materialpointmanagerstructs.py b/src/ansys/meshing/prime/autogen/materialpointmanagerstructs.py index 727703dc7f..b7a99cade6 100644 --- a/src/ansys/meshing/prime/autogen/materialpointmanagerstructs.py +++ b/src/ansys/meshing/prime/autogen/materialpointmanagerstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/meshinfo.py b/src/ansys/meshing/prime/autogen/meshinfo.py index 9ba53f7601..7abd8f428f 100644 --- a/src/ansys/meshing/prime/autogen/meshinfo.py +++ b/src/ansys/meshing/prime/autogen/meshinfo.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/meshinfostructs.py b/src/ansys/meshing/prime/autogen/meshinfostructs.py index b8c0340d52..97ddd21d0b 100644 --- a/src/ansys/meshing/prime/autogen/meshinfostructs.py +++ b/src/ansys/meshing/prime/autogen/meshinfostructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/model.py b/src/ansys/meshing/prime/autogen/model.py index fbd6dab0fe..9a7af7a847 100644 --- a/src/ansys/meshing/prime/autogen/model.py +++ b/src/ansys/meshing/prime/autogen/model.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/modelstructs.py b/src/ansys/meshing/prime/autogen/modelstructs.py index 986260a530..5983cc5d7a 100644 --- a/src/ansys/meshing/prime/autogen/modelstructs.py +++ b/src/ansys/meshing/prime/autogen/modelstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/morpher.py b/src/ansys/meshing/prime/autogen/morpher.py index 1b8c5547cc..75b474e31c 100644 --- a/src/ansys/meshing/prime/autogen/morpher.py +++ b/src/ansys/meshing/prime/autogen/morpher.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/morpherbcsstructs.py b/src/ansys/meshing/prime/autogen/morpherbcsstructs.py index 711097b060..bb5a8de537 100644 --- a/src/ansys/meshing/prime/autogen/morpherbcsstructs.py +++ b/src/ansys/meshing/prime/autogen/morpherbcsstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/morpherstructs.py b/src/ansys/meshing/prime/autogen/morpherstructs.py index aaf5df1d83..a364a35007 100644 --- a/src/ansys/meshing/prime/autogen/morpherstructs.py +++ b/src/ansys/meshing/prime/autogen/morpherstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/multizonecontrol.py b/src/ansys/meshing/prime/autogen/multizonecontrol.py index 9a9c289971..b874a6a988 100644 --- a/src/ansys/meshing/prime/autogen/multizonecontrol.py +++ b/src/ansys/meshing/prime/autogen/multizonecontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/part.py b/src/ansys/meshing/prime/autogen/part.py index ba5ed017fe..992a8c3e8e 100644 --- a/src/ansys/meshing/prime/autogen/part.py +++ b/src/ansys/meshing/prime/autogen/part.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/partstructs.py b/src/ansys/meshing/prime/autogen/partstructs.py index 03f95ada56..e0420a2e1f 100644 --- a/src/ansys/meshing/prime/autogen/partstructs.py +++ b/src/ansys/meshing/prime/autogen/partstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/periodiccontrol.py b/src/ansys/meshing/prime/autogen/periodiccontrol.py index ca9fa1b9ac..fcc68ca982 100644 --- a/src/ansys/meshing/prime/autogen/periodiccontrol.py +++ b/src/ansys/meshing/prime/autogen/periodiccontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/periodiccontrolstructs.py b/src/ansys/meshing/prime/autogen/periodiccontrolstructs.py index 4ae5b4dee9..71819345e9 100644 --- a/src/ansys/meshing/prime/autogen/periodiccontrolstructs.py +++ b/src/ansys/meshing/prime/autogen/periodiccontrolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/primeconfig.py b/src/ansys/meshing/prime/autogen/primeconfig.py index ac02f73312..6983e531a2 100644 --- a/src/ansys/meshing/prime/autogen/primeconfig.py +++ b/src/ansys/meshing/prime/autogen/primeconfig.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/prismcontrol.py b/src/ansys/meshing/prime/autogen/prismcontrol.py index 1e6c28b292..43fc5e8f2b 100644 --- a/src/ansys/meshing/prime/autogen/prismcontrol.py +++ b/src/ansys/meshing/prime/autogen/prismcontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/prismcontrolstructs.py b/src/ansys/meshing/prime/autogen/prismcontrolstructs.py index 8aa4a03ca8..7acfbc7c51 100644 --- a/src/ansys/meshing/prime/autogen/prismcontrolstructs.py +++ b/src/ansys/meshing/prime/autogen/prismcontrolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/quadtospline.py b/src/ansys/meshing/prime/autogen/quadtospline.py index e9380546d1..e8482881dc 100644 --- a/src/ansys/meshing/prime/autogen/quadtospline.py +++ b/src/ansys/meshing/prime/autogen/quadtospline.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/scaffolder.py b/src/ansys/meshing/prime/autogen/scaffolder.py index c4671c4eb3..830f8161a6 100644 --- a/src/ansys/meshing/prime/autogen/scaffolder.py +++ b/src/ansys/meshing/prime/autogen/scaffolder.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/scaffolderstructs.py b/src/ansys/meshing/prime/autogen/scaffolderstructs.py index ce7bfc2d62..f546ba640f 100644 --- a/src/ansys/meshing/prime/autogen/scaffolderstructs.py +++ b/src/ansys/meshing/prime/autogen/scaffolderstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/shellblcontrol.py b/src/ansys/meshing/prime/autogen/shellblcontrol.py index 329c7fb989..f51318f7f1 100644 --- a/src/ansys/meshing/prime/autogen/shellblcontrol.py +++ b/src/ansys/meshing/prime/autogen/shellblcontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/shellblcontrolstructs.py b/src/ansys/meshing/prime/autogen/shellblcontrolstructs.py index 1b115fd8d8..423c15c45a 100644 --- a/src/ansys/meshing/prime/autogen/shellblcontrolstructs.py +++ b/src/ansys/meshing/prime/autogen/shellblcontrolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/sizecontrol.py b/src/ansys/meshing/prime/autogen/sizecontrol.py index f938a89275..716e3fd0ba 100644 --- a/src/ansys/meshing/prime/autogen/sizecontrol.py +++ b/src/ansys/meshing/prime/autogen/sizecontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/sizecontrolstructs.py b/src/ansys/meshing/prime/autogen/sizecontrolstructs.py index d2e36e97c0..11f2462831 100644 --- a/src/ansys/meshing/prime/autogen/sizecontrolstructs.py +++ b/src/ansys/meshing/prime/autogen/sizecontrolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/sizefield.py b/src/ansys/meshing/prime/autogen/sizefield.py index 3b20440791..68107f1bc1 100644 --- a/src/ansys/meshing/prime/autogen/sizefield.py +++ b/src/ansys/meshing/prime/autogen/sizefield.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/sizefieldstructs.py b/src/ansys/meshing/prime/autogen/sizefieldstructs.py index 8dfb4c7aee..6801ac46bc 100644 --- a/src/ansys/meshing/prime/autogen/sizefieldstructs.py +++ b/src/ansys/meshing/prime/autogen/sizefieldstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/splittoolstructs.py b/src/ansys/meshing/prime/autogen/splittoolstructs.py index 22af9d584a..9c99114ced 100644 --- a/src/ansys/meshing/prime/autogen/splittoolstructs.py +++ b/src/ansys/meshing/prime/autogen/splittoolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/surfacesearch.py b/src/ansys/meshing/prime/autogen/surfacesearch.py index 24696218a8..3fabc7a503 100644 --- a/src/ansys/meshing/prime/autogen/surfacesearch.py +++ b/src/ansys/meshing/prime/autogen/surfacesearch.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/surfacesearchstructs.py b/src/ansys/meshing/prime/autogen/surfacesearchstructs.py index c7defc1cab..93896dfeb9 100644 --- a/src/ansys/meshing/prime/autogen/surfacesearchstructs.py +++ b/src/ansys/meshing/prime/autogen/surfacesearchstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/surfaceutilities.py b/src/ansys/meshing/prime/autogen/surfaceutilities.py index 934e4bcd39..4d3d53ca1e 100644 --- a/src/ansys/meshing/prime/autogen/surfaceutilities.py +++ b/src/ansys/meshing/prime/autogen/surfaceutilities.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/surfaceutilitystructs.py b/src/ansys/meshing/prime/autogen/surfaceutilitystructs.py index f606529008..6c416942e0 100644 --- a/src/ansys/meshing/prime/autogen/surfaceutilitystructs.py +++ b/src/ansys/meshing/prime/autogen/surfaceutilitystructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/surfer.py b/src/ansys/meshing/prime/autogen/surfer.py index c2c224970d..9ac8c67343 100644 --- a/src/ansys/meshing/prime/autogen/surfer.py +++ b/src/ansys/meshing/prime/autogen/surfer.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/surferstructs.py b/src/ansys/meshing/prime/autogen/surferstructs.py index b4b4500ace..ee46530228 100644 --- a/src/ansys/meshing/prime/autogen/surferstructs.py +++ b/src/ansys/meshing/prime/autogen/surferstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/thinvolumecontrol.py b/src/ansys/meshing/prime/autogen/thinvolumecontrol.py index 9b280691c5..b23d575230 100644 --- a/src/ansys/meshing/prime/autogen/thinvolumecontrol.py +++ b/src/ansys/meshing/prime/autogen/thinvolumecontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/thinvolumecontrolstructs.py b/src/ansys/meshing/prime/autogen/thinvolumecontrolstructs.py index 21a685b622..dedaa6e24c 100644 --- a/src/ansys/meshing/prime/autogen/thinvolumecontrolstructs.py +++ b/src/ansys/meshing/prime/autogen/thinvolumecontrolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/topodata.py b/src/ansys/meshing/prime/autogen/topodata.py index 8aa00d20f5..f54cab4625 100644 --- a/src/ansys/meshing/prime/autogen/topodata.py +++ b/src/ansys/meshing/prime/autogen/topodata.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/topodatastructs.py b/src/ansys/meshing/prime/autogen/topodatastructs.py index 6c865a8714..a68439d218 100644 --- a/src/ansys/meshing/prime/autogen/topodatastructs.py +++ b/src/ansys/meshing/prime/autogen/topodatastructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/toposearchstructs.py b/src/ansys/meshing/prime/autogen/toposearchstructs.py index 191dcb6535..1629a4a43b 100644 --- a/src/ansys/meshing/prime/autogen/toposearchstructs.py +++ b/src/ansys/meshing/prime/autogen/toposearchstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/topoutilities.py b/src/ansys/meshing/prime/autogen/topoutilities.py index 4eebb2cd29..b6c2e3e8c7 100644 --- a/src/ansys/meshing/prime/autogen/topoutilities.py +++ b/src/ansys/meshing/prime/autogen/topoutilities.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/topoutilitystructs.py b/src/ansys/meshing/prime/autogen/topoutilitystructs.py index 9df9b8b1a2..6e47c0ced7 100644 --- a/src/ansys/meshing/prime/autogen/topoutilitystructs.py +++ b/src/ansys/meshing/prime/autogen/topoutilitystructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/transform.py b/src/ansys/meshing/prime/autogen/transform.py index ea298e63c1..7c27a98666 100644 --- a/src/ansys/meshing/prime/autogen/transform.py +++ b/src/ansys/meshing/prime/autogen/transform.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/transformstructs.py b/src/ansys/meshing/prime/autogen/transformstructs.py index 4d49abde86..a8bd890f29 100644 --- a/src/ansys/meshing/prime/autogen/transformstructs.py +++ b/src/ansys/meshing/prime/autogen/transformstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumecontrol.py b/src/ansys/meshing/prime/autogen/volumecontrol.py index 37e6fae1fe..79ddb060ad 100644 --- a/src/ansys/meshing/prime/autogen/volumecontrol.py +++ b/src/ansys/meshing/prime/autogen/volumecontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumecontrolstructs.py b/src/ansys/meshing/prime/autogen/volumecontrolstructs.py index 3568fe8c86..a7f8583697 100644 --- a/src/ansys/meshing/prime/autogen/volumecontrolstructs.py +++ b/src/ansys/meshing/prime/autogen/volumecontrolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumemeshtool.py b/src/ansys/meshing/prime/autogen/volumemeshtool.py index c21ec19297..673154ff35 100644 --- a/src/ansys/meshing/prime/autogen/volumemeshtool.py +++ b/src/ansys/meshing/prime/autogen/volumemeshtool.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumemeshtoolstructs.py b/src/ansys/meshing/prime/autogen/volumemeshtoolstructs.py index 91a5d45a5e..094a32d344 100644 --- a/src/ansys/meshing/prime/autogen/volumemeshtoolstructs.py +++ b/src/ansys/meshing/prime/autogen/volumemeshtoolstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumesearch.py b/src/ansys/meshing/prime/autogen/volumesearch.py index 362c34dd73..710984d715 100644 --- a/src/ansys/meshing/prime/autogen/volumesearch.py +++ b/src/ansys/meshing/prime/autogen/volumesearch.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumesearchstructs.py b/src/ansys/meshing/prime/autogen/volumesearchstructs.py index c2bbfd9eec..942a9544be 100644 --- a/src/ansys/meshing/prime/autogen/volumesearchstructs.py +++ b/src/ansys/meshing/prime/autogen/volumesearchstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumesweeper.py b/src/ansys/meshing/prime/autogen/volumesweeper.py index 999799ad54..08a051b90a 100644 --- a/src/ansys/meshing/prime/autogen/volumesweeper.py +++ b/src/ansys/meshing/prime/autogen/volumesweeper.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/volumesweeperstructs.py b/src/ansys/meshing/prime/autogen/volumesweeperstructs.py index e639cb86b6..7bd1d5ab6d 100644 --- a/src/ansys/meshing/prime/autogen/volumesweeperstructs.py +++ b/src/ansys/meshing/prime/autogen/volumesweeperstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/vtcomposer.py b/src/ansys/meshing/prime/autogen/vtcomposer.py index 10def9faa9..45292db3c9 100644 --- a/src/ansys/meshing/prime/autogen/vtcomposer.py +++ b/src/ansys/meshing/prime/autogen/vtcomposer.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/vtcomposerstructs.py b/src/ansys/meshing/prime/autogen/vtcomposerstructs.py index 6a577ffcba..2876ab9722 100644 --- a/src/ansys/meshing/prime/autogen/vtcomposerstructs.py +++ b/src/ansys/meshing/prime/autogen/vtcomposerstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/wrapper.py b/src/ansys/meshing/prime/autogen/wrapper.py index 3d42df0adc..92169dcee6 100644 --- a/src/ansys/meshing/prime/autogen/wrapper.py +++ b/src/ansys/meshing/prime/autogen/wrapper.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/wrappercontrol.py b/src/ansys/meshing/prime/autogen/wrappercontrol.py index 446265a201..edc2b2a12a 100644 --- a/src/ansys/meshing/prime/autogen/wrappercontrol.py +++ b/src/ansys/meshing/prime/autogen/wrappercontrol.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/autogen/wrapperstructs.py b/src/ansys/meshing/prime/autogen/wrapperstructs.py index b55ac5d593..eff566ba1b 100644 --- a/src/ansys/meshing/prime/autogen/wrapperstructs.py +++ b/src/ansys/meshing/prime/autogen/wrapperstructs.py @@ -1,4 +1,4 @@ -# Copyright (C) 2024 ANSYS, Inc. and/or its affiliates. +# Copyright (C) 2024 - 2025 ANSYS, Inc. and/or its affiliates. # SPDX-License-Identifier: MIT # # diff --git a/src/ansys/meshing/prime/core/mapdlcdbexportutils.py b/src/ansys/meshing/prime/core/mapdlcdbexportutils.py index 3a5ed7ace6..690900252f 100644 --- a/src/ansys/meshing/prime/core/mapdlcdbexportutils.py +++ b/src/ansys/meshing/prime/core/mapdlcdbexportutils.py @@ -1650,10 +1650,11 @@ def _process_elasticity(self, property_dict, material, mat_id): f"tempereture dependent values are not processed" ) clms = comps_nonlinear_mapping[comp_data['Parameters']['COMPONENT']] + stiff_val = float(comp_data['Data']['Stiffness'][0]) * 1000 elasticity_data += f"TB, JOIN, {mat_id}, 1, 3, {clms}\n" - elasticity_data += f"TBPT, , -1.0, -{comp_data['Data']['Stiffness'][0]}\n" - elasticity_data += f"TBPT, , 0.0, 0.0\n" - elasticity_data += f"TBPT, , 1.0, {comp_data['Data']['Stiffness'][0]}\n" + elasticity_data += f"TBPT, , -1000.0, -{stiff_val}\n" + elasticity_data += "TBPT, , 0.0, 0.0\n" + elasticity_data += f"TBPT, , 1000.0, {stiff_val}\n" else: if len(comp_data['Data']['Stiffness']) != 1: self._logger.warning( @@ -1761,10 +1762,11 @@ def _process_damping(self, property_dict, material, mat_id): f"tempereture dependent values are not processed" ) s1 = comps_nonlinear_mapping[comp_data['Parameters']['COMPONENT']] + damp_coeff = float(comp_data['Data']['damping_coeff'][0]) * 1000 damping_data += f"TB, JOIN, {mat_id}, 1, 3, {s1}\n" - damping_data += f"TBPT, , -1.0, -{comp_data['Data']['damping_coeff'][0]}\n" - damping_data += f"TBPT, , 0.0, 0.0\n" - damping_data += f"TBPT, , 1.0, {comp_data['Data']['damping_coeff'][0]}\n" + damping_data += f"TBPT, , -1000.0, -{damp_coeff}\n" + damping_data += "TBPT, , 0.0, 0.0\n" + damping_data += f"TBPT, , 1000.0, {damp_coeff}\n" else: # self._logger.info('linear') if len(comp_data['Data']['damping_coeff']) != 1: @@ -2806,6 +2808,7 @@ def get_static_analysis_data(self, static_data): time_increment = float(data['time_increment']) if 'time_period' in data: time_period = float(data['time_period']) + min_time_increment = time_period * 1e-05 if 'min_time_increment' in data: min_time_increment = float(data['min_time_increment']) if 'max_time_increment' in data: @@ -2821,7 +2824,7 @@ def get_static_analysis_data(self, static_data): time_interval_val = self.get_output_time_interval() if time_interval_val != 0.0: time_increment = time_interval_val - min_time_increment = time_interval_val + # min_time_increment = time_interval_val max_time_increment = time_interval_val # if time_increment > time_interval_val: # time_increment = time_interval_val @@ -2851,8 +2854,9 @@ def get_static_analysis_data(self, static_data): else: static_analysis_commands += 'ANTYPE, STATIC\n' static_analysis_commands += f'TIME,{self._time}\n' + static_analysis_commands += f'AUTOTS,ON\n' static_analysis_commands += ( - f'DELTIM, {time_increment}, {min_time_increment}, {max_time_increment}\n' + f'DELTIM, {time_increment}, {min_time_increment}, {max_time_increment}, , FORCE\n' ) static_analysis_commands += '\n' self._previous_analysis = "STATIC" @@ -2912,7 +2916,7 @@ def get_modal_dynamic_analysis_data(self, dynamic_data): f'! ---------------------------- STEP: {self._step_counter} -----------------------\n' ) if self._previous_analysis == "STATIC": - dynamic_analysis_commands += 'TINTP, 0.41421,,,,,,1\n' + dynamic_analysis_commands += 'TINTP, 0.41421,,,,,,-1\n' dynamic_analysis_commands += '\n' dynamic_analysis_commands += 'SOLO,STOT,FORCE,HHT\n' dynamic_analysis_commands += '\n' @@ -2929,6 +2933,8 @@ def get_modal_dynamic_analysis_data(self, dynamic_data): dynamic_analysis_commands += 'IC,ALL,DMGY,0,,,,LSIC\n' dynamic_analysis_commands += 'IC,ALL,DMGZ,0,,,,LSIC\n' dynamic_analysis_commands += '\n' + dynamic_analysis_commands += 'NROPT,FULL\n' + dynamic_analysis_commands += '\n' if self._previous_analysis == "FREQUENCY": dynamic_analysis_commands += f'FINISH\n' dynamic_analysis_commands += f'\n' @@ -2984,6 +2990,7 @@ def get_dynamic_analysis_data(self, dynamic_data): time_increment = float(data['time_increment']) if 'time_period' in data: time_period = float(data['time_period']) + min_time_increment = time_period * 1e-5 if 'min_time_increment' in data: min_time_increment = float(data['min_time_increment']) if 'max_time_increment' in data: @@ -3001,7 +3008,7 @@ def get_dynamic_analysis_data(self, dynamic_data): time_interval_val = self.get_output_time_interval() if time_interval_val != 0: time_increment = time_interval_val - min_time_increment = time_interval_val + # min_time_increment = time_interval_val max_time_increment = time_interval_val # if time_increment > time_interval_val: # time_increment = time_interval_val @@ -3024,7 +3031,7 @@ def get_dynamic_analysis_data(self, dynamic_data): f'! ------------------------- STEP: {self._step_counter} -----------------------\n' ) if self._previous_analysis == "STATIC": - dynamic_analysis_commands += 'TINTP, 0.41421,,,,,,1\n' + dynamic_analysis_commands += 'TINTP, 0.41421,,,,,,-1\n' dynamic_analysis_commands += '\n' dynamic_analysis_commands += 'SOLO,STOT,FORCE,HHT\n' dynamic_analysis_commands += '\n' @@ -3041,6 +3048,8 @@ def get_dynamic_analysis_data(self, dynamic_data): dynamic_analysis_commands += 'IC,ALL,DMGY,0,,,,LSIC\n' dynamic_analysis_commands += 'IC,ALL,DMGZ,0,,,,LSIC\n' dynamic_analysis_commands += '\n' + dynamic_analysis_commands += 'NROPT,FULL\n' + dynamic_analysis_commands += '\n' if self._previous_analysis == "FREQUENCY": dynamic_analysis_commands += f'FINISH\n' dynamic_analysis_commands += f'\n' @@ -3060,8 +3069,9 @@ def get_dynamic_analysis_data(self, dynamic_data): if transient_integration_param: dynamic_analysis_commands += f'TINTP, {transient_integration_param}\n' dynamic_analysis_commands += f'TIME, {self._time}\n' + dynamic_analysis_commands += f'AUTOTS,ON\n' dynamic_analysis_commands += ( - f'DELTIM, {time_increment}, {min_time_increment}, {max_time_increment}\n' + f'DELTIM, {time_increment}, {min_time_increment}, {max_time_increment},, FORCE\n' ) dynamic_analysis_commands += f'\n' if res_modes: @@ -3368,12 +3378,12 @@ def get_output_analysis_data(self, output_data): output_analysis_commands += "OUTRES, ERASE\n" output_analysis_commands += "OUTRES, ALL, NONE\n" if time_points: - output_analysis_commands += f"! OUTRES, EANGL, %{time_points}%\n" + output_analysis_commands += f"OUTRES, EANGL, %{time_points}%\n" else: # output_analysis_commands += "OUTRES, ALL, NONE\n" # TODO Removed this line to avoid complications of # multiple tabular output controls with NINTERVAL - output_analysis_commands += "! OUTRES, EANGL, NONE\n" + output_analysis_commands += "OUTRES, EANGL, NONE\n" pass output_analysis_commands += "\n" @@ -3801,6 +3811,10 @@ def get_output_analysis_data(self, output_data): ) ) output_analysis_commands += ', ,\n' + last_line = output_analysis_commands.split("\n")[-2] + if "STRS" in last_line and ", SEAM_WELD," in last_line: + new_line = last_line.replace("STRS", "EANGL") + output_analysis_commands += new_line + "\n" else: self._logger.warning( f"warning: element output key '{key}' is not processed." @@ -4098,6 +4112,7 @@ def _process_step(self, step_data): if key == "Output" and "Dynamic" in step_data: if "STATIC" in self._analysis_sequence and "DYNAMIC" in self._analysis_sequence: self._transient_output_controls = key_commands + self._transient_output_controls += "\nNROPT,FULL\n" if key == "Output" and "Static" in step_data: if "STATIC" in self._analysis_sequence and "DYNAMIC" in self._analysis_sequence: mapdl_step_commands += "Placeholder_Transient_Outres\n" @@ -4468,6 +4483,8 @@ def generate_mapdl_commands( analysis_settings += ( '!--------------------------------------------------------------------------\n' ) + # analysis_settings += '/copy,file0,err,,errfile,tmp\n' + # analysis_settings += '\n' analysis_settings += '/delete,,cnm,,1\n' analysis_settings += '/delete,,DSP,,\n' analysis_settings += '/delete,,mcf,,\n' @@ -4482,13 +4499,15 @@ def generate_mapdl_commands( # analysis_settings += '/delete,,rfrq,,1\n' analysis_settings += '/delete,,out,,1\n' # analysis_settings += '/delete,harmonic,rst,,1\n' - analysis_settings += '/delete,,mntr,,\n' + analysis_settings += '!/delete,,mntr,,\n' analysis_settings += '/delete,,ldhi,,\n' analysis_settings += '/delete,,r001,,1\n' analysis_settings += '/delete,,rst,,1\n' analysis_settings += '/delete,,stat,,1\n' analysis_settings += '/delete,,db,,\n' analysis_settings += '/delete,,rdb,,\n' + # analysis_settings += '\n' + # analysis_settings += '/rename,errfile,tmp,,file,err\n' if "Step" in json_simulation_data: for an_name in steps_data._assign_analysis: analysis_settings += f'/delete,{an_name},rst,,1\n' diff --git a/src/ansys/meshing/prime/internals/client.py b/src/ansys/meshing/prime/internals/client.py index ca6988066a..de5271286e 100644 --- a/src/ansys/meshing/prime/internals/client.py +++ b/src/ansys/meshing/prime/internals/client.py @@ -1,7 +1,6 @@ # 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 @@ -24,6 +23,7 @@ import logging import os +from typing import Optional import ansys.meshing.prime.examples as examples import ansys.meshing.prime.internals.config as config @@ -50,7 +50,8 @@ class Client(object): Maximum time to wait for connection. The default is ``defaults.connection_timeout()``. credentials : Any, optional Credentials to connect to the server. The default is ``None``. - + client_certs_dir : Optional[str] + Directory containing client certificates for mutual TLS. Raises ------ ValueError @@ -65,6 +66,9 @@ def __init__( port: int = defaults.port(), timeout: float = defaults.connection_timeout(), credentials=None, + connection_type: config.ConnectionType = config.ConnectionType.GRPC_SECURE, + uds_file: Optional[str] = None, + client_certs_dir: Optional[str] = None, **kwargs, ): """Initialize the client.""" @@ -72,34 +76,78 @@ def __init__( local = kwargs.get('local', False) if local and server_process is not None: raise ValueError('Local client cannot be instantiated with a server process') + + if connection_type == config.ConnectionType.GRPC_INSECURE: + print("Warning (Client): Modification of these configurations is not recommended.") + print( + "Please see the documentation for your installed product for additional information" + ) + self._local = local self._process = server_process self._comm = None - self._has_exited = False if not local: - try: - from ansys.meshing.prime.internals.grpc_communicator import ( - GRPCCommunicator, - ) + if ( + connection_type == config.ConnectionType.GRPC_SECURE + or connection_type == config.ConnectionType.GRPC_INSECURE + ): + try: + from ansys.meshing.prime.internals.grpc_communicator import ( + GRPCCommunicator, + ) - channel = kwargs.get('channel', None) - if channel is not None: - self._comm = GRPCCommunicator(channel=channel, timeout=timeout) - else: - self._comm = GRPCCommunicator( - ip=ip, port=port, timeout=timeout, credentials=credentials + channel = kwargs.get('channel', None) + + if channel is not None: + self._comm = GRPCCommunicator(channel=channel, timeout=timeout) + else: + if ( + os.name == 'nt' + or connection_type == config.ConnectionType.GRPC_INSECURE + ): + if ( + connection_type == config.ConnectionType.GRPC_INSECURE + and client_certs_dir is not None + ): + print( + "Warning: Ignoring client certificate \ +directory for insecure connections" + ) + client_certs_dir = None + self._comm = GRPCCommunicator( + ip=ip, + port=port, + timeout=timeout, + credentials=credentials, + client_certs_dir=client_certs_dir, + ) + else: + if uds_file is None: + self._comm = GRPCCommunicator( + ip=ip, + port=port, + client_certs_dir=client_certs_dir, + timeout=timeout, + ) + else: + self._comm = GRPCCommunicator( + uds_file=uds_file, timeout=timeout, credentials=credentials + ) + setattr(self, 'port', port) + except ImportError as err: + logging.getLogger('PyPrimeMesh').error( + f'Failed to load grpc_communicator with message: {err.msg}' ) - setattr(self, 'port', port) - except ImportError as err: - logging.getLogger('PyPrimeMesh').error( - f'Failed to load grpc_communicator with message: {err.msg}' - ) + raise + except ConnectionError: + self.exit() + + logging.getLogger('PyPrimeMesh').error('Failed to connect to PRIME GRPC server') + raise + else: + logging.getLogger('PyPrimeMesh').error(f'Invalid server type: {connection_type}') raise - except ConnectionError: - self.exit() - logging.getLogger('PyPrimeMesh').error('Failed to connect to PRIME GRPC server') - raise else: try: from ansys.meshing.prime.internals.prime_communicator import ( @@ -112,10 +160,6 @@ def __init__( f'Failed to load prime_communicator with message: {err.msg}' ) - def __del__(self): - """In case unexpected termination, close the connection.""" - self.exit() - @property def model(self): """Get model associated with the client.""" @@ -159,27 +203,23 @@ def exit(self): >>> print(result) >>> prime_client.exit() # Sever connection with server and kill the server. """ - if not self._has_exited: - if self._comm is not None: - self._comm.close() - self._comm = None - if self._process is not None: - assert self._local == False - terminate_process(self._process) - self._process = None - - if config.using_container(): - container_name = getattr(self, 'container_name') - utils.stop_prime_github_container(container_name) - elif config.has_pim(): - self.remote_instance.delete() - self.pim_client.close() - - clear_examples = bool(int(os.environ.get('PYPRIMEMESH_CLEAR_EXAMPLES', '1'))) - if clear_examples: - download_manager = examples.DownloadManager() - download_manager.clear_download_cache() - self._has_exited = True + if self._comm is not None: + self._comm.close() + self._comm = None + if self._process is not None: + assert self._local == False + terminate_process(self._process) + self._process = None + if config.using_container(): + container_name = getattr(self, 'container_name') + utils.stop_prime_github_container(container_name) + elif config.has_pim(): + self.remote_instance.delete() + self.pim_client.close() + clear_examples = bool(int(os.environ.get('PYPRIMEMESH_CLEAR_EXAMPLES', '1'))) + if clear_examples: + download_manager = examples.DownloadManager() + download_manager.clear_download_cache() def __enter__(self): """Open client.""" diff --git a/src/ansys/meshing/prime/internals/config.py b/src/ansys/meshing/prime/internals/config.py index c0a26c1e48..ecd7a2a994 100644 --- a/src/ansys/meshing/prime/internals/config.py +++ b/src/ansys/meshing/prime/internals/config.py @@ -23,6 +23,7 @@ """Configuration utility for PyPrimeMesh.""" from contextlib import contextmanager +from enum import Enum __all__ = [ 'enable_optimizing_numpy_arrays', @@ -45,6 +46,11 @@ from ansys.meshing.prime.internals.logger import PrimeLogger +class ConnectionType(Enum): + GRPC_SECURE = (1,) + GRPC_INSECURE = (2,) + + def _optimize_vectors(): """Get the value of the flag for optimizing vectors.""" return __DEFAULT_USE_BINARY diff --git a/src/ansys/meshing/prime/internals/grpc_communicator.py b/src/ansys/meshing/prime/internals/grpc_communicator.py index ffc9110742..d9795a1f02 100644 --- a/src/ansys/meshing/prime/internals/grpc_communicator.py +++ b/src/ansys/meshing/prime/internals/grpc_communicator.py @@ -1,7 +1,6 @@ # 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 @@ -22,6 +21,7 @@ """Module for communications with the gRPC server.""" __all__ = ['GRPCCommunicator'] +import os from typing import Optional import grpc @@ -42,6 +42,50 @@ BUFFER_MESSAGE_LENGTH = defaults.max_message_length() - 100 +def get_secure_channel(client_certs_dir: str, server_host: str, server_port: int): + """Create a secure gRPC channel using the provided TLS files. + + Parameters + ---------- + tls_client_files : list + List of paths to the TLS files. The list should contain: + - client certificate file path + - client key file path + - CA certificate file path + Returns + ------- + grpc.Channel + A secure gRPC channel. + """ + target = f"{server_host}:{server_port}" + + if not os.path.exists(client_certs_dir): + raise FileNotFoundError(f"Client certificates directory does not exist: {client_certs_dir}") + + cert_file = f"{client_certs_dir}/client.crt" + key_file = f"{client_certs_dir}/client.key" + ca_file = f"{client_certs_dir}/ca.crt" + + with open(cert_file, 'rb') as f: + certificate_chain = f.read() + with open(key_file, 'rb') as f: + private_key = f.read() + with open(ca_file, 'rb') as f: + root_certificates = f.read() + + try: + creds = grpc.ssl_channel_credentials( + root_certificates=root_certificates, + private_key=private_key, + certificate_chain=certificate_chain, + ) + except Exception as e: + raise RuntimeError(f"Failed to create SSL channel credentials: {e}") + + channel = grpc.secure_channel(target, creds) + return channel + + def make_chunks(data, chunk_size): n = max(1, chunk_size) return (data[i : i + n] for i in range(0, len(data), n)) @@ -80,7 +124,10 @@ class GRPCCommunicator(Communicator): Maximum time to wait for connection. The default is ``10.0``. credentials : Any, optional Credentials for connecting to the server. The default is ``None``. - + uds_file : Optional[str], optional + Path to the Unix Domain Socket (UDS) file. The default is ``None``. + client_certs_dir : Optional[str], optional + Directory containing client certificates for mutual TLS. The default is ``None``. Raises ------ ConnectionError @@ -93,18 +140,30 @@ def __init__( port: Optional[int] = None, timeout: float = 10.0, credentials=None, + uds_file: Optional[str] = None, + client_certs_dir: Optional[str] = None, **kwargs, ): """Initialize the server connection.""" import os self._channel = kwargs.get('channel', None) + if self._channel is None and client_certs_dir is not None: + self._channel = get_secure_channel( + client_certs_dir=client_certs_dir, server_host=ip, server_port=port + ) + self._models = [] if self._channel is None: ip_addr = f"{ip}:{port}" channel_options = grpc_utils.get_default_channel_args() if credentials is None: - self._channel = grpc.insecure_channel(ip_addr, options=channel_options) + if uds_file is not None: + options = (('grpc.default_authority', 'localhost'),) + self._channel = grpc.insecure_channel(uds_file, options=options) + else: + options = (('grpc.default_authority', 'localhost'),) + self._channel = grpc.insecure_channel(ip_addr, options=options) else: self._channel = grpc.secure_channel(ip_addr, credentials, options=channel_options) @@ -279,47 +338,6 @@ def run_on_server(self, model: Model, recipe: str) -> dict: else: raise RuntimeError("No connection with server") - def server_command(self, command: str, *args) -> dict: - """Run commands on the server. - - Parameters - ---------- - command : str - Commands to run. - - Returns - ------- - dict - Result from the server side. - - Raises - ------ - RuntimeError - Bad response from server. - RuntimeError - Can not connect to server. - """ - if self._stub is not None: - command = {"Command": command} - if len(args) > 0: - command.update({"Args": args[0]}) - - response = self._stub.ServerCommand( - request_iterator( - 0, - json.dumps(command), - prime_pb2.StringMessage, - prime_pb2.Model, - prime_pb2.StringJsonContent, - prime_pb2.MessageCompletionToken, - ) - ) - message = get_response(response, '') - return message - else: - raise RuntimeError("No connection with server") - return {} - def close(self): """Close opened channels.""" self._stub = None diff --git a/src/ansys/meshing/prime/internals/launcher.py b/src/ansys/meshing/prime/internals/launcher.py index 38c5e9f83a..11d40ef25a 100644 --- a/src/ansys/meshing/prime/internals/launcher.py +++ b/src/ansys/meshing/prime/internals/launcher.py @@ -1,7 +1,6 @@ # 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 @@ -21,9 +20,11 @@ # SOFTWARE. """Helper module for launching the server.""" +import logging import os import subprocess import sys +import uuid from typing import Optional import ansys.meshing.prime.internals.config as config @@ -72,6 +73,8 @@ def launch_server_process( ip: str = defaults.ip(), port: int = defaults.port(), n_procs: Optional[int] = None, + connection_type: config.ConnectionType = None, + server_certs_dir: Optional[str] = None, **kw, ) -> subprocess.Popen: """Launch a server process for Ansys Prime Server. @@ -89,6 +92,8 @@ def launch_server_process( processes to spawn. The default is ``None``, in which case the server is launched as the only process (normal mode). The process marked as ``Node 0`` hosts the gRPC server. + server_certs_dir : Optional[str] + Directory containing server certificates for mutual TLS. Returns ------- @@ -112,6 +117,8 @@ def launch_server_process( run_prime_script = f'runPrime.{script_ext}' exec_path = os.path.join(prime_root, run_prime_script) + print(f'Launching Ansys Prime Server from {prime_root}') + logging.getLogger('PyPrimeMesh').info('Using server from %s', prime_root) if not os.path.isfile(exec_path): raise FileNotFoundError(f'{run_prime_script} not found in {prime_root}') @@ -121,6 +128,7 @@ def launch_server_process( kw = {} enable_python_server = kw.get('server', 'release') + communicator_type = kw.get('communicator_type', 'grpc') scheduler = kw.get('scheduler', None) if not isinstance(enable_python_server, str): @@ -143,6 +151,7 @@ def launch_server_process( if enable_python_server == 'debug': server_args.append('-debug') + server_args.append(f'--type={communicator_type}') server_args.append(f'--ip={ip}') server_args.append(f'--port={port}') if n_procs is not None and isinstance(n_procs, int): @@ -152,6 +161,9 @@ def launch_server_process( server_args.append(f'--scheduler') server_args.append(f'{scheduler}') + if os.name != 'nt' and connection_type == config.ConnectionType.GRPC_SECURE: + server_args.append(f'--uds={kw.get("uds_file", "")}') + kwargs = { 'stdin': subprocess.DEVNULL, } @@ -161,7 +173,15 @@ def launch_server_process( if sys.platform.startswith('win32'): kwargs['creationflags'] = subprocess.CREATE_NEW_PROCESS_GROUP - print('Using Ansys Prime Server from {prime_root}'.format(prime_root=prime_root)) + if connection_type == config.ConnectionType.GRPC_SECURE: + server_args.append("--secure=yes") + else: + server_args.append("--secure=no") + + if server_certs_dir is not None: + server_args.append(f"--server_cert_dir={server_certs_dir}") + + logging.getLogger('PyPrimeMesh').info('Launching Ansys Prime Server') server = subprocess.Popen(server_args, **kwargs) return server @@ -175,7 +195,7 @@ def launch_remote_prime( This method creates a file transfer service that is available on Ansys Lab. """ if version is None: - version = '251-sp1' + version = 'latest' pim = pypim.connect() instance = pim.create_instance(product_name='prime', product_version=version) @@ -210,6 +230,9 @@ def launch_prime( ip: str = defaults.ip(), port: int = defaults.port(), timeout: float = defaults.connection_timeout(), + connection_type: config.ConnectionType = config.ConnectionType.GRPC_SECURE, + client_certs_dir: Optional[str] = None, + server_certs_dir: Optional[str] = None, n_procs: Optional[int] = None, version: Optional[str] = None, **kwargs, @@ -232,6 +255,10 @@ def launch_prime( processes to spawn. The default is ``None``, in which case the server is launched as the only process (normal mode). The process marked as ``Node 0`` hosts the gRPC server. + client_certs_dir : Optional[str] + Directory containing client certificates for mutual TLS. + server_certs_dir : Optional[str] + Directory containing server certificates for mutual TLS. Returns ------- @@ -252,22 +279,61 @@ def launch_prime( if ip == defaults.ip(): port = utils.get_available_local_port(port) + channel = None + if ( + ip not in ["127.0.0.1", "localhost"] + and connection_type == config.ConnectionType.GRPC_SECURE + ): + if client_certs_dir is None or server_certs_dir is None: + raise RuntimeError(f"Please provide certificate directory for remote connections.") + missing = [ + f + for f in [ + f"{client_certs_dir}/client.crt", + f"{client_certs_dir}/client.key", + f"{client_certs_dir}/ca.crt", + ] + if not os.path.exists(f) + ] + if missing: + raise RuntimeError( + f"Missing required client TLS file(s) for mutual TLS: {', '.join(missing)}" + ) + launch_container = bool(int(os.environ.get('PYPRIMEMESH_LAUNCH_CONTAINER', '0'))) if launch_container: container_name = utils.make_unique_container_name('ansys-prime-server') - utils.launch_prime_github_container(port=port, name=container_name, version=version) + utils.launch_prime_github_container( + port=port, name=container_name, version=version, connection_type=connection_type + ) config.set_using_container(True) - client = Client(port=port, timeout=timeout) + client = Client(port=port, timeout=timeout, client_certs_dir=client_certs_dir) client.container_name = container_name - print( - 'Using Ansys Prime Server from container {container_name}'.format( - container_name=container_name - ) - ) + print('using server from docker : The container name ', container_name) return client + uds_file = None + if os.name != 'nt' and client_certs_dir is None: + uds_file = f'unix:/tmp/pyprimemesh-{uuid.uuid4()}.sock' + server = launch_server_process( - prime_root=prime_root, ip=ip, port=port, n_procs=n_procs, **kwargs + prime_root=prime_root, + ip=ip, + port=port, + n_procs=n_procs, + connection_type=connection_type, + uds_file=uds_file, + server_certs_dir=server_certs_dir, + **kwargs, ) - return Client(server_process=server, ip=ip, port=port, timeout=timeout) + return Client( + server_process=server, + ip=ip, + port=port, + timeout=timeout, + uds_file=uds_file, + connection_type=connection_type, + client_certs_dir=client_certs_dir, + channel=channel, + ) diff --git a/src/ansys/meshing/prime/internals/utils.py b/src/ansys/meshing/prime/internals/utils.py index 238e11ef19..ec1a9d7b8a 100644 --- a/src/ansys/meshing/prime/internals/utils.py +++ b/src/ansys/meshing/prime/internals/utils.py @@ -213,6 +213,7 @@ def launch_prime_github_container( port: int = defaults.port(), name: str = "ansys-prime-server", version: Optional[str] = None, + connection_type: Optional['config.ConnectionType'] = None, ): """Launch a container. @@ -229,6 +230,9 @@ def launch_prime_github_container( Name of the container. The default is ``"ansys-prime-server"``. version : str, optional Version of the container to retrieve. The default is ``None``. + connection_type : config.ConnectionType, optional + Type of connection to use. The default is ``None``, which defaults to + ``config.ConnectionType.GRPC_SECURE``. Raises ------ @@ -254,11 +258,29 @@ def launch_prime_github_container( f'{mount_host}:{mount_image}', '-e', f'ANSYSLMD_LICENSE_FILE={license_file}', + ] + graphics_port = int(os.environ.get('PRIME_GRAPHICS_PORT', '0')) + if graphics_port > 0: + print(f'PyPrimeMesh: using Prime graphics port {graphics_port}') + docker_command += ['-p', f'{graphics_port}:{graphics_port}'] + prime_arguments = [ f'{image_name}:{version}', '--port', f'{port}', ] - subprocess.run(docker_command, stdout=subprocess.DEVNULL) + + # Set default connection type if not provided + if connection_type is None: + connection_type = config.ConnectionType.GRPC_SECURE + + # Handle connection type + if ( + connection_type == config.ConnectionType.GRPC_INSECURE + or os.environ.get('PRIME_MODE', '').upper() == "GRPC_INSECURE" + ): + prime_arguments.append('--secure=no') + + subprocess.run(docker_command + prime_arguments, stdout=subprocess.DEVNULL) def stop_prime_github_container(name): diff --git a/tests/conftest.py b/tests/conftest.py index 3353fe4f5d..96e52adafe 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -57,10 +57,19 @@ def start_ansys_prime_server(self, prime_root=None, ip='127.0.0.1', port=50055, by default ``1``. """ if n_procs == 1: - self.client = prime.launch_prime(prime_root=prime_root, ip=ip, port=port) + self.client = prime.launch_prime( + prime_root=prime_root, + ip=ip, + port=port, + connection_type=prime.internals.config.ConnectionType.GRPC_INSECURE, + ) else: self.client = prime.launch_prime( - prime_root=prime_root, ip=ip, port=port, n_procs=n_procs + prime_root=prime_root, + ip=ip, + port=port, + n_procs=n_procs, + connection_type=prime.internals.config.ConnectionType.GRPC_INSECURE, ) def start_remote_client(self):